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