edit.c revision 1590
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 351590Srgrimesstatic char sccsid[] = "@(#)edit.c 8.1 (Berkeley) 6/6/93"; 361590Srgrimes#endif /* not lint */ 371590Srgrimes 381590Srgrimes#include "rcv.h" 391590Srgrimes#include <fcntl.h> 401590Srgrimes#include "extern.h" 411590Srgrimes 421590Srgrimes/* 431590Srgrimes * Mail -- a mail program 441590Srgrimes * 451590Srgrimes * Perform message editing functions. 461590Srgrimes */ 471590Srgrimes 481590Srgrimes/* 491590Srgrimes * Edit a message list. 501590Srgrimes */ 511590Srgrimesint 521590Srgrimeseditor(msgvec) 531590Srgrimes int *msgvec; 541590Srgrimes{ 551590Srgrimes 561590Srgrimes return edit1(msgvec, 'e'); 571590Srgrimes} 581590Srgrimes 591590Srgrimes/* 601590Srgrimes * Invoke the visual editor on a message list. 611590Srgrimes */ 621590Srgrimesint 631590Srgrimesvisual(msgvec) 641590Srgrimes int *msgvec; 651590Srgrimes{ 661590Srgrimes 671590Srgrimes return edit1(msgvec, 'v'); 681590Srgrimes} 691590Srgrimes 701590Srgrimes/* 711590Srgrimes * Edit a message by writing the message into a funnily-named file 721590Srgrimes * (which should not exist) and forking an editor on it. 731590Srgrimes * We get the editor from the stuff above. 741590Srgrimes */ 751590Srgrimesint 761590Srgrimesedit1(msgvec, type) 771590Srgrimes int *msgvec; 781590Srgrimes int type; 791590Srgrimes{ 801590Srgrimes register int c; 811590Srgrimes int i; 821590Srgrimes FILE *fp; 831590Srgrimes register struct message *mp; 841590Srgrimes off_t size; 851590Srgrimes 861590Srgrimes /* 871590Srgrimes * Deal with each message to be edited . . . 881590Srgrimes */ 891590Srgrimes for (i = 0; msgvec[i] && i < msgCount; i++) { 901590Srgrimes sig_t sigint; 911590Srgrimes 921590Srgrimes if (i > 0) { 931590Srgrimes char buf[100]; 941590Srgrimes char *p; 951590Srgrimes 961590Srgrimes printf("Edit message %d [ynq]? ", msgvec[i]); 971590Srgrimes if (fgets(buf, sizeof buf, stdin) == 0) 981590Srgrimes break; 991590Srgrimes for (p = buf; *p == ' ' || *p == '\t'; p++) 1001590Srgrimes ; 1011590Srgrimes if (*p == 'q') 1021590Srgrimes break; 1031590Srgrimes if (*p == 'n') 1041590Srgrimes continue; 1051590Srgrimes } 1061590Srgrimes dot = mp = &message[msgvec[i] - 1]; 1071590Srgrimes touch(mp); 1081590Srgrimes sigint = signal(SIGINT, SIG_IGN); 1091590Srgrimes fp = run_editor(setinput(mp), mp->m_size, type, readonly); 1101590Srgrimes if (fp != NULL) { 1111590Srgrimes (void) fseek(otf, 0L, 2); 1121590Srgrimes size = ftell(otf); 1131590Srgrimes mp->m_block = blockof(size); 1141590Srgrimes mp->m_offset = offsetof(size); 1151590Srgrimes mp->m_size = fsize(fp); 1161590Srgrimes mp->m_lines = 0; 1171590Srgrimes mp->m_flag |= MODIFY; 1181590Srgrimes rewind(fp); 1191590Srgrimes while ((c = getc(fp)) != EOF) { 1201590Srgrimes if (c == '\n') 1211590Srgrimes mp->m_lines++; 1221590Srgrimes if (putc(c, otf) == EOF) 1231590Srgrimes break; 1241590Srgrimes } 1251590Srgrimes if (ferror(otf)) 1261590Srgrimes perror("/tmp"); 1271590Srgrimes (void) Fclose(fp); 1281590Srgrimes } 1291590Srgrimes (void) signal(SIGINT, sigint); 1301590Srgrimes } 1311590Srgrimes return 0; 1321590Srgrimes} 1331590Srgrimes 1341590Srgrimes/* 1351590Srgrimes * Run an editor on the file at "fpp" of "size" bytes, 1361590Srgrimes * and return a new file pointer. 1371590Srgrimes * Signals must be handled by the caller. 1381590Srgrimes * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI. 1391590Srgrimes */ 1401590SrgrimesFILE * 1411590Srgrimesrun_editor(fp, size, type, readonly) 1421590Srgrimes register FILE *fp; 1431590Srgrimes off_t size; 1441590Srgrimes int type, readonly; 1451590Srgrimes{ 1461590Srgrimes register FILE *nf = NULL; 1471590Srgrimes register int t; 1481590Srgrimes time_t modtime; 1491590Srgrimes char *edit; 1501590Srgrimes struct stat statb; 1511590Srgrimes extern char tempEdit[]; 1521590Srgrimes 1531590Srgrimes if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) { 1541590Srgrimes perror(tempEdit); 1551590Srgrimes goto out; 1561590Srgrimes } 1571590Srgrimes if ((nf = Fdopen(t, "w")) == NULL) { 1581590Srgrimes perror(tempEdit); 1591590Srgrimes (void) unlink(tempEdit); 1601590Srgrimes goto out; 1611590Srgrimes } 1621590Srgrimes if (size >= 0) 1631590Srgrimes while (--size >= 0 && (t = getc(fp)) != EOF) 1641590Srgrimes (void) putc(t, nf); 1651590Srgrimes else 1661590Srgrimes while ((t = getc(fp)) != EOF) 1671590Srgrimes (void) putc(t, nf); 1681590Srgrimes (void) fflush(nf); 1691590Srgrimes if (fstat(fileno(nf), &statb) < 0) 1701590Srgrimes modtime = 0; 1711590Srgrimes else 1721590Srgrimes modtime = statb.st_mtime; 1731590Srgrimes if (ferror(nf)) { 1741590Srgrimes (void) Fclose(nf); 1751590Srgrimes perror(tempEdit); 1761590Srgrimes (void) unlink(tempEdit); 1771590Srgrimes nf = NULL; 1781590Srgrimes goto out; 1791590Srgrimes } 1801590Srgrimes if (Fclose(nf) < 0) { 1811590Srgrimes perror(tempEdit); 1821590Srgrimes (void) unlink(tempEdit); 1831590Srgrimes nf = NULL; 1841590Srgrimes goto out; 1851590Srgrimes } 1861590Srgrimes nf = NULL; 1871590Srgrimes if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR) 1881590Srgrimes edit = type == 'e' ? _PATH_EX : _PATH_VI; 1891590Srgrimes if (run_command(edit, 0, -1, -1, tempEdit, NOSTR, NOSTR) < 0) { 1901590Srgrimes (void) unlink(tempEdit); 1911590Srgrimes goto out; 1921590Srgrimes } 1931590Srgrimes /* 1941590Srgrimes * If in read only mode or file unchanged, just remove the editor 1951590Srgrimes * temporary and return. 1961590Srgrimes */ 1971590Srgrimes if (readonly) { 1981590Srgrimes (void) unlink(tempEdit); 1991590Srgrimes goto out; 2001590Srgrimes } 2011590Srgrimes if (stat(tempEdit, &statb) < 0) { 2021590Srgrimes perror(tempEdit); 2031590Srgrimes goto out; 2041590Srgrimes } 2051590Srgrimes if (modtime == statb.st_mtime) { 2061590Srgrimes (void) unlink(tempEdit); 2071590Srgrimes goto out; 2081590Srgrimes } 2091590Srgrimes /* 2101590Srgrimes * Now switch to new file. 2111590Srgrimes */ 2121590Srgrimes if ((nf = Fopen(tempEdit, "a+")) == NULL) { 2131590Srgrimes perror(tempEdit); 2141590Srgrimes (void) unlink(tempEdit); 2151590Srgrimes goto out; 2161590Srgrimes } 2171590Srgrimes (void) unlink(tempEdit); 2181590Srgrimesout: 2191590Srgrimes return nf; 2201590Srgrimes} 221