1: static  char *sccsid = "@(#)dumpoptr.c	1.4 (Berkeley) 12/17/80";
   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:     char    **np;
 135:     int pid, s;
 136: 
 137:     switch (pid = fork()) {
 138:     case -1:
 139:         return;
 140:     case 0:
 141:         break;
 142:     default:
 143:         while (wait(&s) != pid)
 144:             continue;
 145:         return;
 146:     }
 147: 
 148:     if (!notify || gp == 0)
 149:         exit(0);
 150:     clock = time((time_t *) 0);
 151:     localclock = localtime(&clock);
 152: 
 153:     if((f_utmp = fopen("/etc/utmp", "r")) == NULL) {
 154:         msg("Cannot open /etc/utmp\n");
 155:         return;
 156:     }
 157: 
 158:     while (!feof(f_utmp)){
 159:         if (fread((char *) &utmp, sizeof (struct utmp), 1, f_utmp) != 1)
 160:             break;
 161:         if (utmp.ut_name[0] == 0)
 162:             continue;
 163:         for (np = gp->gr_mem; *np; np++){
 164:             if (strncmp(*np, utmp.ut_name, sizeof(utmp.ut_name)) != 0)
 165:                 continue;
 166:             /*
 167: 			 *	Do not send messages to operators on dialups
 168: 			 */
 169:             if (strncmp(utmp.ut_line, DIALUP, strlen(DIALUP)) == 0)
 170:                 continue;
 171: #ifdef DEBUG
 172:             msg("Message to %s at %s\n",
 173:                 utmp.ut_name, utmp.ut_line);
 174: #endif DEBUG
 175:             sendmes(utmp.ut_line, message);
 176:         }
 177:     }
 178:     fclose(f_utmp);
 179:     Exit(0);    /* the wait in this same routine will catch this */
 180:     /* NOTREACHED */
 181: }
 182: 
 183: sendmes(tty, message)
 184: char *tty, *message;
 185: {
 186:     char t[50], buf[BUFSIZ];
 187:     register char *cp;
 188:     register int c, ch;
 189:     int msize;
 190:     FILE *f_tty;
 191: 
 192:     msize = strlen(message);
 193:     strcpy(t, "/dev/");
 194:     strcat(t, tty);
 195: 
 196:     if((f_tty = fopen(t, "w")) != NULL) {
 197:         setbuf(f_tty, buf);
 198:         fprintf(f_tty, "\nMessage from the dump program to all operators at %d:%02d ...\r\n\n"
 199:                ,localclock->tm_hour
 200:                ,localclock->tm_min);
 201:         for (cp = message, c = msize; c-- > 0; cp++) {
 202:             ch = *cp;
 203:             if (ch == '\n')
 204:                 putc('\r', f_tty);
 205:             putc(ch, f_tty);
 206:         }
 207:         fclose(f_tty);
 208:     }
 209: }
 210: 
 211: /*
 212:  *	print out an estimate of the amount of time left to do the dump
 213:  */
 214: 
 215: time_t  tschedule = 0;
 216: 
 217: timeest()
 218: {
 219:     time_t  tnow, deltat;
 220: 
 221:     time (&tnow);
 222:     if (tnow >= tschedule){
 223:         tschedule = tnow + 300;
 224:         if (blockswritten < 500L)
 225:             return;
 226:         deltat = tstart_writing - tnow +
 227:             (time_t) (((1.0*(tnow - tstart_writing))/blockswritten) * esize);
 228:         msg("%3.2f%% done, finished in %ld:%02ld\n",
 229:             (double) ((((double) blockswritten)*100.0)/(double) esize),
 230:             (deltat/3600L), (deltat%3600L)/60L);
 231:     }
 232: }
 233: 
 234:     /* VARARGS1 */
 235:     /* ARGSUSED */
 236: msg(fmt, a1, a2, a3, a4, a5)
 237:     char    *fmt;
 238: {
 239:     fprintf(stderr,"  DUMP: ");
 240: #ifdef TDEBUG
 241:     fprintf(stderr,"pid=%d ", getpid());
 242: #endif
 243:     _doprnt (fmt, &a1, stderr);
 244:     fflush(stdout);
 245:     fflush(stderr);
 246: }
 247: 
 248:     /* VARARGS1 */
 249:     /* ARGSUSED */
 250: msgtail(fmt, a1, a2, a3, a4, a5)
 251:     char    *fmt;
 252: {
 253:     fprintf(stderr, fmt, a1, a2, a3, a4, a5);
 254: }
 255: /*
 256:  *	Tell the operator what has to be done;
 257:  *	we don't actually do it
 258:  */
 259: 
 260: getfstab()
 261: {
 262:     register    struct  fstab   *dt;
 263:             struct  fstab   *fsp;
 264: 
 265:     nfstab = 0;
 266:     if (setfsent() == 0) {
 267:         msg("Can't open %s for dump table information.\n", FSTAB);
 268:     } else {
 269:         for (nfstab = 0, dt = fstab; nfstab < MAXFSTAB;){
 270:             if ( (fsp = getfsent()) == 0)
 271:                 break;
 272:             if (   (strcmp(fsp->fs_type, FSTAB_RW) == 0)
 273:                 || (strcmp(fsp->fs_type, FSTAB_RO) == 0) ){
 274:                 *dt = *fsp;
 275:                 nfstab++;
 276:                 dt++;
 277:             }
 278:         }
 279:         endfsent();
 280:     }
 281: }
 282: 
 283: /*
 284:  *	Search in the fstab for a file name.
 285:  *	This file name can be either the special or the path file name.
 286:  *
 287:  *	The entries in the fstab are the BLOCK special names, not the
 288:  *	character special names.
 289:  *	The caller of fstabsearch assures that the character device
 290:  *	is dumped (that is much faster)
 291:  *
 292:  *	The file name can omit the leading '/'.
 293:  */
 294: struct  fstab   *fstabsearch(key)
 295:     char    *key;
 296: {
 297:     register    struct  fstab *dt;
 298:             int i;
 299:             int keylength;
 300:             char    *rawname();
 301: 
 302:     keylength = min(strlen(key) + 1, sizeof (dt->fs_file));
 303:     for (i = 0, dt = fstab; i < nfstab; i++, dt++){
 304:         if (strncmp(dt->fs_file, key, keylength) == 0)
 305:             return(dt);
 306:         if (strncmp(dt->fs_spec, key, keylength) == 0)
 307:             return(dt);
 308:         if (strncmp(rawname(dt->fs_spec), key, keylength) == 0)
 309:             return(dt);
 310: 
 311:         if (key[0] != '/'){
 312:             if (   (dt->fs_spec[0] == '/')
 313:                 && (strncmp(dt->fs_spec+1, key, keylength) == 0))
 314:                 return(dt);
 315:             if (   (dt->fs_file[0] == '/')
 316:                 && (strncmp(dt->fs_file+1, key, keylength) == 0))
 317:                 return(dt);
 318:         }
 319:     }
 320:     return(0);
 321: }
 322: 
 323: /*
 324:  *	Tell the operator what to do
 325:  */
 326: lastdump(arg)
 327:     char    arg;        /* w ==> just what to do; W ==> most recent dumps */
 328: {
 329:             char    *lastname;
 330:             char    *date;
 331:     register    int i;
 332:             time_t  tnow;
 333:     register    struct  fstab   *dt;
 334:             int dumpme;
 335:     register    struct  idates  *itwalk;
 336: 
 337:     int idatesort();
 338: 
 339:     time(&tnow);
 340:     getfstab();     /* /etc/fstab input */
 341:     inititimes();       /* /etc/dumpdates input */
 342:     qsort(idatev, nidates, sizeof(struct idates *), idatesort);
 343: 
 344:     if (arg == 'w')
 345:         fprintf(stdout, "Dump these file systems:\n");
 346:     else
 347:         fprintf(stdout, "Last dump(s) done (Dump '>' file systems):\n");
 348:     lastname = "??";
 349:     ITITERATE(i, itwalk){
 350:         if (strncmp(lastname, itwalk->id_name, sizeof(itwalk->id_name)) == 0)
 351:             continue;
 352:         date = (char *)ctime(&itwalk->id_ddate);
 353:         date[16] = '\0';        /* blast away seconds and year */
 354:         lastname = itwalk->id_name;
 355:         dt = fstabsearch(itwalk->id_name);
 356:         dumpme = (  (dt != 0)
 357:              && (dt->fs_freq != 0)
 358:              && (itwalk->id_ddate < tnow - (dt->fs_freq*DAY)));
 359:         if ( (arg != 'w') || dumpme)
 360:           fprintf(stdout,"%c %8s\t(%6s) Last dump: Level %c, Date %s\n",
 361:             dumpme && (arg != 'w') ? '>' : ' ',
 362:             itwalk->id_name,
 363:             dt ? dt->fs_file : 0,
 364:             itwalk->id_incno,
 365:             date
 366:             );
 367:     }
 368: }
 369: 
 370: int idatesort(p1, p2)
 371:     struct  idates  **p1, **p2;
 372: {
 373:     int diff;
 374: 
 375:     diff = strncmp((*p1)->id_name, (*p2)->id_name, sizeof((*p1)->id_name));
 376:     if (diff == 0)
 377:         /*
 378: 		 *	This won't work.  Must use the second form.
 379: 		return ((*p2)->id_ddate - (*p1)->id_ddate);
 380: 		*/
 381:         if ((*p2)->id_ddate > (*p1)->id_ddate)
 382:             return (1);
 383:         else    if ((*p2)->id_ddate == (*p1)->id_ddate)
 384:                 return (0);
 385:             else    return (-1);
 386:     else
 387:         return (diff);
 388: }
 389: 
 390: int max(a,b)
 391: {
 392:     return(a>b?a:b);
 393: }
 394: int min(a,b)
 395: {
 396:     return(a<b?a:b);
 397: }

Defined functions

alarmcatch defined in line 76; used 3 times
fstabsearch defined in line 294; used 3 times
getfstab defined in line 260; used 2 times
idatesort defined in line 370; used 2 times
interrupt defined in line 89; used 4 times
lastdump defined in line 326; used 2 times
max defined in line 390; never used
min defined in line 394; used 1 times
msg defined in line 236; used 60 times
msgtail defined in line 250; used 3 times
query defined in line 29; used 6 times
sendmes defined in line 183; used 1 times
set_operators defined in line 107; used 1 times
timeest defined in line 217; used 1 times

Defined variables

attnmessage defined in line 28; used 2 times
gp defined in line 102; used 4 times
localclock defined in line 122; used 3 times
sccsid defined in line 1; never used
timeout defined in line 27; used 3 times
tschedule defined in line 215; used 2 times

Defined struct's

Group defined in line 9; used 6 times
Last modified: 1983-07-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1457
Valid CSS Valid XHTML 1.0 Strict