xref: /original-bsd/usr.bin/mail/edit.c (revision ba72ef4c)
1 #
2 
3 #include "rcv.h"
4 #include <stdio.h>
5 #include <sys/stat.h>
6 
7 /*
8  * Mail -- a mail program
9  *
10  * Perform message editing functions.
11  */
12 
13 static char *SccsId = "@(#)edit.c	1.1 10/08/80";
14 
15 /*
16  * Edit a message list.
17  */
18 
19 editor(msgvec)
20 	int *msgvec;
21 {
22 	char *edname;
23 
24 	if ((edname = value("EDITOR")) == NOSTR)
25 		edname = EDITOR;
26 	return(edit1(msgvec, edname));
27 }
28 
29 /*
30  * Invoke the visual editor on a message list.
31  */
32 
33 visual(msgvec)
34 	int *msgvec;
35 {
36 	char *edname;
37 
38 	if ((edname = value("VISUAL")) == NOSTR)
39 		edname = VISUAL;
40 	return(edit1(msgvec, edname));
41 }
42 
43 /*
44  * Edit a message by writing the message into a funnily-named file
45  * (which should not exist) and forking an editor on it.
46  * We get the editor from the stuff above.
47  */
48 
49 edit1(msgvec, ed)
50 	int *msgvec;
51 	char *ed;
52 {
53 	register char *cp, *cp2;
54 	register int c;
55 	int *ip, pid, mesg, lines;
56 	unsigned int ms;
57 	int (*sigint)(), (*sigquit)();
58 	FILE *ibuf, *obuf;
59 	char edname[15], nbuf[10];
60 	struct message *mp;
61 	extern char tempEdit[];
62 	off_t fsize(), size;
63 	struct stat statb;
64 	long modtime;
65 
66 	/*
67 	 * Set signals; locate editor.
68 	 */
69 
70 	sigint = signal(SIGINT, SIG_IGN);
71 	sigquit = signal(SIGQUIT, SIG_IGN);
72 
73 	/*
74 	 * Deal with each message to be edited . . .
75 	 */
76 
77 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
78 		mesg = *ip;
79 		mp = &message[mesg-1];
80 		mp->m_flag |= MODIFY;
81 
82 		/*
83 		 * Make up a name for the edit file of the
84 		 * form "Message%d" and make sure it doesn't
85 		 * already exist.
86 		 */
87 
88 		cp = &nbuf[10];
89 		*--cp = 0;
90 		while (mesg) {
91 			*--cp = mesg % 10 + '0';
92 			mesg /= 10;
93 		}
94 		cp2 = copy("Message", edname);
95 		while (*cp2++ = *cp++)
96 			;
97 		if (!access(edname, 2)) {
98 			printf("%s: file exists\n", edname);
99 			goto out;
100 		}
101 
102 		/*
103 		 * Copy the message into the edit file.
104 		 */
105 
106 		close(creat(edname, 0600));
107 		if ((obuf = fopen(edname, "w")) == NULL) {
108 			perror(edname);
109 			goto out;
110 		}
111 		if (send(mp, obuf) < 0) {
112 			perror(edname);
113 			fclose(obuf);
114 			remove(edname);
115 			goto out;
116 		}
117 		fflush(obuf);
118 		if (ferror(obuf)) {
119 			remove(edname);
120 			fclose(obuf);
121 			goto out;
122 		}
123 		fclose(obuf);
124 
125 		/*
126 		 * Fork/execl the editor on the edit file.
127 		 */
128 
129 		if (stat(edname, &statb) < 0)
130 			modtime = 0;
131 		modtime = statb.st_mtime;
132 		pid = vfork();
133 		if (pid == -1) {
134 			perror("fork");
135 			remove(edname);
136 			goto out;
137 		}
138 		if (pid == 0) {
139 			if (sigint != SIG_IGN)
140 				signal(SIGINT, SIG_DFL);
141 			if (sigquit != SIG_IGN)
142 				signal(SIGQUIT, SIG_DFL);
143 			execl(ed, ed, edname, 0);
144 			perror(ed);
145 			_exit(1);
146 		}
147 		while (wait(&mesg) != pid)
148 			;
149 
150 		/*
151 		 * Now copy the message to the end of the
152 		 * temp file.
153 		 */
154 
155 		if (stat(edname, &statb) < 0) {
156 			perror(edname);
157 			goto out;
158 		}
159 		if (modtime == statb.st_mtime) {
160 			remove(edname);
161 			goto out;
162 		}
163 		if ((ibuf = fopen(edname, "r")) == NULL) {
164 			perror(edname);
165 			remove(edname);
166 			goto out;
167 		}
168 		remove(edname);
169 		fseek(otf, (long) 0, 2);
170 		size = fsize(otf);
171 		mp->m_block = blockof(size);
172 		mp->m_offset = offsetof(size);
173 		ms = 0;
174 		lines = 0;
175 		while ((c = getc(ibuf)) != EOF) {
176 			if (c == '\n')
177 				lines++;
178 			putc(c, otf);
179 			if (ferror(otf))
180 				break;
181 			ms++;
182 		}
183 		mp->m_size = ms;
184 		mp->m_lines = lines;
185 		if (ferror(otf))
186 			perror("/tmp");
187 		fclose(ibuf);
188 	}
189 
190 	/*
191 	 * Restore signals and return.
192 	 */
193 
194 out:
195 	signal(SIGINT, sigint);
196 	signal(SIGQUIT, sigquit);
197 }
198