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