The goal is to call this from new.c as an alternative to the
.folders file.
=== modified file 'ChangeLog'
--- ChangeLog 2008-08-05 23:15:07 +0000
+++ ChangeLog 2008-08-07 00:16:56 +0000
@@ -1,3 +1,13 @@
+2008-08-06 Eric Gillespie <epg(_at_)pretzelnet(_dot_)org>
+
+ * h/Makefile.in, h/crawl_folders.h, sbr/Makefile.in,
+ sbr/crawl_folders.c, uip/folder.c: Extract the folder crawling
+ code from folder.c into new crawl_folders function, using a
+ callback to assemble the folder info in folder.c. Drop compare
+ function and use strcmp instead. Rename addfold and addir to
+ add_folder and add_children (add dir vs. add folder?
+ confusing names).
+
2008-08-05 Eric Gillespie <epg(_at_)pretzelnet(_dot_)org>
* uip/folder.c: chdir(nmhdir) in main rather than in dodir, which
=== modified file 'h/Makefile.in'
--- h/Makefile.in 2008-08-05 23:13:06 +0000
+++ h/Makefile.in 2008-08-06 23:29:50 +0000
@@ -10,7 +10,7 @@
VPATH = @srcdir@
# header files included in distribution
-HDRS = addrsbr.h aliasbr.h dropsbr.h fmt_compile.h fmt_scan.h
\
+HDRS = addrsbr.h aliasbr.h crawl_folders.h dropsbr.h fmt_compile.h
fmt_scan.h \
md5.h mf.h mh.h mhcachesbr.h mhparse.h mime.h msh.h mts.h \
netdb.h nmh.h nntp.h picksbr.h popsbr.h prototypes.h rcvmail.h \
scansbr.h signals.h tws.h vmhsbr.h utils.h
=== added file 'h/crawl_folders.h'
--- h/crawl_folders.h 1970-01-01 00:00:00 +0000
+++ h/crawl_folders.h 2008-08-06 23:31:05 +0000
@@ -0,0 +1,19 @@
+
+/*
+ * crawl_folders.h -- crawl folder hierarchy
+ *
+ * $Id$
+ */
+
+#define CRAWL_NUMFOLDERS 100
+
+/* Callbacks return non-zero if crawl_folders should crawl the children of
+ * `folder'. Callbacks need not duplicate folder, as crawl_folders does not
+ * free it. */
+typedef int (crawl_callback_t)(char *folder, void *baton);
+
+/* Crawl the folder hierarchy rooted at the relative path `dir'. For each
+ * folder, pass `callback' the folder name (as a path relative to the current
+ * directory) and `baton'; the callback may direct crawl_folders not to crawl
+ * its children; see above. */
+void crawl_folders (char *dir, crawl_callback_t *callback, void *baton);
=== modified file 'sbr/Makefile.in'
--- sbr/Makefile.in 2008-08-05 23:13:06 +0000
+++ sbr/Makefile.in 2008-08-06 23:30:15 +0000
@@ -58,7 +58,8 @@
check_charset.c client.c closefds.c concat.c context_del.c \
context_find.c context_foil.c context_read.c \
context_replace.c context_save.c copy.c \
- copyip.c cpydata.c cpydgst.c discard.c done.c dtime.c dtimep.c \
+ copyip.c cpydata.c cpydgst.c crawl_folders.c \
+ discard.c done.c dtime.c dtimep.c \
error.c ext_hook.c fdcompare.c folder_addmsg.c folder_delmsgs.c \
folder_free.c folder_pack.c folder_read.c \
folder_realloc.c gans.c getans.c getanswer.c \
=== added file 'sbr/crawl_folders.c'
--- sbr/crawl_folders.c 1970-01-01 00:00:00 +0000
+++ sbr/crawl_folders.c 2008-08-06 23:41:08 +0000
@@ -0,0 +1,151 @@
+
+/*
+ * crawl_folders.c -- crawl folder hierarchy
+ *
+ * $Id$
+ *
+ * This code is Copyright (c) 2008, by the authors of nmh. See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ */
+
+#include <h/mh.h>
+#include <h/crawl_folders.h>
+#include <h/utils.h>
+
+struct crawl_context {
+ int max; /* how many folders we currently can hold in
+ * the array `folders', increased by
+ * CRAWL_NUMFOLDERS at a time */
+ int total; /* how many `folders' actually has */
+ char **folders; /* the array of folders */
+ int start;
+ int foldp;
+};
+
+/*
+ * Add the folder name into the
+ * list in a sorted fashion.
+ */
+
+static void
+add_folder (char *fold, struct crawl_context *crawl)
+{
+ register int i, j;
+
+ /* if necessary, reallocate the space for folder names */
+ if (crawl->foldp >= crawl->max) {
+ crawl->max += CRAWL_NUMFOLDERS;
+ crawl->folders = mh_xrealloc (crawl->folders,
+ crawl->max * sizeof(char *));
+ }
+
+ for (i = crawl->start; i < crawl->foldp; i++)
+ if (strcmp (fold, crawl->folders[i]) < 0) {
+ for (j = crawl->foldp - 1; j >= i; j--)
+ crawl->folders[j + 1] = crawl->folders[j];
+ crawl->foldp++;
+ crawl->folders[i] = fold;
+ return;
+ }
+
+ crawl->total++;
+ crawl->folders[crawl->foldp++] = fold;
+}
+
+static void
+add_children (char *name, struct crawl_context *crawl)
+{
+ char *prefix, *child;
+ struct stat st;
+ struct dirent *dp;
+ DIR * dd;
+ int child_is_folder;
+
+ if (!(dd = opendir (name))) {
+ admonish (name, "unable to read directory ");
+ return;
+ }
+
+ if (strcmp (name, ".") == 0) {
+ prefix = getcpy ("");
+ } else {
+ prefix = concat (name, "/", (void *)NULL);
+ }
+
+ while ((dp = readdir (dd))) {
+ /* If the system supports it, try to skip processing of children we
+ * know are not directories or symlinks. */
+ child_is_folder = -1;
+#if defined(HAVE_STRUCT_DIRENT_D_TYPE)
+ if (dp->d_type == DT_DIR) {
+ child_is_folder = 1;
+ } else if (dp->d_type != DT_LNK && dp->d_type != DT_UNKNOWN) {
+ continue;
+ }
+#endif
+ if (!strcmp (dp->d_name, ".") || !strcmp (dp->d_name, "..")) {
+ continue;
+ }
+ child = concat (prefix, dp->d_name, (void *)NULL);
+ /* If we have no d_type or d_type is DT_LNK or DT_UNKNOWN, stat the
+ * child to see what it is. */
+ if (child_is_folder == -1) {
+ child_is_folder = (stat (child, &st) != -1 && S_ISDIR(st.st_mode));
+ }
+ if (child_is_folder) {
+ /* add_folder saves child in the list, don't free it */
+ add_folder (child, crawl);
+ } else {
+ free (child);
+ }
+ }
+
+ closedir (dd);
+ free(prefix);
+}
+
+static void
+crawl_folders_body (struct crawl_context *crawl,
+ char *dir, crawl_callback_t *callback, void *baton)
+{
+ int i;
+ int os = crawl->start;
+ int of = crawl->foldp;
+
+ crawl->start = crawl->foldp;
+
+ add_children (dir, crawl);
+
+ for (i = crawl->start; i < crawl->foldp; i++) {
+ char *fold = crawl->folders[i];
+ int crawl_children = 1;
+
+ if (callback != NULL) {
+ crawl_children = callback (fold, baton);
+ }
+
+ if (crawl_children) {
+ crawl_folders_body (crawl, fold, callback, baton);
+ }
+ }
+
+ crawl->start = os;
+ crawl->foldp = of;
+}
+
+void
+crawl_folders (char *dir, crawl_callback_t *callback, void *baton)
+{
+ struct crawl_context *crawl = mh_xmalloc (sizeof(*crawl));
+ crawl->max = CRAWL_NUMFOLDERS;
+ crawl->total = crawl->start = crawl->foldp = 0;
+ crawl->folders = mh_xmalloc (crawl->max * sizeof(*crawl->folders));
+
+ crawl_folders_body (crawl, dir, callback, baton);
+
+ /* Note that we "leak" the folder names, on the assumption that the caller
+ * is using them. */
+ free (crawl->folders);
+ free (crawl);
+}
=== modified file 'uip/folder.c'
--- uip/folder.c 2008-08-05 23:15:07 +0000
+++ uip/folder.c 2008-08-07 00:07:29 +0000
@@ -12,6 +12,7 @@
*/
#include <h/mh.h>
+#include <h/crawl_folders.h>
#include <h/utils.h>
#include <errno.h>
@@ -78,22 +79,10 @@
static int total_folders = 0; /* total number of folders */
-static int start = 0;
-static int foldp = 0;
-
static char *nmhdir;
static char *stack = "Folder-Stack";
static char folder[BUFSIZ];
-#define NUMFOLDERS 100
-
-/*
- * This is how many folders we currently can hold in the array
- * `folds'. We increase this amount by NUMFOLDERS at a time.
- */
-static int maxfolders;
-static char **folds;
-
/*
* Structure to hold information about
* folders as we scan them.
@@ -118,13 +107,10 @@
/*
* static prototypes
*/
-static void dodir (char *);
static int get_folder_info (char *, char *);
+static crawl_callback_t get_folder_info_callback;
static void print_folders (void);
static int sfold (struct msgs *, char *);
-static void addir (char *);
-static void addfold (char *);
-static int compare (char *, char *);
static void readonly_folders (void);
@@ -350,12 +336,8 @@
done (0);
}
- /* Allocate initial space to record folder names */
- maxfolders = NUMFOLDERS;
- folds = mh_xmalloc (maxfolders * sizeof(char *));
-
/* Allocate initial space to record folder information */
- maxFolderInfo = NUMFOLDERS;
+ maxFolderInfo = CRAWL_NUMFOLDERS;
fi = mh_xmalloc (maxFolderInfo * sizeof(*fi));
/*
@@ -365,7 +347,7 @@
/*
* If no folder is given, do them all
*/
- /* change directory to base of nmh directory for dodir */
+ /* change directory to base of nmh directory for crawl_folders */
if (chdir (nmhdir) == NOTOK)
adios (nmhdir, "unable to change directory to");
if (!argfolder) {
@@ -373,7 +355,7 @@
admonish (NULL, "no folder given for message %s", msg);
readonly_folders (); /* do any readonly folders */
strncpy (folder, (cp = context_find (pfolder)) ? cp : "",
sizeof(folder));
- dodir (".");
+ crawl_folders (".", get_folder_info_callback, NULL);
} else {
strncpy (folder, argfolder, sizeof(folder));
if (get_folder_info (argfolder, msg)) {
@@ -385,7 +367,7 @@
* we still need to list all level-1 sub-folders.
*/
if (!frecurse)
- dodir (folder);
+ crawl_folders (folder, get_folder_info_callback, NULL);
}
} else {
strncpy (folder, argfolder ? argfolder : getfolder (1), sizeof(folder));
@@ -412,32 +394,8 @@
return 1;
}
-/*
- * Base routine for scanning a folder
- */
-
-static void
-dodir (char *dir)
-{
- int i;
- int os = start;
- int of = foldp;
-
- start = foldp;
-
- addir (dir);
-
- for (i = start; i < foldp; i++) {
- get_folder_info (folds[i], NULL);
- fflush (stdout);
- }
-
- start = os;
- foldp = of;
-}
-
static int
-get_folder_info (char *fold, char *msg)
+get_folder_info_body (char *fold, char *msg, int *crawl_children)
{
int i, retval = 1;
struct msgs *mp = NULL;
@@ -449,7 +407,7 @@
* for folder information
*/
if (total_folders >= maxFolderInfo) {
- maxFolderInfo += NUMFOLDERS;
+ maxFolderInfo += CRAWL_NUMFOLDERS;
fi = mh_xrealloc (fi, maxFolderInfo * sizeof(*fi));
}
@@ -493,8 +451,32 @@
folder_free (mp); /* free folder/message structure */
}
- if (frecurse && (fshort || fi[i].others) && (fi[i].error == 0))
- dodir (fold);
+ *crawl_children = (frecurse && (fshort || fi[i].others)
+ && (fi[i].error == 0));
+ return retval;
+}
+
+static int
+get_folder_info_callback (char *fold, void *baton)
+{
+ int crawl_children;
+ get_folder_info_body (fold, NULL, &crawl_children);
+ fflush (stdout);
+ return crawl_children;
+}
+
+static int
+get_folder_info (char *fold, char *msg)
+{
+ int crawl_children;
+ int retval;
+
+ retval = get_folder_info_body (fold, msg, &crawl_children);
+
+ if (crawl_children) {
+ crawl_folders (fold, get_folder_info_callback, NULL);
+ }
+
return retval;
}
@@ -654,99 +636,6 @@
}
-static void
-addir (char *name)
-{
- char *prefix, *child;
- struct stat st;
- struct dirent *dp;
- DIR * dd;
- int child_is_folder;
-
- if (!(dd = opendir (name))) {
- admonish (name, "unable to read directory ");
- return;
- }
-
- if (strcmp (name, ".") == 0) {
- prefix = getcpy ("");
- } else {
- prefix = concat (name, "/", (void *)NULL);
- }
-
- while ((dp = readdir (dd))) {
- /* If the system supports it, try to skip processing of children we
- * know are not directories or symlinks. */
- child_is_folder = -1;
-#if defined(HAVE_STRUCT_DIRENT_D_TYPE)
- if (dp->d_type == DT_DIR) {
- child_is_folder = 1;
- } else if (dp->d_type != DT_LNK && dp->d_type != DT_UNKNOWN) {
- continue;
- }
-#endif
- if (!strcmp (dp->d_name, ".") || !strcmp (dp->d_name, "..")) {
- continue;
- }
- child = concat (prefix, dp->d_name, (void *)NULL);
- /* If we have no d_type or d_type is DT_LNK or DT_UNKNOWN, stat the
- * child to see what it is. */
- if (child_is_folder == -1) {
- child_is_folder = (stat (child, &st) != -1 && S_ISDIR(st.st_mode));
- }
- if (child_is_folder) {
- /* addfold saves child in the list, don't free it */
- addfold (child);
- } else {
- free (child);
- }
- }
-
- closedir (dd);
- free(prefix);
-}
-
-/*
- * Add the folder name into the
- * list in a sorted fashion.
- */
-
-static void
-addfold (char *fold)
-{
- register int i, j;
-
- /* if necessary, reallocate the space for folder names */
- if (foldp >= maxfolders) {
- maxfolders += NUMFOLDERS;
- folds = mh_xrealloc (folds, maxfolders * sizeof(char *));
- }
-
- for (i = start; i < foldp; i++)
- if (compare (fold, folds[i]) < 0) {
- for (j = foldp - 1; j >= i; j--)
- folds[j + 1] = folds[j];
- foldp++;
- folds[i] = fold;
- return;
- }
-
- folds[foldp++] = fold;
-}
-
-
-static int
-compare (char *s1, char *s2)
-{
- register int i;
-
- while (*s1 || *s2)
- if ((i = *s1++ - *s2++))
- return i;
-
- return 0;
-}
-
/*
* Do the read only folders
*/
_______________________________________________
Nmh-workers mailing list
Nmh-workers(_at_)nongnu(_dot_)org
http://lists.nongnu.org/mailman/listinfo/nmh-workers