xref: /original-bsd/usr.bin/mail/edit.c (revision 5998a314)
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	2.4 10/21/82";
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 	long 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) < 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 			sigchild();
148 			if (sigint != SIG_IGN)
149 				sigsys(SIGINT, SIG_DFL);
150 			if (sigquit != SIG_IGN)
151 				sigsys(SIGQUIT, SIG_DFL);
152 			execl(ed, ed, edname, 0);
153 			perror(ed);
154 			_exit(1);
155 		}
156 		while (wait(&mesg) != pid)
157 			;
158 
159 		/*
160 		 * If in read only mode, just remove the editor
161 		 * temporary and return.
162 		 */
163 
164 		if (readonly) {
165 			remove(edname);
166 			continue;
167 		}
168 
169 		/*
170 		 * Now copy the message to the end of the
171 		 * temp file.
172 		 */
173 
174 		if (stat(edname, &statb) < 0) {
175 			perror(edname);
176 			goto out;
177 		}
178 		if (modtime == statb.st_mtime) {
179 			remove(edname);
180 			goto out;
181 		}
182 		if ((ibuf = fopen(edname, "r")) == NULL) {
183 			perror(edname);
184 			remove(edname);
185 			goto out;
186 		}
187 		remove(edname);
188 		fseek(otf, (long) 0, 2);
189 		size = fsize(otf);
190 		mp->m_block = blockof(size);
191 		mp->m_offset = offsetof(size);
192 		ms = 0L;
193 		lines = 0;
194 		while ((c = getc(ibuf)) != EOF) {
195 			if (c == '\n')
196 				lines++;
197 			putc(c, otf);
198 			if (ferror(otf))
199 				break;
200 			ms++;
201 		}
202 		mp->m_size = ms;
203 		mp->m_lines = lines;
204 		if (ferror(otf))
205 			perror("/tmp");
206 		fclose(ibuf);
207 	}
208 
209 	/*
210 	 * Restore signals and return.
211 	 */
212 
213 out:
214 	sigset(SIGINT, sigint);
215 	sigset(SIGQUIT, sigquit);
216 }
217