|
|
1.1 root 1: #
2:
3: #include "rcv.h"
4: #include <ctype.h>
5:
6: /*
7: * Mail -- a mail program
8: *
9: * Message list handling.
10: */
11:
12: /*
13: * Convert the user string of message numbers and
14: * store the numbers into vector.
15: *
16: * Returns the count of messages picked up or -1 on error.
17: */
18:
19: getmsglist(buf, vector, flags)
20: char *buf;
21: int *vector;
22: {
23: register int *ip;
24: register struct message *mp;
25:
26: if (markall(buf, flags) < 0)
27: return(-1);
28: ip = vector;
29: for (mp = &message[0]; mp < &message[msgCount]; mp++)
30: if (mp->m_flag & MMARK)
31: *ip++ = mp - &message[0] + 1;
32: *ip = NULL;
33: return(ip - vector);
34: }
35:
36: /*
37: * Mark all messages that the user wanted from the command
38: * line in the message structure. Return 0 on success, -1
39: * on error.
40: */
41:
42: markall(buf, f)
43: char buf[];
44: {
45: register char **np;
46: register int i;
47: char *namelist[NMLSIZE], *bufp;
48: int tok, beg, mc, star, other, valdot;
49:
50: valdot = dot - &message[0] + 1;
51: for (i = 1; i <= msgCount; i++)
52: unmark(i);
53: bufp = buf;
54: mc = 0;
55: np = &namelist[0];
56: scaninit();
57: tok = scan(&bufp);
58: star = 0;
59: other = 0;
60: beg = 0;
61: while (tok != TEOL) {
62: switch (tok) {
63: case TNUMBER:
64: number:
65: if (star) {
66: printf("No numbers mixed with *\n");
67: return(-1);
68: }
69: mc++;
70: other++;
71: if (beg != 0) {
72: if (check(lexnumber, f))
73: return(-1);
74: for (i = beg; i <= lexnumber; i++)
75: mark(i);
76: beg = 0;
77: break;
78: }
79: beg = lexnumber;
80: if (check(beg, f))
81: return(-1);
82: tok = scan(&bufp);
83: regret(tok);
84: if (tok != TDASH) {
85: mark(beg);
86: beg = 0;
87: }
88: break;
89:
90: case TPLUS:
91: if (beg != 0) {
92: printf("Non-numeric second argument\n");
93: return(-1);
94: }
95: if (valdot < msgCount)
96: mark(valdot+1);
97: else {
98: printf("Referencing beyond EOF\n");
99: return(-1);
100: }
101: break;
102:
103: case TDASH:
104: if (beg == 0) {
105: if (valdot > 1)
106: mark(valdot-1);
107: else {
108: printf("Referencing before 1\n");
109: return(-1);
110: }
111: }
112: break;
113:
114: case TSTRING:
115: if (beg != 0) {
116: printf("Non-numeric second argument\n");
117: return(-1);
118: }
119: other++;
120: *np++ = savestr(lexstring);
121: break;
122:
123: case TDOLLAR:
124: case TUP:
125: case TDOT:
126: lexnumber = metamess(lexstring[0], f);
127: if (lexnumber == -1)
128: return(-1);
129: goto number;
130:
131: case TSTAR:
132: if (other) {
133: printf("Can't mix \"*\" with anything\n");
134: return(-1);
135: }
136: star++;
137: break;
138: }
139: tok = scan(&bufp);
140: }
141: *np = NOSTR;
142: mc = 0;
143: if (star) {
144: for (i = 0; i < msgCount; i++)
145: if ((message[i].m_flag & MDELETED) == f) {
146: mark(i+1);
147: mc++;
148: }
149: if (mc == 0) {
150: printf("No applicable messages.\n");
151: return(-1);
152: }
153: return(0);
154: }
155:
156: /*
157: * If no numbers were given, mark all of the messages,
158: * so that we can unmark any whose sender was not selected
159: * if any user names were given.
160: */
161:
162: if (np > namelist && mc == 0)
163: for (i = 1; i <= msgCount; i++)
164: if ((message[i-1].m_flag & (MSAVED|MDELETED)) == f)
165: mark(i);
166:
167: /*
168: * If any names were given, go through and eliminate any
169: * messages whose senders were not requested.
170: */
171:
172: if (np > namelist) {
173: for (i = 1; i <= msgCount; i++) {
174: for (mc = 0, np = &namelist[0]; *np != NOSTR; np++)
175: if (sender(*np, i)) {
176: mc++;
177: break;
178: }
179: if (mc == 0)
180: unmark(i);
181: }
182:
183: /*
184: * Make sure we got some decent messages.
185: */
186:
187: mc = 0;
188: for (i = 1; i <= msgCount; i++)
189: if (message[i-1].m_flag & MMARK) {
190: mc++;
191: break;
192: }
193: if (mc == 0) {
194: printf("No applicable messages from {%s",
195: namelist[0]);
196: for (np = &namelist[1]; *np != NOSTR; np++)
197: printf(", %s", *np);
198: printf("}\n");
199: return(-1);
200: }
201: }
202: return(0);
203: }
204:
205: /*
206: * Check the passed message number for legality and proper flags.
207: */
208:
209: check(mesg, f)
210: {
211: register struct message *mp;
212:
213: if (mesg < 1 || mesg > msgCount) {
214: printf("%d: Invalid message number\n", mesg);
215: return(-1);
216: }
217: mp = &message[mesg-1];
218: if ((mp->m_flag & MDELETED) != f) {
219: printf("%d: Inappropriate message\n", mesg);
220: return(-1);
221: }
222: return(0);
223: }
224:
225: /*
226: * Scan out the list of string arguments, shell style
227: * for a RAWLIST.
228: */
229:
230: getrawlist(line, argv)
231: char line[];
232: char **argv;
233: {
234: register char **ap, *cp, *cp2;
235: char linebuf[BUFSIZ], quotec;
236:
237: ap = argv;
238: cp = line;
239: while (*cp != '\0') {
240: while (any(*cp, " \t"))
241: cp++;
242: cp2 = linebuf;
243: quotec = 0;
244: if (any(*cp, "'\""))
245: quotec = *cp++;
246: if (quotec == 0)
247: while (*cp != '\0' && !any(*cp, " \t"))
248: *cp2++ = *cp++;
249: else {
250: while (*cp != '\0' && *cp != quotec)
251: *cp2++ = *cp++;
252: if (*cp != '\0')
253: cp++;
254: }
255: *cp2 = '\0';
256: if (cp2 == linebuf)
257: break;
258: *ap++ = savestr(linebuf);
259: }
260: *ap = NOSTR;
261: return(ap-argv);
262: }
263:
264: /*
265: * scan out a single lexical item and return its token number,
266: * updating the string pointer passed **p. Also, store the value
267: * of the number or string scanned in lexnumber or lexstring as
268: * appropriate. In any event, store the scanned `thing' in lexstring.
269: */
270:
271: struct lex {
272: char l_char;
273: char l_token;
274: } singles[] = {
275: '$', TDOLLAR,
276: '.', TDOT,
277: '^', TUP,
278: '*', TSTAR,
279: '-', TDASH,
280: '+', TPLUS,
281: '(', TOPEN,
282: ')', TCLOSE,
283: 0, 0
284: };
285:
286: scan(sp)
287: char **sp;
288: {
289: register char *cp, *cp2;
290: register int c;
291: register struct lex *lp;
292: int quotec;
293:
294: if (regretp >= 0) {
295: copy(stringstack[regretp], lexstring);
296: lexnumber = numberstack[regretp];
297: return(regretstack[regretp--]);
298: }
299: cp = *sp;
300: cp2 = lexstring;
301: c = *cp++;
302:
303: /*
304: * strip away leading white space.
305: */
306:
307: while (any(c, " \t"))
308: c = *cp++;
309:
310: /*
311: * If no characters remain, we are at end of line,
312: * so report that.
313: */
314:
315: if (c == '\0') {
316: *sp = --cp;
317: return(TEOL);
318: }
319:
320: /*
321: * If the leading character is a digit, scan
322: * the number and convert it on the fly.
323: * Return TNUMBER when done.
324: */
325:
326: if (isdigit(c)) {
327: lexnumber = 0;
328: while (isdigit(c)) {
329: lexnumber = lexnumber*10 + c - '0';
330: *cp2++ = c;
331: c = *cp++;
332: }
333: *cp2 = '\0';
334: *sp = --cp;
335: return(TNUMBER);
336: }
337:
338: /*
339: * Check for single character tokens; return such
340: * if found.
341: */
342:
343: for (lp = &singles[0]; lp->l_char != 0; lp++)
344: if (c == lp->l_char) {
345: lexstring[0] = c;
346: lexstring[1] = '\0';
347: *sp = cp;
348: return(lp->l_token);
349: }
350:
351: /*
352: * We've got a string! Copy all the characters
353: * of the string into lexstring, until we see
354: * a null, space, or tab.
355: * If the lead character is a " or ', save it
356: * and scan until you get another.
357: */
358:
359: quotec = 0;
360: if (any(c, "'\"")) {
361: quotec = c;
362: c = *cp++;
363: }
364: while (c != '\0') {
365: if (c == quotec)
366: break;
367: if (quotec == 0 && any(c, " \t"))
368: break;
369: if (cp2 - lexstring < STRINGLEN-1)
370: *cp2++ = c;
371: c = *cp++;
372: }
373: if (quotec && c == 0)
374: fprintf(stderr, "Missing %c\n", quotec);
375: *sp = --cp;
376: *cp2 = '\0';
377: return(TSTRING);
378: }
379:
380: /*
381: * Unscan the named token by pushing it onto the regret stack.
382: */
383:
384: regret(token)
385: {
386: if (++regretp >= REGDEP)
387: panic("Too many regrets");
388: regretstack[regretp] = token;
389: lexstring[STRINGLEN-1] = '\0';
390: stringstack[regretp] = savestr(lexstring);
391: numberstack[regretp] = lexnumber;
392: }
393:
394: /*
395: * Reset all the scanner global variables.
396: */
397:
398: scaninit()
399: {
400: regretp = -1;
401: }
402:
403: /*
404: * Find the first message whose flags & m == f and return
405: * its message number.
406: */
407:
408: first(f, m)
409: {
410: register int mesg;
411: register struct message *mp;
412:
413: mesg = dot - &message[0] + 1;
414: f &= MDELETED;
415: m &= MDELETED;
416: for (mp = dot; mp < &message[msgCount]; mp++) {
417: if ((mp->m_flag & m) == f)
418: return(mesg);
419: mesg++;
420: }
421: mesg = dot - &message[0];
422: for (mp = dot-1; mp >= &message[0]; mp--) {
423: if ((mp->m_flag & m) == f)
424: return(mesg);
425: mesg--;
426: }
427: return(NULL);
428: }
429:
430: /*
431: * See if the passed name sent the passed message number. Return true
432: * if so.
433: */
434:
435: sender(str, mesg)
436: char *str;
437: {
438: register struct message *mp;
439: register char *cp;
440:
441: mp = &message[mesg-1];
442: cp = nameof(mp);
443: return(icequal(cp, str));
444: }
445:
446: /*
447: * Mark the named message by setting its mark bit.
448: */
449:
450: mark(mesg)
451: {
452: register int i;
453:
454: i = mesg;
455: if (i < 1 || i > msgCount)
456: panic("Bad message number to mark");
457: message[i-1].m_flag |= MMARK;
458: }
459:
460: /*
461: * Unmark the named message.
462: */
463:
464: unmark(mesg)
465: {
466: register int i;
467:
468: i = mesg;
469: if (i < 1 || i > msgCount)
470: panic("Bad message number to unmark");
471: message[i-1].m_flag &= ~MMARK;
472: }
473:
474: /*
475: * Return the message number corresponding to the passed meta character.
476: */
477:
478: metamess(meta, f)
479: {
480: register int c, m;
481: register struct message *mp;
482:
483: c = meta;
484: switch (c) {
485: case '^':
486: /*
487: * First 'good' message left.
488: */
489: for (mp = &message[0]; mp < &message[msgCount]; mp++)
490: if ((mp->m_flag & MDELETED) == f)
491: return(mp - &message[0] + 1);
492: printf("No applicable messages\n");
493: return(-1);
494:
495: case '$':
496: /*
497: * Last 'good message left.
498: */
499: for (mp = &message[msgCount-1]; mp >= &message[0]; mp--)
500: if ((mp->m_flag & MDELETED) == f)
501: return(mp - &message[0] + 1);
502: printf("No applicable messages\n");
503: return(-1);
504:
505: case '.':
506: /*
507: * Current message.
508: */
509: m = dot - &message[0] + 1;
510: if ((dot->m_flag & MDELETED) != f) {
511: printf("%d: Inappropriate message\n", m);
512: return(-1);
513: }
514: return(m);
515:
516: default:
517: printf("Unknown metachar (%c)\n", c);
518: return(-1);
519: }
520: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.