]> git.decadent.org.uk Git - ion3.git/blob - ioncore/exec.c
06838a65bc2ccbd0542dd17fad40fe769332ed0c
[ion3.git] / ioncore / exec.c
1 /*
2  * ion/ioncore/exec.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2007. 
5  *
6  * Ion is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  */
11
12 #include <limits.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16
17 #include <libmainloop/select.h>
18 #include <libmainloop/exec.h>
19
20 #include "common.h"
21 #include "exec.h"
22 #include "property.h"
23 #include "global.h"
24 #include "ioncore.h"
25 #include "saveload.h"
26
27
28 /*{{{ Exec */
29
30
31 void ioncore_setup_display(int xscr)
32 {
33     char *tmp, *ptr;
34     char *display;
35
36     /* Set up $DISPLAY */
37     
38     display=XDisplayName(ioncore_g.display);
39     
40     /* %ui, UINT_MAX is used to ensure there is enough space for the screen
41      * number
42      */
43     libtu_asprintf(&tmp, "DISPLAY=%s.0123456789a", display);
44
45     if(tmp==NULL)
46         return;
47
48     ptr=strchr(tmp, ':');
49     if(ptr!=NULL){
50         ptr=strchr(ptr, '.');
51         if(ptr!=NULL)
52             *ptr='\0';
53     }
54
55     if(xscr>=0)
56         snprintf(tmp+strlen(tmp), 11, ".%u", (unsigned)xscr);
57     
58     putenv(tmp);
59         
60     /* No need to free it, we'll execve soon */
61     /*free(tmp);*/
62
63     /*XFree(display);*/
64 }
65
66
67 void ioncore_setup_environ(const WExecP *p)
68 {
69     /* Set up $DISPLAY */
70     
71     ioncore_setup_display(p->target!=NULL 
72                           ? region_rootwin_of(p->target)->xscr
73                           : -1);
74     
75     /* Set up working directory */
76     
77     if(p->wd!=NULL){
78         if(chdir(p->wd)!=0)
79             warn_err_obj(p->wd);
80     }
81 }
82
83
84 WHook *ioncore_exec_environ_hook=NULL;
85
86
87 static void setup_exec(void *execp)
88 {
89     hook_call_p(ioncore_exec_environ_hook, execp, NULL);
90     
91 #ifndef CF_NO_SETPGID
92     setpgid(0, 0);
93 #endif
94     
95     ioncore_g.dpy=NULL;
96 }
97
98
99 EXTL_EXPORT
100 int ioncore_do_exec_on(WRegion *reg, const char *cmd, const char *wd,
101                        ExtlFn errh)
102 {
103     WExecP p;
104     
105     p.target=reg;
106     p.cmd=cmd;
107     p.wd=wd;
108     
109     return mainloop_popen_bgread(cmd, setup_exec, (void*)&p, 
110                                  extl_fn_none(), errh);
111 }
112
113
114 /*EXTL_DOC
115  * Run \var{cmd} with the environment variable DISPLAY set to point to the
116  * X display the WM is running on. No specific screen is set unlike with
117  * \fnref{WRootWin.exec_on}. The PID of the (shell executing the) new 
118  * process is returned.
119  */
120 EXTL_SAFE
121 EXTL_EXPORT
122 int ioncore_exec(const char *cmd)
123 {
124     return ioncore_do_exec_on(NULL, cmd, NULL, extl_fn_none());
125 }
126
127
128 /*EXTL_DOC
129  * Run \var{cmd} with a read pipe connected to its stdout.
130  * When data is received through the pipe, \var{handler} is called
131  * with that data.
132  */
133 EXTL_SAFE
134 EXTL_EXPORT
135 int ioncore_popen_bgread(const char *cmd, ExtlFn h, ExtlFn errh)
136 {
137     WExecP p;
138     
139     p.target=NULL;
140     p.wd=NULL;
141     p.cmd=cmd;
142     
143     return mainloop_popen_bgread(cmd, setup_exec, (void*)&p, h, errh);
144 }
145
146
147
148 /*}}}*/
149
150
151 /*{{{ Exit, restart, snapshot */
152
153
154 static void (*smhook)(int what);
155
156 bool ioncore_set_smhook(void (*fn)(int what))
157 {
158     smhook=fn;
159     return TRUE;
160 }
161
162
163 void ioncore_do_exit()
164 {
165     ioncore_deinit();
166     exit(0);
167 }
168
169
170 bool ioncore_do_snapshot()
171 {
172     if(!ioncore_save_layout())
173         return FALSE;
174
175     extl_protect(NULL);
176     hook_call_v(ioncore_snapshot_hook);
177     extl_unprotect(NULL);
178     
179     return TRUE;
180 }
181
182
183 void ioncore_emergency_snapshot()
184 {
185     if(smhook!=NULL)
186         warn(TR("Not saving state: running under session manager."));
187     else
188         ioncore_do_snapshot();
189 }
190
191
192
193 static char *other=NULL;
194
195 static void set_other(const char *s)
196 {
197     if(other!=NULL)
198         free(other);
199     other=(s==NULL ? NULL : scopy(s));
200 }
201
202
203 void ioncore_do_restart()
204 {
205     ioncore_deinit();
206     if(other!=NULL){
207         if(ioncore_g.display!=NULL)
208             ioncore_setup_display(-1);
209         mainloop_do_exec(other);
210         warn_err_obj(other);
211     }
212     execvp(ioncore_g.argv[0], ioncore_g.argv);
213     die_err_obj(ioncore_g.argv[0]);
214 }
215
216
217 /*EXTL_DOC
218  * Causes the window manager to simply exit without saving
219  * state/session.
220  */
221 EXTL_EXPORT
222 void ioncore_resign()
223 {
224     if(smhook!=NULL){
225         smhook(IONCORE_SM_RESIGN);
226     }else{
227         ioncore_do_exit();
228     }
229 }
230
231
232 /*EXTL_DOC
233  * End session saving it first.
234  */
235 EXTL_EXPORT
236 void ioncore_shutdown()
237 {
238     if(smhook!=NULL){
239         smhook(IONCORE_SM_SHUTDOWN);
240     }else{
241         ioncore_do_snapshot();
242         ioncore_do_exit();
243     }
244 }
245
246
247 /*EXTL_DOC
248  * Restart, saving session first.
249  */
250 EXTL_EXPORT
251 void ioncore_restart()
252 {
253     set_other(NULL);
254     
255     if(smhook!=NULL){
256         smhook(IONCORE_SM_RESTART);
257     }else{
258         ioncore_do_snapshot();
259         ioncore_do_restart();
260     }
261 }
262
263
264 /*EXTL_DOC
265  * Attempt to restart another window manager \var{cmd}.
266  */
267 EXTL_EXPORT
268 void ioncore_restart_other(const char *cmd)
269 {
270     set_other(cmd);
271     
272     if(smhook!=NULL){
273         smhook(IONCORE_SM_RESTART_OTHER);
274     }else{
275         ioncore_do_snapshot();
276         ioncore_do_restart();
277     }
278 }
279
280
281 /*EXTL_DOC
282  * Save session.
283  */
284 EXTL_EXPORT
285 void ioncore_snapshot()
286 {
287     if(smhook!=NULL)
288         smhook(IONCORE_SM_SNAPSHOT);
289     else
290         ioncore_do_snapshot();
291 }
292
293
294 /*}}}*/
295