# 2.11BSD#431 - /usr/src/sbin/dump/dumpoptr.c

##### Functions

    alarmcatch        X
    broadcast         X
    idatesort         X
    interrupt         X
    lastdump          X
    msg               X
    msgtail           X
    query             X
    sendmes           X
    set_operators     X
    timeest           X

##### Variables

    attnmessage       X
    gp                X
    localclock        X
    timeout           X
    tschedule         X

       1: #if !defined(lint) && defined(DOSCCS)
       2: static  char *sccsid = "@(#)dumpoptr.c	1.6 (2.11BSD GTE) 1996/11/16";
       3: #endif
       4:
       5: #include "dump.h"
       6:
       7: struct  group *getgrnam();
       8: /*
       9:  *	Query the operator; This fascist piece of code requires
      10:  *	an exact response.
      11:  *	It is intended to protect dump aborting by inquisitive
      12:  *	people banging on the console terminal to see what is
      13:  *	happening which might cause dump to croak, destroying
      14:  *	a large number of hours of work.
      15:  *
      16:  *	Every 2 minutes we reprint the message, alerting others
      17:  *	that dump needs attention.
      18:  */
      19: int timeout;
      20: char    *attnmessage;       /* attemtion message */
      21:
      22: query(question)
      23:     char    *question;
      24: {
      25:     char    replybuffer[64];
      26:     int back;
      27:     FILE    *mytty;
      28:
      29:     if ( (mytty = fopen("/dev/tty", "r")) == NULL){
      30:         msg("fopen on /dev/tty fails\n");
      31:         abort();
      32:     }
      33:     attnmessage = question;
      34:     timeout = 0;
      35:     alarmcatch();
      36:     for(;;){
      37:         if ( fgets(replybuffer, 63, mytty) == NULL){
      38:             if (ferror(mytty)){
      39:                 clearerr(mytty);
      40:                 continue;
      41:             }
      42:         } else if ( (strcmp(replybuffer, "yes\n") == 0) ||
      43:                 (strcmp(replybuffer, "Yes\n") == 0)){
      44:                 back = 1;
      45:                 goto done;
      46:         } else if ( (strcmp(replybuffer, "no\n") == 0) ||
      47:                 (strcmp(replybuffer, "No\n") == 0)){
      48:                 back = 0;
      49:                 goto done;
      50:         } else {
      51:             msg("\"Yes\" or \"No\"?\n");
      52:             alarmcatch();
      53:         }
      54:     }
      55:     done:
      56:     /*
      57: 	 *	Turn off the alarm, and reset the signal to trap out..
      58: 	 */
      59:     alarm(0);
      60:     if (signal(SIGALRM, sigalrm) == SIG_IGN)
      61:         signal(SIGALRM, SIG_IGN);
      62:     fclose(mytty);
      63:     return(back);
      64: }
      65: /*
      66:  *	Alert the console operator, and enable the alarm clock to
      67:  *	sleep for 2 minutes in case nobody comes to satisfy dump
      68:  */
      69: alarmcatch()
      70: {
      71:     if (timeout)
      72:         msgtail("\n");
      73:     msg("NEEDS ATTENTION: %s: (\"yes\" or \"no\") ",
      74:         attnmessage);
      75:     signal(SIGALRM, alarmcatch);
      76:     alarm(120);
      77:     timeout = 1;
      78: }
      79: /*
      80:  *	Here if an inquisitive operator interrupts the dump program
      81:  */
      82: interrupt()
      83: {
      84:     msg("Interrupt received.\n");
      85:     if (query("Do you want to abort dump?"))
      86:         dumpabort();
      87:     signal(SIGINT, interrupt);
      88: }
      89:
      90: /*
      91:  *	The following variables and routines manage alerting
      92:  *	operators to the status of dump.
      93:  *	This works much like wall(1) does.
      94:  */
      95: struct  group *gp;
      96:
      97: /*
      98:  *	Get the names from the group entry "operator" to notify.
      99:  */
     100: set_operators()
     101: {
     102:     if (!notify)        /*not going to notify*/
     103:         return;
     104:     gp = getgrnam(OPGRENT);
     105:     endgrent();
     106:     if (gp == (struct group *)0){
     107:         msg("No entry in /etc/group for %s.\n",
     108:             OPGRENT);
     109:         notify = 0;
     110:         return;
     111:     }
     112: }
     113:
     114: struct tm *localtime();
     115: struct tm *localclock;
     116:
     117: /*
     118:  *	We fork a child to do the actual broadcasting, so
     119:  *	that the process control groups are not messed up
     120:  */
     121: broadcast(message)
     122:     char    *message;
     123: {
     124:     time_t      clock;
     125:     FILE    *f_utmp;
     126:     struct  utmp    utmp;
     127:     char    **np;
     128:     int pid, s;
     129:
     130:     switch (pid = fork()) {
     131:     case -1:
     132:         return;
     133:     case 0:
     134:         break;
     135:     default:
     136:         while (wait(&s) != pid)
     137:             continue;
     138:         return;
     139:     }
     140:
     141:     if (!notify || gp == 0)
     142:         exit(0);
     143:     clock = time((time_t *)0);
     144:     localclock = localtime(&clock);
     145:
     146:     if((f_utmp = fopen(_PATH_UTMP, "r")) == NULL) {
     147:         msg("Cannot open 'utmp'\n");
     148:         return;
     149:     }
     150:
     151:     while (!feof(f_utmp)){
     152:         if (fread((char *)&utmp, sizeof (struct utmp), 1, f_utmp) != 1)
     153:             break;
     154:         if (utmp.ut_name[0] == 0)
     155:             continue;
     156:         for (np = gp->gr_mem; *np; np++){
     157:             if (strncmp(*np, utmp.ut_name, sizeof(utmp.ut_name)) != 0)
     158:                 continue;
     159:             /*
     160: 			 *	Do not send messages to operators on dialups
     161: 			 */
     162:             if (strncmp(utmp.ut_line, DIALUP, strlen(DIALUP)) == 0)
     163:                 continue;
     164: #ifdef DEBUG
     165:             msg("Message to %s at %s\n",
     166:                 utmp.ut_name, utmp.ut_line);
     167: #endif DEBUG
     168:             sendmes(utmp.ut_line, message);
     169:         }
     170:     }
     171:     fclose(f_utmp);
     172:     Exit(0);    /* the wait in this same routine will catch this */
     173:     /* NOTREACHED */
     174: }
     175:
     176: sendmes(tty, message)
     177: char *tty, *message;
     178: {
     179:     char t[50], buf[BUFSIZ];
     180:     register char *cp;
     181:     register int c;
     182:     int ch, msize;
     183:     register FILE *f_tty;
     184:
     185:     msize = strlen(message);
     186:     strcpy(t, "/dev/");
     187:     strcat(t, tty);
     188:
     189:     if((f_tty = fopen(t, "w")) != NULL) {
     190:         setbuf(f_tty, buf);
     191:         fprintf(f_tty, "\n\007\007\007Message from the dump program to all operators at %d:%02d ...\r\n\n"
     192:                ,localclock->tm_hour
     193:                ,localclock->tm_min);
     194:         for (cp = message, c = msize; c-- > 0; cp++) {
     195:             ch = *cp;
     196:             if (ch == '\n')
     197:                 putc('\r', f_tty);
     198:             putc(ch, f_tty);
     199:         }
     200:         fclose(f_tty);
     201:     }
     202: }
     203:
     204: /*
     205:  *	print out an estimate of the amount of time left to do the dump
     206:  */
     207:
     208: time_t  tschedule = 0;
     209:
     210: timeest()
     211: {
     212:     time_t  tnow, deltat;
     213:     long    pleft;
     214:     char buf[BUFSIZ];
     215:
     216:     time (&tnow);
     217:     if (tnow >= tschedule){
     218:         tschedule = tnow + 300;
     219:         if (blockswritten < 500L)
     220:             return;
     221: /*
     222: 			/				    \
     223: 			|/ estimated blocks \		    |
     224: 	delta time =	||----------------  | X time so far |  - time so far
     225: 			|\ blocks thus far  /		    |
     226: 			\				    /
     227: */
     228:         pleft  = ((100 * esize)/blockswritten) - 100;
     229:         deltat = (time_t) (tnow - tstart_writing) * pleft;
     230:         deltat = deltat/100;    /* scale back down */
     231:         sprintf(buf,"%3.2f%%%% done, finished in %d:%02d\n",
     232:             (float) (blockswritten*100.0)/esize,
     233:             (int)(deltat/3600L), (int)((deltat%3600L)/60L));
     234:         msg(buf);
     235:     }
     236: }
     237:
     238: /* VARARGS1 */
     239: /* ARGSUSED */
     240: msg(fmt, a1, a2, a3, a4, a5)
     241:     char    *fmt;
     242: {
     243:     fprintf(stderr,"  DUMP: ");
     244: #ifdef TDEBUG
     245:     fprintf(stderr,"pid=%d ", getpid());
     246: #endif
     247:     fprintf(stderr, fmt, a1, a2, a3, a4, a5);
     248:     fflush(stdout);
     249:     fflush(stderr);
     250: }
     251:
     252: /* VARARGS1 */
     253: /* ARGSUSED */
     254: msgtail(fmt, a1, a2, a3, a4, a5)
     255:     char    *fmt;
     256: {
     257:     fprintf(stderr, fmt, a1, a2, a3, a4, a5);
     258: }
     259:
     260: /*
     261:  *	Tell the operator what has to be done.
     262:  */
     263: lastdump(arg)
     264:     char    arg;    /* w ==> just what to do; W ==> most recent dumps */
     265: {
     266:             char    *lastname;
     267:             char    *date;
     268:     register    int i;
     269:             time_t  tnow;
     270:     register    struct  fstab   *dt;
     271:             int dumpme;
     272:     register    struct  idates  *itwalk;
     273:
     274:     int idatesort();
     275:
     276:     time(&tnow);
     277:     inititimes();       /* /etc/dumpdates input */
     278:     qsort(idatev, nidates, sizeof(struct idates *), idatesort);
     279:
     280:     if (arg == 'w')
     281:         fprintf(stdout, "Dump these file systems:\n");
     282:     else
     283:         fprintf(stdout, "Last dump(s) done (Dump '>' file systems):\n");
     284:     lastname = "??";
     285:     ITITERATE(i, itwalk){
     286:         if (strncmp(lastname, itwalk->id_name, sizeof(itwalk->id_name)) == 0)
     287:             continue;
     288:         date = (char *)ctime(&itwalk->id_ddate);
     289:         date[16] = '\0';    /* blast away seconds and year */
     290:         lastname = itwalk->id_name;
     291:         dt = getfsspec(deraw(itwalk->id_name));
     292:         dumpme = (  (dt != 0)
     293:              && (dt->fs_freq != 0)
     294:              && (itwalk->id_ddate < tnow - (dt->fs_freq*DAY)));
     295:         if ( (arg != 'w') || dumpme)
     296:           fprintf(stdout,"%c %8s\t(%6s) Last dump: Level %c, Date %s\n",
     297:             dumpme && (arg != 'w') ? '>' : ' ',
     298:             itwalk->id_name,
     299:             dt ? dt->fs_file : 0,
     300:             itwalk->id_incno,
     301:             date
     302:             );
     303:     }
     304: }
     305:
     306: int idatesort(p1, p2)
     307:     struct  idates  **p1, **p2;
     308: {
     309:     int diff;
     310:
     311:     diff = strncmp((*p1)->id_name, (*p2)->id_name, sizeof((*p1)->id_name));
     312:     if (diff == 0)
     313:         if ((*p2)->id_ddate > (*p1)->id_ddate)
     314:             return (1);
     315:         else
     316:             if ((*p2)->id_ddate == (*p1)->id_ddate)
     317:                 return (0);
     318:             else
     319:                 return (-1);
     320:     else
     321:         return (diff);
     322: }

#### Defined functions

alarmcatch defined in line 69; used 3 times

- in line 35, 52, 75

broadcast defined in line 121; used 4 times

- in /usr/src/sbin/dump/dumpmain.c line 312
- in /usr/src/sbin/dump/dumptape.c line 111, 180
- in /usr/src/sbin/dump/dumptraverse.c line 271

idatesort defined in line 306; used 2 times

- in line 274-278(2)

interrupt defined in line 82; used 2 times

- in line 87
- in /usr/src/sbin/dump/dump.h line 74

lastdump defined in line 263; used 2 times

- in /usr/src/sbin/dump/dumpmain.c line 43-48(2)

msg defined in line 240; used 70 times

- in line 30, 51, 73, 84, 107, 147, 165, 234
- in /usr/src/sbin/dump/dumpitime.c line 60, 117, 124, 150-154(2)
- in /usr/src/sbin/dump/dumpmain.c line 208-212(3), 222, 234-238(2), 248, 288, 298-301(2), 307-308(2), 361-375(9)
- in /usr/src/sbin/dump/dumprmt.c line 64, 166, 174, 206
- in /usr/src/sbin/dump/dumptape.c line 105-116(6), 126, 159, 179, 216, 228-235(3), 242-251(4), 264, 271, 282, 296, 307, 315, 331-336(2), 369, 431, 448
- in /usr/src/sbin/dump/dumptraverse.c line 262-272(4)

msgtail defined in line 254; used 4 times

- in line 72
- in /usr/src/sbin/dump/dumpmain.c line 214-218(3)

query defined in line 22; used 6 times

- in line 85
- in /usr/src/sbin/dump/dumptape.c line 112, 182-183(2), 283
- in /usr/src/sbin/dump/dumptraverse.c line 273

sendmes defined in line 176; used 1 times

- in line 168

set_operators defined in line 100; used 1 times

- in /usr/src/sbin/dump/dumpmain.c line 192

timeest defined in line 210; used 1 times

- in /usr/src/sbin/dump/dumptape.c line 147

#### Defined variables

attnmessage defined in line 20; used 2 times

- in line 33, 74

gp defined in line 95; used 4 times

- in line 104-106(2), 141, 156

localclock defined in line 115; used 3 times

- in line 144, 192-193(2)

sccsid defined in line 2; never used
timeout defined in line 19; used 3 times

- in line 34, 71, 77

tschedule defined in line 208; used 2 times

- in line 217-218(2)

Last modified: 1996-11-17 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1049 |