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