1 #include <Elementary.h>
3 # include "elementary_config.h"
10 #include <sys/socket.h>
13 # define _GNU_SOURCE 1
22 extern char **environ;
25 static double restart_time = 0.0;
27 #define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
29 static struct sigaction old_sigint;
30 static struct sigaction old_sigterm;
31 static struct sigaction old_sigquit;
32 static struct sigaction old_sigalrm;
33 static struct sigaction old_sigusr1;
34 static struct sigaction old_sigusr2;
35 static struct sigaction old_sighup;
36 static struct sigaction old_sigchld;
37 static struct sigaction old_sigsegv;
38 static struct sigaction old_sigill;
39 static struct sigaction old_sigfpe;
40 static struct sigaction old_sigbus;
41 static struct sigaction old_sigabrt;
42 static int _log_dom = -1;
44 #define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
45 #define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
46 #define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
47 #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
48 #define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
51 post_fork(void *data __UNUSED__)
53 sigaction(SIGINT, &old_sigint, NULL);
54 sigaction(SIGTERM, &old_sigterm, NULL);
55 sigaction(SIGQUIT, &old_sigquit, NULL);
56 sigaction(SIGALRM, &old_sigalrm, NULL);
57 sigaction(SIGUSR1, &old_sigusr1, NULL);
58 sigaction(SIGUSR2, &old_sigusr2, NULL);
59 sigaction(SIGHUP, &old_sighup, NULL);
60 sigaction(SIGCHLD, &old_sigchld, NULL);
61 sigaction(SIGSEGV, &old_sigsegv, NULL);
62 sigaction(SIGILL, &old_sigill, NULL);
63 sigaction(SIGFPE, &old_sigfpe, NULL);
64 sigaction(SIGBUS, &old_sigbus, NULL);
65 sigaction(SIGABRT, &old_sigabrt, NULL);
66 if ((_log_dom > -1) && (_log_dom != EINA_LOG_DOMAIN_GLOBAL))
68 eina_log_domain_unregister(_log_dom);
74 child_handler(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
77 while (waitpid(-1, &status, WNOHANG) > 0);
81 crash_handler(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
85 ERR("crash detected. restarting.");
87 if ((t - restart_time) <= 2.0)
89 CRITICAL("crash too fast - less than 2 seconds. abort restart");
96 handle_run(int fd, unsigned long bytes)
98 unsigned char *buf = NULL;
107 if (read(fd, buf, bytes) != (int)bytes)
109 CRITICAL("cannot read %i bytes of args and environment data", (int)bytes);
115 argc = ((unsigned long *)(buf))[0];
116 envnum = ((unsigned long *)(buf))[1];
120 CRITICAL("no executable specified");
124 argv = alloca(argc * sizeof(char *));
125 if (envnum > 0) envir = alloca(envnum * sizeof(char *));
126 off = ((unsigned long *)(buf))[2 + argc + envnum] - sizeof(unsigned long);
127 cwd = (char *)(buf + off);
129 for (i = 0; i < argc; i++)
131 off = ((unsigned long *)(buf))[2 + i] - sizeof(unsigned long);
132 argv[i] = (char *)(buf + off);
143 for (i = 0; i < envnum; i++)
145 off = ((unsigned long *)(buf))[2 + argc + i] - sizeof(unsigned long);
146 envir[i] = (char *)(buf + off);
151 elm_quicklaunch_prepare(argc, argv);
152 elm_quicklaunch_fork(argc, argv, cwd, post_fork, NULL);
153 elm_quicklaunch_cleanup();
157 main(int argc, char **argv)
159 int sock, socket_unix_len;
161 struct sockaddr_un socket_unix;
164 struct sigaction action;
169 fprintf(stderr, "ERROR: failed to init eina.");
172 _log_dom = eina_log_domain_register
173 ("elementary_quicklaunch", EINA_COLOR_CYAN);
176 EINA_LOG_ERR("could not register elementary_quicklaunch log domain.");
177 _log_dom = EINA_LOG_DOMAIN_GLOBAL;
180 if (!(disp = getenv("DISPLAY"))) disp = "unknown";
181 snprintf(buf, sizeof(buf), "/tmp/elm-ql-%i", getuid());
182 if (stat(buf, &st) < 0)
183 if (mkdir(buf, S_IRUSR | S_IWUSR | S_IXUSR) < 0)
185 CRITICAL("cannot create directory '%s' : %s",
186 buf, strerror(errno));
189 snprintf(buf, sizeof(buf), "/tmp/elm-ql-%i/%s", getuid(), disp);
191 sock = socket(AF_UNIX, SOCK_STREAM, 0);
194 CRITICAL("cannot create socket for socket for '%s': %s",
195 buf, strerror(errno));
198 if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0)
200 CRITICAL("cannot set close on exec socket for '%s' (fd=%d): %s",
201 buf, sock, strerror(errno));
206 if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0)
208 CRITICAL("cannot set linger for socket for '%s' (fd=%d): %s",
209 buf, sock, strerror(errno));
212 socket_unix.sun_family = AF_UNIX;
213 strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
214 socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
215 if (bind(sock, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
217 CRITICAL("cannot bind socket for '%s' (fd=%d): %s",
218 buf, sock, strerror(errno));
221 if (listen(sock, 4096) < 0)
223 CRITICAL("listen(sock=%d, 4096): %s", sock, strerror(errno));
226 elm_quicklaunch_mode_set(EINA_TRUE);
227 elm_quicklaunch_init(argc, argv);
228 restart_time = ecore_time_get();
230 memset(&action, 0, sizeof(struct sigaction));
231 action.sa_handler = SIG_DFL;
232 action.sa_sigaction = NULL;
233 action.sa_flags = SA_RESTART | SA_SIGINFO;
234 sigemptyset(&action.sa_mask);
235 sigaction(SIGINT, &action, &old_sigint);
237 action.sa_handler = SIG_DFL;
238 action.sa_sigaction = NULL;
239 action.sa_flags = SA_RESTART | SA_SIGINFO;
240 sigemptyset(&action.sa_mask);
241 sigaction(SIGTERM, &action, &old_sigterm);
243 action.sa_handler = SIG_DFL;
244 action.sa_sigaction = NULL;
245 action.sa_flags = SA_RESTART | SA_SIGINFO;
246 sigemptyset(&action.sa_mask);
247 sigaction(SIGQUIT, &action, &old_sigquit);
249 action.sa_handler = SIG_DFL;
250 action.sa_sigaction = NULL;
251 action.sa_flags = SA_RESTART | SA_SIGINFO;
252 sigemptyset(&action.sa_mask);
253 sigaction(SIGALRM, &action, &old_sigalrm);
255 action.sa_handler = SIG_DFL;
256 action.sa_sigaction = NULL;
257 action.sa_flags = SA_RESTART | SA_SIGINFO;
258 sigemptyset(&action.sa_mask);
259 sigaction(SIGUSR1, &action, &old_sigusr1);
261 action.sa_handler = SIG_DFL;
262 action.sa_sigaction = NULL;
263 action.sa_flags = SA_RESTART | SA_SIGINFO;
264 sigemptyset(&action.sa_mask);
265 sigaction(SIGUSR2, &action, &old_sigusr2);
267 action.sa_handler = SIG_DFL;
268 action.sa_sigaction = NULL;
269 action.sa_flags = SA_RESTART | SA_SIGINFO;
270 sigemptyset(&action.sa_mask);
271 sigaction(SIGHUP, &action, &old_sighup);
273 action.sa_handler = NULL;
274 action.sa_sigaction = child_handler;
275 action.sa_flags = SA_RESTART | SA_SIGINFO;
276 sigemptyset(&action.sa_mask);
277 sigaction(SIGCHLD, &action, &old_sigchld);
279 action.sa_handler = NULL;
280 action.sa_sigaction = crash_handler;
281 action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
282 sigemptyset(&action.sa_mask);
283 sigaction(SIGSEGV, &action, &old_sigsegv);
285 action.sa_handler = NULL;
286 action.sa_sigaction = crash_handler;
287 action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
288 sigemptyset(&action.sa_mask);
289 sigaction(SIGILL, &action, &old_sigill);
291 action.sa_handler = NULL;
292 action.sa_sigaction = crash_handler;
293 action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
294 sigemptyset(&action.sa_mask);
295 sigaction(SIGFPE, &action, &old_sigfpe);
297 action.sa_handler = NULL;
298 action.sa_sigaction = crash_handler;
299 action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
300 sigemptyset(&action.sa_mask);
301 sigaction(SIGBUS, &action, &old_sigbus);
303 action.sa_handler = NULL;
304 action.sa_sigaction = crash_handler;
305 action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
306 sigemptyset(&action.sa_mask);
307 sigaction(SIGABRT, &action, &old_sigabrt);
312 struct sockaddr_un client;
315 len = sizeof(struct sockaddr_un);
316 fd = accept(sock, (struct sockaddr *)&client, &len);
317 elm_quicklaunch_sub_init(argc, argv);
318 // don't seed since we are doing this AFTER launch request
319 // elm_quicklaunch_seed();
325 num = read(fd, &bytes, sizeof(unsigned long));
326 if (num == sizeof(unsigned long))
327 handle_run(fd, bytes);
329 while (elm_quicklaunch_sub_shutdown() > 0);
331 elm_quicklaunch_shutdown();
333 if ((_log_dom > -1) && (_log_dom != EINA_LOG_DOMAIN_GLOBAL))
335 eina_log_domain_unregister(_log_dom);