killall, pidof: use argv0 for process matching too

top: show cmdline, not comm field
(fixes problems with re-execed applets showing as processes with name "exe",
and not being found by pidof/killall by applet name)

function                                             old     new   delta
find_pid_by_name                                      98     156     +58
procps_scan                                          692     732     +40
top_main                                            2724    2762     +38
find_pair                                            164     180     +16
collect_int                                          114     123      +9
cmp_main                                             547     555      +8
collect_fork                                         112     119      +7
collect_ctx                                          112     119      +7
read_package_field                                   253     257      +4
passwd_main                                         1983    1985      +2
process_stdin                                        435     433      -2
xstrtoul_range_sfx                                   229     226      -3
get_next_block                                      1852    1849      -3
arith                                               2042    2033      -9
sv_main                                             1236    1226     -10
singlemount                                         4690    4672     -18
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 10/6 up/down: 189/-45)          Total: 144 bytes
   text    data     bss     dec     hex filename
 734789    3028   14400  752217   b7a59 busybox_old
 734933    3028   14400  752361   b7ae9 busybox_unstripped
This commit is contained in:
Denis Vlasenko 2007-06-30 08:03:26 +00:00
parent 42ee26d00c
commit f7d07b1723
4 changed files with 60 additions and 27 deletions

View File

@ -836,6 +836,8 @@ typedef struct {
DIR *dir; DIR *dir;
/* Fields are set to 0/NULL if failed to determine (or not requested) */ /* Fields are set to 0/NULL if failed to determine (or not requested) */
char *cmd; char *cmd;
char *argv0;
/*char *exe;*/
USE_SELINUX(char *context;) USE_SELINUX(char *context;)
/* Everything below must contain no ptrs to malloc'ed data: /* Everything below must contain no ptrs to malloc'ed data:
* it is memset(0) for each process in procps_scan() */ * it is memset(0) for each process in procps_scan() */
@ -861,13 +863,15 @@ enum {
PSSCAN_UIDGID = 1 << 4, PSSCAN_UIDGID = 1 << 4,
PSSCAN_COMM = 1 << 5, PSSCAN_COMM = 1 << 5,
PSSCAN_CMD = 1 << 6, PSSCAN_CMD = 1 << 6,
PSSCAN_STATE = 1 << 7, PSSCAN_ARGV0 = 1 << 7,
PSSCAN_VSZ = 1 << 8, PSSCAN_EXE = 1 << 8, /* not implemented yet */
PSSCAN_RSS = 1 << 9, PSSCAN_STATE = 1 << 9,
PSSCAN_STIME = 1 << 10, PSSCAN_VSZ = 1 << 10,
PSSCAN_UTIME = 1 << 11, PSSCAN_RSS = 1 << 11,
PSSCAN_TTY = 1 << 12, PSSCAN_STIME = 1 << 12,
USE_SELINUX(PSSCAN_CONTEXT = 1 << 13,) PSSCAN_UTIME = 1 << 13,
PSSCAN_TTY = 1 << 14,
USE_SELINUX(PSSCAN_CONTEXT = 1 << 15,)
/* These are all retrieved from proc/NN/stat in one go: */ /* These are all retrieved from proc/NN/stat in one go: */
PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID
| PSSCAN_COMM | PSSCAN_STATE | PSSCAN_COMM | PSSCAN_STATE

View File

@ -38,6 +38,14 @@ execXXX("/proc/self/exe", applet_name, params....)
and therefore comm field contains "exe". and therefore comm field contains "exe".
*/ */
static const char *bb_basename(const char *name)
{
const char *cp = strrchr(name, '/');
if (cp)
return cp + 1;
return name;
}
/* find_pid_by_name() /* find_pid_by_name()
* *
* Modified by Vladimir Oleynik for use with libbb/procps.c * Modified by Vladimir Oleynik for use with libbb/procps.c
@ -55,8 +63,16 @@ pid_t* find_pid_by_name(const char* procName)
procps_status_t* p = NULL; procps_status_t* p = NULL;
pidList = xmalloc(sizeof(*pidList)); pidList = xmalloc(sizeof(*pidList));
while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM))) { while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM|PSSCAN_ARGV0))) {
if (strncmp(p->comm, procName, sizeof(p->comm)-1) == 0) { if (
/* we require comm to match and to not be truncated */
/* in Linux, if comm is 15 chars, it may be a truncated
* name, so we don't allow that to match */
(!p->comm[sizeof(p->comm)-2] && strcmp(p->comm, procName) == 0)
/* or we require argv0 to match (essential for matching reexeced /proc/self/exe)*/
|| (p->argv0 && strcmp(bb_basename(p->argv0), procName) == 0)
/* TOOD: we can also try exe, do we want that? */
) {
pidList = xrealloc(pidList, sizeof(*pidList) * (i+2)); pidList = xrealloc(pidList, sizeof(*pidList) * (i+2));
pidList[i++] = p->pid; pidList[i++] = p->pid;
} }

View File

@ -266,18 +266,24 @@ procps_status_t* procps_scan(procps_status_t* sp, int flags)
} }
if (flags & PSSCAN_CMD) { if (flags & (PSSCAN_CMD|PSSCAN_ARGV0)) {
if (sp->argv0) {
free(sp->argv0);
sp->argv0 = NULL;
}
if (sp->cmd) {
free(sp->cmd); free(sp->cmd);
sp->cmd = NULL; sp->cmd = NULL;
}
strcpy(filename_tail, "/cmdline"); strcpy(filename_tail, "/cmdline");
/* TODO: to get rid of size limits, read into malloc buf,
* then realloc it down to real size. */
n = read_to_buf(filename, buf); n = read_to_buf(filename, buf);
if (n <= 0) if (n <= 0)
break; break;
if (buf[n-1] == '\n') { if (flags & PSSCAN_ARGV0)
if (!--n) sp->argv0 = xstrdup(buf);
break; if (flags & PSSCAN_CMD) {
buf[n] = '\0';
}
do { do {
n--; n--;
if ((unsigned char)(buf[n]) < ' ') if ((unsigned char)(buf[n]) < ' ')
@ -285,6 +291,7 @@ procps_status_t* procps_scan(procps_status_t* sp, int flags)
} while (n); } while (n);
sp->cmd = xstrdup(buf); sp->cmd = xstrdup(buf);
} }
}
break; break;
} }
return sp; return sp;

View File

@ -40,7 +40,8 @@ typedef struct top_status_t {
unsigned pid, ppid; unsigned pid, ppid;
unsigned uid; unsigned uid;
char state[4]; char state[4];
char comm[COMM_LEN]; /* TODO: read /proc/$PID/cmdline only for processes which are displayed */
char cmd[64];
} top_status_t; } top_status_t;
typedef struct jiffy_counts_t{ typedef struct jiffy_counts_t{
@ -444,7 +445,7 @@ static void display_status(int count, int scr_width)
#endif #endif
); );
if (col > 0) if (col > 0)
printf("%.*s", col, s->comm); printf("%.*s", col, s->cmd);
/* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu,
jif.busy - prev_jif.busy, jif.total - prev_jif.total); */ jif.busy - prev_jif.busy, jif.total - prev_jif.total); */
s++; s++;
@ -559,6 +560,7 @@ int top_main(int argc, char **argv)
| PSSCAN_UTIME | PSSCAN_UTIME
| PSSCAN_STATE | PSSCAN_STATE
| PSSCAN_COMM | PSSCAN_COMM
| PSSCAN_CMD
| PSSCAN_SID | PSSCAN_SID
| PSSCAN_UIDGID | PSSCAN_UIDGID
))) { ))) {
@ -572,7 +574,10 @@ int top_main(int argc, char **argv)
#endif #endif
top[n].uid = p->uid; top[n].uid = p->uid;
strcpy(top[n].state, p->state); strcpy(top[n].state, p->state);
strcpy(top[n].comm, p->comm); if (p->cmd)
safe_strncpy(top[n].cmd, p->cmd, sizeof(top[n].cmd));
else /* mimic ps */
sprintf(top[n].cmd, "[%s]", p->comm);
} }
if (ntop == 0) { if (ntop == 0) {
bb_error_msg_and_die("no process info in /proc"); bb_error_msg_and_die("no process info in /proc");
@ -585,6 +590,7 @@ int top_main(int argc, char **argv)
continue; continue;
} }
do_stats(); do_stats();
/* TODO: we don't need to sort all 10000 processes, we need to find top 24! */
qsort(top, ntop, sizeof(top_status_t), (void*)mult_lvl_cmp); qsort(top, ntop, sizeof(top_status_t), (void*)mult_lvl_cmp);
#else #else
qsort(top, ntop, sizeof(top_status_t), (void*)sort_function); qsort(top, ntop, sizeof(top_status_t), (void*)sort_function);