|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid = "@(#)savecore.c 4.13 (Berkeley) 83/07/02"; ! 3: #endif ! 4: ! 5: /* ! 6: * savecore ! 7: */ ! 8: #include <stdio.h> ! 9: #include <nlist.h> ! 10: #include <sys/param.h> ! 11: #include <sys/dir.h> ! 12: #include <sys/stat.h> ! 13: #include <sys/fs.h> ! 14: #include <sys/time.h> ! 15: ! 16: #define DAY (60L*60L*24L) ! 17: #define LEEWAY (3*DAY) ! 18: ! 19: #define eq(a,b) (!strcmp(a,b)) ! 20: #ifdef vax ! 21: #define ok(number) ((number)&0x7fffffff) ! 22: #else ! 23: #define ok(number) (number) ! 24: #endif ! 25: ! 26: #define SHUTDOWNLOG "/usr/adm/shutdownlog" ! 27: ! 28: struct nlist nl[] = { ! 29: #define X_DUMPDEV 0 ! 30: { "_dumpdev" }, ! 31: #define X_DUMPLO 1 ! 32: { "_dumplo" }, ! 33: #define X_TIME 2 ! 34: { "_time" }, ! 35: #define X_DUMPSIZE 3 ! 36: { "_dumpsize" }, ! 37: #define X_VERSION 4 ! 38: { "_version" }, ! 39: #define X_PANICSTR 5 ! 40: { "_panicstr" }, ! 41: #define X_DUMPMAG 6 ! 42: { "_dumpmag" }, ! 43: { "" }, ! 44: }; ! 45: ! 46: char *system; ! 47: char *dirname; /* directory to save dumps in */ ! 48: char *ddname; /* name of dump device */ ! 49: char *find_dev(); ! 50: dev_t dumpdev; /* dump device */ ! 51: time_t dumptime; /* time the dump was taken */ ! 52: int dumplo; /* where dump starts on dumpdev */ ! 53: int dumpsize; /* amount of memory dumped */ ! 54: int dumpmag; /* magic number in dump */ ! 55: time_t now; /* current date */ ! 56: char *path(); ! 57: unsigned malloc(); ! 58: char *ctime(); ! 59: char vers[80]; ! 60: char core_vers[80]; ! 61: char panic_mesg[80]; ! 62: int panicstr; ! 63: off_t lseek(); ! 64: off_t Lseek(); ! 65: ! 66: main(argc, argv) ! 67: char **argv; ! 68: int argc; ! 69: { ! 70: ! 71: if (argc != 2 && argc != 3) { ! 72: fprintf(stderr, "usage: savecore dirname [ system ]\n"); ! 73: exit(1); ! 74: } ! 75: dirname = argv[1]; ! 76: if (argc == 3) ! 77: system = argv[2]; ! 78: if (access(dirname, 2) < 0) { ! 79: perror(dirname); ! 80: exit(1); ! 81: } ! 82: read_kmem(); ! 83: if (dump_exists()) { ! 84: (void) time(&now); ! 85: check_kmem(); ! 86: log_entry(); ! 87: if (get_crashtime() && check_space()) { ! 88: save_core(); ! 89: clear_dump(); ! 90: } else ! 91: exit(1); ! 92: } ! 93: return 0; ! 94: } ! 95: ! 96: int ! 97: dump_exists() ! 98: { ! 99: register int dumpfd; ! 100: int word; ! 101: ! 102: dumpfd = Open(ddname, 0); ! 103: Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_DUMPMAG].n_value)), 0); ! 104: Read(dumpfd, (char *)&word, sizeof word); ! 105: close(dumpfd); ! 106: return (word == dumpmag); ! 107: } ! 108: ! 109: clear_dump() ! 110: { ! 111: register int dumpfd; ! 112: int zero = 0; ! 113: ! 114: dumpfd = Open(ddname, 1); ! 115: Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_DUMPMAG].n_value)), 0); ! 116: Write(dumpfd, (char *)&zero, sizeof zero); ! 117: close(dumpfd); ! 118: } ! 119: ! 120: char * ! 121: find_dev(dev, type) ! 122: register dev_t dev; ! 123: register int type; ! 124: { ! 125: register DIR *dfd = opendir("/dev"); ! 126: struct direct *dir; ! 127: struct stat statb; ! 128: static char devname[MAXPATHLEN + 1]; ! 129: char *dp; ! 130: ! 131: strcpy(devname, "/dev/"); ! 132: while ((dir = readdir(dfd))) { ! 133: strcpy(devname + 5, dir->d_name); ! 134: if (stat(devname, &statb)) { ! 135: perror(devname); ! 136: continue; ! 137: } ! 138: if ((statb.st_mode&S_IFMT) != type) ! 139: continue; ! 140: if (dev == statb.st_rdev) { ! 141: closedir(dfd); ! 142: dp = (char *)malloc(strlen(devname)+1); ! 143: strcpy(dp, devname); ! 144: return dp; ! 145: } ! 146: } ! 147: closedir(dfd); ! 148: fprintf(stderr, "savecore: Can't find device %d,%d\n", ! 149: major(dev), minor(dev)); ! 150: exit(1); ! 151: /*NOTREACHED*/ ! 152: } ! 153: ! 154: read_kmem() ! 155: { ! 156: int kmem; ! 157: FILE *fp; ! 158: register char *cp; ! 159: ! 160: nlist("/vmunix", nl); ! 161: if (nl[X_DUMPDEV].n_value == 0) { ! 162: fprintf(stderr, "savecore: /vmunix: dumpdev not in namelist\n"); ! 163: exit(1); ! 164: } ! 165: if (nl[X_DUMPLO].n_value == 0) { ! 166: fprintf(stderr, "savecore: /vmunix: dumplo not in namelist\n"); ! 167: exit(1); ! 168: } ! 169: if (nl[X_TIME].n_value == 0) { ! 170: fprintf(stderr, "savecore: /vmunix: time not in namelist\n"); ! 171: exit(1); ! 172: } ! 173: if (nl[X_DUMPSIZE].n_value == 0) { ! 174: fprintf(stderr, "savecore: /vmunix: dumpsize not in namelist\n"); ! 175: exit(1); ! 176: } ! 177: if (nl[X_VERSION].n_value == 0) { ! 178: fprintf(stderr, "savecore: /vmunix: version not in namelist\n"); ! 179: exit(1); ! 180: } ! 181: if (nl[X_PANICSTR].n_value == 0) { ! 182: fprintf(stderr, "savecore: /vmunix: panicstr not in namelist\n"); ! 183: exit(1); ! 184: } ! 185: if (nl[X_DUMPMAG].n_value == 0) { ! 186: fprintf(stderr, "savecore: /vmunix: dumpmag not in namelist\n"); ! 187: exit(1); ! 188: } ! 189: kmem = Open("/dev/kmem", 0); ! 190: Lseek(kmem, (long)nl[X_DUMPDEV].n_value, 0); ! 191: Read(kmem, (char *)&dumpdev, sizeof (dumpdev)); ! 192: Lseek(kmem, (long)nl[X_DUMPLO].n_value, 0); ! 193: Read(kmem, (char *)&dumplo, sizeof (dumplo)); ! 194: Lseek(kmem, (long)nl[X_DUMPMAG].n_value, 0); ! 195: Read(kmem, (char *)&dumpmag, sizeof (dumpmag)); ! 196: dumplo *= 512L; ! 197: ddname = find_dev(dumpdev, S_IFBLK); ! 198: if ((fp = fdopen(kmem, "r")) == NULL) { ! 199: fprintf(stderr, "savecore: Couldn't fdopen kmem\n"); ! 200: exit(1); ! 201: } ! 202: if (system) ! 203: return; ! 204: fseek(fp, (long)nl[X_VERSION].n_value, 0); ! 205: fgets(vers, sizeof vers, fp); ! 206: fclose(fp); ! 207: } ! 208: ! 209: check_kmem() ! 210: { ! 211: FILE *fp; ! 212: register char *cp; ! 213: ! 214: if ((fp = fopen(ddname, "r")) == NULL) { ! 215: perror(ddname); ! 216: exit(1); ! 217: } ! 218: fseek(fp, (off_t)(dumplo+ok(nl[X_VERSION].n_value)), 0); ! 219: fgets(core_vers, sizeof core_vers, fp); ! 220: fclose(fp); ! 221: if (!eq(vers, core_vers)) ! 222: fprintf(stderr, ! 223: "savecore: Warning: vmunix version mismatch:\n\t%sand\n\t%s", ! 224: vers, core_vers); ! 225: fp = fopen(ddname, "r"); ! 226: fseek(fp, (off_t)(dumplo + ok(nl[X_PANICSTR].n_value)), 0); ! 227: fread((char *)&panicstr, sizeof panicstr, 1, fp); ! 228: if (panicstr) { ! 229: fseek(fp, dumplo + ok(panicstr), 0); ! 230: cp = panic_mesg; ! 231: do ! 232: *cp = getc(fp); ! 233: while (*cp++); ! 234: } ! 235: fclose(fp); ! 236: } ! 237: ! 238: get_crashtime() ! 239: { ! 240: int dumpfd; ! 241: time_t clobber = (time_t)0; ! 242: ! 243: if (system) ! 244: return (1); ! 245: dumpfd = Open(ddname, 0); ! 246: Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_TIME].n_value)), 0); ! 247: Read(dumpfd, (char *)&dumptime, sizeof dumptime); ! 248: close(dumpfd); ! 249: if (dumptime == 0) ! 250: return (0); ! 251: printf("System went down at %s", ctime(&dumptime)); ! 252: if (dumptime < now - LEEWAY || dumptime > now + LEEWAY) { ! 253: printf("Dump time is unreasonable\n"); ! 254: return (0); ! 255: } ! 256: return (1); ! 257: } ! 258: ! 259: char * ! 260: path(file) ! 261: char *file; ! 262: { ! 263: register char *cp = (char *)malloc(strlen(file) + strlen(dirname) + 2); ! 264: ! 265: (void) strcpy(cp, dirname); ! 266: (void) strcat(cp, "/"); ! 267: (void) strcat(cp, file); ! 268: return (cp); ! 269: } ! 270: ! 271: check_space() ! 272: { ! 273: struct stat dsb; ! 274: register char *ddev; ! 275: int dfd, spacefree; ! 276: struct fs fs; ! 277: ! 278: if (stat(dirname, &dsb) < 0) { ! 279: perror(dirname); ! 280: exit(1); ! 281: } ! 282: ddev = find_dev(dsb.st_dev, S_IFBLK); ! 283: dfd = Open(ddev, 0); ! 284: Lseek(dfd, (long)(SBLOCK * DEV_BSIZE), 0); ! 285: Read(dfd, (char *)&fs, sizeof fs); ! 286: close(dfd); ! 287: spacefree = fs.fs_cstotal.cs_nbfree * fs.fs_bsize / 1024; ! 288: if (read_number("minfree") > spacefree) { ! 289: fprintf(stderr, ! 290: "savecore: Dump omitted, not enough space on device\n"); ! 291: return (0); ! 292: } ! 293: if (fs.fs_cstotal.cs_nbfree * fs.fs_frag + fs.fs_cstotal.cs_nffree < ! 294: fs.fs_dsize * fs.fs_minfree / 100) ! 295: fprintf(stderr, ! 296: "Dump performed, but free space threshold crossed\n"); ! 297: return (1); ! 298: } ! 299: ! 300: read_number(fn) ! 301: char *fn; ! 302: { ! 303: char lin[80]; ! 304: register FILE *fp; ! 305: ! 306: if ((fp = fopen(path(fn), "r")) == NULL) ! 307: return (0); ! 308: if (fgets(lin, 80, fp) == NULL) { ! 309: fclose(fp); ! 310: return (0); ! 311: } ! 312: fclose(fp); ! 313: return (atoi(lin)); ! 314: } ! 315: ! 316: save_core() ! 317: { ! 318: register int n; ! 319: char buffer[32*NBPG]; ! 320: register char *cp = buffer; ! 321: register int ifd, ofd, bounds; ! 322: register FILE *fp; ! 323: ! 324: bounds = read_number("bounds"); ! 325: ifd = Open(system?system:"/vmunix", 0); ! 326: sprintf(cp, "vmunix.%d", bounds); ! 327: ofd = Create(path(cp), 0644); ! 328: while((n = Read(ifd, cp, BUFSIZ)) > 0) ! 329: Write(ofd, cp, n); ! 330: close(ifd); ! 331: close(ofd); ! 332: ifd = Open(ddname, 0); ! 333: Lseek(ifd, (off_t)(dumplo + ok(nl[X_DUMPSIZE].n_value)), 0); ! 334: Read(ifd, (char *)&dumpsize, sizeof (dumpsize)); ! 335: sprintf(cp, "vmcore.%d", bounds); ! 336: ofd = Create(path(cp), 0644); ! 337: Lseek(ifd, (off_t)dumplo, 0); ! 338: printf("Saving %d bytes of image in vmcore.%d\n", NBPG*dumpsize, ! 339: bounds); ! 340: while (dumpsize > 0) { ! 341: n = Read(ifd, cp, (dumpsize > 32 ? 32 : dumpsize) * NBPG); ! 342: Write(ofd, cp, n); ! 343: dumpsize -= n/NBPG; ! 344: } ! 345: close(ifd); ! 346: close(ofd); ! 347: fp = fopen(path("bounds"), "w"); ! 348: fprintf(fp, "%d\n", bounds+1); ! 349: fclose(fp); ! 350: } ! 351: ! 352: char *days[] = { ! 353: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ! 354: }; ! 355: ! 356: char *months[] = { ! 357: "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", ! 358: "Oct", "Nov", "Dec" ! 359: }; ! 360: ! 361: log_entry() ! 362: { ! 363: FILE *fp; ! 364: struct tm *tm, *localtime(); ! 365: ! 366: tm = localtime(&now); ! 367: fp = fopen("/usr/adm/shutdownlog", "a"); ! 368: if (fp == 0) ! 369: return; ! 370: fseek(fp, 0L, 2); ! 371: fprintf(fp, "%02d:%02d %s %s %2d, %4d. Reboot", tm->tm_hour, ! 372: tm->tm_min, days[tm->tm_wday], months[tm->tm_mon], ! 373: tm->tm_mday, tm->tm_year + 1900); ! 374: if (panicstr) ! 375: fprintf(fp, " after panic: %s\n", panic_mesg); ! 376: else ! 377: putc('\n', fp); ! 378: fclose(fp); ! 379: } ! 380: ! 381: /* ! 382: * Versions of std routines that exit on error. ! 383: */ ! 384: ! 385: Open(name, rw) ! 386: char *name; ! 387: int rw; ! 388: { ! 389: int fd; ! 390: ! 391: if ((fd = open(name, rw)) < 0) { ! 392: perror(name); ! 393: exit(1); ! 394: } ! 395: return fd; ! 396: } ! 397: ! 398: Read(fd, buff, size) ! 399: int fd, size; ! 400: char *buff; ! 401: { ! 402: int ret; ! 403: ! 404: if ((ret = read(fd, buff, size)) < 0) { ! 405: perror("read"); ! 406: exit(1); ! 407: } ! 408: return ret; ! 409: } ! 410: ! 411: off_t ! 412: Lseek(fd, off, flag) ! 413: int fd, flag; ! 414: long off; ! 415: { ! 416: long ret; ! 417: ! 418: if ((ret = lseek(fd, off, flag)) == -1L) { ! 419: perror("lseek"); ! 420: exit(1); ! 421: } ! 422: return ret; ! 423: } ! 424: ! 425: Create(file, mode) ! 426: char *file; ! 427: int mode; ! 428: { ! 429: register int fd; ! 430: ! 431: if ((fd = creat(file, mode)) < 0) { ! 432: perror(file); ! 433: exit(1); ! 434: } ! 435: return fd; ! 436: } ! 437: ! 438: Write(fd, buf, size) ! 439: int fd, size; ! 440: char *buf; ! 441: { ! 442: ! 443: if (write(fd, buf, size) < size) { ! 444: perror("write"); ! 445: exit(1); ! 446: } ! 447: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.