home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / program / d / elvis / Source / c / tmp < prev    next >
Encoding:
Text File  |  1990-04-14  |  11.4 KB  |  377 lines

  1. /* tmpfile.c */
  2.  
  3. extern int rnd();
  4.  
  5. /* Author:
  6.  *      Steve Kirkendall
  7.  *      16820 SW Tallac Way
  8.  *      Beaverton, OR 97006
  9.  *      kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
  10.  */
  11.  
  12.  
  13. /* This file contains functions which create & readback a TMPFILE */
  14.  
  15.  
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include "vi.h"
  19.  
  20. /* This is the name of the temp file */
  21. static char     tmpname[80];
  22.  
  23. /* This function creates the temp file and copies the original file into it.
  24.  * Returns 0 if successful, or 1 if failure.
  25.  */
  26. int tmpstart(filename)
  27.         char            *filename; /* name of the original file */
  28. {
  29.         int             origfd; /* fd used for reading the original file */
  30.         struct stat     statb;  /* stat buffer, used to examine inode */
  31.         register BLK    *this;  /* pointer to the current block buffer */
  32.         register BLK    *next;  /* pointer to the next block buffer */
  33.         int             inbuf;  /* number of characters in a buffer */
  34.         int             nread;  /* number of bytes read */
  35.         register int    j, k;
  36.         int             i;
  37.  
  38.         /* switching to a different file certainly counts as a change */
  39.         changes++;
  40.         redraw(MARK_UNSET, FALSE);
  41.  
  42.         /* open the original file for reading */
  43.         *origname = '\0';
  44.         if (filename)
  45.         {
  46.                 strcpy(origname, filename);
  47.                 origfd = open(origname, O_RDONLY);
  48.                 if (origfd < 0 && errno != ENOENT)
  49.                 {
  50.                         msg("Can't open \"%s\"", origname);
  51.                         exit(1);
  52.                 }
  53.                 if (origfd >= 0 && stat(origname, &statb) < 0)
  54.                 {
  55.                         msg("Can't stat \"%s\"", origname);
  56.                         exit(1);
  57.                 }
  58.                 if (origfd >= 0)
  59.                 {
  60.                         origtime = statb.st_mtime;
  61.                         if (*o_readonly || !(statb.st_mode &
  62.                                   (statb.st_uid != geteuid() ? 0022 : 0200)))
  63.                         {
  64.                                 setflag(file, READONLY);
  65.                         }
  66.                 }
  67.                 else
  68.                 {
  69.                         origtime = 0L;
  70.                 }
  71.         }
  72.         else
  73.         {
  74.                 setflag(file, NOFILE);
  75.                 origfd = -1;
  76.                 origtime = 0L;
  77.                 stat("@", &statb);
  78.         statb.st_type=4095; /* text file */
  79.         }
  80.  
  81.         /* make a name for the tmp file */
  82. #ifdef ARC
  83.     /* try to create file in ram first - for speed */
  84.     sprintf(tmpname,"ram:vi_%x%x_",rnd(),rnd());
  85.     if ( (tmpfd=creat(tmpname,0600)) < 0) {
  86.         /* no ram disc, try current place */
  87.         sprintf(tmpname,"vi_%3x%3x_",rnd(),rnd());
  88.         tmpfd=creat(tmpname,0600);
  89.     }
  90.     close(tmpfd);
  91. #else        
  92.         sprintf(tmpname, TMPNAME, rnd(),rnd());
  93.  
  94.         /* create the temp file */
  95.         close(creat(tmpname, 0600));
  96. #endif /* ARC */
  97.         tmpfd = open(tmpname, O_RDWR);
  98.         if (tmpfd < 0)
  99.         {
  100.                 msg("Can't create temporary file %s",tmpname);
  101.                 exit(1);
  102.         }
  103.  
  104.         /* allocate space for the header in the file */
  105.         write(tmpfd, hdr.c, BLKSIZE);
  106.  
  107.         /* initialize lnum[] */
  108.         for (i = 1; i < MAXBLKS; i++)
  109.         {
  110.                 lnum[i] = INFINITY;
  111.         }
  112.         lnum[0] = 0;
  113.  
  114.         /* if there is no original file, then create a 1-line file */
  115.         if (origfd < 0)
  116.         {
  117.                 hdr.n[0] = 0;   /* invalid inode# denotes new file */
  118.  
  119.                 this = blkget(1);       /* get the new text block */
  120.                 strcpy(this->c, "\n");  /* put a line in it */
  121.  
  122.                 lnum[1] = 1;    /* block 1 ends with line 1 */
  123.                 nlines = 1;     /* there is 1 line in the file */
  124.  
  125.                 if (*origname)
  126.                 {
  127.                         msg("\"%s\" [NEW FILE]  1 line", origname);
  128.                 }
  129.                 else
  130.                 {
  131.                         msg("\"[NO FILE]\"  1 line");
  132.                 }
  133.         }
  134.         else /* there is an original file -- read it in */
  135.         {
  136.                 nlines = 0;
  137.  
  138.                 /* preallocate 1 "next" buffer */
  139.                 i = 1;
  140.                 next = blkget(i);
  141.                 inbuf = 0;
  142.  
  143.                 /* loop, moving blocks from orig to tmp */
  144.                 for (;;)
  145.                 {
  146.                         /* "next" buffer becomes "this" buffer */
  147.                         this = next;
  148.  
  149.                         /* read [more] text into this block */
  150.                         nread = read(origfd, this->c + inbuf, BLKSIZE - 1 - inbuf);
  151.                         if (nread < 0)
  152.                         {
  153.                                 close(origfd);
  154.                                 close(tmpfd);
  155.                                 tmpfd = -1;
  156.                                 unlink(tmpname);
  157.                                 msg("Error reading \"%s\"", origname);
  158.                                 exit(1);
  159.                         }
  160.  
  161.                         /* convert NUL characters to something else */
  162.                         for (k = inbuf; k < inbuf + nread; k++)
  163.                         {
  164.                                 if (!this->c[k])
  165.                                 {
  166.                                         setflag(file, HADNUL);
  167.                                         this->c[k] = 0x80;
  168.                                 }
  169.                         }
  170.                         inbuf += nread;
  171.  
  172.                         /* if the buffer is empty, quit */
  173.                         if (inbuf == 0)
  174.                         {
  175.                                 break;
  176.                         }
  177.  
  178.                         /* search backward for last newline */
  179.                         for (k = inbuf; --k >= 0 && this->c[k] != '\n';)
  180.                         {
  181.                         }
  182.                         if (k++ < 0)
  183.                         {
  184.                                 if (inbuf >= BLKSIZE - 1)
  185.                                 {
  186.                                         k = 80;
  187.                                 }
  188.                                 else
  189.                                 {
  190.                                         k = inbuf;
  191.                                 }
  192.                         }
  193.  
  194.                         /* allocate next buffer */
  195.                         next = blkget(++i);
  196.  
  197.                         /* move fragmentary last line to next buffer */
  198.                         inbuf -= k;
  199.                         for (j = 0; k < BLKSIZE; j++, k++)
  200.                         {
  201.                                 next->c[j] = this->c[k];
  202.                                 this->c[k] = 0;
  203.                         }
  204.  
  205.                         /* if necessary, add a newline to this buf */
  206.                         for (k = BLKSIZE - inbuf; --k >= 0 && !this->c[k]; )
  207.                         {
  208.                         }
  209.                         if (this->c[k] != '\n')
  210.                         {
  211.                                 setflag(file, ADDEDNL);
  212.                                 this->c[k + 1] = '\n';
  213.                         }
  214.  
  215.                         /* count the lines in this block */
  216.                         for (k = 0; k < BLKSIZE && this->c[k]; k++)
  217.                         {
  218.                                 if (this->c[k] == '\n')
  219.                                 {
  220.                                         nlines++;
  221.                                 }
  222.                         }
  223.                         lnum[i - 1] = nlines;
  224.                 }
  225.  
  226.                 /* report the number of lines in the file */
  227.                 msg("\"%s\"  %ld line%s", origname, nlines, nlines == 1 ? "" : "s");
  228.         }
  229.  
  230.         /* initialize the cursor to start of line 1 */
  231.         cursor = MARK_FIRST;
  232.  
  233.         /* close the original file */
  234.         close(origfd);
  235.  
  236. #ifndef NO_RECYCLE
  237.         /* initialize the block allocator */
  238.         garbage();
  239. #endif
  240.         return 0;
  241. }
  242.  
  243.  
  244.  
  245. /* This function copies the temp file back onto an original file.
  246.  * Returns TRUE if successful, or FALSE if the file could NOT be saved.
  247.  */
  248. tmpsave(filename)
  249.         char    *filename;      /* the name to save it to */
  250. {
  251.         int             fd;     /* fd of the file we're writing to */
  252.         register int    len;    /* length of a text block */
  253.         register BLK    *this;  /* a text block */
  254.         register int    i;
  255.  
  256.         /* if no filename is given, assume the original file name */
  257.         if (!filename || !*filename)
  258.         {
  259.                 filename = origname;
  260.         }
  261.  
  262.         /* if still no file name, then fail */
  263.         if (!*filename)
  264.         {
  265.                 msg("Don't know a name for this file -- NOT WRITTEN");
  266.                 return FALSE;
  267.         }
  268.  
  269.         /* open the file */
  270.         if (*filename == '>' && filename[1] == '>')
  271.         {
  272.                 filename += 2;
  273.                 while (*filename == ' ' || *filename == '\t')
  274.                 {
  275.                         filename++;
  276.                 }
  277. #ifdef O_APPEND
  278.                 fd = open(filename, O_WRONLY|O_APPEND);
  279. #else
  280.                 fd = open(filename, O_WRONLY);
  281.                 lseek(fd, 0L, 2);
  282. #endif
  283.         }
  284.         else
  285.         {
  286.                 fd = creat(filename, 0666);
  287.         }
  288.         if (fd < 0)
  289.         {
  290.                 msg("Can't write to \"%s\" -- NOT WRITTEN", filename);
  291.                 return FALSE;
  292.         }
  293.  
  294.         /* write each text block to the file */
  295.         for (i = 1; i < MAXBLKS && (this = blkget(i)) && this->c[0]; i++)
  296.         {
  297.                 for (len = 0; len < BLKSIZE && this->c[len]; len++)
  298.                 {
  299.                 }
  300.                 write(fd, this->c, len);
  301.         }
  302.  
  303.         /* reset the "modified" flag */
  304.         clrflag(file, MODIFIED);
  305.         if (strcmp(filename, SCRATCHFILE))
  306.         {
  307.                 msg("Wrote \"%s\"  %ld lines", filename, nlines);
  308.         }
  309.  
  310.         /* close the file */
  311.         close(fd);
  312.  
  313.         return TRUE;
  314. }
  315.  
  316.  
  317. /* This function deletes the temporary file.  If the file has been modified
  318.  * and "bang" is FALSE, then it returns FALSE without doing anything; else
  319.  * it returns TRUE.
  320.  *
  321.  * If the "autowrite" option is set, then instead of returning FALSE when
  322.  * the file has been modified and "bang" is false, it will call tmpend().
  323.  */
  324. tmpabort(bang)
  325.         int     bang;
  326. {
  327.         /* if there is no file, return successfully */
  328.         if (tmpfd < 0)
  329.         {
  330.                 return TRUE;
  331.         }
  332.  
  333.         /* see if we must return FALSE -- can't quit */
  334.         if (!bang && tstflag(file, MODIFIED))
  335.         {
  336.                 /* if "autowrite" is set, then act like tmpend() */
  337.                 if (*o_autowrite)
  338.                         return tmpend(bang);
  339.                 else
  340.                         return FALSE;
  341.         }
  342.  
  343.         /* delete the tmp file */
  344.         cutswitch(tmpname);
  345.         close(tmpfd);
  346.         tmpfd = -1;
  347.         unlink(tmpname);
  348.         strcpy(prevorig, origname);
  349.         prevline = markline(cursor);
  350.         *origname = '\0';
  351.         origtime = 0L;
  352.         blkinit();
  353.         nlines = 0;
  354.         initflags();
  355.         return TRUE;
  356. }
  357.  
  358. /* This function saves the file if it has been modified, and then deletes
  359.  * the temporary file. Returns TRUE if successful, or FALSE if the file
  360.  * needs to be saved but can't be.  When it returns FALSE, it will not have
  361.  * deleted the tmp file, either.
  362.  */
  363. tmpend(bang)
  364.         int     bang;
  365. {
  366.         /* save the file if it has been modified */
  367.         if (tstflag(file, MODIFIED) && !tmpsave((char *)0) && !bang)
  368.         {
  369.                 return FALSE;
  370.         }
  371.  
  372.         /* delete the tmp file */
  373.         tmpabort(TRUE);
  374.  
  375.         return TRUE;
  376. }
  377.