8cd0461821be27c874aff50da97bd6187247c19f
[platform/core/connectivity/stc-manager.git] / src / helper / helper-procfs.c
1 /*
2  * Copyright (c) 2017 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 /**
19  * @file procfs.c
20  * @desc wrapper for reading profs information.
21  *
22  * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
23  *
24  */
25
26 #include <ctype.h>
27 #include <stdio.h>
28 #include <stdbool.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <dirent.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36
37 #include "stc-error.h"
38 #include "stc-manager-util.h"
39 #include "helper-procfs.h"
40
41 #define USRAPPS "/usr/apps/"
42
43 API int proc_get_cmdline(pid_t pid, char *cmdline)
44 {
45         char buf[PROC_BUF_MAX];
46         char cmdline_buf[PROC_NAME_MAX];
47         char *filename;
48         FILE *fp;
49         char *token = NULL;
50         char *saveptr = NULL;
51
52         snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
53         fp = fopen(buf, "r");
54         if (fp == NULL)
55                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
56
57         if (fgets(cmdline_buf, PROC_NAME_MAX-1, fp) == NULL) {
58                 fclose(fp); //LCOV_EXCL_LINE
59                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
60         }
61         fclose(fp);
62
63         if (g_strstr_len(cmdline_buf, strlen(USRAPPS), USRAPPS) != NULL) {
64                 /* Application */
65                 filename = cmdline_buf + strlen(USRAPPS);
66                 token = strtok_r(filename, "/", &saveptr);
67                 if (token != NULL)
68                         filename = token;
69         } else {
70                 token = strtok_r(cmdline_buf, " ", &saveptr);
71                 if (token != NULL)
72                         filename = strrchr(token, '/');
73                 else
74                         filename = strrchr(cmdline_buf, '/');
75
76                 if (filename == NULL)
77                         filename = cmdline_buf;
78                 else
79                         filename = filename + 1;
80         }
81
82         strncpy(cmdline, filename, PROC_NAME_MAX-1);
83
84         return STC_ERROR_NONE;
85 }
86
87 //LCOV_EXCL_START
88 pid_t find_pid_from_cmdline(char *cmdline)
89 {
90         pid_t pid = -1, foundpid = -1;
91         int ret = 0;
92         DIR *dp;
93         struct dirent *dentry;
94         char appname[PROC_NAME_MAX];
95
96         dp = opendir("/proc");
97         if (!dp) {
98                 STC_LOGE("BACKGRD MANAGE : fail to open /proc");
99                 return STC_ERROR_FAIL;
100         }
101
102         while ((dentry = readdir(dp)) != NULL) {
103                 if (!isdigit(dentry->d_name[0]))
104                         continue;
105
106                 pid = atoi(dentry->d_name);
107                 if (!pid)
108                         continue;
109                 ret = proc_get_cmdline(pid, appname);
110                 if (ret == STC_ERROR_NONE) {
111                         if (!strncmp(cmdline, appname, strlen(appname)+1)) {
112                                 foundpid = pid;
113                                 break;
114                         }
115                 }
116         }
117         closedir(dp);
118         return foundpid;
119 }
120
121 API void proc_foreach_pid(proc_pid_cb cb, void *user_data)
122 {
123         pid_t pid = -1;
124         int ret = 0;
125         DIR *dp;
126         struct dirent *dentry;
127
128         dp = opendir("/proc");
129         if (!dp) {
130                 STC_LOGE("failed to open /proc");
131                 return;
132         }
133
134         while ((dentry = readdir(dp)) != NULL) {
135                 if (!isdigit(dentry->d_name[0]))
136                         continue;
137
138                 pid = atoi(dentry->d_name);
139                 if (!pid)
140                         continue;
141
142                 ret = cb(pid, user_data);
143                 if (ret == false)
144                         break;
145         }
146
147         closedir(dp);
148 }
149
150 int proc_get_label(pid_t pid, char *label)
151 {
152         char buf[PROC_BUF_MAX];
153         FILE *fp;
154
155         snprintf(buf, sizeof(buf), "/proc/%d/attr/current", pid);
156         fp = fopen(buf, "r");
157         if (fp == NULL)
158                 return STC_ERROR_FAIL;
159
160         if (fgets(label, PROC_NAME_MAX-1, fp) == NULL) {
161                 fclose(fp);
162                 return STC_ERROR_FAIL;
163         }
164         fclose(fp);
165         return STC_ERROR_NONE;
166 }
167
168 int proc_get_exepath(pid_t pid, char *buf, int len)
169 {
170         char path[PROC_BUF_MAX];
171         int ret = 0;
172
173         snprintf(path, sizeof(path), "/proc/%d/exe", pid);
174         ret = readlink(path, buf, len-1);
175         if (ret > 0)
176                 buf[ret] = '\0';
177         else
178                 buf[0] = '\0';
179         return STC_ERROR_NONE;
180 }
181
182 static int proc_get_data(char *path, char *buf, int len)
183 {
184         _cleanup_close_ int fd = -1;
185         int ret;
186
187         fd = open(path, O_RDONLY);
188         if (fd < 0)
189                 return STC_ERROR_FAIL;
190
191         ret = read(fd, buf, len-1);
192         if (ret < 0) {
193                 buf[0] = '\0';
194                 return STC_ERROR_FAIL;
195         }
196         buf[ret] = '\0';
197         return STC_ERROR_NONE;
198 }
199
200 int proc_get_raw_cmdline(pid_t pid, char *buf, int len)
201 {
202         char path[PROC_BUF_MAX];
203         snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
204         return proc_get_data(path, buf, len);
205 }
206 //LCOV_EXCL_STOP
207
208 API int proc_get_status(pid_t pid, char status[][PROC_BUF_MAX])
209 {
210         unsigned int i;
211         unsigned int index = 0;
212         char path[PROC_BUF_MAX];
213         char status_buf[PROC_BUF_MAX];
214         bool updated[PROC_STATUS_CNT] = {FALSE, };
215         FILE *fp;
216
217         snprintf(path, sizeof(path), "/proc/%d/status", pid);
218         fp = fopen(path, "r");
219         if (fp == NULL)
220                 return STC_ERROR_FAIL;
221
222         for (i = 0; i < PROC_STATUS_CNT; ++i) {
223                 char *token = NULL;
224                 char *saveptr = NULL;
225
226                 if (fgets(status_buf, sizeof(status_buf), fp) == NULL) {
227                         fclose(fp); //LCOV_EXCL_LINE
228                         return STC_ERROR_FAIL; //LCOV_EXCL_LINE
229                 }
230
231                 if (!updated[PROC_STATUS_NAME] && strstr(status_buf,
232                                                          PROC_STATUS_NAME_STR))
233                         index = PROC_STATUS_NAME;
234                 else if (!updated[PROC_STATUS_STATE] && strstr(status_buf,
235                                                                PROC_STATUS_STATE_STR))
236                         index = PROC_STATUS_STATE;
237                 else if (!updated[PROC_STATUS_TGID] && strstr(status_buf,
238                                                               PROC_STATUS_TGID_STR))
239                         index = PROC_STATUS_TGID;
240                 else if (!updated[PROC_STATUS_NGID] && strstr(status_buf,
241                                                               PROC_STATUS_NGID_STR))
242                         index = PROC_STATUS_NGID;
243                 else if (!updated[PROC_STATUS_PID] && strstr(status_buf,
244                                                              PROC_STATUS_PID_STR))
245                         index = PROC_STATUS_PID;
246                 else if (!updated[PROC_STATUS_PPID] && strstr(status_buf,
247                                                               PROC_STATUS_PPID_STR))
248                         index = PROC_STATUS_PPID;
249                 else if (!updated[PROC_STATUS_TRACERPID] && strstr(status_buf,
250                                                                    PROC_STATUS_TRACERPID_STR))
251                         index = PROC_STATUS_TRACERPID;
252                 else
253                         continue;
254
255                 token = strtok_r(status_buf, ":", &saveptr);
256                 if (token != NULL) {
257                         token = strtok_r(NULL, "\n", &saveptr);
258                         if (token != NULL) {
259                                 while (isspace((unsigned char)*token))
260                                         token++;
261                                 strncpy(status[index], token,
262                                         sizeof(status[index]));
263                                 updated[index] = TRUE;
264                         }
265                 }
266         }
267         fclose(fp);
268
269         return STC_ERROR_NONE;
270 }