*** savecore.c Mon Sep 15 15:03:45 1986 --- /usr/staff/tadl/nfs/usr.etc/savecore.c Sun May 18 18:58:41 1986 *************** *** 1,44 **** --- 1,28 ---- -</* -< * Copyright (c) 1980,1986 Regents of the University of California. -< * All rights reserved. The Berkeley software License Agreement -< * specifies the terms and conditions for redistribution. -< */ -< #ifndef lint !<char copyright[] = !<"@(#) Copyright (c) 1980,1986 Regents of the University of California.\n\ !< All rights reserved.\n"; !<#endif not lint -<#ifndef lint -<static char sccsid[] = "@(#)savecore.c 5.8 (Berkeley) 5/26/86"; -<#endif not lint -< /* * savecore */ -< #include <stdio.h> #include <nlist.h> #include <sys/param.h> #include <sys/dir.h> #include <sys/stat.h> !<#include <sys/fs.h> #include <sys/time.h> -<#include <sys/file.h> -<#include <sys/syslog.h> #define DAY (60L*60L*24L) #define LEEWAY (3*DAY) #define eq(a,b) (!strcmp(a,b)) !<#ifdef vax !<#define ok(number) ((number)&0x7fffffff) !<#else !<#define ok(number) (number) !<#endif !<struct nlist current_nl[] = { /* namelist for currently running system */ #define X_DUMPDEV 0 { "_dumpdev" }, #define X_DUMPLO 1 --------------- #ifndef lint !>/* @(#)savecore.c 2.1 86/04/17 NFSSRC */ !>static char *sccsid = "@(#)savecore.c 1.1 86/02/05 SMI"; /* from UCB 4.13 */ !>#endif /* * savecore */ #include <stdio.h> #include <nlist.h> #include <sys/param.h> #include <sys/dir.h> #include <sys/stat.h> !>#include <sys/vfs.h> #include <sys/time.h> #define DAY (60L*60L*24L) #define LEEWAY (3*DAY) #define eq(a,b) (!strcmp(a,b)) !>#define ok(number) ((number)-KERNELBASE) !>#define SHUTDOWNLOG "/usr/adm/shutdownlog" !> !>struct nlist nl[] = { #define X_DUMPDEV 0 { "_dumpdev" }, #define X_DUMPLO 1 *************** *** 56,72 **** --- 40,45 ---- { "" }, }; -<struct nlist dump_nl[] = { /* name list for dumped system */ -< { "_dumpdev" }, /* entries MUST be the same as */ -< { "_dumplo" }, /* those in current_nl[] */ -< { "_time" }, -< { "_dumpsize" }, -< { "_version" }, -< { "_panicstr" }, -< { "_dumpmag" }, -< { "" }, -<}; -< char *system; char *dirname; /* directory to save dumps in */ char *ddname; /* name of dump device */ --------------- char *system; char *dirname; /* directory to save dumps in */ char *ddname; /* name of dump device */ *************** *** 78,84 **** --- 51,57 ---- int dumpmag; /* magic number in dump */ time_t now; /* current date */ char *path(); !<char *malloc(); char *ctime(); char vers[80]; char core_vers[80]; --------------- int dumpmag; /* magic number in dump */ time_t now; /* current date */ char *path(); !>unsigned malloc(); char *ctime(); char vers[80]; char core_vers[80]; *************** *** 86,162 **** --- 59,105 ---- int panicstr; off_t lseek(); off_t Lseek(); -<int Verbose; -<extern int errno; main(argc, argv) char **argv; int argc; { -< char *cp; !< argc--, argv++; !< while (argc > 0 && argv[0][0] == '-') { !< for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { !< !< case 'v': !< Verbose++; !< break; !< !< default: !< usage: !< fprintf(stderr, !< "usage: savecore [-v] dirname [ system ]\n"); exit(1); } !< argc--, argv++; !< } !< if (argc != 1 && argc != 2) !< goto usage; !< dirname = argv[0]; !< if (argc == 2) !< system = argv[1]; !< openlog("savecore", LOG_ODELAY, LOG_AUTH); !< if (access(dirname, W_OK) < 0) { !< int oerrno = errno; !< perror(dirname); -< errno = oerrno; -< syslog(LOG_ERR, "%s: %m", dirname); exit(1); } read_kmem(); !< if (!dump_exists()) { !< if (Verbose) !< fprintf(stderr, "savecore: No dump exists.\n"); !< exit(0); !< } (void) time(&now); check_kmem(); !< if (panicstr) !< syslog(LOG_CRIT, "reboot after panic: %s", panic_mesg); !< else !< syslog(LOG_CRIT, "reboot"); !< if (!get_crashtime() || !check_space()) !< exit(1); save_core(); clear_dump(); !< exit(0); } dump_exists() { register int dumpfd; int word; !< dumpfd = Open(ddname, O_RDONLY); !< Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET); !< Read(dumpfd, (char *)&word, sizeof (word)); close(dumpfd); -< if (Verbose && word != dumpmag) { -< printf("dumplo = %d (%d bytes)\n", dumplo/DEV_BSIZE, dumplo); -< printf("magic number mismatch: %x != %x\n", word, dumpmag); -< } return (word == dumpmag); } --------------- int panicstr; off_t lseek(); off_t Lseek(); main(argc, argv) char **argv; int argc; { !> if (argc != 2 && argc != 3) { !> fprintf(stderr, "usage: savecore dirname [ system ]\n"); exit(1); } !> dirname = argv[1]; !> if (argc == 3) !> system = argv[2]; !> if (access(dirname, 2) < 0) { perror(dirname); exit(1); } read_kmem(); !> if (dump_exists()) { (void) time(&now); check_kmem(); !> log_entry(); !> if (get_crashtime() && check_space()) { save_core(); clear_dump(); !> } else !> exit(1); } +> return 0; +>} +>int dump_exists() { register int dumpfd; int word; !> dumpfd = Open(ddname, 0); !> Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_DUMPMAG].n_value)), 0); !> Read(dumpfd, (char *)&word, sizeof word); close(dumpfd); return (word == dumpmag); } *************** *** 165,173 **** --- 108,116 ---- register int dumpfd; int zero = 0; !< dumpfd = Open(ddname, O_WRONLY); !< Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET); !< Write(dumpfd, (char *)&zero, sizeof (zero)); close(dumpfd); } --------------- register int dumpfd; int zero = 0; !> dumpfd = Open(ddname, 1); !> Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_DUMPMAG].n_value)), 0); !> Write(dumpfd, (char *)&zero, sizeof zero); close(dumpfd); } *************** *** 193,266 **** --- 136,207 ---- continue; if (dev == statb.st_rdev) { closedir(dfd); !< dp = malloc(strlen(devname)+1); strcpy(dp, devname); !< return (dp); } } closedir(dfd); !< fprintf(stderr, "Can't find device %d/%d\n", major(dev), minor(dev)); !< syslog(LOG_ERR, "Can't find device %d/%d\n", major(dev), minor(dev)); exit(1); /*NOTREACHED*/ } -<int cursyms[] = -< { X_DUMPDEV, X_DUMPLO, X_VERSION, X_DUMPMAG, -1 }; -<int dumpsyms[] = -< { X_TIME, X_DUMPSIZE, X_VERSION, X_PANICSTR, X_DUMPMAG, -1 }; read_kmem() { !< register char *cp; FILE *fp; !< char *dump_sys; !< int kmem, i; !< dump_sys = system ? system : "/vmunix"; !< nlist("/vmunix", current_nl); !< nlist(dump_sys, dump_nl); !< /* !< * Some names we need for the currently running system, !< * others for the system that was running when the dump was made. !< * The values obtained from the current system are used !< * to look for things in /dev/kmem that cannot be found !< * in the dump_sys namelist, but are presumed to be the same !< * (since the disk partitions are probably the same!) !< */ !< for (i = 0; cursyms[i] != -1; i++) !< if (current_nl[cursyms[i]].n_value == 0) { !< fprintf(stderr, "/vmunix: %s not in namelist", !< current_nl[cursyms[i]].n_name); !< syslog(LOG_ERR, "/vmunix: %s not in namelist", !< current_nl[cursyms[i]].n_name); exit(1); } !< for (i = 0; dumpsyms[i] != -1; i++) !< if (dump_nl[dumpsyms[i]].n_value == 0) { !< fprintf(stderr, "%s: %s not in namelist", dump_sys, !< dump_nl[dumpsyms[i]].n_name); !< syslog(LOG_ERR, "%s: %s not in namelist", dump_sys, !< dump_nl[dumpsyms[i]].n_name); exit(1); } !< kmem = Open("/dev/kmem", O_RDONLY); !< Lseek(kmem, (long)current_nl[X_DUMPDEV].n_value, L_SET); Read(kmem, (char *)&dumpdev, sizeof (dumpdev)); !< Lseek(kmem, (long)current_nl[X_DUMPLO].n_value, L_SET); Read(kmem, (char *)&dumplo, sizeof (dumplo)); !< Lseek(kmem, (long)current_nl[X_DUMPMAG].n_value, L_SET); Read(kmem, (char *)&dumpmag, sizeof (dumpmag)); !< dumplo *= DEV_BSIZE; ddname = find_dev(dumpdev, S_IFBLK); !< fp = fdopen(kmem, "r"); !< if (fp == NULL) { !< syslog(LOG_ERR, "Couldn't fdopen kmem"); exit(1); } !< if (system) return; !< fseek(fp, (long)current_nl[X_VERSION].n_value, L_SET); !< fgets(vers, sizeof (vers), fp); fclose(fp); } --------------- continue; if (dev == statb.st_rdev) { closedir(dfd); !> dp = (char *)malloc(strlen(devname)+1); strcpy(dp, devname); !> return dp; } } closedir(dfd); !> fprintf(stderr, "savecore: Can't find device %d,%d\n", !> major(dev), minor(dev)); exit(1); /*NOTREACHED*/ } read_kmem() { !> int kmem; FILE *fp; !> register char *cp; !> nlist("/vmunix", nl); !> if (nl[X_DUMPDEV].n_value == 0) { !> fprintf(stderr, "savecore: /vmunix: dumpdev not in namelist\n"); exit(1); } !> if (nl[X_DUMPLO].n_value == 0) { !> fprintf(stderr, "savecore: /vmunix: dumplo not in namelist\n"); exit(1); } !> if (nl[X_TIME].n_value == 0) { !> fprintf(stderr, "savecore: /vmunix: time not in namelist\n"); !> exit(1); !> } !> if (nl[X_DUMPSIZE].n_value == 0) { !> fprintf(stderr, "savecore: /vmunix: dumpsize not in namelist\n"); !> exit(1); !> } !> if (nl[X_VERSION].n_value == 0) { !> fprintf(stderr, "savecore: /vmunix: version not in namelist\n"); !> exit(1); !> } !> if (nl[X_PANICSTR].n_value == 0) { !> fprintf(stderr, "savecore: /vmunix: panicstr not in namelist\n"); !> exit(1); !> } !> if (nl[X_DUMPMAG].n_value == 0) { !> fprintf(stderr, "savecore: /vmunix: dumpmag not in namelist\n"); !> exit(1); !> } !> kmem = Open("/dev/kmem", 0); !> Lseek(kmem, (long)nl[X_DUMPDEV].n_value, 0); Read(kmem, (char *)&dumpdev, sizeof (dumpdev)); !> Lseek(kmem, (long)nl[X_DUMPLO].n_value, 0); Read(kmem, (char *)&dumplo, sizeof (dumplo)); !> Lseek(kmem, (long)nl[X_DUMPMAG].n_value, 0); Read(kmem, (char *)&dumpmag, sizeof (dumpmag)); !> dumplo *= 512L; ddname = find_dev(dumpdev, S_IFBLK); !> if ((fp = fdopen(kmem, "r")) == NULL) { !> fprintf(stderr, "savecore: Couldn't fdopen kmem\n"); exit(1); } !> if (system) { !> nlist(system, nl); return; !> } !> fseek(fp, (long)nl[X_VERSION].n_value, 0); !> fgets(vers, sizeof vers, fp); fclose(fp); } *************** *** 269,298 **** --- 210,233 ---- FILE *fp; register char *cp; !< fp = fopen(ddname, "r"); !< if (fp == NULL) { !< int oerrno = errno; !< perror(ddname); -< errno = oerrno; -< syslog(LOG_ERR, "%s: %m", ddname); exit(1); } !< fseek(fp, (off_t)(dumplo+ok(dump_nl[X_VERSION].n_value)), L_SET); !< fgets(core_vers, sizeof (core_vers), fp); fclose(fp); !< if (!eq(vers, core_vers) && system == 0) fprintf(stderr, !< "Warning: vmunix version mismatch:\n\t%sand\n\t%s", vers, core_vers); !< syslog(LOG_WARNING, !< "Warning: vmunix version mismatch: %s and %s", !< vers, core_vers); fp = fopen(ddname, "r"); !< fseek(fp, (off_t)(dumplo + ok(dump_nl[X_PANICSTR].n_value)), L_SET); !< fread((char *)&panicstr, sizeof (panicstr), 1, fp); if (panicstr) { !< fseek(fp, dumplo + ok(panicstr), L_SET); cp = panic_mesg; do *cp = getc(fp); --------------- FILE *fp; register char *cp; !> if ((fp = fopen(ddname, "r")) == NULL) { perror(ddname); exit(1); } !> if (!system) { !> fseek(fp, (off_t)(dumplo+ok(nl[X_VERSION].n_value)), 0); !> fgets(core_vers, sizeof core_vers, fp); fclose(fp); !> if (!eq(vers, core_vers)) fprintf(stderr, !> "savecore: Warning: vmunix version mismatch:\n\t%sand\n\t%s", vers, core_vers); !> } fp = fopen(ddname, "r"); !> fseek(fp, (off_t)(dumplo + ok(nl[X_PANICSTR].n_value)), 0); !> fread((char *)&panicstr, sizeof panicstr, 1, fp); if (panicstr) { !> fseek(fp, dumplo + ok(panicstr), 0); cp = panic_mesg; do *cp = getc(fp); *************** *** 306,323 **** --- 241,255 ---- int dumpfd; time_t clobber = (time_t)0; !< dumpfd = Open(ddname, O_RDONLY); !< Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_TIME].n_value)), L_SET); Read(dumpfd, (char *)&dumptime, sizeof dumptime); close(dumpfd); !< if (dumptime == 0) { !< if (Verbose) !< printf("Dump time not found.\n"); return (0); -< } printf("System went down at %s", ctime(&dumptime)); if (dumptime < now - LEEWAY || dumptime > now + LEEWAY) { !< printf("dump time is unreasonable\n"); return (0); } return (1); --------------- int dumpfd; time_t clobber = (time_t)0; !> dumpfd = Open(ddname, 0); !> Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_TIME].n_value)), 0); Read(dumpfd, (char *)&dumptime, sizeof dumptime); close(dumpfd); !> if (dumptime == 0) return (0); printf("System went down at %s", ctime(&dumptime)); if (dumptime < now - LEEWAY || dumptime > now + LEEWAY) { !> printf("Dump time is unreasonable\n"); return (0); } return (1); *************** *** 327,333 **** --- 259,265 ---- path(file) char *file; { !< register char *cp = malloc(strlen(file) + strlen(dirname) + 2); (void) strcpy(cp, dirname); (void) strcat(cp, "/"); --------------- path(file) char *file; { !> register char *cp = (char *)malloc(strlen(file) + strlen(dirname) + 2); (void) strcpy(cp, dirname); (void) strcat(cp, "/"); *************** *** 337,371 **** --- 269,290 ---- check_space() { !< struct stat dsb; !< register char *ddev; int dfd, spacefree; -< struct fs fs; !< if (stat(dirname, &dsb) < 0) { !< int oerrno = errno; !< perror(dirname); -< errno = oerrno; -< syslog(LOG_ERR, "%s: %m", dirname); exit(1); } !< ddev = find_dev(dsb.st_dev, S_IFBLK); !< dfd = Open(ddev, O_RDONLY); !< Lseek(dfd, (long)(SBLOCK * DEV_BSIZE), L_SET); !< Read(dfd, (char *)&fs, sizeof (fs)); !< close(dfd); !< spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024; !< if (spacefree < read_number("minfree")) { !< printf("Dump omitted, not enough space on device"); !< syslog(LOG_WARNING, "Dump omitted, not enough space on device"); return (0); } !< if (freespace(&fs, fs.fs_minfree) < 0) { !< printf("Dump performed, but free space threshold crossed"); !< syslog(LOG_WARNING, !< "Dump performed, but free space threshold crossed"); !< } return (1); } --------------- check_space() { !> struct statfs fsb; int dfd, spacefree; !> if (statfs(dirname, &fsb) < 0) { perror(dirname); exit(1); } !> spacefree = fsb.f_bfree * fsb.f_bsize / 1024; !> if (read_number("minfree") > spacefree) { !> fprintf(stderr, !> "savecore: Dump omitted, not enough space on device\n"); return (0); } !> if (fsb.f_bavail < 0) !> fprintf(stderr, !> "Dump performed, but free space threshold crossed\n"); return (1); } *************** *** 375,382 **** --- 294,300 ---- char lin[80]; register FILE *fp; !< fp = fopen(path(fn), "r"); !< if (fp == NULL) return (0); if (fgets(lin, 80, fp) == NULL) { fclose(fp); --------------- char lin[80]; register FILE *fp; !> if ((fp = fopen(path(fn), "r")) == NULL) return (0); if (fgets(lin, 80, fp) == NULL) { fclose(fp); *************** *** 386,407 **** --- 304,319 ---- return (atoi(lin)); } -<#define BUFPAGES (256*1024/NBPG) /* 1/4 Mb */ -< save_core() { register int n; !< register char *cp; register int ifd, ofd, bounds; register FILE *fp; -< cp = malloc(BUFPAGES*NBPG); -< if (cp == 0) { -< fprintf(stderr, "savecore: Can't allocate i/o buffer.\n"); -< return; -< } bounds = read_number("bounds"); !< ifd = Open(system?system:"/vmunix", O_RDONLY); sprintf(cp, "vmunix.%d", bounds); ofd = Create(path(cp), 0644); while((n = Read(ifd, cp, BUFSIZ)) > 0) --------------- return (atoi(lin)); } save_core() { register int n; !> char buffer[32*NBPG]; !> register char *cp = buffer; register int ifd, ofd, bounds; register FILE *fp; bounds = read_number("bounds"); !> ifd = Open(system?system:"/vmunix", 0); sprintf(cp, "vmunix.%d", bounds); ofd = Create(path(cp), 0644); while((n = Read(ifd, cp, BUFSIZ)) > 0) *************** *** 408,430 **** --- 320,338 ---- Write(ofd, cp, n); close(ifd); close(ofd); !< ifd = Open(ddname, O_RDONLY); !< Lseek(ifd, (off_t)(dumplo + ok(dump_nl[X_DUMPSIZE].n_value)), L_SET); Read(ifd, (char *)&dumpsize, sizeof (dumpsize)); sprintf(cp, "vmcore.%d", bounds); ofd = Create(path(cp), 0644); !< Lseek(ifd, (off_t)dumplo, L_SET); printf("Saving %d bytes of image in vmcore.%d\n", NBPG*dumpsize, bounds); -< syslog(LOG_NOTICE, "Saving %d bytes of image in vmcore.%d\n", -< NBPG*dumpsize, bounds); while (dumpsize > 0) { !< n = Read(ifd, cp, !< (dumpsize > BUFPAGES ? BUFPAGES : dumpsize) * NBPG); !< if (n == 0) { !< syslog(LOG_WARNING, !< "WARNING: vmcore may be incomplete\n"); !< printf("WARNING: vmcore may be incomplete\n"); break; } Write(ofd, cp, n); --------------- Write(ofd, cp, n); close(ifd); close(ofd); !> ifd = Open(ddname, 0); !> Lseek(ifd, (off_t)(dumplo + ok(nl[X_DUMPSIZE].n_value)), 0); Read(ifd, (char *)&dumpsize, sizeof (dumpsize)); sprintf(cp, "vmcore.%d", bounds); ofd = Create(path(cp), 0644); !> Lseek(ifd, (off_t)dumplo, 0); printf("Saving %d bytes of image in vmcore.%d\n", NBPG*dumpsize, bounds); while (dumpsize > 0) { !> n = Read(ifd, cp, (dumpsize > 32 ? 32 : dumpsize) * NBPG); !> if (n <= 0) { !> printf("Dump area was too small - %d pages not saved\n", !> dumpsize); break; } Write(ofd, cp, n); *************** *** 435,446 **** --- 343,383 ---- fp = fopen(path("bounds"), "w"); fprintf(fp, "%d\n", bounds+1); fclose(fp); -< free(cp); } /* * Versions of std routines that exit on error. */ Open(name, rw) char *name; int rw; --------------- fp = fopen(path("bounds"), "w"); fprintf(fp, "%d\n", bounds+1); fclose(fp); } +>char *days[] = { +> "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +>}; +> +>char *months[] = { +> "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", +> "Oct", "Nov", "Dec" +>}; +> +>log_entry() +>{ +> FILE *fp; +> struct tm *tm, *localtime(); +> +> tm = localtime(&now); +> fp = fopen("/usr/adm/shutdownlog", "a"); +> if (fp == 0) +> return; +> fseek(fp, 0L, 2); +> fprintf(fp, "%02d:%02d %s %s %2d, %4d. Reboot", tm->tm_hour, +> tm->tm_min, days[tm->tm_wday], months[tm->tm_mon], +> tm->tm_mday, tm->tm_year + 1900); +> if (panicstr) +> fprintf(fp, " after panic: %s\n", panic_mesg); +> else +> putc('\n', fp); +> fclose(fp); +>} +> /* * Versions of std routines that exit on error. */ +> Open(name, rw) char *name; int rw; *************** *** 447,462 **** --- 384,394 ---- { int fd; !< fd = open(name, rw); !< if (fd < 0) { !< int oerrno = errno; !< perror(name); -< errno = oerrno; -< syslog(LOG_ERR, "%s: %m", name); exit(1); } !< return (fd); } Read(fd, buff, size) --------------- { int fd; !> if ((fd = open(name, rw)) < 0) { perror(name); exit(1); } !> return fd; } Read(fd, buff, size) *************** *** 465,480 **** --- 397,407 ---- { int ret; !< ret = read(fd, buff, size); !< if (ret < 0) { !< int oerrno = errno; !< perror("read"); -< errno = oerrno; -< syslog(LOG_ERR, "read: %m"); exit(1); } !< return (ret); } off_t --------------- { int ret; !> if ((ret = read(fd, buff, size)) < 0) { perror("read"); exit(1); } !> return ret; } off_t *************** *** 484,499 **** --- 411,421 ---- { long ret; !< ret = lseek(fd, off, flag); !< if (ret == -1) { !< int oerrno = errno; !< perror("lseek"); -< errno = oerrno; -< syslog(LOG_ERR, "lseek: %m"); exit(1); } !< return (ret); } Create(file, mode) --------------- { long ret; !> if ((ret = lseek(fd, off, flag)) == -1L) { perror("lseek"); exit(1); } !> return ret; } Create(file, mode) *************** *** 502,517 **** --- 424,434 ---- { register int fd; !< fd = creat(file, mode); !< if (fd < 0) { !< int oerrno = errno; !< perror(file); -< errno = oerrno; -< syslog(LOG_ERR, "%s: %m", file); exit(1); } !< return (fd); } Write(fd, buf, size) --------------- { register int fd; !> if ((fd = creat(file, mode)) < 0) { perror(file); exit(1); } !> return fd; } Write(fd, buf, size) *************** *** 520,530 **** --- 437,443 ---- { if (write(fd, buf, size) < size) { -< int oerrno = errno; -< perror("write"); -< errno = oerrno; -< syslog(LOG_ERR, "write: %m"); exit(1); } } --------------- exit(1); } }