home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / mail / edit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  5.2 KB  |  219 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)edit.c    5.15 (Berkeley) 6/25/90";
  36. #endif /* not lint */
  37.  
  38. #include "rcv.h"
  39. #include <sys/stat.h>
  40.  
  41. /*
  42.  * Mail -- a mail program
  43.  *
  44.  * Perform message editing functions.
  45.  */
  46.  
  47. /*
  48.  * Edit a message list.
  49.  */
  50.  
  51. editor(msgvec)
  52.     int *msgvec;
  53. {
  54.  
  55.     return edit1(msgvec, 'e');
  56. }
  57.  
  58. /*
  59.  * Invoke the visual editor on a message list.
  60.  */
  61.  
  62. visual(msgvec)
  63.     int *msgvec;
  64. {
  65.  
  66.     return edit1(msgvec, 'v');
  67. }
  68.  
  69. /*
  70.  * Edit a message by writing the message into a funnily-named file
  71.  * (which should not exist) and forking an editor on it.
  72.  * We get the editor from the stuff above.
  73.  */
  74. edit1(msgvec, type)
  75.     int *msgvec;
  76.     char type;
  77. {
  78.     register int c;
  79.     int i;
  80.     FILE *fp;
  81.     register struct message *mp;
  82.     off_t size;
  83.  
  84.     /*
  85.      * Deal with each message to be edited . . .
  86.      */
  87.     for (i = 0; msgvec[i] && i < msgCount; i++) {
  88.         sig_t sigint;
  89.  
  90.         if (i > 0) {
  91.             char buf[100];
  92.             char *p;
  93.  
  94.             printf("Edit message %d [ynq]? ", msgvec[i]);
  95.             if (fgets(buf, sizeof buf, stdin) == 0)
  96.                 break;
  97.             for (p = buf; *p == ' ' || *p == '\t'; p++)
  98.                 ;
  99.             if (*p == 'q')
  100.                 break;
  101.             if (*p == 'n')
  102.                 continue;
  103.         }
  104.         dot = mp = &message[msgvec[i] - 1];
  105.         touch(mp);
  106.         sigint = signal(SIGINT, SIG_IGN);
  107.         fp = run_editor(setinput(mp), mp->m_size, type, readonly);
  108.         if (fp != NULL) {
  109.             (void) fseek(otf, (long) 0, 2);
  110.             size = ftell(otf);
  111.             mp->m_block = blockof(size);
  112.             mp->m_offset = offsetof(size);
  113.             mp->m_size = fsize(fp);
  114.             mp->m_lines = 0;
  115.             mp->m_flag |= MODIFY;
  116.             rewind(fp);
  117.             while ((c = getc(fp)) != EOF) {
  118.                 if (c == '\n')
  119.                     mp->m_lines++;
  120.                 if (putc(c, otf) == EOF)
  121.                     break;
  122.             }
  123.             if (ferror(otf))
  124.                 perror("/tmp");
  125.             (void) Fclose(fp);
  126.         }
  127.         (void) signal(SIGINT, sigint);
  128.     }
  129.     return 0;
  130. }
  131.  
  132. /*
  133.  * Run an editor on the file at "fpp" of "size" bytes,
  134.  * and return a new file pointer.
  135.  * Signals must be handled by the caller.
  136.  * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI.
  137.  */
  138. FILE *
  139. run_editor(fp, size, type, readonly)
  140.     register FILE *fp;
  141.     off_t size;
  142.     char type;
  143. {
  144.     register FILE *nf = NULL;
  145.     register int t;
  146.     time_t modtime;
  147.     char *edit;
  148.     struct stat statb;
  149.     extern char tempEdit[];
  150.  
  151.     if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) {
  152.         perror(tempEdit);
  153.         goto out;
  154.     }
  155.     if ((nf = Fdopen(t, "w")) == NULL) {
  156.         perror(tempEdit);
  157.         (void) unlink(tempEdit);
  158.         goto out;
  159.     }
  160.     if (size >= 0)
  161.         while (--size >= 0 && (t = getc(fp)) != EOF)
  162.             (void) putc(t, nf);
  163.     else
  164.         while ((t = getc(fp)) != EOF)
  165.             (void) putc(t, nf);
  166.     (void) fflush(nf);
  167.     if (fstat(fileno(nf), &statb) < 0)
  168.         modtime = 0;
  169.     else
  170.         modtime = statb.st_mtime;
  171.     if (ferror(nf)) {
  172.         (void) Fclose(nf);
  173.         perror(tempEdit);
  174.         (void) unlink(tempEdit);
  175.         nf = NULL;
  176.         goto out;
  177.     }
  178.     if (Fclose(nf) < 0) {
  179.         perror(tempEdit);
  180.         (void) unlink(tempEdit);
  181.         nf = NULL;
  182.         goto out;
  183.     }
  184.     nf = NULL;
  185.     if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
  186.         edit = type == 'e' ? _PATH_EX : _PATH_VI;
  187.     if (run_command(edit, 0, -1, -1, tempEdit, NOSTR) < 0) {
  188.         (void) unlink(tempEdit);
  189.         goto out;
  190.     }
  191.     /*
  192.      * If in read only mode or file unchanged, just remove the editor
  193.      * temporary and return.
  194.      */
  195.     if (readonly) {
  196.         (void) unlink(tempEdit);
  197.         goto out;
  198.     }
  199.     if (stat(tempEdit, &statb) < 0) {
  200.         perror(tempEdit);
  201.         goto out;
  202.     }
  203.     if (modtime == statb.st_mtime) {
  204.         (void) unlink(tempEdit);
  205.         goto out;
  206.     }
  207.     /*
  208.      * Now switch to new file.
  209.      */
  210.     if ((nf = Fopen(tempEdit, "a+")) == NULL) {
  211.         perror(tempEdit);
  212.         (void) unlink(tempEdit);
  213.         goto out;
  214.     }
  215.     (void) unlink(tempEdit);
  216. out:
  217.     return nf;
  218. }
  219.