|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980, 1988 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.3 (Berkeley) 2/15/90"; ! 9: #endif not lint ! 10: ! 11: #include "dump.h" ! 12: #include <sys/time.h> ! 13: #include "pathnames.h" ! 14: ! 15: /* ! 16: * This is from /usr/include/grp.h ! 17: * That defined struct group, which conflicts ! 18: * with the struct group defined in param.h ! 19: */ ! 20: struct Group { /* see getgrent(3) */ ! 21: char *gr_name; ! 22: char *gr_passwd; ! 23: int gr_gid; ! 24: char **gr_mem; ! 25: }; ! 26: struct Group *getgrnam(); ! 27: /* ! 28: * Query the operator; This previously-fascist piece of code ! 29: * no longer requires an exact response. ! 30: * It is intended to protect dump aborting by inquisitive ! 31: * people banging on the console terminal to see what is ! 32: * happening which might cause dump to croak, destroying ! 33: * a large number of hours of work. ! 34: * ! 35: * Every 2 minutes we reprint the message, alerting others ! 36: * that dump needs attention. ! 37: */ ! 38: int timeout; ! 39: char *attnmessage; /* attention message */ ! 40: query(question) ! 41: char *question; ! 42: { ! 43: char replybuffer[64]; ! 44: int back; ! 45: FILE *mytty; ! 46: ! 47: if ( (mytty = fopen(_PATH_TTY, "r")) == NULL){ ! 48: msg("fopen on %s fails\n", _PATH_TTY); ! 49: abort(); ! 50: } ! 51: attnmessage = question; ! 52: timeout = 0; ! 53: alarmcatch(); ! 54: for(;;){ ! 55: if ( fgets(replybuffer, 63, mytty) == NULL){ ! 56: if (ferror(mytty)){ ! 57: clearerr(mytty); ! 58: continue; ! 59: } ! 60: } else if (replybuffer[0] == 'y' || replybuffer[0] == 'Y') { ! 61: back = 1; ! 62: goto done; ! 63: } else if (replybuffer[0] == 'n' || replybuffer[0] == 'N') { ! 64: back = 0; ! 65: goto done; ! 66: } else { ! 67: fprintf(stderr, " DUMP: \"Yes\" or \"No\"?\n"); ! 68: fprintf(stderr," DUMP: %s: (\"yes\" or \"no\") ", ! 69: question); ! 70: } ! 71: } ! 72: done: ! 73: /* ! 74: * Turn off the alarm, and reset the signal to trap out.. ! 75: */ ! 76: alarm(0); ! 77: if (signal(SIGALRM, sigalrm) == SIG_IGN) ! 78: signal(SIGALRM, SIG_IGN); ! 79: fclose(mytty); ! 80: return(back); ! 81: } ! 82: ! 83: char lastmsg[100]; ! 84: ! 85: /* ! 86: * Alert the console operator, and enable the alarm clock to ! 87: * sleep for 2 minutes in case nobody comes to satisfy dump ! 88: */ ! 89: alarmcatch() ! 90: { ! 91: if (notify == 0) { ! 92: if (timeout == 0) ! 93: fprintf(stderr," DUMP: %s: (\"yes\" or \"no\") ", ! 94: attnmessage); ! 95: else ! 96: msgtail("\7\7"); ! 97: } else { ! 98: if (timeout) { ! 99: msgtail("\n"); ! 100: broadcast(""); /* just print last msg */ ! 101: } ! 102: fprintf(stderr," DUMP: %s: (\"yes\" or \"no\") ", ! 103: attnmessage); ! 104: } ! 105: signal(SIGALRM, alarmcatch); ! 106: alarm(120); ! 107: timeout = 1; ! 108: } ! 109: /* ! 110: * Here if an inquisitive operator interrupts the dump program ! 111: */ ! 112: interrupt() ! 113: { ! 114: msg("Interrupt received.\n"); ! 115: if (query("Do you want to abort dump?")) ! 116: dumpabort(); ! 117: } ! 118: ! 119: /* ! 120: * The following variables and routines manage alerting ! 121: * operators to the status of dump. ! 122: * This works much like wall(1) does. ! 123: */ ! 124: struct Group *gp; ! 125: ! 126: /* ! 127: * Get the names from the group entry "operator" to notify. ! 128: */ ! 129: set_operators() ! 130: { ! 131: if (!notify) /*not going to notify*/ ! 132: return; ! 133: gp = getgrnam(OPGRENT); ! 134: endgrent(); ! 135: if (gp == (struct Group *)0){ ! 136: msg("No group entry for %s.\n", ! 137: OPGRENT); ! 138: notify = 0; ! 139: return; ! 140: } ! 141: } ! 142: ! 143: struct tm *localtime(); ! 144: struct tm *localclock; ! 145: ! 146: /* ! 147: * We fork a child to do the actual broadcasting, so ! 148: * that the process control groups are not messed up ! 149: */ ! 150: broadcast(message) ! 151: char *message; ! 152: { ! 153: time_t clock; ! 154: FILE *f_utmp; ! 155: struct utmp utmp; ! 156: int nusers; ! 157: char **np; ! 158: int pid, s; ! 159: ! 160: switch (pid = fork()) { ! 161: case -1: ! 162: return; ! 163: case 0: ! 164: break; ! 165: default: ! 166: while (wait(&s) != pid) ! 167: continue; ! 168: return; ! 169: } ! 170: ! 171: if (!notify || gp == 0) ! 172: exit(0); ! 173: clock = time(0); ! 174: localclock = localtime(&clock); ! 175: ! 176: if((f_utmp = fopen(_PATH_UTMP, "r")) == NULL) { ! 177: msg("Cannot open %s\n", _PATH_UTMP); ! 178: return; ! 179: } ! 180: ! 181: nusers = 0; ! 182: while (!feof(f_utmp)){ ! 183: if (fread(&utmp, sizeof (struct utmp), 1, f_utmp) != 1) ! 184: break; ! 185: if (utmp.ut_name[0] == 0) ! 186: continue; ! 187: nusers++; ! 188: for (np = gp->gr_mem; *np; np++){ ! 189: if (strncmp(*np, utmp.ut_name, sizeof(utmp.ut_name)) != 0) ! 190: continue; ! 191: /* ! 192: * Do not send messages to operators on dialups ! 193: */ ! 194: if (strncmp(utmp.ut_line, DIALUP, strlen(DIALUP)) == 0) ! 195: continue; ! 196: #ifdef DEBUG ! 197: msg("Message to %s at %s\n", ! 198: utmp.ut_name, utmp.ut_line); ! 199: #endif DEBUG ! 200: sendmes(utmp.ut_line, message); ! 201: } ! 202: } ! 203: fclose(f_utmp); ! 204: Exit(0); /* the wait in this same routine will catch this */ ! 205: /* NOTREACHED */ ! 206: } ! 207: ! 208: sendmes(tty, message) ! 209: char *tty, *message; ! 210: { ! 211: char t[50], buf[BUFSIZ]; ! 212: register char *cp; ! 213: int lmsg = 1; ! 214: FILE *f_tty; ! 215: ! 216: strcpy(t, _PATH_DEV); ! 217: strcat(t, tty); ! 218: ! 219: if((f_tty = fopen(t, "w")) != NULL) { ! 220: setbuf(f_tty, buf); ! 221: fprintf(f_tty, "\n\07\07\07Message from the dump program to all operators at %d:%02d ...\r\n\n DUMP: NEEDS ATTENTION: " ! 222: ,localclock->tm_hour ! 223: ,localclock->tm_min); ! 224: for (cp = lastmsg; ; cp++) { ! 225: if (*cp == '\0') { ! 226: if (lmsg) { ! 227: cp = message; ! 228: if (*cp == '\0') ! 229: break; ! 230: lmsg = 0; ! 231: } else ! 232: break; ! 233: } ! 234: if (*cp == '\n') ! 235: putc('\r', f_tty); ! 236: putc(*cp, f_tty); ! 237: } ! 238: fclose(f_tty); ! 239: } ! 240: } ! 241: ! 242: /* ! 243: * print out an estimate of the amount of time left to do the dump ! 244: */ ! 245: ! 246: time_t tschedule = 0; ! 247: ! 248: timeest() ! 249: { ! 250: time_t tnow, deltat; ! 251: ! 252: time (&tnow); ! 253: if (tnow >= tschedule){ ! 254: tschedule = tnow + 300; ! 255: if (blockswritten < 500) ! 256: return; ! 257: deltat = tstart_writing - tnow + ! 258: (((1.0*(tnow - tstart_writing))/blockswritten) * esize); ! 259: msg("%3.2f%% done, finished in %d:%02d\n", ! 260: (blockswritten*100.0)/esize, ! 261: deltat/3600, (deltat%3600)/60); ! 262: } ! 263: } ! 264: ! 265: int blocksontape() ! 266: { ! 267: /* ! 268: * esize: total number of blocks estimated over all reels ! 269: * blockswritten: blocks actually written, over all reels ! 270: * etapes: estimated number of tapes to write ! 271: * ! 272: * tsize: blocks can write on this reel ! 273: * asize: blocks written on this reel ! 274: * tapeno: number of tapes written so far ! 275: */ ! 276: if (tapeno == etapes) ! 277: return(esize - (etapes - 1)*tsize); ! 278: return(tsize); ! 279: } ! 280: ! 281: /* VARARGS1 */ ! 282: /* ARGSUSED */ ! 283: msg(fmt, a1, a2, a3, a4, a5) ! 284: char *fmt; ! 285: int a1, a2, a3, a4, a5; ! 286: { ! 287: fprintf(stderr," DUMP: "); ! 288: #ifdef TDEBUG ! 289: fprintf(stderr,"pid=%d ", getpid()); ! 290: #endif ! 291: fprintf(stderr, fmt, a1, a2, a3, a4, a5); ! 292: fflush(stdout); ! 293: fflush(stderr); ! 294: sprintf(lastmsg, fmt, a1, a2, a3, a4, a5); ! 295: } ! 296: ! 297: /* VARARGS1 */ ! 298: /* ARGSUSED */ ! 299: msgtail(fmt, a1, a2, a3, a4, a5) ! 300: char *fmt; ! 301: int a1, a2, a3, a4, a5; ! 302: { ! 303: fprintf(stderr, fmt, a1, a2, a3, a4, a5); ! 304: } ! 305: /* ! 306: * Tell the operator what has to be done; ! 307: * we don't actually do it ! 308: */ ! 309: ! 310: struct fstab * ! 311: allocfsent(fs) ! 312: register struct fstab *fs; ! 313: { ! 314: register struct fstab *new; ! 315: register char *cp; ! 316: char *malloc(); ! 317: ! 318: new = (struct fstab *)malloc(sizeof (*fs)); ! 319: cp = malloc(strlen(fs->fs_file) + 1); ! 320: strcpy(cp, fs->fs_file); ! 321: new->fs_file = cp; ! 322: cp = malloc(strlen(fs->fs_type) + 1); ! 323: strcpy(cp, fs->fs_type); ! 324: new->fs_type = cp; ! 325: cp = malloc(strlen(fs->fs_spec) + 1); ! 326: strcpy(cp, fs->fs_spec); ! 327: new->fs_spec = cp; ! 328: new->fs_passno = fs->fs_passno; ! 329: new->fs_freq = fs->fs_freq; ! 330: return (new); ! 331: } ! 332: ! 333: struct pfstab { ! 334: struct pfstab *pf_next; ! 335: struct fstab *pf_fstab; ! 336: }; ! 337: ! 338: static struct pfstab *table = NULL; ! 339: ! 340: getfstab() ! 341: { ! 342: register struct fstab *fs; ! 343: register struct pfstab *pf; ! 344: ! 345: if (setfsent() == 0) { ! 346: msg("Can't open %s for dump table information.\n", _PATH_FSTAB); ! 347: return; ! 348: } ! 349: while (fs = getfsent()) { ! 350: if (strcmp(fs->fs_type, FSTAB_RW) && ! 351: strcmp(fs->fs_type, FSTAB_RO) && ! 352: strcmp(fs->fs_type, FSTAB_RQ)) ! 353: continue; ! 354: fs = allocfsent(fs); ! 355: pf = (struct pfstab *)malloc(sizeof (*pf)); ! 356: pf->pf_fstab = fs; ! 357: pf->pf_next = table; ! 358: table = pf; ! 359: } ! 360: endfsent(); ! 361: } ! 362: ! 363: /* ! 364: * Search in the fstab for a file name. ! 365: * This file name can be either the special or the path file name. ! 366: * ! 367: * The entries in the fstab are the BLOCK special names, not the ! 368: * character special names. ! 369: * The caller of fstabsearch assures that the character device ! 370: * is dumped (that is much faster) ! 371: * ! 372: * The file name can omit the leading '/'. ! 373: */ ! 374: struct fstab * ! 375: fstabsearch(key) ! 376: char *key; ! 377: { ! 378: register struct pfstab *pf; ! 379: register struct fstab *fs; ! 380: char *rawname(); ! 381: ! 382: if (table == NULL) ! 383: return ((struct fstab *)0); ! 384: for (pf = table; pf; pf = pf->pf_next) { ! 385: fs = pf->pf_fstab; ! 386: if (strcmp(fs->fs_file, key) == 0) ! 387: return (fs); ! 388: if (strcmp(fs->fs_spec, key) == 0) ! 389: return (fs); ! 390: if (strcmp(rawname(fs->fs_spec), key) == 0) ! 391: return (fs); ! 392: if (key[0] != '/'){ ! 393: if (*fs->fs_spec == '/' && ! 394: strcmp(fs->fs_spec + 1, key) == 0) ! 395: return (fs); ! 396: if (*fs->fs_file == '/' && ! 397: strcmp(fs->fs_file + 1, key) == 0) ! 398: return (fs); ! 399: } ! 400: } ! 401: return (0); ! 402: } ! 403: ! 404: /* ! 405: * Tell the operator what to do ! 406: */ ! 407: lastdump(arg) ! 408: char arg; /* w ==> just what to do; W ==> most recent dumps */ ! 409: { ! 410: char *lastname; ! 411: char *date; ! 412: register int i; ! 413: time_t tnow; ! 414: register struct fstab *dt; ! 415: int dumpme; ! 416: register struct idates *itwalk; ! 417: ! 418: int idatesort(); ! 419: ! 420: time(&tnow); ! 421: getfstab(); /* /etc/fstab input */ ! 422: inititimes(); /* /etc/dumpdates input */ ! 423: qsort(idatev, nidates, sizeof(struct idates *), idatesort); ! 424: ! 425: if (arg == 'w') ! 426: fprintf(stdout, "Dump these file systems:\n"); ! 427: else ! 428: fprintf(stdout, "Last dump(s) done (Dump '>' file systems):\n"); ! 429: lastname = "??"; ! 430: ITITERATE(i, itwalk){ ! 431: if (strncmp(lastname, itwalk->id_name, sizeof(itwalk->id_name)) == 0) ! 432: continue; ! 433: date = (char *)ctime(&itwalk->id_ddate); ! 434: date[16] = '\0'; /* blast away seconds and year */ ! 435: lastname = itwalk->id_name; ! 436: dt = fstabsearch(itwalk->id_name); ! 437: dumpme = ( (dt != 0) ! 438: && (dt->fs_freq != 0) ! 439: && (itwalk->id_ddate < tnow - (dt->fs_freq*DAY))); ! 440: if ( (arg != 'w') || dumpme) ! 441: fprintf(stdout,"%c %8s\t(%6s) Last dump: Level %c, Date %s\n", ! 442: dumpme && (arg != 'w') ? '>' : ' ', ! 443: itwalk->id_name, ! 444: dt ? dt->fs_file : "", ! 445: itwalk->id_incno, ! 446: date ! 447: ); ! 448: } ! 449: } ! 450: ! 451: int idatesort(p1, p2) ! 452: struct idates **p1, **p2; ! 453: { ! 454: int diff; ! 455: ! 456: diff = strncmp((*p1)->id_name, (*p2)->id_name, sizeof((*p1)->id_name)); ! 457: if (diff == 0) ! 458: return ((*p2)->id_ddate - (*p1)->id_ddate); ! 459: else ! 460: return (diff); ! 461: } ! 462: ! 463: int max(a,b) ! 464: int a, b; ! 465: { ! 466: return(a>b?a:b); ! 467: } ! 468: int min(a,b) ! 469: int a, b; ! 470: { ! 471: return(a<b?a:b); ! 472: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.