1 /* $Id$ */
2 /*-
3  * Copyright (c) 2003-2004 Benedikt Meurer <benny@xfce.org>
4  * All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301 USA.
20 
21  *
22  * XXX - since this program is executed with root permissions, it may not
23  *       be a good idea to trust glib!!
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 #ifdef HAVE_SYS_WAIT_H
31 #include <sys/wait.h>
32 #endif
33 
34 #ifdef HAVE_MEMORY_H
35 #include <memory.h>
36 #endif
37 #ifdef HAVE_SIGNAL_H
38 #include <signal.h>
39 #endif
40 #include <stdio.h>
41 #ifdef HAVE_STDLIB_H
42 #include <stdlib.h>
43 #endif
44 #ifdef HAVE_STRING_H
45 #include <string.h>
46 #endif
47 #ifdef HAVE_UNISTD_H
48 #include <unistd.h>
49 #endif
50 
51 #include "libxfsm/xfsm-shutdown-common.h"
52 
53 #include <glib.h>
54 
55 /* XXX */
56 #define EXIT_CODE_SUCCESS           0
57 #define EXIT_CODE_FAILED            1
58 #define EXIT_CODE_ARGUMENTS_INVALID 3
59 #define EXIT_CODE_INVALID_USER      4
60 
61 
62 static gboolean
run(const gchar * command)63 run (const gchar *command)
64 {
65 #if defined(HAVE_SIGPROCMASK)
66   sigset_t sigset;
67 #endif
68   gboolean result;
69   gchar **argv;
70   gchar **envp;
71   GError *err = NULL;
72   gint status;
73   gint argc;
74 
75 #if defined(HAVE_SETSID)
76   setsid ();
77 #endif
78 
79 #if defined (HAVE_SIGPROCMASK)
80   sigemptyset (&sigset);
81   sigaddset (&sigset, SIGHUP);
82   sigaddset (&sigset, SIGINT);
83   sigprocmask (SIG_BLOCK, &sigset, NULL);
84 #endif
85 
86   result = g_shell_parse_argv (command, &argc, &argv, &err);
87 
88   if (result)
89     {
90       envp = g_new0 (gchar *, 1);
91 
92       result = g_spawn_sync (NULL, argv, envp,
93                              G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL |
94                              G_SPAWN_STDERR_TO_DEV_NULL,
95                              NULL, NULL, NULL, NULL, &status, &err);
96 
97       g_strfreev (envp);
98       g_strfreev (argv);
99     }
100 
101   if (!result)
102     {
103       puts (err->message);
104       g_error_free (err);
105       return FALSE;
106     }
107 
108   return (WIFEXITED (status) && WEXITSTATUS (status) == 0);
109 }
110 
111 
112 int
main(int argc,char ** argv)113 main (int argc, char **argv)
114 {
115   GOptionContext *context;
116   gint uid;
117   gint euid;
118   const gchar *pkexec_uid_str;
119   gboolean shutdown = FALSE;
120   gboolean restart = FALSE;
121   gboolean suspend = FALSE;
122   gboolean hibernate = FALSE;
123 
124   const GOptionEntry options[] = {
125     { "shutdown",  '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &shutdown, "Shutdown the system", NULL },
126     { "restart",   '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &restart, "Restart the system", NULL },
127     { "suspend",   '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &suspend, "Suspend the system", NULL },
128     { "hibernate", '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &hibernate, "Hibernate the system", NULL },
129     { NULL }
130   };
131 
132   context = g_option_context_new (NULL);
133   g_option_context_set_summary (context, "XFCE Session Helper");
134   g_option_context_add_main_entries (context, options, NULL);
135   g_option_context_parse (context, &argc, &argv, NULL);
136   g_option_context_free (context);
137 
138   /* no input */
139   if (!shutdown && !restart && !suspend && !hibernate)
140     {
141       puts ("No valid option was specified");
142       return EXIT_CODE_ARGUMENTS_INVALID;
143     }
144 
145   /* get calling process */
146   uid = getuid ();
147   euid = geteuid ();
148   if (uid != 0 || euid != 0)
149     {
150       puts ("This program can only be used by the root user");
151       return EXIT_CODE_ARGUMENTS_INVALID;
152     }
153 
154   /* check we're not being spoofed */
155   pkexec_uid_str = g_getenv ("PKEXEC_UID");
156   if (pkexec_uid_str == NULL)
157     {
158       puts ("This program must only be run through pkexec");
159       return EXIT_CODE_INVALID_USER;
160     }
161 
162   /* run the command */
163   if(shutdown)
164     {
165       if (run (POWEROFF_CMD))
166           {
167             return EXIT_CODE_SUCCESS;
168           }
169         else
170           {
171             return EXIT_CODE_FAILED;
172           }
173     }
174   else if(restart)
175     {
176       if (run (REBOOT_CMD))
177           {
178             return EXIT_CODE_SUCCESS;
179           }
180         else
181           {
182             return EXIT_CODE_FAILED;
183           }
184     }
185   else if(suspend)
186     {
187       if (run (UP_BACKEND_SUSPEND_COMMAND))
188           {
189             return EXIT_CODE_SUCCESS;
190           }
191         else
192           {
193             return EXIT_CODE_FAILED;
194           }
195     }
196   else if(hibernate)
197     {
198       if (run (UP_BACKEND_HIBERNATE_COMMAND))
199           {
200             return EXIT_CODE_SUCCESS;
201           }
202         else
203           {
204             return EXIT_CODE_FAILED;
205           }
206     }
207 
208   /* how did we get here? */
209   return EXIT_CODE_FAILED;
210 }
211 
212 
213