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