From f614bdbd720e256613305af860c715cf241cd71c Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Wed, 9 May 2018 12:10:14 +0900 Subject: [PATCH] Better ps --- apps/ps.c | 160 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 117 insertions(+), 43 deletions(-) diff --git a/apps/ps.c b/apps/ps.c index e64c002e..29dcf6a1 100644 --- a/apps/ps.c +++ b/apps/ps.c @@ -25,6 +25,19 @@ #define LINE_LEN 4096 static int show_all = 0; +static int show_threads = 0; +static int show_username = 0; +static int collect_commandline = 0; + +static int widths[5] = {3,3,4,0,0}; + +struct process { + int uid; + int pid; + int tid; + char * process; + char * command_line; +}; void print_username(int uid) { struct passwd * p = getpwuid(uid); @@ -38,10 +51,9 @@ void print_username(int uid) { endpwent(); } -void print_entry(struct dirent * dent) { - char tmp[256], buf[4096]; +struct process * process_entry(struct dirent *dent) { + char tmp[256]; FILE * f; - int read = 1; char line[LINE_LEN]; int pid = 0, uid = 0, tgid = 0; @@ -51,7 +63,7 @@ void print_entry(struct dirent * dent) { f = fopen(tmp, "r"); if (!f) { - return; + return NULL; } line[0] = 0; @@ -77,37 +89,84 @@ void print_entry(struct dirent * dent) { fclose(f); - if ((tgid != pid) && !show_all) { - /* Skip threads */ - return; + if (!show_all) { + /* Filter not ours */ + if (uid != getuid()) return NULL; } - print_username(uid); - if (show_all) { - printf("%5d.%-5d", tgid, pid); + if (!show_threads) { + if (tgid != pid) return NULL; + } + + struct process * out = malloc(sizeof(struct process)); + out->uid = uid; + out->pid = tgid; + out->tid = pid; + out->process = strdup(name); + out->command_line = NULL; + + char garbage[1024]; + int len; + + if ((len = sprintf(garbage, "%d", out->pid)) > widths[0]) widths[0] = len; + if ((len = sprintf(garbage, "%d", out->tid)) > widths[1]) widths[1] = len; + + struct passwd * p = getpwuid(out->uid); + if (p) { + if ((len = strlen(p->pw_name)) > widths[2]) widths[2] = len; } else { - printf(" %5d", pid); + if ((len = sprintf(garbage, "%d", out->uid)) > widths[2]) widths[2] = len; } + endpwent(); - printf(" "); + if (collect_commandline) { + sprintf(tmp, "/proc/%s/cmdline", dent->d_name); + f = fopen(tmp, "r"); + char foo[1024]; + int s = fread(foo, 1, 1024, f); + if (s > 0) { + out->command_line = malloc(s + 1); + memset(out->command_line, 0, s + 1); + memcpy(out->command_line, foo, s); - sprintf(tmp, "/proc/%s/cmdline", dent->d_name); - f = fopen(tmp, "r"); - memset(buf, 0x00, 4096); - read = fread(buf, 1, 4096, f); - fclose(f); + for (int i = 0; i < s; ++i) { + if (out->command_line[i] == 30) { + out->command_line[i] = ' '; + } + } - buf[read] = '\0'; - for (int i = 0; i < read; ++i) { - if (buf[i] == '\036') { - buf[i] = ' '; } + fclose(f); } - if (tgid != pid) { - printf("{%s}\n", buf); + return out; +} + +void print_header(void) { + if (show_username) { + printf("%-*s ", widths[2], "USER"); + } + printf("%*s ", widths[0], "PID"); + printf("%*s ", widths[1], "TID"); + printf("CMD\n"); +} + +void print_entry(struct process * out) { + if (show_username) { + struct passwd * p = getpwuid(out->uid); + if (p) { + printf("%-*s ", widths[2], p->pw_name); + } else { + printf("%-*d ", widths[2], out->uid); + } + endpwent(); + } + printf("%*d ", widths[0], out->pid); + printf("%*d ", widths[1], out->tid); + if (out->command_line) { + printf("%s\n", out->command_line); } else { - printf("%s\n", buf); + printf("%s\n", out->process); } } @@ -117,7 +176,8 @@ void show_usage(int argc, char * argv[]) { "\n" "usage: %s [-A] [format]\n" "\n" - " -A \033[3mshow threads\033[0m\n" + " -A \033[3mshow other users' processes\033[0m\n" + " -T \033[3mshow threads\033[0m\n" " -? \033[3mshow this help text\033[0m\n" "\n", argv[0]); } @@ -125,23 +185,35 @@ void show_usage(int argc, char * argv[]) { int main (int argc, char * argv[]) { /* Parse arguments */ + char c; + while ((c = getopt(argc, argv, "AT?")) != -1) { + switch (c) { + case 'A': + show_all = 1; + break; + case 'T': + show_threads = 1; + break; + case '?': + show_usage(argc, argv); + return 0; + } + } - if (argc > 1) { - for (int i = 1; i < argc; ++i) { - if (argv[i][0] == '-') { - char *c = &argv[i][1]; - while (*c) { - switch (*c) { - case 'A': - show_all = 1; - break; - case '?': - show_usage(argc, argv); - return 0; - } - c++; - } + if (optind < argc) { + char * show = argv[optind]; + while (*show) { + switch (*show) { + case 'u': + show_username = 1; + // fallthrough + case 'a': + collect_commandline = 1; + break; + default: + break; } + show++; } } @@ -154,15 +226,17 @@ int main (int argc, char * argv[]) { struct dirent * ent = readdir(dirp); while (ent != NULL) { if (ent->d_name[0] >= '0' && ent->d_name[0] <= '9') { - struct dirent * entcpy = malloc(sizeof(struct dirent)); - memcpy(entcpy, ent, sizeof(struct dirent)); - list_insert(ents_list, (void *)entcpy); + struct process * p = process_entry(ent); + if (p) { + list_insert(ents_list, (void *)p); + } } ent = readdir(dirp); } closedir(dirp); + print_header(); foreach(entry, ents_list) { print_entry(entry->value); }