Annotation of 43BSD/etc/savecore.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1980,1986 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  */
        !             6: 
        !             7: #ifndef lint
        !             8: char copyright[] =
        !             9: "@(#) Copyright (c) 1980,1986 Regents of the University of California.\n\
        !            10:  All rights reserved.\n";
        !            11: #endif not lint
        !            12: 
        !            13: #ifndef lint
        !            14: static char sccsid[] = "@(#)savecore.c 5.8 (Berkeley) 5/26/86";
        !            15: #endif not lint
        !            16: 
        !            17: /*
        !            18:  * savecore
        !            19:  */
        !            20: 
        !            21: #include <stdio.h>
        !            22: #include <nlist.h>
        !            23: #include <sys/param.h>
        !            24: #include <sys/dir.h>
        !            25: #include <sys/stat.h>
        !            26: #include <sys/fs.h>
        !            27: #include <sys/time.h>
        !            28: #include <sys/file.h>
        !            29: #include <sys/syslog.h>
        !            30: 
        !            31: #define        DAY     (60L*60L*24L)
        !            32: #define        LEEWAY  (3*DAY)
        !            33: 
        !            34: #define eq(a,b) (!strcmp(a,b))
        !            35: #ifdef vax
        !            36: #define ok(number) ((number)&0x7fffffff)
        !            37: #else
        !            38: #define ok(number) (number)
        !            39: #endif
        !            40: 
        !            41: struct nlist current_nl[] = {  /* namelist for currently running system */
        !            42: #define X_DUMPDEV      0
        !            43:        { "_dumpdev" },
        !            44: #define X_DUMPLO       1
        !            45:        { "_dumplo" },
        !            46: #define X_TIME         2
        !            47:        { "_time" },
        !            48: #define        X_DUMPSIZE      3
        !            49:        { "_dumpsize" },
        !            50: #define X_VERSION      4
        !            51:        { "_version" },
        !            52: #define X_PANICSTR     5
        !            53:        { "_panicstr" },
        !            54: #define        X_DUMPMAG       6
        !            55:        { "_dumpmag" },
        !            56:        { "" },
        !            57: };
        !            58: 
        !            59: struct nlist dump_nl[] = {     /* name list for dumped system */
        !            60:        { "_dumpdev" },         /* entries MUST be the same as */
        !            61:        { "_dumplo" },          /*      those in current_nl[]  */
        !            62:        { "_time" },
        !            63:        { "_dumpsize" },
        !            64:        { "_version" },
        !            65:        { "_panicstr" },
        !            66:        { "_dumpmag" },
        !            67:        { "" },
        !            68: };
        !            69: 
        !            70: char   *system;
        !            71: char   *dirname;                       /* directory to save dumps in */
        !            72: char   *ddname;                        /* name of dump device */
        !            73: char   *find_dev();
        !            74: dev_t  dumpdev;                        /* dump device */
        !            75: time_t dumptime;                       /* time the dump was taken */
        !            76: int    dumplo;                         /* where dump starts on dumpdev */
        !            77: int    dumpsize;                       /* amount of memory dumped */
        !            78: int    dumpmag;                        /* magic number in dump */
        !            79: time_t now;                            /* current date */
        !            80: char   *path();
        !            81: char   *malloc();
        !            82: char   *ctime();
        !            83: char   vers[80];
        !            84: char   core_vers[80];
        !            85: char   panic_mesg[80];
        !            86: int    panicstr;
        !            87: off_t  lseek();
        !            88: off_t  Lseek();
        !            89: int    Verbose;
        !            90: extern int errno;
        !            91: 
        !            92: main(argc, argv)
        !            93:        char **argv;
        !            94:        int argc;
        !            95: {
        !            96:        char *cp;
        !            97: 
        !            98:        argc--, argv++;
        !            99:        while (argc > 0 && argv[0][0] == '-') {
        !           100:                for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
        !           101: 
        !           102:                case 'v':
        !           103:                        Verbose++;
        !           104:                        break;
        !           105: 
        !           106:                default:
        !           107:                usage:
        !           108:                        fprintf(stderr,
        !           109:                            "usage: savecore [-v] dirname [ system ]\n");
        !           110:                        exit(1);
        !           111:                }
        !           112:                argc--, argv++;
        !           113:        }
        !           114:        if (argc != 1 && argc != 2)
        !           115:                goto usage;
        !           116:        dirname = argv[0];
        !           117:        if (argc == 2)
        !           118:                system = argv[1];
        !           119:        openlog("savecore", LOG_ODELAY, LOG_AUTH);
        !           120:        if (access(dirname, W_OK) < 0) {
        !           121:                int oerrno = errno;
        !           122: 
        !           123:                perror(dirname);
        !           124:                errno = oerrno;
        !           125:                syslog(LOG_ERR, "%s: %m", dirname);
        !           126:                exit(1);
        !           127:        }
        !           128:        read_kmem();
        !           129:        if (!dump_exists()) {
        !           130:                if (Verbose)
        !           131:                        fprintf(stderr, "savecore: No dump exists.\n");
        !           132:                exit(0);
        !           133:        }
        !           134:        (void) time(&now);
        !           135:        check_kmem();
        !           136:        if (panicstr)
        !           137:                syslog(LOG_CRIT, "reboot after panic: %s", panic_mesg);
        !           138:        else
        !           139:                syslog(LOG_CRIT, "reboot");
        !           140:        if (!get_crashtime() || !check_space())
        !           141:                exit(1);
        !           142:        save_core();
        !           143:        clear_dump();
        !           144:        exit(0);
        !           145: }
        !           146: 
        !           147: dump_exists()
        !           148: {
        !           149:        register int dumpfd;
        !           150:        int word;
        !           151: 
        !           152:        dumpfd = Open(ddname, O_RDONLY);
        !           153:        Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET);
        !           154:        Read(dumpfd, (char *)&word, sizeof (word));
        !           155:        close(dumpfd);
        !           156:        if (Verbose && word != dumpmag) {
        !           157:                printf("dumplo = %d (%d bytes)\n", dumplo/DEV_BSIZE, dumplo);
        !           158:                printf("magic number mismatch: %x != %x\n", word, dumpmag);
        !           159:        }
        !           160:        return (word == dumpmag);
        !           161: }
        !           162: 
        !           163: clear_dump()
        !           164: {
        !           165:        register int dumpfd;
        !           166:        int zero = 0;
        !           167: 
        !           168:        dumpfd = Open(ddname, O_WRONLY);
        !           169:        Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET);
        !           170:        Write(dumpfd, (char *)&zero, sizeof (zero));
        !           171:        close(dumpfd);
        !           172: }
        !           173: 
        !           174: char *
        !           175: find_dev(dev, type)
        !           176:        register dev_t dev;
        !           177:        register int type;
        !           178: {
        !           179:        register DIR *dfd = opendir("/dev");
        !           180:        struct direct *dir;
        !           181:        struct stat statb;
        !           182:        static char devname[MAXPATHLEN + 1];
        !           183:        char *dp;
        !           184: 
        !           185:        strcpy(devname, "/dev/");
        !           186:        while ((dir = readdir(dfd))) {
        !           187:                strcpy(devname + 5, dir->d_name);
        !           188:                if (stat(devname, &statb)) {
        !           189:                        perror(devname);
        !           190:                        continue;
        !           191:                }
        !           192:                if ((statb.st_mode&S_IFMT) != type)
        !           193:                        continue;
        !           194:                if (dev == statb.st_rdev) {
        !           195:                        closedir(dfd);
        !           196:                        dp = malloc(strlen(devname)+1);
        !           197:                        strcpy(dp, devname);
        !           198:                        return (dp);
        !           199:                }
        !           200:        }
        !           201:        closedir(dfd);
        !           202:        fprintf(stderr, "Can't find device %d/%d\n", major(dev), minor(dev));
        !           203:        syslog(LOG_ERR, "Can't find device %d/%d\n", major(dev), minor(dev));
        !           204:        exit(1);
        !           205:        /*NOTREACHED*/
        !           206: }
        !           207: 
        !           208: int    cursyms[] =
        !           209:     { X_DUMPDEV, X_DUMPLO, X_VERSION, X_DUMPMAG, -1 };
        !           210: int    dumpsyms[] =
        !           211:     { X_TIME, X_DUMPSIZE, X_VERSION, X_PANICSTR, X_DUMPMAG, -1 };
        !           212: read_kmem()
        !           213: {
        !           214:        register char *cp;
        !           215:        FILE *fp;
        !           216:        char *dump_sys;
        !           217:        int kmem, i;
        !           218:        
        !           219:        dump_sys = system ? system : "/vmunix";
        !           220:        nlist("/vmunix", current_nl);
        !           221:        nlist(dump_sys, dump_nl);
        !           222:        /*
        !           223:         * Some names we need for the currently running system,
        !           224:         * others for the system that was running when the dump was made.
        !           225:         * The values obtained from the current system are used
        !           226:         * to look for things in /dev/kmem that cannot be found
        !           227:         * in the dump_sys namelist, but are presumed to be the same
        !           228:         * (since the disk partitions are probably the same!)
        !           229:         */
        !           230:        for (i = 0; cursyms[i] != -1; i++)
        !           231:                if (current_nl[cursyms[i]].n_value == 0) {
        !           232:                        fprintf(stderr, "/vmunix: %s not in namelist",
        !           233:                            current_nl[cursyms[i]].n_name);
        !           234:                        syslog(LOG_ERR, "/vmunix: %s not in namelist",
        !           235:                            current_nl[cursyms[i]].n_name);
        !           236:                        exit(1);
        !           237:                }
        !           238:        for (i = 0; dumpsyms[i] != -1; i++)
        !           239:                if (dump_nl[dumpsyms[i]].n_value == 0) {
        !           240:                        fprintf(stderr, "%s: %s not in namelist", dump_sys,
        !           241:                            dump_nl[dumpsyms[i]].n_name);
        !           242:                        syslog(LOG_ERR, "%s: %s not in namelist", dump_sys,
        !           243:                            dump_nl[dumpsyms[i]].n_name);
        !           244:                        exit(1);
        !           245:                }
        !           246:        kmem = Open("/dev/kmem", O_RDONLY);
        !           247:        Lseek(kmem, (long)current_nl[X_DUMPDEV].n_value, L_SET);
        !           248:        Read(kmem, (char *)&dumpdev, sizeof (dumpdev));
        !           249:        Lseek(kmem, (long)current_nl[X_DUMPLO].n_value, L_SET);
        !           250:        Read(kmem, (char *)&dumplo, sizeof (dumplo));
        !           251:        Lseek(kmem, (long)current_nl[X_DUMPMAG].n_value, L_SET);
        !           252:        Read(kmem, (char *)&dumpmag, sizeof (dumpmag));
        !           253:        dumplo *= DEV_BSIZE;
        !           254:        ddname = find_dev(dumpdev, S_IFBLK);
        !           255:        fp = fdopen(kmem, "r");
        !           256:        if (fp == NULL) {
        !           257:                syslog(LOG_ERR, "Couldn't fdopen kmem");
        !           258:                exit(1);
        !           259:        }
        !           260:        if (system)
        !           261:                return;
        !           262:        fseek(fp, (long)current_nl[X_VERSION].n_value, L_SET);
        !           263:        fgets(vers, sizeof (vers), fp);
        !           264:        fclose(fp);
        !           265: }
        !           266: 
        !           267: check_kmem()
        !           268: {
        !           269:        FILE *fp;
        !           270:        register char *cp;
        !           271: 
        !           272:        fp = fopen(ddname, "r");
        !           273:        if (fp == NULL) {
        !           274:                int oerrno = errno;
        !           275: 
        !           276:                perror(ddname);
        !           277:                errno = oerrno;
        !           278:                syslog(LOG_ERR, "%s: %m", ddname);
        !           279:                exit(1);
        !           280:        }
        !           281:        fseek(fp, (off_t)(dumplo+ok(dump_nl[X_VERSION].n_value)), L_SET);
        !           282:        fgets(core_vers, sizeof (core_vers), fp);
        !           283:        fclose(fp);
        !           284:        if (!eq(vers, core_vers) && system == 0)
        !           285:                fprintf(stderr,
        !           286:                   "Warning: vmunix version mismatch:\n\t%sand\n\t%s",
        !           287:                   vers, core_vers);
        !           288:                syslog(LOG_WARNING,
        !           289:                   "Warning: vmunix version mismatch: %s and %s",
        !           290:                   vers, core_vers);
        !           291:        fp = fopen(ddname, "r");
        !           292:        fseek(fp, (off_t)(dumplo + ok(dump_nl[X_PANICSTR].n_value)), L_SET);
        !           293:        fread((char *)&panicstr, sizeof (panicstr), 1, fp);
        !           294:        if (panicstr) {
        !           295:                fseek(fp, dumplo + ok(panicstr), L_SET);
        !           296:                cp = panic_mesg;
        !           297:                do
        !           298:                        *cp = getc(fp);
        !           299:                while (*cp++);
        !           300:        }
        !           301:        fclose(fp);
        !           302: }
        !           303: 
        !           304: get_crashtime()
        !           305: {
        !           306:        int dumpfd;
        !           307:        time_t clobber = (time_t)0;
        !           308: 
        !           309:        dumpfd = Open(ddname, O_RDONLY);
        !           310:        Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_TIME].n_value)), L_SET);
        !           311:        Read(dumpfd, (char *)&dumptime, sizeof dumptime);
        !           312:        close(dumpfd);
        !           313:        if (dumptime == 0) {
        !           314:                if (Verbose)
        !           315:                        printf("Dump time not found.\n");
        !           316:                return (0);
        !           317:        }
        !           318:        printf("System went down at %s", ctime(&dumptime));
        !           319:        if (dumptime < now - LEEWAY || dumptime > now + LEEWAY) {
        !           320:                printf("dump time is unreasonable\n");
        !           321:                return (0);
        !           322:        }
        !           323:        return (1);
        !           324: }
        !           325: 
        !           326: char *
        !           327: path(file)
        !           328:        char *file;
        !           329: {
        !           330:        register char *cp = malloc(strlen(file) + strlen(dirname) + 2);
        !           331: 
        !           332:        (void) strcpy(cp, dirname);
        !           333:        (void) strcat(cp, "/");
        !           334:        (void) strcat(cp, file);
        !           335:        return (cp);
        !           336: }
        !           337: 
        !           338: check_space()
        !           339: {
        !           340:        struct stat dsb;
        !           341:        register char *ddev;
        !           342:        int dfd, spacefree;
        !           343:        struct fs fs;
        !           344: 
        !           345:        if (stat(dirname, &dsb) < 0) {
        !           346:                int oerrno = errno;
        !           347: 
        !           348:                perror(dirname);
        !           349:                errno = oerrno;
        !           350:                syslog(LOG_ERR, "%s: %m", dirname);
        !           351:                exit(1);
        !           352:        }
        !           353:        ddev = find_dev(dsb.st_dev, S_IFBLK);
        !           354:        dfd = Open(ddev, O_RDONLY);
        !           355:        Lseek(dfd, (long)(SBLOCK * DEV_BSIZE), L_SET);
        !           356:        Read(dfd, (char *)&fs, sizeof (fs));
        !           357:        close(dfd);
        !           358:        spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024;
        !           359:        if (spacefree < read_number("minfree")) {
        !           360:                printf("Dump omitted, not enough space on device");
        !           361:                syslog(LOG_WARNING, "Dump omitted, not enough space on device");
        !           362:                return (0);
        !           363:        }
        !           364:        if (freespace(&fs, fs.fs_minfree) < 0) {
        !           365:                printf("Dump performed, but free space threshold crossed");
        !           366:                syslog(LOG_WARNING,
        !           367:                    "Dump performed, but free space threshold crossed");
        !           368:        }
        !           369:        return (1);
        !           370: }
        !           371: 
        !           372: read_number(fn)
        !           373:        char *fn;
        !           374: {
        !           375:        char lin[80];
        !           376:        register FILE *fp;
        !           377: 
        !           378:        fp = fopen(path(fn), "r");
        !           379:        if (fp == NULL)
        !           380:                return (0);
        !           381:        if (fgets(lin, 80, fp) == NULL) {
        !           382:                fclose(fp);
        !           383:                return (0);
        !           384:        }
        !           385:        fclose(fp);
        !           386:        return (atoi(lin));
        !           387: }
        !           388: 
        !           389: #define        BUFPAGES        (256*1024/NBPG)         /* 1/4 Mb */
        !           390: 
        !           391: save_core()
        !           392: {
        !           393:        register int n;
        !           394:        register char *cp;
        !           395:        register int ifd, ofd, bounds;
        !           396:        register FILE *fp;
        !           397: 
        !           398:        cp = malloc(BUFPAGES*NBPG);
        !           399:        if (cp == 0) {
        !           400:                fprintf(stderr, "savecore: Can't allocate i/o buffer.\n");
        !           401:                return;
        !           402:        }
        !           403:        bounds = read_number("bounds");
        !           404:        ifd = Open(system?system:"/vmunix", O_RDONLY);
        !           405:        sprintf(cp, "vmunix.%d", bounds);
        !           406:        ofd = Create(path(cp), 0644);
        !           407:        while((n = Read(ifd, cp, BUFSIZ)) > 0)
        !           408:                Write(ofd, cp, n);
        !           409:        close(ifd);
        !           410:        close(ofd);
        !           411:        ifd = Open(ddname, O_RDONLY);
        !           412:        Lseek(ifd, (off_t)(dumplo + ok(dump_nl[X_DUMPSIZE].n_value)), L_SET);
        !           413:        Read(ifd, (char *)&dumpsize, sizeof (dumpsize));
        !           414:        sprintf(cp, "vmcore.%d", bounds);
        !           415:        ofd = Create(path(cp), 0644);
        !           416:        Lseek(ifd, (off_t)dumplo, L_SET);
        !           417:        printf("Saving %d bytes of image in vmcore.%d\n", NBPG*dumpsize,
        !           418:                bounds);
        !           419:        syslog(LOG_NOTICE, "Saving %d bytes of image in vmcore.%d\n",
        !           420:                NBPG*dumpsize, bounds);
        !           421:        while (dumpsize > 0) {
        !           422:                n = Read(ifd, cp,
        !           423:                    (dumpsize > BUFPAGES ? BUFPAGES : dumpsize) * NBPG);
        !           424:                if (n == 0) {
        !           425:                        syslog(LOG_WARNING,
        !           426:                            "WARNING: vmcore may be incomplete\n");
        !           427:                        printf("WARNING: vmcore may be incomplete\n");
        !           428:                        break;
        !           429:                }
        !           430:                Write(ofd, cp, n);
        !           431:                dumpsize -= n/NBPG;
        !           432:        }
        !           433:        close(ifd);
        !           434:        close(ofd);
        !           435:        fp = fopen(path("bounds"), "w");
        !           436:        fprintf(fp, "%d\n", bounds+1);
        !           437:        fclose(fp);
        !           438:        free(cp);
        !           439: }
        !           440: 
        !           441: /*
        !           442:  * Versions of std routines that exit on error.
        !           443:  */
        !           444: Open(name, rw)
        !           445:        char *name;
        !           446:        int rw;
        !           447: {
        !           448:        int fd;
        !           449: 
        !           450:        fd = open(name, rw);
        !           451:        if (fd < 0) {
        !           452:                int oerrno = errno;
        !           453: 
        !           454:                perror(name);
        !           455:                errno = oerrno;
        !           456:                syslog(LOG_ERR, "%s: %m", name);
        !           457:                exit(1);
        !           458:        }
        !           459:        return (fd);
        !           460: }
        !           461: 
        !           462: Read(fd, buff, size)
        !           463:        int fd, size;
        !           464:        char *buff;
        !           465: {
        !           466:        int ret;
        !           467: 
        !           468:        ret = read(fd, buff, size);
        !           469:        if (ret < 0) {
        !           470:                int oerrno = errno;
        !           471: 
        !           472:                perror("read");
        !           473:                errno = oerrno;
        !           474:                syslog(LOG_ERR, "read: %m");
        !           475:                exit(1);
        !           476:        }
        !           477:        return (ret);
        !           478: }
        !           479: 
        !           480: off_t
        !           481: Lseek(fd, off, flag)
        !           482:        int fd, flag;
        !           483:        long off;
        !           484: {
        !           485:        long ret;
        !           486: 
        !           487:        ret = lseek(fd, off, flag);
        !           488:        if (ret == -1) {
        !           489:                int oerrno = errno;
        !           490: 
        !           491:                perror("lseek");
        !           492:                errno = oerrno;
        !           493:                syslog(LOG_ERR, "lseek: %m");
        !           494:                exit(1);
        !           495:        }
        !           496:        return (ret);
        !           497: }
        !           498: 
        !           499: Create(file, mode)
        !           500:        char *file;
        !           501:        int mode;
        !           502: {
        !           503:        register int fd;
        !           504: 
        !           505:        fd = creat(file, mode);
        !           506:        if (fd < 0) {
        !           507:                int oerrno = errno;
        !           508: 
        !           509:                perror(file);
        !           510:                errno = oerrno;
        !           511:                syslog(LOG_ERR, "%s: %m", file);
        !           512:                exit(1);
        !           513:        }
        !           514:        return (fd);
        !           515: }
        !           516: 
        !           517: Write(fd, buf, size)
        !           518:        int fd, size;
        !           519:        char *buf;
        !           520: {
        !           521: 
        !           522:        if (write(fd, buf, size) < size) {
        !           523:                int oerrno = errno;
        !           524: 
        !           525:                perror("write");
        !           526:                errno = oerrno;
        !           527:                syslog(LOG_ERR, "write: %m");
        !           528:                exit(1);
        !           529:        }
        !           530: }

unix.superglobalmegacorp.com

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