From e84531958e854d2c7c8e9da2fd7cc7e9205b5ee5 Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 16 Aug 2013 14:08:20 +0100 Subject: [PATCH] Support -f for ps(1) Fix missing break in tty.c as well. --- proc.h | 2 ++ ps.c | 64 +++++++++++++++++++++++++++++++++++++++++++---------- util/proc.c | 52 +++++++++++++++++++++++++++++++++++++++++++ util/tty.c | 1 + 4 files changed, 107 insertions(+), 12 deletions(-) diff --git a/proc.h b/proc.h index 6785ade..3cc7d29 100644 --- a/proc.h +++ b/proc.h @@ -27,6 +27,8 @@ struct procstat { long rsslim; }; +int parsecmdline(pid_t pid, char *buf, size_t siz); int parsestat(pid_t pid, struct procstat *ps); int proceuid(pid_t pid, uid_t *euid); +int procuid(pid_t pid, uid_t *euid); int validps(const char *path); diff --git a/ps.c b/ps.c index 652fded..23388df 100644 --- a/ps.c +++ b/ps.c @@ -1,10 +1,13 @@ /* See LICENSE file for copyright and license details. */ +#include #include #include #include #include #include #include +#include +#include #include "proc.h" #include "util.h" @@ -15,7 +18,8 @@ static void psr(const char *path); enum { PS_aflag = 1 << 0, PS_Aflag = 1 << 1, - PS_dflag = 1 << 2 + PS_dflag = 1 << 2, + PS_fflag = 1 << 3 }; static int flags; @@ -37,14 +41,17 @@ main(int argc, char *argv[]) flags |= PS_Aflag; break; case 'f': - eprintf("not implemented\n"); + flags |= PS_fflag; + break; default: usage(); } ARGEND; - printf(" PID TTY TIME CMD\n"); + if (!(flags & PS_fflag)) + printf(" PID TTY TIME CMD\n"); + else + printf("UID PID PPID C STIME TTY TIME CMD\n"); recurse("/proc", psr); - return 0; } @@ -57,10 +64,16 @@ usage(void) static void psout(struct procstat *ps) { + char cmdline[BUFSIZ], *cmd; + char stimestr[6]; char *ttystr, *myttystr; int tty_maj, tty_min; - uid_t myeuid, peuid; + uid_t myeuid, peuid, puid; unsigned sut; + struct sysinfo info; + struct tm *tm; + time_t start; + struct passwd *pw; /* Ignore session leaders */ if (flags & PS_dflag) @@ -72,13 +85,15 @@ psout(struct procstat *ps) devtotty(ps->tty_nr, &tty_maj, &tty_min); ttystr = ttytostr(tty_maj, tty_min); /* Only print processes that are associated with - * a terminal */ - if (ttystr[0] == '?' && (flags & PS_aflag)) { - free(ttystr); - return; + * a terminal and they are not session leaders */ + if (flags & PS_aflag) { + if (ps->pid == ps->sid || ttystr[0] == '?') { + free(ttystr); + return; + } } - if (!flags) { + if (!(flags & (PS_aflag | PS_Aflag | PS_dflag))) { myttystr = ttyname(STDIN_FILENO); if (myttystr) { if (strcmp(myttystr + strlen("/dev/"), ttystr)) { @@ -97,8 +112,33 @@ psout(struct procstat *ps) } } - printf("%5d %-6s %02u:%02u:%02u %s\n", ps->pid, ttystr, - sut / 3600, (sut % 3600) / 60, sut % 60, ps->comm); + procuid(ps->pid, &puid); + errno = 0; + pw = getpwuid(puid); + if (errno || !pw) + eprintf("getpwuid %d:", puid); + + sysinfo(&info); + start = time(NULL) - (info.uptime - (ps->starttime / 100)); + tm = localtime(&start); + strftime(stimestr, sizeof(stimestr), + "%H:%M", tm); + if (parsecmdline(ps->pid, cmdline, sizeof(cmdline)) < 0) + cmd = ps->comm; + else + cmd = cmdline; + + if (!(flags & PS_fflag)) + printf("%5d %-6s %02u:%02u:%02u %s\n", ps->pid, ttystr, + sut / 3600, (sut % 3600) / 60, sut % 60, ps->comm); + else { + printf("%-8s %5d %5d ? %5s %-5s %02u:%02u:%02u %s%s%s\n", + pw->pw_name, ps->pid, + ps->ppid, stimestr, ttystr, + sut / 3600, (sut % 3600) / 60, sut % 60, + (cmd == ps->comm) ? "[" : "", cmd, + (cmd == ps->comm) ? "]" : ""); + } free(ttystr); } diff --git a/util/proc.c b/util/proc.c index ac6b991..1700155 100644 --- a/util/proc.c +++ b/util/proc.c @@ -1,4 +1,6 @@ /* See LICENSE file for copyright and license details. */ +#include +#include #include #include #include @@ -32,6 +34,56 @@ proceuid(pid_t pid, uid_t *euid) return -1; } +int +procuid(pid_t pid, uid_t *uid) +{ + FILE *fp; + char buf[BUFSIZ], *p; + char path[PATH_MAX]; + uid_t procuid; + + snprintf(path, sizeof(path), "/proc/%d/status", pid); + if (!(fp = fopen(path, "r"))) + eprintf("%s fopen:", path); + while (fgets(buf, sizeof(buf), fp)) { + if (!strncmp(buf, "Uid:", 4)) { + p = buf + strlen("Uid:"); + sscanf(p, "%u", &procuid); + *uid = procuid; + fclose(fp); + return 0; + } + } + fclose(fp); + return -1; +} + +int +parsecmdline(pid_t pid, char *buf, size_t siz) +{ + int fd; + char path[PATH_MAX]; + ssize_t n, i; + + snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); + fd = open(path, O_RDONLY); + if (fd < 0) + eprintf("open %s:", path); + n = read(fd, buf, siz - 1); + if (n < 0) + eprintf("read %s:", path); + if (!n) { + close(fd); + return -1; + } + buf[n] = '\0'; + for (i = 0; i < n; i++) + if (buf[i] == '\0') + buf[i] = ' '; + close(fd); + return 0; +} + int parsestat(pid_t pid, struct procstat *ps) { diff --git a/util/tty.c b/util/tty.c index 4b5e518..51393ec 100644 --- a/util/tty.c +++ b/util/tty.c @@ -30,6 +30,7 @@ ttytostr(int tty_maj, int tty_min) break; case 4: snprintf(ttystr, len, "%s%d", tty, tty_min); + break; default: ttystr[0] = '?'; ttystr[1] = '\0';