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