|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 6428 (0x191c) Types: TextFile Notes: UNIX file Names: »ac.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─ ⟦this⟧ »cmd/ac.c«
/* * AC * Login connect-time accounting. */ #include <stdio.h> #include <ctype.h> #include <utmp.h> #include <time.h> #define DAYSEC (24*60*60L) /* Seconds in a day */ #define HOUR (60*60) /* Seconds in hour */ char *wtmpf = "/usr/adm/wtmp"; char *months[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", }; char *days[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; char **plist; /* List of do-only people */ typedef struct TERM { struct TERM *t_next; char t_line[8]; char t_name[DIRSIZ]; time_t t_time; } TERM; TERM *terminals; typedef struct PEOPLE { struct PEOPLE *p_next; char p_name[DIRSIZ]; time_t p_time; } PEOPLE; PEOPLE *people; time_t lasttime; /* Last time read from file */ time_t runtotal; /* Running total used by ac -d */ time_t midnight; /* Time of next midnight */ int dflag; /* Daily version (midnight-midnight) */ int pflag; /* Print totals by people */ int badflag; /* Possible bad file format */ main(argc, argv) char *argv[]; { register char *ap; while (argc>1 && *argv[1]=='-') { for (ap = &argv[1][1]; *ap != '\0'; ap++) switch (*ap) { case 'd': dflag = 1; break; case 'p': pflag = 1; break; case 'w': if (argc < 2) usage(); wtmpf = argv[2]; argv++; argc--; break; default: usage(); } argv++; argc--; } plist = argv+1; readwtmp(); print(0); if (badflag) acerr("possible bad file format"); exit(0); } /* * Read through the wtmp file keeping track of * each individual user. At the end either print total * or by individual people. */ readwtmp() { struct utmp ut; register struct tm *tmp; register TERM *tp; register FILE *fp; time_t tdelta; if ((fp = fopen(wtmpf, "r")) == NULL) { fprintf(stderr, "ac: cannot open %s\n", wtmpf); exit(1); } while (fread(&ut, sizeof ut, 1, fp) == 1) { if (dflag && midnight==0) { tmp = localtime(&ut.ut_time); midnight = ut.ut_time - tmp->tm_sec - tmp->tm_min*60 - tmp->tm_hour*60*60L + DAYSEC; } else while (dflag && lasttime>=midnight) { atmidnight(); print(1); midnight += DAYSEC; } if (ut.ut_line[1] == '\0') switch (ut.ut_line[0]) { case '~': /* Reboot */ lasttime = ut.ut_time; logout(NULL); continue; case '|': /* Old time */ tdelta = ut.ut_time; continue; case '}': /* New time */ tdelta = ut.ut_time-tdelta; lasttime = ut.ut_time; for (tp = terminals; tp!=NULL; tp = tp->t_next) tp->t_time += tdelta; continue; } if (ut.ut_time < lasttime) { if (lasttime-ut.ut_time > 60) { badflag++; continue; } ut.ut_time = lasttime; } else lasttime = ut.ut_time; logout(&ut); if (ut.ut_name[0] != '\0') login(&ut); } fclose(fp); time(&lasttime); logout(NULL); } /* * Mark a user as logged out. * The user is given by the tty-name * found in the utmp structure pointer. * If this pointer is NULL, log all users * out (e.g. at reboot and end of file). */ logout(utp) register struct utmp *utp; { register TERM *tp, *ptp; loop: if (terminals == NULL) return; ptp = NULL; for (tp=terminals; tp != NULL; ptp=tp, tp=tp->t_next) if (utp==NULL || strncmp(tp->t_line, utp->ut_line, 8)==0) { if (ptp == NULL) terminals = tp->t_next; else ptp->t_next = tp->t_next; tp->t_time = (utp==NULL ? lasttime : utp->ut_time) - tp->t_time; enter(tp); free((char *)tp); if (utp != NULL) return; goto loop; } } /* * Log the times recorded for the terminals by * midnight of the current day. */ atmidnight() { register TERM *tp; for (tp = terminals; tp != NULL; tp = tp->t_next) { if (tp->t_time < midnight) { tp->t_time = midnight-tp->t_time; enter(tp); tp->t_time = midnight; } } } /* * Mark the user found on this terminal * as logged in. */ login(utp) register struct utmp *utp; { register TERM *tp; register char *np; for (np = utp->ut_name; *np != '\0'; np++) if (!isascii(*np) || !isprint(*np)) { badflag++; lasttime = 0; return; } for (np = utp->ut_line; *np != '\0'; np++) if (!isascii(*np) || (!isalpha(*np) && !isdigit(*np))) { badflag++; lasttime = 0; return; } if (*plist != NULL) { register char **plp; for (plp = plist; *plp != NULL; plp++) if (**plp == *utp->ut_name && strncmp(*plp, utp->ut_name, DIRSIZ)==0) break; if (*plp == NULL) return; } if ((tp = (TERM*)malloc(sizeof(TERM)))==NULL) acerr("Out of mem▶0f◀ory for terminals"); tp->t_time = utp->ut_time; strncpy(tp->t_name, utp->ut_name, DIRSIZ); strncpy(tp->t_line, utp->ut_line, 8); tp->t_next = terminals; terminals = tp; } /* * Enter a terminal node into the people table. */ enter(tp) register TERM *tp; { register PEOPLE *pp; if (tp->t_name[0] == '\0') return; for (pp = people; pp != NULL; pp = pp->p_next) if (strncmp(tp->t_name, pp->p_name, DIRSIZ) == 0) { pp->p_time += tp->t_time; return; } if ((pp = (PEOPLE *)malloc(sizeof(PEOPLE))) == NULL) acerr("Out of memory for people"); pp->p_next = people; people = pp; pp->p_time = tp->t_time; strncpy(pp->p_name, tp->t_name, DIRSIZ); } /* * Print the results, depending on the flags. * The `flag' says whether print is called at the * end (0) or for each midnight-midnight period (1). */ print(flag) int flag; { register struct tm *tmp; register PEOPLE *pp; time_t total = 0; if (dflag) { time_t endofday; endofday = midnight-2*HOUR; tmp = localtime(&endofday); printf("%s %s %d:\n", days[tmp->tm_wday], months[tmp->tm_mon], tmp->tm_mday); } for (pp = people; pp != NULL; pp = pp->p_next) { if (pp->p_time > 0) { total += pp->p_time; if (pflag) prtime(pp->p_name, pp->p_time); } if (flag) pp->p_time = 0; } runtotal += total; prtime("Total:", total); if (dflag) { printf("\n"); if (flag == 0) { dflag = 0; prtime("Total:", runtotal); } } } /* * Print a time entry with a name. */ prtime(name, time) char *name; time_t time; { if (dflag) printf("\t"); printf("%-*.*s", DIRSIZ, DIRSIZ, name); time = (time+30)/60; printf("%3D:%02D\n", time/60, time%60); } /* * Error reporting. */ /* VARARGS */ acerr(x) { fprintf(stderr, "ac: %r\n", &x); exit(1); } usage() { fprintf(stderr, "Usage: ac [-w wtmpfile] [-d] [-p] [username ...]\n"); exit(1); }