📄 readproc.c
字号:
proc_t* readproc(PROCTAB* PT, proc_t* rbuf) { static struct direct *ent; /* dirent handle */ static struct stat sb; /* stat buffer */ static char path[32], sbuf[512]; /* bufs for stat,statm */ int allocated = 0, matched = 0; /* flags */ proc_t *p = NULL; /* loop until a proc matching restrictions is found or no more processes */ /* I know this could be a while loop -- this way is easier to indent ;-) */next_proc: /* get next PID for consideration *//*printf("PT->flags is 0x%08x\n", PT->flags);*/#define flags (PT->flags) if (Do(PID)) { if (!*PT->pids) /* set to next item in pids */ return NULL; sprintf(path, "/proc/%d", *(PT->pids)++); matched = 1; } else { /* get next numeric /proc ent */ while ((ent = readdir(PT->procfs)) && (*ent->d_name < '0' || *ent->d_name > '9')) ; if (!ent || !ent->d_name) return NULL; sprintf(path, "/proc/%s", ent->d_name); } if (stat(path, &sb) == -1) /* no such dirent (anymore) */ goto next_proc; if (Do(UID) && !XinLN(uid_t, sb.st_uid, PT->uids, PT->nuid)) goto next_proc; /* not one of the requested uids */ if (!allocated) { /* assign mem for return buf */ p = rbuf ? rbuf : xcalloc(p, sizeof *p); /* passed buf or alloced mem */ allocated = 1; /* remember space is set up */ } p->euid = sb.st_uid; /* need a way to get real uid */ if ((file2str(path, "stat", sbuf, sizeof sbuf)) == -1) goto next_proc; /* error reading /proc/#/stat */ stat2proc(sbuf, p); /* parse /proc/#/stat */ if (!matched && Do(TTY) && !XinL(dev_t, p->tty, PT->ttys)) goto next_proc; /* not one of the requested ttys */ if (!matched && Do(ANYTTY) && p->tty == -1) goto next_proc; /* no controlling terminal */ if (!matched && Do(STAT) && !strchr(PT->stats,p->state)) goto next_proc; /* not one of the requested states */ if (Do(FILLMEM)) { /* read, parse /proc/#/statm */ if ((file2str(path, "statm", sbuf, sizeof sbuf)) != -1 ) statm2proc(sbuf, p); /* ignore statm errors here */ } /* statm fields just zero */ if (Do(FILLSTATUS)) { /* read, parse /proc/#/status */ if ((file2str(path, "status", sbuf, sizeof sbuf)) != -1 ){ status2proc(sbuf, p, 0 /*FIXME*/); } } /* some number->text resolving which is time consuming */ if (Do(FILLUSR)){ strncpy(p->euser, user_from_uid(p->euid), sizeof p->euser); strncpy(p->egroup, group_from_gid(p->egid), sizeof p->egroup); if(Do(FILLSTATUS)) { strncpy(p->ruser, user_from_uid(p->ruid), sizeof p->ruser); strncpy(p->rgroup, group_from_gid(p->rgid), sizeof p->rgroup); strncpy(p->suser, user_from_uid(p->suid), sizeof p->suser); strncpy(p->sgroup, group_from_gid(p->sgid), sizeof p->sgroup); strncpy(p->fuser, user_from_uid(p->fuid), sizeof p->fuser); strncpy(p->fgroup, group_from_gid(p->fgid), sizeof p->fgroup); } } if (Do(FILLCMD)) /* read+parse /proc/#/cmdline */ p->cmdline = file2strvec(path, "cmdline"); if (Do(FILLENV)) /* read+parse /proc/#/environ */ p->environ = file2strvec(path, "environ"); if (p->state == 'Z') /* fixup cmd for zombies */ strncat(p->cmd," <defunct>", sizeof p->cmd); return p;}#undef flags/* ps_readproc: return a pointer to a proc_t filled with requested info about the * next process available matching the restriction set. If no more such * processes are available, return a null pointer (boolean false). Use the * passed buffer instead of allocating space if it is non-NULL. *//* This is optimized so that if a PID list is given, only those files are * searched for in /proc. If other lists are given in addition to the PID list, * the same logic can follow through as for the no-PID list case. This is * fairly complex, but it does try to not to do any unnecessary work. * Unfortunately, the reverse filtering option in which any PID *except* the * ones listed is pursued. */proc_t* ps_readproc(PROCTAB* PT, proc_t* rbuf) { static struct direct *ent; /* dirent handle */ static struct stat sb; /* stat buffer */ static char path[32], sbuf[512]; /* bufs for stat,statm */ int allocated = 0 /* , matched = 0 */ ; /* flags */ proc_t *p = NULL; /* loop until a proc matching restrictions is found or no more processes */ /* I know this could be a while loop -- this way is easier to indent ;-) */next_proc: /* get next PID for consideration *//*printf("PT->flags is 0x%08x\n", PT->flags);*/#define flags (PT->flags) while ((ent = readdir(PT->procfs)) && (*ent->d_name < '0' || *ent->d_name > '9')) ; if (!ent || !ent->d_name) return NULL; sprintf(path, "/proc/%s", ent->d_name); if (stat(path, &sb) == -1) /* no such dirent (anymore) */ goto next_proc; if (!allocated) { /* assign mem for return buf */ p = rbuf ? rbuf : xcalloc(p, sizeof *p); /* passed buf or alloced mem */ allocated = 1; /* remember space is set up */ } p->euid = sb.st_uid; /* need a way to get real uid */ if ((file2str(path, "stat", sbuf, sizeof sbuf)) == -1) goto next_proc; /* error reading /proc/#/stat */ stat2proc(sbuf, p); /* parse /proc/#/stat *//* if (Do(FILLMEM)) {*/ /* read, parse /proc/#/statm */ if ((file2str(path, "statm", sbuf, sizeof sbuf)) != -1 ) statm2proc(sbuf, p); /* ignore statm errors here *//* } */ /* statm fields just zero */ /* if (Do(FILLSTATUS)) { */ /* read, parse /proc/#/status */ if ((file2str(path, "status", sbuf, sizeof sbuf)) != -1 ){ status2proc(sbuf, p, 0 /*FIXME*/); }/* }*/ /* some number->text resolving which is time consuming */ /* if (Do(FILLUSR)){ */ strncpy(p->euser, user_from_uid(p->euid), sizeof p->euser); strncpy(p->egroup, group_from_gid(p->egid), sizeof p->egroup);/* if(Do(FILLSTATUS)) { */ strncpy(p->ruser, user_from_uid(p->ruid), sizeof p->ruser); strncpy(p->rgroup, group_from_gid(p->rgid), sizeof p->rgroup); strncpy(p->suser, user_from_uid(p->suid), sizeof p->suser); strncpy(p->sgroup, group_from_gid(p->sgid), sizeof p->sgroup); strncpy(p->fuser, user_from_uid(p->fuid), sizeof p->fuser); strncpy(p->fgroup, group_from_gid(p->fgid), sizeof p->fgroup);/* }*//* }*//* if (Do(FILLCMD)) */ /* read+parse /proc/#/cmdline */ p->cmdline = file2strvec(path, "cmdline");/* if (Do(FILLENV)) */ /* read+parse /proc/#/environ */ p->environ = file2strvec(path, "environ"); if (p->state == 'Z') /* fixup cmd for zombies */ strncat(p->cmd," <defunct>", sizeof p->cmd); return p;}#undef flagsvoid look_up_our_self(proc_t *p) { static char path[32], sbuf[512]; /* bufs for stat,statm */ sprintf(path, "/proc/%d", getpid()); if (file2str(path, "stat", sbuf, sizeof sbuf) >= 0) stat2proc(sbuf, p); /* parse /proc/#/stat */ if (file2str(path, "statm", sbuf, sizeof sbuf) >= 0) statm2proc(sbuf, p); /* ignore statm errors here */ if (file2str(path, "status", sbuf, sizeof sbuf) >= 0) status2proc(sbuf, p, 0 /*FIXME*/);}/* Convenient wrapper around openproc and readproc to slurp in the whole process * tree subset satisfying the constraints of flags and the optional PID list. * Free allocated memory with freeproctree(). The tree structure is a classic * left-list children + right-list siblings. The algorithm is a two-pass of the * process table. Since most process trees will have children with strictly * increasing PIDs, most of the structure will be picked up in the first pass. * The second loop then cleans up any nodes which turn out to have preceeded * their parent in /proc order. *//* Traverse tree 't' breadth-first looking for a process with pid p */proc_t* LookupPID(proc_t* t, pid_t p) { proc_t* tmp = NULL; if (!t) return NULL; if (t->pid == p) /* look here/terminate recursion */ return t; if ((tmp = LookupPID(t->l, p))) /* recurse over children */ return tmp; for (; t; t=t->r) /* recurse over siblings */ if ((tmp = LookupPID(tmp, p))) return tmp; return NULL;}proc_t* readproctree(int flags, ...) { static proc_t tree; PROCTAB* PT = NULL; proc_t *node, *tmp=NULL, *tmp2=NULL; va_list ap; /* pass through apropriate arguments to openproc */ va_start(ap, flags); if (Do(UID)) { /* temporary variables to ensure that va_arg() instances * are called in the right order */ uid_t* u; int i; u = va_arg(ap, uid_t*); i = va_arg(ap, int); PT = openproc(flags, u, i); } else if (Do(PID) || Do(TTY) || Do(STAT)) PT = openproc(flags, va_arg(ap, void*)); else PT = openproc(flags); va_end(ap); /* first pass: build tree, putting orphans on the first level */ tree.l = tree.r = NULL; while ((node = readproc(PT,0))) if ((tmp = LookupPID(&tree, node->ppid))) { node->r = tmp->l->r; /* node --> left list of parent */ tmp->l->r = node; } else { node->r = tree.r; /* node --> right list of 'tree' */ tree.r = node; } /* second pass: scan tree for PPIDs of level-1 nodes moving links as necessary */ for (node = &tree; node; node = node->r) if ((tmp = LookupPID(&tree, node->r->ppid))) { tmp2 = node->r; /* unlink from right list of 'tree' */ node->r = node->r->r; tmp2->r = tmp->l->r; /* insert as child of found node */ tmp->l->r = node; } closeproc(PT); return &tree;}/* Convenient wrapper around openproc and readproc to slurp in the whole process * table subset satisfying the constraints of flags and the optional PID list. * Free allocated memory with freeproctab(). Access via tab[N]->member. The * pointer list is NULL terminated. */proc_t** readproctab(int flags, ...) { PROCTAB* PT = NULL; proc_t** tab = NULL; int n = 0; va_list ap; va_start(ap, flags); /* pass through args to openproc */ if (Do(UID)) { /* temporary variables to ensure that va_arg() instances * are called in the right order */ uid_t* u; int i; u = va_arg(ap, uid_t*); i = va_arg(ap, int); PT = openproc(flags, u, i); } else if (Do(PID) || Do(TTY) || Do(STAT)) PT = openproc(flags, va_arg(ap, void*)); /* assume ptr sizes same */ else PT = openproc(flags); va_end(ap); do { /* read table: */ tab = xrealloc(tab, (n+1)*sizeof(proc_t*));/* realloc as we go, using */ tab[n] = readproc(PT, NULL); /* final null to terminate */ } while (tab[n++]); /* stop when NULL reached */ closeproc(PT); return tab;}/* deallocate a table of pointers to proc structures */void freeproctab(proc_t** tab) { proc_t** p; for(p = tab; *p; p++) freeproc(*p); free(tab);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -