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