jv@mh.nl (Johan Vromans) (03/06/90)
This shar archive contains a fast lookup article by id mechanism for GNUS using NNSPOOL. It works only if yoy have built NEWS with [n]dbm or dbz. Enjoy. Johan #---------------------------------- cut here ---------------------------------- # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by Johan Vromans <jv@mhres> on Mon Mar 5 13:38:39 1990 # # This archive contains: # README getartbyid.c getartbyid.el # # Existing files will not be overwritten. # Error checking via wc(1) will be performed. LANG=""; export LANG if test -f README then echo Ok to overwrite existing file README\? read answer case "$answer" in [yY]*) echo Proceeding;; *) echo Aborting; exit 1;; esac rm -f README if test -f README then echo Error: could not remove README, aborting exit 1 fi fi echo x - README cat >README <<'@EOF' This shar archive contains a fast lookup article by id mechanisme for GNUS using NNSPOOL. It works only if yoy have built NEWS with [n]dbm or dbz. It consists of a replacement function for nnspool-find-article-by-message-id, and a fast lookup program. The program should be compiled and placed somewher in your PATH. Compile with: gcc -s -O getartbyid.c -o getartbyid -ldbm It also works with vanilla CC and Jon Zeeff's DBZ. Load getartbyid.el after loading gnus/nnspool, and you will have a blinding fast '^' key. Motivation: I created this function since I could not afford Emacs to carry an 8Mb buffer all of the time - other programs started running out of VM. Enjoy. @EOF set `wc -lwc <README` if test $1$2$3 != 22113680 then echo ERROR: wc results of README are $* should be 22 113 680 fi chmod 644 README if test -f getartbyid.c then echo Ok to overwrite existing file getartbyid.c\? read answer case "$answer" in [yY]*) echo Proceeding;; *) echo Aborting; exit 1;; esac rm -f getartbyid.c if test -f getartbyid.c then echo Error: could not remove getartbyid.c, aborting exit 1 fi fi echo x - getartbyid.c cat >getartbyid.c <<'@EOF' /* getartinfo.c - fetch article info using Bnews history file */ /* Usage: getartinfo [-v] [id] ... */ #include <stdio.h> #include <ctype.h> #include <string.h> /* DBM / DBZ declarations */ typedef struct { char *dptr; int dsize; } datum; datum fetch (); /* other forwards */ char *memcpy (); static char *lcase (); #define HISTFILE "/usr/lib/news/history" #define BUFLEN 512 int f_verbose = 0; main (argc, argv) int argc; char *argv[]; { FILE *hist = NULL; /* history file, if opened */ datum key, val; /* DBM items */ int fail = 0; /* failure count */ char artbuf [BUFLEN]; /* buf to hold article id */ char *artid; /* pointer to article id */ char buf [BUFLEN]; /* read buf for history file */ long fpos; /* seek position in hist file */ char *p; /* */ if (argc >= 1 && !strcmp (argv[1], "-v")) { argc--; argv++; f_verbose = 1; } /* initialize DBM */ if (dbminit (HISTFILE) < 0) { perror (HISTFILE); return -1; } /* process arguments */ while (--argc > 0) { /* copy article id into article buf, provide < and > if needed */ strcpy (artid = artbuf+1, *++argv); if (*artid != '<') { *--artid = '<'; strcat (artid, ">"); } /* lowcase and build DBM key */ key.dptr = artid; key.dsize = strlen (key.dptr)+1; lcase (key.dptr, key.dsize-1); /* fetch from DBM */ val = fetch (key); if (val.dptr == NULL) { if (f_verbose) fprintf (stderr, "%s: not found\n", *argv); fail++; /* tally */ continue; } /* open the history file upon first need */ if (hist == NULL) { if ((hist = fopen (HISTFILE, "r")) == NULL) { perror (HISTFILE); return -1; } } /* get the file pos from the DBM return value */ memcpy ((char*)&fpos, val.dptr, sizeof(long)); /* look it up */ if (fseek (hist, fpos, 0) < 0 ) { if (f_verbose) perror ("seek"); fail++; continue; } if (fgets (buf, BUFLEN, hist) == NULL) { if (f_verbose) perror ("read"); fail++; continue; } /* check if it is the right article */ p = strchr (buf, '\t'); if (p == NULL) p = strchr (buf, '\n'); *p = 0; lcase (buf, strlen (buf)); if (strcmp (buf, key.dptr) != 0) { /* it's not */ if (f_verbose) fprintf (stderr, "db corrupt?\n"); fail++; continue; } *p = '\t'; /* print results */ buf[strlen(buf)-1] = '\0'; /* zap the \n */ printf ("%s\n", buf); } /* wrap up */ dbmclose (); if (hist != NULL) fclose (hist); /* return number of failures */ return fail; } static char *lcase (s) register char *s; { register int n = strlen (s); for (s += n; n > 0; --n) { if (isupper(*--s)) *s = tolower(*s); } return s; } @EOF set `wc -lwc <getartbyid.c` if test $1$2$3 != 1354542803 then echo ERROR: wc results of getartbyid.c are $* should be 135 454 2803 fi chmod 644 getartbyid.c if test -f getartbyid.el then echo Ok to overwrite existing file getartbyid.el\? read answer case "$answer" in [yY]*) echo Proceeding;; *) echo Aborting; exit 1;; esac rm -f getartbyid.el if test -f getartbyid.el then echo Error: could not remove getartbyid.el, aborting exit 1 fi fi echo x - getartbyid.el cat >getartbyid.el <<'@EOF' (defun nnspool-find-article-by-message-id (id) "Return full pathname of an article identified by message-ID. This function uses an external C-program to do the history lookup." (save-excursion (let ((aname nil) (buffer (get-buffer-create "*newshistory*"))) (set-buffer buffer) (erase-buffer) (call-process "getartbyid" nil t nil id) (goto-char (point-min)) (prog1 (if (re-search-forward (concat "^" (regexp-quote id) "[ \t].*[ \t]\\([^ \t/]+\\)/\\([0-9]+\\)[ \t]*$") nil t) (let ((group (buffer-substring (match-beginning 1) (match-end 1))) (number (buffer-substring (match-beginning 2) (match-end 2)))) (concat (nnspool-article-pathname (nnspool-replace-chars-in-string group ?. ?/)) number))) (set-buffer-modified-p nil) (kill-buffer buffer))))) @EOF set `wc -lwc <getartbyid.el` if test $1$2$3 != 2379833 then echo ERROR: wc results of getartbyid.el are $* should be 23 79 833 fi chmod 644 getartbyid.el exit 0 -- Johan Vromans jv@mh.nl via internet backbones Multihouse Automatisering bv uucp: ..!{uunet,hp4nl}!mh.nl!jv Doesburgweg 7, 2803 PL Gouda, The Netherlands phone/fax: +31 1820 62944/62500 ------------------------ "Arms are made for hugging" -------------------------