home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / apps / text_ed / elv16b2 / st / tmp.c < prev    next >
C/C++ Source or Header  |  1992-08-09  |  17KB  |  802 lines

  1. /* tmp.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains functions which create & readback a TMPFILE */
  12.  
  13. #include "config.h"
  14. #include "vi.h"
  15. #if TOS
  16. # include <stat.h>
  17. #else
  18. # if OSK
  19. #  include "osk.h"
  20. # else
  21. #  if AMIGA
  22. #   include "amistat.h"
  23. #  else
  24. #   include <sys/stat.h>
  25. #  endif
  26. # endif
  27. #endif
  28. #if TURBOC
  29. # include <process.h>
  30. #endif
  31.  
  32. /* a quick hack 'cause close(-1) wasn't a no-op on early versions of MiNT  -nox */
  33. #if MINT
  34. int mclose(fd)
  35.     int fd;
  36. {
  37.     if (fd >= 0)
  38.         return close(fd);
  39.     return 0;
  40. }
  41. #define close mclose
  42. #endif
  43.  
  44. #ifndef NO_MODELINES
  45. static void do_modelines(l, stop)
  46.     long    l;    /* line number to start at */
  47.     long    stop;    /* line number to stop at */
  48. {
  49.     char    *str;    /* used to scan through the line */
  50.     char    *start;    /* points to the start of the line */
  51.     char    buf[80];
  52.  
  53.     /* if modelines are disabled, then do nothing */
  54.     if (!*o_modelines)
  55.     {
  56.         return;
  57.     }
  58.  
  59.     /* for each line... */
  60.     for (; l <= stop; l++)
  61.     {
  62.         /* for each position in the line.. */
  63.         for (str = fetchline(l); *str; str++)
  64.         {
  65.             /* if it is the start of a modeline command... */
  66.             if ((str[0] == 'e' && str[1] == 'x'
  67.               || str[0] == 'v' && str[1] == 'i')
  68.               && str[2] == ':')
  69.             {
  70.                 start = str += 3;
  71.  
  72.                 /* find the end */
  73.                 for (str = start + strlen(start); *--str != ':'; )
  74.                 {
  75.                 }
  76.  
  77.                 /* if it is a well-formed modeline, execute it */
  78.                 if (str > start && str - start < sizeof buf)
  79.                 {
  80.                     strncpy(buf, start, (int)(str - start));
  81.                     exstring(buf, str - start, '\\');
  82.                     break;
  83.                 }
  84.             }
  85.         }
  86.     }
  87. }
  88. #endif
  89.  
  90.  
  91. /* The FAIL() macro prints an error message and then exits. */
  92. #define FAIL(why,arg)    mode = MODE_EX; msg(why, arg); endwin(); exit(9)
  93.  
  94. /* This is the name of the temp file */
  95. static char    tmpname[80];
  96.  
  97. /* This function creates the temp file and copies the original file into it.
  98.  * Returns if successful, or stops execution if it fails.
  99.  */
  100. int tmpstart(filename)
  101.     char        *filename; /* name of the original file */
  102. {
  103.     int        origfd;    /* fd used for reading the original file */
  104.     struct stat    statb;    /* stat buffer, used to examine inode */
  105.     REG BLK        *this;    /* pointer to the current block buffer */
  106.     REG BLK        *next;    /* pointer to the next block buffer */
  107.     int        inbuf;    /* number of characters in a buffer */
  108.     int        nread;    /* number of bytes read */
  109.     REG int        j, k;
  110.     int        i;
  111.     long        nbytes;
  112.  
  113.     /* switching to a different file certainly counts as a change */
  114.     changes++;
  115.     redraw(MARK_UNSET, FALSE);
  116.  
  117.     /* open the original file for reading */
  118.     *origname = '\0';
  119.     if (filename && *filename)
  120.     {
  121.         strcpy(origname, filename);
  122.         origfd = open(origname, O_RDONLY);
  123.         if (origfd < 0 && errno != ENOENT)
  124.         {
  125.             msg("Can't open \"%s\"", origname);
  126.             return tmpstart("");
  127.         }
  128.         if (origfd >= 0)
  129.         {
  130.             if (stat(origname, &statb) < 0)
  131.             {
  132.                 FAIL("Can't stat \"%s\"", origname);
  133.             }
  134. #if TOS
  135.             if (origfd >= 0 && (statb.st_mode & S_IJDIR))
  136. #else
  137. # if OSK
  138.             if (origfd >= 0 && (statb.st_mode & S_IFDIR))
  139. # else
  140.             if (origfd >= 0 && (statb.st_mode & S_IFMT) != S_IFREG)
  141. # endif
  142. #endif
  143.             {
  144.                 msg("\"%s\" is not a regular file", origname);
  145.                 return tmpstart("");
  146.             }
  147.         }
  148.         else
  149.         {
  150.             stat(".", &statb);
  151.         }
  152.         if (origfd >= 0)
  153.         {
  154.             origtime = statb.st_mtime;
  155. #if OSK
  156.             if (*o_readonly || !(statb.st_mode &
  157.                   ((getuid() >> 16) == 0 ? S_IOWRITE | S_IWRITE :
  158.                   ((statb.st_gid != (getuid() >> 16) ? S_IOWRITE : S_IWRITE)))))
  159. #endif
  160. #if AMIGA || MSDOS
  161.             if (*o_readonly || !(statb.st_mode & S_IWRITE))
  162. #endif
  163. #if TOS
  164. # ifdef __GNUC__ 
  165.             if (*o_readonly || !(statb.st_mode & S_IWRITE))
  166. # else
  167.             if (*o_readonly || (statb.st_mode & S_IJRON))
  168. # endif
  169. #endif
  170. #if ANY_UNIX || MINT
  171.             if (*o_readonly || !(statb.st_mode &
  172.                   ((geteuid() == 0) ? 0222 :
  173.                   ((statb.st_uid != geteuid() ? 0022 : 0200)))))
  174. #endif
  175. #if VMS
  176.             if (*o_readonly)
  177. #endif
  178.             {
  179.                 setflag(file, READONLY);
  180.             }
  181.         }
  182.         else
  183.         {
  184.             origtime = 0L;
  185.         }
  186.     }
  187.     else
  188.     {
  189.         setflag(file, NOFILE);
  190.         origfd = -1;
  191.         origtime = 0L;
  192.         stat(".", &statb);
  193.     }
  194.  
  195.     /* make a name for the tmp file */
  196.     tmpnum++;
  197. #if MSDOS || TOS || MINT
  198.     /* MS-Dos doesn't allow multiple slashes, but supports drives
  199.      * with current directories.
  200.      * This relies on TMPNAME beginning with "%s\\"!!!!
  201.      */
  202.     strcpy(tmpname, o_directory);
  203.     if ((i = strlen(tmpname)) && !strchr(":/\\", tmpname[i-1]))
  204.         tmpname[i++]=SLASH;
  205.     sprintf(tmpname+i, TMPNAME+3, getpid(), tmpnum);
  206. #else
  207.     sprintf(tmpname, TMPNAME, o_directory, getpid(), tmpnum);
  208. #endif
  209.  
  210.     /* make sure nobody else is editing the same file */
  211.     if (access(tmpname, 0) == 0)
  212.     {
  213.         FAIL("Temp file \"%s\" already exists?", tmpname);
  214.     }
  215.  
  216.     /* create the temp file */
  217. #if ANY_UNIX || MINT
  218.     close(creat(tmpname, 0600));        /* only we can read it */
  219. #else
  220.     close(creat(tmpname, FILEPERMS));    /* anybody body can read it, alas */
  221. #endif
  222.     tmpfd = open(tmpname, O_RDWR | O_BINARY);
  223.     if (tmpfd < 0)
  224.     {
  225.         FAIL("Can't create temp file... Does directory \"%s\" exist?", o_directory);
  226.         return 1;
  227.     }
  228.  
  229.     /* allocate space for the header in the file */
  230.     write(tmpfd, hdr.c, (unsigned)BLKSIZE);
  231.     write(tmpfd, tmpblk.c, (unsigned)BLKSIZE);
  232.  
  233. #ifndef NO_RECYCLE
  234.     /* initialize the block allocator */
  235.     /* This must already be done here, before the first attempt
  236.      * to write to the new file! GB */
  237.     garbage();
  238. #endif
  239.  
  240.     /* initialize lnum[] */
  241.     for (i = 1; i < MAXBLKS; i++)
  242.     {
  243.         lnum[i] = INFINITY;
  244.     }
  245.     lnum[0] = 0;
  246.  
  247.     /* if there is no original file, then create a 1-line file */
  248.     if (origfd < 0)
  249.     {
  250.         hdr.n[0] = 0;    /* invalid inode# denotes new file */
  251.  
  252.         this = blkget(1);     /* get the new text block */
  253.         strcpy(this->c, "\n");    /* put a line in it */
  254.  
  255.         lnum[1] = 1L;    /* block 1 ends with line 1 */
  256.         nlines = 1L;    /* there is 1 line in the file */
  257.         nbytes = 1L;
  258.  
  259.         if (*origname)
  260.         {
  261.             msg("\"%s\" [NEW FILE]  1 line, 1 char", origname);
  262.         }
  263.         else
  264.         {
  265.             msg("\"[NO FILE]\"  1 line, 1 char");
  266.         }
  267.     }
  268.     else /* there is an original file -- read it in */
  269.     {
  270.         nbytes = nlines = 0;
  271.  
  272.         /* preallocate 1 "next" buffer */
  273.         i = 1;
  274.         next = blkget(i);
  275.         inbuf = 0;
  276.  
  277.         /* loop, moving blocks from orig to tmp */
  278.         for (;;)
  279.         {
  280.             /* "next" buffer becomes "this" buffer */
  281.             this = next;
  282.  
  283.             /* read [more] text into this block */
  284. #if MINT
  285.             nread = (*o_crlf ? tread : read)
  286.                 (origfd, &this->c[inbuf], BLKSIZE - 1 - inbuf);
  287. #else
  288.             nread = tread(origfd, &this->c[inbuf], BLKSIZE - 1 - inbuf);
  289. #endif
  290.             if (nread < 0)
  291.             {
  292.                 close(origfd);
  293.                 close(tmpfd);
  294.                 tmpfd = -1;
  295.                 unlink(tmpname);
  296.                 FAIL("Error reading \"%s\"", origname);
  297.             }
  298.  
  299.             /* convert NUL characters to something else */
  300.             for (j = k = inbuf; k < inbuf + nread; k++)
  301.             {
  302.                 if (!this->c[k])
  303.                 {
  304.                     setflag(file, HADNUL);
  305.                     this->c[j++] = 0x80;
  306.                 }
  307. #ifndef CRUNCH
  308.                 else if (*o_beautify && this->c[k] < ' ' && this->c[k] >= 1)
  309.                 {
  310.                     if (this->c[k] == '\t'
  311.                      || this->c[k] == '\n'
  312.                      || this->c[k] == '\f')
  313.                     {
  314.                         this->c[j++] = this->c[k];
  315.                     }
  316.                     else if (this->c[k] == '\b')
  317.                     {
  318.                         /* delete '\b', but complain */
  319.                         setflag(file, HADBS);
  320.                     }
  321.                     /* else silently delete control char */
  322.                 }
  323. #endif
  324.                 else
  325.                 {
  326.                     this->c[j++] = this->c[k];
  327.                 }
  328.             }
  329.             inbuf = j;
  330.  
  331.             /* if the buffer is empty, quit */
  332.             if (inbuf == 0)
  333.             {
  334.                 goto FoundEOF;
  335.             }
  336.  
  337. #if MSDOS || TOS || MINT
  338. /* BAH! MS text mode read fills inbuf, then compresses eliminating \r
  339.    but leaving garbage at end of buf. The same is true for TURBOC. GB. */
  340.  
  341.             memset(this->c + inbuf, '\0', BLKSIZE - inbuf);
  342. #endif
  343.  
  344.             /* search backward for last newline */
  345.             for (k = inbuf; --k >= 0 && this->c[k] != '\n';)
  346.             {
  347.             }
  348.             if (k++ < 0)
  349.             {
  350.                 if (inbuf >= BLKSIZE - 1)
  351.                 {
  352.                     k = 80;
  353.                 }
  354.                 else
  355.                 {
  356.                     k = inbuf;
  357.                 }
  358.             }
  359.  
  360.             /* allocate next buffer */
  361.             next = blkget(++i);
  362.  
  363.             /* move fragmentary last line to next buffer */
  364.             inbuf -= k;
  365.             for (j = 0; k < BLKSIZE; j++, k++)
  366.             {
  367.                 next->c[j] = this->c[k];
  368.                 this->c[k] = 0;
  369.             }
  370.  
  371.             /* if necessary, add a newline to this buf */
  372.             for (k = BLKSIZE - inbuf; --k >= 0 && !this->c[k]; )
  373.             {
  374.             }
  375.             if (this->c[k] != '\n')
  376.             {
  377.                 setflag(file, ADDEDNL);
  378.                 this->c[k + 1] = '\n';
  379.             }
  380.  
  381.             /* count the lines in this block */
  382.             for (k = 0; k < BLKSIZE && this->c[k]; k++)
  383.             {
  384.                 if (this->c[k] == '\n')
  385.                 {
  386.                     nlines++;
  387.                 }
  388.                 nbytes++;
  389.             }
  390.             lnum[i - 1] = nlines;
  391.         }
  392. FoundEOF:
  393.  
  394.         /* if this is a zero-length file, add 1 line */
  395.         if (nlines == 0)
  396.         {
  397.             this = blkget(1);     /* get the new text block */
  398.             strcpy(this->c, "\n");    /* put a line in it */
  399.  
  400.             lnum[1] = 1;    /* block 1 ends with line 1 */
  401.             nlines = 1;    /* there is 1 line in the file */
  402.             nbytes = 1;
  403.         }
  404.  
  405. #if MSDOS || TOS || MINT
  406. # if MINT
  407.         if (*o_crlf)
  408. # endif
  409.         /* each line has an extra CR that we didn't count yet */
  410.         nbytes += nlines;
  411. #endif
  412.  
  413.         /* report the number of lines in the file */
  414.         msg("\"%s\" %s %ld line%s, %ld char%s",
  415.             origname,
  416.             (tstflag(file, READONLY) ? "[READONLY]" : ""),
  417.             nlines,
  418.             nlines == 1 ? "" : "s",
  419.             nbytes,
  420.             nbytes == 1 ? "" : "s");
  421.     }
  422.  
  423.     /* initialize the cursor to start of line 1 */
  424.     cursor = MARK_FIRST;
  425.  
  426.     /* close the original file */
  427.     close(origfd);
  428.  
  429.     /* any other messages? */
  430.     if (tstflag(file, HADNUL))
  431.     {
  432.         msg("This file contained NULs.  They've been changed to \\x80 chars");
  433.     }
  434.     if (tstflag(file, ADDEDNL))
  435.     {
  436.         msg("Newline characters have been inserted to break up long lines");
  437.     }
  438. #ifndef CRUNCH
  439.     if (tstflag(file, HADBS))
  440.     {
  441.         msg("Backspace characters deleted due to ':set beautify'");
  442.     }
  443. #endif
  444.  
  445.     storename(origname);
  446.  
  447. #ifndef NO_MODELINES
  448.     if (nlines > 10)
  449.     {
  450.         do_modelines(1L, 5L);
  451.         do_modelines(nlines - 4L, nlines);
  452.     }
  453.     else
  454.     {
  455.         do_modelines(1L, nlines);
  456.     }
  457. #endif
  458.  
  459.     /* force all blocks out onto the disk, to support file recovery */
  460.     blksync();
  461.  
  462.     return 0;
  463. }
  464.  
  465.  
  466.  
  467. /* This function copies the temp file back onto an original file.
  468.  * Returns TRUE if successful, or FALSE if the file could NOT be saved.
  469.  */
  470. int tmpsave(filename, bang)
  471.     char    *filename;    /* the name to save it to */
  472.     int    bang;        /* forced write? */
  473. {
  474.     int        fd;    /* fd of the file we're writing to */
  475.     REG int        len;    /* length of a text block */
  476.     REG BLK        *this;    /* a text block */
  477.     long        bytes;    /* byte counter */
  478.     REG int        i;
  479.  
  480.     /* if no filename is given, assume the original file name */
  481.     if (!filename || !*filename)
  482.     {
  483.         filename = origname;
  484.     }
  485.  
  486.     /* if still no file name, then fail */
  487.     if (!*filename)
  488.     {
  489.         msg("Don't know a name for this file -- NOT WRITTEN");
  490.         return FALSE;
  491.     }
  492.  
  493.     /* can't rewrite a READONLY file */
  494.     if (!strcmp(filename, origname) && tstflag(file, READONLY) && !bang)
  495.     {
  496.         msg("\"%s\" [READONLY] -- NOT WRITTEN", filename);
  497.         return FALSE;
  498.     }
  499.  
  500.     /* open the file */
  501.     if (*filename == '>' && filename[1] == '>')
  502.     {
  503.         filename += 2;
  504.         while (*filename == ' ' || *filename == '\t')
  505.         {
  506.             filename++;
  507.         }
  508. #ifdef O_APPEND
  509.         fd = open(filename, O_WRONLY|O_APPEND);
  510. #else
  511.         fd = open(filename, O_WRONLY);
  512.         lseek(fd, 0L, 2);
  513. #endif
  514.     }
  515.     else
  516.     {
  517.         /* either the file must not exist, or it must be the original
  518.          * file, or we must have a bang, or "writeany" must be set.
  519.          */
  520.         if (strcmp(filename, origname) && access(filename, 0) == 0 && !bang
  521. #ifndef CRUNCH
  522.             && !*o_writeany
  523. #endif
  524.                    )
  525.         {
  526.             msg("File already exists - Use :w! to overwrite");
  527.             return FALSE;
  528.         }
  529. #if VMS
  530.         /* Create a new VMS version of this file. */
  531.         { 
  532.         char *strrchr(), *ptr = strrchr(filename,';');
  533.         if (ptr) *ptr = '\0';  /* Snip off any ;number in the name */
  534.         }
  535. #endif
  536.         fd = creat(filename, FILEPERMS);
  537.     }
  538.     if (fd < 0)
  539.     {
  540.         msg("Can't write to \"%s\" -- NOT WRITTEN", filename);
  541.         return FALSE;
  542.     }
  543.  
  544.     /* write each text block to the file */
  545.     bytes = 0L;
  546.     for (i = 1; i < MAXBLKS && (this = blkget(i)) && this->c[0]; i++)
  547.     {
  548.         for (len = 0; len < BLKSIZE && this->c[len]; len++)
  549.         {
  550.         }
  551. #if MINT
  552.         if ((*o_crlf ? twrite : write)(fd, this->c, len) < len)
  553. #else
  554.         if (twrite(fd, this->c, len) < len)
  555. #endif
  556.         {
  557.             msg("Trouble writing to \"%s\"", filename);
  558.             if (!strcmp(filename, origname))
  559.             {
  560.                 setflag(file, MODIFIED);
  561.             }
  562.             close(fd);
  563.             return FALSE;
  564.         }
  565.         bytes += len;
  566.     }
  567.  
  568.     /* reset the "modified" flag, but not the "undoable" flag */
  569.     clrflag(file, MODIFIED);
  570.     significant = FALSE;
  571.     if (!strcmp(origname, filename))
  572.     {
  573.         exitcode |= 1;
  574.     }
  575.  
  576.     /* report lines & characters */
  577. #if MSDOS || TOS || MINT
  578. # if MINT
  579.     if (*o_crlf)
  580. # endif
  581.     bytes += nlines; /* for the inserted carriage returns */
  582. #endif
  583.     msg("Wrote \"%s\"  %ld lines, %ld characters", filename, nlines, bytes);
  584.  
  585.     /* close the file */
  586.     close(fd);
  587.  
  588.     return TRUE;
  589. }
  590.  
  591.  
  592. /* This function deletes the temporary file.  If the file has been modified
  593.  * and "bang" is FALSE, then it returns FALSE without doing anything; else
  594.  * it returns TRUE.
  595.  *
  596.  * If the "autowrite" option is set, then instead of returning FALSE when
  597.  * the file has been modified and "bang" is false, it will call tmpend().
  598.  */
  599. int tmpabort(bang)
  600.     int    bang;
  601. {
  602.     /* if there is no file, return successfully */
  603.     if (tmpfd < 0)
  604.     {
  605.         return TRUE;
  606.     }
  607.  
  608.     /* see if we must return FALSE -- can't quit */
  609.     if (!bang && tstflag(file, MODIFIED))
  610.     {
  611.         /* if "autowrite" is set, then act like tmpend() */
  612.         if (*o_autowrite)
  613.             return tmpend(bang);
  614.         else
  615.             return FALSE;
  616.     }
  617.  
  618.     /* delete the tmp file */
  619.     cutswitch();
  620.     strcpy(prevorig, origname);
  621.     prevline = markline(cursor);
  622.     *origname = '\0';
  623.     origtime = 0L;
  624.     blkinit();
  625.     nlines = 0;
  626.     initflags();
  627.     return TRUE;
  628. }
  629.  
  630. /* This function saves the file if it has been modified, and then deletes
  631.  * the temporary file. Returns TRUE if successful, or FALSE if the file
  632.  * needs to be saved but can't be.  When it returns FALSE, it will not have
  633.  * deleted the tmp file, either.
  634.  */
  635. int tmpend(bang)
  636.     int    bang;
  637. {
  638.     /* save the file if it has been modified */
  639.     if (tstflag(file, MODIFIED) && !tmpsave((char *)0, FALSE) && !bang)
  640.     {
  641.         return FALSE;
  642.     }
  643.  
  644.     /* delete the tmp file */
  645.     tmpabort(TRUE);
  646.  
  647.     return TRUE;
  648. }
  649.  
  650.  
  651. /* If the tmp file has been changed, then this function will force those
  652.  * changes to be written to the disk, so that the tmp file will survive a
  653.  * system crash or power failure.
  654.  */
  655. #if AMIGA || MSDOS || TOS || MINT
  656. sync()
  657. {
  658.     /* MS-DOS and TOS don't flush their buffers until the file is closed,
  659.      * so here we close the tmp file and then immediately reopen it.
  660.      */
  661.     close(tmpfd);
  662.     tmpfd = open(tmpname, O_RDWR | O_BINARY);
  663.     return 0;
  664. }
  665. #endif
  666.  
  667.  
  668. /* This function stores the file's name in the second block of the temp file.
  669.  * SLEAZE ALERT!  SLEAZE ALERT!  The "tmpblk" buffer is probably being used
  670.  * to store the arguments to a command, so we can't use it here.  Instead,
  671.  * we'll borrow the buffer that is used for "shift-U".
  672.  */
  673. int
  674. storename(name)
  675.     char    *name;    /* the name of the file - normally origname */
  676. {
  677. #ifndef CRUNCH
  678.     int    len;
  679.     char    *ptr;
  680. #endif
  681.  
  682.     /* we're going to clobber the U_text buffer, so reset U_line */
  683.     U_line = 0L;
  684.  
  685.     if (!name)
  686.     {
  687.         strncpy(U_text, "", BLKSIZE);
  688.         U_text[1] = 127;
  689.     }
  690. #ifndef CRUNCH
  691. #if TOS | MINT | MSDOS
  692.     else if (*name != '/' && *name !='\\' && (!*name || name[1]!=':'))
  693. #else
  694.     else if (*name != SLASH)
  695. #endif
  696.     {
  697.         /* get the directory name */
  698.         ptr = getcwd(U_text, BLKSIZE);
  699.         if (ptr != U_text)
  700.         {
  701.             strcpy(U_text, ptr);
  702.         }
  703.  
  704.         /* append a slash to the directory name */
  705.         len = strlen(U_text);
  706.         U_text[len++] = SLASH;
  707.  
  708.         /* append the filename, padded with heaps o' NULs */
  709.         strncpy(U_text + len, *name ? name : "foo", BLKSIZE - len);
  710.     }
  711. #endif
  712.     else
  713.     {
  714.         /* copy the filename into U_text */
  715.         strncpy(U_text, *name ? name : "foo", BLKSIZE);
  716.     }
  717. #if MINT
  718.     for (ptr=U_text; *ptr && ptr < U_text+BLKSIZE; ++ptr) {
  719.         if (*ptr == '\\')
  720.             *ptr = '/';
  721.     }
  722. #endif
  723.     if (tmpfd >= 0)
  724.     {
  725.         /* write the name out to second block of the temp file */
  726.         lseek(tmpfd, (long)BLKSIZE, 0);
  727.         write(tmpfd, U_text, (unsigned)BLKSIZE);
  728.     }
  729.     return 0;
  730. }
  731.  
  732.  
  733.  
  734. /* This function handles deadly signals.  It restores sanity to the terminal
  735.  * preserves the current temp file, and deletes any old temp files.
  736.  */
  737. int deathtrap(sig)
  738.     int    sig;    /* the deadly signal that we caught */
  739. {
  740.     char    *why;
  741.  
  742.     /* restore the terminal's sanity */
  743.     endwin();
  744.  
  745. #ifdef CRUNCH
  746.     why = "-Elvis died";
  747. #else
  748.     /* give a more specific description of how Elvis died */
  749.     switch (sig)
  750.     {
  751. # ifdef SIGHUP
  752.       case SIGHUP:    why = "-the modem lost its carrier";        break;
  753. # endif
  754. # ifndef DEBUG
  755. #  ifdef SIGILL
  756.       case SIGILL:    why = "-Elvis hit an illegal instruction";    break;
  757. #  endif
  758. #  ifdef SIGBUS
  759.       case SIGBUS:    why = "-Elvis had a bus error";            break;
  760. #  endif
  761. #  ifdef SIGSEGV
  762. #   if !TOS
  763.       case SIGSEGV:    why = "-Elvis had a segmentation violation";    break;
  764. #   endif
  765. #  endif
  766. #  ifdef SIGSYS
  767.       case SIGSYS:    why = "-Elvis munged a system call";        break;
  768. #  endif
  769. # endif /* !DEBUG */
  770. # ifdef SIGPIPE
  771.       case SIGPIPE:    why = "-the pipe reader died";            break;
  772. # endif
  773. # ifdef SIGTERM
  774.       case SIGTERM:    why = "-Elvis was terminated";            break;
  775. # endif
  776. # if !MINIX
  777. #  ifdef SIGUSR1
  778.       case SIGUSR1:    why = "-Elvis was killed via SIGUSR1";        break;
  779. #  endif
  780. #  ifdef SIGUSR2
  781.       case SIGUSR2:    why = "-Elvis was killed via SIGUSR2";        break;
  782. #  endif
  783. # endif
  784.       default:    why = "-Elvis died";                break;
  785.     }
  786. #endif
  787.  
  788.     /* if we had a temp file going, then preserve it */
  789.     if (tmpnum > 0 && tmpfd >= 0)
  790.     {
  791.         close(tmpfd);
  792.         sprintf(tmpblk.c, "%s \"%s\" %s", PRESERVE, why, tmpname);
  793.         system(tmpblk.c);
  794.     }
  795.  
  796.     /* delete any old temp files */
  797.     cutend();
  798.  
  799.     /* exit with the proper exit status */
  800.     exit(sig);
  801. }
  802.