#include #include #include #include #include #include #include #include #include #include "wconfig.h" #define RETRY( x ) do { \ x; \ } while (errno == EINTR); /* * copy argc and argv for an existing process identified by `pid' * into suitable storage given in ***argv and *argc. * * subsequent calls use the same static area for argv and argc. * * returns 0 for failure, in which case argc := 0 and argv := NULL * returns 1 for success */ Bool GetCommandForPid(int pid, char ***argv, int *argc) { static char buf[_POSIX_ARG_MAX]; int fd, i, j; ssize_t count; *argv = NULL; *argc = 0; /* cmdline is a flattened series of null-terminated strings */ snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); while (1) { /* not switching this to stdio yet, as this does not need * to be portable, and i'm lazy */ if ((fd = open(buf, O_RDONLY)) != -1) break; if (errno == EINTR) continue; return False; } while (1) { if ((count = read(fd, buf, sizeof(buf))) != -1) break; if (errno == EINTR) continue; RETRY( close(fd) ) return False; } RETRY( close(fd) ) /* count args */ for (i = 0; i < count; i++) if (buf[i] == '\0') (*argc)++; if (*argc == 0) return False; *argv = (char **)wmalloc(sizeof(char *) * (*argc + 1 /* term. null ptr */)); (*argv)[0] = buf; /* go through buf, set argv[$next] to the beginning of each string */ for (i = 0, j = 1; i < count; i++) { if (buf[i] != '\0') continue; if (i < count - 1) (*argv)[j++] = &buf[i + 1]; if (j == *argc) break; } /* the list of arguments must be terminated by a null pointer */ (*argv)[j] = NULL; return True; }