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