nmh-workers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Nmh-workers] some indexing results


From: Paul Vixie
Subject: Re: [Nmh-workers] some indexing results
Date: Tue, 15 Feb 2011 21:37:47 +0000

> From: Ken Hornstein <address@hidden>
> Date: Tue, 15 Feb 2011 15:57:55 -0500
> 
> Well, I'm not sure that would help _me_ all that much, since ~ is all on
> the same network filesystem.  But then (assuming that it works) I would
> probably want the databases network-filesystem accessable.  So I think
> what you have would work fine for me.

if you'd like to give it a try, here's a snapshot.  you'll want to uncomment
MHDB_HEADERS in the Makefile, and as to how you build NMH 1.3 with the diff
applied that's up to you.  my ~/.mh_profile contains the following lines:

add-hook: /home/vixie/src/mhdb/mhdb-add
del-hook: /home/vixie/src/mhdb/mhdb-del
ref-hook: /home/vixie/src/mhdb/mhdb-ref

note that i have not yet altered mhdb_store_hdr() to include the first few
lines of the body, so the modified "scan" does not show the first few words
of the message.  also, this snapshot still depends on the non-standard C
library function fropen() which to the best of my knowledge make it FreeBSD
specific.  if you get that far, you'll need to run mhdb-buildall.sh one time
to get things started, and after that NMH will keep everything in sync via
the hook interface.

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#       Makefile
#       mhdb-add.c
#       mhdb-build.sh
#       mhdb-buildall.sh
#       mhdb-del.c
#       mhdb-dump.c
#       mhdb-ref.c
#       mhdb.c
#       mhdb.h
#       mhdb_pvt.h
#       nmh-1.3.diffs
#
echo x - Makefile
sed 's/^X//' >Makefile << 'b67911656ef5d18c4ae36cb6741b7965'
XALL = mhdb-add mhdb-del mhdb-ref mhdb-dump
X
XDEFS = -DDBM_HEADER='<ndbm.h>'
X# -DMHDB_HEADERS
XOPT = -g
XCFLAGS = -Wall ${DEFS} ${OPT}
X
Xall: ${ALL}
X
Xclean:
X       rm -f *.o
X       rm -f ${ALL}
X
Xmhdb-add: mhdb-add.o mhdb.o
X       ${CC} -o $@ $>
Xmhdb-del: mhdb-del.o mhdb.o
X       ${CC} -o $@ $>
Xmhdb-ref: mhdb-ref.o mhdb.o
X       ${CC} -o $@ $>
Xmhdb-dump: mhdb-dump.o mhdb.o
X       ${CC} -o $@ $>
X
Xmhdb.o: mhdb.c mhdb.h mhdb_pvt.h Makefile
Xmhdb-add.o: mhdb-add.c mhdb.h Makefile
Xmhdb-del.o: mhdb-del.c mhdb.h Makefile
Xmhdb-ref.o: mhdb-ref.c mhdb.h Makefile
Xmhdb-dump.o: mhdb-dump.c mhdb.h mhdb_pvt.h Makefile
b67911656ef5d18c4ae36cb6741b7965
echo x - mhdb-add.c
sed 's/^X//' >mhdb-add.c << 'bad38879bcc2b0eecb693d699b4bb7f3'
X#include <sys/param.h>
X
X#include <assert.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X
X#include "mhdb.h"
X
Xstatic mhdb_t d;
Xstatic char *p;
X
Xstatic void    mhdb_add(const char *mhpath);
X
Xint
Xmain(int argc, char *argv[]) {
X       if (strcmp(argv[1], "-") != 0) {
X               mhdb_add(argv[1]);
X       } else {
X               char line[MAXPATHLEN+1];
X
X               while (fgets(line, sizeof line, stdin)) {
X                       char *t = strrchr(line, '\n');
X
X                       if (t != NULL)
X                               *t = '\0';
X                       mhdb_add(line);
X               }
X       }
X                      
X       if (d != NULL)
X               mhdb_close(d);
X       if (p != NULL)
X               free(p);
X       exit(0);
X}
X
Xstatic void
Xmhdb_add(const char *mhpath) {
X       char *t = mhdb_path(mhpath);
X       int uid;
X
X       if (d != NULL && p != NULL && strcmp(t, p) != 0) {
X               mhdb_close(d);
X               d = NULL;
X               free(p);
X               p = NULL;
X       }
X       if (d == NULL) {
X               assert(p == NULL);
X               d = mhdb_open(t, mhdb_acc_exclusive);
X               p = t;
X       }
X       uid = mhdb_assign_uid(d, mhpath, 0);
X#ifdef MHDB_HEADERS
X       mhdb_store_hdr(d, mhpath, uid);
X#endif
X}
bad38879bcc2b0eecb693d699b4bb7f3
echo x - mhdb-build.sh
sed 's/^X//' >mhdb-build.sh << 'c5486321891e08b434fdda65fcfd40eb'
X#! /bin/sh
X
XPATH=/home/vixie/src/mhdb:$PATH
X
Xcase "$1" in
X+*) folder=$1 ;;
X*) echo usage: $0 +folder; exit 1
Xesac
X
Xpath=`mhpath $folder`
Xif [ ! -d $path ]; then
X       echo $0: not a folder: $folder
X       exit 1
Xfi
X
Xrm -f $path/mhindex.db
Xmhpath all $folder | mhdb-add -
X
Xexit
c5486321891e08b434fdda65fcfd40eb
echo x - mhdb-buildall.sh
sed 's/^X//' >mhdb-buildall.sh << '26bd47b3340bba2e977eb8b5f3c93ac4'
X#! /bin/sh
X
XPATH=/home/vixie/src/mhdb:$PATH
X
Xfolders -fast -recurse | while read folder; do
X       echo +$folder
X       mhdb-build.sh +$folder
Xdone
X
Xexit
26bd47b3340bba2e977eb8b5f3c93ac4
echo x - mhdb-del.c
sed 's/^X//' >mhdb-del.c << '5200b83c898774d7b2e51862a90a17e9'
X#include <sys/param.h>
X
X#include <assert.h>
X#include <stdlib.h>
X#include <stdio.h>
X#include <string.h>
X
X#include "mhdb.h"
X
Xstatic mhdb_t d;
Xstatic char *p;
X
Xstatic void    mhdb_del(const char *mhpath);
X
Xint
Xmain(int argc, char *argv[]) {
X       if (strcmp(argv[1], "-") != 0) {
X               mhdb_del(argv[1]);
X       } else {
X               char line[MAXPATHLEN+1];
X
X               while (fgets(line, sizeof line, stdin)) {
X                       char *t = strrchr(line, '\n');
X
X                       if (t != NULL)
X                               *t = '\0';
X                       mhdb_del(line);
X               }
X       }
X                      
X       if (d != NULL)
X               mhdb_close(d);
X       if (p != NULL)
X               free(p);
X       exit(0);
X}
X
Xstatic void
Xmhdb_del(const char *mhpath) {
X       char *t = mhdb_path(mhpath);
X       int uid;
X
X       if (d != NULL && p != NULL && strcmp(t, p) != 0) {
X               mhdb_close(d);
X               d = NULL;
X               free(p);
X               p = NULL;
X       }
X       if (d == NULL) {
X               assert(p == NULL);
X               d = mhdb_open(t, mhdb_acc_exclusive);
X               p = t;
X       }
X       uid = mhdb_get_uid(d, mhpath);
X#ifdef MHDB_HEADERS
X       mhdb_remove_hdr(d, uid);
X#endif
X       mhdb_delete_uid(d, mhpath, uid);
X}
5200b83c898774d7b2e51862a90a17e9
echo x - mhdb-dump.c
sed 's/^X//' >mhdb-dump.c << '4bf3f93188fb7e605f36d4cd168ed683'
X#include <sys/stat.h>
X
X#include <err.h>
X#include <stdio.h>
X#include <stdlib.h>
X
X#include "mhdb.h"
X#include "mhdb_pvt.h"
X
Xstatic void mhdb_dump_folder(mhdb_t);
Xstatic void mhdb_dump_message(mhdb_t, const char *mhpath);
X
Xint
Xmain(int argc, char *argv[]) {
X       struct stat sb;
X       mhdb_t mhdb;
X
X       mhdb = mhdb_openpath(argv[1], 0);
X       if (mhdb == NULL)
X               err(1, "mhdb_open failed (%s)", argv[1]);
X       if (stat(argv[1], &sb) < 0)
X               err(1, "stat failed (%s)", argv[1]);
X       if (S_ISDIR(sb.st_mode)) {
X               mhdb_dump_folder(mhdb);
X       } else if (S_ISREG(sb.st_mode)) {
X               mhdb_dump_message(mhdb, argv[1]);
X       } else
X               warn("%s is neither a directory nor a file", argv[1]);
X       mhdb_close(mhdb);
X       exit(0);
X}
X
Xstatic void
Xmhdb_dump_folder(mhdb_t mhdb) {
X       datum key;
X
X       for (key = dbm_firstkey(mhdb->d);
X            key.dptr != NULL;
X            key = dbm_nextkey(mhdb->d)) {
X               datum data;
X
X               data = dbm_fetch(mhdb->d, key);
X               printf("'%.*s' => '%.*s'\n",
X                      key.dsize, key.dptr,
X                      data.dsize, data.dptr);
X       }
X}
X
Xstatic void
Xmhdb_dump_message(mhdb_t mhdb, const char *mhpath) {
X       int uid = mhdb_get_uid(mhdb, mhpath);
X
X       printf("uid = %d\n", uid);
X#ifdef MHDB_HEADERS
X       if (uid != 0) {
X               ssize_t siz;
X               char *hdr;
X
X               siz = mhdb_get_hdr(mhdb, &hdr, uid);
X               if (siz >= 0) {
X                       printf("---\n%.*s===\n", (int) siz, hdr);
X                       free(hdr);
X               }
X       }
X#endif
X}
4bf3f93188fb7e605f36d4cd168ed683
echo x - mhdb-ref.c
sed 's/^X//' >mhdb-ref.c << '748283885dfe181dcd50f277c1754ece'
X#include <stdlib.h>
X#include <string.h>
X
X#include "mhdb.h"
X
Xint
Xmain(int argc, char *argv[]) {
X       char *p1, *p2;
X       mhdb_t d1, d2;
X       int uid;
X
X       /* Here we call mhdb_path and mhdb_open separately (vs mh-add/mh-del)
X        * because if it's the same folder we don't want to open the database
X        * twice.
X        */
X       p1 = mhdb_path(argv[1]);
X       p2 = mhdb_path(argv[2]);
X       d1 = mhdb_open(p1, mhdb_acc_exclusive);
X       d2 = (filenamecmp(p1, p2) == 0)
X               ? d1
X               : mhdb_open(p2, mhdb_acc_exclusive);
X       free(p2);
X       free(p1);
X       uid = mhdb_get_uid(d1, argv[1]);
X#ifdef MHDB_HEADERS
X       if (d1 != d2)
X               mhdb_remove_hdr(d1, uid);
X#endif
X       mhdb_delete_uid(d1, argv[1], uid);
X       uid = mhdb_assign_uid(d2, argv[2], (d1 == d2) ? uid : 0);
X#ifdef MHDB_HEADERS
X       if (d1 != d2)
X               mhdb_store_hdr(d2, argv[2], uid);
X#endif
X       mhdb_close(d2);
X       if (d1 != d2)
X               mhdb_close(d1);
X       exit(0);
X}
748283885dfe181dcd50f277c1754ece
echo x - mhdb.c
sed 's/^X//' >mhdb.c << '10087cbdba0abeaae47aec0eb43b7228'
X#include <sys/file.h>
X
X#include <ctype.h>
X#include <err.h>
X#include <stdarg.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X
X#include "mhdb.h"
X#include "mhdb_pvt.h"
X
Xstatic const char base[] = "mhindex";
X
Xstatic int mhdb_atoi(datum a);
Xstatic int mhdb_isnum(const char *s);
Xstatic int mhdb_msgno(const char *mhpath);
X
X/* Compute a dbname corresponding to this full MH path name, which could
X * be of a message (if it has an all-numeric base name) or folder (if not).
X *
X * Danger: if given /home/vixie/Mail/123 (all numeric name) this code will
X * silently do the wrong thing (/home/vixie/Mail/mhindex.db).  Unlike MH,
X * it does not stat() the argument to find out if it's a directory or not.
X *
X * Danger: allocates on the heap and returns that -- caller must call free().
X */
Xchar *
Xmhdb_path(const char *mhpath) {
X       char *t, *p;
X
X       t = malloc(strlen(mhpath) + strlen(base) + sizeof "/");
X       if (t == NULL)
X               err(1, "malloc failed");
X       strcpy(t, mhpath);
X       p = strrchr(t, '/');
X       if (p != NULL) {
X               if (mhdb_isnum(p + 1))          /* ends in /msgnum */
X                       p[1] = '\0';            /* ...so, truncate. */
X               else if (p[1] != '\0')          /* ends in non-'/' */
X                       strcat(t, "/");         /* ...so, append '/' */
X       }
X       strcat(t, base);
X       return (t);
X}
X
X/* Open the database, creating if nec'y, and lock it.  Since we use flock()
X * the unlock is implicit upon close() or exit().
X */
Xmhdb_t
Xmhdb_open(const char *dbpath, mhdb_acc_t acc) {
X       mhdb_t self;
X       DBM *d;
X       int writable_p = (acc == mhdb_acc_exclusive);
X
X       d = dbm_open(dbpath, writable_p ? (O_CREAT | O_RDWR) : O_RDONLY, 0666);
X       if (d == NULL) {
X               if (writable_p)
X                       err(1, "dbm_open failed");
X               else
X                       return (NULL);
X       }
X
X       if (acc != mhdb_acc_nolock)
X               if (flock(dbm_dirfno(d), writable_p ? LOCK_EX : LOCK_SH) < 0)
X                       err(1, "flock failed");
X
X       self = malloc(sizeof *self);
X       self->d = d;
X       return (self);
X}
X
X/* Convenience function so that folks who don't need to know the dbpath can
X * avoid the hassle of calling free().  (imapd and dovecot i'm looking at YOU.)
X */
Xmhdb_t
Xmhdb_openpath(const char *mhpath, mhdb_acc_t acc) {
X       mhdb_t self;
X       char *dbpath;
X
X       dbpath = mhdb_path(mhpath);
X       self = mhdb_open(dbpath, acc);
X       free(dbpath);
X       return (self);
X}
X
X/* Close and release.
X */
Xvoid
Xmhdb_close(mhdb_t self) {
X       dbm_close(self->d);
X       free(self);
X}
X
X/* Write something to the audit log.
X */
Xvoid
Xmhdb_audit(const char *fmt, ...) {
X       va_list ap;
X
X       va_start(ap, fmt);
X       vfprintf(stderr, fmt, ap);
X       va_end(ap);
X}
X
X/* Get an existing uid from the database.
X */
Xint
Xmhdb_get_uid(mhdb_t self, const char *mhpath) {
X       datum key, data;
X       int msg, uid;
X       char *t;
X
X       msg = mhdb_msgno(mhpath);
X       if (msg == 0) {
X               warnx("mhdb_add: no message number (%s)", mhpath);
X               return (0);
X       }
X
X       /* Get the UID for this message number, if any. */
X       asprintf(&t, "%d:msg:uid", msg);
X       key.dptr = t;
X       key.dsize = strlen(t);
X       data = dbm_fetch(self->d, key);
X       uid = (data.dptr != NULL) ? mhdb_atoi(data) : 0;
X       free(key.dptr);
X
X       return (uid);
X}
X
X/* Add a new msg<->uid mapping to the database.  Returns new (or given) UID.
X */
Xint
Xmhdb_assign_uid(mhdb_t self, const char *mhpath, int given_uid) {
X       datum key, data;
X       int msg, uid;
X       char *t;
X
X       msg = mhdb_msgno(mhpath);
X       if (msg == 0) {
X               warnx("mhdb_add: no message number (%s)", mhpath);
X               return (0);
X       }
X
X       /* Get next UID from file header, unless it was given. */
X       if (given_uid != 0) {
X               uid = given_uid;
X       } else {
X               key.dptr = "file_header";
X               key.dsize = strlen(key.dptr);
X               data = dbm_fetch(self->d, key);
X               if (data.dptr == NULL) {
X                       data.dptr = "1";
X                       data.dsize = strlen(data.dptr);
X                       }
X               uid = mhdb_atoi(data);
X       }
X
X       /* Store mapping from this UID to the message number. */
X       asprintf(&t, "%d:uid:msg", uid);
X       key.dptr = t;
X       key.dsize = strlen(t);
X       asprintf(&t, "%d", msg);
X       data.dptr = t;
X       data.dsize = strlen(t);
X       switch (dbm_store(self->d, key, data, DBM_INSERT)) {
X               case -1: err(1, "dbm_store");
X               case 1: errx(1, "key %s already present", key.dptr);
X       }
X       free(data.dptr);
X       free(key.dptr);
X
X       /* Store mapping from this message number to this UID. */
X       asprintf(&t, "%d:msg:uid", msg);
X       key.dptr = t;
X       key.dsize = strlen(t);
X       asprintf(&t, "%d", uid);
X       data.dptr = t;
X       data.dsize = strlen(t);
X       switch (dbm_store(self->d, key, data, DBM_INSERT)) {
X               case -1: err(1, "dbm_store");
X               case 1: errx(1, "key %s already present", key.dptr);
X       }
X       free(data.dptr);
X       free(key.dptr);
X
X       /* Increment the UID and store it back in the database,
X        * unless it was given.
X        */
X       if (given_uid == 0) {
X               key.dptr = "file_header";
X               key.dsize = strlen(key.dptr);
X               asprintf(&t, "%d", uid + 1);
X               data.dptr = t;
X               data.dsize = strlen(t);
X               if (dbm_store(self->d, key, data, DBM_REPLACE) < 0)
X                       err(1, "dbm_store");
X               free(data.dptr);
X       }
X
X       return (uid);
X}
X
X/* Remove a UID mapping from the database.
X */
Xvoid
Xmhdb_delete_uid(mhdb_t self, const char *mhpath, int uid) {
X       datum key;
X       int msg;
X       char *t;
X
X       msg = mhdb_msgno(mhpath);
X       if (msg == 0) {
X               warnx("mhdb_add: no message number (%s)", mhpath);
X               return;
X       }
X
X       /* Remove mapping from msg to uid (or fail silently). */
X       asprintf(&t, "%d:msg:uid", msg);
X       key.dptr = t;
X       key.dsize = strlen(t);
X       dbm_delete(self->d, key);
X       free(key.dptr);
X
X       /* Remove mapping from uid to msg if there is one. */
X       asprintf(&t, "%d:uid:msg", uid);
X       key.dptr = t;
X       key.dsize = strlen(t);
X       dbm_delete(self->d, key);
X       free(key.dptr);
X}
X
X#ifdef MHDB_HEADERS
X/* Retrieve a message's header, indexed by UID.
X */
Xssize_t
Xmhdb_get_hdr(mhdb_t self, char **bufp, int uid) {
X       datum key, data;
X       char *t;
X
X       asprintf(&t, "%d:uid:hdr", uid);
X       key.dptr = t;
X       key.dsize = strlen(t);
X
X       data = dbm_fetch(self->d, key);
X       if (data.dptr == NULL) {
X               warnx("mhdb_get_hdr: no message header (uid %d)", uid);
X               free(key.dptr);
X               return (-1);
X       }
X
X       *bufp = malloc(data.dsize);
X       memcpy(*bufp, data.dptr, data.dsize);
X       free(key.dptr);
X       return (data.dsize);
X}
X
X/* Store a message's header, indexed by UID.
X */
Xvoid
Xmhdb_store_hdr(mhdb_t self, const char *mhpath, int uid) {
X       datum key, data;
X       char ch, pch, *t;
X       FILE *fp;
X
X       asprintf(&t, "%d:uid:hdr", uid);
X       key.dptr = t;
X       key.dsize = strlen(t);
X
X       fp = fopen(mhpath, "r");
X       if (fp == NULL) {
X               warn("mhdb_store_hdr: cannot open file (%s)", mhpath);
X               return;
X       }
X       for (pch = EOF; (ch = getc(fp)) != EOF; pch = ch)
X               if (ch == '\n' && pch == '\n')
X                       break;
X       data.dsize = ftell(fp);
X       data.dptr = malloc(data.dsize);
X       rewind(fp);
X       fread(data.dptr, sizeof(char), data.dsize, fp);
X       fclose(fp);
X
X       if (dbm_store(self->d, key, data, DBM_INSERT) < 0)
X               warn("dbm_store");
X       free(data.dptr);
X       free(key.dptr);
X}
X
X/* Remove a message's header, indexed by UID.
X */
Xvoid
Xmhdb_remove_hdr(mhdb_t self, int uid) {
X       datum key;
X       char *t;
X
X       asprintf(&t, "%d:uid:hdr", uid);
X       key.dptr = t;
X       key.dsize = strlen(t);
X       dbm_delete(self->d, key);
X       free(key.dptr);
X}
X#endif
X
X/* --- private --- */
X
X/* Do what atoi would do but for a counted string (not null terminated)
X * held in a datum.
X */
Xstatic int
Xmhdb_atoi(datum a) {
X       int i = 0;
X
X       while (a.dsize-- > 0)
X               i *= 10, i += *a.dptr++ - '0';
X       return (i);
X}
X
X/* Is this string all-numeric?
X */
Xstatic int
Xmhdb_isnum(const char *s) {
X       char ch;
X
X       while ((ch = *s++) != '\0')
X               if (isascii(ch) && isdigit(ch))
X                       /*next*/;
X               else
X                       return (0);
X       return (1);
X}
X
X/* Retrieve MH message number from path name.
X */
Xstatic int
Xmhdb_msgno(const char *mhpath) {
X       const char *p = strrchr(mhpath, '/');
X
X       if (p != NULL)
X               p++;
X       else
X               p = mhpath;
X       return (atoi(p));
X}
X
10087cbdba0abeaae47aec0eb43b7228
echo x - mhdb.h
sed 's/^X//' >mhdb.h << 'b1edf5d0ed51f0163028cca21f9ec519'
X#ifndef MHDB_H
X#define MHDB_H 1
X
X#ifdef APPLE
X#define filenamecmp strcasecmp
X#else
X#define filenamecmp strcmp
X#endif
X
X#include <sys/types.h>
X#include <fcntl.h>
X
Xstruct mhdb;
Xtypedef struct mhdb *mhdb_t;
X
Xtypedef enum {
X       mhdb_acc_nolock = 0,
X       mhdb_acc_shared,
X       mhdb_acc_exclusive
X} mhdb_acc_t;
X
Xchar           *mhdb_path(const char *mhpath);
Xmhdb_t         mhdb_open(const char *dbpath, mhdb_acc_t);
Xmhdb_t         mhdb_openpath(const char *mhpath, mhdb_acc_t);
Xvoid           mhdb_close(mhdb_t);
Xvoid           mhdb_audit(const char *fmt, ...);
Xint            mhdb_get_uid(mhdb_t, const char *mhpath);
Xint            mhdb_assign_uid(mhdb_t, const char *mhpath, int given_uid);
Xvoid           mhdb_delete_uid(mhdb_t, const char *mhpath, int uid);
X#ifdef MHDB_HEADERS
Xssize_t                mhdb_get_hdr(mhdb_t, char **, int uid);
Xvoid           mhdb_store_hdr(mhdb_t, const char *mhpath, int uid);
Xvoid           mhdb_remove_hdr(mhdb_t, int uid);
X#endif
X
X#endif /*MHDB_H*/
b1edf5d0ed51f0163028cca21f9ec519
echo x - mhdb_pvt.h
sed 's/^X//' >mhdb_pvt.h << '3e3c03f8520d5ba4363c9fc2c4ba2a52'
X#ifndef MHDB_PVT_H
X#define MHDB_PVT_H 1
X
X#include DBM_HEADER
X
Xstruct mhdb {
X       DBM *d;
X};
X
X#endif /*MHDB_PVT_H*/
3e3c03f8520d5ba4363c9fc2c4ba2a52
echo x - nmh-1.3.diffs
sed 's/^X//' >nmh-1.3.diffs << '0605ee6e1463c974ef5ec76760fe8d32'
X--- nmh-1.3/uip/scan.c.pre-vixie       2011-02-07 05:20:02.000000000 +0000
X+++ nmh-1.3/uip/scan.c 2011-02-08 16:38:51.000000000 +0000
X@@ -17,6 +17,26 @@
X #include <h/utils.h>
X #include <errno.h>
X 
X+#define MHDB 1
X+
X+#ifdef MHDB
X+#include "/home/vixie/src/mhdb/mhdb.h"
X+struct functx {
X+      char *dptr, *hdr;
X+      ssize_t dsize;
X+      int uid;
X+};
X+static int funread (void *cookie, char *buf, int len) {
X+      struct functx *fc = cookie;
X+      int plan = min(len, fc->dsize);
X+
X+      memcpy(buf, fc->dptr, plan);
X+      fc->dptr += plan;
X+      fc->dsize -= plan;
X+      return (plan);
X+}
X+#endif
X+
X static struct swit switches[] = {
X #define       CLRSW   0
X     { "clear", 0 },
X@@ -72,6 +92,9 @@
X     struct msgs_array msgs = { 0, 0, NULL };
X     struct msgs *mp;
X     FILE *in;
X+#ifdef MHDB
X+    mhdb_t mhdb;
X+#endif
X 
X #ifdef LOCALE
X     setlocale(LC_ALL, "");
X@@ -212,6 +235,9 @@
X     if (!folder)
X       folder = getfolder (1);
X     maildir = m_maildir (folder);
X+#ifdef MHDB
X+    mhdb = mhdb_openpath (maildir, mhdb_acc_shared);
X+#endif
X 
X     if (chdir (maildir) == NOTOK)
X       adios (maildir, "unable to change directory to");
X@@ -262,7 +288,25 @@
X        (revflag ? msgnum >= mp->lowsel : msgnum <= mp->hghsel);
X        msgnum += (revflag ? -1 : 1)) {
X       if (is_selected(mp, msgnum)) {
X-          if ((in = fopen (cp = m_name (msgnum), "r")) == NULL) {
X+          struct functx *fc = NULL;
X+          in = NULL;
X+#ifdef MHDB
X+            if (mhdb != NULL) {
X+              fc = malloc (sizeof *fc);
X+              fc->uid = mhdb_get_uid (mhdb, m_name (msgnum));
X+              fc->dsize = mhdb_get_hdr (mhdb, &fc->hdr, fc->uid);
X+              fc->dptr = fc->hdr;
X+              if (fc->dsize > 0)
X+                  in = fropen (fc, funread);
X+              else {
X+                  free (fc);
X+                  fc = NULL;
X+              }
X+          }
X+#endif
X+          if (in == NULL)
X+              in = fopen (cp = m_name (msgnum), "r");
X+          if (in == NULL) {
X #if 0
X               if (errno != EACCES)
X #endif
X@@ -313,6 +357,13 @@
X           }
X           hdrflag = 0;
X           fclose (in);
X+#ifdef MHDB
X+          if (fc != NULL) {
X+              free(fc->hdr);
X+              free(fc);
X+              fc = NULL;
X+          }
X+#endif
X           if (ontty)
X               fflush (stdout);
X       }
X--- nmh-1.3/uip/scansbr.c.pre-vixie    2011-02-07 18:52:37.000000000 +0000
X+++ nmh-1.3/uip/scansbr.c      2011-02-07 18:54:12.000000000 +0000
X@@ -325,6 +325,7 @@
X     if ((datecomp && !datecomp->c_text) || (!size && !outnum)) {
X       struct stat st;
X 
X+      if (fileno(inb) != -1) { /*MHDB*/
X       fstat (fileno(inb), &st);
X       if (!size && !outnum)
X           dat[2] = st.st_size;
X@@ -341,6 +342,7 @@
X               datecomp->c_flags &= ~CF_DATEFAB;
X           }
X       }
X+      } /*MHDB*/
X     }
X 
X     fmt_scan (fmt, scanl, slwidth, dat);
0605ee6e1463c974ef5ec76760fe8d32
exit




reply via email to

[Prev in Thread] Current Thread [Next in Thread]