|
|
1.1 ! root 1: /* mf.c - mail filter subroutines */ ! 2: ! 3: #include "mf.h" ! 4: #include <ctype.h> ! 5: #include <stdio.h> ! 6: ! 7: static int compress(), isat(), parse_address(), phrase(), route_addr(), ! 8: local_part(), domain(), route(), my_lex(); ! 9: ! 10: /* */ ! 11: ! 12: static char * ! 13: getcpy(s) ! 14: register char *s; ! 15: { ! 16: register char *p; ! 17: ! 18: if (!s) { _cleanup(); abort(); for(;;) pause();} ! 19: if ((p = malloc ((unsigned) (strlen (s) + 2))) != NULL) ! 20: (void) strcpy (p, s); ! 21: return p; ! 22: } ! 23: ! 24: ! 25: static char * ! 26: add(s1, s2) ! 27: register char *s1, *s2; ! 28: { ! 29: register char *p; ! 30: ! 31: if (s2 == NULL) ! 32: return getcpy (s1); ! 33: ! 34: if ((p = malloc ((unsigned) (strlen (s1) + strlen (s2) + 2))) != NULL) ! 35: (void) sprintf (p, "%s%s", s2, s1); ! 36: free (s2); ! 37: return p; ! 38: } ! 39: ! 40: /* */ ! 41: ! 42: isfrom(string) ! 43: register char *string; ! 44: { ! 45: return (strncmp (string, "From ", 5) == 0 ! 46: || strncmp (string, ">From ", 6) == 0); ! 47: } ! 48: ! 49: ! 50: lequal(a, b) ! 51: register char *a, *b; ! 52: { ! 53: for (; *a; a++, b++) ! 54: if (*b == NULL) ! 55: return FALSE; ! 56: else { ! 57: char c1 = islower (*a) ? toupper (*a) : *a; ! 58: char c2 = islower (*b) ? toupper (*b) : *b; ! 59: if (c1 != c2) ! 60: return FALSE; ! 61: } ! 62: ! 63: return (*b == NULL); ! 64: } ! 65: ! 66: /* */ ! 67: ! 68: /* ! 69: * ! 70: * seekadrx() is tricky. We want to cover both UUCP-style and ARPA-style ! 71: * addresses, so for each list of addresses we see if we can find some ! 72: * character to give us a hint. ! 73: * ! 74: */ ! 75: ! 76: ! 77: #define CHKADR 0 /* undertermined address style */ ! 78: #define UNIXDR 1 /* UNIX-style address */ ! 79: #define ARPADR 2 /* ARPAnet-style address */ ! 80: ! 81: ! 82: static char *punctuators = ";<>.()[]"; ! 83: static char *vp = NULL; ! 84: static char *tp = NULL; ! 85: ! 86: static struct adrx adrxs1; ! 87: ! 88: /* */ ! 89: ! 90: struct adrx * ! 91: seekadrx(addrs) ! 92: register char *addrs; ! 93: { ! 94: static int state = CHKADR; ! 95: register char *cp; ! 96: register struct adrx *adrxp; ! 97: ! 98: if (state == CHKADR) ! 99: for (state = UNIXDR, cp = addrs; *cp; cp++) ! 100: if (index (punctuators, *cp)) { ! 101: state = ARPADR; ! 102: break; ! 103: } ! 104: ! 105: switch (state) { ! 106: case UNIXDR: ! 107: adrxp = uucpadrx (addrs); ! 108: break; ! 109: ! 110: case ARPADR: ! 111: default: ! 112: adrxp = getadrx (addrs); ! 113: break; ! 114: } ! 115: ! 116: if (adrxp == NULL) ! 117: state = CHKADR; ! 118: ! 119: return adrxp; ! 120: } ! 121: ! 122: /* */ ! 123: ! 124: /* ! 125: * ! 126: * uucpadrx() implements a partial UUCP-style address parser. It's based ! 127: * on the UUCP notion that addresses are separated by spaces or commas. ! 128: * ! 129: */ ! 130: ! 131: ! 132: struct adrx * ! 133: uucpadrx(addrs) ! 134: register char *addrs; ! 135: { ! 136: register char *cp, ! 137: *wp, ! 138: *xp, ! 139: *yp, ! 140: *zp; ! 141: register struct adrx *adrxp = &adrxs1; ! 142: ! 143: if (vp == NULL) { ! 144: vp = tp = getcpy (addrs); ! 145: compress (addrs, vp); ! 146: } ! 147: else ! 148: if (tp == NULL) { ! 149: free (vp); ! 150: vp = NULL; ! 151: return NULL; ! 152: } ! 153: ! 154: for (cp = tp; isspace (*cp); cp++) ! 155: continue; ! 156: if (*cp == NULL) { ! 157: free (vp); ! 158: vp = tp = NULL; ! 159: return NULL; ! 160: } ! 161: ! 162: /* */ ! 163: ! 164: if ((wp = index (cp, ',')) == NULL) ! 165: if ((wp = index (cp, ' ')) != NULL) { ! 166: xp = wp; ! 167: while (isspace (*xp)) ! 168: xp++; ! 169: if (*xp != NULL && isat (--xp)) { ! 170: yp = xp + 4; ! 171: while (isspace (*yp)) ! 172: yp++; ! 173: if (*yp != NULL) ! 174: if ((zp = index (yp, ' ')) != NULL) ! 175: *zp = NULL, tp = ++zp; ! 176: else ! 177: tp = NULL; ! 178: else ! 179: *wp = NULL, tp = ++wp; ! 180: } ! 181: else ! 182: *wp = NULL, tp = ++wp; ! 183: } ! 184: else ! 185: tp = NULL; ! 186: else ! 187: *wp = NULL, tp = ++wp; ! 188: ! 189: if (adrxp -> text) ! 190: free (adrxp -> text); ! 191: adrxp -> text = getcpy (cp); ! 192: adrxp -> mbox = cp; ! 193: adrxp -> host = adrxp -> path = NULL; ! 194: if ((wp = rindex (cp, '@')) != NULL) { ! 195: *wp++ = NULL; ! 196: adrxp -> host = *wp ? wp : NULL; ! 197: } ! 198: else ! 199: for (wp = cp + strlen (cp) - 4; wp >= cp; wp--) ! 200: if (isat (wp)) { ! 201: *wp++ = NULL; ! 202: adrxp -> host = wp + 3; ! 203: } ! 204: ! 205: adrxp -> pers = adrxp -> grp = adrxp -> note = adrxp -> err = NULL; ! 206: adrxp -> ingrp = 0; ! 207: ! 208: return adrxp; ! 209: } ! 210: ! 211: /* */ ! 212: ! 213: static int ! 214: compress(fp, tp) ! 215: register char *fp, *tp; ! 216: { ! 217: register char c, ! 218: *cp; ! 219: ! 220: for (c = ' ', cp = tp; (*tp = *fp++) != NULL;) ! 221: if (isspace (*tp)) { ! 222: if (c != ' ') ! 223: *tp++ = c = ' '; ! 224: } ! 225: else ! 226: c = *tp++; ! 227: ! 228: if (c == ' ' && cp < tp) ! 229: *--tp = NULL; ! 230: } ! 231: ! 232: ! 233: static int ! 234: isat(p) ! 235: register char *p; ! 236: { ! 237: return (strncmp (p, " AT ", 4) ! 238: && strncmp (p, " At ", 4) ! 239: && strncmp (p, " aT ", 4) ! 240: && strncmp (p, " at ", 4) ? FALSE : TRUE); ! 241: } ! 242: ! 243: /* */ ! 244: ! 245: /* ! 246: * ! 247: * getadrx() implements a partial 822-style address parser. The parser ! 248: * is neither complete nor correct. It does however recognize nearly all ! 249: * of the 822 address syntax. In addition it handles the majority of the ! 250: * 733 syntax as well. Most problems arise from trying to accomodate both. ! 251: * ! 252: * In terms of 822, the route-specification in ! 253: * ! 254: * "<" [route] local-part "@" domain ">" ! 255: * ! 256: * is parsed and returned unchanged. Multiple at-signs are compressed ! 257: * via source-routing. Recursive groups are not allowed as per the ! 258: * standard. ! 259: * ! 260: * In terms of 733, " at " is recognized as equivalent to "@". ! 261: * ! 262: * In terms of both the parser will not complain about missing hosts. ! 263: * ! 264: * ----- ! 265: * ! 266: * We should not allow addresses like ! 267: * ! 268: * Marshall T. Rose <MRose@UCI> ! 269: * ! 270: * but should insist on ! 271: * ! 272: * "Marshall T. Rose" <MRose@UCI> ! 273: * ! 274: * Unfortunately, a lot of mailers stupidly let people get away with this. ! 275: * ! 276: * ----- ! 277: * ! 278: * We should not allow addresses like ! 279: * ! 280: * <MRose@UCI> ! 281: * ! 282: * but should insist on ! 283: * ! 284: * MRose@UCI ! 285: * ! 286: * Unfortunately, a lot of mailers stupidly let people's UAs get away with ! 287: * this. ! 288: * ! 289: * ----- ! 290: * ! 291: * We should not allow addresses like ! 292: * ! 293: * @UCI:MRose@UCI-750a ! 294: * ! 295: * but should insist on ! 296: * ! 297: * Marshall Rose <@UCI:MRose@UCI-750a> ! 298: * ! 299: * Unfortunately, a lot of mailers stupidly do this. ! 300: * ! 301: */ ! 302: ! 303: /* */ ! 304: ! 305: #define QUOTE '\\' ! 306: ! 307: #define LX_END 0 ! 308: #define LX_ERR 1 ! 309: #define LX_ATOM 2 ! 310: #define LX_QSTR 3 ! 311: #define LX_DLIT 4 ! 312: #define LX_SEMI 5 ! 313: #define LX_COMA 6 ! 314: #define LX_LBRK 7 ! 315: #define LX_RBRK 8 ! 316: #define LX_COLN 9 ! 317: #define LX_DOT 10 ! 318: #define LX_AT 11 ! 319: ! 320: static struct { ! 321: char lx_chr; ! 322: int lx_val; ! 323: } special[] = { ! 324: ';', LX_SEMI, ! 325: ',', LX_COMA, ! 326: '<', LX_LBRK, ! 327: '>', LX_RBRK, ! 328: ':', LX_COLN, ! 329: '.', LX_DOT, ! 330: '@', LX_AT, ! 331: '(', LX_ERR, ! 332: ')', LX_ERR, ! 333: QUOTE, LX_ERR, ! 334: '"', LX_ERR, ! 335: '[', LX_ERR, ! 336: ']', LX_ERR, ! 337: NULL, NULL ! 338: }; ! 339: ! 340: /* */ ! 341: ! 342: static int glevel = 0; ! 343: static int ingrp = 0; ! 344: static int last_lex = LX_END; ! 345: ! 346: static char *dp = NULL; ! 347: static char *cp = NULL; ! 348: static char *ap = NULL; ! 349: static char *pers = NULL; ! 350: static char *mbox = NULL; ! 351: static char *host = NULL; ! 352: static char *path = NULL; ! 353: static char *grp = NULL; ! 354: static char *note = NULL; ! 355: static char err[BUFSIZ]; ! 356: static char adr[BUFSIZ]; ! 357: ! 358: static struct adrx adrxs2; ! 359: ! 360: /* */ ! 361: ! 362: struct adrx * ! 363: getadrx(addrs) ! 364: register char *addrs; ! 365: { ! 366: register char *bp; ! 367: register struct adrx *adrxp = &adrxs2; ! 368: ! 369: if (pers) ! 370: free (pers); ! 371: if (mbox) ! 372: free (mbox); ! 373: if (host) ! 374: free (host); ! 375: if (path) ! 376: free (path); ! 377: if (grp) ! 378: free (grp); ! 379: if (note) ! 380: free (note); ! 381: pers = mbox = host = path = grp = note = NULL; ! 382: err[0] = NULL; ! 383: ! 384: if (dp == NULL) { ! 385: dp = cp = getcpy (addrs ? addrs : ""); ! 386: glevel = 0; ! 387: } ! 388: else ! 389: if (cp == NULL) { ! 390: free (dp); ! 391: dp = NULL; ! 392: return NULL; ! 393: } ! 394: ! 395: switch (parse_address ()) { ! 396: case DONE: ! 397: free (dp); ! 398: dp = cp = NULL; ! 399: return NULL; ! 400: ! 401: case OK: ! 402: switch (last_lex) { ! 403: case LX_COMA: ! 404: case LX_END: ! 405: break; ! 406: ! 407: default: /* catch trailing comments */ ! 408: bp = cp; ! 409: (void) my_lex (adr); ! 410: cp = bp; ! 411: break; ! 412: } ! 413: break; ! 414: ! 415: default: ! 416: break; ! 417: } ! 418: ! 419: if (err[0]) ! 420: for (;;) { ! 421: switch (last_lex) { ! 422: case LX_COMA: ! 423: case LX_END: ! 424: break; ! 425: ! 426: default: ! 427: (void) my_lex (adr); ! 428: continue; ! 429: } ! 430: break; ! 431: } ! 432: while (isspace (*ap)) ! 433: ap++; ! 434: if (cp) ! 435: (void) sprintf (adr, "%.*s", cp - ap, ap); ! 436: else ! 437: (void) strcpy (adr, ap); ! 438: bp = adr + strlen (adr) - 1; ! 439: if (*bp == ',' || *bp == ';' || *bp == '\n') ! 440: *bp = NULL; ! 441: ! 442: /* */ ! 443: ! 444: adrxp -> text = adr; ! 445: adrxp -> pers = pers; ! 446: adrxp -> mbox = mbox; ! 447: adrxp -> host = host; ! 448: adrxp -> path = path; ! 449: adrxp -> grp = grp; ! 450: adrxp -> ingrp = ingrp; ! 451: adrxp -> note = note; ! 452: adrxp -> err = err[0] ? err : NULL; ! 453: ! 454: return adrxp; ! 455: } ! 456: ! 457: /* */ ! 458: ! 459: static int ! 460: parse_address() ! 461: { ! 462: char buffer[BUFSIZ]; ! 463: ! 464: again: ; ! 465: ap = cp; ! 466: switch (my_lex (buffer)) { ! 467: case LX_ATOM: ! 468: case LX_QSTR: ! 469: pers = getcpy (buffer); ! 470: break; ! 471: ! 472: case LX_SEMI: ! 473: if (glevel-- <= 0) { ! 474: (void) strcpy (err, "extraneous semi-colon"); ! 475: return NOTOK; ! 476: } ! 477: case LX_COMA: ! 478: if (note) { ! 479: free (note); ! 480: note = NULL; ! 481: } ! 482: goto again; ! 483: ! 484: case LX_END: ! 485: return DONE; ! 486: ! 487: case LX_LBRK: /* sigh (2) */ ! 488: goto get_addr; ! 489: ! 490: case LX_AT: /* sigh (3) */ ! 491: cp = ap; ! 492: if (route_addr (buffer) == NOTOK) ! 493: return NOTOK; ! 494: return OK; /* why be choosy? */ ! 495: ! 496: default: ! 497: (void) sprintf (err, "illegal address construct (%s)", buffer); ! 498: return NOTOK; ! 499: } ! 500: ! 501: /* */ ! 502: ! 503: switch (my_lex (buffer)) { ! 504: case LX_ATOM: ! 505: case LX_QSTR: ! 506: pers = add (buffer, add (" ", pers)); ! 507: more_phrase: ; /* sigh (1) */ ! 508: if (phrase (buffer) == NOTOK) ! 509: return NOTOK; ! 510: ! 511: switch (last_lex) { ! 512: case LX_LBRK: ! 513: get_addr: ; ! 514: if (route_addr (buffer) == NOTOK) ! 515: return NOTOK; ! 516: if (last_lex == LX_RBRK) ! 517: return OK; ! 518: (void) sprintf (err, "missing right-bracket (%s)", buffer); ! 519: return NOTOK; ! 520: ! 521: case LX_COLN: ! 522: get_group: ; ! 523: if (glevel++ > 0) { ! 524: (void) sprintf (err, "nested groups not allowed (%s)", ! 525: pers); ! 526: return NOTOK; ! 527: } ! 528: grp = add (": ", pers); ! 529: pers = NULL; ! 530: { ! 531: char *pp = cp; ! 532: ! 533: for (;;) ! 534: switch (my_lex (buffer)) { ! 535: case LX_SEMI: ! 536: case LX_END: /* tsk, tsk */ ! 537: glevel--; ! 538: return OK; ! 539: ! 540: case LX_COMA: ! 541: continue; ! 542: ! 543: default: ! 544: cp = pp; ! 545: return parse_address (); ! 546: } ! 547: } ! 548: ! 549: case LX_DOT: /* sigh (1) */ ! 550: pers = add (".", pers); ! 551: goto more_phrase; ! 552: ! 553: default: ! 554: (void) sprintf (err, ! 555: "no mailbox in address, only a phrase (%s%s)", ! 556: pers, buffer); ! 557: return NOTOK; ! 558: } ! 559: ! 560: /* */ ! 561: ! 562: case LX_LBRK: ! 563: goto get_addr; ! 564: ! 565: case LX_COLN: ! 566: goto get_group; ! 567: ! 568: case LX_DOT: ! 569: mbox = add (buffer, pers); ! 570: pers = NULL; ! 571: if (route_addr (buffer) == NOTOK) ! 572: return NOTOK; ! 573: goto check_end; ! 574: ! 575: case LX_AT: ! 576: ingrp = glevel; ! 577: mbox = pers; ! 578: pers = NULL; ! 579: if (domain (buffer) == NOTOK) ! 580: return NOTOK; ! 581: check_end: ; ! 582: switch (last_lex) { ! 583: case LX_SEMI: ! 584: if (glevel-- <= 0) { ! 585: (void) strcpy (err, "extraneous semi-colon"); ! 586: return NOTOK; ! 587: } ! 588: case LX_COMA: ! 589: case LX_END: ! 590: return OK; ! 591: ! 592: default: ! 593: (void) sprintf (err, "junk after local@domain (%s)", ! 594: buffer); ! 595: return NOTOK; ! 596: } ! 597: ! 598: case LX_SEMI: /* no host */ ! 599: case LX_COMA: ! 600: case LX_END: ! 601: ingrp = glevel; ! 602: if (last_lex == LX_SEMI && glevel-- <= 0) { ! 603: (void) strcpy (err, "extraneous semi-colon"); ! 604: return NOTOK; ! 605: } ! 606: mbox = pers; ! 607: pers = NULL; ! 608: return OK; ! 609: ! 610: default: ! 611: (void) sprintf (err, "missing mailbox (%s)", buffer); ! 612: return NOTOK; ! 613: } ! 614: } ! 615: ! 616: /* */ ! 617: ! 618: static int ! 619: phrase(buffer) ! 620: register char *buffer; ! 621: { ! 622: for (;;) ! 623: switch (my_lex (buffer)) { ! 624: case LX_ATOM: ! 625: case LX_QSTR: ! 626: pers = add (buffer, add (" ", pers)); ! 627: continue; ! 628: ! 629: default: ! 630: return OK; ! 631: } ! 632: } ! 633: ! 634: /* */ ! 635: ! 636: static int ! 637: route_addr(buffer) ! 638: register char *buffer; ! 639: { ! 640: register char *pp = cp; ! 641: ! 642: if (my_lex (buffer) == LX_AT) { ! 643: if (route (buffer) == NOTOK) ! 644: return NOTOK; ! 645: } ! 646: else ! 647: cp = pp; ! 648: ! 649: if (local_part (buffer) == NOTOK) ! 650: return NOTOK; ! 651: ! 652: switch (last_lex) { ! 653: case LX_AT: ! 654: return domain (buffer); ! 655: ! 656: case LX_RBRK: /* no host */ ! 657: case LX_COMA: ! 658: case LX_END: ! 659: return OK; ! 660: ! 661: default: ! 662: (void) sprintf (err, "no at-sign after local-part (%s)", buffer); ! 663: return NOTOK; ! 664: } ! 665: } ! 666: ! 667: /* */ ! 668: ! 669: static int ! 670: local_part(buffer) ! 671: register char *buffer; ! 672: { ! 673: ingrp = glevel; ! 674: ! 675: for (;;) { ! 676: switch (my_lex (buffer)) { ! 677: case LX_ATOM: ! 678: case LX_QSTR: ! 679: mbox = add (buffer, mbox); ! 680: break; ! 681: ! 682: default: ! 683: (void) sprintf (err, "no mailbox in local-part (%s)", buffer); ! 684: return NOTOK; ! 685: } ! 686: ! 687: switch (my_lex (buffer)) { ! 688: case LX_DOT: ! 689: mbox = add (buffer, mbox); ! 690: continue; ! 691: ! 692: default: ! 693: return OK; ! 694: } ! 695: } ! 696: } ! 697: ! 698: /* */ ! 699: ! 700: static int ! 701: domain(buffer) ! 702: register char *buffer; ! 703: { ! 704: for (;;) { ! 705: switch (my_lex (buffer)) { ! 706: case LX_ATOM: ! 707: case LX_DLIT: ! 708: host = add (buffer, host); ! 709: break; ! 710: ! 711: default: ! 712: (void) sprintf (err, ! 713: "no sub-domain in domain-part of address (%s)", ! 714: buffer); ! 715: return NOTOK; ! 716: } ! 717: ! 718: switch (my_lex (buffer)) { ! 719: case LX_DOT: ! 720: host = add (buffer, host); ! 721: continue; ! 722: ! 723: case LX_AT: /* sigh (0) */ ! 724: mbox = add (host, add ("%", mbox)); ! 725: free (host); ! 726: host = NULL; ! 727: continue; ! 728: ! 729: default: ! 730: return OK; ! 731: } ! 732: } ! 733: } ! 734: ! 735: /* */ ! 736: ! 737: static int ! 738: route(buffer) ! 739: register char *buffer; ! 740: { ! 741: path = getcpy ("@"); ! 742: ! 743: for (;;) { ! 744: switch (my_lex (buffer)) { ! 745: case LX_ATOM: ! 746: case LX_DLIT: ! 747: path = add (buffer, path); ! 748: break; ! 749: ! 750: default: ! 751: (void) sprintf (err, ! 752: "no sub-domain in domain-part of address (%s)", ! 753: buffer); ! 754: return NOTOK; ! 755: } ! 756: switch (my_lex (buffer)) { ! 757: case LX_COMA: ! 758: path = add (buffer, path); ! 759: for (;;) { ! 760: switch (my_lex (buffer)) { ! 761: case LX_COMA: ! 762: continue; ! 763: ! 764: case LX_AT: ! 765: path = add (buffer, path); ! 766: break; ! 767: ! 768: default: ! 769: (void) sprintf (err, ! 770: "no at-sign found for next domain in route (%s)", ! 771: buffer); ! 772: } ! 773: break; ! 774: } ! 775: continue; ! 776: ! 777: case LX_AT: /* XXX */ ! 778: case LX_DOT: ! 779: path = add (buffer, path); ! 780: continue; ! 781: ! 782: case LX_COLN: ! 783: path = add (buffer, path); ! 784: return OK; ! 785: ! 786: default: ! 787: (void) sprintf (err, ! 788: "no colon found to terminate route (%s)", buffer); ! 789: return NOTOK; ! 790: } ! 791: } ! 792: } ! 793: ! 794: /* */ ! 795: ! 796: static int ! 797: my_lex(buffer) ! 798: register char *buffer; ! 799: { ! 800: int i; ! 801: register char c, ! 802: *bp; ! 803: ! 804: bp = buffer; ! 805: *bp = NULL; ! 806: if (!cp) ! 807: return (last_lex = LX_END); ! 808: ! 809: c = *cp++; ! 810: while (isspace (c)) ! 811: c = *cp++; ! 812: if (c == NULL) { ! 813: cp = NULL; ! 814: return (last_lex = LX_END); ! 815: } ! 816: ! 817: if (c == '(') ! 818: for (*bp++ = c, i = 0;;) ! 819: switch (c = *cp++) { ! 820: case NULL: ! 821: cp = NULL; ! 822: return (last_lex = LX_ERR); ! 823: case QUOTE: ! 824: *bp++ = c; ! 825: if ((c = *cp++) == NULL) { ! 826: cp = NULL; ! 827: return (last_lex = LX_ERR); ! 828: } ! 829: *bp++ = c; ! 830: continue; ! 831: case '(': ! 832: i++; ! 833: default: ! 834: *bp++ = c; ! 835: continue; ! 836: case ')': ! 837: *bp++ = c; ! 838: if (--i < 0) { ! 839: *bp = NULL; ! 840: note = note ? add (buffer, add (" ", note)) ! 841: : getcpy (buffer); ! 842: return my_lex (buffer); ! 843: } ! 844: } ! 845: ! 846: /* */ ! 847: ! 848: if (c == '"') ! 849: for (*bp++ = c;;) ! 850: switch (c = *cp++) { ! 851: case NULL: ! 852: cp = NULL; ! 853: return (last_lex = LX_ERR); ! 854: case QUOTE: ! 855: *bp++ = c; ! 856: if ((c = *cp++) == NULL) { ! 857: cp = NULL; ! 858: return (last_lex = LX_ERR); ! 859: } ! 860: default: ! 861: *bp++ = c; ! 862: continue; ! 863: case '"': ! 864: *bp++ = c; ! 865: *bp = NULL; ! 866: return (last_lex = LX_QSTR); ! 867: } ! 868: ! 869: if (c == '[') ! 870: for (*bp++ = c;;) ! 871: switch (c = *cp++) { ! 872: case NULL: ! 873: cp = NULL; ! 874: return (last_lex = LX_ERR); ! 875: case QUOTE: ! 876: *bp++ = c; ! 877: if ((c = *cp++) == NULL) { ! 878: cp = NULL; ! 879: return (last_lex = LX_ERR); ! 880: } ! 881: default: ! 882: *bp++ = c; ! 883: continue; ! 884: case ']': ! 885: *bp++ = c; ! 886: *bp = NULL; ! 887: return (last_lex = LX_DLIT); ! 888: } ! 889: ! 890: /* */ ! 891: ! 892: *bp++ = c; ! 893: *bp = NULL; ! 894: for (i = 0; special[i].lx_chr != NULL; i++) ! 895: if (c == special[i].lx_chr) ! 896: return (last_lex = special[i].lx_val); ! 897: ! 898: if (iscntrl (c)) ! 899: return (last_lex = LX_ERR); ! 900: ! 901: for (;;) { ! 902: if ((c = *cp++) == NULL) ! 903: break; ! 904: for (i = 0; special[i].lx_chr != NULL; i++) ! 905: if (c == special[i].lx_chr) ! 906: goto got_atom; ! 907: if (iscntrl (c) || isspace (c)) ! 908: break; ! 909: *bp++ = c; ! 910: } ! 911: got_atom: ; ! 912: if (c == NULL) ! 913: cp = NULL; ! 914: else ! 915: cp--; ! 916: *bp = NULL; ! 917: last_lex = !lequal (buffer, "at") || cp == NULL || index (cp, '<') != NULL ! 918: ? LX_ATOM : LX_AT; ! 919: return last_lex; ! 920: } ! 921: ! 922: /* */ ! 923: ! 924: char * ! 925: legal_person(p) ! 926: register char *p; ! 927: { ! 928: int i; ! 929: register char *cp; ! 930: static char buffer[BUFSIZ]; ! 931: ! 932: if (*p == '"') ! 933: return p; ! 934: for (cp = p; *cp; cp++) ! 935: for (i = 0; special[i].lx_chr; i++) ! 936: if (*cp == special[i].lx_chr) { ! 937: (void) sprintf (buffer, "\"%s\"", p); ! 938: return buffer; ! 939: } ! 940: ! 941: return p; ! 942: } ! 943: ! 944: /* */ ! 945: ! 946: mfgets(in, bp) ! 947: register FILE *in; ! 948: register char **bp; ! 949: { ! 950: int i; ! 951: register char *cp, ! 952: *dp, ! 953: *ep; ! 954: static int len = 0; ! 955: static char *pp = NULL; ! 956: ! 957: if (pp == NULL) ! 958: if ((pp = malloc ((unsigned) (len = BUFSIZ))) == NULL) ! 959: return NOTOK; ! 960: ! 961: for (ep = (cp = pp) + len - 2;;) { ! 962: switch (i = getc (in)) { ! 963: case EOF: ! 964: eol: ; ! 965: if (cp != pp) { ! 966: *cp = NULL; ! 967: *bp = pp; ! 968: return OK; ! 969: } ! 970: eoh: ; ! 971: *bp = NULL; ! 972: free (pp); ! 973: pp = NULL; ! 974: return DONE; ! 975: ! 976: case NULL: ! 977: continue; ! 978: ! 979: case '\n': ! 980: if (cp == pp) /* end of headers, gobble it */ ! 981: goto eoh; ! 982: switch (i = getc (in)) { ! 983: default: /* end of line */ ! 984: case '\n': /* end of headers, save for next call */ ! 985: (void) ungetc (i, in); ! 986: goto eol; ! 987: ! 988: case ' ': /* continue headers */ ! 989: case '\t': ! 990: *cp++ = '\n'; ! 991: break; ! 992: } /* fall into default case */ ! 993: ! 994: default: ! 995: *cp++ = i; ! 996: break; ! 997: } ! 998: if (cp >= ep) ! 999: if ((dp = realloc (pp, (unsigned) (len += BUFSIZ))) == NULL) { ! 1000: free (pp); ! 1001: pp = NULL; ! 1002: return NOTOK; ! 1003: } ! 1004: else ! 1005: cp += dp - pp, ep = (pp = cp) + len - 2; ! 1006: } ! 1007: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.