xref: /csrg-svn/usr.bin/mail/edit.c (revision 43865)
122451Sdist /*
222451Sdist  * Copyright (c) 1980 Regents of the University of California.
333499Sbostic  * All rights reserved.
433499Sbostic  *
542741Sbostic  * %sccs.include.redist.c%
622451Sdist  */
722451Sdist 
834905Sbostic #ifndef lint
9*43865Sedward static char sccsid[] = "@(#)edit.c	5.15 (Berkeley) 06/25/90";
1034905Sbostic #endif /* not lint */
111228Skas 
121228Skas #include "rcv.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 
2934963Sedward 	return edit1(msgvec, 'e');
301228Skas }
311228Skas 
321228Skas /*
331228Skas  * Invoke the visual editor on a message list.
341228Skas  */
351228Skas 
361228Skas visual(msgvec)
371228Skas 	int *msgvec;
381228Skas {
391228Skas 
4034963Sedward 	return edit1(msgvec, 'v');
411228Skas }
421228Skas 
431228Skas /*
441228Skas  * Edit a message by writing the message into a funnily-named file
451228Skas  * (which should not exist) and forking an editor on it.
461228Skas  * We get the editor from the stuff above.
471228Skas  */
4834963Sedward edit1(msgvec, type)
491228Skas 	int *msgvec;
5034963Sedward 	char type;
511228Skas {
521228Skas 	register int c;
5334963Sedward 	int i;
5434879Sedward 	FILE *fp;
5531142Sedward 	register struct message *mp;
5634963Sedward 	off_t size;
571228Skas 
581228Skas 	/*
591228Skas 	 * Deal with each message to be edited . . .
601228Skas 	 */
6134879Sedward 	for (i = 0; msgvec[i] && i < msgCount; i++) {
6239612Sedward 		sig_t sigint;
6334963Sedward 
6434963Sedward 		if (i > 0) {
6534963Sedward 			char buf[100];
6634963Sedward 			char *p;
6734963Sedward 
6834987Sedward 			printf("Edit message %d [ynq]? ", msgvec[i]);
6934963Sedward 			if (fgets(buf, sizeof buf, stdin) == 0)
7034963Sedward 				break;
7134987Sedward 			for (p = buf; *p == ' ' || *p == '\t'; p++)
7234963Sedward 				;
7334963Sedward 			if (*p == 'q')
7434963Sedward 				break;
7534963Sedward 			if (*p == 'n')
7634963Sedward 				continue;
771228Skas 		}
7834987Sedward 		dot = mp = &message[msgvec[i] - 1];
7934987Sedward 		touch(mp);
8034963Sedward 		sigint = signal(SIGINT, SIG_IGN);
8134963Sedward 		fp = run_editor(setinput(mp), mp->m_size, type, readonly);
8234963Sedward 		if (fp != NULL) {
8334963Sedward 			(void) fseek(otf, (long) 0, 2);
8434963Sedward 			size = ftell(otf);
8534963Sedward 			mp->m_block = blockof(size);
8634963Sedward 			mp->m_offset = offsetof(size);
8734963Sedward 			mp->m_size = fsize(fp);
8834963Sedward 			mp->m_lines = 0;
8934963Sedward 			mp->m_flag |= MODIFY;
9034963Sedward 			rewind(fp);
9134963Sedward 			while ((c = getc(fp)) != EOF) {
9234963Sedward 				if (c == '\n')
9334963Sedward 					mp->m_lines++;
9434963Sedward 				if (putc(c, otf) == EOF)
9534963Sedward 					break;
9634963Sedward 			}
9734963Sedward 			if (ferror(otf))
9834963Sedward 				perror("/tmp");
99*43865Sedward 			(void) Fclose(fp);
1001228Skas 		}
10134963Sedward 		(void) signal(SIGINT, sigint);
1021228Skas 	}
10334963Sedward 	return 0;
10434963Sedward }
10534963Sedward 
10634963Sedward /*
10734963Sedward  * Run an editor on the file at "fpp" of "size" bytes,
10834963Sedward  * and return a new file pointer.
10934963Sedward  * Signals must be handled by the caller.
11037870Sbostic  * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI.
11134963Sedward  */
11234963Sedward FILE *
11334963Sedward run_editor(fp, size, type, readonly)
11434963Sedward 	register FILE *fp;
11534963Sedward 	off_t size;
11634963Sedward 	char type;
11734963Sedward {
11834963Sedward 	register FILE *nf = NULL;
11934963Sedward 	register int t;
12034963Sedward 	time_t modtime;
12134963Sedward 	char *edit;
12234963Sedward 	struct stat statb;
12334963Sedward 	extern char tempEdit[];
12434963Sedward 
12534963Sedward 	if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) {
12634963Sedward 		perror(tempEdit);
12734963Sedward 		goto out;
12834963Sedward 	}
129*43865Sedward 	if ((nf = Fdopen(t, "w")) == NULL) {
13034963Sedward 		perror(tempEdit);
13134963Sedward 		(void) unlink(tempEdit);
13234963Sedward 		goto out;
13334963Sedward 	}
13434963Sedward 	if (size >= 0)
13534963Sedward 		while (--size >= 0 && (t = getc(fp)) != EOF)
13634963Sedward 			(void) putc(t, nf);
13734963Sedward 	else
13834963Sedward 		while ((t = getc(fp)) != EOF)
13934963Sedward 			(void) putc(t, nf);
14034963Sedward 	(void) fflush(nf);
14134963Sedward 	if (fstat(fileno(nf), &statb) < 0)
14234963Sedward 		modtime = 0;
14334963Sedward 	else
14434963Sedward 		modtime = statb.st_mtime;
145*43865Sedward 	if (ferror(nf)) {
146*43865Sedward 		(void) Fclose(nf);
14734963Sedward 		perror(tempEdit);
14834963Sedward 		(void) unlink(tempEdit);
14934963Sedward 		nf = NULL;
15034963Sedward 		goto out;
15134963Sedward 	}
152*43865Sedward 	if (Fclose(nf) < 0) {
153*43865Sedward 		perror(tempEdit);
154*43865Sedward 		(void) unlink(tempEdit);
155*43865Sedward 		nf = NULL;
156*43865Sedward 		goto out;
157*43865Sedward 	}
15834963Sedward 	nf = NULL;
15934963Sedward 	if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
16037870Sbostic 		edit = type == 'e' ? _PATH_EX : _PATH_VI;
16134963Sedward 	if (run_command(edit, 0, -1, -1, tempEdit, NOSTR) < 0) {
16234963Sedward 		(void) unlink(tempEdit);
16334963Sedward 		goto out;
16434963Sedward 	}
1651228Skas 	/*
16634963Sedward 	 * If in read only mode or file unchanged, just remove the editor
16734963Sedward 	 * temporary and return.
1681228Skas 	 */
16934963Sedward 	if (readonly) {
17034963Sedward 		(void) unlink(tempEdit);
17134963Sedward 		goto out;
17234963Sedward 	}
17334963Sedward 	if (stat(tempEdit, &statb) < 0) {
17434963Sedward 		perror(tempEdit);
17534963Sedward 		goto out;
17634963Sedward 	}
17734963Sedward 	if (modtime == statb.st_mtime) {
17834963Sedward 		(void) unlink(tempEdit);
17934963Sedward 		goto out;
18034963Sedward 	}
18134963Sedward 	/*
18234963Sedward 	 * Now switch to new file.
18334963Sedward 	 */
184*43865Sedward 	if ((nf = Fopen(tempEdit, "a+")) == NULL) {
18534963Sedward 		perror(tempEdit);
18634963Sedward 		(void) unlink(tempEdit);
18734963Sedward 		goto out;
18834963Sedward 	}
18934963Sedward 	(void) unlink(tempEdit);
1901228Skas out:
19134963Sedward 	return nf;
1921228Skas }
193