reinstated code to announce headers in lex
[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
12static char *SccsId = "@(#)cmd2.c 1.1 %G%";
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;
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;
80hitit:
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
94save(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
156swrite(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
225char *
226snarf(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
264delete(msgvec)
265 int msgvec[];
266{
267 return(delm(msgvec));
268}
269
270/*
271 * Delete messages, then type the new dot.
272 */
273
274deltype(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
298delm(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
338undelete(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
359core()
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}