External command

## External command External command — Convenience API for using external command. |

## Synopsis

    #define             GCUT_PROCESS_ERROR
    struct              GCutProcess;
    struct              GCutProcessClass;
    enum                GCutProcessError;
    GQuark              gcut_process_error_quark            (void);
    GCutProcess *       gcut_process_new                    (const gchar *command,
                                                             ...);
    GCutProcess *       gcut_process_new_command_line       (const gchar *command_line);
    GCutProcess *       gcut_process_new_va_list            (const gchar *command,
                                                             va_list args);
    GCutProcess *       gcut_process_new_argv               (gint argc,
                                                             gchar **argv);
    GCutProcess *       gcut_process_new_strings            (const gchar **command);
    GCutProcess *       gcut_process_new_array              (GArray *command);
    void                gcut_process_set_flags              (GCutProcess *process,
                                                             GSpawnFlags flags);
    GSpawnFlags         gcut_process_get_flags              (GCutProcess *process);
    void                gcut_process_set_env                (GCutProcess *process,
                                                             const gchar *name,
                                                             ...);
    gchar **            gcut_process_get_env                (GCutProcess *process);
    gboolean            gcut_process_run                    (GCutProcess *process,
                                                             GError **error);
    GPid                gcut_process_get_pid                (GCutProcess *process);
    gint                gcut_process_wait                   (GCutProcess *process,
                                                             guint timeout,
                                                             GError **error);
    gboolean            gcut_process_kill                   (GCutProcess *process,
                                                             gint signal_number,
                                                             GError **error);
    gboolean            gcut_process_write                  (GCutProcess *process,
                                                             const gchar *chunk,
                                                             gsize size,
                                                             GError **error);
    GIOStatus           gcut_process_flush                  (GCutProcess *process,
                                                             GError **error);
    GString *           gcut_process_get_output_string      (GCutProcess *process);
    GString *           gcut_process_get_error_string       (GCutProcess *process);
    GIOChannel *        gcut_process_get_input_channel      (GCutProcess *process);
    GIOChannel *        gcut_process_get_output_channel     (GCutProcess *process);
    GIOChannel *        gcut_process_get_error_channel      (GCutProcess *process);
    GInputStream *      gcut_process_get_output_stream      (GCutProcess *process);
    GInputStream *      gcut_process_get_error_stream       (GCutProcess *process);
    guint               gcut_process_get_forced_termination_wait_time
                                                            (GCutProcess *process);
    void                gcut_process_set_forced_termination_wait_time
                                                            (GCutProcess *process,
                                                             guint timeout);
    GCutEventLoop *     gcut_process_get_event_loop         (GCutProcess *process);
    void                gcut_process_set_event_loop         (GCutProcess *process,
                                                             GCutEventLoop *loop);

## Object Hierarchy

      GObject
       +----GCutProcess

## Properties

      "command"                  gpointer              : Read / Write

## Signals

      "error"                                          : Run Last
      "error-received"                                 : Run Last
      "output-received"                                : Run Last
      "reaped"                                         : Run Last

## Description

GCutProcess encapsulates external command execution, communication and termination. GCutProcess reports an error as GError. It can be asserted easily by `gcut_assert_error()`.

External command is specified to constructor like `gcut_process_new()`, `gcut_process_new_strings()` and so on. External command isn't run at the time. `gcut_process_run()` runs specified external command.

Standard/Error outputs of external command are passed by "output-received"/"error-received" signals or GIOChannel returned by `gcut_process_get_output()`/`gcut_process_get_error()`. `gcut_process_write()` writes a chunk to standard input of external command.

To wait external command finished, `gcut_process_wait()` can be used. It accepts timeout to avoid infinite waiting.

e.g.:

    static GString *output_string;
    static GCutProcess *process;

    void
    cut_setup (void)
    {
        output_string = g_string_new(NULL);
        process = NULL;
    }

    void
    cut_teardown (void)
    {
        if (output_string)
            g_string_free(output_string, TRUE);
        if (process)
            g_object_unref(process);
    }

    static void
    cb_output_received (GCutProcess *process, const gchar *chunk, gsize size,
                        gpointer user_data)
    {
        g_string_append_len(output_string, chunk, size);
    }

    void
    test_echo (void)
    {
        GError *error = NULL;

        process = gcut_process_new("echo", "XXX", NULL);
        g_signal_connect(process, "receive-output",
                         G_CALLBACK(cb_output_received), NULL);

        gcut_process_run(process, &error);
        gcut_assert_error(error);

        gcut_process_wait(process, 1000, &error);
        gcut_assert_error(error);
        cut_assert_equal_string("XXX\n", output_string->str);
    }

## Details

### GCUT_PROCESS_ERROR

    #define GCUT_PROCESS_ERROR           (gcut_process_error_quark())

### struct GCutProcess

    struct GCutProcess;

### struct GCutProcessClass

    struct GCutProcessClass {
        GObjectClass parent_class;

        void (*output_received) (GCutProcess *process,
                                 const gchar *chunk,
                                 gsize        size);
        void (*error_received)  (GCutProcess *process,
                                 const gchar *chunk,
                                 gsize        size);
        void (*reaped)          (GCutProcess *process,
                                 gint         status);
        void (*error)           (GCutProcess *process,
                                 GError      *error);
    };

### enum GCutProcessError

    typedef enum {
        GCUT_PROCESS_ERROR_COMMAND_LINE,
        GCUT_PROCESS_ERROR_IO_ERROR,
        GCUT_PROCESS_ERROR_ALREADY_RUNNING,
        GCUT_PROCESS_ERROR_NOT_RUNNING,
        GCUT_PROCESS_ERROR_INVALID_OBJECT,
        GCUT_PROCESS_ERROR_INVALID_SIGNAL,
        GCUT_PROCESS_ERROR_PERMISSION_DENIED,
        GCUT_PROCESS_ERROR_TIMEOUT
    } GCutProcessError;

Error codes returned by GCutProcess related operations.

`GCUT_PROCESS_ERROR_COMMAND_LINE` | Command line related error.
`GCUT_PROCESS_ERROR_IO_ERROR` | IO error.
`GCUT_PROCESS_ERROR_ALREADY_RUNNING` | External command is already running.
`GCUT_PROCESS_ERROR_NOT_RUNNING` | External command isn't running.
`GCUT_PROCESS_ERROR_INVALID_OBJECT` | Invalid GCutProcess object is passed.
`GCUT_PROCESS_ERROR_INVALID_SIGNAL` | Invalid signal is passed.
`GCUT_PROCESS_ERROR_PERMISSION_DENIED` | Permission denied.
`GCUT_PROCESS_ERROR_TIMEOUT` | Timeout.

Since 1.1.5

### gcut_process_error_quark ()

    GQuark              gcut_process_error_quark            (void);

### gcut_process_new ()

    GCutProcess *       gcut_process_new                    (const gchar *command,
                                                             ...);

Creates a new GCutProcess object that runs `command`.

`command` : | the external command name to be ran
`...` : | the arguments for `command`
Returns : | a new GCutProcess.

Since 1.1.5

### gcut_process_new_command_line ()

    GCutProcess *       gcut_process_new_command_line       (const gchar *command_line);

Creates a new GCutProcess object that runs `command_line`.

`command_line` : | a command line
Returns : | a new GCutProcess.

Since 1.1.5

### gcut_process_new_va_list ()

    GCutProcess *       gcut_process_new_va_list            (const gchar *command,
                                                             va_list args);

Creates a new GCutProcess object that runs `command`.

`command` : | the external command name to be ran
`args` : | arguments for `command`
Returns : | a new GCutProcess.

Since 1.1.5

### gcut_process_new_argv ()

    GCutProcess *       gcut_process_new_argv               (gint argc,
                                                             gchar **argv);

Creates a new GCutProcess object that runs `command`.

`argc` : | the number of elements of `argv`
`argv` : | the external command name to be ran and arguments of it.
Returns : | a new GCutProcess.

Since 1.1.5

### gcut_process_new_strings ()

    GCutProcess *       gcut_process_new_strings            (const gchar **command);

Creates a new GCutProcess object that runs `command`.

`command` : | the external command name to be ran and arguments of it. `NULL`-terminated.
Returns : | a new GCutProcess.

Since 1.1.5

### gcut_process_new_array ()

    GCutProcess *       gcut_process_new_array              (GArray *command);

Creates a new GCutProcess object that runs `command`.

`command` : | the external command name to be ran and arguments of it. The GArray should be zero-terminated.
Returns : | a new GCutProcess.

Since 1.1.5

### gcut_process_set_flags ()

    void                gcut_process_set_flags              (GCutProcess *process,
                                                             GSpawnFlags flags);

Sets `flags` for spawning.

`process` : | a GCutProcess
`flags` : | the flags to be passed to `g_spawn_async_with_pipes()`.

Since 1.1.5

### gcut_process_get_flags ()

    GSpawnFlags         gcut_process_get_flags              (GCutProcess *process);

Gets `flags` for spawning.

`process` : | a GCutProcess
Returns : | the flags for spawning.

Since 1.1.5

### gcut_process_set_env ()

    void                gcut_process_set_env                (GCutProcess *process,
                                                             const gchar *name,
                                                             ...);

Sets environment variable for external command.

`process` : | a GCutProcess
`name` : | the first environment name.
`...` : | the value of `name`, followed by name and value pairs. `NULL`-terminated.

Since 1.1.5

### gcut_process_get_env ()

    gchar **            gcut_process_get_env                (GCutProcess *process);

Gets environment variable for external command.

`process` : | a GCutProcess
Returns : | a newly-allocated `NULL`-terminated environment variables. ("NAME1=VALUE1", "NAME2=VALUE2", ..., `NULL`) It should be freed by `g_strfreev()` when no longer needed.

Since 1.1.5

### gcut_process_run ()

    gboolean            gcut_process_run                    (GCutProcess *process,
                                                             GError **error);

Runs a new external process.

`process` : | a GCutProcess
`error` : | return location for an error, or `NULL`
Returns : | `TRUE` on success, otherwise `FALSE`

Since 1.1.5

### gcut_process_get_pid ()

    GPid                gcut_process_get_pid                (GCutProcess *process);

Gets the process ID of running external process. If external process isn't running, 0 is returned.

`process` : | a GCutProcess
Returns : | the process ID of running external process if external process is running, otherwise 0.

Since 1.1.5

### gcut_process_wait ()

    gint                gcut_process_wait                   (GCutProcess *process,
                                                             guint timeout,
                                                             GError **error);

Waits running external process is finished while `timeout` milliseconds. If external process isn't finished while `timeout` milliseconds, `GCUT_PROCESS_ERROR_TIMEOUT` error is set and -1 is returned. If external process isn't running, `GCUT_PROCESS_ERROR_NOT_RUNNING` error is set and -1 is returned.

`process` : | a GCutProcess
`timeout` : | the timeout period in milliseconds
`error` : | return location for an error, or `NULL`
Returns : | an exit status of external process on success, otherwise -1.

Since 1.1.5

### gcut_process_kill ()

    gboolean            gcut_process_kill                   (GCutProcess *process,
                                                             gint signal_number,
                                                             GError **error);

Sends `signal_number` signal to external process.

`process` : | a GCutProcess
`signal_number` : | the signal number to be sent to external process
`error` : | return location for an error, or `NULL`
Returns : | `TRUE` on success, otherwise `FALSE`

Since 1.1.5

### gcut_process_write ()

    gboolean            gcut_process_write                  (GCutProcess *process,
                                                             const gchar *chunk,
                                                             gsize size,
                                                             GError **error);

Writes `chunk` to external process's standard input.

`process` : | a GCutProcess
`chunk` : | the data to be wrote
`size` : | the size of `chunk`
`error` : | return location for an error, or `NULL`
Returns : | `TRUE` on success, otherwise `FALSE`

Since 1.1.5

### gcut_process_flush ()

    GIOStatus           gcut_process_flush                  (GCutProcess *process,
                                                             GError **error);

Flush buffered external process's standard input.

`process` : | a GCutProcess
`error` : | return location for an error, or `NULL`
Returns : | the status of the operation: One of `G_IO_STATUS_NORMAL`, `G_IO_STATUS_AGAIN`, or `G_IO_STATUS_ERROR`.

Since 1.1.5

### gcut_process_get_output_string ()

    GString *           gcut_process_get_output_string      (GCutProcess *process);

`process` : | a GCutProcess
Returns : | a GString that has all result of standard output of external process.

Since 1.1.5

### gcut_process_get_error_string ()

    GString *           gcut_process_get_error_string       (GCutProcess *process);

`process` : | a GCutProcess
Returns : | a GString that has all result of standard error of external process.

Since 1.1.5

### gcut_process_get_input_channel ()

    GIOChannel *        gcut_process_get_input_channel      (GCutProcess *process);

Gets a GIOChannel connected with standard input of external process.

`process` : | a GCutProcess
Returns : | a GIOChannel if external process is running, otherwise `NULL`.

Since 1.1.5

### gcut_process_get_output_channel ()

    GIOChannel *        gcut_process_get_output_channel     (GCutProcess *process);

Gets a GIOChannel connected with standard output of external process.

`process` : | a GCutProcess
Returns : | a GIOChannel if external process is running, otherwise `NULL`.

Since 1.1.5

### gcut_process_get_error_channel ()

    GIOChannel *        gcut_process_get_error_channel      (GCutProcess *process);

Gets a GIOChannel connected with standard error output of external process.

`process` : | a GCutProcess
Returns : | a GIOChannel if external process is running, otherwise `NULL`.

Since 1.1.5

### gcut_process_get_output_stream ()

    GInputStream *      gcut_process_get_output_stream      (GCutProcess *process);

Gets a GInputStream connected with standard output of external process.

`process` : | a GCutProcess
Returns : | a GInputStream if external process is running, otherwise `NULL`.

Since 1.1.5

### gcut_process_get_error_stream ()

    GInputStream *      gcut_process_get_error_stream       (GCutProcess *process);

Gets a GInputStream connected with standard error output of external process.

`process` : | a GCutProcess
Returns : | a GInputStream if external process is running, otherwise `NULL`.

Since 1.1.5

### gcut_process_get_forced_termination_wait_time ()

    guint               gcut_process_get_forced_termination_wait_time
                                                            (GCutProcess *process);

Gets a wait time in milliseconds for forced termination on dispose.

`process` : | a GCutProcess
Returns : | a timeout value for waiting forced terminated external command on dispose.

Since 1.1.5

### gcut_process_set_forced_termination_wait_time ()

    void                gcut_process_set_forced_termination_wait_time
                                                            (GCutProcess *process,
                                                             guint timeout);

Sets a wait time in milliseconds for forced termination on dispose. If `timeout` is 0, it doesn't wait termination of external process. The default value is 10.

`process` : | a GCutProcess
`timeout` : | the timeout value in milliseconds

Since 1.1.5

### gcut_process_get_event_loop ()

    GCutEventLoop *     gcut_process_get_event_loop         (GCutProcess *process);

Gets a event loop using by the `process`.

`process` : | a GCutProcess
Returns : | a GCutEventLoop.

Since 1.1.6

### gcut_process_set_event_loop ()

    void                gcut_process_set_event_loop         (GCutProcess *process,
                                                             GCutEventLoop *loop);

Sets a event loop for the `process`. If `loop` is `NULL`, the default GLib event loop will be used.

`process` : | a GCutProcess
`loop` : | the event loop or `NULL`

Since 1.1.6

## Property Details

### The `"command"` property

      "command"                  gpointer              : Read / Write

The command to be ran by the process.

## Signal Details

### The `"error"` signal

    void                user_function                      (GCutProcess *process,
                                                            gpointer     error,
                                                            gpointer     user_data)      : Run Last

It is emitted each time an external process causes an error. (e.g. IO error)

`process` : | the object which received the signal.
`error` : | the error of an external process. (`GError`)
`user_data` : | user data set when the signal handler was connected.

Since 1.1.5

### The `"error-received"` signal

    void                user_function                      (GCutProcess *process,
                                                            gchar       *chunk,
                                                            guint64      size,
                                                            gpointer     user_data)      : Run Last

It is emitted each time an external process outputs something to its standard error output and it is read.

Note that you need to run `GCutEventLoop` by `gcut_event_loop_run()` or `gcut_event_loop_iterate()` for detecting an external process's output is readable.

`process` : | the object which received the signal.
`chunk` : | the chunk read from an external process's standard error output.
`size` : | the size of `chunk`. (`gsize`)
`user_data` : | user data set when the signal handler was connected.

Since 1.1.5

### The `"output-received"` signal

    void                user_function                      (GCutProcess *process,
                                                            gchar       *chunk,
                                                            guint64      size,
                                                            gpointer     user_data)      : Run Last

It is emitted each time an external process outputs something to its standard output and it is read.

Note that you need to run `GCutEventLoop` by `gcut_event_loop_run()` or `gcut_event_loop_iterate()` for detecting an external process's output is readable.

`process` : | the object which received the signal.
`chunk` : | the chunk read from an external process's standard output.
`size` : | the size of `chunk`. (`gsize`)
`user_data` : | user data set when the signal handler was connected.

Since 1.1.5

### The `"reaped"` signal

    void                user_function                      (GCutProcess *process,
                                                            gint         status,
                                                            gpointer     user_data)      : Run Last

It is emitted when an external process is exited.

Note that you need to run `GCutEventLoop` by `gcut_event_loop_run()` or `gcut_event_loop_iterate()` for detecting an external process is exited.

`process` : | the object which received the signal.
`status` : | the exit status of an external process.
`user_data` : | user data set when the signal handler was connected.

Since 1.1.5