commit e84531958e854d2c7c8e9da2fd7cc7e9205b5ee5
parent 74146c54a7b1ae44c892c407139d1f6916cfca10
Author: sin <sin@2f30.org>
Date: Fri, 16 Aug 2013 14:08:20 +0100
Support -f for ps(1)
Fix missing break in tty.c as well.
Diffstat:
M | proc.h | | | 2 | ++ |
M | ps.c | | | 64 | ++++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
M | util/proc.c | | | 52 | ++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | 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';