edit.c revision 67496
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. 3267496Sphk * 3367496Sphk * $FreeBSD: head/usr.bin/mail/edit.c 67496 2000-10-24 13:54:31Z phk $ 341590Srgrimes */ 351590Srgrimes 361590Srgrimes#ifndef lint 371590Srgrimesstatic char sccsid[] = "@(#)edit.c 8.1 (Berkeley) 6/6/93"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#include "rcv.h" 411590Srgrimes#include <fcntl.h> 421590Srgrimes#include "extern.h" 431590Srgrimes 441590Srgrimes/* 451590Srgrimes * Mail -- a mail program 461590Srgrimes * 471590Srgrimes * Perform message editing functions. 481590Srgrimes */ 491590Srgrimes 501590Srgrimes/* 511590Srgrimes * Edit a message list. 521590Srgrimes */ 531590Srgrimesint 541590Srgrimeseditor(msgvec) 551590Srgrimes int *msgvec; 561590Srgrimes{ 571590Srgrimes 581590Srgrimes return edit1(msgvec, 'e'); 591590Srgrimes} 601590Srgrimes 611590Srgrimes/* 621590Srgrimes * Invoke the visual editor on a message list. 631590Srgrimes */ 641590Srgrimesint 651590Srgrimesvisual(msgvec) 661590Srgrimes int *msgvec; 671590Srgrimes{ 681590Srgrimes 691590Srgrimes return edit1(msgvec, 'v'); 701590Srgrimes} 711590Srgrimes 721590Srgrimes/* 731590Srgrimes * Edit a message by writing the message into a funnily-named file 741590Srgrimes * (which should not exist) and forking an editor on it. 751590Srgrimes * We get the editor from the stuff above. 761590Srgrimes */ 771590Srgrimesint 781590Srgrimesedit1(msgvec, type) 791590Srgrimes int *msgvec; 801590Srgrimes int type; 811590Srgrimes{ 821590Srgrimes register int c; 831590Srgrimes int i; 841590Srgrimes FILE *fp; 851590Srgrimes register struct message *mp; 861590Srgrimes off_t size; 871590Srgrimes 881590Srgrimes /* 891590Srgrimes * Deal with each message to be edited . . . 901590Srgrimes */ 911590Srgrimes for (i = 0; msgvec[i] && i < msgCount; i++) { 921590Srgrimes sig_t sigint; 931590Srgrimes 941590Srgrimes if (i > 0) { 951590Srgrimes char buf[100]; 961590Srgrimes char *p; 971590Srgrimes 981590Srgrimes printf("Edit message %d [ynq]? ", msgvec[i]); 991590Srgrimes if (fgets(buf, sizeof buf, stdin) == 0) 1001590Srgrimes break; 1011590Srgrimes for (p = buf; *p == ' ' || *p == '\t'; p++) 1021590Srgrimes ; 1031590Srgrimes if (*p == 'q') 1041590Srgrimes break; 1051590Srgrimes if (*p == 'n') 1061590Srgrimes continue; 1071590Srgrimes } 1081590Srgrimes dot = mp = &message[msgvec[i] - 1]; 1091590Srgrimes touch(mp); 1101590Srgrimes sigint = signal(SIGINT, SIG_IGN); 1111590Srgrimes fp = run_editor(setinput(mp), mp->m_size, type, readonly); 1121590Srgrimes if (fp != NULL) { 1131590Srgrimes (void) fseek(otf, 0L, 2); 1141590Srgrimes size = ftell(otf); 1151590Srgrimes mp->m_block = blockof(size); 11667496Sphk mp->m_offset = boffsetof(size); 1171590Srgrimes mp->m_size = fsize(fp); 1181590Srgrimes mp->m_lines = 0; 1191590Srgrimes mp->m_flag |= MODIFY; 1201590Srgrimes rewind(fp); 1211590Srgrimes while ((c = getc(fp)) != EOF) { 1221590Srgrimes if (c == '\n') 1231590Srgrimes mp->m_lines++; 1241590Srgrimes if (putc(c, otf) == EOF) 1251590Srgrimes break; 1261590Srgrimes } 1271590Srgrimes if (ferror(otf)) 1281590Srgrimes perror("/tmp"); 1291590Srgrimes (void) Fclose(fp); 1301590Srgrimes } 1311590Srgrimes (void) signal(SIGINT, sigint); 1321590Srgrimes } 1331590Srgrimes return 0; 1341590Srgrimes} 1351590Srgrimes 1361590Srgrimes/* 1371590Srgrimes * Run an editor on the file at "fpp" of "size" bytes, 1381590Srgrimes * and return a new file pointer. 1391590Srgrimes * Signals must be handled by the caller. 1401590Srgrimes * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI. 1411590Srgrimes */ 1421590SrgrimesFILE * 1431590Srgrimesrun_editor(fp, size, type, readonly) 1441590Srgrimes register FILE *fp; 1451590Srgrimes off_t size; 1461590Srgrimes int type, readonly; 1471590Srgrimes{ 1481590Srgrimes register FILE *nf = NULL; 1491590Srgrimes register int t; 1501590Srgrimes time_t modtime; 1511590Srgrimes char *edit; 1521590Srgrimes struct stat statb; 15340171Sthepish extern char *tempEdit; 1541590Srgrimes 1551590Srgrimes if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) { 1561590Srgrimes perror(tempEdit); 1571590Srgrimes goto out; 1581590Srgrimes } 1591590Srgrimes if ((nf = Fdopen(t, "w")) == NULL) { 1601590Srgrimes perror(tempEdit); 1611590Srgrimes (void) unlink(tempEdit); 1621590Srgrimes goto out; 1631590Srgrimes } 1641590Srgrimes if (size >= 0) 1651590Srgrimes while (--size >= 0 && (t = getc(fp)) != EOF) 1661590Srgrimes (void) putc(t, nf); 1671590Srgrimes else 1681590Srgrimes while ((t = getc(fp)) != EOF) 1691590Srgrimes (void) putc(t, nf); 1701590Srgrimes (void) fflush(nf); 1711590Srgrimes if (fstat(fileno(nf), &statb) < 0) 1721590Srgrimes modtime = 0; 1731590Srgrimes else 1741590Srgrimes modtime = statb.st_mtime; 1751590Srgrimes if (ferror(nf)) { 1761590Srgrimes (void) Fclose(nf); 1771590Srgrimes perror(tempEdit); 1781590Srgrimes (void) unlink(tempEdit); 1791590Srgrimes nf = NULL; 1801590Srgrimes goto out; 1811590Srgrimes } 1821590Srgrimes if (Fclose(nf) < 0) { 1831590Srgrimes perror(tempEdit); 1841590Srgrimes (void) unlink(tempEdit); 1851590Srgrimes nf = NULL; 1861590Srgrimes goto out; 1871590Srgrimes } 1881590Srgrimes nf = NULL; 1891590Srgrimes if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR) 1901590Srgrimes edit = type == 'e' ? _PATH_EX : _PATH_VI; 1911590Srgrimes if (run_command(edit, 0, -1, -1, tempEdit, NOSTR, NOSTR) < 0) { 1921590Srgrimes (void) unlink(tempEdit); 1931590Srgrimes goto out; 1941590Srgrimes } 1951590Srgrimes /* 1961590Srgrimes * If in read only mode or file unchanged, just remove the editor 1971590Srgrimes * temporary and return. 1981590Srgrimes */ 1991590Srgrimes if (readonly) { 2001590Srgrimes (void) unlink(tempEdit); 2011590Srgrimes goto out; 2021590Srgrimes } 2031590Srgrimes if (stat(tempEdit, &statb) < 0) { 2041590Srgrimes perror(tempEdit); 2051590Srgrimes goto out; 2061590Srgrimes } 2071590Srgrimes if (modtime == statb.st_mtime) { 2081590Srgrimes (void) unlink(tempEdit); 2091590Srgrimes goto out; 2101590Srgrimes } 2111590Srgrimes /* 2121590Srgrimes * Now switch to new file. 2131590Srgrimes */ 2141590Srgrimes if ((nf = Fopen(tempEdit, "a+")) == NULL) { 2151590Srgrimes perror(tempEdit); 2161590Srgrimes (void) unlink(tempEdit); 2171590Srgrimes goto out; 2181590Srgrimes } 2191590Srgrimes (void) unlink(tempEdit); 2201590Srgrimesout: 2211590Srgrimes return nf; 2221590Srgrimes} 223