Mercurial > hg > Applications > mh
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; +}