home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / gnu / src / baseline / jove-4.14.6.lha / jove-4.14.6 / recover.c < prev    next >
C/C++ Source or Header  |  1992-01-10  |  17KB  |  820 lines

  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.  It directs recover to
  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 "wait.h"
  27.  
  28. #ifdef UNIX
  29. # include <signal.h>
  30. # include <sys/file.h>
  31. # include <pwd.h>
  32. # include <time.h>
  33. #endif
  34.  
  35. #ifdef    SYSV
  36. # include <sys/utsname.h>
  37. #endif
  38.  
  39. #ifndef    L_SET
  40. # define L_SET    0
  41. # define L_INCR    1
  42. #endif
  43.  
  44. extern char    *ctime proto((const time_t *));
  45.  
  46. private char    blk_buf[JBUFSIZ];
  47. private int    nleft;
  48. private FILE    *ptrs_fp;
  49. private int    data_fd;
  50. private struct rec_head    Header;
  51. private long    Nchars,
  52.     Nlines;
  53. private char    tty[] = "/dev/tty";
  54. private int    UserID,
  55.     Verbose = 0;
  56. private char    *Directory = NULL;        /* the directory we're looking in */
  57.  
  58. private struct file_pair {
  59.     char    *file_data,
  60.         *file_rec;
  61. #define INSPECTED    01
  62.     int    file_flags;
  63.     struct file_pair    *file_next;
  64. } *First = NULL;
  65.  
  66. private struct rec_entry    *buflist[100];    /* system initializes to 0 */
  67.  
  68. #ifndef F_COMPLETION
  69. # define F_COMPLETION    /* since scandir.c is surrounded by an ifdef */
  70. #endif
  71.  
  72. /* simpler version of one in util.c, needed by scandir.c */
  73. UnivPtr
  74. emalloc(size)
  75. size_t size;
  76. {
  77.     register UnivPtr ptr;
  78.  
  79.     if ((ptr = malloc(size)) == NULL) {
  80.         fprintf(stderr, "couldn't malloc(%d)\n", size);
  81.         exit(1);
  82.     }
  83.     return ptr;
  84. }
  85.         
  86. /* simpler version of one in util.c, needed by scandir.c */
  87. UnivPtr
  88. erealloc(ptr, size)
  89. UnivPtr ptr;
  90. size_t size;
  91. {
  92.     if ((ptr = realloc(ptr, size)) == NULL) {
  93.         fprintf(stderr, "couldn't realloc(%d)\n", size);
  94.         exit(1);
  95.     }
  96.     return ptr;
  97. }
  98.  
  99. /* duplicated in util.c, needed by scandir.c */
  100. void
  101. null_ncpy(to, from, n)
  102. char    *to,
  103.     *from;
  104. size_t    n;
  105. {
  106.     (void) strncpy(to, from, n);
  107.     to[n] = '\0';
  108. }
  109.  
  110. #define complain printf    /* kludge! needed by scandir.c */
  111. #include "scandir.c"    /* to get dirent simulation and jscandir */
  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.         lseek(data_fd, (long) bno * JBUFSIZ, L_SET);
  155.         read(data_fd, (UnivPtr)blk_buf, (size_t)JBUFSIZ);
  156.         curblock = bno;
  157.     }
  158.     return blk_buf + off;
  159. }
  160.  
  161. char *
  162. copystr(s)
  163. char    *s;
  164. {
  165.     char    *str;
  166.  
  167.     str = malloc((size_t) (strlen(s) + 1));
  168.     strcpy(str, s);
  169.  
  170.     return str;
  171. }
  172.  
  173. private char    *CurDir;
  174.  
  175. /* Scan the DIRNAME directory for jove tmp files, and make a linked list
  176.    out of them. */
  177.  
  178. private int    add_name proto((char *));
  179.  
  180. private void
  181. get_files(dirname)
  182. char    *dirname;
  183. {
  184.     char **nmptr;
  185.  
  186.     CurDir = dirname;
  187.     First = NULL;
  188.     jscandir(dirname, &nmptr, add_name,
  189.         (int (*) proto((UnivConstPtr, UnivConstPtr)))NULL);
  190. }
  191.  
  192. private int
  193. add_name(fname)
  194. char *fname;
  195. {
  196.     char    dfile[128],
  197.         rfile[128];
  198.     struct file_pair    *fp;
  199.     struct rec_head        header;
  200.     int    fd;
  201.  
  202.     if (strncmp(fname, "jrec", (size_t)4) != 0)
  203.         return 0;
  204.     /* If we get here, we found a "recover" tmp file, so now
  205.        we look for the corresponding "data" tmp file.  First,
  206.        though, we check to see whether there is anything in
  207.        the "recover" file.  If it's 0 length, there's no point
  208.        in saving its name. */
  209.     (void) sprintf(rfile, "%s/%s", CurDir, fname);
  210.     (void) sprintf(dfile, "%s/jove%s", CurDir, fname + 4);
  211.     if ((fd = open(rfile, 0)) != -1) {
  212.         if ((read(fd, (UnivPtr) &header, sizeof header) != sizeof header)) {
  213.             close(fd);
  214.             return 0;
  215.         } else
  216.             close(fd);
  217.     }
  218.     if (access(dfile, 0) != 0) {
  219.         fprintf(stderr, "recover: can't find the data file for %s/%s\n", Directory, fname);
  220.         fprintf(stderr, "so deleting...\n");
  221.         (void) unlink(rfile);
  222.         (void) unlink(dfile);
  223.         return 0;
  224.     }
  225.     /* If we get here, we've found both files, so we put them
  226.        in the list. */
  227.     fp = (struct file_pair *) malloc (sizeof *fp);
  228.     if (fp == NULL) {
  229.         fprintf(stderr, "recover: cannot malloc for file_pair.\n");
  230.         exit(-1);
  231.     }
  232.     fp->file_data = copystr(dfile);
  233.     fp->file_rec = copystr(rfile);
  234.     fp->file_flags = 0;
  235.     fp->file_next = First;
  236.     First = fp;
  237.  
  238.     return 1;
  239. }
  240.  
  241. private void
  242. options()
  243. {
  244.     printf("Options are:\n");
  245.     printf("    ?        list options.\n");
  246.     printf("    get        get a buffer to a file.\n");
  247.     printf("    list        list known buffers.\n");
  248.     printf("    print        print a buffer to terminal.\n");
  249.     printf("    quit        quit and delete jove tmp files.\n");
  250.     printf("    restore        restore all buffers.\n");
  251. }
  252.  
  253. /* Returns a legitimate buffer # */
  254.  
  255. private void    tellme proto((char *, char *)),
  256.     list proto((void));
  257.  
  258. private struct rec_entry **
  259. getsrc()
  260. {
  261.     char    name[128];
  262.     int    number;
  263.  
  264.     for (;;) {
  265.         tellme("Which buffer ('?' for list)? ", name);
  266.         if (name[0] == '?')
  267.             list();
  268.         else if (name[0] == '\0')
  269.             return NULL;
  270.         else if ((number = atoi(name)) > 0 && number <= Header.Nbuffers)
  271.             return &buflist[number];
  272.         else {
  273.             int    i;
  274.  
  275.             for (i = 1; i <= Header.Nbuffers; i++)
  276.                 if (strcmp(buflist[i]->r_bname, name) == 0)
  277.                     return &buflist[i];
  278.             printf("%s: unknown buffer.\n", name);
  279.         }
  280.     }
  281. }
  282.  
  283. /* Get a destination file name. */
  284.  
  285. static char *
  286. getdest()
  287. {
  288.     static char    filebuf[256];
  289.  
  290.     tellme("Output file: ", filebuf);
  291.     if (filebuf[0] == '\0')
  292.         return NULL;
  293.     return filebuf;
  294. }
  295.  
  296. #include "ctype.h"
  297.  
  298. private char *
  299. readword(buf)
  300. char    *buf;
  301. {
  302.     int    c;
  303.     char    *bp = buf;
  304.  
  305.     do ; while (strchr(" \t\n", c = getchar()));
  306.  
  307.     do {
  308.         if (strchr(" \t\n", c))
  309.             break;
  310.         *bp++ = c;
  311.     } while ((c = getchar()) != EOF);
  312.     *bp = '\0';
  313.  
  314.     return buf;
  315. }
  316.  
  317. private void
  318. tellme(quest, answer)
  319. char    *quest,
  320.     *answer;
  321. {
  322. #ifndef BSD386
  323.     /* this is naughty anyway */
  324.     if (stdin->_cnt <= 0) {
  325.         printf("%s", quest);
  326.         fflush(stdout);
  327.     }
  328. #else
  329.     printf("%s", quest);
  330.     fflush(stdout);
  331. #endif
  332.     readword(answer);
  333. }
  334.  
  335. /* Print the specified file to standard output. */
  336.  
  337. private jmp_buf    int_env;
  338.  
  339. private SIGRESULT
  340. catch(junk)
  341. int    junk;
  342. {
  343.     longjmp(int_env, 1);
  344.     /*NOTREACHED*/
  345. }
  346.  
  347. private void    get proto((struct rec_entry **src, char *dest));
  348.  
  349. private void
  350. restore()
  351. {
  352.     register int    i;
  353.     char    tofile[100],
  354.         answer[30];
  355.     int    nrecovered = 0;
  356.  
  357.     for (i = 1; i <= Header.Nbuffers; i++) {
  358.         (void) sprintf(tofile, "#%s", buflist[i]->r_bname);
  359. tryagain:
  360.         printf("Restoring %s to %s, okay?", buflist[i]->r_bname,
  361.                              tofile);
  362.         tellme(" ", answer);
  363.         switch (answer[0]) {
  364.         case 'y':
  365.             break;
  366.  
  367.         case 'n':
  368.             continue;
  369.  
  370.         default:
  371.             tellme("What file should I use instead? ", tofile);
  372.             goto tryagain;
  373.         }
  374.         get(&buflist[i], tofile);
  375.         nrecovered += 1;
  376.     }
  377.     printf("Recovered %d buffers.\n", nrecovered);
  378. }
  379.  
  380. private void    dump_file proto((int which, FILE *out));
  381.  
  382. private void
  383. get(src, dest)
  384. struct rec_entry    **src;
  385. char    *dest;
  386. {
  387.     FILE    *outfile;
  388.  
  389.     if (src == NULL || dest == NULL)
  390.         return;
  391.     (void) signal(SIGINT, catch);
  392.     if (setjmp(int_env) == 0) {
  393.         if (dest == tty)
  394.             outfile = stdout;
  395.         else {
  396.             if ((outfile = fopen(dest, "w")) == NULL) {
  397.                 printf("recover: cannot create %s.\n", dest);
  398.                 (void) signal(SIGINT, SIG_DFL);
  399.                 return;
  400.             }
  401.             printf