]> git.itanic.dy.fi Git - scan-pagemap/blob - pidlib.c
Show full process argument list instead only executable name
[scan-pagemap] / pidlib.c
1 /*
2  * Copyright (C) 2010 Timo Kokkonen <timo.t.kokkonen@iki.fi>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16  */
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <libgen.h>
24 #include <errno.h>
25 #include <string.h>
26
27 #include "pidlib.h"
28
29 char *get_name_by_pid(int pid)
30 {
31         static int last_pid;
32         static char cmdline[128];
33         static char *bname;
34
35         if (last_pid == pid)
36                 return bname;
37
38         if (read_cmdline(pid, pid, cmdline, sizeof(cmdline))) {
39                 bname = NULL;
40                 return NULL;
41         }
42
43         bname = basename(cmdline);
44
45         last_pid = pid;
46         return bname;
47 }
48
49 static int parse_pid(DIR **dir)
50 {
51         struct dirent *dirent;
52         int error;
53
54 restart:
55         dirent = readdir(*dir);
56         if (!dirent) {
57                 if (errno == 0) {
58                         closedir(*dir);
59                         *dir = NULL;
60                         return 0;
61                 }
62                 error = errno;
63                 printf("Failed to read /proc directory: %s\n", strerror(error));
64                 return -1;
65         }
66
67         if (dirent->d_name[0] < '0' || dirent->d_name[0] > '9')
68                 goto restart;
69
70         return atoi(dirent->d_name);
71 }
72
73 static int opendir_check(DIR **dir, const char *path)
74 {
75         int error;
76
77         if (!*dir) {
78                 *dir = opendir(path);
79                 if (!dir) {
80                         error = errno;
81                         fprintf(stderr, "Failed to open %s directory: %s\n",
82                                 path, strerror(error));
83                         return -1;
84                 }
85         }
86
87         return 0;
88 }
89
90 int get_next_tid(int pid, DIR **dir)
91 {
92         if (*dir == NULL) {
93                 char path[64];
94
95                 snprintf(path, sizeof(path), "/proc/%d/task/", pid);
96                 if (opendir_check(dir, path))
97                         return -1;
98         }
99
100         return parse_pid(dir);
101 }
102
103 int get_next_pid(DIR **dir)
104 {
105         if (opendir_check(dir, "/proc"))
106                 return -1;
107
108         return parse_pid(dir);
109 }
110
111 int get_next_pid_by_name(DIR **dir, char *name)
112 {
113         int pid;
114         char *pname;
115
116         if (opendir_check(dir, "/proc"))
117                 return -1;
118
119         while (1) {
120                 pid = parse_pid(dir);
121                 if (pid <= 0)
122                         break;
123
124                 pname = get_name_by_pid(pid);
125                 if (pname == NULL)
126                         continue;
127                 if (strcmp(pname, name))
128                         continue;
129
130                 return pid;
131         }
132
133         return 0;
134 }
135
136 int read_cmdline(int pid, int tid, char *cmdline, size_t len)
137 {
138         FILE *file;
139         char path[512];
140         int ret;
141
142         snprintf(path, sizeof(path), "/proc/%d/task/%d/cmdline", pid, tid);
143         file = fopen(path, "rb");
144
145         if (!file)
146                 return -1;
147
148         ret = fread(cmdline, 1, len, file);
149         if (ret > 0)
150                 cmdline[ret - 1] = 0;
151         fclose(file);
152
153         return ret > 0 ? 0 : -1;
154 }
155
156 static int pid_is_ok(int pid)
157 {
158         struct stat statt;
159         char path[64];
160
161         snprintf(path, sizeof(path), "/proc/%d/", pid);
162
163         if (stat(path, &statt))
164                 return 0;
165
166         return pid;
167 }
168
169 /*
170  * Test whether a pid string number exists in the system as a pid
171  * number
172  */
173 int pidstr_is_ok(const char *str)
174 {
175         int i, pid;
176
177         /* Test that it is all digits */
178         for (i = 0; i < strlen(str); i++)
179                 if (str[i] < '0' || str[i] > '9')
180                         return 0;
181
182         pid = atoi(str);
183
184         return pid_is_ok(pid);
185 }