home *** CD-ROM | disk | FTP | other *** search
- From: genrad!panda!talcott!elsie!ado
- Subject: ttyuse
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 3, Issue 21
- Submitted by: harvard!seismo!elsie!ado
-
-
- : Run this file through sh, not csh.
- : It contains a manual page and source code for 'ttyuse';
- : you will also need some implementation of 'getopt' on your system.
- : To date, 'ttyuse' has only been used on 4.1bsd and 4.2bsd systems.
- sed 's/^X//' << 'EOF' > ttyuse.n
- X.TH TTYUSE 1
- X.SH NAME
- Xttyuse \- show terminal usage
- X.SH SYNOPSIS
- X.B ttyuse
- X[
- X.B \-l
- X] [
- X.B \-R
- X] [
- X.B \-w
- Xwtmp ]
- X.I time
- X.IR "user " ...
- X.IR "/dev/* " ...
- X.br
- X.BR "ttyuse =" " (to get a `how to use it' message)"
- X.SH DESCRIPTION
- X.I Ttyuse
- Xwrites (to the standard output) a summary of daily terminal usage.
- XIf one or more
- X.IR user s
- Xare named on the command line,
- Xthe report is limited to those users.
- XIf one or more device names are given,
- Xthe report is limited to those devices.
- X(All--and only--command line arguments that begin with
- X.RB ` /dev/ '
- Xare taken to be device names.)
- XAnd if a
- X.I time
- Xargument is given, the report is limited to given date(s); the
- Xtime argument may take these forms:
- X.nf
- X.in +.5i
- X.ta \w'm/d-m/d 'u
- Xm/d a month and day (example: 5/15);
- Xm/d-d a month, starting day, and stopping day;
- Xm/d-m/d starting and stopping months and days;
- Xm/d- starting month and day
- X (the current day is used as the ending day)
- X.fi
- X.in -.5i
- XIn the absence of a
- X.I time
- Xargument,
- Xoutput for the current day is produced.
- X.PP
- XThe leftmost of the 79 columns of output look like this:
- X.in +.5i
- X.nf
- XMon Sep 23 1985
- XTT USE 12-1--2--3--4--5--6--7--8--~--10-11-12-1--
- X01 5.0 Snorri
- X02 8.7 Mark Mark::::::::
- X03 7.7 MRoot::::::::Mar
- X05 0.8 Root
- X07 12. ado ~ Ado:::::::::
- X09 0.4 ~ Ma
- X13 3.9 UU 2U 2U UU22U UU UUUUU UU U2 U UUucUucp::
- X 39.3 < 2>< 1>< 1>< 2>< 5>< 5>< 4>
- X.in -.5i
- X.fi
- XThe first line gives the date the report is for.
- XThe second line provides headings for the lines that follow.
- XIn those following lines, the
- X.RB ` TT '
- Xcolumns give the
- X.IR ps (1)-style
- Xabbreviation of the terminal the line of output is about,
- Xand the
- X.RB ` USE '
- Xcolumns give the total hours of use for the terminal on the
- Xdate the report is for.
- XEach other column represents a twenty-minute time period.
- XA capital letter in one of these columns means that a
- Xuser whose name begins with that letter logged in during
- Xthe time period; the user's name continues in lower case into
- Xfollowing columns for as long as they remain logged in
- X(followed by colons if they stay logged in for a long time).
- XIf more than one login occurs during a time period, the
- Xnumber of logins appears in the time period's column;
- Xan asterisk appears if there were ten or more logins.
- X.PP
- XThe final line for a date's report shows the total
- Xterminal-hours for the day,
- Xand the total number of terminals used during each two-hour period.
- X.PP
- XReboots are shown by a
- X.RB ` ~ '
- Xcharacter in the relevant column of output;
- Xtime changes are shown by a
- X.RB ` | '
- Xcharacter in the `time-changed-from' column and a
- X.RB ` { '
- Xcharacter in the `time-changed-to' column.
- XThese characters appear in the headings line and in lines
- Xof output for terminals that were idle during the time
- Xperiod when the reboot or time change occurred.
- X.PP
- XThe
- X.RB ` USE '
- Xcolumns are absent from reports for days with 25 hours
- X(Daylight Saving Time transition days).
- X.PP
- XThese options are available:
- X.TP
- X.B \-l
- XProduce long lines of output (up to 131 columns) where each column
- Xrepresents twelve minutes. The final line of a date's report
- Xshows the total number of terminals used during each one-hour
- Xperiod.
- X.TP
- X.B \-R
- XInterpret the entire accounting file.
- X.TP
- X.BI "\-w " wtmp
- XUse the file whose name is given by
- X.I wtmp
- Xas the accounting file,
- Xrather than using the default name shown below.
- X.SH FILES
- X/usr/adm/wtmp
- X.SH SEE ALSO
- Xps(1)
- X.. @(#)ttyuse.n 1.1
- EOF
- sed 's/^X//' << 'EOF' > ttyuse.c
- X/*
- X** Still to handle: do days with no logins or logouts but tty use!
- X*/
- X
- X#include "stdio.h"
- X#include "ctype.h"
- X#include "utmp.h"
- X#include "time.h"
- X
- X#ifdef OBJECTID
- Xstatic char sccsid[] = "@(#)ttyuse.c 1.1";
- X#endif
- X
- X#ifdef USG
- X/* Uncompatible Software Glitch */
- X#define index strchr
- X#endif
- X
- X#ifndef TRUE
- X#define TRUE (1)
- X#define FALSE (0)
- X#endif
- X
- X#ifndef arg4alloc
- X#define arg4alloc unsigned
- X#endif
- X
- Xextern char * calloc();
- Xextern char * ctime();
- Xextern char * index();
- Xextern struct tm * localtime();
- Xextern long lseek();
- Xextern char * realloc();
- Xextern char * sprintf();
- Xextern char * strcat();
- Xextern char * strcpy();
- Xextern long time();
- X
- Xstatic long midnight();
- Xstatic long mdy2t();
- X
- X#define MAXDAYHOURS 25
- X#define HOURSLOTS 3
- X#define LONGHOURSLOTS 5
- X
- X#define MINUTE 60
- X#define HOUR (60*MINUTE)
- X
- Xstruct entry {
- X struct utmp u;
- X int marked;
- X int daysecs;
- X char l[MAXDAYHOURS * LONGHOURSLOTS + 1];
- X};
- X
- Xstatic struct entry * entries;
- Xstatic struct entry * ebeyond;
- X
- Xstatic int dayhours;
- Xstatic int dayslots;
- Xstatic int hourslots;
- X
- X#define NAMESIZE (sizeof entries[0].u.ut_name)
- X#define LINESIZE (sizeof entries[0].u.ut_line)
- X#define namecmp(name1, name2) strncmp(name1, name2, NAMESIZE)
- X#define linecmp(line1, line2) strncmp(line1, line2, LINESIZE)
- X#define namecpy(to, from) strncpy(to, from, NAMESIZE)
- X#define linecpy(to, from) strncpy(to, from, LINESIZE)
- X
- X#define BOOTCHAR '~'
- X#define OLDTCHAR '|'
- X/*
- X** 4.[12]bsd writes '{' to the file, but the documentation says that '}' is
- X** the character. We'll take either.
- X**
- X** System V does things differently, of course.
- X*/
- X#define NEWTCHAR '{'
- X#define OTHTCHAR '}'
- X
- X#define BOOTLINE(s) (*(s) == BOOTCHAR && (s)[1] == '\0' || \
- X strcmp((s), "reboot") == 0)
- X#define OLDTLINE(s) (*(s) == OLDTCHAR && (s)[1] == '\0' || \
- X strncmp((s), "old time", 8) == 0)
- X#define NEWTLINE(s) (*(s) == NEWTCHAR && (s)[1] == '\0' || \
- X *(s) == OTHTCHAR && (s)[1] == '\0' || \
- X strncmp((s), "new time", 8) == 0)
- X#define TIMELINE(s) (OLDTLINE(s) || NEWTLINE(s))
- X#define SPCLLINE(s) (TIMELINE(s) || BOOTLINE(s))
- X
- Xstatic struct entry *
- Xlookup(up, doenter)
- Xregister struct utmp * up;
- X{
- X register struct entry * ep;
- X register char * cp;
- X register int i;
- X
- X cp = up->ut_line;
- X if (SPCLLINE(cp))
- X return NULL;
- X for (ep = entries; ep < ebeyond; ++ep)
- X if (linecmp(cp, ep->u.ut_line) == 0)
- X return ep;
- X if (!doenter)
- X return NULL;
- X i = ebeyond - entries;
- X if (i == 0)
- X ep = (struct entry *) calloc(1, sizeof *ep);
- X else ep = (struct entry *) realloc((char *) entries,
- X (arg4alloc) ((i + 1) * sizeof *ep));
- X if (ep == NULL)
- X for ( ; ; )
- X wildrexit("alloc");
- X entries = ep;
- X ebeyond = ep + i + 1;
- X ep = ebeyond - 1;
- X (void) linecpy(ep->u.ut_line, up->ut_line);
- X (void) sprintf(ep->l, "%*s", dayslots, "");
- X ep->u.ut_time = 0;
- X ep->u.ut_name[0] = '\0';
- X ep->marked = FALSE;
- X ep->daysecs = 0;
- X return ep;
- X}
- X
- Xstatic char headline[MAXDAYHOURS * LONGHOURSLOTS + 1];
- X
- Xstatic int lflag; /* long lines */
- Xstatic char * wname = "/usr/adm/wtmp";
- X
- Xstatic char * name;
- X
- Xstatic char ** argusers;
- Xstatic int cntusers;
- X
- Xstatic long starttime;
- Xstatic long stoptime;
- X
- Xstatic
- Xdodate(string)
- Xregister char * string;
- X{
- X struct tm local;
- X int bmon, bday, byear, emon, eday, eyear, i;
- X long now;
- X char c;
- X
- X (void) time(&now);
- X local = *localtime(&now);
- X c = '\0';
- X i = sscanf(string, "%d/%d-%d/%d%c", &bmon, &bday, &emon, &eday, &c);
- X if (i != 4 || c != '\0') {
- X c = '\0';
- X i = sscanf(string, "%d/%d-%d%c", &bmon, &bday, &eday, &c);
- X if (i == 3 && c == '\0') {
- X emon = bmon;
- X if (bday > eday)
- X for ( ; ; )
- X wildexit("date");
- X } else {
- X c = '\0';
- X i = sscanf(string, "%d/%d%c", &bmon, &bday, &c);
- X if (i == 2 && c == '\0') {
- X emon = bmon;
- X eday = bday;
- X } else {
- X c = '\0';
- X i = sscanf(string, "%d/%d-%c",
- X &bmon, &bday, &c);
- X if (i == 2 && c == '\0') {
- X emon = local.tm_mon + 1;
- X eday = local.tm_mday;
- X } else for ( ; ; )
- X wildexit("date");
- X }
- X }
- X }
- X byear = eyear = local.tm_year + 1900;
- X if (bmon > emon || bmon == emon && bday > eday)
- X --byear;
- X starttime = mdy2t(bmon, bday, byear);
- X stoptime = mdy2t(emon, eday, eyear);
- X}
- X
- Xstatic char *
- Xttyabbr(string)
- Xregister char * string;
- X{
- X static char buf[3];
- X
- X if (strncmp(string, "tty", 3) == 0)
- X (void) strncpy(buf, string + 3, 2);
- X else (void) strncpy(buf, string, 2);
- X buf[2] = '\0';
- X return buf;
- X}
- X
- Xstatic struct utmp * utmp;
- Xstatic struct utmp * ubeyond;
- Xstatic struct utmp * unext;
- Xstatic struct utmp * ubase;
- X
- Xstatic int
- Xqtime(up1, up2)
- Xchar * up1;
- Xchar * up2;
- X{
- X register long diff;
- X
- X diff = ((struct utmp *) up1)->ut_time - ((struct utmp *) up2)->ut_time;
- X if (diff == 0)
- X return 0;
- X else if (diff > 0)
- X return 1;
- X else return -1;
- X}
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar * argv[];
- X{
- X register FILE * fp;
- X register struct entry * ep;
- X register int i;
- X register long t;
- X register long lastm, m;
- X register int slot;
- X register int didttys;
- X register long filesize;
- X static int Rflag;
- X static int diddate;
- X char buf[134];
- X extern int optind;
- X extern char * optarg;
- X
- X for (name = argv[0]; *name != '\0'; ++name)
- X if (name[0] == '/' && name[1] != '\0' && name[1] != '/')
- X argv[0] = ++name;
- X name = argv[0];
- X if (argc == 2 && strcmp(argv[1], "=") == 0) {
- X (void) printf(
- X"%s: usage is %s [-lR] [-w wtmp] [m/d[-[[m/]d]]] [user...] [/dev/*...]\n",
- X name, name);
- X for ( ; ; )
- X exit(1);
- X }
- X while ((i = getopt(argc, argv, "lRw:")) != EOF)
- X switch (i) {
- X case 'l':
- X lflag = TRUE;
- X break;
- X case 'R':
- X Rflag = TRUE;
- X starttime = 0;
- X (void) time(&stoptime);
- X break;
- X case 'w':
- X wname = optarg;
- X break;
- X default:
- X for ( ; ; )
- X wildexit("usage");
- X }
- X hourslots = lflag ? LONGHOURSLOTS : HOURSLOTS;
- X /*
- X ** Parse arguments
- X */
- X i = (argc - optind) + 1;
- X argusers = (char **) calloc((arg4alloc) i, sizeof *argusers);
- X if (argusers == NULL)
- X for ( ; ; )
- X wildrexit("calloc");
- X cntusers = 0;
- X for (i = optind; i < argc; ++i)
- X if (strncmp(argv[i], "/dev/", 5) == 0) {
- X struct utmp fake;
- X
- X (void) linecpy(fake.ut_line, &argv[i][5]);
- X (void) namecpy(fake.ut_name, "fake");
- X if (lookup(&fake, FALSE) != NULL)
- X for ( ; ; )
- X wildrexit("duplicate /dev argument");
- X if (lookup(&fake, TRUE) == NULL) /* "cannot happen */
- X for ( ; ; )
- X wildrexit("lookup");
- X } else if (index(argv[i], '/') == 0)
- X argusers[cntusers++] = argv[i];
- X else if (Rflag)
- X for ( ; ; )
- X wildexit("combination of date and -R");
- X else if (diddate)
- X for ( ; ; )
- X wildexit("multiple dates");
- X else {
- X dodate(argv[i]);
- X diddate = TRUE;
- X }
- X argusers[cntusers] = NULL;
- X didttys = entries != NULL;
- X if (!Rflag && !diddate) {
- X (void) time(&starttime);
- X stoptime = starttime;
- X }
- X starttime = midnight(starttime);
- X stoptime = midnight(stoptime);
- X stoptime = midnight(stoptime + MAXDAYHOURS * HOUR);
- X /*
- X ** And now the real work begins.
- X */
- X if ((fp = fopen(wname, "r")) == NULL)
- X for ( ; ; )
- X wildrexit("opening wtmp");
- X (void) fseek(fp, 0L, 2);
- X filesize = ftell(fp);
- X if (filesize == 0)
- X for ( ; ; )
- X tameexit();
- X if (filesize < 0 || (filesize % sizeof *utmp) != 0)
- X for ( ; ; )
- X wildexit("wtmp size");
- X i = filesize / sizeof *utmp;
- X utmp = (struct utmp *) calloc((arg4alloc) i, sizeof *utmp);
- X if (utmp == NULL)
- X for ( ; ; )
- X wildrexit("calloc");
- X ubeyond = utmp + i;
- X /*
- X ** Step 1--read it in.
- X */
- X#ifdef fileno
- X (void) lseek(fileno(fp), 0L, 0);
- X i = read(fileno(fp), (char *) utmp, (int) filesize);
- X#endif
- X#ifndef fileno
- X (void) fseek(fp, 0L, 0);
- X i = fread((char *) utmp, sizeof *utmp, (int) i, fp) * sizeof *utmp);
- X#endif
- X if (i != filesize || ferror(fp) || fclose(fp))
- X for ( ; ; )
- X wildrexit("reading wtmp");
- X /*
- X ** Step 2--eliminate records up to and including last reboot before
- X ** start time.
- X */
- X for (unext = utmp; unext<ubeyond && unext->ut_time<starttime; ++unext)
- X if (BOOTLINE(unext->ut_line))
- X utmp = unext + 1;
- X /*
- X ** Step 3--eliminate trailing records for times past stoptime.
- X */
- X while ((ubeyond - 1) > utmp && (ubeyond - 1)->ut_time >= stoptime)
- X --ubeyond;
- X /*
- X ** Step 4--eliminate bogus records.
- X */
- X for (unext = ubase = utmp; unext < ubeyond; ++unext)
- X if (unext->ut_time == 0 || unext->ut_line[0] == '\0')
- X continue;
- X else if (ubase == unext)
- X ++ubase;
- X else *ubase++ = *unext;
- X /*
- X ** Step 5--eliminate leading logouts, reboots, and time changes.
- X */
- X while (utmp < ubeyond && SPCLLINE(utmp->ut_line))
- X ++utmp;
- X /*
- X ** Step 6--eliminate trailing reboots and time changes.
- X */
- X while ((ubeyond - 1) > utmp && SPCLLINE((ubeyond - 1)->ut_line))
- X --ubeyond;
- X /*
- X ** Step 7--if ttys were specified, eliminate records for other ttys.
- X */
- X if (didttys)
- X for (ubase = unext = utmp; unext < ubeyond; ++unext)
- X if (SPCLLINE(unext->ut_line) ||
- X lookup(unext, FALSE) != NULL)
- X if (ubase == unext)
- X ++ubase;
- X else *ubase++ = *unext;
- X /*
- X ** Final step--sort records between time changes.
- X */
- X for (ubase = unext = utmp; unext < ubeyond; ++unext)
- X if (TIMELINE(unext->ut_line)) {
- X if (unext != ubase)
- X (void) qsort((char *) ubase, unext - ubase,
- X sizeof *ubase, qtime);
- X ubase = unext + 1;
- X }
- X if (ubeyond > ubase)
- X (void) qsort((char *) ubase, ubeyond - ubase,
- X sizeof *ubase, qtime);
- X if (Rflag)
- X unext = utmp;
- X else {
- X /*
- X ** Find first record that's for after the start time.
- X */
- X for (unext = utmp; unext < ubeyond; ++unext)
- X if (unext->ut_time >= starttime)
- X break;
- X if (unext >= ubeyond) /* easy enough! */
- X for ( ; ; )
- X tameexit();
- X ubase = unext;
- X /*
- X ** Scan back to a reboot or to the first record
- X ** (or, if we didttys, until all ttys are accounted for).
- X */
- X for ( ; unext > utmp; --unext) {
- X if (BOOTLINE(unext->ut_line))
- X break;
- X if ((ep = lookup(unext, !didttys)) == NULL)
- X continue;
- X if (ep->marked)
- X continue;
- X ep->marked = TRUE;
- X (void) namecpy(ep->u.ut_name, unext->ut_name);
- X if (didttys) {
- X for (ep = entries; ep < ebeyond; ++ep)
- X if (!ep->marked)
- X break;
- X if (ep >= ebeyond)
- X break;
- X }
- X }
- X /*
- X ** If users were specified, zap the records for anybody else.
- X */
- X if (cntusers > 0)
- X for (ep = entries; ep < ebeyond; ++ep) {
- X for (i = 0; i < cntusers; ++i)
- X if (namecmp(argusers[i],
- X ep->u.ut_name) == 0)
- X break;
- X if (i >= cntusers)
- X ep->u.ut_name[0] = '\0';
- X }
- X /*
- X ** We're ready!
- X */
- X utmp = unext = ubase;
- X }
- X lastm = starttime - 1;
- X for ( ; unext < ubeyond; ++unext, lastm = m) {
- X t = unext->ut_time;
- X m = midnight(t);
- X if (m != lastm) {
- X if (lastm >= starttime && lastm < stoptime) {
- X for (ep = entries; ep < ebeyond; ++ep) {
- X if (ep->u.ut_name[0] == '\0')
- X continue;
- X ep->daysecs += (lastm + dayhours *
- X HOUR) - ep->u.ut_time;
- X if (ep->daysecs == 0)
- X ++(ep->daysecs);
- X colonize(ep->l, dayslots - 1);
- X }
- X dump(lastm);
- X }
- X newday(m, 0L, '\0');
- X }
- X slot = (unext->ut_time - m) / (HOUR / hourslots);
- X if (BOOTLINE(unext->ut_line)) {
- X headline[slot] = BOOTCHAR;
- X for (ep = entries; ep < ebeyond; ++ep) {
- X if (ep->u.ut_name[0] != '\0') {
- X ep->daysecs += unext->ut_time -
- X ep->u.ut_time;
- X if (ep->daysecs == 0)
- X ++(ep->daysecs);
- X colonize(ep->l, slot);
- X ep->u.ut_name[0] = '\0';
- X ep->u.ut_time = 0;
- X }
- X }
- X continue;
- X }
- X if (NEWTLINE(unext->ut_line))
- X for ( ; ; )
- X wildexit("new time without old time");
- X if (OLDTLINE(unext->ut_line)) {
- X if (unext == ubeyond || !NEWTLINE((unext + 1)->ut_line))
- X for ( ; ; )
- X wildexit("old time without new time");
- X headline[slot] = OLDTCHAR;
- X for (ep = entries; ep < ebeyond; ++ep) {
- X if (ep->u.ut_name[0] == '\0')
- X ep->l[slot] = OLDTCHAR;
- X else {
- X ep->daysecs += unext->ut_time -
- X ep->u.ut_time;
- X if (ep->daysecs == 0)
- X ++(ep->daysecs);
- X colonize(ep->l, slot);
- X }
- X }
- X dump(lastm);
- X ++unext;
- X if (unext->ut_line[0] == NEWTCHAR ||
- X unext->ut_line[0] == OTHTCHAR)
- X newday(m, unext->ut_time,
- X unext->ut_line[0]);
- X else newday(m, unext->ut_time, NEWTCHAR);
- X continue;
- X }
- X if ((ep = lookup(unext, !didttys)) == NULL)
- X continue;
- X /*
- X ** If a login is in progress, either a login or
- X ** logout terminates it.
- X */
- X if (ep->u.ut_name[0] != '\0') {
- X ep->daysecs += unext->ut_time - ep->u.ut_time;
- X if (ep->daysecs == 0)
- X ++(ep->daysecs);
- X colonize(ep->l, slot);
- X ep->u.ut_name[0] = '\0';
- X ep->u.ut_time = 0;
- X }
- X if (unext->ut_name[0] == '\0')
- X continue;
- X if (cntusers > 0) {
- X for (i = 0; i < cntusers; ++i)
- X if (namecmp(argusers[i], unext->ut_name) == 0)
- X break;
- X if (i == cntusers)
- X continue;
- X }
- X ep->u.ut_time = unext->ut_time;
- X if (isupper(ep->l[slot])) {
- X buf[0] = '2';
- X i = 1;
- X } else {
- X register char * cp;
- X
- X cp = index("23456789**", ep->l[slot]);
- X if (cp != 0) {
- X buf[0] = *(cp + 1);
- X i = 1;
- X } else i = 0;
- X }
- X fudge(unext->ut_name);
- X (void) namecpy(ep->u.ut_name, unext->ut_name);
- X (void) namecpy(&buf[i], unext->ut_name);
- X /*
- X ** Ensure termination.
- X */
- X buf[NAMESIZE + i] = '\0';
- X if (i == 0 && islower(buf[0]))
- X buf[0] = toupper(buf[0]);
- X i = strlen(buf);
- X if (i > (dayslots - slot))
- X i = dayslots - slot;
- X (void) strncpy(&ep->l[slot], buf, i);
- X }
- X for (ep = entries; ep < ebeyond; ++ep) {
- X if (ep->u.ut_name[0] == '\0')
- X continue;
- X ep->daysecs += t - ep->u.ut_time;
- X if (ep->daysecs == 0)
- X ++(ep->daysecs);
- X colonize(ep->l, slot);
- X }
- X dump(lastm);
- X for ( ; ; )
- X tameexit();
- X}
- X
- Xstatic int
- Xqline(ep1, ep2)
- Xchar * ep1;
- Xchar * ep2;
- X{
- X return linecmp(((struct entry *) ep1)->u.ut_line,
- X ((struct entry *) ep2)->u.ut_line);
- X}
- X
- Xstatic int
- Xttysused(base, count)
- Xregister int base;
- Xregister int count;
- X{
- X register struct entry * ep;
- X register int i;
- X register int result;
- X
- X result = 0;
- X for (ep = entries; ep < ebeyond; ++ep)
- X for (i = 0; i < count; ++i) {
- X switch (ep->l[base + i]) {
- X case ' ':
- X case BOOTCHAR:
- X case OLDTCHAR:
- X case NEWTCHAR:
- X case OTHTCHAR:
- X continue;
- X }
- X ++result;
- X break;
- X }
- X return result;
- X}
- X
- Xstatic
- Xdump(m)
- Xlong m; /* midnight */
- X{
- X register struct entry * ep;
- X register char * cp;
- X register int i, j, k, lines;
- X register int width, prec;
- X register double d;
- X struct tm tm;
- X long grandtot;
- X char buf[20];
- X
- X tm = *localtime(&m);
- X grandtot = 0;
- X for (ep = entries; ep < ebeyond; ++ep)
- X grandtot += ep->daysecs;
- X if (grandtot == 0)
- X return;
- X (void) qsort((char *) entries, ebeyond - entries,
- X sizeof entries[0], qline);
- X lines = 0;
- X width = (lflag ? 131 : 79) - dayslots;
- X prec = (width >= 7) ? width : 3;
- X for (ep = entries; ep < ebeyond; ++ep) {
- X if (ep->daysecs == 0)
- X continue;
- X if (lines == 0) {
- X cp = ctime(&m);
- X (void) printf("%.11s%s", cp, cp + 20);
- X (void) printf("%-*.*s", width, prec, "TT USE");
- X (void) puts(headline);
- X }
- X d = ep->daysecs / (double) HOUR;
- X (void) sprintf(buf, "%2.2s%4.1f", ttyabbr(ep->u.ut_line), d);
- X if (buf[2] != ' ')
- X (void) sprintf(buf, "%2.2s%4.0f",
- X ttyabbr(ep->u.ut_line), d);
- X (void) printf("%-*.*s", width, prec, buf);
- X for (i = 0; i < dayslots; ++i)
- X if (headline[i] == BOOTCHAR && ep->l[i] == ' ')
- X ep->l[i] = BOOTCHAR;
- X cp = ep->l + dayslots;
- X while (cp > ep->l && *(cp - 1) == ' ')
- X --cp;
- X (void) printf("%.*s\n", cp - ep->l, ep->l);
- X ++lines;
- X }
- X if (lines <= 1)
- X return;
- X if (prec > 6)
- X (void) sprintf(buf, "%6.1f", grandtot / (double) HOUR);
- X else buf[0] = '\0';
- X (void) printf("%-*.*s", width, prec, buf);
- X for (i = 0; i < dayslots; i += j) {
- X j = lflag ? hourslots : (2 * hourslots);
- X if (i == 0 && (dayslots % j) != 0)
- X j += dayslots % j;
- X if ((k = ttysused(i, j)) == 0)
- X (void) printf("%*s", j, "");
- X else (void) printf("<%*d>", j - 2, k);
- X }
- X (void) printf("\n");
- X}
- X
- Xstatic
- Xcolonize(line, slot)
- Xregister char * line;
- Xregister int slot;
- X{
- X register int i;
- X
- X for (i = slot + 1; i < dayslots && line[slot] != ' '; ++i)
- X line[i] = ' ';
- X while (slot >= 0 && line[slot] == ' ') {
- X line[slot] = ':';
- X --slot;
- X }
- X}
- X
- Xstatic
- Xwildrexit(string)
- Xchar * string;
- X{
- X (void) fprintf(stderr, "%s: wild result from %s\n", name, string);
- X for ( ; ; )
- X exit(1);
- X}
- X
- Xstatic
- Xwildexit(string)
- Xchar * string;
- X{
- X (void) fprintf(stderr, "%s: wild %s\n", name, string);
- X for ( ; ; )
- X exit(1);
- X}
- X
- Xstatic
- Xtameexit()
- X{
- X for ( ; ; )
- X exit(0);
- X}
- X
- Xstatic
- Xfudge(buf)
- Xregister char * buf;
- X{
- X register int i;
- X
- X for (i = 0; i < NAMESIZE; ++i)
- X switch (buf[i]) {
- X case '\0':
- X return;
- X case BOOTCHAR:
- X case OLDTCHAR:
- X case NEWTCHAR:
- X case OTHTCHAR:
- X case ':':
- X case '*':
- X case ' ':
- X case '2': case '3': case '4': case '5':
- X case '6': case '7': case '8': case '9':
- X buf[i] = '?';
- X break;
- X default:
- X if (!isascii(buf[i]))
- X buf[i] = '?';
- X else if (isupper(buf[i]))
- X buf[i] = tolower(buf[i]);
- X else if (!isprint(buf[i]))
- X buf[i] = '?';
- X break;
- X }
- X}
- X
- Xstatic long
- Xmdy2t(m, d, y)
- X{
- X register struct tm * tmp;
- X register int diff;
- X register int lastdiff;
- X long guess;
- X
- X if (y < 1969 || m <= 0 || m > 12 || d <= 0 || d >= 32)
- X for ( ; ; )
- X wildrexit("date");
- X guess = d + (m - 1) * (365.25 / 12.) + (y - 1970) * 365.25;
- X guess = guess * HOUR * 24;
- X y -= 1900;
- X --m;
- X lastdiff = 0;
- X for ( ; ; ) {
- X tmp = localtime(&guess);
- X if ((diff = tmp->tm_year - y) == 0 &&
- X (diff = tmp->tm_mon - m) == 0)
- X diff = tmp->tm_mday - d;
- X if (diff == 0)
- X return midnight(guess);
- X if (lastdiff != 0)
- X if ((diff > 0) != (lastdiff > 0))
- X for ( ; ; )
- X wildrexit("date");
- X if (diff > 0)
- X guess -= 12 * HOUR;
- X else guess += 12 * HOUR;
- X lastdiff = diff;
- X }
- X}
- X
- Xstatic long
- Xmidnight(t)
- Xlong t;
- X{
- X register int diff, lastdiff;
- X struct tm tm;
- X struct tm mtm;
- X long m;
- X
- X tm = *localtime(&t);
- X if (tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0)
- X return t;
- X m = t;
- X m -= tm.tm_hour * HOUR;
- X m -= tm.tm_min * MINUTE;
- X m -= tm.tm_sec;
- X lastdiff = 0;
- X for ( ; ; ) {
- X mtm = *localtime(&m);
- X if ((diff = mtm.tm_year - tm.tm_year) == 0 &&
- X (diff = mtm.tm_mon - tm.tm_mon) == 0 &&
- X (diff = mtm.tm_mday - tm.tm_mday) == 0 &&
- X (diff = mtm.tm_hour) == 0)
- X if (mtm.tm_min == 0 && mtm.tm_sec == 0)
- X return m;
- X else for ( ; ; )
- X wildrexit("finding midnight");
- X if (lastdiff != 0)
- X if ((diff > 0) != (lastdiff > 0))
- X for ( ; ; )
- X wildrexit("finding midnight");
- X if (diff > 0)
- X m -= HOUR;
- X else m += HOUR;
- X lastdiff = diff;
- X }
- X}
- X
- Xstatic
- Xnewday(m, t, headchar)
- Xlong m, t;
- X{
- X register struct entry * ep;
- X register int i, j, slot;
- X long t2;
- X char buf[20];
- X
- X dayhours = (midnight(m + MAXDAYHOURS * HOUR) - m) / HOUR;
- X if (dayhours <= 0 || dayhours > MAXDAYHOURS)
- X for ( ; ; )
- X wildexit("number of hours in a day");
- X dayslots = hourslots * dayhours;
- X headline[0] = '\0';
- X for (i = 0; i < dayhours; ++i) {
- X if (dayhours == 24)
- X j = i;
- X else {
- X t2 = m + i * HOUR;
- X j = localtime(&t2)->tm_hour;
- X }
- X if ((j %= 12) == 0)
- X j = 12;
- X if (j == 12 && lflag)
- X if (i == 0)
- X (void) strcpy(buf, "Mid.-");
- X else (void) strcpy(buf, "Noon-");
- X else (void) sprintf(buf, "%d-----", j);
- X buf[hourslots] = '\0';
- X (void) strcat(headline, buf);
- X }
- X if (t == 0)
- X slot = 0;
- X else {
- X slot = (t - m) / (HOUR / hourslots);
- X headline[slot] = headchar;
- X }
- X for (ep = entries; ep < ebeyond; ++ep) {
- X (void) sprintf(ep->l, "%*s", dayslots, "");
- X ep->daysecs = 0;
- X if (ep->u.ut_name[0] == '\0') {
- X ep->u.ut_time = 0;
- X if (t != 0)
- X ep->l[slot] = headchar;
- X } else {
- X ep->u.ut_time = (t == 0) ? m : t;
- X for (i = 0; i < NAMESIZE; ++i) {
- X if (ep->u.ut_name[i] == '\0')
- X break;
- X if ((slot + i) >= dayslots)
- X break;
- X ep->l[slot + i] = ep->u.ut_name[i];
- X }
- X }
- X }
- X}
- EOF
- exit
-
-
-