c4cf4d80bb082f657ac184feeb93da6d3bddfd0d
[platform/framework/web/wrt.git] / src / wrt-launchpad-daemon / src / simple_util.c
1 /*
2  * Copyright (c) 2011 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
18 #include <string.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <dirent.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include "simple_util.h"
26
27 #define BINSH_NAME      "/bin/sh"
28 #define BINSH_SIZE      7
29
30 #define PROC_STAT_GID_POS       5
31
32
33 static inline int __read_proc(const char *path, char *buf, int size);
34 static inline int __find_pid_by_cmdline(const char *dname,
35                                       const char *cmdline, void *priv);
36 static inline int __get_pgid_from_stat(int pid);
37
38
39 static inline int __read_proc(const char *path, char *buf, int size)
40 {
41         int fd;
42         int ret;
43
44         if (buf == NULL || path == NULL)
45                 return -1;
46
47         fd = open(path, O_RDONLY);
48         if (fd < 0)
49                 return -1;
50
51         ret = read(fd, buf, size - 1);
52         if (ret <= 0) {
53                 close(fd);
54                 return -1;
55         } else
56                 buf[ret] = 0;
57
58         close(fd);
59
60         return ret;
61 }
62
63 static inline int __find_pid_by_cmdline(const char *dname,
64                                       const char *cmdline, void *priv)
65 {
66         char *apppath;
67         int pid = 0;
68
69         apppath = (char *)priv;
70         if (strncmp(cmdline, apppath, MAX_LOCAL_BUFSZ-1) == 0) {
71                 pid = atoi(dname);
72                 if (pid != getpgid(pid))
73                         pid = 0;
74         }
75
76         return pid;
77 }
78
79 int __proc_iter_cmdline(
80         int (*iterfunc)(const char *dname, const char *cmdline, void *priv),
81                     void *priv)
82 {
83         DIR *dp;
84         struct dirent *dentry;
85         int pid;
86         int ret;
87         char buf[MAX_LOCAL_BUFSZ];
88
89         dp = opendir("/proc");
90         if (dp == NULL) {
91                 return -1;
92         }
93
94         if (iterfunc == NULL)
95                 iterfunc = __find_pid_by_cmdline;
96
97         while ((dentry = readdir(dp)) != NULL) {
98                 if (!isdigit(dentry->d_name[0]))
99                         continue;
100
101                 snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry->d_name);
102                 ret = __read_proc(buf, buf, sizeof(buf));
103                 if (ret <= 0)
104                         continue;
105
106                 /* support app launched by shell script*/
107                 if (strncmp(buf, BINSH_NAME, BINSH_SIZE) == 0)
108                         pid =
109                             iterfunc(dentry->d_name, &buf[BINSH_SIZE + 1],
110                                      priv);
111                 else
112                         pid = iterfunc(dentry->d_name, buf, priv);
113
114                 if (pid > 0) {
115                         closedir(dp);
116                         return pid;
117                 }
118         }
119
120         closedir(dp);
121         return -1;
122 }
123
124 char *__proc_get_cmdline_bypid(int pid)
125 {
126         char buf[MAX_LOCAL_BUFSZ];
127         int ret;
128
129         snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
130         ret = __read_proc(buf, buf, sizeof(buf));
131         if (ret <= 0)
132                 return NULL;
133
134         /* support app launched by shell script*/
135         if (strncmp(buf, BINSH_NAME, BINSH_SIZE) == 0)
136                 return strdup(&buf[BINSH_SIZE + 1]);
137         else
138                 return strdup(buf);
139 }
140
141 static inline int __get_pgid_from_stat(int pid)
142 {
143         char buf[MAX_LOCAL_BUFSZ];
144         char *str;
145         int ret;
146         int i;
147         int count = 0;
148
149         if (pid <= 1)
150                 return -1;
151
152         snprintf(buf, sizeof(buf), "/proc/%d/stat", pid);
153         ret = __read_proc(buf, buf, sizeof(buf));
154         if (ret < 0)
155                 return -1;
156
157         for (i = 0; i < (ret - 1); i++) {
158                 if (buf[i] == ' ') {
159                         count++;
160                         if (count == PROC_STAT_GID_POS - 1)
161                                 str = &(buf[i + 1]);
162                         else if (count == PROC_STAT_GID_POS) {
163                                 buf[i] = 0;
164                                 break;
165                         }
166                 }
167         }
168
169         if (count == PROC_STAT_GID_POS)
170                 pid = atoi(str);
171         else
172                 pid = -1;
173
174         return pid;
175 }
176
177 int __proc_iter_pgid(int pgid, int (*iterfunc) (int pid, void *priv),
178                      void *priv)
179 {
180         DIR *dp;
181         struct dirent *dentry;
182         int _pgid;
183         int ret = -1;
184
185         dp = opendir("/proc");
186         if (dp == NULL) {
187                 return -1;
188         }
189
190         while ((dentry = readdir(dp)) != NULL) {
191                 if (!isdigit(dentry->d_name[0]))
192                         continue;
193
194                 _pgid = __get_pgid_from_stat(atoi(dentry->d_name));
195                 if (pgid == _pgid) {
196                         ret = iterfunc(atoi(dentry->d_name), priv);
197                         if (ret >= 0)
198                                 break;
199                 }
200         }
201
202         closedir(dp);
203         return ret;
204 }
205