pstree.c
C Source File · 165 lines
#include <stdio.h>#include <stdlib.h>#include <dirent.h>#include <ctype.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <getopt.h>
static int read_comm(pid_t pid, char *buf, size_t n) { char path[64]; snprintf(path, sizeof(path), "/proc/%d/comm", pid); FILE *f = fopen(path, "r"); if (!f) return -1; if (!fgets(buf, (int)n, f)) { fclose(f); return -1; } buf[strcspn(buf, "\n")] = 0; fclose(f); return 0;}
static int get_ppid_from_stat(pid_t pid, pid_t *ppid_out) { char path[64], line[4096]; snprintf(path, sizeof(path), "/proc/%d/stat", pid); FILE *f = fopen(path, "r"); if (!f) return -1; if (!fgets(line, sizeof(line), f)) { fclose(f); return -1; } fclose(f);
int id, ppid; char comm[256], state; if (sscanf(line, "%d (%255[^)]) %c %d", &id, comm, &state, &ppid) != 4) return -1; *ppid_out = (pid_t)ppid; return 0;}
void Version() { printf("------my_pstree------\n"); printf("Version 1.0 generated by Katyusha & Codex\n");}
#define MAXN 300005struct process { pid_t pid, ppid; char *s;};typedef struct process process;process p[MAXN];
int head[MAXN], ecnt;struct edge { int to, nxt;};typedef struct edge edge;edge E[MAXN];
void add(int u, int v) { E[++ecnt].to = v; E[ecnt].nxt = head[u]; head[u] = ecnt;}
int print_pid = 0, version = 0, print_sort = 0;
int cmp(process *x, process *y) { if (print_sort) { return (*x).pid < (*y).pid; } else { int c = strcmp((*x).s, (*y).s); if (c < 0) return 1; if (c > 0) return 0; return (*x).pid < (*y).pid; }}
void swap(int *x, int *y) { int t = *x; *x = *y; *y = t;}
void dfs(int u, int gap) { for (int i = 1; i <= gap; i++) putchar(' '); char buf[256], _buf[256]; if (u != 0) { snprintf(_buf, sizeof(_buf), "(%d)", u); snprintf(buf, sizeof(buf), "%s%s", p[u].s, (print_pid)? _buf : ""); printf("%s\n", buf); } int _gap = (u != 0) ? (gap + 3 + strlen(buf)) : 0; int cid[1024], cnt = 0;
for (int i = head[u]; i ; i = E[i].nxt) { int v = E[i].to; cid[cnt++] = v; } while (1){ int flag = 0; for (int i = 1; i < cnt; i++) { if (cmp(&p[cid[i]], &p[cid[i - 1]])) { swap(&cid[i - 1], &cid[i]); flag = 1; } } if (!flag) break; } for (int i = 0; i < cnt; i++) { dfs(cid[i], _gap); }}
int main(int argc, char *argv[]) {
int opt;
static struct option option_long[] = { {"show-pids", no_argument, 0, 'p'}, {"numeric-sort", no_argument, 0, 'n'}, {"version", no_argument, 0, 'V'}, {0, 0, 0, 0} };
while ((opt = getopt_long(argc, argv, "pnV", option_long, NULL)) != -1) { switch (opt) { case 'p': print_pid = 1; break; case 'V': version = 1; break; case 'n': print_sort = 1; break; default: return 1; } }
if (version) { Version(); return 0; }
DIR *d = opendir("/proc"); if (!d) { perror("opendir /proc"); return 1; } struct dirent *de; while ((de = readdir(d)) != NULL) { if (!isdigit((unsigned char)de->d_name[0])) continue; pid_t pid = (pid_t)atoi(de->d_name); p[pid].s = (char *)malloc(256 * sizeof(char)); p[pid].pid = pid; int ret1 = read_comm(pid, p[pid].s, 256); int ret2 = get_ppid_from_stat(pid, &p[pid].ppid); if (ret1 == -1 || ret2 == -1) continue; add(p[pid].ppid, pid); }
dfs(0, 0); for (int i = 0; i < MAXN; i++) free(p[i].s); closedir(d);}





