xref: /csrg-svn/usr.bin/mail/edit.c (revision 22451)
1*22451Sdist /*
2*22451Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22451Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22451Sdist  * specifies the terms and conditions for redistribution.
5*22451Sdist  */
6*22451Sdist 
714529Ssam #ifndef lint
8*22451Sdist static char sccsid[] = "@(#)edit.c	5.1 (Berkeley) 06/06/85";
9*22451Sdist #endif not lint
101228Skas 
111228Skas #include "rcv.h"
121228Skas #include <stdio.h>
131228Skas #include <sys/stat.h>
141228Skas 
151228Skas /*
161228Skas  * Mail -- a mail program
171228Skas  *
181228Skas  * Perform message editing functions.
191228Skas  */
201228Skas 
211228Skas /*
221228Skas  * Edit a message list.
231228Skas  */
241228Skas 
251228Skas editor(msgvec)
261228Skas 	int *msgvec;
271228Skas {
281228Skas 	char *edname;
291228Skas 
301228Skas 	if ((edname = value("EDITOR")) == NOSTR)
311228Skas 		edname = EDITOR;
321228Skas 	return(edit1(msgvec, edname));
331228Skas }
341228Skas 
351228Skas /*
361228Skas  * Invoke the visual editor on a message list.
371228Skas  */
381228Skas 
391228Skas visual(msgvec)
401228Skas 	int *msgvec;
411228Skas {
421228Skas 	char *edname;
431228Skas 
441228Skas 	if ((edname = value("VISUAL")) == NOSTR)
451228Skas 		edname = VISUAL;
461228Skas 	return(edit1(msgvec, edname));
471228Skas }
481228Skas 
491228Skas /*
501228Skas  * Edit a message by writing the message into a funnily-named file
511228Skas  * (which should not exist) and forking an editor on it.
521228Skas  * We get the editor from the stuff above.
531228Skas  */
541228Skas 
551228Skas edit1(msgvec, ed)
561228Skas 	int *msgvec;
571228Skas 	char *ed;
581228Skas {
591228Skas 	register char *cp, *cp2;
601228Skas 	register int c;
611228Skas 	int *ip, pid, mesg, lines;
628745Scarl 	long ms;
631228Skas 	int (*sigint)(), (*sigquit)();
641228Skas 	FILE *ibuf, *obuf;
651228Skas 	char edname[15], nbuf[10];
661228Skas 	struct message *mp;
671228Skas 	extern char tempEdit[];
681228Skas 	off_t fsize(), size;
691228Skas 	struct stat statb;
701228Skas 	long modtime;
711228Skas 
721228Skas 	/*
731228Skas 	 * Set signals; locate editor.
741228Skas 	 */
751228Skas 
763410Skurt 	sigint = sigset(SIGINT, SIG_IGN);
773410Skurt 	sigquit = sigset(SIGQUIT, SIG_IGN);
781228Skas 
791228Skas 	/*
801228Skas 	 * Deal with each message to be edited . . .
811228Skas 	 */
821228Skas 
831228Skas 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
841228Skas 		mesg = *ip;
851228Skas 		mp = &message[mesg-1];
861228Skas 		mp->m_flag |= MODIFY;
871228Skas 
881228Skas 		/*
891228Skas 		 * Make up a name for the edit file of the
901228Skas 		 * form "Message%d" and make sure it doesn't
911228Skas 		 * already exist.
921228Skas 		 */
931228Skas 
941228Skas 		cp = &nbuf[10];
951228Skas 		*--cp = 0;
961228Skas 		while (mesg) {
971228Skas 			*--cp = mesg % 10 + '0';
981228Skas 			mesg /= 10;
991228Skas 		}
1001228Skas 		cp2 = copy("Message", edname);
1011228Skas 		while (*cp2++ = *cp++)
1021228Skas 			;
1031228Skas 		if (!access(edname, 2)) {
1041228Skas 			printf("%s: file exists\n", edname);
1051228Skas 			goto out;
1061228Skas 		}
1071228Skas 
1081228Skas 		/*
1091228Skas 		 * Copy the message into the edit file.
1101228Skas 		 */
1111228Skas 
1121228Skas 		close(creat(edname, 0600));
1131228Skas 		if ((obuf = fopen(edname, "w")) == NULL) {
1141228Skas 			perror(edname);
1151228Skas 			goto out;
1161228Skas 		}
1177577Skurt 		if (send(mp, obuf, 0) < 0) {
1181228Skas 			perror(edname);
1191228Skas 			fclose(obuf);
1201228Skas 			remove(edname);
1211228Skas 			goto out;
1221228Skas 		}
1231228Skas 		fflush(obuf);
1241228Skas 		if (ferror(obuf)) {
1251228Skas 			remove(edname);
1261228Skas 			fclose(obuf);
1271228Skas 			goto out;
1281228Skas 		}
1291228Skas 		fclose(obuf);
1301228Skas 
1311228Skas 		/*
1321472Skas 		 * If we are in read only mode, make the
1331472Skas 		 * temporary message file readonly as well.
1341472Skas 		 */
1351472Skas 
1361472Skas 		if (readonly)
1371472Skas 			chmod(edname, 0400);
1381472Skas 
1391472Skas 		/*
1401228Skas 		 * Fork/execl the editor on the edit file.
1411228Skas 		 */
1421228Skas 
1431228Skas 		if (stat(edname, &statb) < 0)
1441228Skas 			modtime = 0;
1451228Skas 		modtime = statb.st_mtime;
1461228Skas 		pid = vfork();
1471228Skas 		if (pid == -1) {
1481228Skas 			perror("fork");
1491228Skas 			remove(edname);
1501228Skas 			goto out;
1511228Skas 		}
1521228Skas 		if (pid == 0) {
1537544Skurt 			sigchild();
1541228Skas 			if (sigint != SIG_IGN)
1553410Skurt 				sigsys(SIGINT, SIG_DFL);
1561228Skas 			if (sigquit != SIG_IGN)
1573410Skurt 				sigsys(SIGQUIT, SIG_DFL);
1581228Skas 			execl(ed, ed, edname, 0);
1591228Skas 			perror(ed);
1601228Skas 			_exit(1);
1611228Skas 		}
1621228Skas 		while (wait(&mesg) != pid)
1631228Skas 			;
1641228Skas 
1651228Skas 		/*
1661472Skas 		 * If in read only mode, just remove the editor
1671472Skas 		 * temporary and return.
1681472Skas 		 */
1691472Skas 
1701472Skas 		if (readonly) {
1711472Skas 			remove(edname);
1721472Skas 			continue;
1731472Skas 		}
1741472Skas 
1751472Skas 		/*
1761228Skas 		 * Now copy the message to the end of the
1771228Skas 		 * temp file.
1781228Skas 		 */
1791228Skas 
1801228Skas 		if (stat(edname, &statb) < 0) {
1811228Skas 			perror(edname);
1821228Skas 			goto out;
1831228Skas 		}
1841228Skas 		if (modtime == statb.st_mtime) {
1851228Skas 			remove(edname);
1861228Skas 			goto out;
1871228Skas 		}
1881228Skas 		if ((ibuf = fopen(edname, "r")) == NULL) {
1891228Skas 			perror(edname);
1901228Skas 			remove(edname);
1911228Skas 			goto out;
1921228Skas 		}
1931228Skas 		remove(edname);
1941228Skas 		fseek(otf, (long) 0, 2);
1951228Skas 		size = fsize(otf);
1961228Skas 		mp->m_block = blockof(size);
1971228Skas 		mp->m_offset = offsetof(size);
1988745Scarl 		ms = 0L;
1991228Skas 		lines = 0;
2001228Skas 		while ((c = getc(ibuf)) != EOF) {
2011228Skas 			if (c == '\n')
2021228Skas 				lines++;
2031228Skas 			putc(c, otf);
2041228Skas 			if (ferror(otf))
2051228Skas 				break;
2061228Skas 			ms++;
2071228Skas 		}
2081228Skas 		mp->m_size = ms;
2091228Skas 		mp->m_lines = lines;
2101228Skas 		if (ferror(otf))
2111228Skas 			perror("/tmp");
2121228Skas 		fclose(ibuf);
2131228Skas 	}
2141228Skas 
2151228Skas 	/*
2161228Skas 	 * Restore signals and return.
2171228Skas 	 */
2181228Skas 
2191228Skas out:
2203410Skurt 	sigset(SIGINT, sigint);
2213410Skurt 	sigset(SIGQUIT, sigquit);
2221228Skas }
223