UDisksSpawnedJob

UDisksSpawnedJob — Job that spawns a command

Functions

Properties

gchar * 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

Types and Values

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”             gchar *

The command-line to run.

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.

Flags: Write / Construct Only


The “run-as-euid” property

  “run-as-euid”              guint

The effective uid_t to run the program as.

Flags: Write / Construct Only

Default value: 0


The “run-as-uid” property

  “run-as-uid”               guint

The uid_t to run the program as.

Flags: Write / Construct Only

Default value: 0

Signal Details

The “spawned-job-completed” signal

gboolean
user_function (UDisksSpawnedJob *job,
               GError           *error,
               gint              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