util: clarify a bit of the code for parsing commands in wmgenmenu
[wmaker-crm.git] / src / osdep_linux.c
blobbb1ef2e6444fac401b23a374d958675b68f4a333
2 #include <sys/types.h>
3 #include <sys/stat.h>
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <limits.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
12 #include <WINGs/WUtil.h>
14 #include "wconfig.h"
15 #include "osdep.h"
19 * copy argc and argv for an existing process identified by `pid'
20 * into suitable storage given in ***argv and *argc.
22 * subsequent calls use the same static area for argv and argc.
24 * returns 0 for failure, in which case argc := 0 and argv := NULL
25 * returns 1 for success
27 Bool GetCommandForPid(int pid, char ***argv, int *argc)
29 static char buf[_POSIX_ARG_MAX];
30 int fd, i, j;
31 ssize_t count;
33 *argv = NULL;
34 *argc = 0;
36 /* cmdline is a flattened series of null-terminated strings */
37 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
38 while (1) {
39 /* not switching this to stdio yet, as this does not need
40 * to be portable, and i'm lazy */
41 if ((fd = open(buf, O_RDONLY)) != -1)
42 break;
43 if (errno == EINTR)
44 continue;
45 return False;
48 while (1) {
49 if ((count = read(fd, buf, sizeof(buf))) != -1)
50 break;
51 if (errno == EINTR)
52 continue;
53 close(fd);
54 return False;
56 close(fd);
58 /* count args */
59 for (i = 0; i < count; i++)
60 if (buf[i] == '\0')
61 (*argc)++;
63 if (*argc == 0)
64 return False;
66 *argv = (char **)wmalloc(sizeof(char *) * (*argc + 1 /* term. null ptr */));
67 (*argv)[0] = buf;
69 /* go through buf, set argv[$next] to the beginning of each string */
70 for (i = 0, j = 1; i < count; i++) {
71 if (buf[i] != '\0')
72 continue;
73 if (i < count - 1)
74 (*argv)[j++] = &buf[i + 1];
75 if (j == *argc)
76 break;
79 /* the list of arguments must be terminated by a null pointer */
80 (*argv)[j] = NULL;
81 return True;