Better ps

This commit is contained in:
K. Lange 2018-05-09 12:10:14 +09:00
parent da909e4f79
commit f614bdbd72
1 changed files with 117 additions and 43 deletions

146
apps/ps.c
View File

@ -25,6 +25,19 @@
#define LINE_LEN 4096 #define LINE_LEN 4096
static int show_all = 0; 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) { void print_username(int uid) {
struct passwd * p = getpwuid(uid); struct passwd * p = getpwuid(uid);
@ -38,10 +51,9 @@ void print_username(int uid) {
endpwent(); endpwent();
} }
void print_entry(struct dirent * dent) { struct process * process_entry(struct dirent *dent) {
char tmp[256], buf[4096]; char tmp[256];
FILE * f; FILE * f;
int read = 1;
char line[LINE_LEN]; char line[LINE_LEN];
int pid = 0, uid = 0, tgid = 0; int pid = 0, uid = 0, tgid = 0;
@ -51,7 +63,7 @@ void print_entry(struct dirent * dent) {
f = fopen(tmp, "r"); f = fopen(tmp, "r");
if (!f) { if (!f) {
return; return NULL;
} }
line[0] = 0; line[0] = 0;
@ -77,37 +89,84 @@ void print_entry(struct dirent * dent) {
fclose(f); fclose(f);
if ((tgid != pid) && !show_all) { if (!show_all) {
/* Skip threads */ /* Filter not ours */
return; if (uid != getuid()) return NULL;
} }
print_username(uid); if (!show_threads) {
if (show_all) { if (tgid != pid) return NULL;
printf("%5d.%-5d", tgid, pid); }
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 { } 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); sprintf(tmp, "/proc/%s/cmdline", dent->d_name);
f = fopen(tmp, "r"); f = fopen(tmp, "r");
memset(buf, 0x00, 4096); char foo[1024];
read = fread(buf, 1, 4096, f); 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);
for (int i = 0; i < s; ++i) {
if (out->command_line[i] == 30) {
out->command_line[i] = ' ';
}
}
}
fclose(f); fclose(f);
buf[read] = '\0';
for (int i = 0; i < read; ++i) {
if (buf[i] == '\036') {
buf[i] = ' ';
}
} }
if (tgid != pid) { return out;
printf("{%s}\n", buf); }
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 { } else {
printf("%s\n", buf); 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", out->process);
} }
} }
@ -117,7 +176,8 @@ void show_usage(int argc, char * argv[]) {
"\n" "\n"
"usage: %s [-A] [format]\n" "usage: %s [-A] [format]\n"
"\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" " -? \033[3mshow this help text\033[0m\n"
"\n", argv[0]); "\n", argv[0]);
} }
@ -125,23 +185,35 @@ void show_usage(int argc, char * argv[]) {
int main (int argc, char * argv[]) { int main (int argc, char * argv[]) {
/* Parse arguments */ /* Parse arguments */
char c;
if (argc > 1) { while ((c = getopt(argc, argv, "AT?")) != -1) {
for (int i = 1; i < argc; ++i) { switch (c) {
if (argv[i][0] == '-') {
char *c = &argv[i][1];
while (*c) {
switch (*c) {
case 'A': case 'A':
show_all = 1; show_all = 1;
break; break;
case 'T':
show_threads = 1;
break;
case '?': case '?':
show_usage(argc, argv); show_usage(argc, argv);
return 0; 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); struct dirent * ent = readdir(dirp);
while (ent != NULL) { while (ent != NULL) {
if (ent->d_name[0] >= '0' && ent->d_name[0] <= '9') { if (ent->d_name[0] >= '0' && ent->d_name[0] <= '9') {
struct dirent * entcpy = malloc(sizeof(struct dirent)); struct process * p = process_entry(ent);
memcpy(entcpy, ent, sizeof(struct dirent)); if (p) {
list_insert(ents_list, (void *)entcpy); list_insert(ents_list, (void *)p);
}
} }
ent = readdir(dirp); ent = readdir(dirp);
} }
closedir(dirp); closedir(dirp);
print_header();
foreach(entry, ents_list) { foreach(entry, ents_list) {
print_entry(entry->value); print_entry(entry->value);
} }