diff uip/dropsbr.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/uip/dropsbr.c	Mon Apr 18 23:46:02 2005 +0900
@@ -0,0 +1,753 @@
+/* dropsbr.c - write to a mailbox */
+#ifndef	lint
+static char ident[] = "@(#)$Id$";
+#endif	/* lint */
+
+#include <stdio.h>
+#ifndef	MMDFONLY
+#include "../h/mh.h"
+#include "../h/dropsbr.h"
+#include "../zotnet/mts.h"
+#else	/* MMDFONLY */
+#include "dropsbr.h"
+#include "strings.h"
+#include "mmdfonly.h"
+#endif	/* MMDFONLY */
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if     (defined(BSD42) || defined(SOCKETS)) && defined(NTOHLSWAP)
+#undef NULLVP
+#include <netinet/in.h>
+#else
+#define	ntohl(n) (n)
+#endif
+
+
+#define	MMDF	1
+#define	UUCP	2
+
+/*  */
+
+static	int	mbx_style = MMDF;
+
+static int	mbx_create(), mbx_chk(), map_open();
+
+extern int  errno;
+
+off_t   lseek ();
+
+/*  */
+
+int     mbx_mmdf () {
+    int     style = mbx_style;
+
+    mbx_style = MMDF;
+    return style;
+}
+
+
+int     mbx_uucp () {
+    int     style = mbx_style;
+
+    mbx_style = UUCP;
+    return style;
+}
+
+/*  */
+
+int     mbx_open (file, uid, gid, mode)
+char   *file;
+int     uid,
+        gid,
+	mode;
+{
+    int     clear,
+            fd;
+
+    if ((fd = mbx_Xopen (file, uid, gid, mode, &clear)) == NOTOK)
+	return fd;
+
+    if (!clear)
+	switch (mbx_style) {
+	    case MMDF: 
+	    default: 
+		if (mbx_chk (fd) == NOTOK) {
+		    (void) close (fd);
+		    return NOTOK;
+		}
+		break;
+
+	    case UUCP: 
+		if (lseek (fd, (off_t)0, 2) == (off_t) NOTOK) {
+		    (void) close (fd);
+		    return NOTOK;
+		}
+		break;
+	}
+
+    return fd;
+}
+
+/*  */
+
+int	mbx_Xopen (file, uid, gid, mode, clear)
+char   *file;
+int	uid,
+	gid,
+	mode,
+       *clear;
+{
+    register int j;
+    int	    count,
+            fd;
+    struct stat st;
+
+    for (*clear = 0, count = 4, j = 0; count > 0; count--)
+	if ((fd = lkopen (file, 6)) == NOTOK)
+	    switch (errno) {
+		case ENOENT: 
+		    if (mbx_create (file, uid, gid, mode) == NOTOK)
+			return NOTOK;
+		    (*clear)++;
+		    break;
+
+#ifdef	BSD42
+		case EWOULDBLOCK:
+#endif	/* BSD42 */
+		case ETXTBSY: 
+		    j = errno;
+		    sleep (5);
+		    break;
+
+		default: 
+		    return NOTOK;
+	    }
+	else {
+	    *clear = fstat (fd, &st) != NOTOK && st.st_size == (off_t)0;
+	    break;
+	}
+
+    errno = j;
+    return fd;
+}
+
+/*  */
+
+static int  mbx_create (file, uid, gid, mode)
+char   *file;
+int     uid,
+        gid,
+	mode;
+{
+    int     fd;
+
+    if ((fd = creat (file, 0600)) == NOTOK)
+	return NOTOK;
+
+    (void) close (fd);
+    (void) chown (file, uid, gid);
+    (void) chmod (file, mode);
+
+    return OK;
+}
+
+
+static int  mbx_chk (fd)
+int     fd;
+{
+    int     count;
+    char    ldelim[BUFSIZ];
+
+    count = strlen (mmdlm2);
+
+    if (lseek (fd, (off_t) (-count), 2) == (off_t) NOTOK
+	    || read (fd, ldelim, count) != count)
+	return NOTOK;
+    ldelim[count] = 0;
+
+    if (strcmp (ldelim, mmdlm2)
+	    && write (fd, "\n", 1) != 1
+	    && write (fd, mmdlm2, count) != count)
+	return NOTOK;
+
+    return OK;
+}
+
+/*  */
+
+int	mbx_read (fp, pos, drops, noisy)
+register FILE  *fp;
+register long	pos;
+struct drop **drops;
+int	noisy;
+{
+    register int    len,
+                    size;
+    register long     ld1,
+		    ld2;
+    register char  *bp;
+    char    buffer[BUFSIZ];
+    register struct drop   *cp,
+                           *dp,
+                           *ep,
+                           *pp;
+
+    pp = (struct drop  *) calloc ((unsigned) (len = MAXFOLDER), sizeof *dp);
+    if (pp == NULL) {
+	if (noisy)
+	    admonish (NULLCP, "unable to allocate drop storage");
+	return NOTOK;
+    }
+
+    ld1 = (long) strlen (mmdlm1);
+    ld2 = (long) strlen (mmdlm2);
+
+    (void) fseek (fp, pos, 0);
+    for (ep = (dp = pp) + len - 1; fgets (buffer, sizeof buffer, fp);) {
+	size = 0;
+	if (strcmp (buffer, mmdlm1) == 0)
+	    pos += ld1, dp -> d_start = (long) pos;
+	else {
+	    dp -> d_start = (long)pos , pos += (long) strlen (buffer);
+	    for (bp = buffer; *bp; bp++, size++)
+		if (*bp == '\n')
+		    size++;
+	}
+
+	while (fgets (buffer, sizeof buffer, fp) != NULL)
+	    if (strcmp (buffer, mmdlm2) == 0)
+		break;
+	    else {
+		pos += (long) strlen (buffer);
+		for (bp = buffer; *bp; bp++, size++)
+		    if (*bp == '\n')
+			size++;
+	    }
+
+	if (dp -> d_start != (long) pos) {
+	    dp -> d_id = 0;
+	    dp -> d_size = (long) size;
+	    dp -> d_stop = (long) pos;
+	    dp++;
+	}
+	pos += ld2;
+
+	if (dp >= ep) {
+	    register int    curlen = dp - pp;
+
+	    cp = (struct drop  *) realloc ((char *) pp,
+		                    (unsigned) (len += MAXFOLDER) * sizeof *pp);
+	    if (cp == NULL) {
+		if (noisy)
+		    admonish (NULLCP, "unable to allocate drop storage");
+		free ((char *) pp);
+		return 0;
+	    }
+	    dp = cp + curlen, ep = (pp = cp) + len - 1;
+	}
+    }
+
+    if (dp == pp)
+	free ((char *) pp);
+    else
+	*drops = pp;
+    return (dp - pp);
+}
+
+/*  */
+
+int	mbx_write (mailbox, md, fp, id, last, pos, stop, mapping, noisy)
+char   *mailbox;
+register FILE *fp;
+int     md,
+	id,
+	mapping,
+	noisy;
+long	last;
+register long	pos,
+		stop;
+{
+    register int    i,
+                    j,
+                    size;
+    long   	    start,
+                    off;
+    register char  *cp;
+    char    buffer[BUFSIZ];
+
+    off = (long) lseek (md, (off_t)0, 1);
+    j = strlen (mmdlm1);
+    if (write (md, mmdlm1, j) != j)
+	return NOTOK;
+    start = (long) lseek (md, (off_t)0, 1);
+    size = 0;
+
+    (void) fseek (fp, pos, 0);
+    while (fgets (buffer, sizeof buffer, fp) != NULL && pos < stop) {
+	i = strlen (buffer);
+	for (j = 0; (j = stringdex (mmdlm1, buffer)) >= 0; buffer[j]++)
+	    continue;
+	for (j = 0; (j = stringdex (mmdlm2, buffer)) >= 0; buffer[j]++)
+	    continue;
+	if (write (md, buffer, i) != i)
+	    return NOTOK;
+	pos += (long) i;
+	if (mapping)
+	    for (cp = buffer; i-- > 0; size++)
+		if (*cp++ == '\n')
+		    size++;
+    }
+
+    stop = (long) lseek (md, (off_t)0, 1);
+    j = strlen (mmdlm2);
+    if (write (md, mmdlm2, j) != j)
+	return NOTOK;
+    if (mapping)
+	(void) map_write (mailbox, md, id, last, start, stop, off, size, noisy);
+
+    return OK;
+}
+
+/*  */
+
+int     mbx_copy (mailbox, md, fd, mapping, text, noisy)
+char   *mailbox;
+int     md,
+        fd,
+	mapping,
+	noisy;
+char   *text;
+{
+    register int    i,
+                    j,
+                    size;
+    long           start,
+                    stop,
+                    pos;
+    register char  *cp;
+    char    buffer[BUFSIZ];
+    register FILE  *fp;
+
+    pos = (long) lseek (md, (off_t)0, 1);
+    size = 0;
+
+    switch (mbx_style) {
+	case MMDF: 
+	default: 
+	    j = strlen (mmdlm1);
+	    if (write (md, mmdlm1, j) != j)
+		return NOTOK;
+	    start = (long) lseek (md, (off_t)0, 1);
+
+	    if (text) {
+		i = strlen (text);
+		if (write (md, text, i) != i)
+		    return NOTOK;
+		for (cp = text; *cp++; size++)
+		    if (*cp == '\n')
+			size++;
+	    }
+		    
+	    while ((i = read (fd, buffer, sizeof buffer)) > 0) {
+		for (j = 0;
+			(j = stringdex (mmdlm1, buffer)) >= 0;
+			buffer[j]++)
+		    continue;
+		for (j = 0;
+			(j = stringdex (mmdlm2, buffer)) >= 0;
+			buffer[j]++)
+		    continue;
+		if (write (md, buffer, i) != i)
+		    return NOTOK;
+		if (mapping)
+		    for (cp = buffer; i-- > 0; size++)
+			if (*cp++ == '\n')
+			    size++;
+	    }
+
+	    stop = (long) lseek (md, (off_t)0, 1);
+	    j = strlen (mmdlm2);
+	    if (write (md, mmdlm2, j) != j)
+		return NOTOK;
+	    if (mapping)
+		(void) map_write (mailbox, md, 0, (long)0, start, stop, pos, size,
+			    noisy);
+
+	    return (i != NOTOK ? OK : NOTOK);
+
+	case UUCP: 		/* I hate this... */
+	    if ((j = dup (fd)) == NOTOK)
+		return NOTOK;
+	    if ((fp = fdopen (j, "r")) == NULL) {
+		(void) close (j);
+		return NOTOK;
+	    }
+	    start = (long) lseek (md, (off_t)0, 1);
+
+	    if (text) {
+		i = strlen (text);
+		if (write (md, text, i) != i)
+		    return NOTOK;
+		for (cp = text; *cp++; size++)
+		    if (*cp == '\n')
+			size++;
+	    }
+		    
+	    for (j = 0; fgets (buffer, sizeof buffer, fp) != NULL; j++) {
+#ifndef CONTENT_LENGTH
+		if (j != 0 && strncmp (buffer, "From ", 5) == 0) {
+		    (void) write (md, ">", 1);
+		    size++;
+		}
+#endif
+		i = strlen (buffer);
+		if (write (md, buffer, i) != i) {
+		    (void) fclose (fp);
+		    return NOTOK;
+		}
+		if (mapping)
+		    for (cp = buffer; i-- > 0; size++)
+			if (*cp++ == '\n')
+			    size++;
+	    }
+	    if (write (md, "\n", 1) != 1) {
+		(void) fclose (fp);
+		return NOTOK;
+	    }
+	    if (mapping) size += 2;
+
+	    (void) fclose (fp);
+	    (void) (long) lseek (fd, (off_t)0, 2);
+	    stop = (long) lseek (md, (off_t)0, 1);
+	    if (mapping)
+		(void) map_write (mailbox, md, 0, (long)0, start, stop, pos, size,
+			    noisy);
+
+	    return OK;
+    }
+}
+
+/*  */
+
+int 	mbx_size (md, start, stop)
+int	md;
+long	start,
+	stop;
+{
+    register int    i,
+                    fd;
+    register long   pos;
+    register FILE  *fp;
+
+    if ((fd = dup (md)) == NOTOK || (fp = fdopen (fd, "r")) == NULL) {
+	if (fd != NOTOK)
+	    (void) close (fd);
+	return NOTOK;
+    }
+
+    (void) fseek (fp, start, 0);
+    for (i = 0, pos = stop - start; pos-- > 0; i++)
+	if (fgetc (fp) == '\n')
+	    i++;
+
+    (void) fclose (fp);
+
+    return i;
+}
+
+/*  */
+
+int     mbx_close (mailbox, md)
+char   *mailbox;
+int     md;
+{
+    (void) lkclose (md, mailbox);
+
+    return OK;
+}
+
+/*  */
+
+/* This function is performed implicitly by getbbent.c:
+
+		bb -> bb_map = map_name (bb -> bb_file);
+*/
+
+char    *map_name (file)
+register char	*file;
+{
+    register char  *cp;
+    static char buffer[BUFSIZ];
+
+    if ((cp = r1bindex (file, '/')) == file)
+	(void) sprintf (buffer, ".%s.map", cp);
+    else
+	(void) sprintf (buffer, "%.*s.%s.map", cp - file, file, cp);
+
+    return buffer;
+}
+
+/*  */
+
+int	map_read (file, pos, drops, noisy)
+char   *file;
+long	pos;
+struct drop **drops;
+int	noisy;
+{
+    register int    i, j,
+                    md,
+                    msgp;
+    register char  *cp;
+    struct drop d;
+    register struct drop   *mp,
+                           *dp;
+
+    if ((md = open (cp = map_name (file), 0)) == NOTOK
+	    || map_chk (cp, md, mp = &d, pos, noisy)) {
+	if (md != NOTOK)
+	    (void) close (md);
+	return 0;
+    }
+
+    msgp = mp -> d_id;
+    dp = (struct drop  *) calloc ((unsigned) (msgp + 1), sizeof *dp);
+    if (dp == NULL) {
+	(void) close (md);
+	return 0;
+    }
+
+    bcopy ((char *) mp, (char *) dp, sizeof *dp);
+
+    (void) lseek (md, (off_t) sizeof *mp, 0);
+    if ((i = read (md, (char *) (dp + 1), msgp * sizeof *dp)) < sizeof *dp) {
+	i = 0;
+	free ((char *) dp);
+    }
+    else {
+#ifdef	NTOHLSWAP
+	register struct drop *tdp;
+	for (j = 0, tdp = dp; j <= i / sizeof(*dp); j++, tdp++) {
+	    tdp->d_id = ntohl(tdp->d_id);
+	    tdp->d_size = ntohl(tdp->d_size);
+	    tdp->d_start = ntohl(tdp->d_start);
+	    tdp->d_stop = ntohl(tdp->d_stop);
+	}
+#endif
+	*drops = dp;
+    }
+
+    (void) close (md);
+
+    return (i / sizeof *dp);
+}
+
+/*  */
+
+int     map_write (mailbox, md, id, last, start, stop, pos, size, noisy)
+register char   *mailbox;
+int     md,
+        id,
+	size,
+	noisy;
+long   last,
+	start,
+        stop,
+        pos;
+{
+    register int    i;
+    int     clear,
+            fd,
+            td;
+    char   *file;
+    register struct drop   *dp;
+    struct drop    d1,
+		   d2,
+                  *rp;
+    register FILE *fp;
+
+    if ((fd = map_open (file = map_name (mailbox), &clear, md)) == NOTOK)
+	return NOTOK;
+
+    if (!clear && map_chk (file, fd, &d1, pos, noisy)) {
+	(void) unlink (file);
+	(void) mbx_close (file, fd);
+	if ((fd = map_open (file, &clear, md)) == NOTOK)
+	    return NOTOK;
+	clear++;
+    }
+
+    if (clear) {
+	if ((td = dup (md)) == NOTOK || (fp = fdopen (td, "r")) == NULL) {
+	    if (noisy)
+		admonish (file, "unable to %s", td != NOTOK ? "fdopen" : "dup");
+	    if (td != NOTOK)
+		(void) close (td);
+	    (void) mbx_close (file, fd);
+	    return NOTOK;
+	}
+
+	switch (i = mbx_read (fp, 0L, &rp, noisy)) {
+	    case NOTOK:
+		(void) fclose (fp);
+		(void) mbx_close (file, fd);
+		return NOTOK;
+
+	    case OK:
+		break;
+
+	    default:
+		d1.d_id = 0;
+		for (dp = rp; i-- >0; dp++) {
+		    if (dp -> d_start == start)
+			dp -> d_id = id;
+#ifdef NTOHLSWAP
+		    dp -> d_id = htonl(dp -> d_id);
+		    dp -> d_size = htonl(dp -> d_size);
+		    dp -> d_start = htonl(dp -> d_start);
+		    dp -> d_stop = htonl(dp -> d_stop);
+#endif
+		    (void) lseek (fd, (off_t) (++d1.d_id * sizeof *dp), 0);
+		    if (write (fd, (char *) dp, sizeof *dp) != sizeof *dp) {
+			if (noisy)
+			    admonish (file, "write error");
+			(void) mbx_close (file, fd);
+			(void) fclose (fp);
+			return NOTOK;
+		    }
+		}
+		free ((char *) rp);
+		break;
+	}
+    }
+    else {
+	if (last == 0)
+	    last = d1.d_start;
+	dp = &d2;
+#ifdef NTOHLSWAP
+	dp -> d_id = htonl(id);
+	dp -> d_size = htonl((long) (size ? size : mbx_size (fd, start, stop)));
+	dp -> d_start = htonl((long) start);
+	dp -> d_stop = htonl((long) stop);
+#else
+	dp -> d_id = id;
+	dp -> d_size = (long) (size ? size : mbx_size (fd, start, stop));
+	dp -> d_start = (long) start;
+	dp -> d_stop = (long) stop;
+#endif
+	(void) lseek (fd, (off_t) (++d1.d_id * sizeof *dp), 0);
+	if (write (fd, (char *) dp, sizeof *dp) != sizeof *dp) {
+	    if (noisy)
+		admonish (file, "write error");
+	    (void) mbx_close (file, fd);
+	    return NOTOK;
+	}
+    }
+
+    dp = &d1;
+#ifdef NTOHLSWAP
+    dp -> d_id = htonl(dp -> d_id);
+    dp -> d_size = htonl(DRVRSN);
+    dp -> d_start = htonl((long) last);
+    dp -> d_stop = htonl((long) lseek (md, (off_t)0, 1));
+#else
+    dp -> d_size = DRVRSN;
+    dp -> d_start = (long) last;
+    dp -> d_stop = (long) lseek (md, (off_t)0, 1);
+#endif
+
+    (void) lseek (fd, (off_t)0, 0);
+    if (write (fd, (char *) dp, sizeof *dp) != sizeof *dp) {
+	if (noisy)
+	    admonish (file, "write error");
+	(void) mbx_close (file, fd);
+	return NOTOK;
+    }
+
+    (void) mbx_close (file, fd);
+
+    return OK;
+}
+
+/*  */
+
+static int  map_open (file, clear, md)
+char   *file;
+int    *clear,
+	md;
+{
+    int	    mode;
+    struct  stat st;
+
+    mode = fstat (md, &st) != NOTOK ? (int) (st.st_mode & 0777) : m_gmprot ();
+    return mbx_Xopen (file, st.st_uid, st.st_gid, mode, clear);
+}
+
+/*  */
+
+int  map_chk (file, fd, dp, pos, noisy)
+char   *file;
+int     fd,
+	noisy;
+register struct drop *dp;
+long	pos;
+{
+    long    count;
+    struct drop d, tmpd;
+    register struct drop    *dl;
+
+    if (read (fd, (char *) &tmpd, sizeof *dp) != sizeof *dp) {
+#ifdef	notdef
+	admonish (NULLCP, "%s: missing or partial index", file);
+#endif	/* notdef */
+	return NOTOK;
+    }
+#ifndef	NTOHLSWAP
+    *dp = tmpd;		/* if ntohl(n)=(n), can use struct assign */
+#else
+    dp->d_id = ntohl(tmpd.d_id);
+    dp->d_size = ntohl(tmpd.d_size);
+    dp->d_start = ntohl(tmpd.d_start);
+    dp->d_stop = ntohl(tmpd.d_stop);
+#endif
+    
+    if (dp -> d_size != DRVRSN) {
+	if (noisy)
+	    admonish (NULLCP, "%s: version mismatch (%d != %d)", file,
+				dp->d_size, DRVRSN);
+	return NOTOK;
+    }
+
+    if (dp -> d_stop != (long) pos) {
+	if (noisy && pos != (long)0)
+	    admonish (NULLCP,
+		    "%s: pointer mismatch or incomplete index (%ld!=%ld)", 
+		    file, dp -> d_stop, (long) pos);
+	return NOTOK;
+    }
+
+    if ((long) ((dp -> d_id + 1) * sizeof *dp) != (long) lseek (fd, (off_t)0, 2)) {
+	if (noisy)
+	    admonish (NULLCP, "%s: corrupt index(1)", file);
+	return NOTOK;
+    }
+
+    dl = &d;
+    count = (long) strlen (mmdlm2);
+    (void) lseek (fd, (off_t) (dp -> d_id * sizeof *dp), 0);
+    if (read (fd, (char *) dl, sizeof *dl) != sizeof *dl
+#ifdef NTOHLSWAP
+	    || (ntohl(dl -> d_stop) != dp -> d_stop
+		&& ntohl(dl -> d_stop) + count != dp -> d_stop)) {
+#else
+	    || dl -> d_stop != dp -> d_stop
+		&& dl -> d_stop + count != dp -> d_stop) {
+#endif
+	if (noisy)
+	    admonish (NULLCP, "%s: corrupt index(2)", file);
+	return NOTOK;
+    }
+
+    return OK;
+}