xref: /original-bsd/usr.bin/mail/edit.c (revision 6c57d260)
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.3 04/01/81";
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 = sigset(SIGINT, SIG_IGN);
71 	sigquit = sigset(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 		 * If we are in read only mode, make the
127 		 * temporary message file readonly as well.
128 		 */
129 
130 		if (readonly)
131 			chmod(edname, 0400);
132 
133 		/*
134 		 * Fork/execl the editor on the edit file.
135 		 */
136 
137 		if (stat(edname, &statb) < 0)
138 			modtime = 0;
139 		modtime = statb.st_mtime;
140 		pid = vfork();
141 		if (pid == -1) {
142 			perror("fork");
143 			remove(edname);
144 			goto out;
145 		}
146 		if (pid == 0) {
147 			if (sigint != SIG_IGN)
148 				sigsys(SIGINT, SIG_DFL);
149 			if (sigquit != SIG_IGN)
150 				sigsys(SIGQUIT, SIG_DFL);
151 			execl(ed, ed, edname, 0);
152 			perror(ed);
153 			_exit(1);
154 		}
155 		while (wait(&mesg) != pid)
156 			;
157 
158 		/*
159 		 * If in read only mode, just remove the editor
160 		 * temporary and return.
161 		 */
162 
163 		if (readonly) {
164 			remove(edname);
165 			continue;
166 		}
167 
168 		/*
169 		 * Now copy the message to the end of the
170 		 * temp file.
171 		 */
172 
173 		if (stat(edname, &statb) < 0) {
174 			perror(edname);
175 			goto out;
176 		}
177 		if (modtime == statb.st_mtime) {
178 			remove(edname);
179 			goto out;
180 		}
181 		if ((ibuf = fopen(edname, "r")) == NULL) {
182 			perror(edname);
183 			remove(edname);
184 			goto out;
185 		}
186 		remove(edname);
187 		fseek(otf, (long) 0, 2);
188 		size = fsize(otf);
189 		mp->m_block = blockof(size);
190 		mp->m_offset = offsetof(size);
191 		ms = 0;
192 		lines = 0;
193 		while ((c = getc(ibuf)) != EOF) {
194 			if (c == '\n')
195 				lines++;
196 			putc(c, otf);
197 			if (ferror(otf))
198 				break;
199 			ms++;
200 		}
201 		mp->m_size = ms;
202 		mp->m_lines = lines;
203 		if (ferror(otf))
204 			perror("/tmp");
205 		fclose(ibuf);
206 	}
207 
208 	/*
209 	 * Restore signals and return.
210 	 */
211 
212 out:
213 	sigset(SIGINT, sigint);
214 	sigset(SIGQUIT, sigquit);
215 }
216