|
|
1.1 ! root 1: static char rcsid[] = "$Header: sysline.c,v 1.4 83/07/31 23:47:49 layer Exp $"; ! 2: ! 3: /* ! 4: * sysline - system status display on 25th line of terminal ! 5: * j.k.foderaro ! 6: * ! 7: * Prints a variety of information on the special status line of terminals ! 8: * that have a status display capability. Cursor motions, status commands, ! 9: * etc. are gleamed from /etc/termcap. ! 10: * By default, all information is printed, and flags are given on the command ! 11: * line to disable the printing of information. The information and ! 12: * disabling flags are: ! 13: * ! 14: * flag what ! 15: * ----- ---- ! 16: * time of day ! 17: * load average and change in load average in the last 5 mins ! 18: * number of user logged on ! 19: * -p # of processes the users owns which are runnable and the ! 20: * number which are suspended. Processes whose parent is 1 ! 21: * are not counted. ! 22: * -l users who've logged on and off. ! 23: * -m summarize new mail which has arrived ! 24: * ! 25: * <other flags> ! 26: * -r use non reverse video ! 27: * -c turn off 25th line for 5 seconds before redisplaying. ! 28: * -b beep once one the half hour, twice on the hour ! 29: * +N refresh display every N seconds. ! 30: * -i print pid first thing ! 31: * -e do simple print designed for an emacs buffer line ! 32: * -h print hostname between time and load average ! 33: * -D print day/date before time of day ! 34: * -d debug mode - print status line data in human readable format ! 35: * -q quiet mode - don't output diagnostic messages ! 36: * -s print Short (left-justified) line if escapes not allowed ! 37: * -j Print left Justified line regardless ! 38: * ! 39: */ ! 40: ! 41: /* for 4.2 BSD */ ! 42: #define BSD4_2 ! 43: ! 44: #define NETPREFIX "ucb" ! 45: ! 46: /* turn this on always */ ! 47: #define WHO ! 48: ! 49: /* turn this on if you are on running 4.1a or greater (i.e. a system ! 50: with the gethostname() function */ ! 51: #define HOSTNAME ! 52: #define RWHO ! 53: ! 54: /* turn this on if you are running on vmunix */ ! 55: #define VMUNIX ! 56: ! 57: /* turn this on if you are running on 4.1c or greater */ ! 58: #define NEW_BOOTTIME ! 59: ! 60: #include <sys/param.h> ! 61: #include <signal.h> ! 62: #include <stdio.h> ! 63: #include <utmp.h> ! 64: #include <ctype.h> ! 65: #ifndef BSD4_2 ! 66: #include <unctrl.h> ! 67: #endif ! 68: #include <sys/time.h> ! 69: #include <sys/stat.h> ! 70: #ifdef VMUNIX ! 71: #include <nlist.h> ! 72: #include <sys/vtimes.h> ! 73: #include <sys/proc.h> ! 74: #endif ! 75: #ifdef pdp11 ! 76: #include <a.out.h> ! 77: #include <sys/proc.h> ! 78: #define strcmpn strncmp ! 79: #endif ! 80: #include <curses.h> ! 81: #undef nl ! 82: #ifdef TERMINFO ! 83: #include <term.h> ! 84: #endif ! 85: ! 86: #ifdef RWHO ! 87: #define DOWN_THRESHOLD (2 * 60) ! 88: #define RWHOLEADER "/usr/spool/rwho/whod." ! 89: #define MAXFILENAME 128 ! 90: ! 91: struct whod { ! 92: char wd_vers; ! 93: char wd_type; ! 94: char wd_fill[2]; ! 95: int wd_sendtime; ! 96: int wd_recvtime; ! 97: char wd_hostname[32]; ! 98: int wd_loadav[3]; ! 99: int wd_boottime; ! 100: }; ! 101: ! 102: struct outmp { ! 103: char out_line[8]; /* tty name */ ! 104: char out_name[8]; /* user id */ ! 105: long out_time; /* time on */ ! 106: }; ! 107: #endif RWHO ! 108: ! 109: #ifdef VMUNIX ! 110: #define MAXUSERS 100 ! 111: #else ! 112: #define MAXUSERS 40 ! 113: #endif ! 114: #define DEFDELAY 60 /* update status once per minute */ ! 115: #define MAILDIR "/usr/spool/mail" ! 116: ! 117: /* if MaxLoad is defined, then if the load average exceeded MaxLoad ! 118: * then the process table will not be scanned and the log in/out data ! 119: * will not be checked. The purpose of this is to reduced the load ! 120: * on the system when it is loaded. ! 121: */ ! 122: #define MaxLoad 6.0 ! 123: ! 124: ! 125: struct nlist nl[] = ! 126: #ifdef NEW_BOOTTIME ! 127: { { "_boottime" }, /* After 4.1a the label changed to "boottime" */ ! 128: #else ! 129: { { "_bootime" }, /* Under 4.1a and earlier it is "bootime" */ ! 130: #endif ! 131: #define NL_BOOT 0 ! 132: { "_proc" }, ! 133: #define NL_PROC 1 ! 134: { "_avenrun" }, ! 135: #define NL_AVEN 2 ! 136: #ifdef VMUNIX ! 137: { "_nproc" }, ! 138: #define NL_NPROC 3 ! 139: #endif ! 140: { 0 }}; ! 141: ! 142: struct proc *pr; ! 143: int nproc; ! 144: int procadr; ! 145: ! 146: double avenrun[3]; /* used for storing load averages */ ! 147: ! 148: int kmem; /* file pointers for memory */ ! 149: int ut; ! 150: int users, nentries; ! 151: ! 152: #ifdef WHO ! 153: char whofilename[100]; ! 154: #endif ! 155: ! 156: #ifdef RWHO ! 157: char *remotehost[10]; ! 158: int nremotes = 0; ! 159: #endif RWHO ! 160: ! 161: #ifdef HOSTNAME ! 162: char hostname[32]; ! 163: #endif ! 164: ! 165: char lockfilename[100]; /* if exists, will prevent us from running */ ! 166: ! 167: /* flags which determine which info is printed */ ! 168: int mailcheck = 1; /* m - do biff like checking of mail */ ! 169: int proccheck = 1; /* p - give information on processes */ ! 170: int logcheck = 1; /* l - tell who logs in and out */ ! 171: int hostprint = 0; /* h - print out hostname */ ! 172: int dateprint = 0; /* h - print out day/date */ ! 173: int quiet = 0; /* q - hush diagnostic messages */ ! 174: ! 175: /* flags which determine how things are printed */ ! 176: int clr_bet_ref = 0; /* c - clear line between refeshes */ ! 177: int reverse = 1; /* r - use reverse video */ ! 178: int shortline = 0; /* s - short (left-justified) if escapes not allowed */ ! 179: int leftline = 0; /* j - left-justified even if escapes allowed */ ! 180: int sawmail; /* remember mail was seen to print bells */ ! 181: ! 182: /* flags which have terminal do random things */ ! 183: int beep = 0; /* b - beep every half hour and twice every hour */ ! 184: int synch = 1; /* synchronize with clock */ ! 185: int printid = 0; /* print pid of this process at startup */ ! 186: ! 187: /* ! 188: * used to turn off reverse video every REVOFF times ! 189: * in an attempt to not wear out the phospher. ! 190: */ ! 191: #define REVOFF 5 ! 192: int revtime = 1; ! 193: ! 194: /* select output device (status display or straight output (emacs window)) */ ! 195: int emacs = 0; /* assume status display */ ! 196: int dbug = 0; ! 197: ! 198: /* used by mail checker */ ! 199: off_t mailsize = 0; ! 200: off_t linebeg = 0; /* place where we last left off reading */ ! 201: ! 202: /* globals */ ! 203: int mailprocessed; ! 204: char *username; ! 205: struct stat stbuf, mstbuf; /* mstbuf for mail check only */ ! 206: char *ourtty,*ttyname(); /* keep track of what tty we're on */ ! 207: char *getenv(); ! 208: char *tparm(), *tgoto(); ! 209: unsigned delay = DEFDELAY; ! 210: int chars; ! 211: short uid; ! 212: double loadavg = 0.0; /* current load average */ ! 213: int fullprocess; ! 214: int users = 0; ! 215: ! 216: /* strings which control status line display */ ! 217: #ifdef TERMINFO ! 218: ! 219: char *rev_out, *rev_end, *arrows; ! 220: ! 221: #else /* TERMCAP */ ! 222: ! 223: char to_status_line[64]; ! 224: char from_status_line[64]; ! 225: char dis_status_line[64]; ! 226: char rev_out[20], rev_end[20]; ! 227: char *arrows, *bell = "\007"; ! 228: int eslok; /* escapes on status line okay (reverse, cursor addressing) */ ! 229: int columns; ! 230: #endif ! 231: ! 232: /* ! 233: * In order to determine how many people are logged on and who has ! 234: * logged in or out, we read in the /etc/utmp file. We also keep track of ! 235: * the previous utmp file. ! 236: */ ! 237: struct utmp uts[2][MAXUSERS]; ! 238: ! 239: outc(c) ! 240: char c; ! 241: { ! 242: if (dbug) ! 243: printf("%s", unctrl(c)); ! 244: else putchar(c); ! 245: } ! 246: ! 247: erroutc(c) ! 248: char c; ! 249: { ! 250: if (dbug) ! 251: fprintf(stderr,"%s", unctrl(c)); ! 252: else fputc(c,stderr); ! 253: } ! 254: ! 255: main(argc,argv) ! 256: char **argv; ! 257: { ! 258: register new,old,tmp; ! 259: int clearbotl(); ! 260: char *cp; ! 261: extern char _sobuf[]; ! 262: ! 263: ! 264: setbuf(stdout, _sobuf); ! 265: signal(SIGINT,SIG_IGN); ! 266: signal(SIGQUIT,SIG_IGN); ! 267: signal(SIGALRM,SIG_IGN); ! 268: #ifdef VMUNIX ! 269: signal(SIGTTOU,SIG_IGN); ! 270: #endif ! 271: /* ! 272: * When we logoff, init will do a "vhangup()" on this ! 273: * tty which turns off I/O access and sends a SIGHUP ! 274: * signal. We catch this and thereby clear the status ! 275: * display. Note that a bug in 4.1bsd caused the SIGHUP ! 276: * signal to be sent to the wrong process, so you had to ! 277: * `kill -HUP' yourself in your .logout file. ! 278: */ ! 279: signal(SIGHUP,clearbotl); ! 280: ! 281: #ifdef HOSTNAME ! 282: gethostname(hostname,sizeof(hostname)); ! 283: #endif ! 284: ! 285: argv++; ! 286: while(--argc > 0) { ! 287: switch(argv[0][0]) { ! 288: case '-': for(cp = &argv[0][1]; *cp ; cp++) ! 289: { ! 290: switch(*cp) { ! 291: case 'r' : reverse = 0; /* turn off reverse video */ ! 292: break; ! 293: case 'c': clr_bet_ref = 1; ! 294: break; ! 295: case 'h': hostprint = 1; ! 296: break; ! 297: case 'D': dateprint = 1; ! 298: break; ! 299: #ifdef RWHO ! 300: case 'H': if(!strcmp(hostname,argv[1]) || ! 301: !strcmp(&hostname[strlen(NETPREFIX)] ! 302: ,argv[1])) ! 303: { ! 304: argv++, argc--; ! 305: break; ! 306: } ! 307: remotehost[nremotes++] = argv[1]; ! 308: argv++, argc--; ! 309: break; ! 310: #endif RWHO ! 311: case 'm': mailcheck = 0; ! 312: break; ! 313: case 'p': proccheck = 0; ! 314: break; ! 315: case 'l': logcheck = 0; ! 316: break; ! 317: case 'b': beep = 1; ! 318: break; ! 319: case 'i': printid = 1; ! 320: break; ! 321: case 'e': emacs = 1; ! 322: break; ! 323: case 'd': dbug = 1; ! 324: signal(SIGINT, SIG_DFL); ! 325: signal(SIGQUIT, SIG_DFL); ! 326: break; ! 327: case 'q': quiet = 1; ! 328: break; ! 329: case 's': shortline = 1; ! 330: break; ! 331: case 'j': leftline = 1; ! 332: break; ! 333: default: fprintf(stderr, ! 334: "sysline: bad flag: %c\n",*cp); ! 335: } ! 336: } ! 337: break; ! 338: case '+': delay = atoi(&argv[0][1]); ! 339: if((delay <= 10) || (delay > 500)) delay = DEFDELAY; ! 340: synch = 0; /* no more sync */ ! 341: break; ! 342: default: fprintf(stderr,"sysline: illegal argument %s\n",argv[0]); ! 343: } ! 344: argv++; ! 345: } ! 346: if(emacs) { ! 347: columns = 80; ! 348: } else { ! 349: /* if not to emacs window, initialize terminal dependent info */ ! 350: initterm(); ! 351: } ! 352: ! 353: /* immediately fork and let the parent die if not emacs mode */ ! 354: if(!emacs && !dbug && fork()) exit(0); ! 355: uid = getuid(); ! 356: ! 357: ourtty = ttyname(2); /* remember what tty we are on */ ! 358: if(printid) { printf("%d\n",getpid()); fflush(stdout);} ! 359: close(1); ! 360: dup2(2, 1); ! 361: ! 362: strcpy(whofilename,getenv("HOME")); ! 363: strcat(whofilename,"/.who"); ! 364: ! 365: strcpy(lockfilename,getenv("HOME")); ! 366: strcat(lockfilename,"/.syslinelock"); ! 367: ! 368: if((ut = open("/etc/utmp",0)) < 0) ! 369: { ! 370: fprintf(stderr,"Can't open utmp"); ! 371: exit(1); ! 372: } ! 373: ! 374: if((kmem = open("/dev/kmem",0)) < 0) ! 375: { ! 376: fprintf(stderr,"Can't open kmem"); ! 377: exit(1); ! 378: } ! 379: ! 380: /* read in namelist in order to get location of symbols */ ! 381: readnamelist(); ! 382: ! 383: if(proccheck) initprocread(); ! 384: ! 385: if(mailcheck) ! 386: { ! 387: chdir(MAILDIR); ! 388: username = getenv("USER"); ! 389: if(stat(username,&mstbuf) != -1) ! 390: { ! 391: mailsize = mstbuf.st_size; ! 392: } ! 393: else mailsize = 0; ! 394: } ! 395: ! 396: old = 0; ! 397: new = 1; ! 398: ! 399: while(emacs || isloggedin()) ! 400: { ! 401: if(access(lockfilename,0)) ! 402: { ! 403: mailprocessed = 0; ! 404: prtinfo(old,new); ! 405: sleep(delay); ! 406: if(clr_bet_ref) ! 407: { ! 408: tputs(dis_status_line, 1, outc); ! 409: fflush(stdout); ! 410: sleep(5); ! 411: } ! 412: revtime = (1 + revtime) % REVOFF; ! 413: ! 414: /* ! 415: * if we have processed mail, then dont switch utmp pointers ! 416: * since we havent printed the people whove logged in and out ! 417: */ ! 418: if(!mailprocessed || !fullprocess) ! 419: { ! 420: tmp = old; ! 421: old = new; ! 422: new = tmp; ! 423: } ! 424: } else sleep(60); ! 425: } ! 426: clearbotl(); ! 427: /* NOTREACHED */ ! 428: } ! 429: ! 430: isloggedin() ! 431: { ! 432: /* ! 433: * you can tell if a person has logged out if the owner of ! 434: * the tty has changed ! 435: */ ! 436: struct stat statbuf; ! 437: if(fstat(2,&statbuf) == 0) ! 438: { ! 439: if(statbuf.st_uid == uid) return(1); ! 440: } ! 441: return(0); /* not logged in */ ! 442: } ! 443: ! 444: ! 445: readnamelist() ! 446: { ! 447: time_t bootime, clock, nintv, time(); ! 448: ! 449: #ifdef pdp11 ! 450: nlist("/unix",nl); ! 451: #else ! 452: nlist("/vmunix",nl); ! 453: #endif ! 454: if(nl[0].n_value == 0) { ! 455: if (!quiet) ! 456: fprintf(stderr, "No namelist\n"); ! 457: return; ! 458: } ! 459: lseek(kmem, (long)nl[NL_BOOT].n_value, 0); ! 460: read(kmem, &bootime, sizeof(bootime)); ! 461: (void) time(&clock); ! 462: nintv = clock - bootime; ! 463: if (nintv <= 0L || nintv > 60L*60L*24L*365L) { ! 464: if (!quiet) ! 465: fprintf(stderr, "Time makes no sense... namelist must be wrong\n"); ! 466: nl[NL_PROC].n_value = nl[NL_AVEN].n_value = 0; ! 467: } ! 468: } ! 469: ! 470: readutmp(n) ! 471: { ! 472: lseek(ut,0L,0); ! 473: nentries = read(ut,&uts[n][0],MAXUSERS*sizeof(struct utmp)) ! 474: / sizeof(struct utmp); ! 475: } ! 476: ! 477: /* ! 478: * read in the process table locations and sizes, and allocate space ! 479: * for storing the process table. This is done only once. ! 480: */ ! 481: initprocread() ! 482: { ! 483: if (nl[NL_PROC].n_value == 0) return; ! 484: #ifdef VMUNIX ! 485: lseek(kmem,(long)nl[NL_PROC].n_value,0); ! 486: read(kmem,&procadr,sizeof(procadr)); ! 487: lseek(kmem,(long)nl[NL_NPROC].n_value,0); ! 488: read(kmem,&nproc,sizeof(nproc)); ! 489: #endif ! 490: #ifdef pdp11 ! 491: procadr = nl[NL_PROC].n_value; ! 492: nproc = NPROC; /* from param.h */ ! 493: #endif ! 494: pr = (struct proc *) calloc(nproc,sizeof(struct proc)); ! 495: } ! 496: ! 497: /* ! 498: * read in the process table. This assumes that initprocread has alread been ! 499: * called to set up storage. ! 500: */ ! 501: readproctab() ! 502: { ! 503: if (nl[NL_PROC].n_value == 0) return(0); ! 504: /* printf("There are %d entries beginning at %x\n",nproc,procadr); */ ! 505: lseek(kmem,(long)procadr,0); ! 506: read(kmem,pr,nproc * sizeof(struct proc)); ! 507: return(1); ! 508: } ! 509: ! 510: /* ! 511: * codes to say what has happened to a particular entry in utmp ! 512: * NOCH means no change, ON means new person logged on, ! 513: * OFF means person logged off. ! 514: */ ! 515: #define NOCH 0; ! 516: #define ON 0x1 ! 517: #define OFF 0x2 ! 518: ! 519: prtinfo(old,new) ! 520: int old,new; ! 521: { ! 522: int procrun,procstop; ! 523: int on,off; ! 524: int status[MAXUSERS]; ! 525: register int i; ! 526: double diff; ! 527: char *sysrup(); ! 528: ! 529: stringinit(); ! 530: ! 531: #ifdef WHO ! 532: /* check for file named .who in the home directory */ ! 533: whocheck(); ! 534: #endif ! 535: ! 536: timeprint(); ! 537: ! 538: /* ! 539: * if mail is seen, don't print rest of info, just the mail ! 540: * reverse new and old so that next time we run, we won't lose log ! 541: * in and out information ! 542: */ ! 543: if(mailcheck && (sawmail = mailseen()) ) ! 544: { ! 545: mailprocessed = 1; ! 546: goto bottom; ! 547: } ! 548: ! 549: #ifdef HOSTNAME ! 550: #ifdef RWHO ! 551: if(remotehost) ! 552: { ! 553: for(i=0; i < nremotes; i++) ! 554: stringprt(" %s", sysrup(remotehost[i])); ! 555: } ! 556: #endif ! 557: /* ! 558: * print hostname info if requested ! 559: */ ! 560: if(hostprint) ! 561: { ! 562: stringspace(); ! 563: stringcat(hostname,strlen(hostname),1); ! 564: } ! 565: #endif ! 566: ! 567: /* ! 568: * print load average and difference between current load average ! 569: * and the load average 5 minutes ago ! 570: */ ! 571: if (nl[NL_AVEN].n_value != 0) { ! 572: stringspace(); ! 573: #ifdef VMUNIX ! 574: lseek(kmem,(long)nl[NL_AVEN].n_value,0); ! 575: read(kmem,avenrun,sizeof(avenrun)); ! 576: #endif ! 577: #ifdef pdp11 ! 578: loadav(avenrun); ! 579: #endif ! 580: stringprt("%.1f ",avenrun[0]); ! 581: if((diff = avenrun[0] - avenrun[1]) < 0.0) ! 582: stringprt("%.1f",diff); ! 583: else stringprt("+%.1f",diff); ! 584: loadavg = avenrun[0]; /* remember load average */ ! 585: } ! 586: ! 587: /* ! 588: * print log on and off information ! 589: */ ! 590: stringspace(); ! 591: ! 592: fullprocess = 1; ! 593: ! 594: #ifdef MaxLoad ! 595: if(loadavg > MaxLoad) fullprocess = 0; /* too loaded to run */ ! 596: #endif ! 597: /* read utmp file (logged in data) only if we are doing a full ! 598: process or if this is the first time and we are calculating ! 599: the number of users ! 600: */ ! 601: if(fullprocess || (users == 0)) readutmp(new); ! 602: ! 603: ! 604: /* ! 605: * make a pass through utmp, checking if person has logged off ! 606: * or on. Results are stored in status[] ! 607: */ ! 608: on = off = 0; ! 609: /* only do this if it hasn't been done yet (users == 0) or ! 610: * if the load average is low enough to permit it ! 611: */ ! 612: if(fullprocess || (users == 0 )) ! 613: { ! 614: users = 0; ! 615: for(i=0 ; i < nentries ; i++) ! 616: { ! 617: if(strcmpn(uts[old][i].ut_name,uts[new][i].ut_name,8) != 0) ! 618: { ! 619: if(uts[old][i].ut_name[0] == '\0') ! 620: { ! 621: status[i] = ON; ! 622: on++; ! 623: } ! 624: else if (uts[new][i].ut_name[0] == '\0') ! 625: { ! 626: status[i] = OFF; ! 627: off++; ! 628: } ! 629: else { ! 630: status[i] = ON | OFF; ! 631: on++; ! 632: off++; ! 633: } ! 634: } ! 635: else status[i] = NOCH; ! 636: ! 637: if(uts[new][i].ut_name[0]) users++; ! 638: } ! 639: } ! 640: ! 641: /* at this point we know how many users there are */ ! 642: stringprt("%du",users); ! 643: ! 644: /* if there is any unread mail, put out a star */ ! 645: /* fprintf(stderr,"mailsz:%d,mtime:%d,atime:%d\n", ! 646: mailsize,mstbuf.st_mtime,mstbuf.st_atime); */ ! 647: if((mailsize > 0) && (mstbuf.st_mtime >= mstbuf.st_atime)) ! 648: stringcat("*",1,1); ! 649: ! 650: /* if the load is too high, then we indicate that with a - sign */ ! 651: if(!fullprocess && (proccheck || logcheck)) stringcat("-",1,1); ! 652: ! 653: /* if we are to check on number of process running, do so now */ ! 654: if(fullprocess && proccheck && readproctab()) ! 655: { ! 656: /* ! 657: * we are only interested in processes which have the same ! 658: * uid as us, and whose parent process id is not 1. ! 659: */ ! 660: procrun = procstop = 0; ! 661: for(i=0; i < nproc ; i++) ! 662: { ! 663: if((pr[i].p_stat == 0) || (pr[i].p_pgrp == 0)) continue; ! 664: if((pr[i].p_uid == uid) && (pr[i].p_ppid != 1)) ! 665: { ! 666: /* printf("found pid %d, stat=%o\n", pr[i].p_pid, pr[i].p_stat); */ ! 667: switch (pr[i].p_stat) { ! 668: ! 669: case SSTOP: ! 670: procstop++; ! 671: break; ! 672: ! 673: case SSLEEP: ! 674: /* ! 675: * sleep can mean waiting for a signal or just ! 676: * in a disk or page wait queue ready to run. ! 677: * We can tell if it is the later by the pri being ! 678: * negative ! 679: */ ! 680: if (pr[i].p_pri < PZERO) procrun++; ! 681: break; ! 682: ! 683: case SWAIT: ! 684: case SRUN: ! 685: case SIDL: ! 686: procrun++; ! 687: ! 688: } ! 689: } ! 690: } ! 691: ! 692: if((procrun > 0) || (procstop > 0)) ! 693: { ! 694: stringspace(); ! 695: if((procrun > 0) && (procstop > 0)) ! 696: { ! 697: stringprt("%dr",procrun); ! 698: stringprt(" %ds",procstop); ! 699: } ! 700: else if(procrun > 0) stringprt("%dr",procrun); ! 701: else stringprt("%ds",procstop); ! 702: } ! 703: } ! 704: ! 705: /* ! 706: * if anyone has logged on or off, and we are interested in it, ! 707: * print it out ! 708: */ ! 709: if(logcheck && on) ! 710: { ! 711: stringspace(); ! 712: stringprt("on:",on); ! 713: for(i = 0 ; i < nentries ; i++) ! 714: { ! 715: if(status[i] & ON) ! 716: { ! 717: stringprt(" %.8s",uts[new][i].ut_name); ! 718: ttyprint(uts[new][i].ut_line); ! 719: } ! 720: } ! 721: } ! 722: ! 723: /* ! 724: * check for people logging off if we are intereste ! 725: */ ! 726: if(logcheck && off) ! 727: { ! 728: stringspace(); ! 729: stringprt("off:",off); ! 730: for(i = 0 ; i < nentries ; i++) ! 731: { ! 732: if(status[i] & OFF) ! 733: { ! 734: stringprt(" %.8s",uts[old][i].ut_name); ! 735: ttyprint(uts[old][i].ut_line); ! 736: } ! 737: } ! 738: } ! 739: bottom: ! 740: /* dump out what we know */ ! 741: stringdump(); ! 742: } ! 743: ! 744: timeprint() ! 745: { ! 746: long curtime; ! 747: struct tm *tp, *localtime(); ! 748: static int beepable=0; ! 749: ! 750: /* always print time */ ! 751: time(&curtime); ! 752: tp = localtime(&curtime); ! 753: ! 754: if (dateprint) ! 755: stringprt("%.11s", ctime(&curtime)); ! 756: stringprt("%d:",(tp->tm_hour > 12 ? tp->tm_hour - 12 ! 757: : (tp->tm_hour == 0 ? 12 : tp->tm_hour))); ! 758: stringprt("%02d",tp->tm_min); ! 759: ! 760: if(synch) delay = 60 - tp->tm_sec; /* sync with clock */ ! 761: ! 762: /* beepable is used to insure that we get at most one set of beeps ! 763: every half hour */ ! 764: if(beep && beepable && (tp->tm_min == 30)) ! 765: { ! 766: tputs(bell, 1, outc); fflush(stdout); ! 767: beepable = 0; ! 768: } ! 769: else if(beep && beepable && (tp->tm_min == 00)) ! 770: { ! 771: tputs(bell, 1, outc); fflush(stdout); ! 772: sleep(2); ! 773: tputs(bell, 1, outc); fflush(stdout); ! 774: beepable = 0; ! 775: } ! 776: else if(beep && ((tp->tm_min != 00) || (tp->tm_min != 30))) ! 777: beepable = 1; ! 778: ! 779: } ! 780: ! 781: /* ! 782: * whocheck -- check for file named .who and print it on the who line first ! 783: */ ! 784: whocheck() ! 785: { ! 786: register wf,i,chss; ! 787: char buff[81]; ! 788: ! 789: if((wf = open(whofilename,0)) >= 0) ! 790: { ! 791: chss = read(wf,buff,80); ! 792: if(chss == 0) ! 793: { ! 794: close(wf); ! 795: return; ! 796: } ! 797: buff[chss] = '\0'; ! 798: /* ! 799: * remove all line feeds, and replace by spaces if they are within ! 800: * the message, else replace them by nulls. ! 801: */ ! 802: for(i = chss; i >= 0; i--) ! 803: { ! 804: if(buff[i] == '\n') ! 805: { ! 806: if(buff[i+1]) buff[i] = ' '; ! 807: else buff[i] = '\0'; ! 808: } ! 809: } ! 810: stringprt("%s",buff); ! 811: stringspace(); ! 812: close(wf); ! 813: } ! 814: } ! 815: ! 816: /* ! 817: * ttyprint -- given the name of a tty, print in the string buffer its ! 818: * short name surrounded by parenthesis. ! 819: * ttyxx is printed as (xx) ! 820: * console is printed as (cty) ! 821: */ ! 822: ttyprint(name) ! 823: char *name; ! 824: { ! 825: char buff[10]; ! 826: ! 827: if(strcmpn(name,"tty",3)==0) ! 828: { ! 829: sprintf(buff,"(%s)",name+3); ! 830: } ! 831: else if(strcmp(name,"console")== 0) ! 832: { ! 833: sprintf(buff,"(cty)"); ! 834: } ! 835: else sprintf(buff,"(%s)",name); ! 836: ! 837: stringcat(buff,strlen(buff),0); ! 838: } ! 839: ! 840: /* ! 841: * mail checking function ! 842: * returns 0 if no mail seen ! 843: */ ! 844: mailseen() ! 845: { ! 846: FILE *mfd; ! 847: int retval = 0; ! 848: int chs,initchs; ! 849: register char *rp,*cp; ! 850: char lbuf[100], sendbuf[100]; ! 851: int toprint,seenspace = 0; ! 852: ! 853: if(stat(username,&mstbuf) != -1) ! 854: { ! 855: if((mstbuf.st_size > mailsize) && ((mfd=fopen(username,"r")) != NULL)) ! 856: { ! 857: /* fprintf(stderr,"Mail gotten was %db, now %db\n", ! 858: mailsize,stbuf.st_size); */ ! 859: fseek(mfd,mailsize,0); ! 860: while((initchs = readline(mfd, lbuf, sizeof(lbuf))) != EOF) ! 861: { ! 862: if(strcmpn(lbuf,"From",4) == 0) ! 863: { ! 864: cp = lbuf+5; /* start after the From */ ! 865: while(*cp && (*++cp != ' ')); /* skip to blank */ ! 866: *cp = '\0'; /* terminate name */ ! 867: stringspace(); ! 868: /* if(!emacs) stringcat(bell,0,0); BELL MOVED */ ! 869: sprintf(sendbuf,"Mail from %s ",lbuf+5); ! 870: stringcat(sendbuf,strlen(sendbuf),0); ! 871: /* print message preceeded by little arrow */ ! 872: /* skip over the headers and look for blank line */ ! 873: while(((chs = readline(mfd, lbuf, sizeof(lbuf))) != EOF) && (chs != 0)) ! 874: if(strcmpn(lbuf,"Subject",7)==0) ! 875: { ! 876: sprintf(sendbuf,"on %s",lbuf+9); ! 877: stringcat(sendbuf,strlen(sendbuf),1); ! 878: } ! 879: if(!emacs) stringcat(arrows,2,0); ! 880: else stringcat(" : ",3,0); ! 881: ! 882: if(chs != EOF) ! 883: { ! 884: cp = sendbuf; ! 885: toprint = columns - chars; /* space left on line */ ! 886: lbuf[0] = '\0'; ! 887: while((chs = readline(mfd, lbuf, sizeof(lbuf))) != EOF) ! 888: { ! 889: if(toprint > 0) ! 890: { ! 891: *cp++ = ' '; /* space before lines */ ! 892: toprint--; ! 893: } ! 894: rp = lbuf; ! 895: if(strcmpn(lbuf,"From",4) == 0) break; ! 896: while(*rp && (toprint > 0)) ! 897: { ! 898: if(isspace(*rp)) ! 899: { ! 900: if(!seenspace) ! 901: { ! 902: *cp++ = ' '; ! 903: seenspace = 1; ! 904: toprint--; ! 905: } ! 906: } ! 907: else { ! 908: *cp++ = *rp; ! 909: seenspace = 0; ! 910: toprint--; ! 911: } ! 912: rp++; ! 913: } ! 914: } ! 915: *cp = '\0'; ! 916: stringcat(sendbuf,strlen(sendbuf),1); ! 917: /* if(!emacs) stringcat(bell,0,0); BELL MOVED */ ! 918: retval = 1; ! 919: } ! 920: break; ! 921: } ! 922: } ! 923: if(initchs == EOF) ! 924: { ! 925: stringprt("Mail has just arrived",chs); ! 926: } ! 927: /* ! 928: * want to update write time so a star will ! 929: * appear after the number of users until the ! 930: * user reads his mail ! 931: */ ! 932: mailsize = linebeg; ! 933: touch(username,mfd); ! 934: fclose(mfd); ! 935: } ! 936: else mailsize = mstbuf.st_size; ! 937: } ! 938: else mailsize = 0; ! 939: return(retval); ! 940: } ! 941: ! 942: /* ! 943: * readline -- read a line from fp and store it in buf. ! 944: * return the number of characters read. ! 945: */ ! 946: readline(fp, buf, maxch) ! 947: FILE *fp; ! 948: char *buf; ! 949: { ! 950: register char *cp, ch; ! 951: int size = maxch; ! 952: long ftell(); ! 953: ! 954: linebeg = ftell(fp); /* remember loc where line begins */ ! 955: cp = buf; ! 956: while(((ch=getc(fp)) != EOF) && (ch != '\n') && (size-- > 0)) *cp++ = ch; ! 957: *cp = '\0'; ! 958: if((size == maxch) && (ch == EOF)) return (EOF); ! 959: else return(maxch - size); ! 960: } ! 961: ! 962: ! 963: /* string hacking functions */ ! 964: ! 965: int eol; /* non zero when we have hit the end of line */ ! 966: char *sp; ! 967: char strarr[120]; ! 968: ! 969: stringinit() ! 970: { ! 971: sp = strarr; ! 972: chars = 0; ! 973: eol = 0; ! 974: } ! 975: ! 976: stringprt(format,value) ! 977: char *format; ! 978: { ! 979: char tempbuf[150]; ! 980: int bufsiz; ! 981: ! 982: sprintf(tempbuf,format,value); ! 983: bufsiz = strlen(tempbuf); ! 984: stringcat(tempbuf,bufsiz,0); ! 985: } ! 986: ! 987: stringdump() ! 988: { ! 989: char bigbuf[200]; ! 990: register char *cp; ! 991: register int i; ! 992: char blanks[80]; ! 993: ! 994: *sp = '\0'; ! 995: bigbuf[0] = 0; ! 996: if(!emacs) { ! 997: if (sawmail) strcat(bigbuf, bell); ! 998: if (eslok) { ! 999: if(!leftline) ! 1000: cp = tparm(to_status_line, columns - chars); ! 1001: else ! 1002: cp = tparm(to_status_line, 0); ! 1003: strcat(bigbuf, cp); ! 1004: } else { ! 1005: strcat(bigbuf, to_status_line); ! 1006: if (!shortline & !leftline) { ! 1007: for (i=0; i < (columns-chars); i++) ! 1008: blanks[i] = ' '; ! 1009: blanks[columns-chars] = '\0'; ! 1010: strcat(bigbuf, blanks); ! 1011: } ! 1012: } ! 1013: if(reverse && !(revtime == 0)) strcat(bigbuf, rev_out); ! 1014: } ! 1015: strcat(bigbuf,strarr); ! 1016: if (!emacs) { ! 1017: if (reverse) strcat(bigbuf, rev_end); ! 1018: strcat(bigbuf, from_status_line); ! 1019: if (sawmail) { ! 1020: strcat(bigbuf, bell); ! 1021: strcat(bigbuf, bell); ! 1022: } ! 1023: tputs(bigbuf, 1, outc); ! 1024: if (dbug) putchar('\n'); ! 1025: fflush(stdout); ! 1026: } else ! 1027: write(2,bigbuf,strlen(bigbuf)); ! 1028: } ! 1029: ! 1030: stringspace() ! 1031: { ! 1032: if(!emacs && reverse && !(revtime == 0)) { ! 1033: #ifdef TERMINFO ! 1034: stringcat(rev_end, magic_cookie_glitch<=0?0:magic_cookie_glitch, 0); ! 1035: stringcat(" ",1,0); ! 1036: stringcat(rev_out, magic_cookie_glitch<=0?0:magic_cookie_glitch, 0); ! 1037: #else ! 1038: stringcat(rev_end,0,0); ! 1039: stringcat(" ",1,0); ! 1040: stringcat(rev_out,0,0); ! 1041: #endif ! 1042: } else stringcat(" ",1,0); ! 1043: } ! 1044: ! 1045: /* ! 1046: * stringcat :: concatenate the characters in string str to the list we are ! 1047: * building to send out. ! 1048: * ! 1049: * the three args are ! 1050: * str - the string to print. may contain funny (terminal control) chars. ! 1051: * chrs - the number of printable characters in the string ! 1052: * trunc - a flag which is non zero if we should truncate strings which ! 1053: * don't fit. If this is 0 then if a string doesn't completely ! 1054: * fit it wont' be printed, this prevents us from getting 1/2 ! 1055: * way through an escape sequence. ! 1056: */ ! 1057: stringcat(str,chrs,trunc) ! 1058: char *str; ! 1059: { ! 1060: ! 1061: if((chrs == 0) || (!eol && chars + chrs <= columns) ! 1062: || (!eol && trunc && (chars < columns))) ! 1063: { ! 1064: while(*sp++ = *str++) ! 1065: if(trunc) ! 1066: { ! 1067: if(++chars >= columns) /* check for trunc */ ! 1068: { ! 1069: eol = 1; ! 1070: return; ! 1071: } ! 1072: } ! 1073: sp--; ! 1074: if(!trunc) chars += chrs; ! 1075: } ! 1076: else eol = 1; ! 1077: } ! 1078: ! 1079: /* ! 1080: * touch :: update the modify time of a file. ! 1081: */ ! 1082: touch(name,filedes) ! 1083: char *name; /* name of file */ ! 1084: FILE *filedes; /* already open for read file descriptor */ ! 1085: { ! 1086: register fd; ! 1087: char buf[1]; ! 1088: ! 1089: lseek(fileno(filedes),0L,0); ! 1090: read(fileno(filedes),buf,1); /* get first byte */ ! 1091: if((fd = open(name,2)) >= 0) /* open in append mode */ ! 1092: { ! 1093: lseek(fd,0L,0); /* go to beginning */ ! 1094: write(fd,buf,1); /* and rewrite first byte */ ! 1095: close(fd); ! 1096: } ! 1097: } ! 1098: ! 1099: ! 1100: /* ! 1101: * clearbotl :: clear bottom line. ! 1102: * called when process quits or is killed. ! 1103: * it clears the bottom line of the terminal. ! 1104: */ ! 1105: clearbotl() ! 1106: { ! 1107: register int fd; ! 1108: int exit(); ! 1109: ! 1110: signal(SIGALRM,exit); ! 1111: alarm(30); /* if can't open in 30 secs, just die */ ! 1112: if( !emacs && (fd = open(ourtty,1)) >=0) ! 1113: { ! 1114: write(fd,dis_status_line,strlen(dis_status_line)); ! 1115: close(fd); ! 1116: } ! 1117: exit(0); ! 1118: } ! 1119: ! 1120: #ifdef TERMINFO ! 1121: initterm() ! 1122: { ! 1123: static char standbuf[40]; ! 1124: ! 1125: setupterm(0, 1, 0); ! 1126: if (!has_status_line) { ! 1127: /* not an appropriate terminal */ ! 1128: if (!quiet) ! 1129: fprintf(stderr, "sysline: no status capability for %s\n", ! 1130: getenv("TERM")); ! 1131: exit(1); ! 1132: } ! 1133: if (status_line_esc_ok) { ! 1134: if (set_attributes) { ! 1135: /* reverse video mode */ ! 1136: strcpy(standbuf, tparm(set_attributes,0,0,1,0,0,0,0,0,0)); ! 1137: rev_out = standbuf; ! 1138: rev_end = exit_attribute_mode; ! 1139: } else if (enter_standout_mode && exit_standout_mode) { ! 1140: rev_out = enter_standout_mode; ! 1141: rev_end = exit_standout_mode; ! 1142: } else { ! 1143: rev_out = rev_end = ""; ! 1144: } ! 1145: } else ! 1146: rev_out = rev_end = ""; ! 1147: columns--; /* avoid cursor wraparound */ ! 1148: } ! 1149: ! 1150: #else /* TERMCAP */ ! 1151: ! 1152: initterm() ! 1153: { ! 1154: char *term, *cp; ! 1155: char tbuf[1024], is2[40]; ! 1156: extern char *UP; ! 1157: ! 1158: if ((term=getenv("TERM")) == NULL) { ! 1159: if (!quiet) ! 1160: fprintf(stderr, "sysline: No TERM variable in enviroment\n"); ! 1161: exit(1); ! 1162: } ! 1163: if (tgetent(tbuf, term) <= 0) { ! 1164: if (!quiet) ! 1165: fprintf(stderr, "sysline: Unknown terminal type: %s\n", term); ! 1166: exit(1); ! 1167: } ! 1168: if (tgetflag("hs") <= 0) { ! 1169: if (!strcmpn(term, "h19", 3)) { ! 1170: /* for upward compatability with h19sys */ ! 1171: strcpy(to_status_line, "\033j\033x5\033x1\033Y8%+ \033o"); ! 1172: strcpy(from_status_line, "\033k\033y5"); ! 1173: strcpy(dis_status_line, "\033y1"); ! 1174: strcpy(rev_out, "\033p"); ! 1175: strcpy(rev_end, "\033q"); ! 1176: arrows = "\033Fhh\033G"; ! 1177: columns = 80; ! 1178: UP = "\b"; ! 1179: return; ! 1180: } ! 1181: if (!quiet) ! 1182: fprintf(stderr, "sysline: No status capability for %s\n", term); ! 1183: exit(1); ! 1184: } ! 1185: cp = is2; ! 1186: if (tgetstr("i2", &cp) != NULL) { ! 1187: /* someday tset will do this */ ! 1188: tputs(is2, 1, erroutc); ! 1189: fflush(stdout); ! 1190: } ! 1191: ! 1192: /* the "-1" below is to avoid cursor wraparound problems */ ! 1193: columns = tgetnum("co") - 1; ! 1194: cp = to_status_line; ! 1195: tgetstr("ts", &cp); ! 1196: cp = from_status_line; ! 1197: tgetstr("fs", &cp); ! 1198: cp = dis_status_line; ! 1199: tgetstr("ds", &cp); ! 1200: eslok = tgetflag("es"); ! 1201: if (eslok) { ! 1202: cp = rev_out; ! 1203: tgetstr("so", &cp); ! 1204: cp = rev_end; ! 1205: tgetstr("se", &cp); ! 1206: } else { ! 1207: reverse = 0; /* turn off reverse video */ ! 1208: }; ! 1209: UP = "\b"; ! 1210: if (!strcmpn(term, "h19", 3)) ! 1211: arrows = "\033Fhh\033G"; /* "two tiny graphic arrows" */ ! 1212: else ! 1213: arrows = "->"; ! 1214: } ! 1215: ! 1216: char * ! 1217: tparm(cap, parm) ! 1218: char *cap; ! 1219: int parm; ! 1220: { ! 1221: return tgoto(cap, 0, parm); ! 1222: } ! 1223: #endif ! 1224: ! 1225: #ifdef pdp11 ! 1226: loadav(ap) ! 1227: double ap[]; ! 1228: { ! 1229: register int i; ! 1230: short s_avenrun[3]; ! 1231: ! 1232: lseek(kmem, (long)nl[NL_AVEN].n_value, 0); ! 1233: read(kmem, s_avenrun, sizeof(s_avenrun)); ! 1234: for (i=0; i < (sizeof(s_avenrun)/sizeof(s_avenrun[0])); i++) ! 1235: ap[i] = s_avenrun[i] / 256.0; ! 1236: } ! 1237: #endif ! 1238: ! 1239: #ifdef RWHO ! 1240: char * ! 1241: sysrup(hostname) ! 1242: char *hostname; ! 1243: { ! 1244: char filename[MAXFILENAME]; ! 1245: FILE *rwhofile; ! 1246: struct whod wd; ! 1247: char buffer[BUFSIZ]; ! 1248: long now; ! 1249: ! 1250: /* ! 1251: * try rwho hostname file, and if that fails try ucbhostname. ! 1252: */ ! 1253: (void) strcpy(filename, RWHOLEADER); ! 1254: (void) strcat(filename, hostname); ! 1255: rwhofile = fopen(filename, "r"); ! 1256: if (rwhofile == NULL) { ! 1257: (void) strcpy(filename, RWHOLEADER); ! 1258: (void) strcat(filename, "ucb"); ! 1259: (void) strcat(filename, hostname); ! 1260: rwhofile = fopen(filename, "r"); ! 1261: if (rwhofile == NULL) { ! 1262: (void) sprintf(buffer, "%s?", hostname); ! 1263: return buffer; ! 1264: } ! 1265: } ! 1266: if (fread(&wd, sizeof wd, 1, rwhofile) != 1) { ! 1267: (void) sprintf(buffer, "%s ?", hostname); ! 1268: fclose(rwhofile); ! 1269: return buffer; ! 1270: } ! 1271: (void) time(&now); ! 1272: if (now - wd.wd_recvtime > DOWN_THRESHOLD) { ! 1273: long interval; ! 1274: long days, hours, minutes; ! 1275: ! 1276: interval = now - wd.wd_recvtime; ! 1277: minutes = (interval + 59) / 60; /* round to minutes */ ! 1278: hours = minutes / 60; /* extract hours from minutes */ ! 1279: minutes %= 60; /* remove hours from minutes */ ! 1280: days = hours / 24; /* extract days from hours */ ! 1281: hours %= 24; /* remove days from hours */ ! 1282: if (days > 7 || days < 0) { ! 1283: (void) sprintf(buffer, "%s down", hostname); ! 1284: } else if (days > 0) { ! 1285: (void) sprintf(buffer, "%s %d+%d:%02d", ! 1286: hostname, days, hours, minutes); ! 1287: } else { ! 1288: (void) sprintf(buffer, "%s %d:%02d", hostname, hours, minutes); ! 1289: } ! 1290: } else { ! 1291: (void) sprintf(buffer, "%s %.1f", hostname, wd.wd_loadav[0]/100.0); ! 1292: } ! 1293: if (rwhofile != NULL) { ! 1294: fclose(rwhofile); ! 1295: } ! 1296: return buffer; ! 1297: } ! 1298: #endif RWHO
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.