Add comments to fork() logic for readibility
[notion/jeffpc.git] / ioncore / exec.c
blobe16480be45b0fa4638b4adfd09423a400ba09245
1 /*
2 * ion/ioncore/exec.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <limits.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <stdio.h>
14 #include <libmainloop/select.h>
15 #include <libmainloop/exec.h>
17 #include "common.h"
18 #include "exec.h"
19 #include "property.h"
20 #include "global.h"
21 #include "ioncore.h"
22 #include "saveload.h"
25 /*{{{ Exec */
28 void ioncore_setup_display(int xscr)
30 char *tmp, *ptr;
31 char *display;
33 /* Set up $DISPLAY */
35 display=XDisplayName(ioncore_g.display);
37 /* %ui, UINT_MAX is used to ensure there is enough space for the screen
38 * number
40 libtu_asprintf(&tmp, "DISPLAY=%s.0123456789a", display);
42 if(tmp==NULL)
43 return;
45 ptr=strchr(tmp, ':');
46 if(ptr!=NULL){
47 ptr=strchr(ptr, '.');
48 if(ptr!=NULL)
49 *ptr='\0';
52 if(xscr>=0)
53 snprintf(tmp+strlen(tmp), 11, ".%u", (unsigned)xscr);
55 putenv(tmp);
57 /* No need to free it, we'll execve soon */
58 /*free(tmp);*/
60 /*XFree(display);*/
64 void ioncore_setup_environ(const WExecP *p)
66 /* Set up $DISPLAY */
68 ioncore_setup_display(p->target!=NULL
69 ? region_rootwin_of(p->target)->xscr
70 : -1);
72 /* Set up working directory */
74 if(p->wd!=NULL){
75 if(chdir(p->wd)!=0)
76 warn_err_obj(p->wd);
81 WHook *ioncore_exec_environ_hook=NULL;
84 static void setup_exec(void *execp)
86 hook_call_p(ioncore_exec_environ_hook, execp, NULL);
88 #ifndef CF_NO_SETPGID
89 setpgid(0, 0);
90 #endif
92 ioncore_g.dpy=NULL;
96 EXTL_EXPORT
97 int ioncore_do_exec_on(WRegion *reg, const char *cmd, const char *wd,
98 ExtlFn errh)
100 WExecP p;
102 p.target=reg;
103 p.cmd=cmd;
104 p.wd=wd;
106 return mainloop_popen_bgread(cmd, setup_exec, (void*)&p,
107 extl_fn_none(), errh);
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.
117 EXTL_SAFE
118 EXTL_EXPORT
119 int ioncore_exec(const char *cmd)
121 return ioncore_do_exec_on(NULL, cmd, NULL, extl_fn_none());
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.
133 EXTL_SAFE
134 EXTL_EXPORT
135 int ioncore_popen_bgread(const char *cmd, ExtlFn h, ExtlFn errh,
136 const char *wd)
138 WExecP p;
140 p.target=NULL;
141 p.wd=wd;
142 p.cmd=cmd;
144 return mainloop_popen_bgread(cmd, setup_exec, (void*)&p, h, errh);
149 /*}}}*/
152 /*{{{ Exit, restart, snapshot */
155 static void (*smhook)(int what);
157 bool ioncore_set_smhook(void (*fn)(int what))
159 smhook=fn;
160 return TRUE;
164 void ioncore_do_exit()
166 ioncore_deinit();
167 exit(0);
171 bool ioncore_do_snapshot(bool save_layout)
173 if(save_layout && !ioncore_save_layout())
174 return FALSE;
176 extl_protect(NULL);
177 hook_call_v(ioncore_snapshot_hook);
178 extl_unprotect(NULL);
180 return TRUE;
184 void ioncore_emergency_snapshot()
186 if(smhook!=NULL)
187 warn(TR("Not saving state: running under session manager."));
188 else
189 ioncore_do_snapshot(TRUE);
194 static char *other=NULL;
196 static void set_other(const char *s)
198 if(other!=NULL)
199 free(other);
200 other=(s==NULL ? NULL : scopy(s));
204 void ioncore_do_restart()
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);
213 execvp(ioncore_g.argv[0], ioncore_g.argv);
214 die_err_obj(ioncore_g.argv[0]);
218 /*EXTL_DOC
219 * Causes the window manager to simply exit without saving
220 * state/session.
222 EXTL_EXPORT
223 void ioncore_resign()
225 if(smhook!=NULL){
226 smhook(IONCORE_SM_RESIGN);
227 }else{
228 ioncore_do_exit();
233 /*EXTL_DOC
234 * End session saving it first.
236 EXTL_EXPORT
237 void ioncore_shutdown()
239 if(smhook!=NULL){
240 smhook(IONCORE_SM_SHUTDOWN);
241 }else{
242 ioncore_do_snapshot(ioncore_g.autosave_layout);
243 ioncore_do_exit();
248 /*EXTL_DOC
249 * Restart, saving session first.
251 EXTL_EXPORT
252 void ioncore_restart()
254 set_other(NULL);
256 if(smhook!=NULL){
257 smhook(IONCORE_SM_RESTART);
258 }else{
259 ioncore_do_snapshot(ioncore_g.autosave_layout);
260 ioncore_do_restart();
265 /*EXTL_DOC
266 * Attempt to restart another window manager \var{cmd}.
268 EXTL_EXPORT
269 void ioncore_restart_other(const char *cmd)
271 set_other(cmd);
273 if(smhook!=NULL){
274 smhook(IONCORE_SM_RESTART_OTHER);
275 }else{
276 ioncore_do_snapshot(ioncore_g.autosave_layout);
277 ioncore_do_restart();
282 /*EXTL_DOC
283 * Save session.
285 EXTL_EXPORT
286 void ioncore_snapshot()
288 if(smhook!=NULL)
289 smhook(IONCORE_SM_SNAPSHOT);
290 else
291 ioncore_do_snapshot(TRUE);
295 /*}}}*/