Actually make the windows key the default meta key
[notion.git] / mod_statusbar / statusd-launch.c
blobff480f8cd38dacd0e5546f74c2c1156517af4e07
1 /*
2 * ion/mod_statusbar/statusd-launch.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <sys/time.h>
10 #include <sys/types.h>
11 #include <signal.h>
12 #include <unistd.h>
13 #include <time.h>
14 #include <errno.h>
16 #include <libtu/minmax.h>
17 #include <libextl/readconfig.h>
18 #include <libmainloop/exec.h>
19 #include <libmainloop/select.h>
20 #include <libmainloop/signal.h>
21 #include <ioncore/saveload.h>
22 #include <ioncore/bindmaps.h>
23 #include <ioncore/global.h>
24 #include <ioncore/ioncore.h>
26 #include "statusbar.h"
29 #define CF_STATUSD_TIMEOUT_SEC 3
31 #define BL 1024
33 #define USEC 1000000
35 static bool process_pipe(int fd, ExtlFn fn,
36 bool *doneseen, bool *eagain)
38 char buf[BL];
39 int n;
41 *eagain=FALSE;
43 n=read(fd, buf, BL-1);
45 if(n<0){
46 if(errno==EAGAIN || errno==EINTR){
47 *eagain=(errno==EAGAIN);
48 return TRUE;
50 warn_err_obj(TR("reading a pipe"));
51 return FALSE;
52 }else if(n>0){
53 buf[n]='\0';
54 *doneseen=FALSE;
55 return extl_call(fn, "s", "b", &buf, doneseen);
58 return FALSE;
62 static bool wait_statusd_init(int outfd, int errfd, ExtlFn dh, ExtlFn eh)
64 fd_set rfds;
65 struct timeval tv, endtime, now;
66 int nfds=maxof(outfd, errfd);
67 int retval;
68 bool dummy, doneseen, eagain=FALSE;
70 if(mainloop_gettime(&endtime)!=0){
71 warn_err();
72 return FALSE;
75 now=endtime;
76 endtime.tv_sec+=CF_STATUSD_TIMEOUT_SEC;
78 while(1){
79 FD_ZERO(&rfds);
81 /* Calculate remaining time */
82 if(now.tv_sec>endtime.tv_sec){
83 goto timeout;
84 }else if(now.tv_sec==endtime.tv_sec){
85 if(now.tv_usec>=endtime.tv_usec)
86 goto timeout;
87 tv.tv_sec=0;
88 tv.tv_usec=endtime.tv_usec-now.tv_usec;
89 }else{
90 tv.tv_usec=USEC+endtime.tv_usec-now.tv_usec;
91 tv.tv_sec=-1+endtime.tv_sec-now.tv_sec;
92 /* Kernel lameness tuner: */
93 tv.tv_sec+=tv.tv_usec/USEC;
94 tv.tv_usec%=USEC;
97 FD_SET(outfd, &rfds);
98 FD_SET(errfd, &rfds);
100 retval=select(nfds+1, &rfds, NULL, NULL, &tv);
101 if(retval>0){
102 if(FD_ISSET(errfd, &rfds)){
103 if(!process_pipe(errfd, eh, &dummy, &eagain))
104 return FALSE;
106 if(FD_ISSET(outfd, &rfds)){
107 if(!process_pipe(outfd, dh, &doneseen, &eagain))
108 return FALSE;
109 if(doneseen){
110 /* Read rest of errors. */
111 bool ok;
113 ok=process_pipe(errfd, eh, &dummy, &eagain);
114 }while(ok && !eagain);
115 return TRUE;
118 }else if(retval==0){
119 goto timeout;
122 if(mainloop_gettime(&now)!=0){
123 warn_err();
124 return FALSE;
128 return TRUE;
130 timeout:
131 /* Just complain to stderr, not startup error log, and do not fail.
132 * The system might just be a bit slow. We can continue, but without
133 * initial values for the meters, geometry adjustments may be necessary
134 * when we finally get that information.
136 ioncore_warn_nolog(TR("ion-statusd timed out."));
137 return TRUE;
141 EXTL_EXPORT
142 int mod_statusbar__launch_statusd(const char *cmd,
143 ExtlFn initdatahandler,
144 ExtlFn initerrhandler,
145 ExtlFn datahandler,
146 ExtlFn errhandler)
148 pid_t pid;
149 int outfd=-1, errfd=-1;
151 if(cmd==NULL)
152 return -1;
154 pid=mainloop_do_spawn(cmd, NULL, NULL,
155 NULL, &outfd, &errfd);
157 if(pid<0)
158 return -1;
160 if(!wait_statusd_init(outfd, errfd, initdatahandler, initerrhandler))
161 goto err;
163 if(!mainloop_register_input_fd_extlfn(outfd, datahandler))
164 goto err;
166 if(!mainloop_register_input_fd_extlfn(errfd, errhandler))
167 goto err2;
169 return pid;
171 err2:
172 mainloop_unregister_input_fd(outfd);
173 err:
174 close(outfd);
175 close(errfd);
176 return -1;
179 /* statusd automatically exits when notion dies. However, when notion is
180 * restarted (i.e. notioncore.restart()), the new notion process is simply
181 * execve'ed on top of the old one, therefore the ion-statusd process must
182 * be explicitly terminated on deinit. This function should be called
183 * from Lua on deinit with the ion-statusd process id generated above.
185 EXTL_EXPORT
186 int mod_statusbar__terminate_statusd(int pid)
188 if(pid==0) {
189 return -1;
192 /* Send SIGHUP to the specified statusd process to indicate
193 * that we're done. */
194 kill( (pid_t)pid, SIGHUP);
196 return 0;