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