Annotation of coherent/d/bin/ac.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * AC
        !             3:  * Login connect-time accounting.
        !             4:  */
        !             5: 
        !             6: #include <stdio.h>
        !             7: #include <ctype.h>
        !             8: #include <utmp.h>
        !             9: #include <time.h>
        !            10: 
        !            11: #define        DAYSEC  (24*60*60L)             /* Seconds in a day */
        !            12: #define        HOUR    (60*60)                 /* Seconds in hour */
        !            13: 
        !            14: char   *wtmpf = "/usr/adm/wtmp";
        !            15: char   *months[] = {
        !            16:        "January", "February", "March", "April", "May", "June",
        !            17:        "July", "August", "September", "October", "November", "December",
        !            18: };
        !            19: 
        !            20: char   *days[] = {
        !            21:        "Sunday", "Monday", "Tuesday", "Wednesday",
        !            22:        "Thursday", "Friday", "Saturday"
        !            23: };
        !            24: char   **plist;                        /* List of do-only people */
        !            25: 
        !            26: typedef        struct TERM {
        !            27:        struct TERM     *t_next;
        !            28:        char    t_line[8];
        !            29:        char    t_name[DIRSIZ];
        !            30:        time_t  t_time;
        !            31: }      TERM;
        !            32: 
        !            33: TERM   *terminals;
        !            34: 
        !            35: typedef        struct PEOPLE {
        !            36:        struct PEOPLE   *p_next;
        !            37:        char    p_name[DIRSIZ];
        !            38:        time_t  p_time;
        !            39: }      PEOPLE;
        !            40: 
        !            41: PEOPLE *people;
        !            42: 
        !            43: time_t lasttime;               /* Last time read from file */
        !            44: time_t runtotal;               /* Running total used by ac -d */
        !            45: time_t midnight;               /* Time of next midnight */
        !            46: 
        !            47: int    dflag;                  /* Daily version (midnight-midnight) */
        !            48: int    pflag;                  /* Print totals by people */
        !            49: int    badflag;                /* Possible bad file format */
        !            50: 
        !            51: main(argc, argv)
        !            52: char *argv[];
        !            53: {
        !            54:        register char *ap;
        !            55: 
        !            56:        while (argc>1 && *argv[1]=='-') {
        !            57:                for (ap = &argv[1][1]; *ap != '\0'; ap++)
        !            58:                        switch (*ap) {
        !            59:                        case 'd':
        !            60:                                dflag = 1;
        !            61:                                break;
        !            62: 
        !            63:                        case 'p':
        !            64:                                pflag = 1;
        !            65:                                break;
        !            66: 
        !            67: 
        !            68:                        case 'w':
        !            69:                                if (argc < 2)
        !            70:                                        usage();
        !            71:                                wtmpf = argv[2];
        !            72:                                argv++;
        !            73:                                argc--;
        !            74:                                break;
        !            75: 
        !            76:                        default:
        !            77:                                usage();
        !            78:                        }
        !            79:                argv++;
        !            80:                argc--;
        !            81:        }
        !            82:        plist = argv+1;
        !            83:        readwtmp();
        !            84:        print(0);
        !            85:        if (badflag)
        !            86:                acerr("possible bad file format");
        !            87:        exit(0);
        !            88: }
        !            89: 
        !            90: /*
        !            91:  * Read through the wtmp file keeping track of
        !            92:  * each individual user.  At the end either print total
        !            93:  * or by individual people.
        !            94:  */
        !            95: readwtmp()
        !            96: {
        !            97:        struct utmp ut;
        !            98:        register struct tm *tmp;
        !            99:        register TERM *tp;
        !           100:        register FILE *fp;
        !           101:        time_t tdelta;
        !           102: 
        !           103:        if ((fp = fopen(wtmpf, "r")) == NULL) {
        !           104:                fprintf(stderr, "ac: cannot open %s\n", wtmpf);
        !           105:                exit(1);
        !           106:        }
        !           107:        while (fread(&ut, sizeof ut, 1, fp) == 1) {
        !           108:                if (dflag && midnight==0) {
        !           109:                        tmp = localtime(&ut.ut_time);
        !           110:                        midnight = ut.ut_time - tmp->tm_sec
        !           111:                            - tmp->tm_min*60 - tmp->tm_hour*60*60L + DAYSEC;
        !           112:                } else while (dflag && lasttime>=midnight) {
        !           113:                        atmidnight();
        !           114:                        print(1);
        !           115:                        midnight += DAYSEC;
        !           116:                }
        !           117:                if (ut.ut_line[1] == '\0')
        !           118:                        switch (ut.ut_line[0]) {
        !           119:                        case '~':               /* Reboot */
        !           120:                                lasttime = ut.ut_time;
        !           121:                                logout(NULL);
        !           122:                                continue;
        !           123: 
        !           124:                        case '|':               /* Old time */
        !           125:                                tdelta = ut.ut_time;
        !           126:                                continue;
        !           127: 
        !           128:                        case '}':               /* New time */
        !           129:                                tdelta = ut.ut_time-tdelta;
        !           130:                                lasttime = ut.ut_time;
        !           131:                                for (tp = terminals; tp!=NULL; tp = tp->t_next)
        !           132:                                        tp->t_time += tdelta;
        !           133:                                continue;
        !           134:                        }
        !           135:                if (ut.ut_time < lasttime) {
        !           136:                        if (lasttime-ut.ut_time > 60) {
        !           137:                                badflag++;
        !           138:                                continue;
        !           139:                        }
        !           140:                        ut.ut_time = lasttime;
        !           141:                } else
        !           142:                        lasttime = ut.ut_time;
        !           143:                logout(&ut);
        !           144:                if (ut.ut_name[0] != '\0')
        !           145:                        login(&ut);
        !           146:        }
        !           147:        fclose(fp);
        !           148:        time(&lasttime);
        !           149:        logout(NULL);
        !           150: }
        !           151: 
        !           152: /*
        !           153:  * Mark a user as logged out.
        !           154:  * The user is given by the tty-name
        !           155:  * found in the utmp structure pointer.
        !           156:  * If this pointer is NULL, log all users
        !           157:  * out (e.g. at reboot and end of file).
        !           158:  */
        !           159: logout(utp)
        !           160: register struct utmp *utp;
        !           161: {
        !           162:        register TERM *tp, *ptp;
        !           163: 
        !           164: loop:
        !           165:        if (terminals == NULL)
        !           166:                return;
        !           167:        ptp = NULL;
        !           168:        for (tp=terminals; tp != NULL; ptp=tp, tp=tp->t_next)
        !           169:                if (utp==NULL || strncmp(tp->t_line, utp->ut_line, 8)==0) {
        !           170:                        if (ptp == NULL)
        !           171:                                terminals = tp->t_next; else
        !           172:                                ptp->t_next = tp->t_next;
        !           173:                        tp->t_time = (utp==NULL ? lasttime : utp->ut_time)
        !           174:                            - tp->t_time;
        !           175:                        enter(tp);
        !           176:                        free((char *)tp);
        !           177:                        if (utp != NULL)
        !           178:                                return;
        !           179:                        goto loop;
        !           180:                }
        !           181: }
        !           182: 
        !           183: /*
        !           184:  * Log the times recorded for the terminals by
        !           185:  * midnight of the current day.
        !           186:  */
        !           187: atmidnight()
        !           188: {
        !           189:        register TERM *tp;
        !           190: 
        !           191:        for (tp = terminals; tp != NULL; tp = tp->t_next) {
        !           192:                if (tp->t_time < midnight) {
        !           193:                        tp->t_time = midnight-tp->t_time;
        !           194:                        enter(tp);
        !           195:                        tp->t_time = midnight;
        !           196:                }
        !           197:        }
        !           198: }
        !           199: 
        !           200: /*
        !           201:  * Mark the user found on this terminal
        !           202:  * as logged in.
        !           203:  */
        !           204: login(utp)
        !           205: register struct utmp *utp;
        !           206: {
        !           207:        register TERM *tp;
        !           208:        register char *np;
        !           209: 
        !           210:        for (np = utp->ut_name; *np != '\0'; np++)
        !           211:                if (!isascii(*np) || !isprint(*np)) {
        !           212:                        badflag++;
        !           213:                        lasttime = 0;
        !           214:                        return;
        !           215:                }
        !           216:        for (np = utp->ut_line; *np != '\0'; np++)
        !           217:                if (!isascii(*np) || (!isalpha(*np) && !isdigit(*np))) {
        !           218:                        badflag++;
        !           219:                        lasttime = 0;
        !           220:                        return;
        !           221:                }
        !           222:        if (*plist != NULL) {
        !           223:                register char **plp;
        !           224: 
        !           225:                for (plp = plist; *plp != NULL; plp++)
        !           226:                        if (**plp == *utp->ut_name
        !           227:                             && strncmp(*plp, utp->ut_name, DIRSIZ)==0)
        !           228:                                break;
        !           229:                if (*plp == NULL)
        !           230:                        return;
        !           231:        }
        !           232:        if ((tp = (TERM*)malloc(sizeof(TERM)))==NULL)
        !           233:                acerr("Out of memory for terminals");
        !           234:        tp->t_time = utp->ut_time;
        !           235:        strncpy(tp->t_name, utp->ut_name, DIRSIZ);
        !           236:        strncpy(tp->t_line, utp->ut_line, 8);
        !           237:        tp->t_next = terminals;
        !           238:        terminals = tp;
        !           239: }
        !           240: 
        !           241: /*
        !           242:  * Enter a terminal node into the people table.
        !           243:  */
        !           244: enter(tp)
        !           245: register TERM *tp;
        !           246: {
        !           247:        register PEOPLE *pp;
        !           248: 
        !           249:        if (tp->t_name[0] == '\0')
        !           250:                return;
        !           251:        for (pp = people; pp != NULL; pp = pp->p_next)
        !           252:                if (strncmp(tp->t_name, pp->p_name, DIRSIZ) == 0) {
        !           253:                        pp->p_time += tp->t_time;
        !           254:                        return;
        !           255:                }
        !           256:        if ((pp = (PEOPLE *)malloc(sizeof(PEOPLE))) == NULL)
        !           257:                acerr("Out of memory for people");
        !           258:        pp->p_next = people;
        !           259:        people = pp;
        !           260:        pp->p_time = tp->t_time;
        !           261:        strncpy(pp->p_name, tp->t_name, DIRSIZ);
        !           262: }
        !           263: 
        !           264: /*
        !           265:  * Print the results, depending on the flags.
        !           266:  * The `flag' says whether print is called at the
        !           267:  * end (0) or for each midnight-midnight period (1).
        !           268:  */
        !           269: print(flag)
        !           270: int flag;
        !           271: {
        !           272:        register struct tm *tmp;
        !           273:        register PEOPLE *pp;
        !           274:        time_t total = 0;
        !           275: 
        !           276:        if (dflag) {
        !           277:                time_t endofday;
        !           278: 
        !           279:                endofday = midnight-2*HOUR;
        !           280:                tmp = localtime(&endofday);
        !           281:                printf("%s %s %d:\n", days[tmp->tm_wday], months[tmp->tm_mon],
        !           282:                    tmp->tm_mday);
        !           283:        }
        !           284:        for (pp = people; pp != NULL; pp = pp->p_next) {
        !           285:                if (pp->p_time > 0) {
        !           286:                        total += pp->p_time;
        !           287:                        if (pflag)
        !           288:                                prtime(pp->p_name, pp->p_time);
        !           289:                }
        !           290:                if (flag)
        !           291:                        pp->p_time = 0;
        !           292:        }
        !           293:        runtotal += total;
        !           294:        prtime("Total:", total);
        !           295:        if (dflag) {
        !           296:                printf("\n");
        !           297:                if (flag == 0) {
        !           298:                        dflag = 0;
        !           299:                        prtime("Total:", runtotal);
        !           300:                }
        !           301:        }
        !           302: }
        !           303: 
        !           304: /*
        !           305:  * Print a time entry with a name.
        !           306:  */
        !           307: prtime(name, time)
        !           308: char *name;
        !           309: time_t time;
        !           310: {
        !           311:        if (dflag)
        !           312:                printf("\t");
        !           313:        printf("%-*.*s", DIRSIZ, DIRSIZ, name);
        !           314:        time = (time+30)/60;
        !           315:        printf("%3ld:%02ld\n", time/60, time%60);
        !           316: }
        !           317: 
        !           318: /*
        !           319:  * Error reporting.
        !           320:  */
        !           321: /* VARARGS */
        !           322: acerr(x)
        !           323: {
        !           324:        fprintf(stderr, "ac: %r\n", &x);
        !           325:        exit(1);
        !           326: }
        !           327: 
        !           328: usage()
        !           329: {
        !           330:        fprintf(stderr, "Usage: ac [-w wtmpfile] [-d] [-p] [username ...]\n");
        !           331:        exit(1);
        !           332: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.