|
|
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.