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

Defined functions

alarmcatch defined in line 65; used 3 times
blocksontape defined in line 234; never used
idatesort defined in line 318; used 2 times
interrupt defined in line 78; used 4 times
lastdump defined in line 275; used 2 times
max defined in line 336; never used
min defined in line 340; never used
msg defined in line 252; used 58 times
msgtail defined in line 266; used 3 times
query defined in line 18; used 6 times
sendmes defined in line 172; used 1 times
set_operators defined in line 96; used 1 times
timeest defined in line 206; used 1 times

Defined variables

attnmessage defined in line 17; used 2 times
gp defined in line 91; used 4 times
localclock defined in line 111; used 3 times
sccsid defined in line 1; never used
timeout defined in line 16; used 3 times
tschedule defined in line 204; used 2 times
Last modified: 1996-11-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4634
Valid CSS Valid XHTML 1.0 Strict