2 * Extended `who' command, version 1.8.
4 * (c) 1996, 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU General Public License. See file COPYING in any of the GNU packages.
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, "ywho: 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_IWGRP & 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 free, buffers, stotal, sfree;
289 free = buffers = stotal = sfree = 0;
290 while (fgets(line, 256, f))
292 if (!strncmp(line, "MemFree:", 8))
293 sscanf(line+8, "%d", &free);
294 else if (!strncmp(line, "Buffers:", 8))
295 sscanf(line+8, "%d", &buffers);
296 else if (!strncmp(line, "SwapTotal:", 10))
297 sscanf(line+10, "%d", &stotal);
298 else if (!strncmp(line, "SwapFree:", 9))
299 sscanf(line+9, "%d", &sfree);
302 memory(1024*(free+buffers));
307 memory(1024*(stotal - sfree));
311 printf(", %d user%s.\n", usercnt, usercnt == 1 ? "" : "s");
319 if (d = opendir("/proc"))
321 while (e = readdir(d))
324 sscanf(e->d_name, "%d", &i);
327 struct procrec *p = xmalloc(sizeof(struct procrec));
329 char name[256], eman[1024];
332 strcpy(name, "/proc/");
333 strcat(name, e->d_name);
334 if (!stat(name, &st))
336 p->next = first_procrec;
340 strcat(eman, "/cmdline");
341 if ((fil = open(eman, O_RDONLY)) >= 0)
343 int z = read(fil, p->cmd_line, sizeof(p->cmd_line) - 1);
346 p->cmd_line[z] = 0x91;
350 strcat(eman, "/stat");
351 if ((fil = open(eman, O_RDONLY)) >= 0)
353 int z = read(fil, eman, 1023);
355 int trash, utim, stim, cutim, cstim;
359 k = strchr(eman, ')');
365 sscanf(k+4, "%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
366 &p->ppid, &p->pgrp, &p->sess, &trash, &trash,
367 &trash, &trash, &trash, &trash, &trash, &utim,
368 &stim, &cutim, &cstim);
370 p->tim = utim + stim;
371 p->ctim = cutim + cstim;
381 perror("unable to scan /proc");
389 struct utrec *u = first_utrec;
390 struct procrec *m, *n, *o, *q;
395 while (m && m->pid != u->login_pid)
405 if (q->sess == n->sess)
407 if (q->pid == n->ppid && n->usr == -1)
417 u->total_time = m->ctim;
421 printf("%s %s\n", u->user_name, o->cmd_line);
426 for(u=first_utrec; u; u=u->next)
428 for(m=first_procrec; m; m=m->next)
429 if (u->usr == m->usr)
434 printf("** %s %s\n", u->user_name, m->cmd_line);
438 for(m=first_procrec; m; m=m->next)
439 if (m->usr >= 2 && m->ppid == 1) /* Exclude no_user,root,bin */
441 for(u=first_utrec; u; u=u->next)
442 if (u->usr == m->usr)
446 u = xmalloc(sizeof(struct utrec));
447 u->next = first_utrec;
451 pw = getpwuid(u->usr = m->usr);
453 strcpy(u->user_name, pw->pw_name);
455 sprintf(u->user_name, "<%d>", m->usr);
465 u->total_time += m->ctim;
468 printf("// %s %s\n", u->user_name, m->cmd_line);
474 comp(struct utrec *a, struct utrec *b)
479 k = strcmp(a->user_name, b->user_name);
482 if (!a->host_name[0] && b->host_name[0])
484 return strcmp(a->line_id, b->line_id);
490 struct utrec *fi = NULL;
491 struct utrec *z, **y, **m, **l;
518 printf("Name Li MD From LogT IdleT RunT Command\n");
519 for(u=first_utrec; u; u=u->next)
525 u->line_id[1] = u->line_id[0];
529 u->line_id[0] = u->line_id[1] = '-';
531 printf("%-8.8s %-3s %c%c %-17.17s ",
535 u->detach ? 'D' : ' ',
539 if (u->login_time > now)
541 puttime(now - u->login_time);
543 if (u->click_time > now)
545 if (now - u->click_time >= 60)
546 puttime(now - u->click_time);
555 puttime((unsigned)u->total_time/(unsigned)HZ);
558 c = u->proc->cmd_line;
559 while (*c != 0x91 && i--)
561 if (*c < 0x20 || (*c >= 0x7f && *c < 0xa0))
569 printf(" <nothing>");
584 printf("!!! There %s %d zombie%s walking around.\n",
585 zombies == 1 ? "is" : "are",
587 zombies == 1 ? "" : "s" );