Annotation of 43BSDReno/old/dump.4.1/dumpoptr.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)dumpoptr.c 5.1 (Berkeley) 6/5/85";
                      9: #endif not lint
                     10: 
                     11: #include "dump.h"
                     12: 
                     13: /*
                     14:  *     This is from /usr/include/grp.h
                     15:  *     That defined struct group, which conflicts
                     16:  *     with the struct group defined in param.h
                     17:  */
                     18: struct Group { /* see getgrent(3) */
                     19:        char    *gr_name;
                     20:        char    *gr_passwd;
                     21:        int     gr_gid;
                     22:        char    **gr_mem;
                     23: };
                     24: struct Group *getgrnam();
                     25: /*
                     26:  *     Query the operator; This fascist piece of code requires
                     27:  *     an exact response.
                     28:  *     It is intended to protect dump aborting by inquisitive
                     29:  *     people banging on the console terminal to see what is
                     30:  *     happening which might cause dump to croak, destroying
                     31:  *     a large number of hours of work.
                     32:  *
                     33:  *     Every 2 minutes we reprint the message, alerting others
                     34:  *     that dump needs attention.
                     35:  */
                     36: int    timeout;
                     37: char   *attnmessage;           /* attemtion message */
                     38: query(question)
                     39:        char    *question;
                     40: {
                     41:        char    replybuffer[64];
                     42:        int     back;
                     43:        FILE    *mytty;
                     44: 
                     45:        if ( (mytty = fopen("/dev/tty", "r")) == NULL){
                     46:                msg("fopen on /dev/tty fails\n");
                     47:                abort();
                     48:        }
                     49:        attnmessage = question;
                     50:        timeout = 0;
                     51:        alarmcatch();
                     52:        for(;;){
                     53:                if ( fgets(replybuffer, 63, mytty) == NULL){
                     54:                        if (ferror(mytty)){
                     55:                                clearerr(mytty);
                     56:                                continue;
                     57:                        }
                     58:                } else if ( (strcmp(replybuffer, "yes\n") == 0) ||
                     59:                            (strcmp(replybuffer, "Yes\n") == 0)){
                     60:                                back = 1;
                     61:                                goto done;
                     62:                } else if ( (strcmp(replybuffer, "no\n") == 0) ||
                     63:                            (strcmp(replybuffer, "No\n") == 0)){
                     64:                                back = 0;
                     65:                                goto done;
                     66:                } else {
                     67:                        msg("\"Yes\" or \"No\" ONLY!\n");
                     68:                        alarmcatch();
                     69:                }
                     70:        }
                     71:     done:
                     72:        /*
                     73:         *      Turn off the alarm, and reset the signal to trap out..
                     74:         */
                     75:        alarm(0);
                     76:        if (signal(SIGALRM, sigalrm) == SIG_IGN)
                     77:                signal(SIGALRM, SIG_IGN);
                     78:        fclose(mytty);
                     79:        return(back);
                     80: }
                     81: /*
                     82:  *     Alert the console operator, and enable the alarm clock to
                     83:  *     sleep for 2 minutes in case nobody comes to satisfy dump
                     84:  */
                     85: alarmcatch()
                     86: {
                     87:        if (timeout)
                     88:                msgtail("\n");
                     89:        msg("NEEDS ATTENTION: %s: (\"yes\" or \"no\") ",
                     90:                attnmessage);
                     91:        signal(SIGALRM, alarmcatch);
                     92:        alarm(120);
                     93:        timeout = 1;
                     94: }
                     95: /*
                     96:  *     Here if an inquisitive operator interrupts the dump program
                     97:  */
                     98: interrupt()
                     99: {
                    100:        msg("Interrupt received. Do >>>YOU<<< know what are you doing?\n");
                    101:        if (query("Do you really want to abort dump?"))
                    102:                dumpabort();
                    103:        signal(SIGINT, interrupt);
                    104: }
                    105: 
                    106: /*
                    107:  *     The following variables and routines manage alerting
                    108:  *     operators to the status of dump.
                    109:  *     This works much like wall(1) does.
                    110:  */
                    111: struct Group *gp;
                    112: 
                    113: /*
                    114:  *     Get the names from the group entry "operator" to notify.
                    115:  */    
                    116: set_operators()
                    117: {
                    118:        if (!notify)            /*not going to notify*/
                    119:                return;
                    120:        gp = getgrnam(OPGRENT);
                    121:        endgrent();
                    122:        if (gp == (struct Group *)0){
                    123:                msg("No entry in /etc/group for %s.\n",
                    124:                        OPGRENT);
                    125:                notify = 0;
                    126:                return;
                    127:        }
                    128: }
                    129: 
                    130: struct tm *localtime();
                    131: struct tm *localclock;
                    132: 
                    133: /*
                    134:  *     We fork a child to do the actual broadcasting, so
                    135:  *     that the process control groups are not messed up
                    136:  */
                    137: broadcast(message)
                    138:        char    *message;
                    139: {
                    140:        time_t          clock;
                    141:        FILE    *f_utmp;
                    142:        struct  utmp    utmp;
                    143:        int     nusers;
                    144:        char    **np;
                    145:        int     pid, s;
                    146: 
                    147:        switch (pid = fork()) {
                    148:        case -1:
                    149:                return;
                    150:        case 0:
                    151:                break;
                    152:        default:
                    153:                while (wait(&s) != pid)
                    154:                        continue;
                    155:                return;
                    156:        }
                    157: 
                    158:        if (!notify || gp == 0)
                    159:                exit(0);
                    160:        clock = time(0);
                    161:        localclock = localtime(&clock);
                    162: 
                    163:        if((f_utmp = fopen("/etc/utmp", "r")) == NULL) {
                    164:                msg("Cannot open /etc/utmp\n");
                    165:                return;
                    166:        }
                    167: 
                    168:        nusers = 0;
                    169:        while (!feof(f_utmp)){
                    170:                if (fread(&utmp, sizeof (struct utmp), 1, f_utmp) != 1)
                    171:                        break;
                    172:                if (utmp.ut_name[0] == 0)
                    173:                        continue;
                    174:                nusers++;
                    175:                for (np = gp->gr_mem; *np; np++){
                    176:                        if (strncmp(*np, utmp.ut_name, sizeof(utmp.ut_name)) != 0)
                    177:                                continue;
                    178:                        /*
                    179:                         *      Do not send messages to operators on dialups
                    180:                         */
                    181:                        if (strncmp(utmp.ut_line, DIALUP, strlen(DIALUP)) == 0)
                    182:                                continue;
                    183: #ifdef DEBUG
                    184:                        msg("Message to %s at %s\n",
                    185:                                utmp.ut_name, utmp.ut_line);
                    186: #endif DEBUG
                    187:                        sendmes(utmp.ut_line, message);
                    188:                }
                    189:        }
                    190:        fclose(f_utmp);
                    191:        Exit(0);        /* the wait in this same routine will catch this */
                    192:        /* NOTREACHED */
                    193: }
                    194: 
                    195: sendmes(tty, message)
                    196: char *tty, *message;
                    197: {
                    198:        char t[50], buf[BUFSIZ];
                    199:        register char *cp;
                    200:        register int c, ch;
                    201:        int     msize;
                    202:        FILE *f_tty;
                    203: 
                    204:        msize = strlen(message);
                    205:        strcpy(t, "/dev/");
                    206:        strcat(t, tty);
                    207: 
                    208:        if((f_tty = fopen(t, "w")) != NULL) {
                    209:                setbuf(f_tty, buf);
                    210:                fprintf(f_tty, "\nMessage from the dump program to all operators at %d:%02d ...\r\n\n"
                    211:                       ,localclock->tm_hour
                    212:                       ,localclock->tm_min);
                    213:                for (cp = message, c = msize; c-- > 0; cp++) {
                    214:                        ch = *cp;
                    215:                        if (ch == '\n')
                    216:                                putc('\r', f_tty);
                    217:                        putc(ch, f_tty);
                    218:                }
                    219:                fclose(f_tty);
                    220:        }
                    221: }
                    222: 
                    223: /*
                    224:  *     print out an estimate of the amount of time left to do the dump
                    225:  */
                    226: 
                    227: time_t tschedule = 0;
                    228: 
                    229: timeest()
                    230: {
                    231:        time_t  tnow, deltat;
                    232: 
                    233:        time (&tnow);
                    234:        if (tnow >= tschedule){
                    235:                tschedule = tnow + 300;
                    236:                if (blockswritten < 500)
                    237:                        return; 
                    238:                deltat = tstart_writing - tnow +
                    239:                        (((1.0*(tnow - tstart_writing))/blockswritten) * esize);
                    240:                msg("%3.2f%% done, finished in %d:%02d\n",
                    241:                        (blockswritten*100.0)/esize,
                    242:                        deltat/3600, (deltat%3600)/60);
                    243:        }
                    244: }
                    245: 
                    246: int blocksontape()
                    247: {
                    248:        /*
                    249:         *      esize: total number of blocks estimated over all reels
                    250:         *      blockswritten:  blocks actually written, over all reels
                    251:         *      etapes: estimated number of tapes to write
                    252:         *
                    253:         *      tsize:  blocks can write on this reel
                    254:         *      asize:  blocks written on this reel
                    255:         *      tapeno: number of tapes written so far
                    256:         */
                    257:        if (tapeno == etapes)
                    258:                return(esize - (etapes - 1)*tsize);
                    259:        return(tsize);
                    260: }
                    261: 
                    262:        /* VARARGS1 */
                    263:        /* ARGSUSED */
                    264: msg(fmt, a1, a2, a3, a4, a5)
                    265:        char    *fmt;
                    266: {
                    267:        fprintf(stderr,"  DUMP: ");
                    268: #ifdef TDEBUG
                    269:        fprintf(stderr,"pid=%d ", getpid());
                    270: #endif
                    271:        fprintf(stderr, fmt, a1, a2, a3, a4, a5);
                    272:        fflush(stdout);
                    273:        fflush(stderr);
                    274: }
                    275: 
                    276:        /* VARARGS1 */
                    277:        /* ARGSUSED */
                    278: msgtail(fmt, a1, a2, a3, a4, a5)
                    279:        char    *fmt;
                    280: {
                    281:        fprintf(stderr, fmt, a1, a2, a3, a4, a5);
                    282: }
                    283: /*
                    284:  *     Tell the operator what has to be done;
                    285:  *     we don't actually do it
                    286:  */
                    287: 
                    288: struct fstab *
                    289: allocfsent(fs)
                    290:        register struct fstab *fs;
                    291: {
                    292:        register struct fstab *new;
                    293:        register char *cp;
                    294:        char *malloc();
                    295: 
                    296:        new = (struct fstab *)malloc(sizeof (*fs));
                    297:        cp = malloc(strlen(fs->fs_file) + 1);
                    298:        strcpy(cp, fs->fs_file);
                    299:        new->fs_file = cp;
                    300:        cp = malloc(strlen(fs->fs_type) + 1);
                    301:        strcpy(cp, fs->fs_type);
                    302:        new->fs_type = cp;
                    303:        cp = malloc(strlen(fs->fs_spec) + 1);
                    304:        strcpy(cp, fs->fs_spec);
                    305:        new->fs_spec = cp;
                    306:        new->fs_passno = fs->fs_passno;
                    307:        new->fs_freq = fs->fs_freq;
                    308:        return (new);
                    309: }
                    310: 
                    311: struct pfstab {
                    312:        struct  pfstab *pf_next;
                    313:        struct  fstab *pf_fstab;
                    314: };
                    315: 
                    316: static struct pfstab *table = NULL;
                    317: 
                    318: getfstab()
                    319: {
                    320:        register struct fstab *fs;
                    321:        register struct pfstab *pf;
                    322: 
                    323:        if (setfsent() == 0) {
                    324:                msg("Can't open %s for dump table information.\n", FSTAB);
                    325:                return;
                    326:        }
                    327:        while (fs = getfsent()) {
                    328:                if (strcmp(fs->fs_type, FSTAB_RW) &&
                    329:                    strcmp(fs->fs_type, FSTAB_RO) &&
                    330:                    strcmp(fs->fs_type, FSTAB_RQ))
                    331:                        continue;
                    332:                fs = allocfsent(fs);
                    333:                pf = (struct pfstab *)malloc(sizeof (*pf));
                    334:                pf->pf_fstab = fs;
                    335:                pf->pf_next = table;
                    336:                table = pf;
                    337:        }
                    338:        endfsent();
                    339: }
                    340: 
                    341: /*
                    342:  * Search in the fstab for a file name.
                    343:  * This file name can be either the special or the path file name.
                    344:  *
                    345:  * The entries in the fstab are the BLOCK special names, not the
                    346:  * character special names.
                    347:  * The caller of fstabsearch assures that the character device
                    348:  * is dumped (that is much faster)
                    349:  *
                    350:  * The file name can omit the leading '/'.
                    351:  */
                    352: struct fstab *
                    353: fstabsearch(key)
                    354:        char *key;
                    355: {
                    356:        register struct pfstab *pf;
                    357:        register struct fstab *fs;
                    358:        char *rawname();
                    359: 
                    360:        if (table == NULL)
                    361:                return ((struct fstab *)0);
                    362:        for (pf = table; pf; pf = pf->pf_next) {
                    363:                fs = pf->pf_fstab;
                    364:                if (strcmp(fs->fs_file, key) == 0)
                    365:                        return (fs);
                    366:                if (strcmp(fs->fs_spec, key) == 0)
                    367:                        return (fs);
                    368:                if (strcmp(rawname(fs->fs_spec), key) == 0)
                    369:                        return (fs);
                    370:                if (key[0] != '/'){
                    371:                        if (*fs->fs_spec == '/' &&
                    372:                            strcmp(fs->fs_spec + 1, key) == 0)
                    373:                                return (fs);
                    374:                        if (*fs->fs_file == '/' &&
                    375:                            strcmp(fs->fs_file + 1, key) == 0)
                    376:                                return (fs);
                    377:                }
                    378:        }
                    379:        return (0);
                    380: }
                    381: 
                    382: /*
                    383:  *     Tell the operator what to do
                    384:  */
                    385: lastdump(arg)
                    386:        char    arg;            /* w ==> just what to do; W ==> most recent dumps */
                    387: {
                    388:                        char    *lastname;
                    389:                        char    *date;
                    390:        register        int     i;
                    391:                        time_t  tnow;
                    392:        register        struct  fstab   *dt;
                    393:                        int     dumpme;
                    394:        register        struct  idates  *itwalk;
                    395: 
                    396:        int     idatesort();
                    397: 
                    398:        time(&tnow);
                    399:        getfstab();             /* /etc/fstab input */
                    400:        inititimes();           /* /etc/dumpdates input */
                    401:        qsort(idatev, nidates, sizeof(struct idates *), idatesort);
                    402: 
                    403:        if (arg == 'w')
                    404:                fprintf(stdout, "Dump these file systems:\n");
                    405:        else
                    406:                fprintf(stdout, "Last dump(s) done (Dump '>' file systems):\n");
                    407:        lastname = "??";
                    408:        ITITERATE(i, itwalk){
                    409:                if (strncmp(lastname, itwalk->id_name, sizeof(itwalk->id_name)) == 0)
                    410:                        continue;
                    411:                date = (char *)ctime(&itwalk->id_ddate);
                    412:                date[16] = '\0';                /* blast away seconds and year */
                    413:                lastname = itwalk->id_name;
                    414:                dt = fstabsearch(itwalk->id_name);
                    415:                dumpme = (  (dt != 0)
                    416:                         && (dt->fs_freq != 0)
                    417:                         && (itwalk->id_ddate < tnow - (dt->fs_freq*DAY)));
                    418:                if ( (arg != 'w') || dumpme)
                    419:                  fprintf(stdout,"%c %8s\t(%6s) Last dump: Level %c, Date %s\n",
                    420:                        dumpme && (arg != 'w') ? '>' : ' ',
                    421:                        itwalk->id_name,
                    422:                        dt ? dt->fs_file : 0,
                    423:                        itwalk->id_incno,
                    424:                        date
                    425:                    );
                    426:        }
                    427: }
                    428: 
                    429: int    idatesort(p1, p2)
                    430:        struct  idates  **p1, **p2;
                    431: {
                    432:        int     diff;
                    433: 
                    434:        diff = strncmp((*p1)->id_name, (*p2)->id_name, sizeof((*p1)->id_name));
                    435:        if (diff == 0)
                    436:                return ((*p2)->id_ddate - (*p1)->id_ddate);
                    437:        else
                    438:                return (diff);
                    439: }
                    440: 
                    441: int max(a,b)
                    442: {
                    443:        return(a>b?a:b);
                    444: }
                    445: int min(a,b)
                    446: {
                    447:        return(a<b?a:b);
                    448: }

unix.superglobalmegacorp.com

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