Top |
UDisksSpawnedJob * | udisks_spawned_job_new () |
const gchar * | udisks_spawned_job_get_command_line () |
void | udisks_spawned_job_start () |
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 |
GObject ╰── GDBusInterfaceSkeleton ╰── UDisksJobSkeleton ╰── UDisksBaseJob ╰── UDisksSpawnedJob
This type provides an implementation of the UDisksJob interface for jobs that are implemented by spawning a command line.
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.
command_line |
The command line to run. |
|
input_string |
A string to write to stdin of the spawned program or |
|
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 |
const gchar *
udisks_spawned_job_get_command_line (UDisksSpawnedJob *job
);
Gets the command line that job
was constructed with.
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
typedef struct _UDisksSpawnedJob UDisksSpawnedJob;
The UDisksSpawnedJob structure contains only private data and should only be accessed using the provided API.
“command-line”
property “command-line” char *
The command-line to run.
Owner: UDisksSpawnedJob
Flags: Read / Write / Construct Only
Default value: NULL
“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
“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
“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
“spawned-job-completed”
signalgboolean 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 loopof the thread that job
was created in.
job |
The UDisksSpawnedJob emitting the signal. |
|
error |
|
|
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. |
Flags: Run Last