xref: /original-bsd/usr.bin/mail/cmd2.c (revision ba72ef4c)
1 #
2 
3 #include "rcv.h"
4 #include <sys/stat.h>
5 
6 /*
7  * Mail -- a mail program
8  *
9  * More user commands.
10  */
11 
12 static char *SccsId = "@(#)cmd2.c	1.1 10/08/80";
13 
14 /*
15  * If any arguments were given, go to the next applicable argument
16  * following dot, otherwise, go to the next applicable message.
17  * If given as first command with no arguments, print first message.
18  */
19 
20 next(msgvec)
21 	int *msgvec;
22 {
23 	register struct message *mp;
24 	register int *ip, *ip2;
25 	int list[2], mdot;
26 
27 	if (*msgvec != NULL) {
28 
29 		/*
30 		 * If some messages were supplied, find the
31 		 * first applicable one following dot using
32 		 * wrap around.
33 		 */
34 
35 		mdot = dot - &message[0] + 1;
36 		for (ip = msgvec; *ip != NULL; ip++)
37 			if (*ip > mdot)
38 				break;
39 		if (*ip == NULL)
40 			ip = msgvec;
41 		ip2 = ip;
42 		do {
43 			if (*ip2 != NULL)
44 				ip2++;
45 			if (*ip2 == NULL)
46 				ip2 = msgvec;
47 			mp = &message[*ip2 - 1];
48 			if ((mp->m_flag & MDELETED) == 0) {
49 				dot = mp;
50 				goto hitit;
51 			}
52 		} while (ip2 != ip);
53 		printf("No messages applicable\n");
54 		return(1);
55 	}
56 
57 	/*
58 	 * If this is the first command, select message 1.
59 	 * Note that this must exist for us to get here at all.
60 	 */
61 
62 	if (!sawcom) {
63 		dot = &message[0];
64 		goto hitit;
65 	}
66 
67 	/*
68 	 * Just find the next good message after dot, no
69 	 * wraparound.
70 	 */
71 
72 	for (mp = dot+1; mp < &message[msgCount]; mp++)
73 		if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
74 			break;
75 	if (mp >= &message[msgCount]) {
76 		printf("At EOF\n");
77 		return(0);
78 	}
79 	dot = mp;
80 hitit:
81 	/*
82 	 * Print dot.
83 	 */
84 
85 	list[0] = dot - &message[0] + 1;
86 	list[1] = NULL;
87 	return(type(list));
88 }
89 
90 /*
91  * Save the indicated messages at the end of the passed file name.
92  */
93 
94 save(str)
95 	char str[];
96 {
97 	register int *ip, mesg;
98 	register struct message *mp;
99 	char *file, *disp;
100 	int f, *msgvec, lc, cc, t;
101 	FILE *obuf;
102 	struct stat statb;
103 
104 	msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
105 	if ((file = snarf(str, &f)) == NOSTR)
106 		return(1);
107 	if (!f) {
108 		*msgvec = first(0, MMNORM);
109 		if (*msgvec == NULL) {
110 			printf("No messages to save.\n");
111 			return(1);
112 		}
113 		msgvec[1] = NULL;
114 	}
115 	if (f && getmsglist(str, msgvec, 0) < 0)
116 		return(1);
117 	if ((file = expand(file)) == NOSTR)
118 		return(1);
119 	printf("\"%s\" ", file);
120 	flush();
121 	if (stat(file, &statb) >= 0)
122 		disp = "[Appended]";
123 	else
124 		disp = "[New file]";
125 	if ((obuf = fopen(file, "a")) == NULL) {
126 		perror(NOSTR);
127 		return(1);
128 	}
129 	cc = lc = 0;
130 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
131 		mesg = *ip;
132 		touch(mesg);
133 		mp = &message[mesg-1];
134 		if ((t = send(mp, obuf)) < 0) {
135 			perror(file);
136 			fclose(obuf);
137 			return(1);
138 		}
139 		lc += t;
140 		cc += msize(mp);
141 		mp->m_flag |= MSAVED;
142 	}
143 	fflush(obuf);
144 	if (ferror(obuf))
145 		perror(file);
146 	fclose(obuf);
147 	printf("%s %d/%d\n", disp, lc, cc);
148 	return(0);
149 }
150 
151 /*
152  * Write the indicated messages at the end of the passed
153  * file name, minus header and trailing blank line.
154  */
155 
156 swrite(str)
157 	char str[];
158 {
159 	register int *ip, mesg;
160 	register struct message *mp;
161 	register char *file, *disp;
162 	char linebuf[BUFSIZ];
163 	int f, *msgvec, lc, cc, t;
164 	FILE *obuf, *mesf;
165 	struct stat statb;
166 
167 	msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
168 	if ((file = snarf(str, &f)) == NOSTR)
169 		return(1);
170 	if ((file = expand(file)) == NOSTR)
171 		return(1);
172 	if (!f) {
173 		*msgvec = first(0, MMNORM);
174 		if (*msgvec == NULL) {
175 			printf("No messages to write.\n");
176 			return(1);
177 		}
178 		msgvec[1] = NULL;
179 	}
180 	if (f && getmsglist(str, msgvec, 0) < 0)
181 		return(1);
182 	printf("\"%s\" ", file);
183 	flush();
184 	if (stat(file, &statb) >= 0)
185 		disp = "[Appended]";
186 	else
187 		disp = "[New file]";
188 	if ((obuf = fopen(file, "a")) == NULL) {
189 		perror(NOSTR);
190 		return(1);
191 	}
192 	cc = lc = 0;
193 	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
194 		mesg = *ip;
195 		touch(mesg);
196 		mp = &message[mesg-1];
197 		mesf = setinput(mp);
198 		t = mp->m_lines - 2;
199 		readline(mesf, linebuf);
200 		while (t-- > 0) {
201 			fgets(linebuf, BUFSIZ, mesf);
202 			fputs(linebuf, obuf);
203 			cc += strlen(linebuf);
204 		}
205 		lc += mp->m_lines - 2;
206 		mp->m_flag |= MSAVED;
207 	}
208 	fflush(obuf);
209 	if (ferror(obuf))
210 		perror(file);
211 	fclose(obuf);
212 	printf("%s %d/%d\n", disp, lc, cc);
213 	return(0);
214 }
215 
216 /*
217  * Snarf the file from the end of the command line and
218  * return a pointer to it.  If there is no file attached,
219  * just return NOSTR.  Put a null in front of the file
220  * name so that the message list processing won't see it,
221  * unless the file name is the only thing on the line, in
222  * which case, return 0 in the reference flag variable.
223  */
224 
225 char *
226 snarf(linebuf, flag)
227 	char linebuf[];
228 	int *flag;
229 {
230 	register char *cp;
231 
232 	*flag = 1;
233 	cp = strlen(linebuf) + linebuf - 1;
234 
235 	/*
236 	 * Strip away trailing blanks.
237 	 */
238 
239 	while (*cp == ' ' && cp > linebuf)
240 		cp--;
241 	*++cp = 0;
242 
243 	/*
244 	 * Now search for the beginning of the file name.
245 	 */
246 
247 	while (cp > linebuf && !any(*cp, "\t "))
248 		cp--;
249 	if (*cp == '\0') {
250 		printf("No file specified.\n");
251 		return(NOSTR);
252 	}
253 	if (any(*cp, " \t"))
254 		*cp++ = 0;
255 	else
256 		*flag = 0;
257 	return(cp);
258 }
259 
260 /*
261  * Delete messages.
262  */
263 
264 delete(msgvec)
265 	int msgvec[];
266 {
267 	return(delm(msgvec));
268 }
269 
270 /*
271  * Delete messages, then type the new dot.
272  */
273 
274 deltype(msgvec)
275 	int msgvec[];
276 {
277 	int list[2];
278 
279 	if (delm(msgvec) >= 0) {
280 		list[0] = dot - &message[0];
281 		list[0]++;
282 		touch(list[0]);
283 		list[1] = NULL;
284 		return(type(list));
285 	}
286 	else {
287 		printf("No more messages\n");
288 		return(0);
289 	}
290 }
291 
292 /*
293  * Delete the indicated messages.
294  * Set dot to some nice place afterwards.
295  * Internal interface.
296  */
297 
298 delm(msgvec)
299 	int *msgvec;
300 {
301 	register struct message *mp;
302 	register *ip, mesg;
303 	int last;
304 
305 	last = NULL;
306 	for (ip = msgvec; *ip != NULL; ip++) {
307 		mesg = *ip;
308 		touch(mesg);
309 		mp = &message[mesg-1];
310 		mp->m_flag |= MDELETED;
311 		mp->m_flag &= ~(MPRESERVE|MSAVED);
312 		last = mesg;
313 	}
314 	if (last != NULL) {
315 		dot = &message[last-1];
316 		last = first(0, MDELETED);
317 		if (last != NULL) {
318 			dot = &message[last-1];
319 			return(0);
320 		}
321 		else {
322 			dot = &message[0];
323 			return(-1);
324 		}
325 	}
326 
327 	/*
328 	 * Following can't happen -- it keeps lint happy
329 	 */
330 
331 	return(-1);
332 }
333 
334 /*
335  * Undelete the indicated messages.
336  */
337 
338 undelete(msgvec)
339 	int *msgvec;
340 {
341 	register struct message *mp;
342 	register *ip, mesg;
343 
344 	for (ip = msgvec; ip-msgvec < msgCount; ip++) {
345 		mesg = *ip;
346 		if (mesg == 0)
347 			return;
348 		touch(mesg);
349 		mp = &message[mesg-1];
350 		dot = mp;
351 		mp->m_flag &= ~MDELETED;
352 	}
353 }
354 
355 /*
356  * Interactively dump core on "core"
357  */
358 
359 core()
360 {
361 	register int pid;
362 	int status;
363 
364 	if ((pid = vfork()) == -1) {
365 		perror("fork");
366 		return(1);
367 	}
368 	if (pid == 0) {
369 		abort();
370 		_exit(1);
371 	}
372 	printf("Okie dokie");
373 	fflush(stdout);
374 	while (wait(&status) != pid)
375 		;
376 	if (status & 0200)
377 		printf(" -- Core dumped\n");
378 	else
379 		printf("\n");
380 }
381