xref: /csrg-svn/usr.bin/mail/edit.c (revision 34963)
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
634905Sbostic  * provided that the above copyright notice and this paragraph are
734905Sbostic  * duplicated in all such forms and that any documentation,
834905Sbostic  * advertising materials, and other materials related to such
934905Sbostic  * distribution and use acknowledge that the software was developed
1034905Sbostic  * by the University of California, Berkeley.  The name of the
1134905Sbostic  * University may not be used to endorse or promote products derived
1234905Sbostic  * from this software without specific prior written permission.
1334905Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434905Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534905Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1622451Sdist  */
1722451Sdist 
1834905Sbostic #ifndef lint
19*34963Sedward static char sccsid[] = "@(#)edit.c	5.8 (Berkeley) 07/07/88";
2034905Sbostic #endif /* not lint */
211228Skas 
221228Skas #include "rcv.h"
231228Skas #include <stdio.h>
241228Skas #include <sys/stat.h>
2531142Sedward #include <sys/wait.h>
261228Skas 
271228Skas /*
281228Skas  * Mail -- a mail program
291228Skas  *
301228Skas  * Perform message editing functions.
311228Skas  */
321228Skas 
331228Skas /*
341228Skas  * Edit a message list.
351228Skas  */
361228Skas 
371228Skas editor(msgvec)
381228Skas 	int *msgvec;
391228Skas {
401228Skas 
41*34963Sedward 	return edit1(msgvec, 'e');
421228Skas }
431228Skas 
441228Skas /*
451228Skas  * Invoke the visual editor on a message list.
461228Skas  */
471228Skas 
481228Skas visual(msgvec)
491228Skas 	int *msgvec;
501228Skas {
511228Skas 
52*34963Sedward 	return edit1(msgvec, 'v');
531228Skas }
541228Skas 
551228Skas /*
561228Skas  * Edit a message by writing the message into a funnily-named file
571228Skas  * (which should not exist) and forking an editor on it.
581228Skas  * We get the editor from the stuff above.
591228Skas  */
60*34963Sedward edit1(msgvec, type)
611228Skas 	int *msgvec;
62*34963Sedward 	char type;
631228Skas {
64*34963Sedward 	int (*sigcont)() = signal(SIGCONT, SIG_DFL);
651228Skas 	register int c;
66*34963Sedward 	int i;
6734879Sedward 	FILE *fp;
6831142Sedward 	register struct message *mp;
69*34963Sedward 	off_t size;
701228Skas 
711228Skas 	/*
721228Skas 	 * Deal with each message to be edited . . .
731228Skas 	 */
7434879Sedward 	for (i = 0; msgvec[i] && i < msgCount; i++) {
75*34963Sedward 		int (*sigint)();
76*34963Sedward 		int m = msgvec[i];
77*34963Sedward 
78*34963Sedward 		if (i > 0) {
79*34963Sedward 			char buf[100];
80*34963Sedward 			char *p;
81*34963Sedward 
82*34963Sedward 			printf("Edit message %d [ynq]? ", m);
83*34963Sedward 			if (fgets(buf, sizeof buf, stdin) == 0)
84*34963Sedward 				break;
85*34963Sedward 			for (p = buf; any(*p, " \t"); p++)
86*34963Sedward 				;
87*34963Sedward 			if (*p == 'q')
88*34963Sedward 				break;
89*34963Sedward 			if (*p == 'n')
90*34963Sedward 				continue;
911228Skas 		}
92*34963Sedward 		dot = mp = &message[m - 1];
93*34963Sedward 		touch(m);
94*34963Sedward 		sigint = signal(SIGINT, SIG_IGN);
95*34963Sedward 		fp = run_editor(setinput(mp), mp->m_size, type, readonly);
96*34963Sedward 		if (fp != NULL) {
97*34963Sedward 			(void) fseek(otf, (long) 0, 2);
98*34963Sedward 			size = ftell(otf);
99*34963Sedward 			mp->m_block = blockof(size);
100*34963Sedward 			mp->m_offset = offsetof(size);
101*34963Sedward 			mp->m_size = fsize(fp);
102*34963Sedward 			mp->m_lines = 0;
103*34963Sedward 			mp->m_flag |= MODIFY;
104*34963Sedward 			rewind(fp);
105*34963Sedward 			while ((c = getc(fp)) != EOF) {
106*34963Sedward 				if (c == '\n')
107*34963Sedward 					mp->m_lines++;
108*34963Sedward 				if (putc(c, otf) == EOF)
109*34963Sedward 					break;
110*34963Sedward 			}
111*34963Sedward 			if (ferror(otf))
112*34963Sedward 				perror("/tmp");
11334879Sedward 			(void) fclose(fp);
1141228Skas 		}
115*34963Sedward 		(void) signal(SIGINT, sigint);
1161228Skas 	}
117*34963Sedward 	(void) signal(SIGCONT, sigcont);
118*34963Sedward 	return 0;
119*34963Sedward }
120*34963Sedward 
121*34963Sedward /*
122*34963Sedward  * Run an editor on the file at "fpp" of "size" bytes,
123*34963Sedward  * and return a new file pointer.
124*34963Sedward  * Signals must be handled by the caller.
125*34963Sedward  * "Type" is 'e' for EDITOR, 'v' for VISUAL.
126*34963Sedward  */
127*34963Sedward FILE *
128*34963Sedward run_editor(fp, size, type, readonly)
129*34963Sedward 	register FILE *fp;
130*34963Sedward 	off_t size;
131*34963Sedward 	char type;
132*34963Sedward {
133*34963Sedward 	register FILE *nf = NULL;
134*34963Sedward 	register int t;
135*34963Sedward 	time_t modtime;
136*34963Sedward 	char *edit;
137*34963Sedward 	struct stat statb;
138*34963Sedward 	extern char tempEdit[];
139*34963Sedward 
140*34963Sedward 	if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) {
141*34963Sedward 		perror(tempEdit);
142*34963Sedward 		goto out;
143*34963Sedward 	}
144*34963Sedward 	if ((nf = fdopen(t, "w")) == NULL) {
145*34963Sedward 		perror(tempEdit);
146*34963Sedward 		(void) unlink(tempEdit);
147*34963Sedward 		goto out;
148*34963Sedward 	}
149*34963Sedward 	if (size >= 0)
150*34963Sedward 		while (--size >= 0 && (t = getc(fp)) != EOF)
151*34963Sedward 			(void) putc(t, nf);
152*34963Sedward 	else
153*34963Sedward 		while ((t = getc(fp)) != EOF)
154*34963Sedward 			(void) putc(t, nf);
155*34963Sedward 	(void) fflush(nf);
156*34963Sedward 	if (fstat(fileno(nf), &statb) < 0)
157*34963Sedward 		modtime = 0;
158*34963Sedward 	else
159*34963Sedward 		modtime = statb.st_mtime;
160*34963Sedward 	if (ferror(nf) || fclose(nf) < 0) {
161*34963Sedward 		perror(tempEdit);
162*34963Sedward 		(void) unlink(tempEdit);
163*34963Sedward 		nf = NULL;
164*34963Sedward 		goto out;
165*34963Sedward 	}
166*34963Sedward 	nf = NULL;
167*34963Sedward 	if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
168*34963Sedward 		edit = type == 'e' ? EDITOR : VISUAL;
169*34963Sedward 	if (run_command(edit, 0, -1, -1, tempEdit, NOSTR) < 0) {
170*34963Sedward 		(void) unlink(tempEdit);
171*34963Sedward 		goto out;
172*34963Sedward 	}
1731228Skas 	/*
174*34963Sedward 	 * If in read only mode or file unchanged, just remove the editor
175*34963Sedward 	 * temporary and return.
1761228Skas 	 */
177*34963Sedward 	if (readonly) {
178*34963Sedward 		(void) unlink(tempEdit);
179*34963Sedward 		goto out;
180*34963Sedward 	}
181*34963Sedward 	if (stat(tempEdit, &statb) < 0) {
182*34963Sedward 		perror(tempEdit);
183*34963Sedward 		goto out;
184*34963Sedward 	}
185*34963Sedward 	if (modtime == statb.st_mtime) {
186*34963Sedward 		(void) unlink(tempEdit);
187*34963Sedward 		goto out;
188*34963Sedward 	}
189*34963Sedward 	/*
190*34963Sedward 	 * Now switch to new file.
191*34963Sedward 	 */
192*34963Sedward 	if ((nf = fopen(tempEdit, "a+")) == NULL) {
193*34963Sedward 		perror(tempEdit);
194*34963Sedward 		(void) unlink(tempEdit);
195*34963Sedward 		goto out;
196*34963Sedward 	}
197*34963Sedward 	(void) unlink(tempEdit);
1981228Skas out:
199*34963Sedward 	return nf;
2001228Skas }
201