Annotation of 42BSD/etc/savecore.c, revision 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.