]> git.decadent.org.uk Git - ion3.git/blob - ioncore/exec.c
[svn-upgrade] Integrating new upstream version, ion3 (20070506)
[ion3.git] / ioncore / exec.c
1 /*
2  * ion/ioncore/exec.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2007. 
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} with a read pipe connected to its stdout.
127  * When data is received through the pipe, \var{handler} is called
128  * with that data.
129  */
130 EXTL_SAFE
131 EXTL_EXPORT
132 int ioncore_popen_bgread(const char *cmd, ExtlFn h, ExtlFn errh)
133 {
134     WExecP p;
135     
136     p.target=NULL;
137     p.wd=NULL;
138     p.cmd=cmd;
139     
140     return mainloop_popen_bgread(cmd, setup_exec, (void*)&p, h, errh);
141 }
142
143
144
145 /*}}}*/
146
147
148 /*{{{ Exit, restart, snapshot */
149
150
151 static void (*smhook)(int what);
152
153 bool ioncore_set_smhook(void (*fn)(int what))
154 {
155     smhook=fn;
156     return TRUE;
157 }
158
159
160 void ioncore_do_exit()
161 {
162     ioncore_deinit();
163     exit(0);
164 }
165
166
167 bool ioncore_do_snapshot()
168 {
169     if(!ioncore_save_layout())
170         return FALSE;
171
172     extl_protect(NULL);
173     hook_call_v(ioncore_snapshot_hook);
174     extl_unprotect(NULL);
175     
176     return TRUE;
177 }
178
179
180 void ioncore_emergency_snapshot()
181 {
182     if(smhook!=NULL)
183         warn(TR("Not saving state: running under session manager."));
184     else
185         ioncore_do_snapshot();
186 }
187
188
189
190 static char *other=NULL;
191
192 static void set_other(const char *s)
193 {
194     if(other!=NULL)
195         free(other);
196     other=(s==NULL ? NULL : scopy(s));
197 }
198
199
200 void ioncore_do_restart()
201 {
202     ioncore_deinit();
203     if(other!=NULL){
204         if(ioncore_g.display!=NULL)
205             ioncore_setup_display(-1);
206         mainloop_do_exec(other);
207         warn_err_obj(other);
208     }
209     execvp(ioncore_g.argv[0], ioncore_g.argv);
210     die_err_obj(ioncore_g.argv[0]);
211 }
212
213
214 /*EXTL_DOC
215  * Causes the window manager to simply exit without saving
216  * state/session.
217  */
218 EXTL_EXPORT
219 void ioncore_resign()
220 {
221     if(smhook!=NULL){
222         smhook(IONCORE_SM_RESIGN);
223     }else{
224         ioncore_do_exit();
225     }
226 }
227
228
229 /*EXTL_DOC
230  * End session saving it first.
231  */
232 EXTL_EXPORT
233 void ioncore_shutdown()
234 {
235     if(smhook!=NULL){
236         smhook(IONCORE_SM_SHUTDOWN);
237     }else{
238         ioncore_do_snapshot();
239         ioncore_do_exit();
240     }
241 }
242
243
244 /*EXTL_DOC
245  * Restart, saving session first.
246  */
247 EXTL_EXPORT
248 void ioncore_restart()
249 {
250     set_other(NULL);
251     
252     if(smhook!=NULL){
253         smhook(IONCORE_SM_RESTART);
254     }else{
255         ioncore_do_snapshot();
256         ioncore_do_restart();
257     }
258 }
259
260
261 /*EXTL_DOC
262  * Attempt to restart another window manager \var{cmd}.
263  */
264 EXTL_EXPORT
265 void ioncore_restart_other(const char *cmd)
266 {
267     set_other(cmd);
268     
269     if(smhook!=NULL){
270         smhook(IONCORE_SM_RESTART_OTHER);
271     }else{
272         ioncore_do_snapshot();
273         ioncore_do_restart();
274     }
275 }
276
277
278 /*EXTL_DOC
279  * Save session.
280  */
281 EXTL_EXPORT
282 void ioncore_snapshot()
283 {
284     if(smhook!=NULL)
285         smhook(IONCORE_SM_SNAPSHOT);
286     else
287         ioncore_do_snapshot();
288 }
289
290
291 /*}}}*/
292