xref: /csrg-svn/usr.bin/mail/edit.c (revision 62083)
122451Sdist /*
2*62083Sbostic  * Copyright (c) 1980, 1993
3*62083Sbostic  *	The Regents of the University of California.  All rights reserved.
433499Sbostic  *
542741Sbostic  * %sccs.include.redist.c%
622451Sdist  */
722451Sdist 
834905Sbostic #ifndef lint
9*62083Sbostic static char sccsid[] = "@(#)edit.c	8.1 (Berkeley) 06/06/93";
1034905Sbostic #endif /* not lint */
111228Skas 
121228Skas #include "rcv.h"
1354505Sbostic #include <fcntl.h>
1454505Sbostic #include "extern.h"
151228Skas 
161228Skas /*
171228Skas  * Mail -- a mail program
181228Skas  *
191228Skas  * Perform message editing functions.
201228Skas  */
211228Skas 
221228Skas /*
231228Skas  * Edit a message list.
241228Skas  */
2554505Sbostic int
editor(msgvec)261228Skas editor(msgvec)
271228Skas 	int *msgvec;
281228Skas {
291228Skas 
3034963Sedward 	return edit1(msgvec, 'e');
311228Skas }
321228Skas 
331228Skas /*
341228Skas  * Invoke the visual editor on a message list.
351228Skas  */
3654505Sbostic int
visual(msgvec)371228Skas visual(msgvec)
381228Skas 	int *msgvec;
391228Skas {
401228Skas 
4134963Sedward 	return edit1(msgvec, 'v');
421228Skas }
431228Skas 
441228Skas /*
451228Skas  * Edit a message by writing the message into a funnily-named file
461228Skas  * (which should not exist) and forking an editor on it.
471228Skas  * We get the editor from the stuff above.
481228Skas  */
4954505Sbostic int
edit1(msgvec,type)5034963Sedward edit1(msgvec, type)
511228Skas 	int *msgvec;
5254505Sbostic 	int type;
531228Skas {
541228Skas 	register int c;
5534963Sedward 	int i;
5634879Sedward 	FILE *fp;
5731142Sedward 	register struct message *mp;
5834963Sedward 	off_t size;
591228Skas 
601228Skas 	/*
611228Skas 	 * Deal with each message to be edited . . .
621228Skas 	 */
6334879Sedward 	for (i = 0; msgvec[i] && i < msgCount; i++) {
6439612Sedward 		sig_t sigint;
6534963Sedward 
6634963Sedward 		if (i > 0) {
6734963Sedward 			char buf[100];
6834963Sedward 			char *p;
6934963Sedward 
7034987Sedward 			printf("Edit message %d [ynq]? ", msgvec[i]);
7134963Sedward 			if (fgets(buf, sizeof buf, stdin) == 0)
7234963Sedward 				break;
7334987Sedward 			for (p = buf; *p == ' ' || *p == '\t'; p++)
7434963Sedward 				;
7534963Sedward 			if (*p == 'q')
7634963Sedward 				break;
7734963Sedward 			if (*p == 'n')
7834963Sedward 				continue;
791228Skas 		}
8034987Sedward 		dot = mp = &message[msgvec[i] - 1];
8134987Sedward 		touch(mp);
8234963Sedward 		sigint = signal(SIGINT, SIG_IGN);
8334963Sedward 		fp = run_editor(setinput(mp), mp->m_size, type, readonly);
8434963Sedward 		if (fp != NULL) {
8554505Sbostic 			(void) fseek(otf, 0L, 2);
8634963Sedward 			size = ftell(otf);
8734963Sedward 			mp->m_block = blockof(size);
8834963Sedward 			mp->m_offset = offsetof(size);
8934963Sedward 			mp->m_size = fsize(fp);
9034963Sedward 			mp->m_lines = 0;
9134963Sedward 			mp->m_flag |= MODIFY;
9234963Sedward 			rewind(fp);
9334963Sedward 			while ((c = getc(fp)) != EOF) {
9434963Sedward 				if (c == '\n')
9534963Sedward 					mp->m_lines++;
9634963Sedward 				if (putc(c, otf) == EOF)
9734963Sedward 					break;
9834963Sedward 			}
9934963Sedward 			if (ferror(otf))
10034963Sedward 				perror("/tmp");
10143865Sedward 			(void) Fclose(fp);
1021228Skas 		}
10334963Sedward 		(void) signal(SIGINT, sigint);
1041228Skas 	}
10534963Sedward 	return 0;
10634963Sedward }
10734963Sedward 
10834963Sedward /*
10934963Sedward  * Run an editor on the file at "fpp" of "size" bytes,
11034963Sedward  * and return a new file pointer.
11134963Sedward  * Signals must be handled by the caller.
11237870Sbostic  * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI.
11334963Sedward  */
11434963Sedward FILE *
run_editor(fp,size,type,readonly)11534963Sedward run_editor(fp, size, type, readonly)
11634963Sedward 	register FILE *fp;
11734963Sedward 	off_t size;
11854505Sbostic 	int type, readonly;
11934963Sedward {
12034963Sedward 	register FILE *nf = NULL;
12134963Sedward 	register int t;
12234963Sedward 	time_t modtime;
12334963Sedward 	char *edit;
12434963Sedward 	struct stat statb;
12534963Sedward 	extern char tempEdit[];
12634963Sedward 
12734963Sedward 	if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) {
12834963Sedward 		perror(tempEdit);
12934963Sedward 		goto out;
13034963Sedward 	}
13143865Sedward 	if ((nf = Fdopen(t, "w")) == NULL) {
13234963Sedward 		perror(tempEdit);
13334963Sedward 		(void) unlink(tempEdit);
13434963Sedward 		goto out;
13534963Sedward 	}
13634963Sedward 	if (size >= 0)
13734963Sedward 		while (--size >= 0 && (t = getc(fp)) != EOF)
13834963Sedward 			(void) putc(t, nf);
13934963Sedward 	else
14034963Sedward 		while ((t = getc(fp)) != EOF)
14134963Sedward 			(void) putc(t, nf);
14234963Sedward 	(void) fflush(nf);
14334963Sedward 	if (fstat(fileno(nf), &statb) < 0)
14434963Sedward 		modtime = 0;
14534963Sedward 	else
14634963Sedward 		modtime = statb.st_mtime;
14743865Sedward 	if (ferror(nf)) {
14843865Sedward 		(void) Fclose(nf);
14934963Sedward 		perror(tempEdit);
15034963Sedward 		(void) unlink(tempEdit);
15134963Sedward 		nf = NULL;
15234963Sedward 		goto out;
15334963Sedward 	}
15443865Sedward 	if (Fclose(nf) < 0) {
15543865Sedward 		perror(tempEdit);
15643865Sedward 		(void) unlink(tempEdit);
15743865Sedward 		nf = NULL;
15843865Sedward 		goto out;
15943865Sedward 	}
16034963Sedward 	nf = NULL;
16134963Sedward 	if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
16237870Sbostic 		edit = type == 'e' ? _PATH_EX : _PATH_VI;
16354505Sbostic 	if (run_command(edit, 0, -1, -1, tempEdit, NOSTR, NOSTR) < 0) {
16434963Sedward 		(void) unlink(tempEdit);
16534963Sedward 		goto out;
16634963Sedward 	}
1671228Skas 	/*
16834963Sedward 	 * If in read only mode or file unchanged, just remove the editor
16934963Sedward 	 * temporary and return.
1701228Skas 	 */
17134963Sedward 	if (readonly) {
17234963Sedward 		(void) unlink(tempEdit);
17334963Sedward 		goto out;
17434963Sedward 	}
17534963Sedward 	if (stat(tempEdit, &statb) < 0) {
17634963Sedward 		perror(tempEdit);
17734963Sedward 		goto out;
17834963Sedward 	}
17934963Sedward 	if (modtime == statb.st_mtime) {
18034963Sedward 		(void) unlink(tempEdit);
18134963Sedward 		goto out;
18234963Sedward 	}
18334963Sedward 	/*
18434963Sedward 	 * Now switch to new file.
18534963Sedward 	 */
18643865Sedward 	if ((nf = Fopen(tempEdit, "a+")) == NULL) {
18734963Sedward 		perror(tempEdit);
18834963Sedward 		(void) unlink(tempEdit);
18934963Sedward 		goto out;
19034963Sedward 	}
19134963Sedward 	(void) unlink(tempEdit);
1921228Skas out:
19334963Sedward 	return nf;
1941228Skas }
195