xref: /csrg-svn/usr.bin/mail/edit.c (revision 33499)
122451Sdist /*
222451Sdist  * Copyright (c) 1980 Regents of the University of California.
3*33499Sbostic  * All rights reserved.
4*33499Sbostic  *
5*33499Sbostic  * Redistribution and use in source and binary forms are permitted
6*33499Sbostic  * provided that this notice is preserved and that due credit is given
7*33499Sbostic  * to the University of California at Berkeley. The name of the University
8*33499Sbostic  * may not be used to endorse or promote products derived from this
9*33499Sbostic  * software without specific prior written permission. This software
10*33499Sbostic  * is provided ``as is'' without express or implied warranty.
1122451Sdist  */
1222451Sdist 
13*33499Sbostic #ifdef notdef
14*33499Sbostic static char sccsid[] = "@(#)edit.c	5.5 (Berkeley) 02/18/88";
15*33499Sbostic #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 
621228Skas edit1(msgvec, ed)
631228Skas 	int *msgvec;
641228Skas 	char *ed;
651228Skas {
661228Skas 	register int c;
6731142Sedward 	int *ip, pid, mesg;
681228Skas 	int (*sigint)(), (*sigquit)();
691228Skas 	FILE *ibuf, *obuf;
7031143Sedward 	char edname[15];
7131142Sedward 	register struct message *mp;
721228Skas 	extern char tempEdit[];
731228Skas 	off_t fsize(), size;
741228Skas 	struct stat statb;
751228Skas 	long modtime;
7631142Sedward 	union wait status;
771228Skas 
781228Skas 	/*
791228Skas 	 * Set signals; locate editor.
801228Skas 	 */
811228Skas 
8231142Sedward 	sigint = signal(SIGINT, SIG_IGN);
8331142Sedward 	sigquit = signal(SIGQUIT, SIG_IGN);
841228Skas 
851228Skas 	/*
861228Skas 	 * Deal with each message to be edited . . .
871228Skas 	 */
881228Skas 
891228Skas 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
901228Skas 		mesg = *ip;
911228Skas 		mp = &message[mesg-1];
921228Skas 		mp->m_flag |= MODIFY;
9331142Sedward 		touch(mesg);
9431142Sedward 		dot = mp;
951228Skas 
961228Skas 		/*
971228Skas 		 * Make up a name for the edit file of the
981228Skas 		 * form "Message%d" and make sure it doesn't
991228Skas 		 * already exist.
1001228Skas 		 */
10131143Sedward 		(void) sprintf(edname, "Message%d", mesg);
1021228Skas 		if (!access(edname, 2)) {
1031228Skas 			printf("%s: file exists\n", edname);
1041228Skas 			goto out;
1051228Skas 		}
1061228Skas 
1071228Skas 		/*
1081228Skas 		 * Copy the message into the edit file.
1091228Skas 		 */
11031143Sedward 		(void) close(creat(edname, 0600));
1111228Skas 		if ((obuf = fopen(edname, "w")) == NULL) {
1121228Skas 			perror(edname);
1131228Skas 			goto out;
1141228Skas 		}
1157577Skurt 		if (send(mp, obuf, 0) < 0) {
1161228Skas 			perror(edname);
11731143Sedward 			(void) fclose(obuf);
11831143Sedward 			(void) remove(edname);
1191228Skas 			goto out;
1201228Skas 		}
12131143Sedward 		(void) fflush(obuf);
1221228Skas 		if (ferror(obuf)) {
12331143Sedward 			(void) remove(edname);
12431143Sedward 			(void) fclose(obuf);
1251228Skas 			goto out;
1261228Skas 		}
12731143Sedward 		(void) fclose(obuf);
1281228Skas 
1291228Skas 		/*
1301472Skas 		 * If we are in read only mode, make the
1311472Skas 		 * temporary message file readonly as well.
1321472Skas 		 */
1331472Skas 
1341472Skas 		if (readonly)
13531143Sedward 			(void) chmod(edname, 0400);
1361472Skas 
1371472Skas 		/*
1381228Skas 		 * Fork/execl the editor on the edit file.
1391228Skas 		 */
1401228Skas 
1411228Skas 		if (stat(edname, &statb) < 0)
1421228Skas 			modtime = 0;
1431228Skas 		modtime = statb.st_mtime;
1441228Skas 		pid = vfork();
1451228Skas 		if (pid == -1) {
1461228Skas 			perror("fork");
14731143Sedward 			(void) remove(edname);
1481228Skas 			goto out;
1491228Skas 		}
1501228Skas 		if (pid == 0) {
1511228Skas 			if (sigint != SIG_IGN)
15231143Sedward 				(void) signal(SIGINT, SIG_DFL);
1531228Skas 			if (sigquit != SIG_IGN)
15431143Sedward 				(void) signal(SIGQUIT, SIG_DFL);
1551228Skas 			execl(ed, ed, edname, 0);
1561228Skas 			perror(ed);
1571228Skas 			_exit(1);
1581228Skas 		}
15931142Sedward 		while (wait(&status) != pid)
1601228Skas 			;
1611228Skas 
1621228Skas 		/*
1631472Skas 		 * If in read only mode, just remove the editor
1641472Skas 		 * temporary and return.
1651472Skas 		 */
1661472Skas 
1671472Skas 		if (readonly) {
16831143Sedward 			(void) remove(edname);
1691472Skas 			continue;
1701472Skas 		}
1711472Skas 
1721472Skas 		/*
1731228Skas 		 * Now copy the message to the end of the
1741228Skas 		 * temp file.
1751228Skas 		 */
1761228Skas 
1771228Skas 		if (stat(edname, &statb) < 0) {
1781228Skas 			perror(edname);
1791228Skas 			goto out;
1801228Skas 		}
1811228Skas 		if (modtime == statb.st_mtime) {
18231143Sedward 			(void) remove(edname);
1831228Skas 			goto out;
1841228Skas 		}
1851228Skas 		if ((ibuf = fopen(edname, "r")) == NULL) {
1861228Skas 			perror(edname);
18731143Sedward 			(void) remove(edname);
1881228Skas 			goto out;
1891228Skas 		}
19031143Sedward 		(void) remove(edname);
19131143Sedward 		(void) fseek(otf, (long) 0, 2);
19231142Sedward 		size = ftell(otf);
1931228Skas 		mp->m_block = blockof(size);
1941228Skas 		mp->m_offset = offsetof(size);
19531142Sedward 		mp->m_size = fsize(ibuf);
19631142Sedward 		mp->m_lines = 0;
1971228Skas 		while ((c = getc(ibuf)) != EOF) {
1981228Skas 			if (c == '\n')
19931142Sedward 				mp->m_lines++;
20031143Sedward 			(void) putc(c, otf);
2011228Skas 			if (ferror(otf))
2021228Skas 				break;
2031228Skas 		}
2041228Skas 		if (ferror(otf))
2051228Skas 			perror("/tmp");
20631143Sedward 		(void) fclose(ibuf);
2071228Skas 	}
2081228Skas 
2091228Skas 	/*
2101228Skas 	 * Restore signals and return.
2111228Skas 	 */
2121228Skas 
2131228Skas out:
21431143Sedward 	(void) signal(SIGINT, sigint);
21531143Sedward 	(void) signal(SIGQUIT, sigquit);
21631142Sedward 	return 0;
2171228Skas }
218