diff support/pop/mmdfII/pop/po_wtmail.c @ 0:bce86c4163a3

Initial revision
author kono
date Mon, 18 Apr 2005 23:46:02 +0900
parents
children a6481689f99c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/support/pop/mmdfII/pop/po_wtmail.c	Mon Apr 18 23:46:02 2005 +0900
@@ -0,0 +1,777 @@
+#ifndef	POP
+/* bb_wtmail.c - write mail to a BBoard */
+#else	POP
+/* po_wtmail.c - write mail for a POP subscriber */
+#endif	POP
+#ifndef	lint
+static char Id[] = "@(#)$Id$";
+#endif
+
+
+#include "util.h"
+#include "mmdf.h"
+#include "bboards.h"
+#include "cnvtdate.h"
+#include "ch.h"
+#include "phs.h"
+#include <pwd.h>
+#include <sys/stat.h>
+
+/*  */
+
+#ifndef	RP_DOK
+#define	submitopts	"vmth%s*"
+#else	RP_DOK
+#define	submitopts	"vkmth%s*"
+#endif	RP_DOK
+
+#ifndef	POP
+#define	RP_NOPE	RP_AOK
+
+#define	MBXMODE	BBMODE
+#else	POP
+#define	RP_NOPE	RP_USER
+
+#define	MBXMODE	sentprotect
+
+extern int   sentprotect;
+#endif	POP
+
+
+int	err_fd = NOTOK;
+
+int     ds_address ();
+
+extern int  errno;
+
+int    bbrduid, bbrdgid;
+
+char   *chnlname,
+        chnlinfo[LINESIZE];
+#ifndef	POP
+char	bbrdaddr[LINESIZE],
+        bbrdfrom[LINESIZE],
+        bbrdheader[LINESIZE],
+	bbrdhome[LINESIZE],
+        bbrdtime[LINESIZE];
+#endif	not POP
+
+extern char *qu_msgfile,
+            *delim1,
+            *delim2,
+	    *lckdfldir,
+            *locdomain,
+            *locmachine,
+            *locname,
+	    *sitesignature,
+	    *supportaddr;
+
+struct bboard  *curbb;
+
+extern LLog *logptr;
+
+FILE *lk_fopen();
+
+off_t    lseek ();
+char   *index (), *rindex (), *sprintf ();
+struct passwd  *getpwnam ();
+
+/*  */
+
+bb_init (chanptr)
+Chan * chanptr;
+{
+    int     uid,
+            eid;
+    struct passwd *pw;
+
+#ifdef DEBUG
+    ll_log (logptr, LLOGBTR, "bb_init(chanptr=%s)", chanptr -> ch_name);
+#endif
+
+    chnlname = chanptr -> ch_name;
+#ifndef	notdef
+    sprintf (chnlinfo, submitopts, chnlname);
+#else	notdef			/* the following is probably a BAD idea */
+    if (chanptr -> ch_host == NULL)
+	chnlinfo[0] = NULL;	/* local delivery ONLY */
+    else
+	sprintf (chnlinfo, submitopts, chanptr -> ch_host);
+#endif	notdef
+
+#ifndef	POP
+    if ((pw = getpwnam (BBOARDS)) == NULL)
+	err_abrt (RP_BHST, "no passwd entry for '%s'", BBOARDS);
+#else	POP
+    if ((pw = getpwnam (POPUID)) == NULL)
+	err_abrt (RP_BHST, "no passwd entry for '%s'", POPUID);
+#endif	POP
+
+    bbrduid = pw -> pw_uid;
+    bbrdgid = pw -> pw_gid;
+#ifndef	POP
+    if (isstr (locmachine))
+	sprintf (bbrdfrom, "%s@%s.%s.%s", pw -> pw_name, locmachine, locname,
+		locdomain);
+    else
+	sprintf (bbrdfrom, "%s@%s.%s", pw -> pw_name, locname, locdomain);
+#ifdef DEBUG
+    ll_log (logptr, LLOGGEN, "distributing as '%s'", bbrdfrom);
+#endif
+    sprintf (bbrdhome, pw -> pw_dir);
+#endif	not POP
+
+#ifndef	POP
+    if (!setbbent ())
+	err_abrt (RP_BHST, "setbbent() failed");
+#else	POP
+    if (!setpwinfo (pw, POPDB, 1))
+	err_abrt (RP_BHST, "setbbinfo(%s, %s, 1) failed",
+		pw -> pw_name, POPDB);
+#endif	POP
+
+    getwho (&uid, &eid);
+    if (eid != 0)
+	err_abrt (RP_BHST, "not running as root");
+
+    return RP_OK;
+}
+
+
+bb_end (result)
+short   result;
+{
+#ifdef DEBUG
+    ll_log (logptr, LLOGBTR, "bb_end(result=0%o)", result);
+#endif
+
+    return RP_OK;
+}
+
+/*  */
+
+bb_sbinit () {
+#ifdef DEBUG
+    ll_log (logptr, LLOGBTR, "bb_sbinit()");
+#endif
+
+    return RP_OK;
+}
+
+
+bb_sbend () {
+#ifdef DEBUG
+    ll_log (logptr, LLOGBTR, "bb_sbend()");
+#endif
+
+    return RP_OK;
+}
+
+/*  */
+
+bb_winit (info, sender)
+char   *info,
+       *sender;
+{
+#ifdef DEBUG
+    ll_log (logptr, LLOGBTR, "bb_winit(info='%s',sender='%s')",
+	    info, sender);
+#endif
+
+    return RP_OK;
+}
+
+/*  */
+
+bb_wtadr (host, adr)
+char   *host,
+       *adr;
+{
+    short   count,
+            result;
+    int     len,
+	    md,
+            offset,
+	    size;
+    long    start,
+            stop,
+            pos;
+    char   *cp,
+            buffer[BUFSIZ];
+
+#ifdef DEBUG
+    ll_log (logptr, LLOGBTR, "bb_wtadr(host=%s,adr=%s)", host, adr);
+#endif
+
+    if ((cp = index (adr, '@')) != NULL)
+	*cp = NULL;
+    make_lower (adr, adr);
+    if ((curbb = getbbnam (adr)) == NULL)
+	return RP_USER;
+#ifndef	POP
+    if (isstr (locmachine))
+	sprintf (bbrdaddr, "local-%s-request@%s.%s.%s", curbb -> bb_name,
+		locmachine, locname, locdomain);
+    else
+	sprintf (bbrdaddr, "local-%s-request@%s.%s", curbb -> bb_name, locname,
+		locdomain);
+#endif	not POP
+#ifdef DEBUG
+    ll_log (logptr, LLOGGEN, "=> BBoard %s: file='%s' info='%s'",
+	    curbb -> bb_name, curbb -> bb_file, curbb -> bb_info);
+#endif
+
+    if (curbb -> bb_file == NULL || *curbb -> bb_file == NULL)
+	return RP_NOPE;
+#ifdef DEBUG
+    ll_log (logptr, LLOGGEN, "begin local delivery...");
+#endif
+    printx ("\r\nperforming local delivery to file %s...\n",
+	    curbb -> bb_file);
+
+    qu_rtinit (0L);
+
+    if ((md = mbx_open (curbb -> bb_file, bbrduid, bbrdgid, MBXMODE)) == NOTOK)
+	return RP_FIO;
+
+#ifndef	POP
+    if (rp_isbad (result = mbx_init ())) {
+	mbx_close (curbb -> bb_file, md);
+	return result;
+    }
+#endif	not POP
+
+    pos = (long) lseek (md, (off_t)0, 1);
+    count = strlen (delim1);
+    if (write (md, delim1, count) != count) {
+	ll_log (logptr, LLOGTMP, "error writing delim1");
+	result = NOTOK;
+	goto clean_up;
+    }
+    start = (long) lseek (md, (off_t)0, 1);
+    size = 0;
+
+#ifndef	POP
+    count = strlen (bbrdheader);
+    if (write (md, bbrdheader, count) != count) {
+	ll_log (logptr, LLOGTMP, "error writing BBoard information");
+	result = NOTOK;
+	goto clean_up;
+    }
+    for (cp = bbrdheader; *cp; cp++, size++)
+	if (*cp == '\n')
+	    size++;
+#endif	not POP
+
+    for (len = BUFSIZ;
+	    rp_gval (result = qu_rtxt (buffer, &len)) == RP_OK;
+	    len = BUFSIZ) {
+	for (offset = 0;
+		(offset = strindex (delim1, buffer)) >= 0;
+		buffer[offset]++)
+	    continue;
+	for (offset = 0;
+		(offset = strindex (delim2, buffer)) >= 0;
+		buffer[offset]++)
+	    continue;
+	if (write (md, buffer, len) != len) {
+	    ll_log (logptr, LLOGTMP, "error writing to file '%s'",
+		    curbb -> bb_file);
+	    result = NOTOK;
+	    goto clean_up;
+	}
+	for (offset = 0, cp = buffer; offset < len; offset++, size++)
+	    if (*cp++ == '\n')
+		size++;
+    }
+
+    if (result < 0)
+	ll_log (logptr, LLOGTMP, "error reading from message file '%s'",
+		qu_msgfile);
+clean_up: ;
+
+    stop = (long) lseek (md, (off_t)0, 1);
+    count = strlen (delim2);
+    if (write (md, delim2, count) != count)
+	ll_log (logptr, LLOGTMP, "error writing delim2");
+    map_write (curbb -> bb_file, md, curbb -> bb_maxima, start, stop, pos,
+	size, 0);
+#ifdef DEBUG
+    ll_log (logptr, LLOGGEN, "end local delivery...");
+#endif
+
+    if (result < 0)
+	mbx_close (curbb -> bb_file, md);
+    else
+	result = mbx_close (curbb -> bb_file, md);
+
+    return (result != NOTOK ? RP_OK : RP_FIO);
+}
+
+/*  */
+
+bb_txtcpy () {
+#ifndef	POP
+    short   result;
+
+#ifdef	DEBUG
+    ll_log (logptr, LLOGBTR, "bb_txtcpy()");
+#endif
+
+    if (curbb -> bb_dist == NULL
+	    || *curbb -> bb_dist == NULL
+	    || chnlinfo[0] == NULL)
+	return RP_MOK;
+#ifdef DEBUG
+    ll_log (logptr, LLOGGEN, "begin distribution...");
+#endif
+    if (curbb -> bb_file == NULL || *curbb -> bb_file == NULL)
+	printx ("\r\n");
+    printx("\rperforming remote distribution\n");
+
+    if (rp_isbad (result = dist_init ())
+	    || rp_isbad (result = dist_adrs ())
+	    || rp_isbad (result = dist_text ())
+	    || rp_isbad (result = dist_end ()))
+	return dist_lose (result);
+#ifdef DEBUG
+    ll_log (logptr, LLOGGEN, "end distribution...");
+#endif
+
+    if (err_fd != NOTOK)
+	dist_lose (RP_MOK);
+    else
+	printx ("\rmessage distributed\n");
+#endif	not POP
+
+    return RP_MOK;
+}
+
+/*  */
+
+#ifndef	POP
+/* **************** (dist_)  BBOARD DISTRIBUTION **************** */
+
+dist_init () {
+    short   result;
+#ifdef	RP_NS
+    int	    len;
+    struct rp_bufstruct reply;
+#endif	RP_NS
+
+#ifdef DEBUG
+    ll_log (logptr, LLOGBTR, "dist_init()");
+#endif
+
+    if (rp_isbad (result = mm_init ()))
+	return ds_log (result, LLOGFAT, "mm_init() failed [%s]",
+		rp_valstr (result));
+    if (rp_isbad (result = mm_sbinit ()))
+	return ds_log (result, LLOGFAT, "mm_sbinit() failed [%s]",
+		rp_valstr (result));
+    if (rp_isbad (result = mm_winit (chnlname, chnlinfo, bbrdaddr)))
+	return ds_log (result, LLOGFAT,
+		"mm_winit('%s','%s','%s') failed [%s]",
+		chnlname, chnlinfo, bbrdaddr, rp_valstr (result));
+#ifdef	RP_NS
+	if (rp_isbad (result = mm_rrply (&reply, &len)))
+	    return ds_log (result, LLOGFAT, "problem with sender address [%s]",
+		    rp_valstr (result));
+#endif	RP_NS
+
+    return result;
+}
+
+/*  */
+
+dist_adrs ()
+{
+    short   result;
+
+#ifdef DEBUG
+    ll_log (logptr, LLOGBTR, "dist_adrs()");
+#endif
+
+    if (getbbdist (curbb, ds_address))
+	return ds_log (RP_NO, LLOGTMP, "getbbdist failed: %s", getbberr ());
+
+    if (rp_isbad (result = mm_waend ()))
+	return ds_log (result, LLOGFAT, "mm_waend() failed [%s]",
+		rp_valstr (result));
+
+    return result;
+}
+
+/*  */
+
+ds_address (addr, host)
+char *addr,			/* local part */
+     *host;			/* rest */
+{
+    short   result;
+    int     len;
+    struct rp_bufstruct reply;
+
+#ifdef DEBUG
+    ll_log (logptr, LLOGBTR, "ds_address(addr='%s',host='%s')", addr, host);
+#endif
+
+    printx ("\rperforming distribution to %s@%s...\n", addr, host);
+    if (rp_isbad (result = mm_wadr (host, addr))) {
+	ds_log (result, LLOGFAT, "mm_wadr('%s','%s') failed [%s]",
+		host, addr, rp_valstr (result));
+	return NOTOK;
+    }
+    if (rp_isbad (result = mm_rrply (&reply, &len))) {
+	ds_log (result, LLOGFAT,
+		"mm_rrply() failed [%s] getting status of '%s@%s'",
+		rp_valstr (result), addr, host);
+	return NOTOK;
+    }
+
+    switch (rp_gval (reply.rp_val)) {
+	case RP_AOK:
+#ifdef	RP_DOK
+	case RP_DOK:
+#endif	RP_DOK
+#ifdef DEBUG
+	    ll_log (logptr, LLOGGEN, "address '%s@%s' [%s] -- %s",
+		    addr, host, rp_valstr (reply.rp_val), reply.rp_line);
+#endif
+	    return OK;
+
+	case RP_NO:
+#ifdef	RP_NS
+	case RP_NS:
+#endif	RP_NS
+	case RP_USER:
+	case RP_NDEL:
+	case RP_AGN:
+	case RP_NOOP:
+	    ds_log (reply.rp_val, LLOGTMP, "address '%s@%s' [%s] -- %s",
+		    addr, host, rp_valstr (reply.rp_val), reply.rp_line);
+	    return OK;		/* fail-soft */
+
+	default:
+	    ds_log (reply.rp_val, LLOGFAT, "unexpected reply [%s] -- %s",
+		    rp_valstr (reply.rp_val), reply.rp_line);
+	    return NOTOK;
+    }
+}
+
+/*  */
+
+dist_text ()
+{
+    short   result;
+    int     len;
+    char    buffer[BUFSIZ];
+
+#ifdef DEBUG
+    ll_log (logptr, LLOGBTR, "dist_text()");
+#endif
+
+    qu_rtinit (0L);
+    for (len = BUFSIZ;
+	    rp_gval (result = qu_rtxt (buffer, &len)) == RP_OK;
+	    len = BUFSIZ)
+	if (rp_isbad (result = mm_wtxt (buffer, len)))
+	    return ds_log (result, LLOGFAT, "mm_wtxt() failed [%s]",
+		    rp_valstr (result));
+
+    if (result < 0)
+	return ds_log (RP_FIO, LLOGTMP,
+		"error reading from message file '%s'", qu_msgfile);
+
+    if (rp_isbad (result = mm_wtend ()))
+	return ds_log (result, LLOGFAT, "mm_wtend() failed [%s]",
+		rp_valstr (result));
+
+    return result;
+}
+
+/*  */
+
+dist_end ()
+{
+    short   result;
+    int     len;
+    struct rp_bufstruct reply;
+
+#ifdef DEBUG
+    ll_log (logptr, LLOGBTR, "dist_end()");
+#endif
+
+    if (rp_isbad (result = mm_rrply (&reply, &len)))
+	return ds_log (result, LLOGFAT,
+		"mm_rrply() failed [%s] getting final status",
+		rp_valstr (result));
+
+    switch (rp_gval (reply.rp_val)) {
+	case RP_OK:
+	case RP_MOK:
+#ifdef DEBUG
+	    ll_log (logptr, LLOGGEN, "message [%s] -- %s",
+		    rp_valstr (reply.rp_val), reply.rp_line);
+#endif
+	    mm_sbend ();
+	    mm_end (OK);
+	    return result;
+
+	case RP_NO:
+	case RP_NDEL:
+	case RP_AGN:
+	case RP_NOOP:
+	    return ds_log (RP_NO, LLOGTMP, "not delivered [%s] -- %s",
+		    rp_valstr (reply.rp_val), reply.rp_line);
+
+	default:
+	    return ds_log (RP_RPLY, LLOGFAT,
+		    "unexpected final reply [%s] -- %s",
+		    rp_valstr (reply.rp_val), reply.rp_line);
+    }
+}
+
+/*  */
+
+dist_lose (result)
+short   result;
+{
+    int     i;
+    char   *cp,
+            intro[BUFSIZ],
+            buffer[BUFSIZ];
+
+#ifdef	DEBUG
+    ll_log (logptr, LLOGBTR, "dist_lose(result=0%o)", result);
+#endif	DEBUG
+
+    mm_end (NOTOK);
+
+    printx ("\rerrors during distribution: ");
+    if (domsg)
+	(void) fflush (stdout);
+    (void) sprintf (intro, "bboards%d distribution for %s failed [%s]\n",
+	    getpid (), curbb -> bb_name, rp_valstr (result));
+    if (loseaux (bbrdaddr, bbrdfrom, intro) != OK
+	    && loseaux (bbrdfrom, (char *) 0, intro) != OK) {
+	printx ("unable to post advisory.\n");
+	ll_log (logptr, LLOGFAT, "unable to post failure notice");
+	if (err_fd != NOTOK) {
+	    (void) lseek (err_fd, (off_t)0, 0);
+	    if ((i = read (err_fd, buffer, sizeof buffer)) > 0) {
+		buffer[i] = NULL;
+		if (cp = index (buffer, '\n'))
+		    *cp = NULL;
+		ll_log (logptr, LLOGFAT, "info: %s", buffer);
+	    }
+	}
+	if (loseaux (supportaddr, (char *) 0, intro) != NOTOK)
+	    ll_log (logptr, LLOGFAT, "unable to advise %s of failure!",
+		    supportaddr);
+    }
+    else
+	printx ("advisory posted.\n");
+    if (domsg)
+	(void) fflush (stdout);
+
+    if (err_fd != NOTOK) {
+	close (err_fd);
+	err_fd = NOTOK;
+    }
+    return RP_MOK;
+}
+
+/*  */
+
+int	loseaux (to, cc, intro)
+char   *to,
+       *cc,
+       *intro;
+{
+    int     i;
+    char    buffer[BUFSIZ];
+
+    if (ml_init (NO, NO, sitesignature, "Re-distribution Failure") != OK
+	    || ml_adr (to) != OK)
+	return NOTOK;
+    if (cc && (ml_cc () != OK || ml_adr (cc) != OK))
+	return NOTOK;
+    if (ml_aend () != OK || ml_tinit () != OK)
+	return NOTOK;
+
+    ml_txt (intro);
+    if (err_fd != NOTOK) {
+	lseek (err_fd, (off_t)0, 0);
+	while ((i = read (err_fd, buffer, sizeof buffer)) > 0) {
+	    buffer[i] = NULL;
+	    ml_txt (buffer);
+	}
+    }
+    encap ();
+
+    return ml_end (OK);
+}
+
+/*  */
+
+/* very similar to sbr/cpydgst.c */
+
+#define	S1	0
+#define	S2	1
+
+#define	output(c)	if (bp >= dp) {flush (); *bp++ = c;} else *bp++ = c
+#define	flush()		if (bp - outbuf) \
+			    *bp = NULL, ml_txt (outbuf), bp = outbuf
+
+static  encap () {
+    register int    state;
+    short   result;
+    int     len,
+	    init;
+    register char  *cp,
+                   *ep;
+    char    buffer[BUFSIZ];
+    register char  *bp,
+                   *dp;
+    char    outbuf[BUFSIZ];
+
+    qu_rtinit (0L);
+
+    dp = (bp = outbuf) + sizeof outbuf;
+    init = 0;
+    for (state = S1, len = BUFSIZ;
+	    rp_gval (result = qu_rtxt (buffer, &len)) == RP_OK;
+	    len = BUFSIZ)
+	for (ep = (cp = buffer) + len; cp < ep; cp++) {
+	    if (*cp == NULL)
+		continue;
+	    switch (state) {
+		case S1: 
+		    if (*cp == '-') {
+			if (init == 0) {
+			    ml_txt ("\n------- Forwarded Message\n\n");
+			    init++;
+			}
+			output ('-');
+			output (' ');
+		    }
+		    state = S2;	/* fall */
+
+		case S2: 
+		    if (init == 0) {
+			ml_txt ("\n------- Forwarded Message\n\n");
+			init++;
+		    }
+		    output (*cp);
+		    if (*cp == '\n')
+			state = S1;
+		    break;
+	    }
+	}
+
+    flush ();
+
+    if (result < 0) {
+	ll_log (logptr, LLOGTMP, "error reading message when noting failure");
+	if (init)
+	    ml_txt ("\n------- End of Forwarded Message\n\n");
+	ml_txt ("[ error reading message ]\n");
+    }
+    else
+	if (init)
+	    ml_txt ("\n------- End of Forwarded Message\n\n");
+	else {
+	    ll_log (logptr, LLOGTMP, "message empty when noting failure");
+	    ml_txt ("[ message empty ]\n");
+	}
+}
+
+/*  */
+
+/* VARARGS3 */
+
+ds_log (result, level, fmt, a, b, c, d, e)
+short   result;
+int     level;
+char   *fmt,
+       *a,
+       *b,
+       *c,
+       *d,
+       *e;
+{
+    int     i;
+    char    buffer[BUFSIZ],
+	    tmpfil[BUFSIZ];
+
+    ll_log (logptr, level, fmt, a, b, c, d, e);
+
+    sprintf (buffer, fmt, a, b, c, d, e);
+    strcat (buffer, "\n");
+
+    printx ("\rerror: %s", buffer);
+
+    if (err_fd == NOTOK) {
+	unlink (mktemp (strcpy (tmpfil, "/tmp/bboardsXXXXXX")));
+	if ((err_fd = creat (tmpfil, 0600)) == NOTOK)
+	    return result;
+	close (err_fd);
+	if ((err_fd = open (tmpfil, 2)) == NOTOK)
+	    return result;
+	unlink (tmpfil);
+	lseek (err_fd, (off_t)0, 0);
+    }
+    i = strlen (buffer);
+    write (err_fd, buffer, i);
+
+    return result;
+}
+#endif	not POP
+
+/*  */
+
+/* mbx_	    local mailbox routines */
+
+#ifndef	POP
+mbx_init () {
+    int     fd,
+            clear;
+    char    name[BUFSIZ];
+    FILE * fp;
+
+    if ((fd = mbx_Xopen (curbb -> bb_info, bbrduid, bbrdgid, MBXMODE, &clear))
+	    == NOTOK) {
+	if (errno == ETXTBSY) {
+	    printx ("\runable to lock %s\n", curbb -> bb_info);
+	    ll_err (logptr, LLOGTMP, "unable to lock %s",
+		    curbb -> bb_info);
+	    return RP_LOCK;
+	}
+	printx ("\runable to open '%s'", curbb -> bb_info);
+	ll_log (logptr, LLOGTMP, "unable to open '%s'", curbb -> bb_info);
+	return RP_FOPN;
+    }
+    if ((fp = fdopen (fd, "w")) == (FILE *) NULL) {
+	printx ("\runable to fdopen '%s'", curbb -> bb_info);
+	ll_err (logptr, LLOGTMP, "unable to fdopen '%s'", curbb -> bb_info);
+	mbx_close (curbb -> bb_info, fd);
+	return RP_LIO;
+    }
+
+    strcpy (name, curbb -> bb_name);
+    if ((curbb = getbbnam (name)) == (struct bboard *) NULL) {
+	printx ("\runable to get information on BBoard %s\n", name);
+	ll_err (logptr, LLOGFAT, "unable to get info on %s", name);
+	lkfclose (fp, curbb -> bb_info);
+	return RP_LIO;
+    }
+    sprintf (bbrdheader, "BBoard-ID: %d\nBB-Posted: %s\n",
+	    ++curbb -> bb_maxima, cnvtdate (TIMREG, bbrdtime));
+    fprintf (fp, "%d\n%s\n", curbb -> bb_maxima, bbrdtime);
+
+    lkfclose (fp, curbb -> bb_info);
+
+    return RP_OK;
+}
+#endif	not POP