efl

Форк
0
/
quicklaunch.c 
380 строк · 10.5 Кб
1
#ifdef HAVE_CONFIG_H
2
# include "elementary_config.h"
3
#endif
4
#include <stdio.h>
5
#include <stdlib.h>
6
#include <errno.h>
7
#include <string.h>
8
#include <sys/types.h>
9
#include <sys/socket.h>
10
#include <sys/un.h>
11
#ifdef HAVE_ENVIRON
12
# define _GNU_SOURCE 1
13
#endif
14
#include <unistd.h>
15
#include <sys/stat.h>
16
#include <fcntl.h>
17
#include <signal.h>
18
#include <sys/wait.h>
19

20
#include <Elementary.h>
21

22
#ifdef HAVE_ENVIRON
23
extern char **environ;
24
#endif
25

26
static double restart_time = 0.0;
27

28
#define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
29

30
static struct sigaction old_sigint;
31
static struct sigaction old_sigterm;
32
static struct sigaction old_sigquit;
33
static struct sigaction old_sigalrm;
34
static struct sigaction old_sigusr1;
35
static struct sigaction old_sigusr2;
36
static struct sigaction old_sighup;
37
static struct sigaction old_sigchld;
38
static struct sigaction old_sigsegv;
39
static struct sigaction old_sigill;
40
static struct sigaction old_sigfpe;
41
static struct sigaction old_sigbus;
42
static struct sigaction old_sigabrt;
43
static int _log_dom = -1;
44

45
#define CRI(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
46
#define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
47
#define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
48
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
49
#define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
50

51
static void
52
post_fork(void *data EINA_UNUSED)
53
{
54
   sigaction(SIGINT, &old_sigint, NULL);
55
   sigaction(SIGTERM, &old_sigterm, NULL);
56
   sigaction(SIGQUIT, &old_sigquit, NULL);
57
   sigaction(SIGALRM, &old_sigalrm, NULL);
58
   sigaction(SIGUSR1, &old_sigusr1, NULL);
59
   sigaction(SIGUSR2, &old_sigusr2, NULL);
60
   sigaction(SIGHUP, &old_sighup, NULL);
61
   sigaction(SIGCHLD, &old_sigchld, NULL);
62
   sigaction(SIGSEGV, &old_sigsegv, NULL);
63
   sigaction(SIGILL, &old_sigill, NULL);
64
   sigaction(SIGFPE, &old_sigfpe, NULL);
65
   sigaction(SIGBUS, &old_sigbus, NULL);
66
   sigaction(SIGABRT, &old_sigabrt, NULL);
67
   if ((_log_dom > -1) && (_log_dom != EINA_LOG_DOMAIN_GLOBAL))
68
     {
69
        eina_log_domain_unregister(_log_dom);
70
        _log_dom = -1;
71
     }
72
}
73

74
static void
75
child_handler(int x EINA_UNUSED, siginfo_t *info EINA_UNUSED, void *data EINA_UNUSED)
76
{
77
   int status;
78
   while (waitpid(-1, &status, WNOHANG) > 0);
79
}
80

81
static void
82
crash_handler(int x EINA_UNUSED, siginfo_t *info EINA_UNUSED, void *data EINA_UNUSED)
83
{
84
   double t;
85

86
   ERR("crash detected. restarting.");
87
   t = ecore_time_get();
88
   if ((t - restart_time) <= 2.0)
89
     {
90
        CRI("crash too fast - less than 2 seconds. abort restart");
91
        exit(-1);
92
     }
93
   ecore_app_restart();
94
}
95

96
static void
97
handle_run(int fd, unsigned long bytes)
98
{
99
   unsigned char *buf = NULL;
100
   int i;
101
   char **argv = NULL;
102
   char **envir = NULL;
103
   char *cwd;
104
   int argc, envnum;
105
   unsigned long off;
106

107
   if (bytes < 1)
108
     {
109
        CRI("no bytes to quicklaunch");
110
        return;
111
     }
112
   DBG("Starting building up process.");
113
   _elm_startup_time = ecore_time_unix_get();
114

115
   buf = alloca(bytes);
116
   if (read(fd, buf, bytes) != (int)bytes)
117
     {
118
        CRI("cannot read %i bytes of args and environment data", (int)bytes);
119
        close(fd);
120
        return;
121
     }
122
   close(fd);
123
   buf[bytes - 1] = 0;
124

125
   argc = ((unsigned long *)(buf))[0];
126
   envnum = ((unsigned long *)(buf))[1];
127

128
   if (argc <= 0)
129
     {
130
        CRI("no executable specified");
131
        return;
132
     }
133

134
   argv = alloca(argc * sizeof(char *));
135
#ifdef HAVE_ENVIRON
136
   if (envnum > 0) envir = alloca(envnum * sizeof(char *));
137
#endif
138
   off = ((unsigned long *)(buf))[2 + argc + envnum] - sizeof(unsigned long);
139
   cwd = (char *)(buf + off);
140

141
   for (i = 0; i < argc; i++)
142
     {
143
        off = ((unsigned long *)(buf))[2 + i] - sizeof(unsigned long);
144
        argv[i] = (char *)(buf + off);
145
     }
146

147
#ifdef HAVE_ENVIRON
148
   if (envir)
149
     {
150
#ifdef HAVE_CLEARENV
151
        clearenv();
152
#else
153
        environ = NULL;
154
#endif
155
        for (i = 0; i < envnum; i++)
156
          {
157
             off = ((unsigned long *)(buf))[2 + argc + i] - sizeof(unsigned long);
158
             envir[i] = (char *)(buf + off);
159
             putenv(envir[i]);
160
          }
161
     }
162
#endif
163

164
   INF("Requested to run '%s' with %i arguments and %i environment.",
165
           argv[0], argc - 1, envnum);
166
   // Try new form before trying old form
167
   if (!efl_quicklaunch_prepare(argc, argv, cwd))
168
     {
169
        WRN("Failed to prepare with new EFL_MAIN macro, switching to legacy.");
170
        elm_quicklaunch_prepare(argc, argv, cwd);
171
     }
172

173
   elm_quicklaunch_fork(argc, argv, cwd, post_fork, NULL);
174
   elm_quicklaunch_cleanup();
175
}
176

177
int
178
main(int argc, char **argv)
179
{
180
   int sock, socket_unix_len;
181
   struct stat st;
182
   struct sockaddr_un socket_unix;
183
   struct linger lin;
184
   char buf[PATH_MAX];
185
   struct sigaction action;
186
   const char *domain;
187
   int ret = 0;
188
   size_t len;
189

190
   if (!eina_init())
191
     {
192
        fprintf(stderr, "ERROR: failed to init eina.");
193
        exit(-1);
194
     }
195
   _log_dom = eina_log_domain_register
196
      ("elementary_quicklaunch", EINA_COLOR_CYAN);
197
   if (_log_dom < 0)
198
     {
199
        EINA_LOG_ERR("could not register elementary_quicklaunch log domain.");
200
        _log_dom = EINA_LOG_DOMAIN_GLOBAL;
201
     }
202

203
   if (!(domain = getenv("ELM_QUICKLAUNCH_DOMAIN")))
204
     {
205
        domain = getenv("WAYLAND_DISPLAY");
206
        if (!domain) domain = getenv("DISPLAY");
207
        if (!domain) domain = "unknown";
208
     }
209
   eina_vpath_resolve_snprintf(buf, sizeof(buf), "(:usr.run:)/elm-ql-%i", getuid());
210
   if (stat(buf, &st) < 0)
211
     {
212
        ret = mkdir(buf, S_IRUSR | S_IWUSR | S_IXUSR);
213
        if (ret < 0)
214
          {
215
             CRI("cannot create directory '%s'", buf);
216
             exit(-1);
217
          }
218
     }
219
   eina_vpath_resolve_snprintf(buf, sizeof(buf), "(:usr.run:)/elm-ql-%i/%s", getuid(), domain);
220
   unlink(buf);
221
   sock = socket(AF_UNIX, SOCK_STREAM, 0);
222
   if (sock < 0)
223
     {
224
        CRI("cannot create socket for socket for '%s': %s",
225
                 buf, strerror(errno));
226
        exit(-1);
227
     }
228
   if (!eina_file_close_on_exec(sock, EINA_TRUE))
229
     {
230
        CRI("cannot set close on exec socket for '%s' (fd=%d): %s",
231
                 buf, sock, strerror(errno));
232
        exit(-1);
233
     }
234
   lin.l_onoff = 1;
235
   lin.l_linger = 0;
236
   if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0)
237
     {
238
        CRI("cannot set linger for socket for '%s' (fd=%d): %s",
239
                 buf, sock, strerror(errno));
240
        exit(-1);
241
     }
242
   socket_unix.sun_family = AF_UNIX;
243
   len = strlen(buf);
244
   if (len > sizeof(socket_unix.sun_path))
245
     {
246
        CRI("socket path '%s' is too long for buffer", buf);
247
        exit(-1);
248
     }
249
   memcpy(socket_unix.sun_path, buf, len);
250
   if (len < sizeof(socket_unix.sun_path)) socket_unix.sun_path[len] = 0;
251
   socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
252
   if (bind(sock, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
253
     {
254
        CRI("cannot bind socket for '%s' (fd=%d): %s",
255
                 buf, sock, strerror(errno));
256
        exit(-1);
257
     }
258
   if (listen(sock, 4096) < 0)
259
     {
260
        CRI("listen(sock=%d, 4096): %s", sock, strerror(errno));
261
        exit(-1);
262
     }
263
   elm_quicklaunch_mode_set(EINA_TRUE);
264
   elm_quicklaunch_init(argc, argv);
265
   restart_time = ecore_time_get();
266

267
   memset(&action, 0, sizeof(struct sigaction));
268
   action.sa_handler = SIG_DFL;
269
   action.sa_sigaction = NULL;
270
   action.sa_flags = SA_RESTART | SA_SIGINFO;
271
   sigemptyset(&action.sa_mask);
272
   sigaction(SIGINT, &action, &old_sigint);
273

274
   action.sa_handler = SIG_DFL;
275
   action.sa_sigaction = NULL;
276
   action.sa_flags = SA_RESTART | SA_SIGINFO;
277
   sigemptyset(&action.sa_mask);
278
   sigaction(SIGTERM, &action, &old_sigterm);
279

280
   action.sa_handler = SIG_DFL;
281
   action.sa_sigaction = NULL;
282
   action.sa_flags = SA_RESTART | SA_SIGINFO;
283
   sigemptyset(&action.sa_mask);
284
   sigaction(SIGQUIT, &action, &old_sigquit);
285

286
   action.sa_handler = SIG_DFL;
287
   action.sa_sigaction = NULL;
288
   action.sa_flags = SA_RESTART | SA_SIGINFO;
289
   sigemptyset(&action.sa_mask);
290
   sigaction(SIGALRM, &action, &old_sigalrm);
291

292
   action.sa_handler = SIG_DFL;
293
   action.sa_sigaction = NULL;
294
   action.sa_flags = SA_RESTART | SA_SIGINFO;
295
   sigemptyset(&action.sa_mask);
296
   sigaction(SIGUSR1, &action, &old_sigusr1);
297

298
   action.sa_handler = SIG_DFL;
299
   action.sa_sigaction = NULL;
300
   action.sa_flags = SA_RESTART | SA_SIGINFO;
301
   sigemptyset(&action.sa_mask);
302
   sigaction(SIGUSR2, &action, &old_sigusr2);
303

304
   action.sa_handler = SIG_DFL;
305
   action.sa_sigaction = NULL;
306
   action.sa_flags = SA_RESTART | SA_SIGINFO;
307
   sigemptyset(&action.sa_mask);
308
   sigaction(SIGHUP, &action, &old_sighup);
309

310
   action.sa_handler = NULL;
311
   action.sa_sigaction = child_handler;
312
   action.sa_flags = SA_RESTART | SA_SIGINFO;
313
   sigemptyset(&action.sa_mask);
314
   sigaction(SIGCHLD, &action, &old_sigchld);
315

316
   action.sa_handler = NULL;
317
   action.sa_sigaction = crash_handler;
318
   action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
319
   sigemptyset(&action.sa_mask);
320
   sigaction(SIGSEGV, &action, &old_sigsegv);
321

322
   action.sa_handler = NULL;
323
   action.sa_sigaction = crash_handler;
324
   action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
325
   sigemptyset(&action.sa_mask);
326
   sigaction(SIGILL, &action, &old_sigill);
327

328
   action.sa_handler = NULL;
329
   action.sa_sigaction = crash_handler;
330
   action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
331
   sigemptyset(&action.sa_mask);
332
   sigaction(SIGFPE, &action, &old_sigfpe);
333

334
   action.sa_handler = NULL;
335
   action.sa_sigaction = crash_handler;
336
   action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
337
   sigemptyset(&action.sa_mask);
338
   sigaction(SIGBUS, &action, &old_sigbus);
339

340
   action.sa_handler = NULL;
341
   action.sa_sigaction = crash_handler;
342
   action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
343
   sigemptyset(&action.sa_mask);
344
   sigaction(SIGABRT, &action, &old_sigabrt);
345

346
   for (;;)
347
     {
348
        int fd;
349
        struct sockaddr_un client;
350
        socklen_t slen;
351

352
        slen = sizeof(struct sockaddr_un);
353
        fd = accept(sock, (struct sockaddr *)&client, &slen);
354

355
        DBG("Accepting connection.");
356
        elm_quicklaunch_sub_init(argc, argv);
357
        // don't seed since we are doing this AFTER launch request
358
        // elm_quicklaunch_seed();
359
        if (fd >= 0)
360
          {
361
             unsigned long bytes;
362
             int num;
363

364
             num = read(fd, &bytes, sizeof(unsigned long));
365
             if (num == sizeof(unsigned long))
366
               handle_run(fd, bytes);
367
          }
368
        while (elm_quicklaunch_sub_shutdown() > 0);
369
     }
370
   elm_quicklaunch_shutdown();
371

372
   if ((_log_dom > -1) && (_log_dom != EINA_LOG_DOMAIN_GLOBAL))
373
     {
374
        eina_log_domain_unregister(_log_dom);
375
        _log_dom = -1;
376
     }
377
   eina_shutdown();
378

379
   return 0;
380
}
381

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.