|
|
1.1 ! root 1: /* smail.c - MH interface to SendMail/SMTP */ ! 2: ! 3: /* LINTLIBRARY */ ! 4: ! 5: /* This module implements an interface to SendMail very similar to the ! 6: MMDF mm_(3) routines. The sm_() routines herein talk SMTP to a ! 7: sendmail process, mapping SMTP reply codes into RP_-style codes. ! 8: */ ! 9: ! 10: #ifdef BSD42 ! 11: /* Under 4.2BSD, the alarm handing stuff for time-outs will NOT work due to ! 12: the way syscalls get restarted. This really is not crucial, since we ! 13: expect SendMail to be well-behaved and not hang on us. The only time ! 14: I've ever seen Sendmail hang was with a bogus configuration file... ! 15: */ ! 16: #endif BSD42 ! 17: ! 18: #ifndef BSD42 ! 19: #undef SMTP ! 20: #endif not BSD42 ! 21: #ifdef SMTP ! 22: #undef SENDMAIL ! 23: #endif SMTP ! 24: ! 25: #ifndef SIGDECL ! 26: #ifdef SUNOS4 ! 27: #define SIGDECL void ! 28: #else ! 29: #define SIGDECL int ! 30: #endif ! 31: #endif ! 32: ! 33: #include "../h/strings.h" ! 34: #include <stdio.h> ! 35: #include "smail.h" ! 36: #include "../zotnet/mts.h" ! 37: #include <ctype.h> ! 38: #include <signal.h> ! 39: ! 40: #define NOTOK (-1) ! 41: #define OK 0 ! 42: #define DONE 1 ! 43: ! 44: #define TRUE 1 ! 45: #define FALSE 0 ! 46: ! 47: #define NBITS ((sizeof (int)) * 8) ! 48: ! 49: #define min(a,b) ((a) < (b) ? (a) : (b)) ! 50: ! 51: ! 52: #define SM_OPEN 30 ! 53: #define SM_HELO 20 ! 54: #define SM_RSET 15 ! 55: #define SM_MAIL 40 ! 56: #define SM_RCPT 120 ! 57: #define SM_DATA 20 ! 58: #define SM_TEXT 120 ! 59: #define SM_DOT 120 ! 60: #define SM_QUIT 20 ! 61: #define SM_CLOS 10 ! 62: ! 63: /* */ ! 64: ! 65: static int sm_addrs = 0; ! 66: static int sm_alarmed = 0; ! 67: #ifndef SMTP ! 68: static int sm_child = NOTOK; ! 69: #endif not SMTP ! 70: static int sm_debug = 0; ! 71: static int sm_nl = TRUE; ! 72: static int sm_verbose = 0; ! 73: ! 74: static FILE * sm_rfp = NULL; ! 75: static FILE * sm_wfp = NULL; ! 76: ! 77: static char *sm_noreply = "No reply text given"; ! 78: static char *sm_moreply = "; "; ! 79: ! 80: struct smtp sm_reply; /* global... */ ! 81: ! 82: ! 83: char *r1bindex (); ! 84: ! 85: static int rclient(), sm_ierror(), smtalk(), sm_wrecord(), sm_wstream(), ! 86: sm_werror(), smhear(), sm_rrecord(), sm_rerror(); ! 87: static SIGDECL alrmser(); ! 88: ! 89: /* */ ! 90: ! 91: #ifndef SMTP ! 92: ! 93: /* ARGSUSED */ ! 94: ! 95: sm_init(client, server, watch, verbose, debug) ! 96: register char *client; ! 97: char *server; ! 98: register int watch, verbose, debug; ! 99: { ! 100: register int i, ! 101: result, ! 102: vecp; ! 103: int pdi[2], ! 104: pdo[2]; ! 105: char *vec[15]; ! 106: ! 107: if (watch) ! 108: verbose = TRUE; ! 109: sm_verbose = verbose; ! 110: sm_debug = debug; ! 111: if (sm_rfp != NULL && sm_wfp != NULL) ! 112: return RP_OK; ! 113: ! 114: if (pipe (pdi) == NOTOK) ! 115: return sm_ierror ("no pipes"); ! 116: if (pipe (pdo) == NOTOK) { ! 117: (void) close (pdi[0]); ! 118: (void) close (pdi[1]); ! 119: return sm_ierror ("no pipes"); ! 120: } ! 121: ! 122: for (i = 0; (sm_child = fork ()) == NOTOK && i < 5; i++) ! 123: sleep (5); ! 124: switch (sm_child) { ! 125: case NOTOK: ! 126: (void) close (pdo[0]); ! 127: (void) close (pdo[1]); ! 128: (void) close (pdi[0]); ! 129: (void) close (pdi[1]); ! 130: return sm_ierror ("unable to fork"); ! 131: ! 132: case OK: ! 133: if (pdo[0] != fileno (stdin)) ! 134: (void) dup2 (pdo[0], fileno (stdin)); ! 135: if (pdi[1] != fileno (stdout)) ! 136: (void) dup2 (pdi[1], fileno (stdout)); ! 137: if (pdi[1] != fileno (stderr)) ! 138: (void) dup2 (pdi[1], fileno (stderr)); ! 139: for (i = fileno (stderr) + 1; i < NBITS; i++) ! 140: (void) close (i); ! 141: ! 142: vecp = 0; ! 143: vec[vecp++] = r1bindex (sendmail, '/'); ! 144: vec[vecp++] = "-bs"; ! 145: vec[vecp++] = watch ? "-odi" : "-odb"; ! 146: vec[vecp++] = "-oem"; ! 147: vec[vecp++] = "-om"; ! 148: #ifndef RAND ! 149: if (verbose) ! 150: vec[vecp++] = "-ov"; ! 151: #endif not RAND ! 152: vec[vecp++] = NULL; ! 153: ! 154: (void) setgid (getegid ()); ! 155: (void) setuid (geteuid ()); ! 156: execvp (sendmail, vec); ! 157: fprintf (stderr, "unable to exec "); ! 158: perror (sendmail); ! 159: _exit (-1); /* NOTREACHED */ ! 160: ! 161: default: ! 162: (void) signal (SIGALRM, alrmser); ! 163: (void) signal (SIGPIPE, SIG_IGN); ! 164: ! 165: (void) close (pdi[1]); ! 166: (void) close (pdo[0]); ! 167: if ((sm_rfp = fdopen (pdi[0], "r")) == NULL ! 168: || (sm_wfp = fdopen (pdo[1], "w")) == NULL) { ! 169: (void) close (pdi[0]); ! 170: (void) close (pdo[1]); ! 171: sm_rfp = sm_wfp = NULL; ! 172: return sm_ierror ("unable to fdopen"); ! 173: } ! 174: sm_alarmed = 0; ! 175: (void) alarm (SM_OPEN); ! 176: result = smhear (); ! 177: (void) alarm (0); ! 178: switch (result) { ! 179: case 220: ! 180: break; ! 181: ! 182: default: ! 183: (void) sm_end (NOTOK); ! 184: return RP_RPLY; ! 185: } ! 186: if (client && *client) ! 187: switch (smtalk (SM_HELO, "HELO %s", client)) { ! 188: case 250: ! 189: break; ! 190: ! 191: default: ! 192: (void) sm_end (NOTOK); ! 193: return RP_RPLY; ! 194: } ! 195: return RP_OK; ! 196: } ! 197: } ! 198: #else SMTP ! 199: ! 200: /* */ ! 201: ! 202: sm_init(client, server, watch, verbose, debug) ! 203: register char *client, *server; ! 204: register int watch, verbose, debug; ! 205: { ! 206: register int result, ! 207: sd1, ! 208: sd2; ! 209: ! 210: if (watch) ! 211: verbose = TRUE; ! 212: sm_verbose = verbose; ! 213: sm_debug = debug; ! 214: if (sm_rfp != NULL && sm_wfp != NULL) ! 215: return RP_OK; ! 216: #ifndef SENDMTS ! 217: if (client == NULL || *client == NULL) ! 218: client = LocalName (); ! 219: #endif not SENDMTS ! 220: ! 221: if ((sd1 = rclient (server, "tcp", "smtp")) == NOTOK) ! 222: return RP_BHST; ! 223: if ((sd2 = dup (sd1)) == NOTOK) { ! 224: (void) close (sd1); ! 225: return sm_ierror ("unable to dup"); ! 226: } ! 227: ! 228: (void) signal (SIGALRM, alrmser); ! 229: (void) signal (SIGPIPE, SIG_IGN); ! 230: ! 231: if ((sm_rfp = fdopen (sd1, "r")) == NULL ! 232: || (sm_wfp = fdopen (sd2, "w")) == NULL) { ! 233: (void) close (sd1); ! 234: (void) close (sd2); ! 235: sm_rfp = sm_wfp = NULL; ! 236: return sm_ierror ("unable to fdopen"); ! 237: } ! 238: sm_alarmed = 0; ! 239: (void) alarm (SM_OPEN); ! 240: result = smhear (); ! 241: (void) alarm (0); ! 242: switch (result) { ! 243: case 220: ! 244: break; ! 245: ! 246: default: ! 247: (void) sm_end (NOTOK); ! 248: return RP_RPLY; ! 249: } ! 250: if (client && *client) ! 251: switch (smtalk (SM_HELO, "HELO %s", client)) { ! 252: case 250: ! 253: break; ! 254: ! 255: default: ! 256: (void) sm_end (NOTOK); ! 257: return RP_RPLY; ! 258: } ! 259: ! 260: return RP_OK; ! 261: } ! 262: ! 263: ! 264: static int ! 265: rclient(server, protocol, service) ! 266: char *server, *protocol, *service; ! 267: { ! 268: int sd; ! 269: char response[BUFSIZ]; ! 270: ! 271: if ((sd = client (server, protocol, service, FALSE, response)) != NOTOK) ! 272: return sd; ! 273: ! 274: (void) sm_ierror ("%s", response); ! 275: return NOTOK; ! 276: } ! 277: #endif SMTP ! 278: ! 279: /* */ ! 280: ! 281: sm_winit(mode, from) ! 282: register int mode; ! 283: register char *from; ! 284: { ! 285: switch (smtalk (SM_MAIL, "%s FROM:<%s>", ! 286: mode == S_SEND ? "SEND" : mode == S_SOML ? "SOML" ! 287: : mode == S_SAML ? "SAML" : "MAIL", from)) { ! 288: case 250: ! 289: sm_addrs = 0; ! 290: return RP_OK; ! 291: ! 292: case 500: ! 293: case 501: ! 294: case 552: ! 295: return RP_PARM; ! 296: ! 297: default: ! 298: return RP_RPLY; ! 299: } ! 300: } ! 301: ! 302: /* */ ! 303: ! 304: #ifdef BERK ! 305: /* ARGUSED */ ! 306: #endif BERK ! 307: ! 308: sm_wadr(mbox, host, path) ! 309: register char *mbox; ! 310: #ifndef BERK ! 311: register ! 312: #endif not BERK ! 313: char *host, *path; ! 314: { ! 315: #ifndef BERK ! 316: switch (smtalk (SM_RCPT, host && *host ? "RCPT TO:<%s%s@%s>" ! 317: : "RCPT TO:<%s%s>", ! 318: path ? path : "", mbox, host)) { ! 319: #else BERK ! 320: switch (smtalk (SM_RCPT, "RCPT TO:%s", mbox)) { ! 321: #endif BERK ! 322: case 250: ! 323: case 251: ! 324: sm_addrs++; ! 325: return RP_OK; ! 326: ! 327: case 421: ! 328: case 450: ! 329: case 451: ! 330: case 452: ! 331: return RP_NO; ! 332: ! 333: case 500: ! 334: case 501: ! 335: return RP_PARM; ! 336: ! 337: case 550: ! 338: case 551: ! 339: case 552: ! 340: case 553: ! 341: return RP_USER; ! 342: ! 343: default: ! 344: return RP_RPLY; ! 345: } ! 346: } ! 347: ! 348: /* */ ! 349: ! 350: int sm_waend () { ! 351: switch (smtalk (SM_DATA, "DATA")) { ! 352: case 354: ! 353: sm_nl = TRUE; ! 354: return RP_OK; ! 355: ! 356: case 421: ! 357: case 451: ! 358: return RP_NO; ! 359: ! 360: case 500: ! 361: case 501: ! 362: case 503: ! 363: case 554: ! 364: return RP_NDEL; ! 365: ! 366: default: ! 367: return RP_RPLY; ! 368: } ! 369: } ! 370: ! 371: /* */ ! 372: ! 373: sm_wtxt(buffer, len) ! 374: register char *buffer; ! 375: register int len; ! 376: { ! 377: register int result; ! 378: ! 379: sm_alarmed = 0; ! 380: (void) alarm (SM_TEXT); ! 381: result = sm_wstream (buffer, len); ! 382: (void) alarm (0); ! 383: ! 384: return (result == NOTOK ? RP_BHST : RP_OK); ! 385: } ! 386: ! 387: /* */ ! 388: ! 389: sm_wtend() ! 390: { ! 391: if (sm_wstream ((char *) NULL, 0) == NOTOK) ! 392: return RP_BHST; ! 393: ! 394: switch (smtalk (SM_DOT + 3 * sm_addrs, ".")) { ! 395: case 250: ! 396: case 251: ! 397: return RP_OK; ! 398: ! 399: case 451: ! 400: case 452: ! 401: default: ! 402: return RP_NO; ! 403: ! 404: case 552: ! 405: case 554: ! 406: return RP_NDEL; ! 407: } ! 408: } ! 409: ! 410: /* */ ! 411: ! 412: sm_end(type) ! 413: register int type; ! 414: { ! 415: register int status; ! 416: struct smtp sm_note; ! 417: ! 418: #ifndef SMTP ! 419: switch (sm_child) { ! 420: case NOTOK: ! 421: case OK: ! 422: return RP_OK; ! 423: ! 424: default: ! 425: break; ! 426: } ! 427: #endif not SMTP ! 428: if (sm_rfp == NULL && sm_wfp == NULL) ! 429: return RP_OK; ! 430: ! 431: switch (type) { ! 432: case OK: ! 433: (void) smtalk (SM_QUIT, "QUIT"); ! 434: break; ! 435: ! 436: case NOTOK: ! 437: sm_note.code = sm_reply.code; ! 438: (void) strncpy (sm_note.text, sm_reply.text, ! 439: sm_note.length = sm_reply.length);/* fall */ ! 440: case DONE: ! 441: if (smtalk (SM_RSET, "RSET") == 250 && type == DONE) ! 442: return RP_OK; ! 443: #ifndef SMTP ! 444: (void) kill (sm_child, SIGKILL); ! 445: discard (sm_rfp); ! 446: discard (sm_wfp); ! 447: #else SMTP ! 448: (void) smtalk (SM_QUIT, "QUIT"); ! 449: #endif not SMTP ! 450: if (type == NOTOK) { ! 451: sm_reply.code = sm_note.code; ! 452: (void) strncpy (sm_reply.text, sm_note.text, ! 453: sm_reply.length = sm_note.length); ! 454: } ! 455: break; ! 456: } ! 457: if (sm_rfp != NULL) { ! 458: (void) alarm (SM_CLOS); ! 459: (void) fclose (sm_rfp); ! 460: (void) alarm (0); ! 461: } ! 462: if (sm_wfp != NULL) { ! 463: (void) alarm (SM_CLOS); ! 464: (void) fclose (sm_wfp); ! 465: (void) alarm (0); ! 466: } ! 467: ! 468: #ifndef SMTP ! 469: status = pidwait (sm_child); ! 470: ! 471: sm_child = NOTOK; ! 472: #else SMTP ! 473: status = 0; ! 474: #endif SMTP ! 475: sm_rfp = sm_wfp = NULL; ! 476: ! 477: return (status ? RP_BHST : RP_OK); ! 478: } ! 479: ! 480: /* */ ! 481: ! 482: /* VARARGS */ ! 483: ! 484: static int ! 485: sm_ierror(fmt, a, b, c, d) ! 486: char *fmt, *a, *b, *c, *d; ! 487: { ! 488: (void) sprintf (sm_reply.text, fmt, a, b, c, d); ! 489: sm_reply.length = strlen (sm_reply.text); ! 490: sm_reply.code = NOTOK; ! 491: ! 492: return RP_BHST; ! 493: } ! 494: ! 495: /* */ ! 496: ! 497: /* VARARGS2 */ ! 498: ! 499: static int ! 500: smtalk(time, fmt, a, b, c, d) ! 501: register int time; ! 502: register char *fmt; ! 503: { ! 504: register int result; ! 505: char buffer[BUFSIZ]; ! 506: ! 507: (void) sprintf (buffer, fmt, a, b, c, d); ! 508: if (sm_debug) { ! 509: printf ("=> %s\n", buffer); ! 510: (void) fflush (stdout); ! 511: } ! 512: ! 513: sm_alarmed = 0; ! 514: (void) alarm ((unsigned) time); ! 515: if ((result = sm_wrecord (buffer, strlen (buffer))) != NOTOK) ! 516: result = smhear (); ! 517: (void) alarm (0); ! 518: ! 519: return result; ! 520: } ! 521: ! 522: /* */ ! 523: ! 524: static int ! 525: sm_wrecord(buffer, len) ! 526: register char *buffer; ! 527: register int len; ! 528: { ! 529: if (sm_wfp == NULL) ! 530: return sm_werror (); ! 531: ! 532: (void) fwrite (buffer, sizeof *buffer, len, sm_wfp); ! 533: fputs ("\r\n", sm_wfp); ! 534: (void) fflush (sm_wfp); ! 535: ! 536: return (ferror (sm_wfp) ? sm_werror () : OK); ! 537: } ! 538: ! 539: /* */ ! 540: ! 541: static int ! 542: sm_wstream(buffer, len) ! 543: register char *buffer; ! 544: register int len; ! 545: { ! 546: register char *bp; ! 547: static char lc = NULL; ! 548: ! 549: if (sm_wfp == NULL) ! 550: return sm_werror (); ! 551: ! 552: if (buffer == NULL && len == 0) { ! 553: if (lc != '\n') ! 554: fputs ("\r\n", sm_wfp); ! 555: lc = NULL; ! 556: return (ferror (sm_wfp) ? sm_werror () : OK); ! 557: } ! 558: ! 559: for (bp = buffer; len > 0; bp++, len--) { ! 560: switch (*bp) { ! 561: case '\n': ! 562: sm_nl = TRUE; ! 563: (void) fputc ('\r', sm_wfp); ! 564: break; ! 565: ! 566: case '.': ! 567: if (sm_nl) ! 568: (void) fputc ('.', sm_wfp);/* FALL THROUGH */ ! 569: default: ! 570: sm_nl = FALSE; ! 571: } ! 572: (void) fputc (*bp, sm_wfp); ! 573: if (ferror (sm_wfp)) ! 574: return sm_werror (); ! 575: } ! 576: ! 577: if (bp > buffer) ! 578: lc = *--bp; ! 579: return (ferror (sm_wfp) ? sm_werror () : OK); ! 580: } ! 581: ! 582: /* */ ! 583: ! 584: static int ! 585: sm_werror() ! 586: { ! 587: sm_reply.length = ! 588: #ifdef SMTP ! 589: strlen (strcpy (sm_reply.text, sm_wfp == NULL ? "no socket opened" ! 590: : sm_alarmed ? "write to socket timed out" ! 591: : "error writing to socket")); ! 592: #else not SMTP ! 593: strlen (strcpy (sm_reply.text, sm_wfp == NULL ? "no pipe opened" ! 594: : sm_alarmed ? "write to pipe timed out" ! 595: : "error writing to pipe")); ! 596: #endif not SMTP ! 597: ! 598: return (sm_reply.code = NOTOK); ! 599: } ! 600: ! 601: /* */ ! 602: ! 603: static int ! 604: smhear() ! 605: { ! 606: register int i, ! 607: code, ! 608: cont, ! 609: rc, ! 610: more; ! 611: int bc; ! 612: register char *bp, ! 613: *rp; ! 614: char buffer[BUFSIZ]; ! 615: ! 616: again: ; ! 617: ! 618: sm_reply.text[sm_reply.length = 0] = NULL; ! 619: ! 620: rp = sm_reply.text, rc = sizeof sm_reply.text - 1; ! 621: for (more = FALSE; sm_rrecord (bp = buffer, &bc) != NOTOK;) { ! 622: if (sm_debug) { ! 623: printf ("<= %s\n", buffer); ! 624: (void) fflush (stdout); ! 625: } ! 626: ! 627: for (; bc > 0 && (!isascii (*bp) || !isdigit (*bp)); bp++, bc--) ! 628: continue; ! 629: ! 630: cont = FALSE; ! 631: code = atoi (bp); ! 632: bp += 3, bc -= 3; ! 633: for (; bc > 0 && isspace (*bp); bp++, bc--) ! 634: continue; ! 635: if (bc > 0 && *bp == '-') { ! 636: cont = TRUE; ! 637: bp++, bc--; ! 638: for (; bc > 0 && isspace (*bp); bp++, bc--) ! 639: continue; ! 640: } ! 641: ! 642: if (more) { ! 643: if (code != sm_reply.code || cont) ! 644: continue; ! 645: more = FALSE; ! 646: } ! 647: else { ! 648: sm_reply.code = code; ! 649: more = cont; ! 650: if (bc <= 0) { ! 651: (void) strcpy (bp = buffer, sm_noreply); ! 652: bc = strlen (sm_noreply); ! 653: } ! 654: } ! 655: if ((i = min (bc, rc)) > 0) { ! 656: (void) strncpy (rp, bp, i); ! 657: rp += i, rc -= i; ! 658: if (more && rc > strlen (sm_moreply) + 1) { ! 659: (void) strcpy (sm_reply.text + rc, sm_moreply); ! 660: rc += strlen (sm_moreply); ! 661: } ! 662: } ! 663: if (more) ! 664: continue; ! 665: if (sm_reply.code < 100) { ! 666: if (sm_verbose) { ! 667: printf ("%s\n", sm_reply.text); ! 668: (void) fflush (stdout); ! 669: } ! 670: goto again; ! 671: } ! 672: ! 673: sm_reply.length = rp - sm_reply.text; ! 674: return sm_reply.code; ! 675: } ! 676: ! 677: return NOTOK; ! 678: } ! 679: ! 680: /* */ ! 681: ! 682: static int ! 683: sm_rrecord (buffer, len) ! 684: register char *buffer; ! 685: register int *len; ! 686: { ! 687: if (sm_rfp == NULL) ! 688: return sm_rerror (); ! 689: ! 690: buffer[*len = 0] = NULL; ! 691: ! 692: (void) fgets (buffer, BUFSIZ, sm_rfp); ! 693: *len = strlen (buffer); ! 694: if (ferror (sm_rfp) || feof (sm_rfp)) ! 695: return sm_rerror (); ! 696: if (buffer[*len - 1] != '\n') ! 697: while (getc (sm_rfp) != '\n' && !ferror (sm_rfp) && !feof (sm_rfp)) ! 698: continue; ! 699: else ! 700: if (buffer[*len - 2] == '\r') ! 701: *len -= 1; ! 702: buffer[*len - 1] = NULL; ! 703: ! 704: return OK; ! 705: } ! 706: ! 707: /* */ ! 708: ! 709: static int ! 710: sm_rerror() ! 711: { ! 712: sm_reply.length = ! 713: #ifdef SMTP ! 714: strlen (strcpy (sm_reply.text, sm_rfp == NULL ? "no socket opened" ! 715: : sm_alarmed ? "read from socket timed out" ! 716: : feof (sm_rfp) ? "premature end-of-file on socket" ! 717: : "error reading from socket")); ! 718: #else not SMTP ! 719: strlen (strcpy (sm_reply.text, sm_rfp == NULL ? "no pipe opened" ! 720: : sm_alarmed ? "read from pipe timed out" ! 721: : feof (sm_rfp) ? "premature end-of-file on pipe" ! 722: : "error reading from pipe")); ! 723: #endif not SMTP ! 724: ! 725: return (sm_reply.code = NOTOK); ! 726: } ! 727: ! 728: /* */ ! 729: ! 730: /* ARGSUSED */ ! 731: ! 732: static SIGDECL ! 733: alrmser(i) ! 734: int i; ! 735: { ! 736: #ifndef BSD42 ! 737: signal (SIGALRM, alrmser); ! 738: #endif BSD42 ! 739: sm_alarmed++; ! 740: ! 741: if (sm_debug) { ! 742: printf ("timed out...\n"); ! 743: (void) fflush (stdout); ! 744: } ! 745: } ! 746: ! 747: /* */ ! 748: ! 749: char * ! 750: rp_string(code) ! 751: register int code; ! 752: { ! 753: register char *text; ! 754: static char buffer[BUFSIZ]; ! 755: ! 756: switch (sm_reply.code != NOTOK ? code : NOTOK) { ! 757: case RP_AOK: ! 758: text = "AOK"; ! 759: break; ! 760: ! 761: case RP_MOK: ! 762: text = "MOK"; ! 763: break; ! 764: ! 765: case RP_OK: ! 766: text = "OK"; ! 767: break; ! 768: ! 769: case RP_RPLY: ! 770: text = "RPLY"; ! 771: break; ! 772: ! 773: case RP_BHST: ! 774: default: ! 775: text = "BHST"; ! 776: (void) sprintf (buffer, "[%s] %s", text, sm_reply.text); ! 777: return buffer; ! 778: ! 779: case RP_PARM: ! 780: text = "PARM"; ! 781: break; ! 782: ! 783: case RP_NO: ! 784: text = "NO"; ! 785: break; ! 786: ! 787: case RP_USER: ! 788: text = "USER"; ! 789: break; ! 790: ! 791: case RP_NDEL: ! 792: text = "NDEL"; ! 793: break; ! 794: } ! 795: ! 796: (void) sprintf (buffer, "[%s] %3d %s", text, sm_reply.code, sm_reply.text); ! 797: return buffer; ! 798: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.