Annotation of 42BSD/etc/savecore.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.