xref: /csrg-svn/usr.bin/mail/edit.c (revision 34879)
122451Sdist /*
222451Sdist  * Copyright (c) 1980 Regents of the University of California.
333499Sbostic  * All rights reserved.
433499Sbostic  *
533499Sbostic  * Redistribution and use in source and binary forms are permitted
633499Sbostic  * provided that this notice is preserved and that due credit is given
733499Sbostic  * to the University of California at Berkeley. The name of the University
833499Sbostic  * may not be used to endorse or promote products derived from this
933499Sbostic  * software without specific prior written permission. This software
1033499Sbostic  * is provided ``as is'' without express or implied warranty.
1122451Sdist  */
1222451Sdist 
1333499Sbostic #ifdef notdef
14*34879Sedward static char sccsid[] = "@(#)edit.c	5.6 (Berkeley) 06/29/88";
1533499Sbostic #endif /* notdef */
161228Skas 
171228Skas #include "rcv.h"
181228Skas #include <stdio.h>
191228Skas #include <sys/stat.h>
2031142Sedward #include <sys/wait.h>
211228Skas 
221228Skas /*
231228Skas  * Mail -- a mail program
241228Skas  *
251228Skas  * Perform message editing functions.
261228Skas  */
271228Skas 
281228Skas /*
291228Skas  * Edit a message list.
301228Skas  */
311228Skas 
321228Skas editor(msgvec)
331228Skas 	int *msgvec;
341228Skas {
351228Skas 	char *edname;
361228Skas 
371228Skas 	if ((edname = value("EDITOR")) == NOSTR)
381228Skas 		edname = EDITOR;
391228Skas 	return(edit1(msgvec, edname));
401228Skas }
411228Skas 
421228Skas /*
431228Skas  * Invoke the visual editor on a message list.
441228Skas  */
451228Skas 
461228Skas visual(msgvec)
471228Skas 	int *msgvec;
481228Skas {
491228Skas 	char *edname;
501228Skas 
511228Skas 	if ((edname = value("VISUAL")) == NOSTR)
521228Skas 		edname = VISUAL;
531228Skas 	return(edit1(msgvec, edname));
541228Skas }
551228Skas 
561228Skas /*
571228Skas  * Edit a message by writing the message into a funnily-named file
581228Skas  * (which should not exist) and forking an editor on it.
591228Skas  * We get the editor from the stuff above.
601228Skas  */
611228Skas edit1(msgvec, ed)
621228Skas 	int *msgvec;
631228Skas 	char *ed;
641228Skas {
651228Skas 	register int c;
66*34879Sedward 	int i, pid;
671228Skas 	int (*sigint)(), (*sigquit)();
68*34879Sedward 	FILE *fp;
69*34879Sedward 	extern char tempEdit[];
70*34879Sedward 	char *edname = tempEdit;
7131142Sedward 	register struct message *mp;
721228Skas 	off_t fsize(), size;
731228Skas 	struct stat statb;
74*34879Sedward 	time_t modtime;
7531142Sedward 	union wait status;
761228Skas 
771228Skas 	/*
781228Skas 	 * Set signals; locate editor.
791228Skas 	 */
8031142Sedward 	sigint = signal(SIGINT, SIG_IGN);
8131142Sedward 	sigquit = signal(SIGQUIT, SIG_IGN);
821228Skas 	/*
831228Skas 	 * Deal with each message to be edited . . .
841228Skas 	 */
85*34879Sedward 	for (i = 0; msgvec[i] && i < msgCount; i++) {
86*34879Sedward 		mp = &message[msgvec[i] - 1];
871228Skas 		mp->m_flag |= MODIFY;
88*34879Sedward 		touch(msgvec[i]);
8931142Sedward 		dot = mp;
901228Skas 		/*
91*34879Sedward 		 * Copy the message into the edit file.
92*34879Sedward 		 * If we are in read only mode, make the
93*34879Sedward 		 * temporary message file readonly as well.
941228Skas 		 */
95*34879Sedward 		if ((c = creat(edname, readonly ? 0400 : 0600)) < 0) {
96*34879Sedward 			perror(edname);
971228Skas 			goto out;
981228Skas 		}
99*34879Sedward 		if ((fp = fdopen(c, "w")) == NULL) {
1001228Skas 			perror(edname);
101*34879Sedward 			(void) unlink(edname);
1021228Skas 			goto out;
1031228Skas 		}
104*34879Sedward 		if (send(mp, fp, 0) < 0) {
1051228Skas 			perror(edname);
106*34879Sedward 			(void) fclose(fp);
107*34879Sedward 			(void) unlink(edname);
1081228Skas 			goto out;
1091228Skas 		}
110*34879Sedward 		(void) fflush(fp);
111*34879Sedward 		if (ferror(fp)) {
112*34879Sedward 			(void) unlink(edname);
113*34879Sedward 			(void) fclose(fp);
1141228Skas 			goto out;
1151228Skas 		}
116*34879Sedward 		if (fstat(fileno(fp), &statb) < 0)
117*34879Sedward 			modtime = 0;
118*34879Sedward 		else
119*34879Sedward 			modtime = statb.st_mtime;
120*34879Sedward 		(void) fclose(fp);
1211228Skas 		/*
1221228Skas 		 * Fork/execl the editor on the edit file.
1231228Skas 		 */
1241228Skas 		pid = vfork();
1251228Skas 		if (pid == -1) {
1261228Skas 			perror("fork");
127*34879Sedward 			(void) unlink(edname);
1281228Skas 			goto out;
1291228Skas 		}
1301228Skas 		if (pid == 0) {
1311228Skas 			if (sigint != SIG_IGN)
13231143Sedward 				(void) signal(SIGINT, SIG_DFL);
1331228Skas 			if (sigquit != SIG_IGN)
13431143Sedward 				(void) signal(SIGQUIT, SIG_DFL);
1351228Skas 			execl(ed, ed, edname, 0);
1361228Skas 			perror(ed);
1371228Skas 			_exit(1);
1381228Skas 		}
13931142Sedward 		while (wait(&status) != pid)
1401228Skas 			;
1411228Skas 		/*
1421472Skas 		 * If in read only mode, just remove the editor
1431472Skas 		 * temporary and return.
1441472Skas 		 */
1451472Skas 		if (readonly) {
146*34879Sedward 			(void) unlink(edname);
1471472Skas 			continue;
1481472Skas 		}
1491472Skas 		/*
1501228Skas 		 * Now copy the message to the end of the
1511228Skas 		 * temp file.
1521228Skas 		 */
1531228Skas 		if (stat(edname, &statb) < 0) {
1541228Skas 			perror(edname);
1551228Skas 			goto out;
1561228Skas 		}
1571228Skas 		if (modtime == statb.st_mtime) {
158*34879Sedward 			(void) unlink(edname);
1591228Skas 			goto out;
1601228Skas 		}
161*34879Sedward 		if ((fp = fopen(edname, "r")) == NULL) {
1621228Skas 			perror(edname);
163*34879Sedward 			(void) unlink(edname);
1641228Skas 			goto out;
1651228Skas 		}
166*34879Sedward 		(void) unlink(edname);
16731143Sedward 		(void) fseek(otf, (long) 0, 2);
16831142Sedward 		size = ftell(otf);
1691228Skas 		mp->m_block = blockof(size);
1701228Skas 		mp->m_offset = offsetof(size);
171*34879Sedward 		mp->m_size = fsize(fp);
17231142Sedward 		mp->m_lines = 0;
173*34879Sedward 		while ((c = getc(fp)) != EOF) {
1741228Skas 			if (c == '\n')
17531142Sedward 				mp->m_lines++;
17631143Sedward 			(void) putc(c, otf);
1771228Skas 			if (ferror(otf))
1781228Skas 				break;
1791228Skas 		}
1801228Skas 		if (ferror(otf))
1811228Skas 			perror("/tmp");
182*34879Sedward 		(void) fclose(fp);
1831228Skas 	}
1841228Skas 	/*
1851228Skas 	 * Restore signals and return.
1861228Skas 	 */
1871228Skas out:
18831143Sedward 	(void) signal(SIGINT, sigint);
18931143Sedward 	(void) signal(SIGQUIT, sigquit);
19031142Sedward 	return 0;
1911228Skas }
192