xref: /csrg-svn/usr.bin/mail/edit.c (revision 37870)
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*37870Sbostic static char sccsid[] = "@(#)edit.c	5.12 (Berkeley) 05/11/89";
2034905Sbostic #endif /* not lint */
211228Skas 
221228Skas #include "rcv.h"
231228Skas #include <sys/stat.h>
241228Skas 
251228Skas /*
261228Skas  * Mail -- a mail program
271228Skas  *
281228Skas  * Perform message editing functions.
291228Skas  */
301228Skas 
311228Skas /*
321228Skas  * Edit a message list.
331228Skas  */
341228Skas 
351228Skas editor(msgvec)
361228Skas 	int *msgvec;
371228Skas {
381228Skas 
3934963Sedward 	return edit1(msgvec, 'e');
401228Skas }
411228Skas 
421228Skas /*
431228Skas  * Invoke the visual editor on a message list.
441228Skas  */
451228Skas 
461228Skas visual(msgvec)
471228Skas 	int *msgvec;
481228Skas {
491228Skas 
5034963Sedward 	return edit1(msgvec, 'v');
511228Skas }
521228Skas 
531228Skas /*
541228Skas  * Edit a message by writing the message into a funnily-named file
551228Skas  * (which should not exist) and forking an editor on it.
561228Skas  * We get the editor from the stuff above.
571228Skas  */
5834963Sedward edit1(msgvec, type)
591228Skas 	int *msgvec;
6034963Sedward 	char type;
611228Skas {
621228Skas 	register int c;
6334963Sedward 	int i;
6434879Sedward 	FILE *fp;
6531142Sedward 	register struct message *mp;
6634963Sedward 	off_t size;
671228Skas 
681228Skas 	/*
691228Skas 	 * Deal with each message to be edited . . .
701228Skas 	 */
7134879Sedward 	for (i = 0; msgvec[i] && i < msgCount; i++) {
7234963Sedward 		int (*sigint)();
7334963Sedward 
7434963Sedward 		if (i > 0) {
7534963Sedward 			char buf[100];
7634963Sedward 			char *p;
7734963Sedward 
7834987Sedward 			printf("Edit message %d [ynq]? ", msgvec[i]);
7934963Sedward 			if (fgets(buf, sizeof buf, stdin) == 0)
8034963Sedward 				break;
8134987Sedward 			for (p = buf; *p == ' ' || *p == '\t'; p++)
8234963Sedward 				;
8334963Sedward 			if (*p == 'q')
8434963Sedward 				break;
8534963Sedward 			if (*p == 'n')
8634963Sedward 				continue;
871228Skas 		}
8834987Sedward 		dot = mp = &message[msgvec[i] - 1];
8934987Sedward 		touch(mp);
9034963Sedward 		sigint = signal(SIGINT, SIG_IGN);
9134963Sedward 		fp = run_editor(setinput(mp), mp->m_size, type, readonly);
9234963Sedward 		if (fp != NULL) {
9334963Sedward 			(void) fseek(otf, (long) 0, 2);
9434963Sedward 			size = ftell(otf);
9534963Sedward 			mp->m_block = blockof(size);
9634963Sedward 			mp->m_offset = offsetof(size);
9734963Sedward 			mp->m_size = fsize(fp);
9834963Sedward 			mp->m_lines = 0;
9934963Sedward 			mp->m_flag |= MODIFY;
10034963Sedward 			rewind(fp);
10134963Sedward 			while ((c = getc(fp)) != EOF) {
10234963Sedward 				if (c == '\n')
10334963Sedward 					mp->m_lines++;
10434963Sedward 				if (putc(c, otf) == EOF)
10534963Sedward 					break;
10634963Sedward 			}
10734963Sedward 			if (ferror(otf))
10834963Sedward 				perror("/tmp");
10934879Sedward 			(void) fclose(fp);
1101228Skas 		}
11134963Sedward 		(void) signal(SIGINT, sigint);
1121228Skas 	}
11334963Sedward 	return 0;
11434963Sedward }
11534963Sedward 
11634963Sedward /*
11734963Sedward  * Run an editor on the file at "fpp" of "size" bytes,
11834963Sedward  * and return a new file pointer.
11934963Sedward  * Signals must be handled by the caller.
120*37870Sbostic  * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI.
12134963Sedward  */
12234963Sedward FILE *
12334963Sedward run_editor(fp, size, type, readonly)
12434963Sedward 	register FILE *fp;
12534963Sedward 	off_t size;
12634963Sedward 	char type;
12734963Sedward {
12834963Sedward 	register FILE *nf = NULL;
12934963Sedward 	register int t;
13034963Sedward 	time_t modtime;
13134963Sedward 	char *edit;
13234963Sedward 	struct stat statb;
13334963Sedward 	extern char tempEdit[];
13434963Sedward 
13534963Sedward 	if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) {
13634963Sedward 		perror(tempEdit);
13734963Sedward 		goto out;
13834963Sedward 	}
13934963Sedward 	if ((nf = fdopen(t, "w")) == NULL) {
14034963Sedward 		perror(tempEdit);
14134963Sedward 		(void) unlink(tempEdit);
14234963Sedward 		goto out;
14334963Sedward 	}
14434963Sedward 	if (size >= 0)
14534963Sedward 		while (--size >= 0 && (t = getc(fp)) != EOF)
14634963Sedward 			(void) putc(t, nf);
14734963Sedward 	else
14834963Sedward 		while ((t = getc(fp)) != EOF)
14934963Sedward 			(void) putc(t, nf);
15034963Sedward 	(void) fflush(nf);
15134963Sedward 	if (fstat(fileno(nf), &statb) < 0)
15234963Sedward 		modtime = 0;
15334963Sedward 	else
15434963Sedward 		modtime = statb.st_mtime;
15534963Sedward 	if (ferror(nf) || fclose(nf) < 0) {
15634963Sedward 		perror(tempEdit);
15734963Sedward 		(void) unlink(tempEdit);
15834963Sedward 		nf = NULL;
15934963Sedward 		goto out;
16034963Sedward 	}
16134963Sedward 	nf = NULL;
16234963Sedward 	if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
163*37870Sbostic 		edit = type == 'e' ? _PATH_EX : _PATH_VI;
16434963Sedward 	if (run_command(edit, 0, -1, -1, tempEdit, NOSTR) < 0) {
16534963Sedward 		(void) unlink(tempEdit);
16634963Sedward 		goto out;
16734963Sedward 	}
1681228Skas 	/*
16934963Sedward 	 * If in read only mode or file unchanged, just remove the editor
17034963Sedward 	 * temporary and return.
1711228Skas 	 */
17234963Sedward 	if (readonly) {
17334963Sedward 		(void) unlink(tempEdit);
17434963Sedward 		goto out;
17534963Sedward 	}
17634963Sedward 	if (stat(tempEdit, &statb) < 0) {
17734963Sedward 		perror(tempEdit);
17834963Sedward 		goto out;
17934963Sedward 	}
18034963Sedward 	if (modtime == statb.st_mtime) {
18134963Sedward 		(void) unlink(tempEdit);
18234963Sedward 		goto out;
18334963Sedward 	}
18434963Sedward 	/*
18534963Sedward 	 * Now switch to new file.
18634963Sedward 	 */
18734963Sedward 	if ((nf = fopen(tempEdit, "a+")) == NULL) {
18834963Sedward 		perror(tempEdit);
18934963Sedward 		(void) unlink(tempEdit);
19034963Sedward 		goto out;
19134963Sedward 	}
19234963Sedward 	(void) unlink(tempEdit);
1931228Skas out:
19434963Sedward 	return nf;
1951228Skas }
196