|
|
1.1 ! root 1: /* ! 2: * print mail ! 3: */ ! 4: #include <stdio.h> ! 5: #include <setjmp.h> ! 6: #include <ctype.h> ! 7: #include <signal.h> ! 8: #include <regexp.h> ! 9: #include "mail.h" ! 10: #include "string.h" ! 11: #include "message.h" ! 12: #include "aux.h" ! 13: #include <sys/stat.h> ! 14: ! 15: /* global to this file */ ! 16: static int reverse=0; /* ordering of mail messages */ ! 17: static jmp_buf sjbuf; ! 18: int fflg; ! 19: int mflg; ! 20: int pflg; ! 21: int eflg; ! 22: SIG_TYP fint; /* what to do in case of int */ ! 23: SIG_TYP fquit; /* what to do in case of quit */ ! 24: SIG_TYP fpipe; /* what to do in case of sigpipe */ ! 25: ! 26: /* predeclared */ ! 27: message *addr(); ! 28: message *grange(); ! 29: message *range(); ! 30: message *research(); ! 31: message *bresearch(); ! 32: message *incraddr(); ! 33: char *getre(); ! 34: char *header(); ! 35: int edmail(); ! 36: char *doargs(); ! 37: void dumpmail(); ! 38: ! 39: /* imported */ ! 40: char *getlog(); ! 41: FILE *lockopen(); ! 42: FILE *lockreopen(); ! 43: ! 44: SIGRETURN ! 45: done(s) ! 46: int s; ! 47: { ! 48: cleanlocks(); ! 49: V(); ! 50: exit(1); ! 51: } ! 52: ! 53: main(ac, av) ! 54: int ac; ! 55: char *av[]; ! 56: { ! 57: char outbuf[BUFSIZ]; ! 58: int writeable; ! 59: string *user = s_new(); ! 60: char *mailfile; ! 61: char *logname; ! 62: ! 63: /* set signals - make sure we don't override some previous setting */ ! 64: if ((fint=signal(SIGINT, SIG_IGN))!=SIG_DFL) ! 65: signal(SIGINT, fint); ! 66: else ! 67: signal(SIGINT, fint = (SIG_TYP)done); ! 68: if ((fquit=signal(SIGQUIT, SIG_IGN))!=SIG_DFL) ! 69: signal(SIGQUIT, fquit); ! 70: else ! 71: signal(SIGQUIT, fquit = (SIG_TYP)done); ! 72: if ((fpipe=signal(SIGPIPE, SIG_IGN))!=SIG_DFL) ! 73: signal(SIGPIPE, fpipe); ! 74: else ! 75: signal(SIGPIPE, fpipe = (SIG_TYP)done); ! 76: ! 77: logname = getlog(); ! 78: if (logname == NULL) { ! 79: printf ("mail: cannot determine login name\n"); ! 80: return 0; ! 81: } ! 82: s_append(user, logname); ! 83: /* setbuf(stdout, outbuf); */ ! 84: mailfile = doargs(ac, av, s_to_c(user)); ! 85: if (!fflg) ! 86: writeable = P()==0; ! 87: else ! 88: writeable = 1; ! 89: if (eflg) { ! 90: int r = check_mbox(mailfile); ! 91: V(); ! 92: return r; ! 93: } ! 94: if (read_mbox(mailfile, reverse)<0 || mlist == NULL) { ! 95: printf("No mail\n"); ! 96: V(); ! 97: return 0; ! 98: } ! 99: printf("%d messages\n", mlast->pos); ! 100: if (pflg) ! 101: dumpmail(); ! 102: else{ ! 103: while (edmail(mailfile, reverse) && writeable){ ! 104: if(!write_mbox(mailfile, reverse)) ! 105: break; ! 106: } ! 107: } ! 108: V(); ! 109: return 0; ! 110: } ! 111: ! 112: /* parse arguments */ ! 113: char * ! 114: doargs(ac, av, user) ! 115: int ac; ! 116: char *av[]; ! 117: char *user; ! 118: { ! 119: int i; ! 120: string *mailfile; ! 121: char *cp; ! 122: ! 123: /* process args */ ! 124: mailfile = s_new(); ! 125: abspath(user, MAILROOT, mailfile); ! 126: for (i = 1; i<ac; i++) { ! 127: if (av[i][0]!='-') { ! 128: fprintf(stderr, "usage: mail [-mpre] [-f mbox]\n"); ! 129: exit(1); ! 130: } ! 131: for (cp = av[i]+1; *cp; cp++) { ! 132: switch(*cp) { ! 133: case 'r': ! 134: reverse = 1; ! 135: break; ! 136: case 'm': ! 137: mflg = 1; ! 138: break; ! 139: case 'p': ! 140: pflg = 1; ! 141: break; ! 142: case 'e': ! 143: eflg = 1; ! 144: break; ! 145: case 'f': ! 146: fflg = 1; ! 147: if (i+1 >= ac) { ! 148: fprintf(stderr,"mail: missing filename\n"); ! 149: exit(1); ! 150: } ! 151: s_append(s_restart(mailfile), av[++i]); ! 152: break; ! 153: default: ! 154: fprintf(stderr, "usage: mail [-mpre] [-f mbox]\n"); ! 155: exit(1); ! 156: } ! 157: } ! 158: } ! 159: return s_to_c(mailfile); ! 160: } ! 161: ! 162: /* is the mailbox empty? 1 if yes, 0 if no */ ! 163: int ! 164: check_mbox (mf) ! 165: char *mf; ! 166: { ! 167: int n, r; ! 168: char mbuf[1000]; ! 169: string *line; ! 170: FILE *fp; ! 171: ! 172: /* if file doesn't exist, no mail */ ! 173: if ((fp = fopen(mf, "r")) == NULL) ! 174: return 1; ! 175: ! 176: /* if we can't read it, no mail */ ! 177: if (fgets(mbuf, sizeof(mbuf)-2, fp)==NULL){ ! 178: fclose(fp); ! 179: return 1; ! 180: } ! 181: fclose(fp); ! 182: ! 183: /* it is empty iff delivery status is abnormal */ ! 184: n = strlen(mbuf); ! 185: mbuf[n++] = '\n'; ! 186: mbuf[n++] = '\0'; ! 187: line = s_array(mbuf, n); ! 188: r = delivery_status(s_restart(line)) != MF_NORMAL; ! 189: ! 190: s_free (line); ! 191: return r; ! 192: } ! 193: ! 194: /* mesage dump */ ! 195: void ! 196: dumpmail() ! 197: { ! 198: message *mp; ! 199: ! 200: for (mp=mlist; mp!=NULL; mp=mp->next) { ! 201: m_print(mp, stdout, 1, 1); ! 202: } ! 203: } ! 204: ! 205: SIGRETURN ! 206: catchint(s) ! 207: int s; ! 208: { ! 209: signal(SIGINT, catchint); ! 210: clearerr(stdin); ! 211: clearerr(stdout); ! 212: longjmp(sjbuf, 1); ! 213: } ! 214: ! 215: notatnl(cp) ! 216: char *cp; ! 217: { ! 218: if (*cp=='\n') { ! 219: fprintf(stderr, "!argument expected\n"); ! 220: return -1; ! 221: } ! 222: return 0; ! 223: } ! 224: ! 225: int ! 226: atblank(cp) ! 227: char *cp; ! 228: { ! 229: if (*cp!='\n' && *(cp-1)!=' ' && *(cp-1)!='\t') { ! 230: fprintf(stderr, "newline or space expected\n"); ! 231: return -1; ! 232: } ! 233: return 0; ! 234: } ! 235: ! 236: atnl(cp) ! 237: char *cp; ! 238: { ! 239: if (*cp!='\n') { ! 240: fprintf(stderr, "!newline expected\n"); ! 241: return -1; ! 242: } ! 243: return 0; ! 244: } ! 245: ! 246: zero(mp) ! 247: message *mp; ! 248: { ! 249: if (mp==mzero) { ! 250: fprintf(stderr, "!message 0\n"); ! 251: return -1; ! 252: } ! 253: return 0; ! 254: } ! 255: ! 256: #define s_skipwhite(s) for (; *s->ptr==' ' || *s->ptr=='\t'; s->ptr++); ! 257: ! 258: /* ed style interface */ ! 259: edmail(mailfile, reverse) ! 260: char *mailfile; ! 261: int reverse; ! 262: { ! 263: message *dot; ! 264: message *extent; ! 265: string *cmd=s_new(); ! 266: char *cp; ! 267: int cmdc; ! 268: int i, abort=0, nopr, change=1; ! 269: int del; ! 270: ! 271: extent = dot = mzero; ! 272: nopr = mflg; ! 273: for(;;) { ! 274: extent = dot; /* in case of interrupt */ ! 275: if (!nopr) { ! 276: /* advance only if we want to print next message */ ! 277: if(dot->next!=NULL) ! 278: dot = dot->next; ! 279: else ! 280: nopr = 1; ! 281: } ! 282: if (setjmp(sjbuf)) { ! 283: /* come here after interrupt */ ! 284: if (extent!=NULL) ! 285: dot = extent; ! 286: nopr = 1; ! 287: printf("\n"); ! 288: } ! 289: if (fint==(SIG_TYP)done) ! 290: signal(SIGINT, catchint); ! 291: if (!nopr&&dot!=mzero) { ! 292: /* print next message */ ! 293: extent = dot; /* in case of interrupt */ ! 294: print(dot); ! 295: nopr = 1; ! 296: } ! 297: abort = 0; ! 298: nopr = 1; ! 299: change = 1; ! 300: printf("?"); ! 301: fflush(stdout); ! 302: if(s_read_line(stdin, s_restart(cmd)) == NULL) { ! 303: signal(SIGINT, fint); /* bacause of the setjmp */ ! 304: return 1; ! 305: } ! 306: s_restart(cmd); ! 307: s_skipwhite(cmd); ! 308: if (!mflg && *cmd->ptr=='\n' && dot==mlast) { ! 309: signal(SIGINT, fint); /* bacause of the setjmp */ ! 310: return 1; ! 311: } ! 312: extent = range(dot, cmd); ! 313: s_skipwhite(cmd); ! 314: del = 0; ! 315: compoundcmd: ! 316: /* hack to catch a common mistake */ ! 317: if (strncmp(cmd->ptr, "mail", 4)==0) ! 318: cmdc = -1; ! 319: else ! 320: cmdc = *cmd->ptr++; ! 321: s_skipwhite(cmd); ! 322: cp = cmd->ptr; ! 323: for(; extent!=NULL && !abort; extent=extent->extent) { ! 324: switch(cmdc){ ! 325: case 'b': ! 326: abort = atnl(cp)||(del&&delete(extent)); ! 327: if (!abort) ! 328: if (extent!=mzero) ! 329: prheader(extent); ! 330: for(i=0; extent->next!=NULL&&i<9; i++){ ! 331: extent = extent->next; ! 332: prheader(extent); ! 333: } ! 334: break; ! 335: case 'h': ! 336: abort = atnl(cp)||zero(extent) ! 337: ||(del&&delete(extent)) ! 338: ||prheader(extent); ! 339: break; ! 340: case 'd': ! 341: if(*cp=='\n' || *cp==0){ ! 342: abort = zero(extent)||delete(extent); ! 343: nopr = abort||mflg; ! 344: break; ! 345: } ! 346: del = 1; ! 347: goto compoundcmd; ! 348: case 's': ! 349: abort = atblank(cp)||zero(extent)||store(extent, cp, 1) ! 350: ||(del&&delete(extent)); ! 351: nopr = abort||mflg||!del; ! 352: break; ! 353: case 'w': ! 354: abort = atblank(cp)||zero(extent)||notatnl(cp) ! 355: ||store(extent, cp, 0) ! 356: ||(del&&delete(extent)); ! 357: nopr = abort||mflg||!del; ! 358: break; ! 359: case 'm': ! 360: abort = atblank(cp)||zero(extent)||notatnl(cp) ! 361: ||remail(extent, cp, 0) ! 362: ||(del&&delete(extent)); ! 363: nopr = abort||mflg||!del; ! 364: break; ! 365: case 'M': ! 366: abort = atblank(cp)||zero(extent)||notatnl(cp) ! 367: ||remail(extent, cp, 1) ! 368: ||(del&&delete(extent)); ! 369: nopr = abort||mflg||!del; ! 370: break; ! 371: case '\n': ! 372: abort = zero(extent)||print(extent); ! 373: break; ! 374: case 'p': ! 375: if(del){ ! 376: nopr = abort = atnl(cp)||zero(extent) ! 377: ||(del&&delete(extent)); ! 378: break; ! 379: } ! 380: abort = atnl(cp)||zero(extent)||print(extent); ! 381: break; ! 382: case 'r': ! 383: abort = zero(extent)||atnl(cp)||reply(extent, 0) ! 384: ||(del&&delete(extent)); ! 385: nopr = abort||mflg||!del; ! 386: break; ! 387: case 'R': ! 388: abort = zero(extent)||atnl(cp)||reply(extent, 1) ! 389: ||(del&&delete(extent)); ! 390: nopr = abort||mflg||!del; ! 391: break; ! 392: case 'q': ! 393: abort=atnl(cp) ! 394: ||(del&&(zero(extent)||delete(extent))); ! 395: if(abort) ! 396: break; ! 397: signal(SIGINT, fint); /* bacause of the setjmp */ ! 398: return 1; ! 399: case '|': ! 400: abort = zero(extent)||notatnl(cp) ! 401: ||pipemail(extent, cp, 0) ! 402: ||(del&&delete(extent)); ! 403: nopr = abort||mflg||!del; ! 404: break; ! 405: case '=': ! 406: abort = atnl(cp)||(del&&delete(extent)) ! 407: ||whereis(extent); ! 408: change = 0; ! 409: break; ! 410: case '!': ! 411: abort=del&&(zero(extent)||delete(extent)); ! 412: if(abort) ! 413: break; ! 414: escape(cp); ! 415: break; ! 416: case 'u': ! 417: abort = zero(extent)||atnl(cp)||undelete(extent); ! 418: break; ! 419: case 'x': ! 420: signal(SIGINT, fint); /* bacause of the setjmp */ ! 421: return 0; ! 422: case '?': ! 423: abort = atnl(cp) ! 424: ||del&&(zero(extent)||delete(extent)); ! 425: if(abort) ! 426: break; ! 427: help(); ! 428: nopr = abort = 1; ! 429: break; ! 430: case 'i': ! 431: abort = atnl(cp) ! 432: ||(del&&(zero(extent)||delete(extent))); ! 433: if(abort) ! 434: break; ! 435: reread_mbox(mailfile, reverse); ! 436: nopr = abort = 1; ! 437: break; ! 438: default: ! 439: printf("!unknown command (type ? for help)\n"); ! 440: nopr = abort = 1; ! 441: break; ! 442: } ! 443: if (!abort&&change&&extent!=NULL) ! 444: dot = extent; ! 445: } ! 446: } ! 447: } ! 448: ! 449: /* parse an address range */ ! 450: message * ! 451: range(dot, cmd) ! 452: message *dot; ! 453: string *cmd; ! 454: { ! 455: message *first, *last; ! 456: ! 457: s_skipwhite(cmd); ! 458: ! 459: /* get first address in range */ ! 460: switch(*cmd->ptr) { ! 461: case 'g': ! 462: cmd->ptr++; ! 463: return grange(cmd); ! 464: case ',': ! 465: first = mlist; ! 466: break; ! 467: case '0': case '1': case '2': case '3': case '4': ! 468: case '5': case '6': case '7': case '8': case '9': ! 469: first = addr((message *)NULL, cmd); ! 470: break; ! 471: case '?': ! 472: if (*(cmd->ptr+1)=='\n') { ! 473: if(dot!=NULL) ! 474: dot->extent = NULL; ! 475: return dot; ! 476: } ! 477: case '\\': case '/': case '+': case '-': case '$': case '.': ! 478: first = addr(dot, cmd); ! 479: break; ! 480: case '\n': ! 481: first = dot->next; ! 482: if (first==NULL) ! 483: fprintf(stderr, "!address\n"); ! 484: break; ! 485: default: ! 486: if(dot!=NULL) ! 487: dot->extent = NULL; ! 488: return dot; ! 489: } ! 490: if (first == NULL) ! 491: return NULL; ! 492: while(*cmd->ptr == ' ' || *cmd->ptr == '\t') ! 493: cmd->ptr++; ! 494: if (*cmd->ptr != ',') { ! 495: first->extent = NULL; ! 496: return first; ! 497: } ! 498: ! 499: /* get second address in range */ ! 500: cmd->ptr++; ! 501: while(*cmd->ptr == ' ' || *cmd->ptr == '\t') ! 502: cmd->ptr++; ! 503: switch(*cmd->ptr) { ! 504: case '\\': case '/': case '?': case '+': case '-': case '$': ! 505: last = addr(first, cmd); ! 506: break; ! 507: case '.': ! 508: last = addr(dot, cmd); ! 509: break; ! 510: case '0': case '1': case '2': case '3': case '4': ! 511: case '5': case '6': case '7': case '8': case '9': ! 512: last = addr((message *)NULL, cmd); ! 513: break; ! 514: default: ! 515: last = mlast; ! 516: break; ! 517: } ! 518: if (last==NULL) ! 519: return NULL; ! 520: ! 521: /* fill in the range */ ! 522: for(dot=first; dot!=last && dot!=NULL; dot=dot->next) ! 523: dot->extent = dot->next; ! 524: if (dot==NULL) { ! 525: fprintf(stderr, "!addresses out of order\n"); ! 526: return NULL; ! 527: } ! 528: last->extent = NULL; ! 529: return first; ! 530: } ! 531: ! 532: /* parse a global range */ ! 533: message * ! 534: grange(cmd) ! 535: string *cmd; ! 536: { ! 537: char *re; ! 538: message *first, *last, *next; ! 539: regexp *pp; ! 540: ! 541: if (*cmd->ptr == '/') { ! 542: re = getre(cmd); ! 543: if (re == NULL) ! 544: return NULL; ! 545: if ((pp = regcomp(re))==NULL) ! 546: return NULL; ! 547: first = NULL; ! 548: for(next=mlist; next!=NULL; next=next->next) ! 549: if (regexec(pp, header(next), 0, 0)) { ! 550: if (first==NULL) ! 551: first = last = next; ! 552: else { ! 553: last->extent = next; ! 554: last = next; ! 555: } ! 556: last->extent = NULL; ! 557: } ! 558: if (first==NULL) ! 559: fprintf(stderr, "!match\n"); ! 560: free((char *)pp); ! 561: return first; ! 562: } else if (*cmd->ptr == '\\') { ! 563: re = getre(cmd); ! 564: if (re == NULL) ! 565: return NULL; ! 566: if ((pp = regcomp(re))==NULL) ! 567: return NULL; ! 568: first = NULL; ! 569: for(next=mlist; next!=NULL; next=next->next){ ! 570: s_to_c(next->body)[next->size-1]='\0'; ! 571: if (regexec(pp, s_to_c(next->body), 0, 0)) { ! 572: if (first==NULL) ! 573: first = last = next; ! 574: else { ! 575: last->extent = next; ! 576: last = next; ! 577: } ! 578: last->extent = NULL; ! 579: } ! 580: } ! 581: if (first==NULL) ! 582: fprintf(stderr, "!match\n"); ! 583: free((char *)pp); ! 584: return first; ! 585: } else { ! 586: /* fill in the range */ ! 587: for(next=mlist; next!=NULL; next=next->next) ! 588: next->extent = next->next; ! 589: mlast->extent = NULL; ! 590: return mlist; ! 591: } ! 592: } ! 593: ! 594: /* parse an address */ ! 595: message * ! 596: addr(base, cmd) ! 597: message *base; /* where to compute +/- from */ ! 598: string *cmd; ! 599: { ! 600: int forward = -1; ! 601: ! 602: /* get direction */ ! 603: switch(*cmd->ptr) { ! 604: case '+': ! 605: forward = 1; ! 606: cmd->ptr++; ! 607: break; ! 608: case '-': ! 609: forward = 0; ! 610: cmd->ptr++; ! 611: break; ! 612: } ! 613: while(*cmd->ptr == ' ' || *cmd->ptr == '\t') ! 614: cmd->ptr++; ! 615: switch(*cmd->ptr) { ! 616: case '0': case '1': case '2': case '3': case '4': ! 617: case '5': case '6': case '7': case '8': case '9': ! 618: base = incraddr(base, getnumb(cmd), forward); ! 619: if (base==NULL) ! 620: break; ! 621: return addr(base, cmd); ! 622: case '?': ! 623: forward = !forward; ! 624: case '/': ! 625: base = research(base, getre(cmd), forward); ! 626: if (base==NULL) { ! 627: fprintf(stderr, "!search\n"); ! 628: return NULL; ! 629: } ! 630: return addr(base, cmd); ! 631: case '\\': ! 632: base = bresearch(base, getre(cmd), forward); ! 633: if (base==NULL) { ! 634: fprintf(stderr, "!search\n"); ! 635: return NULL; ! 636: } ! 637: return addr(base, cmd); ! 638: case '.': ! 639: cmd->ptr++; ! 640: return addr(base, cmd);; ! 641: case '$': ! 642: cmd->ptr++; ! 643: return addr(mlast, cmd); ! 644: default: ! 645: /* default increment is 1 */ ! 646: if (forward != -1) { ! 647: base = incraddr(base, 1, forward); ! 648: return addr(base, cmd); ! 649: } ! 650: break; ! 651: } ! 652: if (base==NULL) ! 653: fprintf(stderr, "!address\n"); ! 654: return base; ! 655: } ! 656: ! 657: /* increment the base address by offset */ ! 658: message * ! 659: incraddr(base, offset, forward) ! 660: message *base; ! 661: int offset; ! 662: int forward; ! 663: { ! 664: if (base==NULL) { ! 665: base = mzero; ! 666: } ! 667: for(; offset > 0 && base != NULL; offset--) ! 668: base = forward?(base->next):(base->prev); ! 669: return base; ! 670: } ! 671: ! 672: /* look for the message header after base that matches the reg exp */ ! 673: message * ! 674: research(base, rp, forward) ! 675: message *base; ! 676: char *rp; ! 677: int forward; ! 678: { ! 679: regexp *pp; ! 680: message *mp; ! 681: ! 682: if (rp == NULL) ! 683: return NULL; ! 684: if ((pp = regcomp(rp))==NULL) ! 685: return NULL; ! 686: mp = base; ! 687: base = (base==mzero)?(forward?(mp->prev):(mp->next)):base; ! 688: do { ! 689: mp = forward?(mp->next):(mp->prev); ! 690: if (mp==NULL) ! 691: mp = forward?mlist:mlast; ! 692: if (regexec(pp, header(mp), 0, 0)) { ! 693: free((char *)pp); ! 694: return mp; ! 695: } ! 696: } while (mp!=base); ! 697: free((char *)pp); ! 698: return NULL; ! 699: } ! 700: ! 701: /* look for the message after base that matches the reg exp */ ! 702: message * ! 703: bresearch(base, rp, forward) ! 704: message *base; ! 705: char *rp; ! 706: int forward; ! 707: { ! 708: regexp *pp; ! 709: message *mp; ! 710: ! 711: if (rp == NULL) ! 712: return NULL; ! 713: if ((pp = regcomp(rp))==NULL) ! 714: return NULL; ! 715: mp = base = (base==mzero)?mzero->next:base; ! 716: do { ! 717: mp = forward?(mp->next):(mp->prev); ! 718: if (mp==NULL) ! 719: mp = forward?mlist:mlast; ! 720: s_to_c(mp->body)[mp->size-1]='\0'; ! 721: if (regexec(pp, s_to_c(mp->body), 0, 0)) { ! 722: free((char *)pp); ! 723: return mp; ! 724: } ! 725: } while (mp!=base); ! 726: free((char *)pp); ! 727: return NULL; ! 728: } ! 729: ! 730: /* get a number out of the command */ ! 731: int ! 732: getnumb(cmd) ! 733: string *cmd; ! 734: { ! 735: int offset=0; ! 736: while (isdigit(*cmd->ptr)) ! 737: offset = offset*10 + *cmd->ptr++ - '0'; ! 738: return offset; ! 739: } ! 740: ! 741: /* get a regular exression out of the command */ ! 742: char * ! 743: getre(cmd) ! 744: string *cmd; ! 745: { ! 746: static char re[80]; ! 747: char *cp=re; ! 748: char term = *cmd->ptr++; ! 749: ! 750: while (*cmd->ptr!='\0' && *cmd->ptr!='\n' && *cmd->ptr!=term) ! 751: *cp++ = *cmd->ptr++; ! 752: if (*cmd->ptr == term) ! 753: cmd->ptr++; ! 754: if (cp == re) { ! 755: if (*re == '\0') { ! 756: fprintf(stderr, "!no previous regular expression\n"); ! 757: return NULL; ! 758: } ! 759: } else ! 760: *cp = '\0'; ! 761: return re; ! 762: } ! 763: ! 764: regerror(msg) ! 765: char *msg; ! 766: { ! 767: fprintf(stderr, "!illegal address: %s\n", msg); ! 768: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.