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

Defined functions

Create defined in line 433; used 2 times
Lseek defined in line 419; used 11 times
Open defined in line 393; used 6 times
Read defined in line 406; used 9 times
Write defined in line 446; used 3 times
check_space defined in line 273; used 1 times
  • in line 91
find_dev defined in line 97; used 3 times
get_crashtime defined in line 222; used 1 times
  • in line 91
log_entry defined in line 369; used 1 times
  • in line 90
main defined in line 66; never used
path defined in line 261; used 5 times
read_kmem defined in line 134; used 1 times
  • in line 89
read_number defined in line 296; used 2 times
save_core defined in line 314; used 1 times
  • in line 92

Defined variables

bootime defined in line 51; used 4 times
core_vers defined in line 59; used 4 times
days defined in line 360; used 1 times
ddname defined in line 47; used 7 times
debug defined in line 64; used 7 times
dirname defined in line 46; used 7 times
dumpdev defined in line 49; used 5 times
dumplo defined in line 52; used 10 times
dumptime defined in line 50; used 8 times
months defined in line 364; used 1 times
nl defined in line 27; used 17 times
now defined in line 54; used 10 times
panic_mesg defined in line 60; used 4 times
panicstr defined in line 61; used 5 times
physmem defined in line 53; used 7 times
system defined in line 45; used 5 times
vers defined in line 58; used 4 times

Defined macros

BLOCK defined in line 312; used 3 times
CLICK defined in line 14; used 4 times
DAY defined in line 19; used 1 times
  • in line 20
LEEWAY defined in line 20; used 2 times
  • in line 246(2)
NREGS defined in line 16; used 1 times
REGLOC defined in line 15; used 1 times
SHUTDOWNLOG defined in line 25; used 1 times
X_BOOTIME defined in line 38; used 2 times
X_DUMPDEV defined in line 28; used 2 times
X_DUMPLO defined in line 30; used 2 times
X_PANICSTR defined in line 34; used 2 times
X_PHYSMEM defined in line 36; used 2 times
X_TIME defined in line 32; used 3 times
X_VERSION defined in line 40; used 3 times
eq defined in line 22; used 1 times
ok defined in line 23; used 5 times
Last modified: 1983-04-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1660
Valid CSS Valid XHTML 1.0 Strict