Annotation of 42BSD/etc/dump.4.1/dumpoptr.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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