From d1651ddb5d5ec17cd3c813951b92bc44fc75116a Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Fri, 5 Jul 2002 23:12:57 +0000 Subject: [PATCH] Released version 1.10. See ChangeLog for changes. --- ChangeLog | 25 +++++++ Makefile | 12 ++-- ywho.c | 190 +++++++++++++++++++++++++++--------------------------- ywho.lsm | 8 +-- 4 files changed, 130 insertions(+), 105 deletions(-) diff --git a/ChangeLog b/ChangeLog index 50351b5..a62211e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2002-07-06 Martin Mares + + * Released as version 1.10. + + * ywho.c (solve): Rewritten the logic for determining commands + run by users. Session ID's are no longer honored as they change + within a single login session if you use some configurations of + GNU screen or OpenSSH with privilege separation. Now we use one + of maximum depth leaves in the process tree rooted at the login + process mentioned in utmp. Also, cleaned up rest of the solving + function, so it's less hairy. + + * ywho.c: Renamed "usr" fields to "uid" and some other cleanups. + + * ywho.c (readproc): Avoid using uninitialized memory if reading + of process status fails. + + * ywho.c: Sanitized debugging dumps. + +2002-07-05 Martin Mares + + * ywho.c (readproc): Record names of swapped-out processes as well. + + * Split the package to ywho and nwho. + 2001-02-06 Martin Mares * Released as version 1.9. diff --git a/Makefile b/Makefile index 6d7f988..155843a 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CFLAGS=-O2 -Wall -Wno-parentheses LDFLAGS=-s ROOT=/ -REL=ywho-1.9 +REL=ywho-1.10 all: ywho @@ -13,7 +13,6 @@ ywho.o: ywho.c clean: rm -f *.o ywho *~ - rm -rf dist install: strip ywho @@ -21,7 +20,8 @@ install: install -s -m 755 ywho $(ROOT)/usr/bin dist: clean - mkdir dist - cp -a . dist/$(REL) - rm -rf `find dist/$(REL) -name CVS -o -name tmp` dist/$(REL)/dist - cd dist ; tar czvvf /tmp/$(REL).tar.gz $(REL) + mkdir -p ~/tmp + cp -a . ~/tmp/$(REL) + rm -rf `find ~/tmp/$(REL) -name CVS -o -name tmp` + cd ~/tmp ; tar czvvf $(REL).tar.gz $(REL) + rm -rf ~/tmp/$(REL) diff --git a/ywho.c b/ywho.c index f734ba1..5c23a7f 100644 --- a/ywho.c +++ b/ywho.c @@ -1,7 +1,7 @@ /* - * Extended `who' command, version 1.9. + * Extended `who' command, version 1.10. * - * (c) 1996--2001 Martin Mares + * (c) 1996--2002 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU General Public License. See file COPYING in any of the GNU packages. @@ -24,11 +24,18 @@ #undef DEBUG #define MAXHOSTSIZE 24 +#ifdef DEBUG +#define DBG(x,y...) printf(x,##y) +#else +#define DBG(x,y...) do { } while(0) +#endif + struct procrec { struct procrec *next; int pid, ppid, pgrp, sess; - int usr, state; + int uid, state, distance; time_t ctim, tim; + struct utrec *user; char cmd_line[1]; }; @@ -40,7 +47,7 @@ struct utrec { char line[UT_LINESIZE]; time_t login_time, click_time, total_time; char user_name[UT_NAMESIZE+1]; - int usr; + int uid; char host_name[MAXHOSTSIZE+1]; int mesg, detach; struct procrec *proc; @@ -84,6 +91,7 @@ readutmp(void) struct stat st; char device[32]; size_t hlen; + bzero(u, sizeof(*u)); u->next = first_utrec; first_utrec = u; u->login_pid = ut->ut_pid; @@ -101,9 +109,9 @@ readutmp(void) strcpy_padded(u->user_name, ut->ut_user, UT_NAMESIZE); pw = getpwnam(u->user_name); if (pw) - u->usr = pw->pw_uid; + u->uid = pw->pw_uid; else - u->usr = -1; + u->uid = -1; strcpy_padded(u->host_name, ut->ut_host, (MAXHOSTSIZE > UT_HOSTSIZE ? UT_HOSTSIZE : MAXHOSTSIZE)); if ((hlen = strlen(u->host_name)) > maxhost) @@ -141,10 +149,8 @@ readutmp(void) } u->detach = 0; usercnt++; -#ifdef DEBUG - printf("UT %s %s %d %d\n", u->user_name, u->host_name, - u->usr, u->login_pid); -#endif + DBG("UTMP: %s %s %d %d\n", u->user_name, u->host_name, + u->uid, u->login_pid); } endutent(); } @@ -365,7 +371,7 @@ readproc(void) if (!ioctl(1, TIOCGWINSZ, &win) && win.ws_col >= LEFTSIZE + maxhost + 10 && win.ws_col < 1024) cmdcols = win.ws_col; else cmdcols = 80; - cmdcols -= LEFTSIZE + maxhost; + cmdcols -= LEFTSIZE + maxhost; if (d = opendir("/proc")) { while (e = readdir(d)) @@ -377,22 +383,24 @@ readproc(void) struct stat st; char name[256], eman[1024]; int fil; + bzero(p, sizeof(*p)); p->pid = i; strcpy(name, "/proc/"); strcat(name, e->d_name); if (!stat(name, &st)) { - p->next = first_procrec; - first_procrec = p; - p->usr = st.st_uid; + p->uid = st.st_uid; strcpy(eman, name); strcat(eman, "/cmdline"); if ((fil = open(eman, O_RDONLY)) >= 0) { - int z = read(fil, p->cmd_line, cmdcols); + int y, z = read(fil, p->cmd_line, cmdcols); if (z < 0) z = 0; - p->cmd_line[z] = 0x91; + for (y=0; ycmd_line[y]) + p->cmd_line[y] = ' '; + p->cmd_line[z] = 0; close(fil); } strcpy(eman, name); @@ -400,14 +408,19 @@ readproc(void) if ((fil = open(eman, O_RDONLY)) >= 0) { int z = read(fil, eman, 1023); - char *k; + char *j, *k; int trash, utim, stim, cutim, cstim; if (z < 0) z = 0; eman[z] = 0; - k = strchr(eman, ')'); - if (k) + if ((j = strchr(eman, '(')) && (k = strchr(j+1, ')'))) { + *k = 0; + if (!p->cmd_line[0]) + { + strncpy(p->cmd_line, j+1, cmdcols); + p->cmd_line[cmdcols] = 0; + } p->state = k[2]; if (p->state == 'Z') zombies++; @@ -415,6 +428,9 @@ readproc(void) &p->ppid, &p->pgrp, &p->sess, &trash, &trash, &trash, &trash, &trash, &trash, &trash, &utim, &stim, &cutim, &cstim); + DBG("PROC: pid=%d ppid=%d pgrp=%d sess=%d uid=%d\n", p->pid, p->ppid, p->pgrp, p->sess, p->uid); + p->next = first_procrec; + first_procrec = p; } p->tim = utim + stim; p->ctim = cutim + cstim; @@ -435,87 +451,71 @@ readproc(void) static void solve(void) { - struct utrec *u = first_utrec; - struct procrec *m, *n, *o, *q; + struct utrec *u; + struct procrec *m, *n; struct passwd *pw; - while (u) - { - m = first_procrec; - while (m && m->pid != u->login_pid) - m = m->next; - o = m; - if (m) - { - retry: - n = first_procrec; - q = o; - while (n) - { - if (q->sess == n->sess) - n->usr = -1; - if (q->pid == n->ppid && n->usr == -1) - { - o = n; - goto retry; - } - n = n->next; - } - } - u->proc = o; - if (m) - u->total_time = m->ctim; -#ifdef DEBUG - if (o) - { - printf("%s %s\n", u->user_name, o->cmd_line); - } -#endif - u = u->next; - } - for(u=first_utrec; u; u=u->next) + int cnt; + + /* Recognize login session process trees and find leaves of these trees */ + for (u=first_utrec; u; u=u->next) { - for(m=first_procrec; m; m=m->next) - if (u->usr == m->usr) + for (m=first_procrec; m; m=m->next) + if (m->pid == u->login_pid) { - m->usr = -1; - u->detach++; -#ifdef DEBUG - printf("** %s %s\n", u->user_name, m->cmd_line); -#endif + m->user = u; + u->total_time = m->ctim; + u->proc = m; + DBG("** %d is login process for %s@%s\n", m->pid, u->user_name, u->line); } } + do + { + cnt = 0; + for (m=first_procrec; m; m=m->next) + if (!m->user) + for (n=first_procrec; n; n=n->next) + if (n->pid == m->ppid && n->user) + { + u = m->user = n->user; + m->distance = n->distance + 1; + if (!u->proc || u->proc->distance < m->distance) + u->proc = m; + cnt++; + DBG("** %d at distance %d for %s@%s\n", m->pid, m->distance, u->user_name, u->line); + break; + } + } + while (cnt); + + /* Process the remaining processes */ for(m=first_procrec; m; m=m->next) - if (m->usr >= 2 && m->ppid == 1) /* Exclude no_user,root,bin */ - { - for(u=first_utrec; u; u=u->next) - if (u->usr == m->usr) - break; - if (!u) - { - u = xmalloc(sizeof(struct utrec)); - u->next = first_utrec; - first_utrec = u; - u->login_pid = 0; - u->line[0] = 0; - pw = getpwuid(u->usr = m->usr); - if (pw) - strcpy(u->user_name, pw->pw_name); - else - sprintf(u->user_name, "<%d>", m->usr); - u->host_name[0] = 0; - u->mesg = 3; - u->detach = 0; - u->proc = NULL; - u->total_time = 0; - } - if (!u->proc) - u->proc = m; - u->total_time += m->ctim; - u->detach ++; -#ifdef DEBUG - printf("// %s %s\n", u->user_name, m->cmd_line); -#endif - } + { + if (m->user) + continue; + for(u=first_utrec; u; u=u->next) + if (u->uid == m->uid) + break; + if (!u) + { + if (m->uid < 2 || m->ppid != 1) + continue; + u = xmalloc(sizeof(struct utrec)); + bzero(u, sizeof(*u)); + u->next = first_utrec; + first_utrec = u; + pw = getpwuid(u->uid = m->uid); + if (pw) + strcpy(u->user_name, pw->pw_name); + else + sprintf(u->user_name, "<%d>", m->uid); + u->mesg = 3; + } + if (!u->proc) + u->proc = m; + u->total_time += m->ctim; + u->detach++; + DBG("** daemon %s (%s)\n", m->cmd_line, u->user_name); + } } static inline int @@ -595,7 +595,7 @@ show(void) putchar(' '); puttime((unsigned)u->total_time/(unsigned)HZ); putchar(' '); - for (c = u->proc->cmd_line; *c != 0x91; c++) + for (c = u->proc->cmd_line; *c; c++) { if (*c < 0x20 || (*c >= 0x7f && *c < 0xa0)) putchar(' '); diff --git a/ywho.lsm b/ywho.lsm index 9dcccdc..bfb9579 100644 --- a/ywho.lsm +++ b/ywho.lsm @@ -1,15 +1,15 @@ Begin3 Title: ywho -Version: 1.9 -Entered-date: 990328 +Version: 1.10 +Entered-date: 020705 Description: A who-type utility displaying not only who is logged in, but also general system information and commands run by the users. Includes a rwhod replacement with central server, allowing user information to be gathered across routers. -Keywords: who, rwho +Keywords: who Author: Martin Mares Maintained-by: Martin Mares -Primary-site: atrey.karlin.mff.cuni.cz/pub/local/mj/linux/ywho-1.9.tar.gz +Primary-site: atrey.karlin.mff.cuni.cz/pub/local/mj/linux/ywho-1.10.tar.gz Alternate-site: metalab.unc.edu/pub/Linux/system/status Copying-policy: GPL End -- 2.39.2