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