ubase

suckless linux base utils
git clone git://git.2f30.org/ubase.git
Log | Files | Refs | README | LICENSE

commit e84531958e854d2c7c8e9da2fd7cc7e9205b5ee5
parent 74146c54a7b1ae44c892c407139d1f6916cfca10
Author: sin <sin@2f30.org>
Date:   Fri Aug 16 14:08:20 +0100

Support -f for ps(1)

Fix missing break in tty.c as well.

Diffstat:
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 @@ -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 @@ -1,10 +1,13 @@ /* See LICENSE file for copyright and license details. */ +#include <sys/sysinfo.h> #include <errno.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> +#include <time.h> +#include <pwd.h> #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 @@ -1,4 +1,6 @@ /* See LICENSE file for copyright and license details. */ +#include <sys/stat.h> +#include <fcntl.h> #include <unistd.h> #include <errno.h> #include <stdio.h> @@ -33,6 +35,56 @@ proceuid(pid_t pid, uid_t *euid) } 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) { char path[PATH_MAX]; diff --git 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';