# 2.11BSD#431 - /usr/src/sbin/savecore/savecore.c

##### Functions

    Create            X
    Lseek             X
    Open              X
    Read              X
    Write             X
    check_space       X
    find_dev          X
    get_crashtime     X
    log_entry         X
    main              X
    path              X
    read_kmem         X
    read_number       X
    save_core         X

##### Variables

    boottime          X
    core_vers         X
    days              X
    ddname            X
    debug             X
    dirname           X
    dumpdev           X
    dumplo            X
    dumptime          X
    months            X
    nl                X
    now               X
    panic_mesg        X
    panicstr          X
    physmem           X
    system            X
    vers              X

##### Macros

    BLOCK             X
    CLICK             X
    DAY               X
    LEEWAY            X
    NREGS             X
    REGLOC            X
    SHUTDOWNLOG       X
    X_BOOTIME         X
    X_DUMPDEV         X
    X_DUMPLO          X
    X_PANICSTR        X
    X_PHYSMEM         X
    X_TIME            X
    X_VERSION         X
    eq                X
    ok                X

       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

- in line 310, 317

Lseek defined in line 396; used 9 times

- in line 63, 150, 157-162(3), 215-218(2), 271, 318

Open defined in line 370; used 5 times

- in line 149, 214, 270, 308, 315

Read defined in line 383; used 8 times

- in line 151, 158-163(3), 216, 272, 311, 322

Write defined in line 423; used 3 times

- in line 219, 312, 327

check_space defined in line 258; used 1 times

- in line 91

find_dev defined in line 97; used 3 times

- in line 47, 166, 269

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

- in line 54, 287, 310, 317, 332

read_kmem defined in line 117; used 1 times

- in line 89

read_number defined in line 281; used 2 times

- in line 274, 307

save_core defined in line 299; used 1 times

- in line 92

#### Defined variables

boottime defined in line 50; used 4 times

- in line 163(2), 234-236(2)

core_vers defined in line 58; used 4 times

- in line 183-188(4)

days defined in line 337; used 1 times

- in line 357

ddname defined in line 46; used 7 times

- in line 166-167(2), 178-179(2), 191, 214, 315

debug defined in line 64; used 7 times

- in line 73, 107, 125, 153, 186, 217, 223

dirname defined in line 45; used 7 times

- in line 81-85(3), 250-252(2), 265-266(2)

dumpdev defined in line 48; used 5 times

- in line 151-152(3), 166, 210

dumplo defined in line 51; used 9 times

- in line 158(2), 165, 182, 192-195(2), 215-218(2), 318

dumptime defined in line 49; used 8 times

- in line 216(2), 222-236(6)

months defined in line 341; used 1 times

- in line 357

nl defined in line 26; used 17 times

- in line 123-150(8), 157-162(4), 175, 182, 192, 215-218(2)

now defined in line 53; used 10 times

- in line 88, 228-240(8), 351

panic_mesg defined in line 59; used 4 times

- in line 196-199(3), 360

panicstr defined in line 60; used 5 times

- in line 193-195(4), 359

physmem defined in line 52; used 7 times

- in line 160(2), 320-322(4), 328

system defined in line 44; used 5 times

- in line 83, 169, 212, 308(2)

vers defined in line 57; used 4 times

- in line 176(2), 185-188(2)

#### Defined macros

BLOCK defined in line 297; used 3 times

- in line 302, 322(2)

CLICK defined in line 13; used 4 times

- in line 302, 320-322(2), 328

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

- in line 352

X_BOOTIME defined in line 37; used 2 times

- in line 161-162(2)

X_DUMPDEV defined in line 27; used 2 times

- in line 124, 150

X_DUMPLO defined in line 29; used 2 times

- in line 129, 157

X_PANICSTR defined in line 33; used 2 times

- in line 145, 192

X_PHYSMEM defined in line 35; used 2 times

- in line 137, 159

X_TIME defined in line 31; used 3 times

- in line 133, 215-218(2)

X_VERSION defined in line 39; used 3 times

- in line 141, 175, 182

eq defined in line 21; used 1 times

- in line 185

ok defined in line 22; used 5 times

- in line 182, 192-195(2), 215-218(2)

Last modified: 1995-07-16 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2715 |