c6b121a66ce93c893bec71608b46ab1a2622beef
[platform/core/appfw/debug-launchpad.git] / src / common.c
1 /*
2  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define _GNU_SOURCE
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdbool.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <sys/xattr.h>
27 #include <sys/socket.h>
28 #include <sys/un.h>
29 #include <errno.h>
30 #include <dirent.h>
31 #include <unistd.h>
32 #include <bundle.h>
33 #include <bundle_internal.h>
34 #ifdef _APPFW_FEATURE_SOCKET_ACTIVATION
35 #include <systemd/sd-daemon.h>
36 #endif /* _APPFW_FEATURE_SOCKET_ACTIVATION */
37
38 #include "common.h"
39 #include "debug_util.h"
40 #include "defs.h"
41
42 #define MAX_PATH_LEN 1024
43 #define MAX_CMD_BUFSZ 1024
44 #define PATH_TMP "/tmp"
45 #define PATH_DATA "/data"
46 #define AUL_PKT_HEADER_SIZE (sizeof(int) + sizeof(int) + sizeof(int))
47
48 static void __set_sock_option(int fd, int cli)
49 {
50         int size;
51         struct timeval tv = { 5, 200 * 1000 };  /* 5.2 sec */
52
53         size = AUL_SOCK_MAXBUFF;
54         setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
55         setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
56         if (cli)
57                 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
58 }
59
60 #ifdef _APPFW_FEATURE_SOCKET_ACTIVATION
61 static int __create_sock_activation(void)
62 {
63         int listen_fds;
64
65         listen_fds = sd_listen_fds(0);
66         if (listen_fds == 1)
67                 return SD_LISTEN_FDS_START;
68         else if (listen_fds > 1)
69                 _E("Too many file descriptors received.");
70         else
71                 _E("There is no socket stream");
72
73         return -1;
74 }
75 #endif /* _APPFW_FEATURE_SOCKET_ACTIVATION */
76
77 static int __create_server_socket(bool is_app)
78 {
79         struct sockaddr_un saddr;
80         int fd;
81         int ret;
82
83         if (is_app)
84                 fd = socket(AF_UNIX, SOCK_STREAM, 0);
85         else
86                 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
87         /* support above version 2.6.27 */
88         if (fd < 0) {
89                 if (errno == EINVAL) {
90                         fd = socket(AF_UNIX, SOCK_STREAM, 0);
91                         if (fd < 0) {
92                                 _E("second chance - socket create error");
93                                 return -1;
94                         }
95                 } else {
96                         _E("socket error");
97                         return -1;
98                 }
99         }
100
101         memset(&saddr, 0, sizeof(saddr));
102         saddr.sun_family = AF_UNIX;
103
104         if (is_app) {
105                 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
106                                 "%s/apps/%d/%d",
107                                 SOCKET_PATH, getuid(), getpid());
108                 ret = mkdir(saddr.sun_path, 0700);
109                 if (ret != 0) {
110                         if (errno == EEXIST) {
111                                 if (access(saddr.sun_path, R_OK) != 0) {
112                                         _E("Failed to access %s directory - %d",
113                                                         saddr.sun_path, errno);
114                                         close(fd);
115                                         return -1;
116                                 }
117                         } else {
118                                 _E("Failed to create %s directory - %d",
119                                                 saddr.sun_path, errno);
120                                 close(fd);
121                                 return -1;
122                         }
123                 }
124                 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
125                                 "%s/apps/%d/%d/.app-sock",
126                                 SOCKET_PATH, getuid(), getpid());
127         } else {
128                 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
129                                 "%s/daemons/%d/.debug-launchpad-sock",
130                                 SOCKET_PATH, getuid());
131         }
132         unlink(saddr.sun_path);
133
134         if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
135                 _E("bind error");
136                 close(fd);
137                 return -1;
138         }
139
140         if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
141                 /* Flawfinder: ignore */
142                 _E("Failed to change the socket permission");
143                 close(fd);
144                 return -1;
145         }
146
147         __set_sock_option(fd, 0);
148
149         if (listen(fd, 128) == -1) {
150                 _E("listen error");
151                 close(fd);
152                 return -1;
153         }
154
155         return fd;
156 }
157
158 int _create_server_sock(void)
159 {
160         int fd = -1;
161
162 #ifdef _APPFW_FEATURE_SOCKET_ACTIVATION
163         fd = __create_sock_activation();
164 #endif /* _APPFW_FEATURE_SOCKET_ACTIAVTION */
165         if (fd < 0) {
166                 fd = __create_server_socket(false);
167                 if (fd < 0) {
168                         _E("server sock error %d", fd);
169                         return -1;
170                 }
171         }
172
173         return fd;
174 }
175
176 app_pkt_t *_recv_pkt_raw(int fd, int *clifd, struct ucred *cr)
177 {
178         int len;
179         int ret;
180         struct sockaddr_un aul_addr = {0, };
181         int sun_size;
182         app_pkt_t *pkt = NULL;
183         int cl = sizeof(struct ucred);
184         unsigned char buf[AUL_SOCK_MAXBUFF];
185         int cmd;
186         int datalen;
187         int opt;
188
189         sun_size = sizeof(struct sockaddr_un);
190
191         *clifd = accept(fd, (struct sockaddr *)&aul_addr,
192                         (socklen_t *)&sun_size);
193         if (*clifd == -1) {
194                 if (errno != EINTR)
195                         _E("accept error");
196                 return NULL;
197         }
198
199         if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
200                                 (socklen_t *)&cl) < 0) {
201                 _E("peer information error");
202                 close(*clifd);
203                 return NULL;
204         }
205
206         __set_sock_option(*clifd, 1);
207
208 retry_recv:
209         /* receive header(cmd, datalen) */
210         len = recv(*clifd, buf, AUL_PKT_HEADER_SIZE, 0);
211         if (len < 0)
212                 if (errno == EINTR)
213                         goto retry_recv;
214
215         if (len < AUL_PKT_HEADER_SIZE) {
216                 _E("recv error");
217                 close(*clifd);
218                 return NULL;
219         }
220         memcpy(&cmd, buf, sizeof(int));
221         memcpy(&datalen, buf + sizeof(int), sizeof(int));
222         memcpy(&opt, buf + sizeof(int) + sizeof(int), sizeof(int));
223
224         /* allocate for a null byte */
225         pkt = (app_pkt_t *)calloc(1, AUL_PKT_HEADER_SIZE + datalen + 1);
226         if (pkt == NULL) {
227                 close(*clifd);
228                 return NULL;
229         }
230         pkt->cmd = cmd;
231         pkt->len = datalen;
232         pkt->opt = opt;
233
234         len = 0;
235         while (len != pkt->len) {
236                 ret = recv(*clifd, pkt->data + len, pkt->len - len, 0);
237                 if (ret < 0) {
238                         _E("recv error %d %d", len, pkt->len);
239                         free(pkt);
240                         close(*clifd);
241                         return NULL;
242                 }
243                 len += ret;
244                 _D("recv len %d %d", len, pkt->len);
245         }
246
247         return pkt;
248 }
249
250 static char *__appinfo_get_app_path(appinfo_t *appinfo)
251 {
252         int i = 0;
253         int path_len = -1;
254         char *tmp_app_path;
255
256         if (appinfo == NULL || appinfo->app_path == NULL)
257                 return NULL;
258
259         while (appinfo->app_path[i] != 0) {
260                 if (appinfo->app_path[i] == ' '
261                                 || appinfo->app_path[i] == '\t') {
262                         path_len = i;
263                         break;
264                 }
265
266                 i++;
267         }
268
269         if (path_len == 0) {
270                 free(appinfo->app_path);
271                 appinfo->app_path = NULL;
272         } else if (path_len > 0) {
273                 tmp_app_path = (char *)malloc(sizeof(char) * (path_len + 1));
274                 if (tmp_app_path == NULL)
275                         return NULL;
276
277                 snprintf(tmp_app_path, path_len + 1, "%s", appinfo->app_path);
278                 free(appinfo->app_path);
279                 appinfo->app_path = tmp_app_path;
280         }
281
282         return appinfo->app_path;
283 }
284
285 appinfo_t *_appinfo_create(bundle *kb)
286 {
287         appinfo_t *appinfo;
288         const char *ptr;
289
290         appinfo = (appinfo_t *)calloc(1, sizeof(appinfo_t));
291         if (appinfo == NULL)
292                 return NULL;
293
294         ptr = bundle_get_val(kb, AUL_K_APPID);
295         if (ptr)
296                 appinfo->appid = strdup(ptr);
297         ptr = bundle_get_val(kb, AUL_K_PACKAGETYPE);
298         if (ptr)
299                 appinfo->pkg_type = strdup(ptr);
300         ptr = bundle_get_val(kb, AUL_K_HWACC);
301         if (ptr)
302                 appinfo->hwacc = strdup(ptr);
303         ptr = bundle_get_val(kb, AUL_K_PKGID);
304         if (ptr)
305                 appinfo->debug_appid = strdup(ptr);
306         ptr = bundle_get_val(kb, AUL_K_TASKMANAGE);
307         if (ptr)
308                 appinfo->taskmanage = strdup(ptr);
309         ptr = bundle_get_val(kb, AUL_K_COMP_TYPE);
310         if (ptr)
311                 appinfo->comp_type = strdup(ptr);
312         ptr = bundle_get_val(kb, AUL_K_PKGID);
313         if (ptr)
314                 appinfo->pkgid = strdup(ptr);
315         ptr = bundle_get_val(kb, AUL_K_EXEC);
316         if (ptr)
317                 appinfo->app_path = strdup(ptr);
318         if (appinfo->app_path)
319                 appinfo->original_app_path = strdup(appinfo->app_path);
320
321         if (__appinfo_get_app_path(appinfo) == NULL) {
322                 _appinfo_free(appinfo);
323                 return NULL;
324         }
325
326         return appinfo;
327 }
328
329 void _appinfo_free(appinfo_t *appinfo)
330 {
331         if (appinfo == NULL)
332                 return;
333
334         if (appinfo->appid)
335                 free(appinfo->appid);
336         if (appinfo->app_path)
337                 free(appinfo->app_path);
338         if (appinfo->original_app_path)
339                 free(appinfo->original_app_path);
340         if (appinfo->pkg_type)
341                 free(appinfo->pkg_type);
342         if (appinfo->hwacc)
343                 free(appinfo->hwacc);
344         if (appinfo->taskmanage)
345                 free(appinfo->taskmanage);
346         if (appinfo->debug_appid)
347                 free(appinfo->debug_appid);
348         if (appinfo->comp_type)
349                 free(appinfo->comp_type);
350         if (appinfo->pkgid)
351                 free(appinfo->pkgid);
352
353         free(appinfo);
354 }
355
356 static int __parse_app_path(const char *arg, char *out, int out_size)
357 {
358         register int i;
359         int state = 1;
360         char *start_out = out;
361
362         if (arg == NULL || out == NULL)
363                 return 0;
364
365         for (i = 0; out_size > 1; i++) {
366                 switch (state) {
367                 case 1:
368                         switch (arg[i]) {
369                         case ' ':
370                         case '\t':
371                                 state = 5;
372                                 break;
373                         case '\0':
374                                 state = 7;
375                                 break;
376                         case '\"':
377                                 state = 2;
378                                 break;
379                         case '\\':
380                                 state = 4;
381                                 break;
382                         default:
383                                 *out = arg[i];
384                                 out++;
385                                 out_size--;
386                                 break;
387                         }
388                         break;
389                 case 2: /* escape start */
390                         switch (arg[i]) {
391                         case '\0':
392                                 state = 6;
393                                 break;
394                         case '\"':
395                                 state = 1;
396                                 break;
397                         default:
398                                 *out = arg[i];
399                                 out++;
400                                 out_size--;
401                                 break;
402                         }
403                         break;
404                 case 4: /* character escape */
405                         if (arg[i] == '\0')
406                                 state = 6;
407                         else {
408                                 *out = arg[i];
409                                 out++;
410                                 out_size--;
411                                 state = 1;
412                         }
413                         break;
414                 case 5: /* token */
415                         if (out != start_out) {
416                                 *out = '\0';
417                                 out_size--;
418                                 return i;
419                         }
420                         i--;
421                         state = 1;
422                         break;
423                 case 6:
424                         return -1;  /* error */
425                 case 7: /* terminate */
426                         *out = '\0';
427                         out_size--;
428                         return 0;
429                 default:
430                         state = 6;
431                         break;  /* error */
432                 }
433         }
434
435         if (out_size == 1)
436                 *out = '\0';
437
438         /* Buffer overflow*/
439         return -2;
440 }
441
442 void _modify_bundle(bundle *kb, int caller_pid, appinfo_t *appinfo, int cmd)
443 {
444         char *ptr;
445         char exe[MAX_PATH_LEN];
446         int flag;
447         char key[256];
448         char value[256];
449
450         bundle_del(kb, AUL_K_APPID);
451         bundle_del(kb, AUL_K_EXEC);
452         bundle_del(kb, AUL_K_PACKAGETYPE);
453         bundle_del(kb, AUL_K_HWACC);
454         bundle_del(kb, AUL_K_PKGID);
455         bundle_del(kb, AUL_K_TASKMANAGE);
456         bundle_del(kb, AUL_K_COMP_TYPE);
457
458         /* Parse app_path to retrieve default bundle */
459         if (cmd == PAD_CMD_LAUNCH) {
460                 ptr = appinfo->original_app_path;
461                 flag = __parse_app_path(ptr, exe, sizeof(exe));
462                 if (flag > 0) {
463                         ptr += flag;
464                         SECURE_LOGD("parsing app_path: EXEC - %s", exe);
465
466                         do {
467                                 flag = __parse_app_path(ptr, key, sizeof(key));
468                                 if (flag <= 0)
469                                         break;
470                                 ptr += flag;
471
472                                 flag = __parse_app_path(ptr, value,
473                                                 sizeof(value));
474                                 if (flag < 0)
475                                         break;
476                                 ptr += flag;
477
478                                 /* bundle_del(kb, key); */
479                                 bundle_add(kb, key, value);
480                         } while (flag > 0);
481                 } else if (flag == 0) {
482                         _D("parsing app_path: No arguments");
483                 } else {
484                         _D("parsing app_path: Invalid argument");
485                 }
486
487         }
488 }
489
490 static char *__get_libdir(const char *path)
491 {
492         char *path_dup;
493         char buf[PATH_MAX];
494         char *ptr;
495
496         path_dup = strdup(path);
497         if (path_dup == NULL)
498                 return NULL;
499
500         ptr = strrchr(path_dup, '/');
501         if (ptr == NULL)
502                 return NULL;
503
504         *ptr = '\0';
505
506         snprintf(buf, sizeof(buf), "%s/../lib/", path_dup);
507         free(path_dup);
508
509         if (access(buf, F_OK) == -1)
510                 return NULL;
511
512         return strdup(buf);
513 }
514
515 static void __set_sdk_env(const char *appid, const char *value)
516 {
517         char buf[MAX_LOCAL_BUFSZ];
518         char *token = NULL;
519
520         _D("key: %s / value: %s", AUL_K_SDK, value);
521         /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
522         /* GCOV_PREFIX contains the prefix to add to the absolute paths */
523         /*      in the object file. Prefix can be absolute, or relative.*/
524         /*      The default is no prefix.  */
525         /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
526         /*      to stripoff the hardwired absolute paths. Default value is 0. */
527         if (strncmp(value, SDK_CODE_COVERAGE, strlen(value)) == 0) {
528                 token = strrchr(appid, '.');
529                 if (token == NULL)
530                         return;
531                 token++;
532
533                 snprintf(buf, sizeof(buf), PATH_TMP"/%s"PATH_DATA, token);
534                 setenv("GCOV_PREFIX", buf, 1);
535                 setenv("GCOV_PREFIX_STRIP", "0", 1);
536         }
537 }
538
539 void _set_env(appinfo_t *appinfo, bundle *kb)
540 {
541         const char *str;
542         const char **str_array = NULL;
543         int len = 0;
544         int i;
545         char *libdir;
546
547         setenv("PKG_NAME", appinfo->appid, 1);
548
549         str = bundle_get_val(kb, AUL_K_STARTTIME);
550         if (str)
551                 setenv("APP_START_TIME", str, 1);
552         if (appinfo->hwacc)
553                 setenv("HWACC", appinfo->hwacc, 1);
554         if (appinfo->taskmanage)
555                 setenv("TASKMANAGE", appinfo->taskmanage, 1);
556         if (appinfo->appid)
557                 setenv("AUL_APPID", appinfo->appid, 1);
558         if (appinfo->pkgid)
559                 setenv("AUL_PKGID", appinfo->pkgid, 1);
560
561         str = bundle_get_val(kb, AUL_K_WAYLAND_DISPLAY);
562         if (str)
563                 setenv("WAYLAND_DISPLAY", str, 1);
564
565         str = bundle_get_val(kb, AUL_K_WAYLAND_WORKING_DIR);
566         if (str)
567                 setenv("XDG_RUNTIME_DIR", str, 1);
568
569         str = bundle_get_val(kb, AUL_K_API_VERSION);
570         if (str)
571                 setenv("TIZEN_API_VERSION", str, 1);
572
573         str = bundle_get_val(kb, AUL_K_ROOT_PATH);
574         if (str)
575                 setenv("AUL_ROOT_PATH", str, 1);
576
577         libdir = __get_libdir(appinfo->app_path);
578         if (libdir) {
579                 setenv("LD_LIBRARY_PATH", libdir, 1);
580                 free(libdir);
581         }
582
583         if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
584                 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
585         } else {
586                 str = bundle_get_val(kb, AUL_K_SDK);
587                 if (str) {
588                         str_array = &str;
589                         len = 1;
590                 }
591         }
592
593         for (i = 0; i < len; i++)
594                 __set_sdk_env(appinfo->appid, str_array[i]);
595 }
596
597 static char **__add_arg(bundle *kb, char **argv, int *margc, const char *key)
598 {
599         const char *str = NULL;
600         const char **str_array = NULL;
601         int len = 0;
602         int i;
603         char **new_argv = NULL;
604
605         if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
606                 str_array = bundle_get_str_array(kb, key, &len);
607         } else {
608                 str = bundle_get_val(kb, key);
609                 if (str) {
610                         str_array = &str;
611                         len = 1;
612                 }
613         }
614
615         if (str_array) {
616                 if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
617                         || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) {
618                         new_argv = (char **)realloc(argv,
619                                         sizeof(char *) * (*margc + len + 2));
620                         if (new_argv == NULL) {
621                                 _E("Failed to realloc (key: %s)", key);
622                                 exit(-1);
623                         }
624
625                         for (i = *margc + len + 1; i - (len + 1) >= 0; i--)
626                                 new_argv[i] = new_argv[i - (len + 1)];
627
628                         /* need to add new_argv[0] */
629                         for (i = 0; i < len; i++)
630                                 new_argv[1 + i] = strdup(str_array[i]);
631
632                         len++; /* gdbserver or valgrind */
633                 } else if (strncmp(key, DLP_K_ATTACH_ARG, strlen(key)) == 0) {
634                         new_argv = (char **)malloc((len + 2) * sizeof(char *));
635                         if (new_argv == NULL) {
636                                 _E("Failed to malloc (key: %s)", key);
637                                 exit(-1);
638                         }
639
640                         for (i = 0; i < len; i++)
641                                 new_argv[1 + i] = strdup(str_array[i]);
642
643                         *margc = 0;
644                         len = len + 1;
645                 } else {
646                         new_argv = (char **)realloc(argv,
647                                         sizeof(char *) * (*margc + len + 1));
648                         if (new_argv == NULL) {
649                                 _E("Failed to realloc (key: %s)", key);
650                                 exit(-1);
651                         }
652
653                         for (i = 0; i < len; i++)
654                                 new_argv[*margc + i] = strdup(str_array[i]);
655                 }
656
657                 new_argv[*margc + len] = NULL;
658                 *margc += len;
659         } else {
660                 if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
661                         || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) {
662                         new_argv = (char **)realloc(argv,
663                                         sizeof(char *) * (*margc + 2));
664                         if (new_argv == NULL) {
665                                 _E("Failed to realloc (key: %s)", key);
666                                 exit(-1);
667                         }
668
669                         for (i = *margc + 1; i - 1 >= 0; i--)
670                                 new_argv[i] = new_argv[i - 1];
671
672                         /* need to add new_argv[0] */
673                         (*margc)++;
674                 }
675         }
676
677         if (new_argv == NULL)
678                 return argv;
679
680         return new_argv;
681 }
682
683 char **_create_argc_argv(bundle *kb, int *margc, const char *app_path)
684 {
685         char **argv = NULL;
686         char **new_argv = NULL;
687         int argc;
688         int i;
689         char buf[MAX_LOCAL_BUFSZ];
690         const char *str;
691         const char **str_array = NULL;
692         int len = 0;
693         const char *path;
694
695         argc = bundle_export_to_argv(kb, &argv);
696         if (argv) {
697                 argv[0] = strdup(app_path);
698         } else {
699                 _E("bundle_export_to_argv() is failed.");
700                 return NULL;
701         }
702
703         if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
704                 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
705         } else {
706                 str = bundle_get_val(kb, AUL_K_SDK);
707                 if (str) {
708                         str_array = &str;
709                         len = 1;
710                 }
711         }
712
713         for (i = 0; i < len; i++) {
714                 if (str_array[i] == NULL)
715                         break;
716
717                 if (strncmp(str_array[i], SDK_DEBUG,
718                                         strlen(str_array[i])) == 0) {
719                         if (argv[0])
720                                 free(argv[0]);
721                         snprintf(buf, sizeof(buf), "%s.exe", app_path);
722                         /* this code is added  */
723                         /* because core app don't have '.exe' excutable */
724                         /* if '.exe' not exist then use app_path */
725                         if (access(buf, F_OK) != 0)
726                                 argv[0] = strdup(app_path);
727                         else
728                                 argv[0] = strdup(buf);
729
730                         path = bundle_get_val(kb, DLP_K_GDBSERVER_PATH);
731                         if (path == NULL) {
732                                 _E("Failed to get gdbserver path");
733                                 if (argv[0])
734                                         free(argv[0]);
735                                 bundle_free_exported_argv(argc, &argv);
736                                 *margc = 0;
737                                 return NULL;
738                         }
739                         new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG);
740                         new_argv[0] = strdup(path);
741                         argv = new_argv;
742                 } else if (strncmp(str_array[i], SDK_VALGRIND,
743                                         strlen(str_array[i])) == 0) {
744                         path = bundle_get_val(kb, DLP_K_VALGRIND_PATH);
745                         if (path == NULL) {
746                                 _E("Failed to get valgrind path");
747                                 if (argv[0])
748                                         free(argv[0]);
749                                 bundle_free_exported_argv(argc, &argv);
750                                 *margc = 0;
751                                 return NULL;
752                         }
753                         new_argv = __add_arg(kb, argv, &argc,
754                                         DLP_K_VALGRIND_ARG);
755                         new_argv[0] = strdup(path);
756                         argv = new_argv;
757                 } else if (strncmp(str_array[i], SDK_UNIT_TEST,
758                                         strlen(str_array[i])) == 0) {
759                         new_argv = __add_arg(kb, argv, &argc,
760                                         DLP_K_UNIT_TEST_ARG);
761                         argv = new_argv;
762                 } else if (strncmp(str_array[i], SDK_ATTACH,
763                                         strlen(str_array[i])) == 0) {
764                         if (argv[0])
765                                 free(argv[0]);
766                         bundle_free_exported_argv(argc, &argv);
767                         *margc = 0;
768                         path = bundle_get_val(kb, DLP_K_GDBSERVER_PATH);
769                         if (path == NULL) {
770                                 _E("Failed to get gdbserver path");
771                                 return NULL;
772                         }
773                         new_argv = __add_arg(kb, argv, &argc, DLP_K_ATTACH_ARG);
774                         new_argv[0] = strdup(path);
775                         argv = new_argv;
776                 }
777         }
778
779         *margc = argc;
780
781         return argv;
782 }
783
784 static int __delete_dir(const char *path)
785 {
786         DIR *dp;
787         struct dirent dentry;
788         struct dirent *result = NULL;
789         char buf[PATH_MAX];
790         struct stat statbuf;
791         int ret;
792
793         if (path == NULL)
794                 return -1;
795
796         dp = opendir(path);
797         if (dp == NULL)
798                 return -1;
799
800         while (readdir_r(dp, &dentry, &result) == 0 && result) {
801                 if (!strcmp(dentry.d_name, ".") || !strcmp(dentry.d_name, ".."))
802                         continue;
803
804                 snprintf(buf, sizeof(buf), "%s/%s", path, dentry.d_name);
805                 ret = stat(buf, &statbuf);
806                 if (ret == 0) {
807                         if (S_ISDIR(statbuf.st_mode))
808                                 __delete_dir(buf);
809                         else
810                                 unlink(buf);
811                 }
812         }
813
814         rmdir(path);
815         closedir(dp);
816
817         return 0;
818 }
819
820 int _delete_sock_path(int pid, uid_t uid)
821 {
822         char path[PATH_MAX];
823
824         snprintf(path, sizeof(path), "/run/aul/apps/%d/%d", uid, pid);
825         if (access(path, F_OK) == 0)
826                 __delete_dir(path);
827
828         if (access(path, F_OK) == 0)
829                 return -1;
830
831         return 0;
832 }
833
834 int _close_all_fds(void)
835 {
836         DIR *dp;
837         struct dirent dentry;
838         struct dirent *result = NULL;
839         int fd;
840         int max_fd;
841
842         dp = opendir("/proc/self/fd");
843         if (dp == NULL) {
844                 /* fallback */
845                 max_fd = sysconf(_SC_OPEN_MAX);
846                 for (fd = 3; fd < max_fd; fd++)
847                         close(fd);
848
849                 return 0;
850         }
851
852         while (readdir_r(dp, &dentry, &result) == 0 && result) {
853                 if (!isdigit(dentry.d_name[0]))
854                         continue;
855
856                 fd = atoi(dentry.d_name);
857                 if (fd < 3)
858                         continue;
859
860                 if (fd == dirfd(dp))
861                         continue;
862
863                 close(fd);
864         }
865         closedir(dp);
866
867         return 0;
868 }
869