// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of dart.io;

// TODO(ager): The only reason for this class is that we
// cannot patch a top-level at this point.
class _ProcessUtils {
  external static void _exit(int status);
  external static void _setExitCode(int status);
  external static int _getExitCode();
  external static void _sleep(int millis);
  external static int _pid(Process process);
  external static Stream<ProcessSignal> _watchSignal(ProcessSignal signal);
}

/**
 * Exit the Dart VM process immediately with the given exit code.
 *
 * This does not wait for any asynchronous operations to terminate. Using
 * [exit] is therefore very likely to lose data.
 *
 * The handling of exit codes is platform specific.
 *
 * On Linux and OS X an exit code for normal termination will always
 * be in the range [0..255]. If an exit code outside this range is
 * set the actual exit code will be the lower 8 bits masked off and
 * treated as an unsigned value. E.g. using an exit code of -1 will
 * result in an actual exit code of 255 being reported.
 *
 * On Windows the exit code can be set to any 32-bit value. However
 * some of these values are reserved for reporting system errors like
 * crashes.
 *
 * Besides this the Dart executable itself uses an exit code of `254`
 * for reporting compile time errors and an exit code of `255` for
 * reporting runtime error (unhandled exception).
 *
 * Due to these facts it is recommended to only use exit codes in the
 * range [0..127] for communicating the result of running a Dart
 * program to the surrounding environment. This will avoid any
 * cross-platform issues.
 */
void exit(int code) {
  if (code is !int) {
    throw new ArgumentError("Integer value for exit code expected");
  }
  _ProcessUtils._exit(code);
}

/**
 * Set the global exit code for the Dart VM.
 *
 * The exit code is global for the Dart VM and the last assignment to
 * exitCode from any isolate determines the exit code of the Dart VM
 * on normal termination.
 *
 * Default value is `0`.
 *
 * See [exit] for more information on how to chose a value for the
 * exit code.
 */
void set exitCode(int code) {
  if (code is !int) {
    throw new ArgumentError("Integer value for exit code expected");
  }
  _ProcessUtils._setExitCode(code);
}

/**
 * Get the global exit code for the Dart VM.
 *
 * The exit code is global for the Dart VM and the last assignment to
 * exitCode from any isolate determines the exit code of the Dart VM
 * on normal termination.
 *
 * See [exit] for more information on how to chose a value for the
 * exit code.
 */
int get exitCode => _ProcessUtils._getExitCode();

/**
 * Sleep for the duration specified in [duration].
 *
 * Use this with care, as no asynchronous operations can be processed
 * in a isolate while it is blocked in a [sleep] call.
 */
void sleep(Duration duration) {
  int milliseconds = duration.inMilliseconds;
  if (milliseconds < 0) {
    throw new ArgumentError("sleep: duration cannot be negative");
  }
  _ProcessUtils._sleep(milliseconds);
}

/**
 * Returns the PID of the current process.
 */
int get pid => _ProcessUtils._pid(null);

/**
 * Modes for running a new process.
 */
enum ProcessStartMode {
  /// Normal child process.
  NORMAL,
  /// Detached child process with no open communication channel.
  DETACHED,
  /// Detached child process with stdin, stdout and stderr still open
  /// for communication with the child.
  DETACHED_WITH_STDIO
}

/**
 * The means to execute a program.
 *
 * Use the static [start] and [run] methods to start a new process.
 * The run method executes the process non-interactively to completion.
 * In contrast, the start method allows your code to interact with the
 * running process.
 *
 * ## Start a process with the run method
 *
 * The following code sample uses the run method to create a process
 * that runs the UNIX command `ls`, which lists the contents of a directory.
 * The run method completes with a [ProcessResult] object when the process
 * terminates. This provides access to the output and exit code from the
 * process. The run method does not return a Process object; this prevents your
 * code from interacting with the running process.
 *
 *     import 'dart:io';
 *
 *     main() {
 *       // List all files in the current directory in UNIX-like systems.
 *       Process.run('ls', ['-l']).then((ProcessResult results) {
 *         print(results.stdout);
 *       });
 *     }
 *
 * ## Start a process with the start method
 *
 * The following example uses start to create the process.
 * The start method returns a [Future] for a Process object.
 * When the future completes the process is started and
 * your code can interact with the
 * Process: writing to stdin, listening to stdout, and so on.
 *
 * The following sample starts the UNIX `cat` utility, which when given no
 * command-line arguments, echos its input.
 * The program writes to the process's standard input stream
 * and prints data from its standard output stream.
 *
 *     import 'dart:io';
 *     import 'dart:convert';
 *
 *     main() {
 *       Process.start('cat', []).then((Process process) {
 *         process.stdout
 *             .transform(UTF8.decoder)
 *             .listen((data) { print(data); });
 *         process.stdin.writeln('Hello, world!');
 *         process.stdin.writeln('Hello, galaxy!');
 *         process.stdin.writeln('Hello, universe!');
 *       });
 *     }
 *
 * ## Standard I/O streams
 *
 * As seen in the previous code sample, you can interact with the Process's
 * standard output stream through the getter [stdout],
 * and you can interact with the Process's standard input stream through
 * the getter [stdin].
 * In addition, Process provides a getter [stderr] for using the Process's
 * standard error stream.
 *
 * A Process's streams are distinct from the top-level streams
 * for the current program.
 *
 * ## Exit codes
 *
 * Call the [exitCode] method to get the exit code of the process.
 * The exit code indicates whether the program terminated successfully
 * (usually indicated with an exit code of 0) or with an error.
 *
 * If the start method is used, the exitCode is available through a future
 * on the Process object (as shown in the example below).
 * If the run method is used, the exitCode is available
 * through a getter on the ProcessResult instance.
 *
 *     import 'dart:io';
 *
 *     main() {
 *       Process.start('ls', ['-l']).then((process) {
 *         // Get the exit code from the new process.
 *         process.exitCode.then((exitCode) {
 *           print('exit code: $exitCode');
 *         });
 *       });
 *     }
 *
 * ## Other resources
 *
 * [Dart by Example](https://www.dartlang.org/dart-by-example/#dart-io-and-command-line-apps)
 * provides additional task-oriented code samples that show how to use
 * various API from the [dart:io] library.
 */
abstract class Process {
  /**
   * Returns a [:Future:] which completes with the exit code of the process
   * when the process completes.
   *
   * The handling of exit codes is platform specific.
   *
   * On Linux and OS X a normal exit code will be a positive value in
   * the range [0..255]. If the process was terminated due to a signal
   * the exit code will be a negative value in the range [-255..-1],
   * where the absolute value of the exit code is the signal
   * number. For example, if a process crashes due to a segmentation
   * violation the exit code will be -11, as the signal SIGSEGV has the
   * number 11.
   *
   * On Windows a process can report any 32-bit value as an exit
   * code. When returning the exit code this exit code is turned into
   * a signed value. Some special values are used to report
   * termination due to some system event. E.g. if a process crashes
   * due to an access violation the 32-bit exit code is `0xc0000005`,
   * which will be returned as the negative number `-1073741819`. To
   * get the original 32-bit value use `(0x100000000 + exitCode) &
   * 0xffffffff`.
   */
  Future<int> get exitCode;

  /**
   * Starts a process running the [executable] with the specified
   * [arguments]. Returns a [:Future<Process>:] that completes with a
   * Process instance when the process has been successfully
   * started. That [Process] object can be used to interact with the
   * process. If the process cannot be started the returned [Future]
   * completes with an exception.
   *
   * Use [workingDirectory] to set the working directory for the process. Note
   * that the change of directory occurs before executing the process on some
   * platforms, which may have impact when using relative paths for the
   * executable and the arguments.
   *
   * Use [environment] to set the environment variables for the process. If not
   * set the environment of the parent process is inherited. Currently, only
   * US-ASCII environment variables are supported and errors are likely to occur
   * if an environment variable with code-points outside the US-ASCII range is
   * passed in.
   *
   * If [includeParentEnvironment] is `true`, the process's environment will
   * include the parent process's environment, with [environment] taking
   * precedence. Default is `true`.
   *
   * If [runInShell] is `true`, the process will be spawned through a system
   * shell. On Linux and OS X, [:/bin/sh:] is used, while
   * [:%WINDIR%\system32\cmd.exe:] is used on Windows.
   *
   * Users must read all data coming on the [stdout] and [stderr]
   * streams of processes started with [:Process.start:]. If the user
   * does not read all data on the streams the underlying system
   * resources will not be released since there is still pending data.
   *
   * The following code uses `Process.start` to grep for `main` in the
   * file `test.dart` on Linux.
   *
   *     Process.start('grep', ['-i', 'main', 'test.dart']).then((process) {
   *       stdout.addStream(process.stdout);
   *       stderr.addStream(process.stderr);
   *     });
   *
   * If [mode] is [ProcessStartMode.NORMAL] (the default) a child
   * process will be started with `stdin`, `stdout` and `stderr`
   * connected.
   *
   * If `mode` is [ProcessStartMode.DETACHED] a detached process will
   * be created. A detached process has no connection to its parent,
   * and can keep running on its own when the parent dies. The only
   * information available from a detached process is its `pid`. There
   * is no connection to its `stdin`, `stdout` or `stderr`, nor will
   * the process' exit code become available when it terminates.
   *
   * If `mode` is [ProcessStartMode.DETACHED_WITH_STDIO] a detached
   * process will be created where the `stdin`, `stdout` and `stderr`
   * are connected. The creator can communicate with the child through
   * these. The detached process will keep running even if these
   * communication channels are closed. The process' exit code will
   * not become available when it terminated.
   *
   * The default value for `mode` is `ProcessStartMode.NORMAL`.
   */
  external static Future<Process> start(
      String executable,
      List<String> arguments,
      {String workingDirectory,
       Map<String, String> environment,
       bool includeParentEnvironment: true,
       bool runInShell: false,
       ProcessStartMode mode: ProcessStartMode.NORMAL});

  /**
   * Starts a process and runs it non-interactively to completion. The
   * process run is [executable] with the specified [arguments].
   *
   * Use [workingDirectory] to set the working directory for the process. Note
   * that the change of directory occurs before executing the process on some
   * platforms, which may have impact when using relative paths for the
   * executable and the arguments.
   *
   * Use [environment] to set the environment variables for the process. If not
   * set the environment of the parent process is inherited. Currently, only
   * US-ASCII environment variables are supported and errors are likely to occur
   * if an environment variable with code-points outside the US-ASCII range is
   * passed in.
   *
   * If [includeParentEnvironment] is `true`, the process's environment will
   * include the parent process's environment, with [environment] taking
   * precedence. Default is `true`.
   *
   * If [runInShell] is true, the process will be spawned through a system
   * shell. On Linux and OS X, `/bin/sh` is used, while
   * `%WINDIR%\system32\cmd.exe` is used on Windows.
   *
   * The encoding used for decoding `stdout` and `stderr` into text is
   * controlled through [stdoutEncoding] and [stderrEncoding]. The
   * default encoding is [SYSTEM_ENCODING]. If `null` is used no
   * decoding will happen and the [ProcessResult] will hold binary
   * data.
   *
   * Returns a `Future<ProcessResult>` that completes with the
   * result of running the process, i.e., exit code, standard out and
   * standard in.
   *
   * The following code uses `Process.run` to grep for `main` in the
   * file `test.dart` on Linux.
   *
   *     Process.run('grep', ['-i', 'main', 'test.dart']).then((result) {
   *       stdout.write(result.stdout);
   *       stderr.write(result.stderr);
   *     });
   */
  external static Future<ProcessResult> run(
      String executable,
      List<String> arguments,
      {String workingDirectory,
       Map<String, String> environment,
       bool includeParentEnvironment: true,
       bool runInShell: false,
       Encoding stdoutEncoding: SYSTEM_ENCODING,
       Encoding stderrEncoding: SYSTEM_ENCODING});


  /**
   * Starts a process and runs it to completion. This is a synchronous
   * call and will block until the child process terminates.
   *
   * The arguments are the same as for `Process.run`.
   *
   * Returns a `ProcessResult` with the result of running the process,
   * i.e., exit code, standard out and standard in.
   */
  external static ProcessResult runSync(
      String executable,
      List<String> arguments,
      {String workingDirectory,
       Map<String, String> environment,
       bool includeParentEnvironment: true,
       bool runInShell: false,
       Encoding stdoutEncoding: SYSTEM_ENCODING,
       Encoding stderrEncoding: SYSTEM_ENCODING});

  /**
   * Kills the process with id [pid].
   *
   * Where possible, sends the [signal] to the process with id
   * `pid`. This includes Linux and OS X. The default signal is
   * [ProcessSignal.SIGTERM] which will normally terminate the
   * process.
   *
   * On platforms without signal support, including Windows, the call
   * just terminates the process with id `pid` in a platform specific
   * way, and the `signal` parameter is ignored.
   *
   * Returns `true` if the signal is successfully delivered to the
   * process. Otherwise the signal could not be sent, usually meaning
   * that the process is already dead.
   */
  external static bool killPid(
      int pid, [ProcessSignal signal = ProcessSignal.SIGTERM]);

  /**
   * Returns the standard output stream of the process as a [:Stream:].
   */
  Stream<List<int>> get stdout;

  /**
   * Returns the standard error stream of the process as a [:Stream:].
   */
  Stream<List<int>> get stderr;

  /**
   * Returns the standard input stream of the process as an [IOSink].
   */
  IOSink get stdin;

  /**
   * Returns the process id of the process.
   */
  int get pid;

  /**
   * Kills the process.
   *
   * Where possible, sends the [signal] to the process. This includes
   * Linux and OS X. The default signal is [ProcessSignal.SIGTERM]
   * which will normally terminate the process.
   *
   * On platforms without signal support, including Windows, the call
   * just terminates the process in a platform specific way, and the
   * `signal` parameter is ignored.
   *
   * Returns `true` if the signal is successfully delivered to the
   * process. Otherwise the signal could not be sent, usually meaning
   * that the process is already dead.
   */
  bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]);
}


/**
 * [ProcessResult] represents the result of running a non-interactive
 * process started with [Process.run] or [Process.runSync].
 */
class ProcessResult {
  /**
   * Exit code for the process.
   *
   * See [Process.exitCode] for more information in the exit code
   * value.
   */
  final int exitCode;

  /**
   * Standard output from the process. The value used for the
   * `stdoutEncoding` argument to `Process.run` determines the type. If
   * `null` was used this value is of type `List<int>` otherwise it is
   * of type `String`.
   */
  final stdout;

  /**
   * Standard error from the process. The value used for the
   * `stderrEncoding` argument to `Process.run` determines the type. If
   * `null` was used this value is of type `List<int>`
   * otherwise it is of type `String`.
   */
  final stderr;

  /**
   * Process id of the process.
   */
  final int pid;

  ProcessResult(this.pid, this.exitCode, this.stdout, this.stderr);
}


/**
 * On Posix systems, [ProcessSignal] is used to send a specific signal
 * to a child process, see [:Process.kill:].
 *
 * Some [ProcessSignal]s can also be watched, as a way to intercept the default
 * signal handler and implement another. See [ProcessSignal.watch] for more
 * information.
 */
class ProcessSignal {
  static const ProcessSignal SIGHUP = const ProcessSignal._(1, "SIGHUP");
  static const ProcessSignal SIGINT = const ProcessSignal._(2, "SIGINT");
  static const ProcessSignal SIGQUIT = const ProcessSignal._(3, "SIGQUIT");
  static const ProcessSignal SIGILL = const ProcessSignal._(4, "SIGILL");
  static const ProcessSignal SIGTRAP = const ProcessSignal._(5, "SIGTRAP");
  static const ProcessSignal SIGABRT = const ProcessSignal._(6, "SIGABRT");
  static const ProcessSignal SIGBUS = const ProcessSignal._(7, "SIGBUS");
  static const ProcessSignal SIGFPE = const ProcessSignal._(8, "SIGFPE");
  static const ProcessSignal SIGKILL = const ProcessSignal._(9, "SIGKILL");
  static const ProcessSignal SIGUSR1 = const ProcessSignal._(10, "SIGUSR1");
  static const ProcessSignal SIGSEGV = const ProcessSignal._(11, "SIGSEGV");
  static const ProcessSignal SIGUSR2 = const ProcessSignal._(12, "SIGUSR2");
  static const ProcessSignal SIGPIPE = const ProcessSignal._(13, "SIGPIPE");
  static const ProcessSignal SIGALRM = const ProcessSignal._(14, "SIGALRM");
  static const ProcessSignal SIGTERM = const ProcessSignal._(15, "SIGTERM");
  static const ProcessSignal SIGCHLD = const ProcessSignal._(17, "SIGCHLD");
  static const ProcessSignal SIGCONT = const ProcessSignal._(18, "SIGCONT");
  static const ProcessSignal SIGSTOP = const ProcessSignal._(19, "SIGSTOP");
  static const ProcessSignal SIGTSTP = const ProcessSignal._(20, "SIGTSTP");
  static const ProcessSignal SIGTTIN = const ProcessSignal._(21, "SIGTTIN");
  static const ProcessSignal SIGTTOU = const ProcessSignal._(22, "SIGTTOU");
  static const ProcessSignal SIGURG = const ProcessSignal._(23, "SIGURG");
  static const ProcessSignal SIGXCPU = const ProcessSignal._(24, "SIGXCPU");
  static const ProcessSignal SIGXFSZ = const ProcessSignal._(25, "SIGXFSZ");
  static const ProcessSignal SIGVTALRM = const ProcessSignal._(26, "SIGVTALRM");
  static const ProcessSignal SIGPROF = const ProcessSignal._(27, "SIGPROF");
  static const ProcessSignal SIGWINCH = const ProcessSignal._(28, "SIGWINCH");
  static const ProcessSignal SIGPOLL = const ProcessSignal._(29, "SIGPOLL");
  static const ProcessSignal SIGSYS = const ProcessSignal._(31, "SIGSYS");

  final int _signalNumber;
  final String _name;

  const ProcessSignal._(this._signalNumber, this._name);

  String toString() => _name;

  /**
   * Watch for process signals.
   *
   * The following [ProcessSignal]s can be listened to:
   *
   *   * [ProcessSignal.SIGHUP].
   *   * [ProcessSignal.SIGINT]. Signal sent by e.g. CTRL-C.
   *   * [ProcessSignal.SIGTERM]. Not available on Windows.
   *   * [ProcessSignal.SIGUSR1]. Not available on Windows.
   *   * [ProcessSignal.SIGUSR2]. Not available on Windows.
   *   * [ProcessSignal.SIGWINCH]. Not available on Windows.
   *
   * Other signals are disallowed, as they may be used by the VM.
   *
   * A signal can be watched multiple times, from multiple isolates, where all
   * callbacks are invoked when signaled, in no specific order.
   */
  Stream<ProcessSignal> watch() => _ProcessUtils._watchSignal(this);
}


class SignalException implements IOException {
  final String message;
  final osError;

  const SignalException(this.message, [this.osError = null]);

  String toString() {
    var msg = "";
    if (osError != null) {
      msg = ", osError: $osError";
    }
    return "SignalException: $message$msg";
  }
}


class ProcessException implements IOException {
  /**
   * Contains the executable provided for the process.
   */
  final String executable;

  /**
   * Contains the arguments provided for the process.
   */
  final List<String> arguments;

  /**
   * Contains the system message for the process exception if any.
   */
  final String message;

  /**
   * Contains the OS error code for the process exception if any.
   */
  final int errorCode;

  const ProcessException(this.executable, this.arguments, [this.message = "",
                         this.errorCode = 0]);
  String toString() {
    var msg = (message == null) ? 'OS error code: $errorCode' : message;
    var args = arguments.join(' ');
    return "ProcessException: $msg\n  Command: $executable $args";
  }
}
