## UDisksSpawnedJob

UDisksSpawnedJob — Job that spawns a command

## Functions

UDisksSpawnedJob * | udisks_spawned_job_new ()
const gchar * | udisks_spawned_job_get_command_line ()
void | udisks_spawned_job_start ()

## Properties

char * | command-line | Read / Write / Construct Only
AutowipeBuffer * | input-string | Write / Construct Only
guint | run-as-euid | Write / Construct Only
guint | run-as-uid | Write / Construct Only

## Signals

gboolean | spawned-job-completed | Run Last

## Types and Values

| UDisksSpawnedJob

## Object Hierarchy

        GObject
        ╰── GDBusInterfaceSkeleton
            ╰── UDisksJobSkeleton
                ╰── UDisksBaseJob
                    ╰── UDisksSpawnedJob

## Implemented Interfaces

UDisksSpawnedJob implements GDBusInterface and UDisksJob.

## Description

This type provides an implementation of the UDisksJob interface for jobs that are implemented by spawning a command line.

## Functions

### udisks_spawned_job_new ()

    UDisksSpawnedJob *
    udisks_spawned_job_new (const gchar *command_line,
                            GString *input_string,
                            uid_t run_as_uid,
                            uid_t run_as_euid,
                            UDisksDaemon *daemon,
                            GCancellable *cancellable);

Creates a new UDisksSpawnedJob instance.

The job is not started automatically! Use `udisks_spawned_job_start()` to start the job after “spawned-job-completed” or “completed” signals are connected (to get notified when the job is done). This is to prevent a race condition with the spawned process terminating before the signals are connected in which case the signal handlers are never triggered.

#### Parameters

command_line | The command line to run. |
input_string | A string to write to stdin of the spawned program or `NULL`. |
run_as_uid | The uid_t to run the program as. |
run_as_euid | The effective uid_t to run the program as. |
daemon | A UDisksDaemon. |
cancellable | A GCancellable or `NULL`. |

#### Returns

A new UDisksSpawnedJob. Free with `g_object_unref()`.

### udisks_spawned_job_get_command_line ()

    const gchar *
    udisks_spawned_job_get_command_line (UDisksSpawnedJob *job);

Gets the command line that `job` was constructed with.

#### Parameters

job | A UDisksSpawnedJob. |

#### Returns

A string owned by `job` . Do not free.

### udisks_spawned_job_start ()

    void
    udisks_spawned_job_start (UDisksSpawnedJob *job);

Connect to the “spawned-job-completed” or “completed” signals to get notified when the job is done.

*/ void udisks_spawned_job_start (UDisksSpawnedJob *job) { GError *error; gint child_argc; gchar **child_argv = NULL; struct passwd pwstruct; gchar pwbuf[8192]; struct passwd *pw = NULL; int rc;

job->main_context = `g_main_context_get_thread_default()`; if (job->main_context != NULL) g_main_context_ref (job->main_context);

/* could already be cancelled */ error = NULL; if (g_cancellable_set_error_if_cancelled (udisks_base_job_get_cancellable (UDISKS_BASE_JOB (job)), &error)) { emit_completed_with_error_in_idle (job, error); g_clear_error (&error); goto out; }

job->cancellable_handler_id = g_cancellable_connect (udisks_base_job_get_cancellable (UDISKS_BASE_JOB (job)), G_CALLBACK (on_cancelled), job, NULL);

error = NULL; if (!g_shell_parse_argv (job->command_line, &child_argc, &child_argv, &error)) { g_prefix_error (&error, "Error parsing command-line ``s`': ", job->command_line); emit_completed_with_error_in_idle (job, error); g_clear_error (&error); goto out; }

/* Save real egid and gid info for the child process */ if (job->run_as_uid != `getuid()` || job->run_as_euid != `geteuid()`) { rc = getpwuid_r (job->run_as_euid, &pwstruct, pwbuf, sizeof pwbuf, &pw); if (rc != 0 || pw == NULL) { g_set_error(&error, G_IO_ERROR, G_IO_ERROR_FAILED, "No password record for uid `d`: `m`\n", (gint) job->run_as_euid); emit_completed_with_error_in_idle (job, error); g_clear_error (&error); goto out; } job->real_egid = pw->pw_gid;

rc = getpwuid_r (job->run_as_uid, &pwstruct, pwbuf, sizeof pwbuf, &pw); if (rc != 0 || pw == NULL) { g_set_error(&error, G_IO_ERROR, G_IO_ERROR_FAILED, "No password record for uid `d`: `m`\n", (gint) job->run_as_uid); emit_completed_with_error_in_idle (job, error); g_clear_error (&error); goto out; } job->real_gid = pw->pw_gid; job->real_uid = pw->pw_uid; job->real_pwname = strdup (pw->pw_name); }

error = NULL; if (!g_spawn_async_with_pipes (NULL, /* working directory */ child_argv, NULL, /* envp */ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, child_setup, /* child_setup */ job, /* child_setup's user_data */ &(job->child_pid), job->input_string != NULL ? &(job->child_stdin_fd) : NULL, &(job->child_stdout_fd), &(job->child_stderr_fd), &error)) { g_prefix_error (&error, "Error spawning command-line ``s`': ", job->command_line); emit_completed_with_error_in_idle (job, error); g_clear_error (&error); goto out; }

job->child_watch_source = g_child_watch_source_new (job->child_pid); #if __GNUC__ >= 8 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-function-type" #endif /* parameters of the callback depend on the source and can be different from the required "generic" GSourceFunc, see: https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.htmlg-source-set-callback

#### Parameters

job | the job to start |

## Types and Values

### UDisksSpawnedJob

    typedef struct _UDisksSpawnedJob UDisksSpawnedJob;

The UDisksSpawnedJob structure contains only private data and should only be accessed using the provided API.

## Property Details

### The `“command-line”` property

      “command-line”             char *

The command-line to run.

Owner: UDisksSpawnedJob

Flags: Read / Write / Construct Only

Default value: NULL

### The `“input-string”` property

      “input-string”             AutowipeBuffer *

String that will be written to stdin of the spawned program or `NULL` to not write anything.

This is passed as autowipe_buffer (rather than G_TYPE_GSTRING) to nuke the contents after usage since the input string may contain key material.

Owner: UDisksSpawnedJob

Flags: Write / Construct Only

### The `“run-as-euid”` property

      “run-as-euid”              guint

The effective uid_t to run the program as.

Owner: UDisksSpawnedJob

Flags: Write / Construct Only

Default value: 0

### The `“run-as-uid”` property

      “run-as-uid”               guint

The uid_t to run the program as.

Owner: UDisksSpawnedJob

Flags: Write / Construct Only

Default value: 0

## Signal Details

### The `“spawned-job-completed”` signal

    gboolean
    user_function (UDisksSpawnedJob *job,
                   GError           *error,
                   int               status,
                   GString          *standard_output,
                   GString          *standard_error,
                   gpointer          user_data)

Emitted when the spawned job is complete. If spawning the command failed or if the job was cancelled, `error` will non-`NULL`. Otherwise you can use macros such as `WIFEXITED()` and `WEXITSTATUS()` on the `status` integer to obtain more information.

The default implementation simply emits the “completed” signal with `success` set to `TRUE` if, and only if, `error` is `NULL`, `WIFEXITED()` evaluates to `TRUE` and `WEXITSTATUS()` is zero. Additionally, `message` on that signal is set to `standard_error` regards of whether `success` is `TRUE` or `FALSE`.

You can avoid the default implementation by returning `TRUE` from your signal handler.

This signal is emitted in the

thread-default main loop

of the thread that `job` was created in.

#### Parameters

job | The UDisksSpawnedJob emitting the signal. |
error | `NULL` if running the whole command line succeeded, otherwise a GError that is set. |
status | The exit status of the command line that was run. |
standard_output | Standard output from the command line that was run. |
standard_error | Standard error output from the command line that was run. |
user_data | user data set when the signal handler was connected. |

#### Returns

`TRUE` if the signal was handled, `FALSE` to let other handlers run.

Flags: Run Last