|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: char copyright[] = ! 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)w.c 5.24 (Berkeley) 7/27/90"; ! 15: #endif not lint ! 16: ! 17: /* ! 18: * w - print system status (who and what) ! 19: * ! 20: * This program is similar to the systat command on Tenex/Tops 10/20 ! 21: * ! 22: */ ! 23: #include <sys/param.h> ! 24: #include <utmp.h> ! 25: #include <sys/stat.h> ! 26: #include <sys/user.h> ! 27: #include <sys/proc.h> ! 28: #include <sys/ioctl.h> ! 29: #include <machine/pte.h> ! 30: #include <sys/vm.h> ! 31: #include <sys/tty.h> ! 32: #include <nlist.h> ! 33: #include <kvm.h> ! 34: #include <ctype.h> ! 35: #include <paths.h> ! 36: #include <string.h> ! 37: #include <stdio.h> ! 38: ! 39: char *program; ! 40: int ttywidth; /* width of tty */ ! 41: int argwidth; /* width of tty */ ! 42: int header = 1; /* true if -h flag: don't print heading */ ! 43: int wcmd = 1; /* true if this is w(1), and not uptime(1) */ ! 44: int nusers; /* number of users logged in now */ ! 45: char * sel_user; /* login of particular user selected */ ! 46: time_t now; /* the current time of day */ ! 47: struct timeval boottime; ! 48: time_t uptime; /* time of last reboot & elapsed time since */ ! 49: struct utmp utmp; ! 50: struct winsize ws; ! 51: int sortidle; /* sort bu idle time */ ! 52: ! 53: ! 54: /* ! 55: * One of these per active utmp entry. ! 56: */ ! 57: struct entry { ! 58: struct entry *next; ! 59: struct utmp utmp; ! 60: dev_t tdev; /* dev_t of terminal */ ! 61: int idle; /* idle time of terminal in minutes */ ! 62: struct proc *proc; /* list of procs in foreground */ ! 63: char *args; /* arg list of interesting process */ ! 64: } *ep, *ehead = NULL, **nextp = &ehead; ! 65: ! 66: struct nlist nl[] = { ! 67: { "_boottime" }, ! 68: #define X_BOOTTIME 0 ! 69: #if defined(hp300) ! 70: { "_cn_tty" }, ! 71: #define X_CNTTY 1 ! 72: #endif ! 73: { "" }, ! 74: }; ! 75: ! 76: #define USAGE "[ -hi ] [ user ]" ! 77: #define usage() fprintf(stderr, "usage: %s: %s\n", program, USAGE) ! 78: ! 79: main(argc, argv) ! 80: char **argv; ! 81: { ! 82: register int i; ! 83: struct winsize win; ! 84: register struct proc *p; ! 85: struct eproc *e; ! 86: struct stat *stp, *ttystat(); ! 87: FILE *ut; ! 88: char *cp; ! 89: int ch; ! 90: extern char *optarg; ! 91: extern int optind; ! 92: char *strsave(); ! 93: ! 94: program = argv[0]; ! 95: /* ! 96: * are we w(1) or uptime(1) ! 97: */ ! 98: if ((cp = rindex(program, '/')) || *(cp = program) == '-') ! 99: cp++; ! 100: if (*cp == 'u') ! 101: wcmd = 0; ! 102: ! 103: while ((ch = getopt(argc, argv, "hiflsuw")) != EOF) ! 104: switch((char)ch) { ! 105: case 'h': ! 106: header = 0; ! 107: break; ! 108: case 'i': ! 109: sortidle++; ! 110: break; ! 111: case 'f': case 'l': case 's': case 'u': case 'w': ! 112: error("[-flsuw] no longer supported"); ! 113: usage(); ! 114: exit(1); ! 115: case '?': ! 116: default: ! 117: usage(); ! 118: exit(1); ! 119: } ! 120: argc -= optind; ! 121: argv += optind; ! 122: if (argc == 1) { ! 123: sel_user = argv[0]; ! 124: argv++, argc--; ! 125: } ! 126: if (argc) { ! 127: usage(); ! 128: exit(1); ! 129: } ! 130: ! 131: if (header && kvm_nlist(nl) != 0) { ! 132: error("can't get namelist"); ! 133: exit (1); ! 134: } ! 135: time(&now); ! 136: ut = fopen(_PATH_UTMP, "r"); ! 137: while (fread(&utmp, sizeof(utmp), 1, ut)) { ! 138: if (utmp.ut_name[0] == '\0') ! 139: continue; ! 140: nusers++; ! 141: if (wcmd == 0 || (sel_user && ! 142: strncmp(utmp.ut_name, sel_user, UT_NAMESIZE) != 0)) ! 143: continue; ! 144: if ((ep = (struct entry *) ! 145: calloc(1, sizeof (struct entry))) == NULL) { ! 146: error("out of memory"); ! 147: exit(1); ! 148: } ! 149: *nextp = ep; ! 150: nextp = &(ep->next); ! 151: bcopy(&utmp, &(ep->utmp), sizeof (struct utmp)); ! 152: stp = ttystat(ep->utmp.ut_line); ! 153: ep->tdev = stp->st_rdev; ! 154: #if defined(hp300) ! 155: /* ! 156: * XXX If this is the console device, attempt to ascertain ! 157: * the true console device dev_t. ! 158: */ ! 159: if (ep->tdev == 0) { ! 160: static dev_t cn_dev; ! 161: ! 162: if (nl[X_CNTTY].n_value) { ! 163: struct tty cn_tty, *cn_ttyp; ! 164: ! 165: if (kvm_read(nl[X_CNTTY].n_value, ! 166: &cn_ttyp, sizeof (cn_ttyp)) > 0) { ! 167: (void)kvm_read(cn_ttyp, &cn_tty, ! 168: sizeof (cn_tty)); ! 169: cn_dev = cn_tty.t_dev; ! 170: } ! 171: nl[X_CNTTY].n_value = 0; ! 172: } ! 173: ep->tdev = cn_dev; ! 174: } ! 175: #endif ! 176: ep->idle = ((now - stp->st_atime) + 30) / 60; /* secs->mins */ ! 177: if (ep->idle < 0) ! 178: ep->idle = 0; ! 179: } ! 180: fclose(ut); ! 181: ! 182: if (header || wcmd == 0) { ! 183: double avenrun[3]; ! 184: int days, hrs, mins; ! 185: ! 186: /* ! 187: * Print time of day ! 188: */ ! 189: fputs(attime(&now), stdout); ! 190: /* ! 191: * Print how long system has been up. ! 192: * (Found by looking for "boottime" in kernel) ! 193: */ ! 194: (void)kvm_read((off_t)nl[X_BOOTTIME].n_value, &boottime, ! 195: sizeof (boottime)); ! 196: uptime = now - boottime.tv_sec; ! 197: uptime += 30; ! 198: days = uptime / (60*60*24); ! 199: uptime %= (60*60*24); ! 200: hrs = uptime / (60*60); ! 201: uptime %= (60*60); ! 202: mins = uptime / 60; ! 203: ! 204: printf(" up"); ! 205: if (days > 0) ! 206: printf(" %d day%s,", days, days>1?"s":""); ! 207: if (hrs > 0 && mins > 0) { ! 208: printf(" %2d:%02d,", hrs, mins); ! 209: } else { ! 210: if (hrs > 0) ! 211: printf(" %d hr%s,", hrs, hrs>1?"s":""); ! 212: if (mins > 0) ! 213: printf(" %d min%s,", mins, mins>1?"s":""); ! 214: } ! 215: ! 216: /* Print number of users logged in to system */ ! 217: printf(" %d user%s", nusers, nusers>1?"s":""); ! 218: ! 219: /* ! 220: * Print 1, 5, and 15 minute load averages. ! 221: */ ! 222: printf(", load average:"); ! 223: (void)getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])); ! 224: for (i = 0; i < (sizeof(avenrun)/sizeof(avenrun[0])); i++) { ! 225: if (i > 0) ! 226: printf(","); ! 227: printf(" %.2f", avenrun[i]); ! 228: } ! 229: printf("\n"); ! 230: if (wcmd == 0) /* if uptime(1) then done */ ! 231: exit(0); ! 232: #define HEADER "USER TTY FROM LOGIN@ IDLE WHAT\n" ! 233: #define WUSED (sizeof (HEADER) - sizeof ("WHAT\n")) ! 234: printf(HEADER); ! 235: } ! 236: ! 237: while ((p = kvm_nextproc()) != NULL) { ! 238: if (p->p_stat == SZOMB || (p->p_flag & SCTTY) == 0) ! 239: continue; ! 240: e = kvm_geteproc(p); ! 241: for (ep = ehead; ep != NULL; ep = ep->next) { ! 242: if (ep->tdev == e->e_tdev && e->e_pgid == e->e_tpgid) { ! 243: /* ! 244: * Proc is in foreground of this terminal ! 245: */ ! 246: if (proc_compare(ep->proc, p)) ! 247: ep->proc = p; ! 248: break; ! 249: } ! 250: } ! 251: } ! 252: if ((ioctl(1, TIOCGWINSZ, &ws) == -1 && ! 253: ioctl(2, TIOCGWINSZ, &ws) == -1 && ! 254: ioctl(0, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0) ! 255: ttywidth = 79; ! 256: else ! 257: ttywidth = ws.ws_col - 1; ! 258: argwidth = ttywidth - WUSED; ! 259: if (argwidth < 4) ! 260: argwidth = 8; ! 261: for (ep = ehead; ep != NULL; ep = ep->next) { ! 262: ep->args = strsave(kvm_getargs(ep->proc, kvm_getu(ep->proc))); ! 263: if (ep->args == NULL) { ! 264: error("out of memory"); ! 265: exit(1); ! 266: } ! 267: } ! 268: /* sort by idle time */ ! 269: if (sortidle && ehead != NULL) { ! 270: struct entry *from = ehead, *save; ! 271: ! 272: ehead = NULL; ! 273: while (from != NULL) { ! 274: for (nextp = &ehead; ! 275: (*nextp) && from->idle >= (*nextp)->idle; ! 276: nextp = &(*nextp)->next) ! 277: ; ! 278: save = from; ! 279: from = from->next; ! 280: save->next = *nextp; ! 281: *nextp = save; ! 282: } ! 283: } ! 284: ! 285: for (ep = ehead; ep != NULL; ep = ep->next) { ! 286: printf("%-*.*s %-2.2s %-*.*s %s", ! 287: UT_NAMESIZE, UT_NAMESIZE, ep->utmp.ut_name, ! 288: strncmp(ep->utmp.ut_line, "tty", 3) == 0 ? ! 289: ep->utmp.ut_line+3 : ep->utmp.ut_line, ! 290: UT_HOSTSIZE, UT_HOSTSIZE, *ep->utmp.ut_host ? ! 291: ep->utmp.ut_host : "-", ! 292: attime(&ep->utmp.ut_time)); ! 293: if (ep->idle >= 36 * 60) ! 294: printf(" %ddays ", (ep->idle + 12 * 60) / (24 * 60)); ! 295: else ! 296: prttime(ep->idle, " "); ! 297: printf("%.*s\n", argwidth, ep->args); ! 298: } ! 299: } ! 300: ! 301: struct stat * ! 302: ttystat(line) ! 303: { ! 304: static struct stat statbuf; ! 305: char ttybuf[sizeof (_PATH_DEV) + UT_LINESIZE + 1]; ! 306: ! 307: sprintf(ttybuf, "%s/%.*s", _PATH_DEV, UT_LINESIZE, line); ! 308: (void) stat(ttybuf, &statbuf); ! 309: ! 310: return (&statbuf); ! 311: } ! 312: ! 313: char * ! 314: strsave(cp) ! 315: char *cp; ! 316: { ! 317: register unsigned len; ! 318: register char *dp; ! 319: ! 320: len = strlen(cp); ! 321: dp = (char *)calloc(len+1, sizeof (char)); ! 322: (void) strcpy(dp, cp); ! 323: return (dp); ! 324: } ! 325: /* ! 326: * prttime prints a time in hours and minutes or minutes and seconds. ! 327: * The character string tail is printed at the end, obvious ! 328: * strings to pass are "", " ", or "am". ! 329: */ ! 330: prttime(tim, tail) ! 331: time_t tim; ! 332: char *tail; ! 333: { ! 334: ! 335: if (tim >= 60) { ! 336: printf(" %2d:", tim/60); ! 337: tim %= 60; ! 338: printf("%02d", tim); ! 339: } else if (tim >= 0) ! 340: printf(" %2d", tim); ! 341: printf("%s", tail); ! 342: } ! 343: ! 344: #include <varargs.h> ! 345: ! 346: warning(va_alist) ! 347: va_dcl ! 348: { ! 349: char *fmt; ! 350: va_list ap; ! 351: ! 352: fprintf(stderr, "%s: warning: ", program); ! 353: va_start(ap); ! 354: fmt = va_arg(ap, char *); ! 355: (void) vfprintf(stderr, fmt, ap); ! 356: va_end(ap); ! 357: fprintf(stderr, "\n"); ! 358: } ! 359: ! 360: error(va_alist) ! 361: va_dcl ! 362: { ! 363: char *fmt; ! 364: va_list ap; ! 365: ! 366: fprintf(stderr, "%s: ", program); ! 367: va_start(ap); ! 368: fmt = va_arg(ap, char *); ! 369: (void) vfprintf(stderr, fmt, ap); ! 370: va_end(ap); ! 371: fprintf(stderr, "\n"); ! 372: } ! 373: ! 374: syserror(va_alist) ! 375: va_dcl ! 376: { ! 377: char *fmt; ! 378: va_list ap; ! 379: extern errno; ! 380: ! 381: fprintf(stderr, "%s: ", program); ! 382: va_start(ap); ! 383: fmt = va_arg(ap, char *); ! 384: (void) vfprintf(stderr, fmt, ap); ! 385: va_end(ap); ! 386: fprintf(stderr, ": %s\n", strerror(errno)); ! 387: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.