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

Defined functions

Create defined in line 410; used 2 times
Lseek defined in line 396; used 9 times
Open defined in line 370; used 5 times
Read defined in line 383; used 8 times
Write defined in line 423; used 3 times
check_space defined in line 258; used 1 times
  • in line 91
find_dev defined in line 97; used 3 times
get_crashtime defined in line 205; used 1 times
  • in line 91
log_entry defined in line 346; used 1 times
  • in line 90
main defined in line 66; never used
path defined in line 246; used 5 times
read_kmem defined in line 117; used 1 times
  • in line 89
read_number defined in line 281; used 2 times
save_core defined in line 299; used 1 times
  • in line 92

Defined variables

boottime defined in line 50; used 4 times
core_vers defined in line 58; used 4 times
days defined in line 337; used 1 times
ddname defined in line 46; used 7 times
debug defined in line 64; used 7 times
dirname defined in line 45; used 7 times
dumpdev defined in line 48; used 5 times
dumplo defined in line 51; used 9 times
dumptime defined in line 49; used 8 times
months defined in line 341; used 1 times
nl defined in line 26; used 17 times
now defined in line 53; used 10 times
panic_mesg defined in line 59; used 4 times
panicstr defined in line 60; used 5 times
physmem defined in line 52; used 7 times
system defined in line 44; used 5 times
vers defined in line 57; used 4 times

Defined macros

BLOCK defined in line 297; used 3 times
CLICK defined in line 13; used 4 times
DAY defined in line 18; used 1 times
  • in line 19
LEEWAY defined in line 19; used 2 times
  • in line 228(2)
NREGS defined in line 15; never used
REGLOC defined in line 14; never used
SHUTDOWNLOG defined in line 24; used 1 times
X_BOOTIME defined in line 37; used 2 times
X_DUMPDEV defined in line 27; used 2 times
X_DUMPLO defined in line 29; used 2 times
X_PANICSTR defined in line 33; used 2 times
X_PHYSMEM defined in line 35; used 2 times
X_TIME defined in line 31; used 3 times
X_VERSION defined in line 39; used 3 times
eq defined in line 21; used 1 times
ok defined in line 22; used 5 times
Last modified: 1995-07-16
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5187
Valid CSS Valid XHTML 1.0 Strict