home *** CD-ROM | disk | FTP | other *** search
- Subject: swho: screen based who (curses, continuous update)
- From: Paul Pomes <talcott!seismo!uiucdcs!uiucuxc.CSO.UIUC.EDU!paul>
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 3, Issue 74
- Submitted by: Paul Pomes (Univ of Illinois) <seismo!uiucdcs!uiucuxc!paul>
-
-
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # README
- # Makefile
- # swho.c
- # swho.1
- sed 's/^X//' << 'SHAR_EOF' > README
- XSwho provides an enhanced who command using curses. Besides displaying
- Xusercodes, ttys, and login times, swho also provides idle time indicators
- Xand tty types (dialup, switch, localnet, etc). The program is easy on
- Xsystem resources as it stats the utmp file on every wakeup and reads it
- Xonly if it has changed. The screen is cleared every ten minutes and
- Xre-drawn to eliminate screen confusion from messages, announcements, etc.
- XThis "feature" can be eliminated by undefining REDRAW.
- X
- X Paul Pomes
- X
- XUUCP: {ihnp4,pur-ee,convex}!uiucdcs!uiucuxc!paul
- XARPANET: paul%uiucuxc@a.cs.uiuc.edu CSNET: paul%uiucuxc@uiuc.csnet
- XICBM: 40 07 N / 88 13 W
- XUS Mail: Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL 61801
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > Makefile
- X# Makefile for swho, a display utility for showing active users and ttys.
- X#
- X# Written by Paul Pomes, University of Illinois, Computing Services Office
- X# Copyright 1985 by Paul Pomes and University of Illinois Board of Trustees
- X#
- X# UUCP: {ihnp4,pur-ee,convex}!uiucdcs!uiucuxc!paul
- X# ARPANET: paul%uiucuxc@uiuc.arpa
- X# CSNET: paul%uiucuxc@uiuc.csnet
- X# US Mail: Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL 61801
- X#
- X# $Header$
- X
- XCFLAGS= -O
- XLDFLAGS=
- XLIBS = -lcurses -ltermlib
- XDESTBIN= /usr/local/bin
- XDESTLIB= /usr/local/lib
- XMAN = l
- X
- X# make depend doesn't work with single file names as grep doesn't prepend
- X# the "file.c: " string in front of the match. Quick and dirty kludge is
- X# to put the filename twice on the SRCS line.
- X
- XSRCS = swho.c
- XOBJS = swho.o
- X
- X.DEFAULT:
- X co $<
- X
- Xall: swho
- X
- X#
- X# RCS stuff
- X#
- Xci: $(SRCS)
- X -ci $?
- X @touch ci
- X
- Xcoall:
- X co -l $(SRCS)
- X
- Xupdate:
- X ci -sDist -u -f$(VERS) $(SRCS)
- X @touch ci
- X
- Xswho: ${OBJS}
- X cc -o swho ${LDFLAGS} ${OBJS} ${LIBS}
- X
- Xinstall: swho
- X install -s swho ${DESTBIN}
- X cp swho.1 /usr/man/man${MAN}/swho.${MAN}
- X
- Xclean:
- X rm -f swho *.o core a.out make.log lint.out
- X
- Xclobber:
- X make clean
- X rm -f ${SRCS}
- X
- Xlint: ${SRCS}
- X lint -habx ${SRCS}
- X
- Xcompress:
- X make clean
- X find . -size +2 \( -name \*.c -o -name \*.f -o -name \*.h \
- X -o -name \*.l -o -name \*,v \) -exec compress {} \;
- X
- Xuncompress:
- X uncompressdir .
- X
- Xdepend:
- X grep '^#include' ${SRCS} \
- X | sed -e '/"/s/:[^"]*"\([^"]*\)".*/: \1/' \
- X -e '/</s/:[^<]*<\([^>]*\)>.*/: \/usr\/include\/\1/' \
- X | sed 's/\.c/.o/' >makedep
- X echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
- X echo '$$r makedep' >>eddep
- X echo 'w' >>eddep
- X cp Makefile Makefile.bak
- X ed - Makefile < eddep
- X rm eddep makedep
- X echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile
- X echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile
- X echo '# see make depend above' >> Makefile
- X
- X# DO NOT DELETE THIS LINE -- make depend uses it
- X
- Xswho.o: /usr/include/stdio.h
- Xswho.o: /usr/include/utmp.h
- Xswho.o: /usr/include/strings.h
- Xswho.o: /usr/include/sys/time.h
- Xswho.o: /usr/include/signal.h
- Xswho.o: /usr/include/curses.h
- Xswho.o: /usr/include/sys/types.h
- Xswho.o: /usr/include/sys/stat.h
- X# DEPENDENCIES MUST END AT END OF FILE
- X# IF YOU PUT STUFF HERE IT WILL GO AWAY
- X# see make depend above
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > swho.c
- X/*
- X * swho -- display users, ttys, and login times using curses
- X *
- X * usage: swho [-v]
- X *
- X * -v Disable use of standout mode (usually reverse video)
- X *
- X * Written by Paul Pomes, University of Illinois, Computing Services Office
- X * Copyright (C) 1985 by Paul Pomes and the University of Illinois Board
- X * of Trustees
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but without any warranty. No author or distributor accepts
- X * responsibility to anyone for the consequences of using it or for
- X * whether it serves any particular purpose or works at all, unless
- X * s/he says so in writing.
- X *
- X * Everyone is granted permission to copy, modify and redistribute
- X * this program under the following conditions:
- X *
- X * Permission is granted to anyone to make or distribute copies
- X * of program source code, either as received or modified, in any
- X * medium, provided that all copyright notices, permission and
- X * nonwarranty notices are preserved, and that the distributor
- X * grants the recipient permission for further redistribution as
- X * permitted by this document, and gives him and points out to
- X * him an exact copy of this document to inform him of his rights.
- X *
- X * Permission is granted to distribute this program in compiled
- X * or executable form under the same conditions applying for
- X * source code, provided that either
- X * A. it is accompanied by the corresponding machine-readable
- X * source code, or
- X * B. it is accompanied by a written offer, with no time limit,
- X * to give anyone a machine-readable copy of the corresponding
- X * source code in return for reimbursement of the cost of
- X * distribution. This written offer must permit verbatim
- X * duplication by anyone.
- X * C. it is distributed by someone who received only the
- X * executable form, and is accompanied by a copy of the
- X * written offer of source code which he received along with it.
- X *
- X * In other words, you are welcome to use, share and improve this
- X * program. You are forbidden to forbid anyone else to use, share
- X * and improve what you give them. Help stamp out software-hoarding!
- X *
- X * UUCP: {ihnp4,pur-ee,convex}!uiucdcs!uiucuxc!paul
- X * ARPANET: paul@uiucuxc.cso.uiuc.edu
- X * CSNET: paul%uiucuxc@uiuc.csnet
- X * ICBMS: 88 13 N / 40 07 W
- X * US Mail: Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL 61801
- X *
- X * $Log: swho.c,v $
- X * Revision 1.5 86/01/01 13:17:42 paul
- X * Made screen re-draw a #ifdef REDRAW option.
- X *
- X * Revision 1.4 85/12/09 17:08:02 paul
- X * Added -v switch and test for termcap entry sg to disable standout mode.
- X * sg entry indicates standout mode needs a space before and after. Not
- X * so good for a program that uses every one.
- X *
- X * Revision 1.3 85/11/15 15:56:10 paul
- X * Added feature to clear and re-draw the screen every ten minutes.
- X *
- X * Revision 1.2 85/10/30 13:18:17 paul
- X * Added code to denote ttys with no shell as " ---- " in the name
- X * field. -pbp
- X *
- X * Revision 1.1 85/10/24 17:37:22 paul
- X * Initial revision
- X *
- X */
- X
- X#ifndef lint
- Xstatic char RcsId[] = "$Header: swho.c,v 1.5 86/01/01 13:17:42 paul Exp $";
- X#endif
- X
- X#include <stdio.h>
- X#include <utmp.h>
- X
- X#ifdef SYS5
- X#include <string.h>
- X#define index strchr
- X#else
- X#include <strings.h>
- X#endif SYS5
- X
- X#include <sys/time.h>
- X#include <signal.h>
- X#include <curses.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- X#define equal(s1, s2) (strcmp(s1, s2) == 0)
- X
- X/* utmp sizes */
- X#define NMAX sizeof(utmp.ut_name)
- X#define LMAX sizeof(utmp.ut_line)
- X
- X/* width of 1 display column */
- X#define COL_WIDTH 20
- X
- X/* update interval in seconds */
- X#define INTERVAL 10
- X
- X/* count of how many INTERVALs before completely re-drawing the screen.
- X * comment this out to disable screen re-draws.
- X */
- X#define REDRAW 60
- X
- X/* x/60 rounded */
- X#define DIV60(t) ((t+30)/60)
- X
- X/* number of COL_WIDTH columns on screen */
- Xint ncols;
- X
- X/* special terminal types and their symbols */
- Xstruct special {
- X char *name;
- X char symbol;
- X} special[] = {
- X "dialup", 'D',
- X "lnet", 'L',
- X "telenet", 'T',
- X "wats", 'W',
- X "switch", 'S',
- X NULL, '\0'
- X};
- X
- X/* set if terminal inserts blanks when standout mode is used */
- Xint sg;
- X
- X/* current time for idle calculations and display */
- Xtime_t clock;
- X
- X/* one line of utmp information */
- Xstruct utmp utmp;
- X
- X/* copy of argv[0] for error messages */
- Xchar *self;
- X
- X/* standout mode disabled if set */
- Xint video_flag = 0;
- X
- X/* debug messages printed if set */
- Xint debug_flag = 0;
- X
- X/* interrupt handler */
- Xint quit();
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X /* a useful counter */
- X int i;
- X
- X /* line and column manipulation */
- X int line, col;
- X
- X#ifdef REDRAW
- X /* re-draw screen when equal to REDRAW */
- X int redo_timer = 0;
- X#endif REDRAW
- X
- X /* number of minutes user is idle */
- X time_t idle;
- X
- X /* copy of utmp.ut_line */
- X char tty[LMAX+1];
- X
- X /* copy of utmp.ut_name */
- X char name[NMAX+1];
- X
- X /* stat /etc/utmp every INTERVAL seconds; read only when changed */
- X struct stat stb;
- X time_t *mtime = &stb.st_mtime;
- X time_t lasttime;
- X
- X /* stream descriptor for /etc/ttys file */
- X register FILE *tfd;
- X
- X /* set to '1' if tty line has a shell */
- X int ttyon;
- X
- X /* stream descriptor for utmp file */
- X register FILE *ufd;
- X
- X /* pointer to time struct */
- X struct tm *tm;
- X
- X /* library routines */
- X char *malloc();
- X
- X /*
- X * squirrel a copy of *argv[0] away for use in error messages
- X */
- X self = malloc((unsigned) (strlen(*argv) + 1));
- X (void) strcpy(self, *argv);
- X
- X /* parse arguments */
- X i = 1;
- X while (i < argc && *argv[i] == '-') {
- X if (equal(argv[i]+1, "d")) {
- X /* d - set debug level */
- X debug_flag++;
- X i++;
- X fprintf(stderr, "%s: debug option enabled\n", self);
- X }
- X if (equal(argv[i]+1, "v")) {
- X /* v - disable use of standout mode */
- X video_flag++;
- X i++;
- X }
- X else {
- X /* command line errors */
- X fprintf(stderr, "%s: %s - bad flag\n", self, argv[i]+1);
- X fprintf(stderr, "Usage: %s [-v]\n", self);
- X exit(1);
- X }
- X }
- X if ((tfd = fopen("/etc/ttys", "r")) == NULL) {
- X fprintf(stderr, "%s: ", self);
- X perror("/etc/ttys");
- X exit(1);
- X }
- X if ((ufd = fopen("/etc/utmp", "r")) == NULL) {
- X fprintf(stderr, "%s: ", self);
- X perror("/etc/utmp");
- X exit(1);
- X }
- X (void) signal(SIGINT, quit);
- X (void) signal(SIGHUP, quit);
- X so_chk();
- X initscr();
- X ncols = (COLS / COL_WIDTH) - 1;
- X noecho();
- X ttylist();
- X *mtime = (time_t) 0;
- X while (1) {
- X#ifdef REDRAW
- X if (redo_timer++ == REDRAW) {
- X redo_timer = 0;
- X *mtime = (time_t) 0;
- X ttylist();
- X }
- X#endif REDRAW
- X (void) time(&clock);
- X tm = localtime(&clock);
- X if (! video_flag)
- X standout();
- X mvprintw(0, 0, "%.19s", asctime(tm));
- X if (! video_flag)
- X standend();
- X lasttime = *mtime;
- X (void) fstat(fileno(ufd), &stb);
- X if (*mtime > lasttime) {
- X (void) fread((char *) &utmp, sizeof(utmp), 1, ufd);
- X ttyon = fgetc(tfd);
- X for (line = 1, col = 0; ;) {
- X if (fread((char *) &utmp, sizeof(utmp), 1, ufd) != 1)
- X break;
- X if (line == LINES) {
- X if (col == ncols)
- X break;
- X else {
- X line = 0;
- X col++;
- X }
- X }
- X if (ttyon == '0' && utmp.ut_name[0] == '\0')
- X mvprintw(line, col*20, " ---- ");
- X else if (utmp.ut_name[0] == '\0') {
- X mvprintw(line, col*20, " ");
- X mvprintw(line, col*20+13, " ");
- X if (! sg && ! video_flag)
- X standout();
- X mvprintw(line, col*20+8, " ");
- X if (! sg && ! video_flag)
- X standend();
- X }
- X else {
- X tm = localtime((time_t *) &utmp.ut_time);
- X
- X /* utmp strings may not have end null */
- X (void) strncpy(tty, utmp.ut_line, LMAX);
- X (void) strncpy(name, utmp.ut_name, NMAX);
- X mvprintw(line, col*20, "%8s", name);
- X mvprintw(line, col*20+13, "%2d:%02d", tm->tm_hour, tm->tm_min);
- X idle = findidle();
- X if (! sg && ! video_flag)
- X standout();
- X if (idle > (time_t) 60)
- X mvprintw(line, col*20+8, "+");
- X else if (idle > (time_t) 30)
- X mvprintw(line, col*20+8, "-");
- X else
- X mvprintw(line, col*20+8, " ");
- X if (! sg && ! video_flag)
- X standend();
- X }
- X /* advance the pointer in /etc/ttys */
- X while ((ttyon = fgetc(tfd)) != EOF && ttyon != '\n')
- X ;
- X if (ttyon == EOF || (ttyon = fgetc(tfd)) == EOF)
- X break;
- X line++;
- X }
- X rewind(tfd);
- X rewind(ufd);
- X }
- X refresh();
- X sleep(INTERVAL);
- X }
- X}
- X
- X/*
- X * quit -- cleanup after interrupt
- X *
- X * parameters:
- X * none
- X * returns:
- X * none
- X * side effects:
- X * none
- X * deficiencies:
- X */
- Xquit()
- X{
- X (void) signal(SIGINT, SIG_IGN);
- X clear();
- X refresh();
- X endwin();
- X exit(0);
- X}
- X
- X/*
- X * so_chk -- check whether terminal inserts blanks with standout mode
- X *
- X * parameters:
- X * none
- X * returns:
- X * none
- X * side effects:
- X * sets global variable sg
- X * deficiencies:
- X */
- Xso_chk()
- X{
- X char tbuf[1024];
- X int ret_value;
- X
- X char *getenv();
- X
- X if ((ret_value = tgetent(tbuf, getenv("TERM"))) != 1) {
- X if (ret_value == 0) /* no entry */
- X sg = 0;
- X else {
- X fprintf(stderr, "%s: so_chk: can't open /etc/termcap\n", self);
- X exit(1);
- X }
- X return;
- X }
- X if ((sg = tgetnum("sg")) == -1)
- X sg = 0;
- X return;
- X}
- X
- X/*
- X * ttylist -- display the ttys
- X *
- X * parameters:
- X * none
- X * returns:
- X * none
- X * side effects:
- X * updates the display
- X * deficiencies:
- X */
- Xttylist()
- X{
- X
- X register FILE *fd0, *fd1;
- X register struct special *ps;
- X char entry[25];
- X register char *pe;
- X register c;
- X int line, col;
- X
- X /* open files ttys and ttytype. die gracefully otherwise */
- X if ((fd0 = fopen("/etc/ttys", "r")) == NULL) {
- X fprintf(stderr, "%s: ttylist: ", self);
- X perror("/etc/ttys");
- X exit(1);
- X }
- X if ((fd1 = fopen("/etc/ttytype", "r")) == NULL) {
- X fprintf(stderr, "%s: ttylist: ", self);
- X perror("/etc/ttytype");
- X exit(1);
- X }
- X
- X clear();
- X /* first line is the console and is a special case */
- X pe = entry;
- X while ((c = getc(fd0)) != '\n')
- X *pe++ = c;
- X *pe = '\0';
- X pe = entry;
- X mvprintw(1, 9, "%.3s", pe+2);
- X
- X /* first line of ttytype we don't care about */
- X while ((c = getc(fd1)) != '\n')
- X ;
- X
- X /* now continue with the rest of the files */
- X for (col = 0, line = 2; ; ) {
- X if (line == LINES) {
- X if (col == ncols)
- X break;
- X else {
- X line = 0;
- X col++;
- X }
- X }
- X while ((c = getc(fd0)) != '\n' && c != EOF)
- X *pe++ = c;
- X if (c == EOF)
- X break;
- X *pe = '\0';
- X pe = entry;
- X mvprintw(line, col*20+10, "%2s", pe + (strlen(pe)-2));
- X
- X /* read the tty type and mark the special ones */
- X while ((c = getc(fd1)) != '\n' && c != EOF)
- X *pe++ = c;
- X if (c == EOF)
- X break;
- X *pe = '\0';
- X pe = entry;
- X if (index(pe, '\t'))
- X *(index(pe, '\t')) = '\0';
- X else if (index(pe, ' '))
- X *(index(pe, ' ')) = '\0';
- X if (! sg && ! video_flag)
- X standout();
- X mvprintw(line, col*20+8, " ");
- X for (ps = special; ps->name != NULL; ps++)
- X if (equal(ps->name, pe))
- X mvprintw(line, col*20+8, " %c", ps->symbol);
- X if (! sg && ! video_flag)
- X standend();
- X line++;
- X }
- X (void) fclose(fd0);
- X (void) fclose(fd1);
- X
- X /* clean up and go back */
- X refresh();
- X}
- X
- X/*
- X * findidle -- find & return number of minutes current tty has been idle
- X *
- X * parameters:
- X * none
- X * returns:
- X * idle time in (time_t) minutes
- X * side effects:
- X * none
- X * deficiencies:
- X * idle time is a slippery idea, this routine checks only the
- X * access timestamp on the utmp.ut_line tty.
- X */
- Xtime_t
- Xfindidle()
- X{
- X struct stat stbuf;
- X time_t lastaction, diff;
- X char ttyname[20];
- X
- X (void) strcpy(ttyname, "/dev/");
- X (void) strcatn(ttyname, utmp.ut_line, LMAX);
- X (void) stat(ttyname, &stbuf);
- X lastaction = stbuf.st_atime;
- X diff = clock - lastaction;
- X diff = DIV60(diff);
- X if (diff < 0)
- X diff = 0;
- X return(diff);
- X}
- SHAR_EOF
- sed 's/^X//' << 'SHAR_EOF' > swho.1
- X.TH SWHO 1 "UofI CSO"
- X.SH NAME
- Xswho \- screen based who
- X.SH SYNOPSIS
- X.B swho
- X[
- X.B \-v
- X]
- X.SH DESCRIPTION
- X.I Swho
- Xis a screen based utility that displays
- X.IR who (1)
- Xinformation using the
- X.IR curses (3)
- Xpackage.
- XSpecifying the
- X.B \-v
- Xflag inhibits the use of standout mode (usually reverse video).
- X.PP
- XEach column displays, in order, the user name, an idle time character,
- Xa tty type character, the last two letters of the tty name, and the
- Xlogin time.
- X.PP
- XIf the tty line is turned off in /etc/ttys, a " \-\-\-\- " is printed
- Xin the user name field.
- X.PP
- XThe idle time character is a '\-' for idle times greater than 30 minutes
- Xbut less than an hour, and a '+' for idle times over an hour.
- X.PP
- XThe tty type character indicates a general class of tty: D for dialup,
- XS for Gandalf Switch, L for LocalNet, T for Telenet, and W for WATS.
- X.SH FILES
- X/etc/utmp, /etc/ttys, /etc/ttytype
- X.SH "SEE ALSO"
- Xwho(1), w(1)
- SHAR_EOF
- exit 0
-
-