]> git.itanic.dy.fi Git - scan-pagemap/blob - pidlib.c
d432e9dc907065dd1ecc73198112af2af83e08f7
[scan-pagemap] / pidlib.c
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <libgen.h>
7 #include <errno.h>
8 #include <string.h>
9
10 #include "pidlib.h"
11
12 char *get_name_by_pid(int pid)
13 {
14         static int last_pid;
15         static char cmdline[128];
16         static char *bname;
17
18         if (last_pid == pid)
19                 return bname;
20
21         if (read_cmdline(pid, pid, cmdline, sizeof(cmdline))) {
22                 bname = NULL;
23                 return NULL;
24         }
25
26         bname = basename(cmdline);
27
28         last_pid = pid;
29         return bname;
30 }
31
32 static int parse_pid(DIR **dir)
33 {
34         struct dirent *dirent;
35         int error;
36
37 restart:
38         dirent = readdir(*dir);
39         if (!dirent) {
40                 if (errno == 0) {
41                         closedir(*dir);
42                         *dir = NULL;
43                         return 0;
44                 }
45                 error = errno;
46                 printf("Failed to read /proc directory: %s\n", strerror(error));
47                 return -1;
48         }
49
50         if (dirent->d_name[0] < '0' || dirent->d_name[0] > '9')
51                 goto restart;
52
53         return atoi(dirent->d_name);
54 }
55
56 static int opendir_check(DIR **dir, const char *path)
57 {
58         int error;
59
60         if (!*dir) {
61                 *dir = opendir(path);
62                 if (!dir) {
63                         error = errno;
64                         fprintf(stderr, "Failed to open %s directory: %s\n",
65                                 path, strerror(error));
66                         return -1;
67                 }
68         }
69
70         return 0;
71 }
72
73 int get_next_tid(int pid, DIR **dir)
74 {
75         if (*dir == NULL) {
76                 char path[64];
77
78                 snprintf(path, sizeof(path), "/proc/%d/task/", pid);
79                 if (opendir_check(dir, path))
80                         return -1;
81         }
82
83         return parse_pid(dir);
84 }
85
86 int get_next_pid(DIR **dir)
87 {
88         if (opendir_check(dir, "/proc"))
89                 return -1;
90
91         return parse_pid(dir);
92 }
93
94 int get_next_pid_by_name(DIR **dir, char *name)
95 {
96         int pid;
97         char *pname;
98
99         if (opendir_check(dir, "/proc"))
100                 return -1;
101
102         while (1) {
103                 pid = parse_pid(dir);
104                 if (pid <= 0)
105                         break;
106
107                 pname = get_name_by_pid(pid);
108                 if (pname == NULL)
109                         continue;
110                 if (strcmp(pname, name))
111                         continue;
112
113                 return pid;
114         }
115
116         return 0;
117 }
118
119 int read_cmdline(int pid, int tid, char *cmdline, size_t len)
120 {
121         FILE *file;
122         char path[512];
123         int ret;
124
125         snprintf(path, sizeof(path), "/proc/%d/task/%d/cmdline", pid, tid);
126         file = fopen(path, "rb");
127
128         if (!file)
129                 return -1;
130
131         ret = fread(cmdline, 1, len, file);
132         if (ret > 0)
133                 cmdline[ret - 1] = 0;
134         fclose(file);
135
136         return ret > 0 ? 0 : -1;
137 }
138
139 static int pid_is_ok(int pid)
140 {
141         struct stat statt;
142         char path[64];
143
144         snprintf(path, sizeof(path), "/proc/%d/", pid);
145
146         if (stat(path, &statt))
147                 return 0;
148
149         return pid;
150 }
151
152 /*
153  * Test whether a pid string number exists in the system as a pid
154  * number
155  */
156 int pidstr_is_ok(const char *str)
157 {
158         int i, pid;
159
160         /* Test that it is all digits */
161         for (i = 0; i < strlen(str); i++)
162                 if (str[i] < '0' || str[i] > '9')
163                         return 0;
164
165         pid = atoi(str);
166
167         return pid_is_ok(pid);
168 }