2 * Extended `who' command, version 1.3.
4 * (c) 1996 Martin Mares <mj@k332.feld.cvut.cz>
6 * 1.3 (16-96-96) - idle derived from atime instead of mtime.
7 * - displaying of current command fixed.
20 #include <asm/param.h>
26 int pid, ppid, pgrp, sess;
32 static struct procrec *first_procrec;
38 time_t login_time, click_time, total_time;
39 char user_name[UT_NAMESIZE+1];
47 static struct utrec *first_utrec;
48 static int usercnt, zombies;
58 fprintf(stderr, "xwho: out of memory!\n");
65 strcpy_padded(char *to, char *from, int size)
67 memcpy(to, from, size);
74 static struct utmp *ut;
75 static struct passwd *pw;
77 while (ut = getutent())
78 if (ut->ut_type == USER_PROCESS && ut->ut_user[0])
80 struct utrec *u = xmalloc(sizeof(struct utrec));
83 u->next = first_utrec;
85 u->login_pid = ut->ut_pid;
86 u->line_id[0] = ut->ut_id[0];
87 u->line_id[1] = ut->ut_id[1];
89 u->login_time = ut->ut_time;
90 strcpy_padded(u->user_name, ut->ut_user, UT_NAMESIZE);
91 pw = getpwnam(u->user_name);
96 strcpy_padded(u->host_name, ut->ut_host, 16);
97 strcpy(u->line_name, ut->ut_line);
100 char *z = u->line_name;
101 if (!strncmp(u->line_name, "tty", 3))
103 strncpy(u->line_id, z, 3);
106 strcpy(device, "/dev/");
107 strcat(device, u->line_name);
108 if (stat(device, &st))
112 u->mesg = !!(S_IWOTH & st.st_mode);
113 u->click_time = st.st_atime;
114 if (u->click_time < st.st_atime)
115 u->click_time = st.st_atime;
116 if (u->click_time < st.st_ctime)
117 u->click_time = st.st_ctime;
122 printf("UT %s %s %d %d\n", u->user_name, u->host_name,
123 u->usr, u->login_pid);
142 printf("%02d.%02d", h, m);
148 printf("%2dd%02d", d, h);
156 memory(unsigned int i)
171 printf("%dG", (i+511U)/1024U);
180 char line[256], a[32], b[32], c[32];
183 if (f = fopen("/proc/version", "r"))
186 z = strchr(line, '(');
189 while (z != line && z[-1] == ' ')
193 z = line + strlen(line) - 1;
195 z = strstr(line, " version");
197 memmove(z, z+8, strlen(z+8)+1);
201 if (f = fopen("/proc/cpuinfo", "r"))
211 if (!strncmp(line, "cpu\t\t: ", 7))
216 else if (!strncmp(line, "model\t\t: ", 9))
221 else if (!strncmp(line, "mask\t\t: ", 8))
230 line[strlen(line)-1] = 0;
232 if (!strcmp(w, "Unknown"))
243 if (f = fopen("/proc/uptime", "r"))
247 sscanf(line, "%d.%d%d.%d", &p, &p1, &q, &q1);
257 tm = localtime(&now);
258 printf(" at %02d-%02d-%02d/%d %02d.%02d:%02d\n", tm->tm_mday, tm->tm_mon+1,
259 tm->tm_year, (tm->tm_wday+6)%7, tm->tm_hour, tm->tm_min, tm->tm_sec);
261 if (f = fopen("/proc/loadavg", "r"))
265 *strchr(line, '\n') = 0;
279 printf("R/T=%s, ", z);
283 printf("LAV=%s", line);
286 if (f = fopen("/proc/meminfo", "r"))
288 int total, used, free, shared, buffers, totals, useds, frees;
291 sscanf(line, "Mem:%d%d%d%d%d", &total, &used, &free, &shared, &buffers);
293 sscanf(line, "Swap:%d%d%d", &totals, &useds, &frees);
295 memory(free+buffers);
304 printf(", %d user%s.\n", usercnt, usercnt == 1 ? "" : "s");
312 if (d = opendir("/proc"))
314 while (e = readdir(d))
317 sscanf(e->d_name, "%d", &i);
320 struct procrec *p = xmalloc(sizeof(struct procrec));
322 char name[256], eman[1024];
325 strcpy(name, "/proc/");
326 strcat(name, e->d_name);
327 if (!stat(name, &st))
329 p->next = first_procrec;
333 strcat(eman, "/cmdline");
334 if ((fil = open(eman, O_RDONLY)) >= 0)
336 int z = read(fil, p->cmd_line, 33);
339 p->cmd_line[z] = 0xff;
343 strcat(eman, "/stat");
344 if ((fil = open(eman, O_RDONLY)) >= 0)
346 int z = read(fil, eman, 1023);
348 int trash, utim, stim, cutim, cstim;
352 k = strchr(eman, ')');
358 sscanf(k+3, "%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
359 &p->ppid, &p->pgrp, &p->sess, &trash, &trash,
360 &trash, &trash, &trash, &trash, &trash, &utim,
361 &stim, &cutim, &cstim);
363 p->tim = utim + stim;
364 p->ctim = cutim + cstim;
374 perror("unable to scan /proc");
382 struct utrec *u = first_utrec;
383 struct procrec *m, *n, *o, *q;
388 while (m && m->pid != u->login_pid)
398 if (q->sess == n->sess)
400 if (q->pid == n->ppid && n->usr == -1)
410 u->total_time = m->ctim;
414 printf("%s %s\n", u->user_name, o->cmd_line);
419 for(u=first_utrec; u; u=u->next)
421 for(m=first_procrec; m; m=m->next)
422 if (u->usr == m->usr)
427 printf("** %s %s\n", u->user_name, m->cmd_line);
431 for(m=first_procrec; m; m=m->next)
432 if (m->usr >= 2 && m->ppid == 1) /* Exclude no_user,root,bin */
434 for(u=first_utrec; u; u=u->next)
435 if (u->usr == m->usr)
439 u = xmalloc(sizeof(struct utrec));
440 u->next = first_utrec;
444 pw = getpwuid(u->usr = m->usr);
446 strcpy(u->user_name, pw->pw_name);
448 sprintf(u->user_name, "<%d>", m->usr);
458 u->total_time += m->ctim;
461 printf("// %s %s\n", u->user_name, m->cmd_line);
467 comp(struct utrec *a, struct utrec *b)
472 k = strcmp(a->user_name, b->user_name);
475 if (!a->host_name[0] && b->host_name[0])
477 return strcmp(a->line_id, b->line_id);
483 struct utrec *fi = NULL;
484 struct utrec *z, **y, **m, **l;
511 printf("Name Li MD From LogT IdleT RunT Command\n");
512 for(u=first_utrec; u; u=u->next)
518 u->line_id[1] = u->line_id[0];
522 u->line_id[0] = u->line_id[1] = '-';
524 printf("%-8.8s %-3s %c%c %-17.17s ",
528 u->detach ? 'D' : ' ',
532 if (u->login_time > now)
534 puttime(now - u->login_time);
536 if (u->click_time > now)
538 if (now - u->click_time >= 60)
539 puttime(now - u->click_time);
548 puttime((unsigned)u->total_time/(unsigned)HZ);
551 c = u->proc->cmd_line;
552 while (*c != 0xff && i--)
554 putchar(*c ? *c : ' ');
559 printf(" <nothing>");
574 printf("There %s %d zombie%s walking around.",
575 zombies == 1 ? "is" : "are",
577 zombies == 1 ? "" : "s" );