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