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