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;       /* attention 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\"?\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.\n");
 101:     if (query("Do you 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:     int a1, a2, a3, a4, a5;
 267: {
 268:     fprintf(stderr,"  DUMP: ");
 269: #ifdef TDEBUG
 270:     fprintf(stderr,"pid=%d ", getpid());
 271: #endif
 272:     fprintf(stderr, fmt, a1, a2, a3, a4, a5);
 273:     fflush(stdout);
 274:     fflush(stderr);
 275: }
 276: 
 277:     /* VARARGS1 */
 278:     /* ARGSUSED */
 279: msgtail(fmt, a1, a2, a3, a4, a5)
 280:     char    *fmt;
 281:     int a1, a2, a3, a4, a5;
 282: {
 283:     fprintf(stderr, fmt, a1, a2, a3, a4, a5);
 284: }
 285: /*
 286:  *	Tell the operator what has to be done;
 287:  *	we don't actually do it
 288:  */
 289: 
 290: struct fstab *
 291: allocfsent(fs)
 292:     register struct fstab *fs;
 293: {
 294:     register struct fstab *new;
 295:     register char *cp;
 296:     char *malloc();
 297: 
 298:     new = (struct fstab *)malloc(sizeof (*fs));
 299:     cp = malloc(strlen(fs->fs_file) + 1);
 300:     strcpy(cp, fs->fs_file);
 301:     new->fs_file = cp;
 302:     cp = malloc(strlen(fs->fs_type) + 1);
 303:     strcpy(cp, fs->fs_type);
 304:     new->fs_type = cp;
 305:     cp = malloc(strlen(fs->fs_spec) + 1);
 306:     strcpy(cp, fs->fs_spec);
 307:     new->fs_spec = cp;
 308:     new->fs_passno = fs->fs_passno;
 309:     new->fs_freq = fs->fs_freq;
 310:     return (new);
 311: }
 312: 
 313: struct  pfstab {
 314:     struct  pfstab *pf_next;
 315:     struct  fstab *pf_fstab;
 316: };
 317: 
 318: static  struct pfstab *table = NULL;
 319: 
 320: getfstab()
 321: {
 322:     register struct fstab *fs;
 323:     register struct pfstab *pf;
 324: 
 325:     if (setfsent() == 0) {
 326:         msg("Can't open %s for dump table information.\n", FSTAB);
 327:         return;
 328:     }
 329:     while (fs = getfsent()) {
 330:         if (strcmp(fs->fs_type, FSTAB_RW) &&
 331:             strcmp(fs->fs_type, FSTAB_RO) &&
 332:             strcmp(fs->fs_type, FSTAB_RQ))
 333:             continue;
 334:         fs = allocfsent(fs);
 335:         pf = (struct pfstab *)malloc(sizeof (*pf));
 336:         pf->pf_fstab = fs;
 337:         pf->pf_next = table;
 338:         table = pf;
 339:     }
 340:     endfsent();
 341: }
 342: 
 343: /*
 344:  * Search in the fstab for a file name.
 345:  * This file name can be either the special or the path file name.
 346:  *
 347:  * The entries in the fstab are the BLOCK special names, not the
 348:  * character special names.
 349:  * The caller of fstabsearch assures that the character device
 350:  * is dumped (that is much faster)
 351:  *
 352:  * The file name can omit the leading '/'.
 353:  */
 354: struct fstab *
 355: fstabsearch(key)
 356:     char *key;
 357: {
 358:     register struct pfstab *pf;
 359:     register struct fstab *fs;
 360:     char *rawname();
 361: 
 362:     if (table == NULL)
 363:         return ((struct fstab *)0);
 364:     for (pf = table; pf; pf = pf->pf_next) {
 365:         fs = pf->pf_fstab;
 366:         if (strcmp(fs->fs_file, key) == 0)
 367:             return (fs);
 368:         if (strcmp(fs->fs_spec, key) == 0)
 369:             return (fs);
 370:         if (strcmp(rawname(fs->fs_spec), key) == 0)
 371:             return (fs);
 372:         if (key[0] != '/'){
 373:             if (*fs->fs_spec == '/' &&
 374:                 strcmp(fs->fs_spec + 1, key) == 0)
 375:                 return (fs);
 376:             if (*fs->fs_file == '/' &&
 377:                 strcmp(fs->fs_file + 1, key) == 0)
 378:                 return (fs);
 379:         }
 380:     }
 381:     return (0);
 382: }
 383: 
 384: /*
 385:  *	Tell the operator what to do
 386:  */
 387: lastdump(arg)
 388:     char    arg;        /* w ==> just what to do; W ==> most recent dumps */
 389: {
 390:             char    *lastname;
 391:             char    *date;
 392:     register    int i;
 393:             time_t  tnow;
 394:     register    struct  fstab   *dt;
 395:             int dumpme;
 396:     register    struct  idates  *itwalk;
 397: 
 398:     int idatesort();
 399: 
 400:     time(&tnow);
 401:     getfstab();     /* /etc/fstab input */
 402:     inititimes();       /* /etc/dumpdates input */
 403:     qsort(idatev, nidates, sizeof(struct idates *), idatesort);
 404: 
 405:     if (arg == 'w')
 406:         fprintf(stdout, "Dump these file systems:\n");
 407:     else
 408:         fprintf(stdout, "Last dump(s) done (Dump '>' file systems):\n");
 409:     lastname = "??";
 410:     ITITERATE(i, itwalk){
 411:         if (strncmp(lastname, itwalk->id_name, sizeof(itwalk->id_name)) == 0)
 412:             continue;
 413:         date = (char *)ctime(&itwalk->id_ddate);
 414:         date[16] = '\0';        /* blast away seconds and year */
 415:         lastname = itwalk->id_name;
 416:         dt = fstabsearch(itwalk->id_name);
 417:         dumpme = (  (dt != 0)
 418:              && (dt->fs_freq != 0)
 419:              && (itwalk->id_ddate < tnow - (dt->fs_freq*DAY)));
 420:         if ( (arg != 'w') || dumpme)
 421:           fprintf(stdout,"%c %8s\t(%6s) Last dump: Level %c, Date %s\n",
 422:             dumpme && (arg != 'w') ? '>' : ' ',
 423:             itwalk->id_name,
 424:             dt ? dt->fs_file : "",
 425:             itwalk->id_incno,
 426:             date
 427:             );
 428:     }
 429: }
 430: 
 431: int idatesort(p1, p2)
 432:     struct  idates  **p1, **p2;
 433: {
 434:     int diff;
 435: 
 436:     diff = strncmp((*p1)->id_name, (*p2)->id_name, sizeof((*p1)->id_name));
 437:     if (diff == 0)
 438:         return ((*p2)->id_ddate - (*p1)->id_ddate);
 439:     else
 440:         return (diff);
 441: }
 442: 
 443: int max(a,b)
 444:     int a, b;
 445: {
 446:     return(a>b?a:b);
 447: }
 448: int min(a,b)
 449:     int a, b;
 450: {
 451:     return(a<b?a:b);
 452: }

Defined functions

alarmcatch defined in line 85; used 3 times
allocfsent defined in line 290; used 1 times
blocksontape defined in line 246; never used
fstabsearch defined in line 354; used 3 times
getfstab defined in line 320; used 2 times
idatesort defined in line 431; used 2 times
interrupt defined in line 98; used 2 times
lastdump defined in line 387; used 2 times
max defined in line 443; never used
min defined in line 448; never used
msg defined in line 264; used 71 times
msgtail defined in line 279; used 4 times
query defined in line 38; used 6 times
sendmes defined in line 195; used 1 times
set_operators defined in line 116; used 1 times
timeest defined in line 229; used 1 times

Defined variables

attnmessage defined in line 37; used 2 times
gp defined in line 111; used 4 times
localclock defined in line 131; used 3 times
sccsid defined in line 8; never used
table defined in line 318; used 4 times
timeout defined in line 36; used 3 times

Defined struct's

Group defined in line 18; used 6 times
pfstab defined in line 313; used 10 times
Last modified: 1985-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1947
Valid CSS Valid XHTML 1.0 Strict