From 7ac9a0e1f5606696dc799b773d5ec70183ca91a3 Mon Sep 17 00:00:00 2001 From: albert <> Date: Tue, 3 Dec 2002 09:07:59 +0000 Subject: [PATCH] present for Jim --- pgrep.c | 2 +- proc/devname.c | 7 +-- proc/readproc.c | 113 +++++++++++++++++++++++++++++++++++------------- proc/readproc.h | 4 ++ ps/parser.c | 6 +-- ps/ps.1 | 2 + ps/select.c | 2 +- skill.c | 2 +- 8 files changed, 100 insertions(+), 38 deletions(-) diff --git a/pgrep.c b/pgrep.c index cb4573c3..098bf387 100644 --- a/pgrep.c +++ b/pgrep.c @@ -386,7 +386,7 @@ select_procs (void) else if (opt_sid && ! match_numlist (task.session, opt_sid)) match = 0; else if (opt_term) { - if (task.tty == -1) { + if (task.tty == 0) { match = 0; } else { char tty[256]; diff --git a/proc/devname.c b/proc/devname.c index 541d78b5..95b387b8 100644 --- a/proc/devname.c +++ b/proc/devname.c @@ -195,7 +195,7 @@ unsigned dev_to_tty(char *restrict ret, unsigned chop, int dev, int pid, unsigne char *restrict tmp = buf; unsigned i = 0; int c; - if((short)dev == (short)-1) goto fail; + if((short)dev == (short)0) goto no_tty; if(linux_version_code > LINUX_VERSION(2, 5, 0)){ /* didn't get done yet */ if(link_name(tmp, major(dev), minor(dev), pid, "tty" )) goto abbrev; } @@ -203,7 +203,8 @@ unsigned dev_to_tty(char *restrict ret, unsigned chop, int dev, int pid, unsigne if( link_name(tmp, major(dev), minor(dev), pid, "fd/2" )) goto abbrev; if( guess_name(tmp, major(dev), minor(dev) )) goto abbrev; if( link_name(tmp, major(dev), minor(dev), pid, "fd/255")) goto abbrev; -fail: + // fall through if unable to find a device file +no_tty: strcpy(ret, "?"); return 1; abbrev: @@ -232,7 +233,7 @@ abbrev: int tty_to_dev(const char *restrict const name) { struct stat sbuf; static char buf[32]; - if(stat(name, &sbuf) >= 0) return sbuf.st_rdev; + if(name[0]=='/' && stat(name, &sbuf) >= 0) return sbuf.st_rdev; snprintf(buf,32,"/dev/%s",name); if(stat(buf, &sbuf) >= 0) return sbuf.st_rdev; snprintf(buf,32,"/dev/tty%s",name); diff --git a/proc/readproc.c b/proc/readproc.c index ad08ed8d..4347b7ff 100644 --- a/proc/readproc.c +++ b/proc/readproc.c @@ -14,6 +14,7 @@ #include "procps.h" #include #include +#include #include #include #include @@ -74,19 +75,35 @@ void freeproc(proc_t* p) { -static void status2proc(const char *S, proc_t *restrict P, int fill){ +static void status2proc(const char *S, proc_t *restrict P){ char* tmp; - if (fill == 1) { - memset(P->cmd, 0, sizeof P->cmd); - sscanf (S, "Name:\t%15c", P->cmd); - tmp = strchr(P->cmd,'\n'); - *tmp='\0'; - tmp = strstr (S,"State"); - sscanf (tmp, "State:\t%c", &P->state); + int i; + + // The cmd is escaped, with \\ and \n for backslash and newline. + // It certainly may contain "VmSize:" and similar crap. + if(unlikely(strncmp("Name:\t",S,6))) fprintf(stderr, "Internal error!\n"); + S += 6; + i = 0; + while(i < sizeof P->cmd - 1){ + int c = *S++; + if(unlikely(c=='\n')) break; + if(unlikely(c=='\0')) return; // should never happen + if(unlikely(c=='\\')){ + c = *S++; + if(c=='\n') break; // should never happen + if(!c) break; // should never happen + if(c=='n') c='\n'; // else we assume it is '\\' + } + P->cmd[i++] = c; } + P->cmd[i] = '\0'; + + tmp = strstr (S,"State:\t"); + if(likely((long)tmp)) P->state = tmp[7]; + else fprintf(stderr, "Internal error!\n"); tmp = strstr (S,"Pid:"); - if(tmp) sscanf (tmp, + if(likely((long)tmp)) sscanf (tmp, "Pid:\t%d\n" "PPid:\t%d\n", &P->pid, @@ -95,21 +112,21 @@ static void status2proc(const char *S, proc_t *restrict P, int fill){ else fprintf(stderr, "Internal error!\n"); tmp = strstr (S,"Uid:"); - if(tmp) sscanf (tmp, + if(likely((long)tmp)) sscanf (tmp, "Uid:\t%d\t%d\t%d\t%d", &P->ruid, &P->euid, &P->suid, &P->fuid ); else fprintf(stderr, "Internal error!\n"); tmp = strstr (S,"Gid:"); - if(tmp) sscanf (tmp, + if(likely((long)tmp)) sscanf (tmp, "Gid:\t%d\t%d\t%d\t%d", &P->rgid, &P->egid, &P->sgid, &P->fgid ); else fprintf(stderr, "Internal error!\n"); tmp = strstr (S,"VmSize:"); - if(tmp) sscanf (tmp, + if(likely((long)tmp)) sscanf (tmp, "VmSize: %lu kB\n" "VmLck: %lu kB\n" "VmRSS: %lu kB\n" @@ -132,7 +149,7 @@ static void status2proc(const char *S, proc_t *restrict P, int fill){ } tmp = strstr (S,"SigPnd:"); - if(tmp) sscanf (tmp, + if(likely((long)tmp)) sscanf (tmp, #ifdef SIGNAL_STRING "SigPnd: %s SigBlk: %s SigIgn: %s %*s %s", P->signal, P->blocked, P->sigignore, P->sigcatch @@ -153,17 +170,25 @@ static void status2proc(const char *S, proc_t *restrict P, int fill){ */ static void stat2proc(const char* S, proc_t *restrict P) { int num; - char* tmp = strrchr(S, ')'); /* split into "PID (cmd" and "" */ - *tmp = '\0'; /* replace trailing ')' with NUL */ + char* tmp; + /* fill in default values for older kernels */ P->exit_signal = SIGCHLD; P->processor = 0; P->rtprio = -1; P->sched = -1; - /* parse these two strings separately, skipping the leading "(". */ - memset(P->cmd, 0, sizeof P->cmd); /* clear even though *P xcalloc'd ?! */ - sscanf(S, "%d (%15c", &P->pid, P->cmd); /* comm[16] in kernel */ - num = sscanf(tmp + 2, /* skip space after ')' too */ + + P->pid = strtol(S, &tmp, 10); + S = tmp + 2; + tmp = strrchr(S, ')'); // split into "PID (cmd" and "" + num = tmp - S; + if(unlikely(num > sizeof P->cmd)) num = sizeof P->cmd; // 1 too big + num--; // ditch the ')' character + memcpy(P->cmd, S, num); + P->cmd[num] = '\0'; + S = tmp + 2; // skip ") " + + num = sscanf(S, "%c " "%d %d %d %d %d " "%lu %lu %lu %lu %lu " @@ -193,10 +218,6 @@ static void stat2proc(const char* S, proc_t *restrict P) { /* -- Linux 2.2.8 to 2.5.17 end here -- */ &P->rtprio, &P->sched /* both added to 2.5.18 */ ); - - /* fprintf(stderr, "stat2proc converted %d fields.\n",num); */ - if (P->tty == 0) - P->tty = -1; /* the old notty val, update elsewhere bef. moving to 0 */ } static void statm2proc(const char* s, proc_t *restrict P) { @@ -212,8 +233,10 @@ static int file2str(const char *directory, const char *what, char *ret, int cap) int fd, num_read; sprintf(filename, "%s/%s", directory, what); - if ( (fd = open(filename, O_RDONLY, 0)) == -1 ) return -1; - if ( (num_read = read(fd, ret, cap - 1)) <= 0 ) num_read = -1; + fd = open(filename, O_RDONLY, 0); + if(unlikely(fd==-1)) return -1; + num_read = read(fd, ret, cap - 1); + if(unlikely(num_read<=0)) num_read = -1; else ret[num_read] = 0; close(fd); return num_read; @@ -226,7 +249,8 @@ static char** file2strvec(const char* directory, const char* what) { int align; sprintf(buf, "%s/%s", directory, what); - if ( (fd = open(buf, O_RDONLY, 0) ) == -1 ) return NULL; + fd = open(buf, O_RDONLY, 0); + if(fd==-1) return NULL; /* read whole file into a memory buffer, allocating as we go */ while ((n = read(fd, buf, sizeof buf - 1)) > 0) { @@ -272,6 +296,37 @@ static char** file2strvec(const char* directory, const char* what) { return ret; } +// warning: interface may change +int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){ + char name[32]; + int fd; + int n = 0; + snprintf(name, sizeof name, "/proc/%u/cmdline", pid); + fd = open(name, O_RDONLY); + if(fd==-1) return NULL; + dst[0] = '\0'; + for(;;){ + ssize_t r = read(fd,dst+n,sz-n); + if(r==-1){ + if(errno==EINTR) continue; + break; + } + n += r; + if(n==sz) break; // filled the buffer + if(r==0) break; // EOF + } + if(n){ + int i; + if(n==sz) n--; + dst[n] = '\0'; + i=n; + while(i--){ + int c = dst[i]; + if(c<' ' || c>'~') dst[i]=' '; + } + } + return n; +} /* These are some nice GNU C expression subscope "inline" functions. * The can be used with arbitrary types and evaluate their arguments @@ -361,7 +416,7 @@ next_proc: /* get next PID for consideration */ if (flags & PROC_FILLSTATUS) { /* read, parse /proc/#/status */ if ((file2str(path, "status", sbuf, sizeof sbuf)) != -1 ){ - status2proc(sbuf, p, 0 /*FIXME*/); + status2proc(sbuf, p); } } @@ -459,7 +514,7 @@ next_proc: /* get next PID for consideration */ /* if (flags & PROC_FILLSTATUS) { */ /* read, parse /proc/#/status */ if ((file2str(path, "status", sbuf, sizeof sbuf)) != -1 ){ - status2proc(sbuf, p, 0 /*FIXME*/); + status2proc(sbuf, p); } /* }*/ @@ -509,7 +564,7 @@ void look_up_our_self(proc_t *p) { file2str(path, "statm", sbuf, sizeof sbuf); statm2proc(sbuf, p); /* ignore statm errors here */ file2str(path, "status", sbuf, sizeof sbuf); - status2proc(sbuf, p, 0 /*FIXME*/); + status2proc(sbuf, p); } diff --git a/proc/readproc.h b/proc/readproc.h index f43a9422..9c6a0743 100644 --- a/proc/readproc.h +++ b/proc/readproc.h @@ -9,6 +9,7 @@ * in the file COPYING */ +#include "procps.h" #define SIGNAL_STRING @@ -174,6 +175,9 @@ extern void closeproc(PROCTAB* PT); extern proc_t* readproc(PROCTAB* PT, proc_t* return_buf); extern proc_t* ps_readproc(PROCTAB* PT, proc_t* return_buf); +// warning: interface may change +extern int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid); + extern void look_up_our_self(proc_t *p); /* deallocate space allocated by readproc diff --git a/ps/parser.c b/ps/parser.c index 64560186..b00f769f 100644 --- a/ps/parser.c +++ b/ps/parser.c @@ -144,15 +144,15 @@ static const char *parse_tty(char *str, sel_union *ret){ lookup("/dev/pty%s"); lookup("/dev/%snsole"); /* "co" means "console", maybe do all VCs too? */ if(!strcmp(str,"-")){ /* "-" means no tty (from AIX) */ - ret->tty = -1; /* processes w/o tty */ + ret->tty = 0; /* processes w/o tty */ return 0; } if(!strcmp(str,"?")){ /* "?" means no tty, which bash eats (Reno BSD?) */ - ret->tty = -1; /* processes w/o tty */ + ret->tty = 0; /* processes w/o tty */ return 0; } if(!*(str+1) && (stat(str,&sbuf)>=0)){ /* Kludge! Assume bash ate '?'. */ - ret->tty = -1; /* processes w/o tty */ + ret->tty = 0; /* processes w/o tty */ return 0; } #undef lookup diff --git a/ps/ps.1 b/ps/ps.1 index 488c8a40..c139a028 100644 --- a/ps/ps.1 +++ b/ps/ps.1 @@ -239,6 +239,8 @@ D uninterruptible sleep (usually IO) R runnable (on run queue) S sleeping T traced or stopped +W paging +X dead Z a defunct ("zombie") process For BSD formats and when the "stat" keyword is used, additional diff --git a/ps/select.c b/ps/select.c index e6bf8c7f..57ab59c9 100644 --- a/ps/select.c +++ b/ps/select.c @@ -19,7 +19,7 @@ #define session_leader(p) ((p)->session == (p)->pid) #define process_group_leader(p) ((p)->pgid == (p)->pid) -#define without_a_tty(p) ((unsigned short)((p)->tty) == (unsigned short)-1) +#define without_a_tty(p) ((unsigned short)((p)->tty) == (unsigned short)0) #define some_other_user(p) ((p)->euid != cached_euid) #define running(p) (((p)->state=='R')||((p)->state=='D')) #define has_our_euid(p) ((unsigned short)((p)->euid) == (unsigned short)cached_euid) diff --git a/skill.c b/skill.c index 18ebbd1b..6d6ed278 100644 --- a/skill.c +++ b/skill.c @@ -468,7 +468,7 @@ selection_collection: case '-': case '?': num_found++; - ENLIST(tty,-1); + ENLIST(tty,0); if(!NEXTARG) break; } } -- 2.40.0