/* PureAdmin * Copyright (C) 2003 Isak Savo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Functions related to run a program as root * * Copyright (C) 2003-2004 Isak Savo */ #ifdef HAVE_CONFIG_H # include #endif #include #ifdef HAVE_LIBDL #include #endif #include #include #include "globals.h" #include "binreloc.h" //#ifndef SELFPATH //# define SELFPATH BINDIR G_DIR_SEPARATOR_S "pureadmin" //#endif static void startup_notify_complete (void) { #ifdef HAVE_LIBDL void *gdk; gdk = dlopen (NULL, RTLD_LAZY); if (gdk) { void (*gdk_notify_startup_complete)() = dlsym (gdk, "gdk_notify_startup_complete"); if (gdk_notify_startup_complete) gdk_notify_startup_complete (); dlclose (gdk); } else pur_log_wrn ("Couldn't dlopen() myself: %s", g_strerror (errno)); #endif } gpointer gnomesu_dl = NULL; gboolean alternative_run_as_root (gchar **argv) { gboolean rv = FALSE; GError *err = NULL; gchar *icon = g_build_filename (pixmapdir, "pureadmin-48x48.png", NULL); /* No gnomesu available, try gksu as last resort (available on sudo distros, such as ubuntu) */ if (g_find_program_in_path ("gksudo")) { GString *pa_cmdline; gchar *cmd; gint exitstatus; pa_cmdline = g_string_new (""); argv++; while (*argv){ gchar *tmp = g_shell_quote (*argv); g_string_append (pa_cmdline, tmp); g_string_append_c (pa_cmdline, ' '); argv++; } cmd = g_strdup_printf ("gksudo --icon \"%s\" \"%s %s\"", icon, selfname, pa_cmdline->str); startup_notify_complete (); g_spawn_command_line_sync (cmd, NULL, NULL, &exitstatus, &err); g_string_free (pa_cmdline, TRUE); g_free (cmd); /* We should actually check the return value, but gksudo seems * to return anything *BUT* the documented values. */ if (err) { pur_log_err ("Error running gksudo: %s", err->message); g_error_free (err); rv = FALSE; } else if (!WIFEXITED(exitstatus)) { /* Terminated abnormally */ rv = FALSE; } else /* Exited alright and returned 0 */ rv = TRUE; } g_free (icon); return rv; } #ifndef HAVE_LIBDL gboolean init_suexec (void){ return TRUE; } gboolean run_as_root (gchar **argv) { return alternative_run_as_root (argv); } void suexec_shutdown (void) { return; } #else /* init_suexec: Tries to dlopen() libgnomesu, enabling easy switch-user * functions. */ gboolean init_suexec (void) { if (gnomesu_dl == NULL) { gnomesu_dl = dlopen ("libgnomesu.so", RTLD_LAZY); if (!gnomesu_dl) gnomesu_dl = dlopen ("libgnomesu.so.0", RTLD_LAZY); /* One more try */ if (!gnomesu_dl) return FALSE; } return TRUE; } /* suexec_shutdown: Closes the handle to libgnomesu */ void suexec_shutdown (void) { if (!gnomesu_dl) return; if (dlclose(gnomesu_dl) != 0) pur_log_wrn ("Unable to close gnomesu dl-handle: %s", dlerror()); } /* run_as_root: Wrapper around gnomesu_spawn_async() that executes pureadmin * as root. It does some sanity checks first, and makes sure that * the program executed is an absolute path. * * Arguments: argv The argument vector from main() */ gboolean run_as_root (gchar **argv) { static gboolean (*spawn_command) (gchar *,gchar**, gint*) = NULL; gchar *prgm, *tmp; gint pid = 0; if (!init_suexec()) return alternative_run_as_root (argv); dlerror(); if (spawn_command == NULL) { spawn_command = dlsym (gnomesu_dl, "gnomesu_spawn_async"); if ((tmp = dlerror()) != NULL) { pur_log_wrn ("Unable to retreive gnomesu function: %s", tmp); return FALSE; } } /* Ensure we have full path to pureadmin! */ if (!g_path_is_absolute (selfname)) { pur_log_wrn ("Cannot run %s: not an absolute path", selfname); return FALSE; } prgm = g_strdup (selfname); tmp = argv[0]; argv[0] = prgm; if (!spawn_command ("root", argv ,&pid)) pur_log_wrn ("Unable to run pureadmin as root"); argv[0] = tmp; g_free(prgm); return TRUE; } #endif /* HAVE_LIBDL */