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

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

unix.superglobalmegacorp.com

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