|
|
1.1 ! root 1: #ifndef SPOP ! 2: /* sbboards.c - MH style mailer to write to a ZOTnet BBoard */ ! 3: #else SPOP ! 4: /* spop.c - MH style mailer to write to a POP subscriber */ ! 5: #endif SPOP ! 6: ! 7: #ifndef SPOP ! 8: ! 9: /* This program acts like the MMDF ch_bboards channel: it does local ! 10: delivery to a ZOTnet BBoard and/or addition re-distribution to other ! 11: recipients of the BBoard. This program can function both as a SendMail ! 12: mailer and an MH .mh_receive file, depending on whether SENDMTS or ! 13: MHMTS is set. Currently, the MHMTS version of this program does not do ! 14: re-distribution. ! 15: ! 16: This program should be used ONLY if you have "bboards on" set in your ! 17: MH configuration, and if you have "mts sendmail" or "mts mh" set as well. ! 18: */ ! 19: ! 20: #else SPOP ! 21: ! 22: /* This program acts like the MMDF-II ch_pop channel: it does local ! 23: delivery for non-local users. These users are known as POP subscribers ! 24: and use the Post Office Protocol with a POP server in order to access ! 25: their maildrop. ! 26: */ ! 27: ! 28: #endif SPOP ! 29: ! 30: #undef DISTRIBUTE ! 31: #ifdef SENDMTS ! 32: #ifndef SPOP ! 33: #define DISTRIBUTE ! 34: #endif not SPOP ! 35: #endif SENDMTS ! 36: ! 37: #include "../h/mh.h" ! 38: #ifndef SPOP ! 39: #include "../h/addrsbr.h" ! 40: #endif not SPOP ! 41: #include "../h/dropsbr.h" ! 42: #include "../zotnet/bboards.h" ! 43: #include "../zotnet/tws.h" ! 44: #include <stdio.h> ! 45: #include "../zotnet/mts.h" ! 46: #include <pwd.h> ! 47: #ifndef SYS5 ! 48: #include <sysexits.h> ! 49: #else SYS5 ! 50: #define EX_CANTCREAT 1 ! 51: #define EX_IOERR 1 ! 52: #define EX_NOINPUT 1 ! 53: #define EX_NOUSER 1 ! 54: #define EX_OK 0 ! 55: #define EX_OSERR 1 ! 56: #define EX_OSFILE 1 ! 57: #define EX_UNAVAILABLE 1 ! 58: #define EX_USAGE 1 ! 59: #endif SYS5 ! 60: #ifdef DISTRIBUTE ! 61: #include "../mts/sendmail/smail.h" ! 62: #endif DISTRIBUTE ! 63: ! 64: ! 65: #define NBB 100 ! 66: ! 67: #ifndef SPOP ! 68: #define ENTITY "bboard" ! 69: #else SPOP ! 70: #define ENTITY "subscriber" ! 71: #endif SPOP ! 72: ! 73: /* */ ! 74: ! 75: static int bb_fderr; ! 76: ! 77: static int bb_uid; ! 78: static int bb_gid; ! 79: ! 80: int dst_rcpt (); ! 81: ! 82: ! 83: #ifndef SPOP ! 84: static char bb_from[BUFSIZ]; ! 85: static char bb_head[BUFSIZ]; ! 86: static char bb_home[BUFSIZ]; ! 87: static char bb_time[BUFSIZ]; ! 88: #ifdef DISTRIBUTE ! 89: static char bb_rept[BUFSIZ]; ! 90: #endif DISTRIBUTE ! 91: #else SPOP ! 92: #define bb_head NULLCP ! 93: #endif SPOP ! 94: ! 95: static struct bboard *bb[NBB]; ! 96: ! 97: ! 98: long lseek (); ! 99: ! 100: #ifdef SYS5 ! 101: struct passwd *getpwnam (); ! 102: #endif SYS5 ! 103: ! 104: /* */ ! 105: ! 106: /* ARGSUSED */ ! 107: ! 108: main (argc, argv, envp) ! 109: int argc; ! 110: char **argv, ! 111: **envp; ! 112: { ! 113: int fd; ! 114: char tmpfil[BUFSIZ]; ! 115: ! 116: #ifdef MHMTS ! 117: if (argc != 5) ! 118: adios (EX_USAGE, NULL, "you lose really big"); ! 119: #endif MHMTS ! 120: arginit (argv); ! 121: ! 122: fd = copyfile (fileno (stdin), tmpfil); ! 123: (void) unlink (tmpfil); ! 124: ! 125: localmail (fd); ! 126: #ifdef DISTRIBUTE ! 127: distribute (fd); ! 128: notify (fd); ! 129: #endif DISTRIBUTE ! 130: ! 131: exit (EX_OK); ! 132: } ! 133: ! 134: /* */ ! 135: ! 136: static localmail (fd) ! 137: int fd; ! 138: { ! 139: int i, ! 140: md; ! 141: register struct bboard *bp; ! 142: ! 143: for (i = 0; bp = bb[i]; i++) ! 144: if (bp -> bb_file && *bp -> bb_file) { ! 145: (void) lseek (fd, 0L, 0); ! 146: #ifndef SPOP ! 147: if ((md = mbx_open (bp -> bb_file, bb_uid, bb_gid, BBMODE)) ! 148: #else SPOP ! 149: if ((md = mbx_open (bp -> bb_file, bb_uid, bb_gid, POMODE)) ! 150: #endif SPOP ! 151: == NOTOK) { ! 152: (void) lose ("unable to open %s", bp -> bb_file); ! 153: continue; ! 154: } ! 155: #ifndef SPOP ! 156: if (mbx_init (bp) != NOTOK) ! 157: #endif not SPOP ! 158: (void) mbx_copy (bp -> bb_file, md, fd, 1, bb_head, 0); ! 159: (void) mbx_close (bp -> bb_file, md); ! 160: } ! 161: } ! 162: ! 163: /* */ ! 164: ! 165: #ifndef SPOP ! 166: static int mbx_init (bp) ! 167: register struct bboard *bp; ! 168: { ! 169: int fd, ! 170: clear; ! 171: register struct bboard *ip; ! 172: register FILE *fp; ! 173: ! 174: if ((fd = mbx_Xopen (bp -> bb_info, bb_uid, bb_gid, BBMODE, &clear)) ! 175: == NOTOK) ! 176: return lose ("unable to lock and open %s", bp -> bb_info); ! 177: if ((fp = fdopen (fd, "w")) == NULL) { ! 178: (void) mbx_close (bp -> bb_info, fd); ! 179: return lose ("unable to fdopen %s", bp -> bb_info); ! 180: } ! 181: ! 182: if ((ip = getbbnam (bp -> bb_name)) == NULL) { ! 183: (void) lkfclose (fp, bp -> bb_info); ! 184: return lose ("unable to get information on BBoard %s", bp -> bb_name); ! 185: } ! 186: (void) strcpy (bb_time, dtimenow ()); ! 187: (void) sprintf (bb_head, "BBoard-ID: %d\nBB-Posted: %s\n", ! 188: bp -> bb_maxima = ++ip -> bb_maxima, bb_time); ! 189: ! 190: fprintf (fp, "%d\n%s\n", bp -> bb_maxima, bb_time); ! 191: (void) lkfclose (fp, bp -> bb_info); ! 192: ! 193: return OK; ! 194: } ! 195: #endif not SPOP ! 196: ! 197: /* */ ! 198: ! 199: #ifdef DISTRIBUTE ! 200: static distribute (fd) ! 201: int fd; ! 202: { ! 203: int i; ! 204: register struct bboard *bp; ! 205: ! 206: for (i = 0; bp = bb[i]; i++) ! 207: if (bp -> bb_dist && *bp -> bb_dist) ! 208: break; ! 209: if (bp == NULL) ! 210: return; ! 211: ! 212: if (dst_init () == NOTOK) { ! 213: dst_lose (); ! 214: return; ! 215: } ! 216: for (i = 0; bp = bb[i]; i++) ! 217: if (bp -> bb_dist && *bp -> bb_dist) ! 218: if (dst_adrs (bp) == NOTOK) { ! 219: dst_lose (); ! 220: return; ! 221: } ! 222: if (dst_text (fd) == NOTOK || dst_end () == NOTOK) ! 223: dst_lose (); ! 224: } ! 225: ! 226: /* */ ! 227: ! 228: static int dst_init () ! 229: { ! 230: int retval; ! 231: ! 232: if (rp_isbad (retval = sm_init (NULLCP, NULLCP, 0, 0, 0)) ! 233: || rp_isbad (retval = sm_winit (S_MAIL, bb_from))) ! 234: return lose ("problem initializing SendMail; %s", ! 235: rp_string (retval)); ! 236: ! 237: return OK; ! 238: } ! 239: ! 240: /* */ ! 241: ! 242: static int dst_adrs (bp) ! 243: register struct bboard *bp; ! 244: { ! 245: if (getbbdist (bp, dst_rcpt)) ! 246: return lose ("getbbdist failed: %s", getbberr ()); ! 247: ! 248: return OK; ! 249: } ! 250: ! 251: /* */ ! 252: ! 253: static int dst_rcpt (mbox, host) ! 254: register char *mbox, ! 255: *host; ! 256: { ! 257: int retval; ! 258: ! 259: switch (retval = sm_wadr (mbox, host, NULLCP)) { ! 260: case RP_OK: ! 261: return OK; ! 262: ! 263: case RP_NO: ! 264: case RP_USER: ! 265: (void) lose ("%s@%s: loses; %s", mbox, host, rp_string (retval)); ! 266: return OK; /* fail-soft */ ! 267: ! 268: default: ! 269: return lose ("%s@%s: unexpected response; %s", ! 270: mbox, host, rp_string (retval)); ! 271: } ! 272: } ! 273: ! 274: /* */ ! 275: ! 276: static int dst_text (fd) ! 277: int fd; ! 278: { ! 279: int i, ! 280: retval; ! 281: char buffer[BUFSIZ]; ! 282: ! 283: if (rp_isbad (retval = sm_waend ())) ! 284: return lose ("problem ending addresses; %s", rp_string (retval)); ! 285: ! 286: (void) lseek (fd, 0L, 0); ! 287: while ((i = read (fd, buffer, sizeof buffer)) > 0) ! 288: if (rp_isbad (retval = sm_wtxt (buffer, i))) ! 289: return lose ("problem writing text; %s", rp_string (retval)); ! 290: ! 291: return (i != NOTOK ? OK : lose ("error reading from file")); ! 292: } ! 293: ! 294: /* */ ! 295: ! 296: static int dst_end () ! 297: { ! 298: int retval; ! 299: ! 300: switch (retval = sm_wtend ()) { ! 301: case RP_OK: ! 302: (void) sm_end (OK); ! 303: return OK; ! 304: ! 305: case RP_NO: ! 306: case RP_NDEL: ! 307: return lose ("posting failed; %s", rp_string (retval)); ! 308: ! 309: default: ! 310: return lose ("unexpected response; %s", rp_string (retval)); ! 311: } ! 312: } ! 313: ! 314: /* */ ! 315: ! 316: static dst_lose () ! 317: { ! 318: (void) sm_end (NOTOK); ! 319: } ! 320: ! 321: /* */ ! 322: ! 323: /* VARARGS1 */ ! 324: ! 325: static int lose (fmt, a, b, c, d) ! 326: char *fmt, ! 327: *a, ! 328: *b, ! 329: *c, ! 330: *d; ! 331: { ! 332: int fd, ! 333: i; ! 334: char *bp, ! 335: buffer[BUFSIZ]; ! 336: ! 337: if (bb_fderr == NOTOK) { ! 338: if ((fd = open ("/dev/null", 0)) == NOTOK) ! 339: adios (EX_OSERR, "/dev/null", "unable to open"); ! 340: bb_fderr = copyfile (fd, bb_rept); ! 341: } ! 342: ! 343: (void) sprintf (bp = buffer, fmt, a, b, c, d); ! 344: bp += strlen (bp); ! 345: bp += strlen (strcpy(bp, "\n")); ! 346: i = bp - buffer; ! 347: if (write (bb_fderr, buffer, i) != i) ! 348: adios (EX_IOERR, bb_rept, "error writing"); ! 349: ! 350: return NOTOK; ! 351: } ! 352: ! 353: /* */ ! 354: ! 355: static notify (fd) ! 356: int fd; ! 357: { ! 358: int i; ! 359: char buffer[BUFSIZ]; ! 360: ! 361: if (bb_fderr == NOTOK) ! 362: return; ! 363: ! 364: if (rp_isbad (sm_init (NULLCP, NULLCP, 0, 0, 0)) ! 365: || rp_isbad (sm_winit (S_MAIL, bb_from))) ! 366: goto sm_err; ! 367: ! 368: switch (sm_wadr (bb_from, NULLCP, NULLCP)) { ! 369: case RP_OK: ! 370: for (i = 0; bb[i]; i++) { ! 371: (void) sprintf (buffer, "local-%s-request", bb[i] -> bb_name); ! 372: (void) sm_wadr (buffer, LocalName (), NULLCP); ! 373: } ! 374: break; ! 375: ! 376: default: ! 377: goto sm_err; ! 378: } ! 379: ! 380: if (rp_isbad (sm_waend ())) ! 381: goto sm_err; ! 382: ! 383: (void) sprintf (buffer, ! 384: "Date: %s\nFrom: %s\nTo: %s\nSubject: BBoards Failure\n\n", ! 385: dtimenow (), bb_from, bb_from); ! 386: if (rp_isbad (sm_wtxt (buffer, strlen (buffer)))) ! 387: goto sm_err; ! 388: ! 389: for (i = 0; bb[i]; i++) { ! 390: (void) sprintf (buffer, "BBoard %s\n", bb[i] -> bb_name); ! 391: if (rp_isbad (sm_wtxt (buffer, strlen (buffer)))) ! 392: goto sm_err; ! 393: } ! 394: ! 395: (void) lseek (bb_fderr, 0L, 0); ! 396: while ((i = read (bb_fderr, buffer, sizeof buffer)) > 0) ! 397: if (rp_isbad (sm_wtxt (buffer, i))) ! 398: goto sm_err; ! 399: ! 400: (void) strcpy (buffer, "\n------- Forwarded Message\n\n"); ! 401: if (rp_isbad (sm_wtxt (buffer, strlen (buffer))) || encap (fd) == NOTOK) ! 402: goto sm_err; ! 403: (void) strcpy (buffer, "\n------- End of Forwarded Message\n\n"); ! 404: if (rp_isbad (sm_wtxt (buffer, strlen (buffer)))) ! 405: goto sm_err; ! 406: ! 407: switch (sm_wtend ()) { ! 408: case RP_OK: ! 409: (void) unlink (bb_rept); ! 410: (void) sm_end (OK); ! 411: return; ! 412: ! 413: default: ! 414: sm_err: ; ! 415: adios (EX_UNAVAILABLE, NULLCP, ! 416: "failed and unable to post advisory, see %s for details", ! 417: bb_rept); ! 418: } ! 419: } ! 420: ! 421: /* */ ! 422: ! 423: /* very similar to sbr/cpydgst.c */ ! 424: ! 425: #define S1 0 ! 426: #define S2 1 ! 427: ! 428: #define output(c) if (bp >= dp) flush (), *bp++ = c; else *bp++ = c ! 429: #define flush() if ((j = bp - outbuf) \ ! 430: && rp_isbad (sm_wtxt (outbuf, j))) \ ! 431: return NOTOK; \ ! 432: else \ ! 433: bp = outbuf ! 434: ! 435: static int encap (fd) ! 436: register int fd; ! 437: { ! 438: register int i, ! 439: state; ! 440: register char *cp, ! 441: *ep; ! 442: char buffer[BUFSIZ]; ! 443: register int j; ! 444: register char *bp, ! 445: *dp; ! 446: char outbuf[BUFSIZ]; ! 447: ! 448: (void) lseek (fd, 0L, 0); ! 449: ! 450: dp = (bp = outbuf) + sizeof outbuf; ! 451: for (state = S1; (i = read (fd, buffer, sizeof buffer)) > 0;) ! 452: for (ep = (cp = buffer) + i; cp < ep; cp++) { ! 453: if (*cp == NULL) ! 454: continue; ! 455: switch (state) { ! 456: case S1: ! 457: if (*cp == '-') { ! 458: output ('-'); ! 459: output (' '); ! 460: } ! 461: state = S2; /* fall */ ! 462: ! 463: case S2: ! 464: output (*cp); ! 465: if (*cp == '\n') ! 466: state = S1; ! 467: break; ! 468: } ! 469: } ! 470: ! 471: if (i == NOTOK) ! 472: return NOTOK; ! 473: flush (); ! 474: ! 475: return OK; ! 476: } ! 477: #endif DISTRIBUTE ! 478: ! 479: /* */ ! 480: ! 481: #ifndef DISTRIBUTE ! 482: /* VARARGS1 */ ! 483: ! 484: static int lose (fmt, a, b, c, d) ! 485: char *fmt, ! 486: *a, ! 487: *b, ! 488: *c, ! 489: *d; ! 490: { ! 491: adios (EX_UNAVAILABLE, NULLCP, fmt, a, b, c, d);/* NOTREACHED */ ! 492: } ! 493: #endif not DISTRIBUTE ! 494: ! 495: /* */ ! 496: ! 497: static arginit (vec) ! 498: register char **vec; ! 499: { ! 500: register int i; ! 501: #ifdef MHMTS ! 502: register char *ap; ! 503: #endif MHMTS ! 504: char addr[BUFSIZ]; ! 505: register struct bboard *bp; ! 506: register struct passwd *pw; ! 507: ! 508: invo_name = r1bindex (*vec++, '/'); ! 509: m_foil (NULLCP); ! 510: mts_init (invo_name); ! 511: ! 512: #ifndef SPOP ! 513: if ((pw = getpwnam (BBOARDS)) == NULL) ! 514: adios (EX_OSFILE, NULLCP, "no entry for ~%s", BBOARDS); ! 515: #else SPOP ! 516: if ((pw = getpwnam (POPUID)) == NULL || !setpwinfo (pw, POPDB, 1)) ! 517: adios (EX_OSFILE, NULLCP, "%s", pw ? getbberr () : "POP user-id unknown"); ! 518: #endif SPOP ! 519: ! 520: if (pw -> pw_uid != geteuid ()) ! 521: #ifndef SPOP ! 522: adios (EX_OSERR, NULLCP, "not running setuid to %s", BBOARDS); ! 523: #else SPOP ! 524: adios (EX_OSERR, NULLCP, "not running setuid to %s", POPUID); ! 525: #endif SPOP ! 526: ! 527: bb_uid = pw -> pw_uid; ! 528: bb_gid = pw -> pw_gid; ! 529: #ifndef SPOP ! 530: (void) strcpy (bb_from, adrsprintf (pw -> pw_name, LocalName ())); ! 531: (void) strcpy (bb_home, pw -> pw_dir); ! 532: #endif not SPOP ! 533: ! 534: #ifdef MHMTS ! 535: vec += 3; ! 536: #endif MHMTS ! 537: if (*vec == NULL) ! 538: adios (EX_USAGE, NULLCP, "usage: %s %s [%s ...]", ! 539: invo_name, ENTITY, ENTITY); ! 540: ! 541: for (i = 0; *vec; vec++) { ! 542: #ifdef MHMTS ! 543: if (ap = index (*vec, '.')) ! 544: *vec = ++ap; ! 545: #endif MHMTS ! 546: make_lower (addr, *vec); ! 547: ! 548: if ((bp = getbbnam (addr)) == NULL ! 549: && (bp = getbbaka (addr)) == NULL) ! 550: adios (EX_NOUSER, NULLCP, "no such %s as %s", ENTITY, *vec); ! 551: if ((bb[i++] = getbbcpy (bp)) == NULL) ! 552: adios (EX_UNAVAILABLE, NULLCP, "insufficient memory on %s", *vec); ! 553: ! 554: if (i >= NBB - 1) ! 555: adios (EX_USAGE, NULLCP, "too many %ss, starting with %s", ! 556: ENTITY, *vec); ! 557: } ! 558: bb[i] = NULL; ! 559: ! 560: (void) umask (0022); ! 561: ! 562: bb_fderr = NOTOK; ! 563: } ! 564: ! 565: /* */ ! 566: ! 567: static int copyfile (qd, tmpfil) ! 568: int qd; ! 569: register char *tmpfil; ! 570: { ! 571: int i, ! 572: fd; ! 573: char buffer[BUFSIZ]; ! 574: ! 575: (void) strcpy (tmpfil, m_tmpfil (invo_name)); ! 576: if ((fd = creat (tmpfil, 0600)) == NOTOK) ! 577: adios (EX_CANTCREAT, tmpfil, "unable to create"); ! 578: (void) close (fd); ! 579: if ((fd = open (tmpfil, 2)) == NOTOK) ! 580: adios (EX_NOINPUT, tmpfil, "unable to re-open"); ! 581: ! 582: (void) lseek (qd, 0L, 0); ! 583: while ((i = read (qd, buffer, sizeof buffer)) > 0) ! 584: if (write (fd, buffer, i) != i) ! 585: adios (EX_IOERR, tmpfil, "error writing"); ! 586: if (i == NOTOK) ! 587: adios (EX_IOERR, "input", "error reading"); ! 588: ! 589: (void) lseek (fd, 0L, 0); ! 590: ! 591: return fd; ! 592: } ! 593: ! 594: /* */ ! 595: ! 596: /* VARARGS3 */ ! 597: ! 598: #ifdef MHMTS ! 599: /* ARGSUSED */ ! 600: #endif MHMTS ! 601: ! 602: static void adios (code, what, fmt, a, b, c, d, e, f) ! 603: int code; ! 604: char *what, ! 605: *fmt, ! 606: *a, ! 607: *b, ! 608: *c, ! 609: *d, ! 610: *e, ! 611: *f; ! 612: { ! 613: advise (what, fmt, a, b, c, d, e, f); ! 614: #ifdef SENDMTS ! 615: done (code); ! 616: #endif SENDMTS ! 617: #ifdef MHMTS ! 618: done (1); ! 619: #endif MHMTS ! 620: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.