Annotation of 43BSDReno/contrib/jove/recover.c, revision 1.1.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.