elm test: Separated test menu creation function.
[framework/uifw/elementary.git] / src / bin / quicklaunch.c
1 #include <Elementary.h>
2 #ifdef HAVE_CONFIG_H
3 # include "elementary_config.h"
4 #endif
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <errno.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #include <sys/socket.h>
11 #include <sys/un.h>
12 #include <unistd.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <signal.h>
16 #include <sys/wait.h>
17
18 static double restart_time = 0.0;
19
20 #define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
21
22 static struct sigaction old_sigint;
23 static struct sigaction old_sigterm;
24 static struct sigaction old_sigquit;
25 static struct sigaction old_sigalrm;
26 static struct sigaction old_sigusr1;
27 static struct sigaction old_sigusr2;
28 static struct sigaction old_sighup;
29 static struct sigaction old_sigchld;
30 static struct sigaction old_sigsegv;
31 static struct sigaction old_sigill;
32 static struct sigaction old_sigfpe;
33 static struct sigaction old_sigbus;
34 static struct sigaction old_sigabrt;
35 static int _log_dom = -1;
36
37 #define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
38 #define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
39 #define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
40 #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
41 #define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
42
43 static void
44 post_fork(void *data __UNUSED__)
45 {
46    sigaction(SIGINT, &old_sigint, NULL);
47    sigaction(SIGTERM, &old_sigterm, NULL);
48    sigaction(SIGQUIT, &old_sigquit, NULL);
49    sigaction(SIGALRM, &old_sigalrm, NULL);
50    sigaction(SIGUSR1, &old_sigusr1, NULL);
51    sigaction(SIGUSR2, &old_sigusr2, NULL);
52    sigaction(SIGHUP, &old_sighup, NULL);
53    sigaction(SIGCHLD, &old_sigchld, NULL);
54    sigaction(SIGSEGV, &old_sigsegv, NULL);
55    sigaction(SIGILL, &old_sigill, NULL);
56    sigaction(SIGFPE, &old_sigfpe, NULL);
57    sigaction(SIGBUS, &old_sigbus, NULL);
58    sigaction(SIGABRT, &old_sigabrt, NULL);
59    if ((_log_dom > -1) && (_log_dom != EINA_LOG_DOMAIN_GLOBAL))
60      {
61         eina_log_domain_unregister(_log_dom);
62         _log_dom = -1;
63      }
64 }
65
66 static void
67 child_handler(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
68 {
69    int status;
70    while (waitpid(-1, &status, WNOHANG) > 0);
71 }
72
73 static void
74 crash_handler(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__)
75 {
76    double t;
77
78    ERR("crash detected. restarting.");
79    t = ecore_time_get();
80    if ((t - restart_time) <= 2.0)
81      {
82         CRITICAL("crash too fast - less than 2 seconds. abort restart");
83         exit(-1);
84      }
85    ecore_app_restart();
86 }
87
88 static void
89 handle_run(int fd, unsigned long bytes)
90 {
91    unsigned char *buf = NULL;
92    int i;
93    char **argv = NULL;
94    char *cwd;
95    int argc;
96
97    buf = alloca(bytes);
98    if (read(fd, buf, bytes) <= 0)
99      {
100         close(fd);
101         return;
102      }
103    close(fd);
104    argc = ((unsigned long *)(buf))[0];
105    argv = (char **)(&(((unsigned long *)(buf))[1]));
106    for (i = 0; i < argc; i++) argv[i] = (char *)(buf + (unsigned long)argv[i]);
107    cwd = argv[argc - 1] + strlen(argv[argc - 1]) + 1;
108    elm_quicklaunch_prepare(argc, argv);
109    elm_quicklaunch_fork(argc, argv, cwd, post_fork, NULL);
110    elm_quicklaunch_cleanup();
111 }
112
113 int
114 main(int argc, char **argv)
115 {
116    int sock, socket_unix_len;
117    struct stat st;
118    struct sockaddr_un socket_unix;
119    struct linger lin;
120    char buf[PATH_MAX];
121    struct sigaction action;
122
123    if (!eina_init())
124      {
125         fprintf(stderr, "ERROR: failed to init eina.");
126         exit(-1);
127      }
128    _log_dom = eina_log_domain_register
129      ("elementary_quicklaunch", EINA_COLOR_CYAN);
130    if (_log_dom < 0)
131      {
132         EINA_LOG_ERR("could not register elementary_quicklaunch log domain.");
133         _log_dom = EINA_LOG_DOMAIN_GLOBAL;
134      }
135
136    if (!getenv("DISPLAY"))
137      {
138         CRITICAL("DISPLAY env var not set");
139         exit(-1);
140      }
141    snprintf(buf, sizeof(buf), "/tmp/elm-ql-%i", getuid());
142    if (stat(buf, &st) < 0) mkdir(buf, S_IRUSR | S_IWUSR | S_IXUSR);
143    snprintf(buf, sizeof(buf), "/tmp/elm-ql-%i/%s", getuid(), getenv("DISPLAY"));
144    unlink(buf);
145    sock = socket(AF_UNIX, SOCK_STREAM, 0);
146    if (sock < 0)
147      {
148         CRITICAL("cannot create socket for socket for '%s': %s",
149                  buf, strerror(errno));
150         exit(-1);
151      }
152    if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0)
153      {
154         CRITICAL("cannot set close on exec socket for '%s' (fd=%d): %s",
155                  buf, sock, strerror(errno));
156         exit(-1);
157      }
158    lin.l_onoff = 1;
159    lin.l_linger = 0;
160    if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0)
161      {
162         CRITICAL("cannot set linger for socket for '%s' (fd=%d): %s",
163                  buf, sock, strerror(errno));
164         exit(-1);
165      }
166    socket_unix.sun_family = AF_UNIX;
167    strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
168    socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
169    if (bind(sock, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
170      {
171         CRITICAL("cannot bind socket for '%s' (fd=%d): %s",
172                  buf, sock, strerror(errno));
173         exit(-1);
174      }
175    if (listen(sock, 4096) < 0)
176      {
177         CRITICAL("listen(sock=%d, 4096): %s", sock, strerror(errno));
178         exit(-1);
179      }
180    elm_quicklaunch_mode_set(EINA_TRUE);
181    elm_quicklaunch_init(argc, argv);
182    restart_time = ecore_time_get();
183
184    memset(&action, 0, sizeof(struct sigaction));
185    action.sa_handler = SIG_DFL;
186    action.sa_sigaction = NULL;
187    action.sa_flags = SA_RESTART | SA_SIGINFO;
188    sigemptyset(&action.sa_mask);
189    sigaction(SIGINT, &action, &old_sigint);
190
191    action.sa_handler = SIG_DFL;
192    action.sa_sigaction = NULL;
193    action.sa_flags = SA_RESTART | SA_SIGINFO;
194    sigemptyset(&action.sa_mask);
195    sigaction(SIGTERM, &action, &old_sigterm);
196
197    action.sa_handler = SIG_DFL;
198    action.sa_sigaction = NULL;
199    action.sa_flags = SA_RESTART | SA_SIGINFO;
200    sigemptyset(&action.sa_mask);
201    sigaction(SIGQUIT, &action, &old_sigquit);
202
203    action.sa_handler = SIG_DFL;
204    action.sa_sigaction = NULL;
205    action.sa_flags = SA_RESTART | SA_SIGINFO;
206    sigemptyset(&action.sa_mask);
207    sigaction(SIGALRM, &action, &old_sigalrm);
208
209    action.sa_handler = SIG_DFL;
210    action.sa_sigaction = NULL;
211    action.sa_flags = SA_RESTART | SA_SIGINFO;
212    sigemptyset(&action.sa_mask);
213    sigaction(SIGUSR1, &action, &old_sigusr1);
214
215    action.sa_handler = SIG_DFL;
216    action.sa_sigaction = NULL;
217    action.sa_flags = SA_RESTART | SA_SIGINFO;
218    sigemptyset(&action.sa_mask);
219    sigaction(SIGUSR2, &action, &old_sigusr2);
220
221    action.sa_handler = SIG_DFL;
222    action.sa_sigaction = NULL;
223    action.sa_flags = SA_RESTART | SA_SIGINFO;
224    sigemptyset(&action.sa_mask);
225    sigaction(SIGHUP, &action, &old_sighup);
226
227    action.sa_handler = NULL;
228    action.sa_sigaction = child_handler;
229    action.sa_flags = SA_RESTART | SA_SIGINFO;
230    sigemptyset(&action.sa_mask);
231    sigaction(SIGCHLD, &action, &old_sigchld);
232
233    action.sa_handler = NULL;
234    action.sa_sigaction = crash_handler;
235    action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
236    sigemptyset(&action.sa_mask);
237    sigaction(SIGSEGV, &action, &old_sigsegv);
238
239    action.sa_handler = NULL;
240    action.sa_sigaction = crash_handler;
241    action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
242    sigemptyset(&action.sa_mask);
243    sigaction(SIGILL, &action, &old_sigill);
244
245    action.sa_handler = NULL;
246    action.sa_sigaction = crash_handler;
247    action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
248    sigemptyset(&action.sa_mask);
249    sigaction(SIGFPE, &action, &old_sigfpe);
250
251    action.sa_handler = NULL;
252    action.sa_sigaction = crash_handler;
253    action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
254    sigemptyset(&action.sa_mask);
255    sigaction(SIGBUS, &action, &old_sigbus);
256
257    action.sa_handler = NULL;
258    action.sa_sigaction = crash_handler;
259    action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
260    sigemptyset(&action.sa_mask);
261    sigaction(SIGABRT, &action, &old_sigabrt);
262
263    for (;;)
264      {
265         int fd;
266         struct sockaddr_un client;
267         socklen_t len;
268
269         len = sizeof(struct sockaddr_un);
270         fd = accept(sock, (struct sockaddr *)&client, &len);
271         elm_quicklaunch_sub_init(argc, argv);
272 // don't seed since we are doing this AFTER launch request        
273 //      elm_quicklaunch_seed();
274         if (fd >= 0)
275           {
276              unsigned long bytes;
277              int num;
278
279              num = read(fd, &bytes, sizeof(unsigned long));
280              if (num == sizeof(unsigned long))
281                {
282                   ecore_app_args_set(argc, (const char **)argv);
283                   handle_run(fd, bytes);
284                }
285           }
286         while (elm_quicklaunch_sub_shutdown() > 0);
287      }
288    elm_quicklaunch_shutdown();
289
290    if ((_log_dom > -1) && (_log_dom != EINA_LOG_DOMAIN_GLOBAL))
291      {
292         eina_log_domain_unregister(_log_dom);
293         _log_dom = -1;
294      }
295    eina_shutdown();
296
297    return 0;
298 }