home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / jove-4.16-src.tgz / tar.out / bsd / jove / rec.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  5KB  |  185 lines

  1. /************************************************************************
  2.  * This program is Copyright (C) 1986-1996 by Jonathan Payne.  JOVE is  *
  3.  * 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. #include "jove.h"
  9.  
  10. #ifdef RECOVER    /* the body is the rest of this file */
  11.  
  12. #include "fp.h"
  13. #include "sysprocs.h"
  14. #include "rec.h"
  15. #include "fmt.h"
  16. #include "recover.h"
  17.  
  18. #if !defined(MAC) && !defined(ZTCDOS)
  19. # include <sys/file.h>
  20. #endif
  21.  
  22. private int    rec_fd = -1;
  23. private char    *recfname;
  24. private File    *rec_out;
  25.  
  26. #define dmpobj(obj) fputnchar((char *) &obj, (int) sizeof(obj), rec_out)
  27.  
  28. #ifndef L_SET
  29. # define L_SET 0
  30. #endif
  31.  
  32. private struct rec_head    Header;
  33.  
  34. void
  35. rectmpname(tfname)
  36. char *tfname;
  37. {
  38.     if (strlen(tfname) >= sizeof(Header.TmpFileName)) {
  39.         complain("temporary filename too long; recovery disabled.");
  40.         /* NOTREACHED */
  41.     }
  42.     strcpy(Header.TmpFileName, tfname);
  43. }
  44.  
  45. private void
  46. recinit()
  47. {
  48.     char    buf[FILESIZE];
  49.  
  50.     swritef(buf, sizeof(buf), "%s/%s", TmpDir,
  51. #ifdef MAC
  52.         ".jrecXXX"    /* must match string in mac.c:Ffilter() */
  53. #else
  54.         "jrecXXXXXX"
  55. #endif
  56.         );
  57.     recfname = copystr(buf);
  58.     recfname = mktemp(recfname);
  59.     rec_fd = creat(recfname, 0644);
  60.     if (rec_fd == -1) {
  61.         complain("Cannot create \"%s\"; recovery disabled.", recfname);
  62.         /*NOTREACHED*/
  63.     }
  64.     /* initialize the recovery file */
  65.     rec_out = fd_open(recfname, F_WRITE|F_LOCKED, rec_fd, iobuff, LBSIZE);
  66.  
  67.     /* Initialize the record header (TmpFileName initialized by rectmpname). */
  68.     Header.RecMagic = RECMAGIC;
  69. #ifdef UNIX
  70.     Header.Uid = getuid();
  71.     Header.Pid = getpid();
  72. #endif
  73. }
  74.  
  75. /* Close recfile before execing a child process.
  76.  * Since we might be vforking, we must not change any variables
  77.  * (in particular rec_fd).
  78.  */
  79. void
  80. recclose()
  81. {
  82.     if (rec_fd != -1)
  83.         (void) close(rec_fd);
  84. }
  85.  
  86. /* Close and remove recfile before exiting. */
  87.  
  88.  
  89. void
  90. recremove()
  91. {
  92.     if (rec_fd != -1) {
  93.         recclose();
  94.         (void) unlink(recfname);
  95.     }
  96. }
  97.  
  98. /* Write out the line pointers for buffer B. */
  99.  
  100. private void
  101. dmppntrs(b)
  102. register Buffer    *b;
  103. {
  104.     register LinePtr    lp;
  105.  
  106.     for (lp = b->b_first; lp != NULL; lp = lp->l_next)
  107.         dmpobj(lp->l_dline);
  108. }
  109.  
  110. /* dump the buffer info and then the actual line pointers. */
  111.  
  112. private void
  113. dmp_buf_header(b)
  114. register Buffer    *b;
  115. {
  116.     struct rec_entry    record;
  117.  
  118.     byte_zero(&record, sizeof(struct rec_entry));    /* clean out holes for purify */
  119.     record.r_dotline = LinesTo(b->b_first, b->b_dot);
  120.     record.r_dotchar = b->b_char;
  121.     record.r_nlines = record.r_dotline + LinesTo(b->b_dot, (LinePtr)NULL);
  122.     strcpy(record.r_fname, b->b_fname ? b->b_fname : NullStr);
  123.     strcpy(record.r_bname, b->b_name);
  124.     dmpobj(record);
  125. }
  126.  
  127. /* Goes through all the buffers and syncs them to the disk. */
  128.  
  129. int    ModCount = 0;    /* number of buffer mods since last sync */
  130.  
  131. int    SyncFreq = 50;    /* VAR: how often to sync the file pointers */
  132.  
  133. void
  134. SyncRec()
  135. {
  136.     register Buffer    *b;
  137.     static bool    beenhere = NO;
  138.  
  139.     /* Count number of interesting buffers.  If none, don't bother syncing. */
  140.     Header.Nbuffers = 0;
  141.     for (b = world; b != NULL; b = b->b_next)
  142.         if (b->b_type != B_SCRATCH && IsModified(b))
  143.             Header.Nbuffers += 1;
  144.     if (Header.Nbuffers == 0)
  145.         return;
  146.  
  147.     lsave();    /* this makes things really right */
  148.     SyncTmp();    /* note: this will force rectmpname() */
  149.  
  150.     if (!beenhere) {
  151.         beenhere = YES;
  152.         recinit();    /* Init recover file. */
  153.     }
  154.     /* Note: once writing to the recover file fails, we permanently
  155.      * stop trying.  This is to avoid useless thrashing.  Perhaps
  156.      * there should be a way to turn this back on.
  157.      */
  158.     if (rec_fd == -1 || (rec_out->f_flags & F_ERR))
  159.         return;
  160.  
  161.     f_seek(rec_out, (off_t)0);
  162.     (void) time(&Header.UpdTime);
  163.     Header.FreePtr = DFree;
  164.     dmpobj(Header);
  165.     for (b = world; b != NULL; b = b->b_next)
  166.         if (b->b_type != B_SCRATCH && IsModified(b))
  167.             dmp_buf_header(b);
  168.     for (b = world; b != NULL; b = b->b_next)
  169.         if (b->b_type != B_SCRATCH && IsModified(b))
  170.             dmppntrs(b);
  171.     flushout(rec_out);
  172. }
  173.  
  174. /* To be implemented:
  175.    Full Recover.  What we have to do is go find the name of the tmp
  176.    file data/rec pair and use those instead of the ones we would have
  177.    created eventually.  The rec file has a list of buffers, and then
  178.    the actual pointers.  Stored for each buffer is the buffer name,
  179.    the file name, the number of lines, the current line, the current
  180.    character.  The current modes do not need saving as they will be
  181.    saved when the file name is set.  If a process was running in a
  182.    buffer, it will be lost. */
  183.  
  184. #endif /* RECOVER */
  185.