]> mj.ucw.cz Git - ywho.git/commitdiff
Initial revision
authorMartin Mares <mj@ucw.cz>
Fri, 26 Sep 1997 20:25:30 +0000 (20:25 +0000)
committerMartin Mares <mj@ucw.cz>
Fri, 26 Sep 1997 20:25:30 +0000 (20:25 +0000)
Makefile [new file with mode: 0644]
ywho.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..3d997d0
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+# Makefile for YWHO
+
+ywho: ywho.c
+       gcc -s -N -O2 -m486 -fomit-frame-pointer -Wall -Wno-parentheses ywho.c -o ywho
+
+clean:
+       rm *.o ywho
+
+install:
+       strip ywho
+       mv ywho /usr/local/bin
diff --git a/ywho.c b/ywho.c
new file mode 100644 (file)
index 0000000..568ed64
--- /dev/null
+++ b/ywho.c
@@ -0,0 +1,580 @@
+/*
+ *             Extended `who' command, version 1.3.
+ *
+ *             (c) 1996 Martin Mares <mj@k332.feld.cvut.cz>
+ *
+ *             1.3 (16-96-96) - idle derived from atime instead of mtime.
+ *                                                     - displaying of current command fixed.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <utmp.h>
+#include <time.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <sys/stat.h>
+#include <asm/param.h>
+
+#undef DEBUG
+
+struct procrec {
+       struct procrec *next;
+       int pid, ppid, pgrp, sess;
+       int usr, state;
+       time_t ctim, tim;
+       char cmd_line[34];
+       };
+
+static struct procrec *first_procrec;
+
+struct utrec {
+       struct utrec *next;
+       pid_t login_pid;
+       char line_id[4];
+       time_t login_time, click_time, total_time;
+       char user_name[UT_NAMESIZE+1];
+       int usr;
+       char host_name[17];
+       char line_name[12];
+       int mesg, detach;
+       struct procrec *proc;
+       };
+
+static struct utrec *first_utrec;
+static int usercnt, zombies;
+static time_t now;
+
+static void *
+xmalloc(int i)
+{
+void *z;
+       z = malloc(i);
+       if (!z)
+               {
+               fprintf(stderr, "xwho: out of memory!\n");
+               exit(1);
+               }
+       return z;
+}
+
+static void
+strcpy_padded(char *to, char *from, int size)
+{
+       memcpy(to, from, size);
+       to[size] = 0;
+}
+
+static void
+readutmp(void)
+{
+static struct utmp *ut;
+static struct passwd *pw;
+       utmpname(UTMP_FILE);
+       while (ut = getutent())
+               if (ut->ut_type == USER_PROCESS && ut->ut_user[0])
+                       {
+                       struct utrec *u = xmalloc(sizeof(struct utrec));
+                       struct stat st;
+                       char device[32];
+                               u->next = first_utrec;
+                               first_utrec = u;
+                               u->login_pid = ut->ut_pid;
+                               u->line_id[0] = ut->ut_id[0];
+                               u->line_id[1] = ut->ut_id[1];
+                               u->line_id[2] = 0;
+                               u->login_time = ut->ut_time;
+                               strcpy_padded(u->user_name, ut->ut_user, UT_NAMESIZE);
+                               pw = getpwnam(u->user_name);
+                               if (pw)
+                                       u->usr = pw->pw_uid;
+                               else
+                                       u->usr = -1;
+                               strcpy_padded(u->host_name, ut->ut_host, 16);
+                               strcpy(u->line_name, ut->ut_line);
+                               if (!u->line_id[0])
+                                       {
+                                       char *z = u->line_name;
+                                       if (!strncmp(u->line_name, "tty", 3))
+                                               z += 3;
+                                       strncpy(u->line_id, z, 3);
+                                       u->line_id[3] = 0;
+                                       }
+                               strcpy(device, "/dev/");
+                               strcat(device, u->line_name);
+                               if (stat(device, &st))
+                                       u->mesg = 2;
+                               else
+                                       {
+                                       u->mesg = !!(S_IWOTH & st.st_mode);
+                                       u->click_time = st.st_atime;
+                                       if (u->click_time < st.st_atime)
+                                               u->click_time = st.st_atime;
+                                       if (u->click_time < st.st_ctime)
+                                               u->click_time = st.st_ctime;
+                                       }
+                               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
+                       }
+       endutent();
+}
+
+static void
+puttime(int s)
+{
+int d, h, m;
+       if (s < 100)
+               printf("%4ds", s);
+       else
+               {
+               m = s/60;
+               s %= 60;
+               h = m/60;
+               m %= 60;
+               if (h < 100)
+                       printf("%02d.%02d", h, m);
+               else
+                       {
+                       d = h/24;
+                       h %= 24;
+                       if (d < 100)
+                               printf("%2dd%02d", d, h);
+                       else
+                               printf("%4dd", d);
+                       }
+               }
+}
+
+static void
+memory(unsigned int i)
+{
+       if (i < 1000)
+               printf("%dB", i);
+       else
+               {
+               i = (i+511)/1024;
+               if (i < 1000)
+                       printf("%dK", i);
+               else
+                       {
+                       i = (i+511)/1024;
+                       if (i < 1000)
+                               printf("%dM", i);
+                       else
+                               printf("%dG", (i+511U)/1024U);
+                       }
+               }
+}
+
+static void
+dispsys(void)
+{
+FILE *f;
+char line[256], a[32], b[32], c[32];
+char *z, *w;
+       w = NULL;
+       if (f = fopen("/proc/version", "r"))
+               {
+               fgets(line, 256, f);
+               z = strchr(line, '(');
+               if (z)
+                       {
+                       while (z != line && z[-1] == ' ')
+                               z--;
+                       }
+               else
+                       z = line + strlen(line) - 1;
+               *z = 0;
+               z = strstr(line, " version");
+               if (z)
+                       memmove(z, z+8, strlen(z+8)+1);
+               printf(line);
+               fclose(f);
+               }
+       if (f = fopen("/proc/cpuinfo", "r"))
+               {
+               strcpy(a, "???");
+               b[0] = 0;
+               c[0] = 0;
+               for(;;)
+                       {
+                       fgets(line, 256, f);
+                       if (feof(f))
+                               break;
+                       if (!strncmp(line, "cpu\t\t: ", 7))
+                               {
+                               z = line+7;
+                               w = a;
+                               }
+                       else if (!strncmp(line, "model\t\t: ", 9))
+                               {
+                               z = line+9;
+                               w = b;
+                               }
+                       else if (!strncmp(line, "mask\t\t: ", 8))
+                               {
+                               z = line+8;
+                               w = c;
+                               }
+                       else
+                               z = NULL;
+                       if (z)
+                               {
+                               line[strlen(line)-1] = 0;
+                               strcpy(w, z);
+                               if (!strcmp(w, "Unknown"))
+                                       w[0] = 0;
+                               }
+                       }
+               printf(" on %s", a);
+               if (*b)
+                       printf("-%s", b);
+               if (*c)
+                       printf("-%s", c);
+               fclose(f);
+               }
+       if (f = fopen("/proc/uptime", "r"))
+               {
+               int p,q,p1,q1;
+               fgets(line, 256, f);
+               sscanf(line, "%d.%d%d.%d", &p, &p1, &q, &q1);
+               printf(", up ");
+               puttime(p);
+               printf(", run ");
+               puttime(p-q);
+               fclose(f);
+               }
+       {
+       struct tm *tm;
+               now = time(NULL);
+               tm = localtime(&now);
+               printf(" at %02d-%02d-%02d/%d %02d.%02d:%02d\n", tm->tm_mday, tm->tm_mon+1,
+                       tm->tm_year, (tm->tm_wday+6)%7, tm->tm_hour, tm->tm_min, tm->tm_sec);
+       }
+       if (f = fopen("/proc/loadavg", "r"))
+               {
+               int i = 3;
+               fgets(line, 256, f);
+               *strchr(line, '\n') = 0;
+               z = line-1;
+               while (i-- && z)
+                       {
+                       *z = '/';
+                       z = strchr(z, ' ');
+                       }
+               if (z)
+                       {
+                       char *k;
+                       *z++ = 0;
+                       k = strchr(z, ' ');
+                       if (k)
+                         *k = 0;
+                       printf("R/T=%s, ", z);
+                       }
+               else
+                       z = line;
+               printf("LAV=%s", line);
+               fclose(f);
+               }
+       if (f = fopen("/proc/meminfo", "r"))
+               {
+               int total, used, free, shared, buffers, totals, useds, frees;
+               fgets(line, 256, f);
+               fgets(line, 256, f);
+               sscanf(line, "Mem:%d%d%d%d%d", &total, &used, &free, &shared, &buffers);
+               fgets(line, 256, f);
+               sscanf(line, "Swap:%d%d%d", &totals, &useds, &frees);
+               printf(", free ");
+               memory(free+buffers);
+               printf(" of RAM");
+               if (useds)
+                       {
+                       printf(", used ");
+                       memory(useds);
+                       printf(" of swap");
+                       }
+               }
+       printf(", %d user%s.\n", usercnt, usercnt == 1 ? "" : "s");
+}
+
+static void
+readproc(void)
+{
+DIR *d;
+struct dirent *e;
+       if (d = opendir("/proc"))
+               {
+               while (e = readdir(d))
+                       {
+                       int i;
+                               sscanf(e->d_name, "%d", &i);
+                               if (i)
+                                       {
+                                       struct procrec *p = xmalloc(sizeof(struct procrec));
+                                       struct stat st;
+                                       char name[256], eman[1024];
+                                       int fil;
+                                               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;
+                                                       strcpy(eman, name);
+                                                       strcat(eman, "/cmdline");
+                                                       if ((fil = open(eman, O_RDONLY)) >= 0)
+                                                               {
+                                                               int z = read(fil, p->cmd_line, 33);
+                                                               if (z < 0)
+                                                                       z = 0;
+                                                               p->cmd_line[z] = 0xff;
+                                                               close(fil);
+                                                               }
+                                                       strcpy(eman, name);
+                                                       strcat(eman, "/stat");
+                                                       if ((fil = open(eman, O_RDONLY)) >= 0)
+                                                               {
+                                                               int z = read(fil, eman, 1023);
+                                                               char *k;
+                                                               int trash, utim, stim, cutim, cstim;
+                                                                       if (z < 0)
+                                                                               z = 0;
+                                                                       eman[z] = 0;
+                                                                       k = strchr(eman, ')');
+                                                                       if (k)
+                                                                               {
+                                                                               p->state = k[1];
+                                                                               if (p->state == 'Z')
+                                                                                       zombies++;
+                                                                               sscanf(k+3, "%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
+                                                                                       &p->ppid, &p->pgrp, &p->sess, &trash, &trash,
+                                                                                       &trash, &trash, &trash, &trash, &trash, &utim,
+                                                                                       &stim, &cutim, &cstim);
+                                                                               }
+                                                                       p->tim = utim + stim;
+                                                                       p->ctim = cutim + cstim;
+                                                                       close(fil);
+                                                               }
+                                                       }
+                                       }
+                       }
+               closedir(d);
+               }
+       else
+               {
+               perror("unable to scan /proc");
+               exit(1);
+               }
+}
+
+static void
+solve(void)
+{
+struct utrec *u = first_utrec;
+struct procrec *m, *n, *o, *q;
+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)
+               {
+               for(m=first_procrec; m; m=m->next)
+                       if (u->usr == m->usr)
+                               {
+                               m->usr = -1;
+                               u->detach++;
+#ifdef DEBUG
+                               printf("** %s %s\n", u->user_name, m->cmd_line);
+#endif
+                               }
+               }
+       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_id[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->line_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
+                       }
+}
+
+static inline int
+comp(struct utrec *a, struct utrec *b)
+{
+int k;
+       if (b->mesg == 3)
+               return -1;
+       k = strcmp(a->user_name, b->user_name);
+       if (k)
+               return k;
+       if (!a->host_name[0] && b->host_name[0])
+               return -1;
+       return strcmp(a->line_id, b->line_id);
+}
+
+static void
+sort(void)
+{
+struct utrec *fi = NULL;
+struct utrec *z, **y, **m, **l;
+       l = &fi;
+       while (first_utrec)
+               {
+               y = &first_utrec;
+               m = y;
+               while (z = *y)
+                       {
+                       if (comp(z, *m) < 0)
+                               m = y;
+                       y = &z->next;
+                       }
+               z = *m;
+               *m = z->next;
+               *l = z;
+               z->next = NULL;
+               l = &z->next;
+               }
+       first_utrec = fi;
+}
+
+static void
+show(void)
+{
+struct utrec *u;
+int i;
+unsigned char *c;
+       printf("Name     Li  MD From              LogT  IdleT RunT  Command\n");
+       for(u=first_utrec; u; u=u->next)
+               {
+               if (!u->line_id[1])
+                       {
+                       if (u->line_id[0])
+                               {
+                               u->line_id[1] = u->line_id[0];
+                               u->line_id[0] = 'c';
+                               }
+                       else    
+                               u->line_id[0] = u->line_id[1] = '-';
+                       }
+               printf("%-8.8s %-3s %c%c %-17.17s ",
+                       u->user_name,
+                       u->line_id,
+                       u->mesg ? ' ' : '-',
+                       u->detach ? 'D' : ' ',
+                       u->host_name);
+               if (u->mesg <= 1)
+                       {
+                       if (u->login_time > now)
+                               u->login_time = now;
+                       puttime(now - u->login_time);
+                       putchar(' ');
+                       if (u->click_time > now)
+                               u->click_time = now;
+                       if (now - u->click_time >= 60)
+                               puttime(now - u->click_time);
+                       else
+                               printf("     ");
+                       }
+               else
+                       printf("?????      ");
+               if (u->proc)
+                       {
+                       putchar(' ');
+                       puttime((unsigned)u->total_time/(unsigned)HZ);
+                       putchar(' ');
+                       i = 24;
+                       c = u->proc->cmd_line;
+                       while (*c != 0xff && i--)
+                               {
+                               putchar(*c ? *c : ' ');
+                               c++;
+                               }
+                       }
+               else
+                       printf(" <nothing>");
+               putchar('\n');
+               }
+}
+
+int main(void)
+{
+       readutmp();
+       dispsys();
+       readproc();
+       solve();
+       sort();
+       show();
+       if (zombies)
+               {
+               printf("There %s %d zombie%s walking around.",
+                       zombies == 1 ? "is" : "are",
+                       zombies,
+                       zombies == 1 ? "" : "s" );
+               }
+       return 0;
+}