Annotation of 43BSDReno/contrib/jove/recover.c, revision 1.1

1.1     ! root        1: /***************************************************************************
        !             2:  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
        !             3:  * is provided to you without charge, and with no warranty.  You may give  *
        !             4:  * away copies of JOVE, including sources, provided that this notice is    *
        !             5:  * included in all the files.                                              *
        !             6:  ***************************************************************************/
        !             7: 
        !             8: /* Recovers JOVE files after a system/editor crash.
        !             9:    Usage: recover [-d directory] [-syscrash]
        !            10:    The -syscrash option is specified in /etc/rc and what it does it
        !            11:    move all the jove tmp files from TMP_DIR (/tmp) to REC_DIR (/usr/preserve).
        !            12:    recover -syscrash must be invoked in /ect/rc BEFORE /tmp gets cleared out.
        !            13:    (about the same place as expreserve gets invoked to save ed/vi/ex files.
        !            14: 
        !            15:    The -d option lets you specify the directory to search for tmp files when
        !            16:    the default isn't the right one.
        !            17: 
        !            18:    Look in Makefile to change the default directories. */
        !            19: 
        !            20: #include <stdio.h>     /* Do stdio first so it doesn't override OUR
        !            21:                           definitions. */
        !            22: #include "jove.h"
        !            23: #include "temp.h"
        !            24: #include "rec.h"
        !            25: #include "rectune.h"
        !            26: #include <signal.h>
        !            27: #include <sys/file.h>
        !            28: #include <sys/stat.h>
        !            29: #include <sys/dir.h>
        !            30: #include <pwd.h>
        !            31: #include <time.h>
        !            32: #ifdef SYSV
        !            33: # include <sys/utsname.h>
        !            34: #endif
        !            35: 
        !            36: #ifndef L_SET
        !            37: #      define L_SET    0
        !            38: #      define L_INCR   1
        !            39: #endif
        !            40: 
        !            41: extern char    *ctime proto((const time_t *));
        !            42: 
        !            43: private char   blk_buf[JBUFSIZ];
        !            44: private int    nleft;
        !            45: private FILE   *ptrs_fp;
        !            46: private int    data_fd;
        !            47: private struct rec_head        Header;
        !            48: private long   Nchars,
        !            49:        Nlines;
        !            50: private char   tty[] = "/dev/tty";
        !            51: private int    UserID,
        !            52:        Verbose = 0;
        !            53: private char   *Directory = 0;         /* the directory we're looking in */
        !            54: 
        !            55: private struct file_pair {
        !            56:        char    *file_data,
        !            57:                *file_rec;
        !            58: #define INSPECTED      01
        !            59:        int     file_flags;
        !            60:        struct file_pair        *file_next;
        !            61: } *First = 0;
        !            62: 
        !            63: private struct rec_entry       *buflist[100];  /* system initializes to 0 */
        !            64: 
        !            65: #ifndef BSD_DIR
        !            66: 
        !            67: typedef struct {
        !            68:        int     d_fd;           /* File descriptor for this directory */
        !            69: } DIR;
        !            70: 
        !            71: DIR *
        !            72: opendir(dir)
        !            73: char   *dir;
        !            74: {
        !            75:        DIR     *dp = (DIR *) malloc(sizeof *dp);
        !            76: 
        !            77:        if ((dp->d_fd = open(dir, 0)) == -1)
        !            78:                return NULL;
        !            79:        return dp;
        !            80: }
        !            81: 
        !            82: closedir(dp)
        !            83: DIR    *dp;
        !            84: {
        !            85:        (void) close(dp->d_fd);
        !            86:        free(dp);
        !            87: }
        !            88: 
        !            89: struct direct *
        !            90: readdir(dp)
        !            91: DIR    *dp;
        !            92: {
        !            93:        static struct direct    dir;
        !            94: 
        !            95:        do
        !            96:                if (read(dp->d_fd, &dir, sizeof dir) != sizeof dir)
        !            97:                        return NULL;
        !            98: #if defined(elxsi) && defined(SYSV)
        !            99:        /*
        !           100:         * Elxsi has a BSD4.2 implementation which may or may not use
        !           101:         * `twisted inodes' ...  Anyone able to check?
        !           102:         */
        !           103:        while (*(unsigned short *)&dir.d_ino == 0);
        !           104: #else
        !           105:        while (dir.d_ino == 0);
        !           106: #endif
        !           107: 
        !           108:        return &dir;
        !           109: }
        !           110: 
        !           111: #endif /* BSD4_2 */
        !           112: 
        !           113: /* Get a line at `tl' in the tmp file into `buf' which should be LBSIZE
        !           114:    long. */
        !           115: 
        !           116: private char   *getblock proto((daddr atl));
        !           117: 
        !           118: void
        !           119: getline(tl, buf)
        !           120: daddr  tl;
        !           121: char   *buf;
        !           122: {
        !           123:        register char   *bp,
        !           124:                        *lp;
        !           125:        register int    nl;
        !           126: 
        !           127:        lp = buf;
        !           128:        bp = getblock(tl >> 1);
        !           129:        nl = nleft;
        !           130:        tl = blk_round(tl);
        !           131: 
        !           132:        while ((*lp++ = *bp++) != '\0') {
        !           133:                if (--nl == 0) {
        !           134:                        tl = forward_block(tl);
        !           135:                        bp = getblock(tl >> 1);
        !           136:                        nl = nleft;
        !           137:                }
        !           138:        }
        !           139: }
        !           140: 
        !           141: private char *
        !           142: getblock(atl)
        !           143: daddr  atl;
        !           144: {
        !           145:        int     bno,
        !           146:                off;
        !           147:        static int      curblock = -1;
        !           148: 
        !           149:        bno = da_to_bno(atl);
        !           150:        off = da_to_off(atl);
        !           151:        nleft = JBUFSIZ - off;
        !           152: 
        !           153:        if (bno != curblock) {
        !           154:                extern long     lseek proto((int, long, int));
        !           155: 
        !           156:                lseek(data_fd, (long) bno * JBUFSIZ, L_SET);
        !           157:                read(data_fd, blk_buf, (size_t)JBUFSIZ);
        !           158:                curblock = bno;
        !           159:        }
        !           160:        return blk_buf + off;
        !           161: }
        !           162: 
        !           163: char *
        !           164: copystr(s)
        !           165: char   *s;
        !           166: {
        !           167:        char    *str;
        !           168: 
        !           169:        str = malloc((size_t) (strlen(s) + 1));
        !           170:        strcpy(str, s);
        !           171: 
        !           172:        return str;
        !           173: }
        !           174: 
        !           175: /* Scandir returns the number of entries or -1 if the directory cannoot
        !           176:    be opened or malloc fails. */
        !           177: 
        !           178: private int
        !           179: scandir(dir, nmptr, qualify, sorter)
        !           180: char   *dir;
        !           181: struct direct  ***nmptr;
        !           182: int    (*qualify) proto((struct direct *));
        !           183: int    (*sorter) proto((UnivConstPtr, UnivConstPtr));
        !           184: {
        !           185:        DIR     *dirp;
        !           186:        struct direct   *entry,
        !           187:                        **ourarray;
        !           188:        int     nalloc = 10,
        !           189:                nentries = 0;
        !           190: 
        !           191:        if ((dirp = opendir(dir)) == NULL)
        !           192:                return -1;
        !           193:        ourarray = (struct direct **) malloc(nalloc * sizeof (struct direct *));
        !           194:        while ((entry = readdir(dirp)) != NULL) {
        !           195:                if (qualify != NULL && (*qualify)(entry) == 0)
        !           196:                        continue;
        !           197:                if (nentries == nalloc) {
        !           198:                        ourarray = (struct direct **) realloc((char *)ourarray,
        !           199:                                (nalloc += 10) * sizeof (struct direct));
        !           200:                        if (ourarray == NULL)
        !           201:                                return -1;
        !           202:                }
        !           203:                ourarray[nentries] = (struct direct *) malloc(sizeof *entry);
        !           204:                *ourarray[nentries] = *entry;
        !           205:                nentries += 1;
        !           206:        }
        !           207:        closedir(dirp);
        !           208:        if (nentries != nalloc)
        !           209:                ourarray = (struct direct **) realloc((char *)ourarray,
        !           210:                                        (nentries * sizeof (struct direct)));
        !           211:        if (sorter != NULL)
        !           212:                qsort((UnivPtr)ourarray, (size_t) nentries, sizeof (struct direct **), sorter);
        !           213:        *nmptr = ourarray;
        !           214: 
        !           215:        return nentries;
        !           216: }
        !           217: 
        !           218: private char   *CurDir;
        !           219: 
        !           220: /* Scan the DIRNAME directory for jove tmp files, and make a linked list
        !           221:    out of them. */
        !           222: 
        !           223: private int    add_name proto((struct direct *dp));
        !           224: 
        !           225: private void
        !           226: get_files(dirname)
        !           227: char   *dirname;
        !           228: {
        !           229:        struct direct   **nmptr;
        !           230: 
        !           231:        CurDir = dirname;
        !           232:        First = NULL;
        !           233:        scandir(dirname, &nmptr, add_name,
        !           234:                (int (*) proto((UnivConstPtr, UnivConstPtr)))NULL);
        !           235: }
        !           236: 
        !           237: private int
        !           238: add_name(dp)
        !           239: struct direct  *dp;
        !           240: {
        !           241:        char    dfile[128],
        !           242:                rfile[128];
        !           243:        struct file_pair        *fp;
        !           244:        struct rec_head         header;
        !           245:        int     fd;
        !           246: 
        !           247:        if (strncmp(dp->d_name, "jrec", (size_t)4) != 0)
        !           248:                return 0;
        !           249:        /* If we get here, we found a "recover" tmp file, so now
        !           250:           we look for the corresponding "data" tmp file.  First,
        !           251:           though, we check to see whether there is anything in
        !           252:           the "recover" file.  If it's 0 length, there's no point
        !           253:           in saving its name. */
        !           254:        (void) sprintf(rfile, "%s/%s", CurDir, dp->d_name);
        !           255:        (void) sprintf(dfile, "%s/jove%s", CurDir, dp->d_name + 4);
        !           256:        if ((fd = open(rfile, 0)) != -1) {
        !           257:                if ((read(fd, (char *) &header, sizeof header) != sizeof header)) {
        !           258:                        close(fd);
        !           259:                        return 0;
        !           260:                } else
        !           261:                        close(fd);
        !           262:        }
        !           263:        if (access(dfile, 0) != 0) {
        !           264:                fprintf(stderr, "recover: can't find the data file for %s/%s\n", Directory, dp->d_name);
        !           265:                fprintf(stderr, "so deleting...\n");
        !           266:                (void) unlink(rfile);
        !           267:                (void) unlink(dfile);
        !           268:                return 0;
        !           269:        }
        !           270:        /* If we get here, we've found both files, so we put them
        !           271:           in the list. */
        !           272:        fp = (struct file_pair *) malloc (sizeof *fp);
        !           273:        if ((char *) fp == 0) {
        !           274:                fprintf(stderr, "recover: cannot malloc for file_pair.\n");
        !           275:                exit(-1);
        !           276:        }
        !           277:        fp->file_data = copystr(dfile);
        !           278:        fp->file_rec = copystr(rfile);
        !           279:        fp->file_flags = 0;
        !           280:        fp->file_next = First;
        !           281:        First = fp;
        !           282: 
        !           283:        return 1;
        !           284: }
        !           285: 
        !           286: private void
        !           287: options()
        !           288: {
        !           289:        printf("Options are:\n");
        !           290:        printf("        ?               list options.\n");
        !           291:        printf("        get             get a buffer to a file.\n");
        !           292:        printf("        list            list known buffers.\n");
        !           293:        printf("        print           print a buffer to terminal.\n");
        !           294:        printf("        quit            quit and delete jove tmp files.\n");
        !           295:        printf("        restore         restore all buffers.\n");
        !           296: }
        !           297: 
        !           298: /* Returns a legitimate buffer # */
        !           299: 
        !           300: private void   tellme proto((char *, char *)),
        !           301:        list proto((void));
        !           302: 
        !           303: private struct rec_entry **
        !           304: getsrc()
        !           305: {
        !           306:        char    name[128];
        !           307:        int     number;
        !           308: 
        !           309:        for (;;) {
        !           310:                tellme("Which buffer ('?' for list)? ", name);
        !           311:                if (name[0] == '?')
        !           312:                        list();
        !           313:                else if (name[0] == '\0')
        !           314:                        return 0;
        !           315:                else if ((number = atoi(name)) > 0 && number <= Header.Nbuffers)
        !           316:                        return &buflist[number];
        !           317:                else {
        !           318:                        int     i;
        !           319: 
        !           320:                        for (i = 1; i <= Header.Nbuffers; i++)
        !           321:                                if (strcmp(buflist[i]->r_bname, name) == 0)
        !           322:                                        return &buflist[i];
        !           323:                        printf("%s: unknown buffer.\n", name);
        !           324:                }
        !           325:        }
        !           326: }
        !           327: 
        !           328: /* Get a destination file name. */
        !           329: 
        !           330: static char *
        !           331: getdest()
        !           332: {
        !           333:        static char     filebuf[256];
        !           334: 
        !           335:        tellme("Output file: ", filebuf);
        !           336:        if (filebuf[0] == '\0')
        !           337:                return 0;
        !           338:        return filebuf;
        !           339: }
        !           340: 
        !           341: #include "ctype.h"
        !           342: 
        !           343: private char *
        !           344: readword(buf)
        !           345: char   *buf;
        !           346: {
        !           347:        int     c;
        !           348:        char    *bp = buf;
        !           349: 
        !           350:        while (strchr(" \t\n", c = getchar()))
        !           351:                ;
        !           352: 
        !           353:        do {
        !           354:                if (strchr(" \t\n", c))
        !           355:                        break;
        !           356:                *bp++ = c;
        !           357:        } while ((c = getchar()) != EOF);
        !           358:        *bp = 0;
        !           359: 
        !           360:        return buf;
        !           361: }
        !           362: 
        !           363: private void
        !           364: tellme(quest, answer)
        !           365: char   *quest,
        !           366:        *answer;
        !           367: {
        !           368:        if (stdin->_cnt <= 0) {
        !           369:                printf("%s", quest);
        !           370:                fflush(stdout);
        !           371:        }
        !           372:        readword(answer);
        !           373: }
        !           374: 
        !           375: /* Print the specified file to standard output. */
        !           376: 
        !           377: private jmp_buf        int_env;
        !           378: 
        !           379: private SIGRESULT
        !           380: catch(junk)
        !           381: int    junk;
        !           382: {
        !           383:        longjmp(int_env, 1);
        !           384:        /*NOTREACHED*/
        !           385: }
        !           386: 
        !           387: private void   get proto((struct rec_entry **src, char *dest));
        !           388: 
        !           389: private void
        !           390: restore()
        !           391: {
        !           392:        register int    i;
        !           393:        char    tofile[100],
        !           394:                answer[30];
        !           395:        int     nrecovered = 0;
        !           396: 
        !           397:        for (i = 1; i <= Header.Nbuffers; i++) {
        !           398:                (void) sprintf(tofile, "#%s", buflist[i]->r_bname);
        !           399: tryagain:
        !           400:                printf("Restoring %s to %s, okay?", buflist[i]->r_bname,
        !           401:                                                     tofile);
        !           402:                tellme(" ", answer);
        !           403:                switch (answer[0]) {
        !           404:                case 'y':
        !           405:                        break;
        !           406: 
        !           407:                case 'n':
        !           408:                        continue;
        !           409: 
        !           410:                default:
        !           411:                        tellme("What file should I use instead? ", tofile);
        !           412:                        goto tryagain;
        !           413:                }
        !           414:                get(&buflist[i], tofile);
        !           415:                nrecovered += 1;
        !           416:        }
        !           417:        printf("Recovered %d buffers.\n", nrecovered);
        !           418: }
        !           419: 
        !           420: private void   dump_file proto((int which, FILE *out));
        !           421: 
        !           422: private void
        !           423: get(src, dest)
        !           424: struct rec_entry       **src;
        !           425: char   *dest;
        !           426: {
        !           427:        FILE    *outfile;
        !           428: 
        !           429:        if (src == 0 || dest == 0)
        !           430:                return;
        !           431:        (void) signal(SIGINT, catch);
        !           432:        if (setjmp(int_env) == 0) {
        !           433:                if (dest == tty)
        !           434:                        outfile = stdout;
        !           435:                else {
        !           436:                        if ((outfile = fopen(dest, "w")) == NULL) {
        !           437:                                printf("recover: cannot create %s.\n", dest);
        !           438:                                (void) signal(SIGINT, SIG_DFL);
        !           439:                                return;
        !           440:                        }
        !           441:                        printf("\"%s\"", dest);
        !           442:                }
        !           443:                dump_file(src - buflist, outfile);
        !           444:        } else
        !           445:                printf("\nAborted!\n");
        !           446:        (void) signal(SIGINT, SIG_DFL);
        !           447:        if (dest != tty) {
        !           448:                fclose(outfile);
        !           449:                printf(" %ld lines, %ld characters.\n", Nlines, Nchars);
        !           450:        }
        !           451: }
        !           452: 
        !           453: private char **
        !           454: scanvec(args, str)
        !           455: register char  **args,
        !           456:                *str;
        !           457: {
        !           458:        while (*args) {
        !           459:                if (strcmp(*args, str) == 0)
        !           460:                        return args;
        !           461:                args += 1;
        !           462:        }
        !           463:        return 0;
        !           464: }
        !           465: 
        !           466: private void
        !           467: read_rec(recptr)
        !           468: struct rec_entry       *recptr;
        !           469: {
        !           470:        if (fread((char *) recptr, sizeof *recptr, (size_t)1, ptrs_fp) != 1)
        !           471:                fprintf(stderr, "recover: cannot read record.\n");
        !           472: }
        !           473: 
        !           474: private void
        !           475: seekto(which)
        !           476: int    which;
        !           477: {
        !           478:        long    offset;
        !           479:        int     i;
        !           480: 
        !           481:        offset = sizeof (Header) + (Header.Nbuffers * sizeof (struct rec_entry));
        !           482:        for (i = 1; i < which; i++)
        !           483:                offset += buflist[i]->r_nlines * sizeof (daddr);
        !           484:        fseek(ptrs_fp, offset, L_SET);
        !           485: }
        !           486: 
        !           487: private void
        !           488: makblist()
        !           489: {
        !           490:        int     i;
        !           491: 
        !           492:        fseek(ptrs_fp, (long) sizeof (Header), L_SET);
        !           493:        for (i = 1; i <= Header.Nbuffers; i++) {
        !           494:                if (buflist[i] == 0)
        !           495:                        buflist[i] = (struct rec_entry *) malloc (sizeof (struct rec_entry));
        !           496:                read_rec(buflist[i]);
        !           497:        }
        !           498:        while (buflist[i]) {
        !           499:                free((char *) buflist[i]);
        !           500:                buflist[i] = 0;
        !           501:                i += 1;
        !           502:        }
        !           503: }
        !           504: 
        !           505: private daddr
        !           506: getaddr(fp)
        !           507: register FILE  *fp;
        !           508: {
        !           509:        register int    nchars = sizeof (daddr);
        !           510:        daddr   addr;
        !           511:        register char   *cp = (char *) &addr;
        !           512: 
        !           513:        while (--nchars >= 0)
        !           514:                *cp++ = getc(fp);
        !           515: 
        !           516:        return addr;
        !           517: }
        !           518: 
        !           519: private void
        !           520: dump_file(which, out)
        !           521: int    which;
        !           522: FILE   *out;
        !           523: {
        !           524:        register int    nlines;
        !           525:        register daddr  addr;
        !           526:        char    buf[JBUFSIZ];
        !           527: 
        !           528:        seekto(which);
        !           529:        nlines = buflist[which]->r_nlines;
        !           530:        Nchars = Nlines = 0L;
        !           531:        while (--nlines >= 0) {
        !           532:                addr = getaddr(ptrs_fp);
        !           533:                getline(addr, buf);
        !           534:                Nlines += 1;
        !           535:                Nchars += 1 + strlen(buf);
        !           536:                fputs(buf, out);
        !           537:                if (nlines > 0)
        !           538:                        fputc('\n', out);
        !           539:        }
        !           540: }
        !           541: 
        !           542: /* List all the buffers. */
        !           543: 
        !           544: private void
        !           545: list()
        !           546: {
        !           547:        int     i;
        !           548: 
        !           549:        for (i = 1; i <= Header.Nbuffers; i++)
        !           550:                printf("%d) buffer %s  \"%s\" (%d lines)\n", i,
        !           551:                        buflist[i]->r_bname,
        !           552:                        buflist[i]->r_fname,
        !           553:                        buflist[i]->r_nlines);
        !           554: }
        !           555: 
        !           556: private void   ask_del proto((char *prompt, struct file_pair *fp));
        !           557: 
        !           558: private int
        !           559: doit(fp)
        !           560: struct file_pair       *fp;
        !           561: {
        !           562:        char    answer[30];
        !           563:        char    *datafile = fp->file_data,
        !           564:                *pntrfile = fp->file_rec;
        !           565: 
        !           566:        ptrs_fp = fopen(pntrfile, "r");
        !           567:        if (ptrs_fp == NULL) {
        !           568:                if (Verbose)
        !           569:                        fprintf(stderr, "recover: cannot read rec file (%s).\n", pntrfile);
        !           570:                return 0;
        !           571:        }
        !           572:        fread((char *) &Header, sizeof Header, (size_t)1, ptrs_fp);
        !           573:        if (Header.Uid != UserID)
        !           574:                return 0;
        !           575: 
        !           576:        /* Don't ask about JOVE's that are still running ... */
        !           577: #ifdef KILL0
        !           578:        if (kill(Header.Pid, 0) == 0)
        !           579:                return 0;
        !           580: #endif /* KILL0 */
        !           581: 
        !           582:        if (Header.Nbuffers == 0) {
        !           583:                printf("There are no modified buffers in %s; should I delete the tmp file?", pntrfile);
        !           584:                ask_del(" ", fp);
        !           585:                return 1;
        !           586:        }
        !           587: 
        !           588:        if (Header.Nbuffers < 0) {
        !           589:                fprintf(stderr, "recover: %s doesn't look like a jove file.\n", pntrfile);
        !           590:                ask_del("Should I delete it? ", fp);
        !           591:                return 1;       /* We'll, we sort of found something. */
        !           592:        }
        !           593:        printf("Found %d buffer%s last updated: %s",
        !           594:                Header.Nbuffers,
        !           595:                Header.Nbuffers != 1 ? "s" : "",
        !           596:                ctime(&Header.UpdTime));
        !           597:        data_fd = open(datafile, 0);
        !           598:        if (data_fd == -1) {
        !           599:                fprintf(stderr, "recover: but I can't read the data file (%s).\n", datafile);
        !           600:                ask_del("Should I delete the tmp files? ", fp);
        !           601:                return 1;
        !           602:        }
        !           603:        makblist();
        !           604:        list();
        !           605: 
        !           606:        for (;;) {
        !           607:                tellme("(Type '?' for options): ", answer);
        !           608:                switch (answer[0]) {
        !           609:                case '\0':
        !           610:                        continue;
        !           611: 
        !           612:                case '?':
        !           613:                        options();
        !           614:                        break;
        !           615: 
        !           616:                case 'l':
        !           617:                        list();
        !           618:                        break;
        !           619: 
        !           620:                case 'p':
        !           621:                        get(getsrc(), tty);
        !           622:                        break;
        !           623: 
        !           624:                case 'q':
        !           625:                        ask_del("Shall I delete the tmp files? ", fp);
        !           626:                        return 1;
        !           627: 
        !           628:                case 'g':
        !           629:                    {   /* So it asks for src first. */
        !           630:                        char    *dest;
        !           631:                        struct rec_entry        **src;
        !           632: 
        !           633:                        if ((src = getsrc()) == 0)
        !           634:                                break;
        !           635:                        dest = getdest();
        !           636:                        get(src, dest);
        !           637:                        break;
        !           638:                    }
        !           639: 
        !           640:                case 'r':
        !           641:                        restore();
        !           642:                        break;
        !           643: 
        !           644:                default:
        !           645:                        printf("I don't know how to \"%s\"!\n", answer);
        !           646:                        break;
        !           647:                }
        !           648:        }
        !           649: }
        !           650: 
        !           651: private void   del_files proto((struct file_pair *fp));
        !           652: 
        !           653: private void
        !           654: ask_del(prompt, fp)
        !           655: char   *prompt;
        !           656: struct file_pair       *fp;
        !           657: {
        !           658:        char    yorn[20];
        !           659: 
        !           660:        tellme(prompt, yorn);
        !           661:        if (yorn[0] == 'y')
        !           662:                del_files(fp);
        !           663: }
        !           664: 
        !           665: private void
        !           666: del_files(fp)
        !           667: struct file_pair       *fp;
        !           668: {
        !           669:        (void) unlink(fp->file_data);
        !           670:        (void) unlink(fp->file_rec);
        !           671: }
        !           672: 
        !           673: 
        !           674: 
        !           675: MailUser(rec)
        !           676: struct rec_head *rec;
        !           677: {
        !           678: #ifdef SYSV
        !           679:        struct utsname mach;
        !           680: #else
        !           681:        char mach[BUFSIZ];
        !           682: #endif
        !           683:        char mail_cmd[BUFSIZ];
        !           684:        char *last_update;
        !           685:        char *buf_string;
        !           686:        FILE *mail_pipe;
        !           687:        struct passwd *pw;
        !           688:        extern struct passwd *getpwuid proto((int));
        !           689: 
        !           690:        if ((pw = getpwuid(rec->Uid))== NULL)
        !           691:                return;
        !           692: #ifdef SYSV
        !           693:        if (uname(&mach) < 0)
        !           694:                strcpy(mach.sysname, "unknown");
        !           695: #else
        !           696:        gethostname(mach, sizeof(mach));
        !           697: #endif
        !           698:        last_update = ctime(&(rec->UpdTime));
        !           699:        /* Start up mail */
        !           700:        sprintf(mail_cmd, "/bin/mail %s", pw->pw_name);
        !           701:        setuid(getuid());
        !           702:        if ((mail_pipe = popen(mail_cmd, "w")) == NULL)
        !           703:                return;
        !           704:        setbuf(mail_pipe, mail_cmd);
        !           705:        /* Let's be grammatically correct! */
        !           706:        if (rec->Nbuffers == 1)
        !           707:                buf_string = "buffer";
        !           708:        else
        !           709:                buf_string = "buffers";
        !           710:        fprintf(mail_pipe, "Subject: System crash\n");
        !           711:        fprintf(mail_pipe, " \n");
        !           712:        fprintf(mail_pipe, "Jove saved %d %s when the system \"%s\"\n",
        !           713:         rec->Nbuffers, buf_string,
        !           714: #ifdef SYSV
        !           715:         mach.sysname
        !           716: #else
        !           717:         mach
        !           718: #endif
        !           719:         );
        !           720:        fprintf(mail_pipe, "crashed on %s\n\n", last_update);
        !           721:        fprintf(mail_pipe, "You can retrieve the %s using Jove's -r\n", 
        !           722:         buf_string);
        !           723:        fprintf(mail_pipe, "(recover option) i.e. give the command.\n");
        !           724:        fprintf(mail_pipe, "\tjove -r\n");
        !           725:        fprintf(mail_pipe, "See the Jove manual for more details\n");
        !           726:        pclose(mail_pipe);
        !           727: }
        !           728: 
        !           729: 
        !           730: savetmps()
        !           731: {
        !           732:        struct file_pair        *fp;
        !           733:        int     status,
        !           734:                pid,
        !           735:                fd;
        !           736:        struct rec_head         header;
        !           737:        char    buf[BUFSIZ];
        !           738:        char    *fname;
        !           739:        struct stat             stbuf;
        !           740: 
        !           741:        if (strcmp(TMP_DIR, REC_DIR) == 0)
        !           742:                return;         /* Files are moved to the same place. */
        !           743:        get_files(TMP_DIR);
        !           744:        for (fp = First; fp != 0; fp = fp->file_next) {
        !           745:                stat(fp->file_data, &stbuf);
        !           746:                switch (pid = fork()) {
        !           747:                case -1:
        !           748:                        fprintf(stderr, "recover: can't fork\n!");
        !           749:                        exit(-1);
        !           750: 
        !           751:                case 0:
        !           752:                        fprintf(stderr, "Recovering: %s, %s\n", fp->file_data,
        !           753:                         fp->file_rec);
        !           754:                        if ((fd = open(fp->file_rec, 0)) != -1) {
        !           755:                                if ((read(fd, (char *) &header, sizeof header) != sizeof header)) {
        !           756:                                        close(fd);
        !           757:                                        return 0;
        !           758:                                } else
        !           759:                                        close(fd);
        !           760:                        }
        !           761:                        MailUser(&header);
        !           762:                        execl("/bin/mv", "mv", fp->file_data, fp->file_rec, 
        !           763:                                  REC_DIR, (char *)0);
        !           764:                        fprintf(stderr, "recover: cannot execl /bin/mv.\n");
        !           765:                        exit(-1);
        !           766: 
        !           767:                default:
        !           768:                        while (wait(&status) != pid)
        !           769:                                ;
        !           770:                        if (status != 0)
        !           771:                                fprintf(stderr, "recover: non-zero status (%d) returned from copy.\n", status);
        !           772:                        fname = fp->file_data + strlen(TMP_DIR);
        !           773:                        strcpy(buf, REC_DIR);
        !           774:                        strcat(buf, fname);
        !           775:                        if(chown(buf, (int) stbuf.st_uid, (int) stbuf.st_gid) != 0)
        !           776:                                perror("recover: chown failed.");
        !           777:                        fname = fp->file_rec + strlen(TMP_DIR);
        !           778:                        strcpy(buf, REC_DIR);
        !           779:                        strcat(buf, fname);
        !           780:                        if(chown(buf, (int) stbuf.st_uid, (int) stbuf.st_gid) != 0)
        !           781:                                perror("recover: chown failed.");
        !           782:                }
        !           783:        }
        !           784: }
        !           785: 
        !           786: private int
        !           787: lookup(dir)
        !           788: char   *dir;
        !           789: {
        !           790:        struct file_pair        *fp;
        !           791:        int     nfound = 0;
        !           792: 
        !           793:        printf("Checking %s ...\n", dir);
        !           794:        Directory = dir;
        !           795:        get_files(dir);
        !           796:        for (fp = First; fp != 0; fp = fp->file_next) {
        !           797:                nfound += doit(fp);
        !           798:                if (ptrs_fp)
        !           799:                        (void) fclose(ptrs_fp);
        !           800:                if (data_fd > 0)
        !           801:                        (void) close(data_fd);
        !           802:        }
        !           803:        return nfound;
        !           804: }
        !           805: 
        !           806: void
        !           807: main(argc, argv)
        !           808: int    argc;
        !           809: char   *argv[];
        !           810: {
        !           811:        int     nfound;
        !           812:        char    **argvp;
        !           813:        char    *tmp_dir;
        !           814: 
        !           815:        UserID = getuid();
        !           816: 
        !           817:        if (scanvec(argv, "-help")) {
        !           818:                printf("recover: usage: recover [-d directory] [-syscrash]\n");
        !           819:                printf("Use \"jove -r\" after JOVE has died for some\n");
        !           820:                printf("unknown reason.\n\n");
        !           821:                printf("Use \"%s -syscrash\"\n", Recover);
        !           822:                printf("when the system is in the process of rebooting.");
        !           823:                printf("This is done automatically at reboot time\n");
        !           824:                printf("and so most of you don't have to worry about that.\n\n");
        !           825:                printf("Use \"recover -d directory\" when the tmp files are store\n");
        !           826:                printf("in DIRECTORY instead of the default one (/tmp).\n");
        !           827:                exit(0);
        !           828:        }
        !           829:        if (scanvec(argv, "-v"))
        !           830:                Verbose = YES;
        !           831:        if (scanvec(argv, "-syscrash")) {
        !           832:                printf("Recovering jove files ... ");
        !           833:                savetmps();
        !           834:                printf("Done.\n");
        !           835:                exit(0);
        !           836:        }
        !           837:        if ((argvp = scanvec(argv, "-uid")) != NULL)
        !           838:                UserID = atoi(argvp[1]);
        !           839:        if ((argvp = scanvec(argv, "-d")) != NULL)
        !           840:                tmp_dir = argvp[1];
        !           841:        else
        !           842:                tmp_dir = TmpFilePath;
        !           843:        /* Check default directory */
        !           844:        nfound = lookup(tmp_dir);
        !           845:        /* Check whether anything was saved when system died? */
        !           846:        if (strcmp(tmp_dir, REC_DIR) != 0)
        !           847:                nfound += lookup(REC_DIR);
        !           848:        if (nfound == 0)
        !           849:                printf("There's nothing to recover.\n");
        !           850: }

unix.superglobalmegacorp.com

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