/*
- * flist.c -- list nmh folders containing messages
- * -- in a given sequence
- *
- * originally by
- * David Nichols, Xerox-PARC, November, 1992
- *
- * Copyright (c) 1994 Xerox Corporation.
- * Use and copying of this software and preparation of derivative works based
- * upon this software are permitted. Any distribution of this software or
- * derivative works must comply with all applicable United States export
- * control laws. This software is made available AS IS, and Xerox Corporation
- * makes no warranty about the software, its performance or its conformity to
- * any specification.
- *
- * $Id$
- */
+** flist.c -- list nmh folders containing messages
+** -- in a given sequence
+**
+** originally by
+** David Nichols, Xerox-PARC, November, 1992
+**
+** Copyright (c) 1994 Xerox Corporation.
+** Use and copying of this software and preparation of derivative works based
+** upon this software are permitted. Any distribution of this software or
+** derivative works must comply with all applicable United States export
+** control laws. This software is made available AS IS, and Xerox Corporation
+** makes no warranty about the software, its performance or its conformity to
+** any specification.
+*/
#include <h/mh.h>
#include <h/utils.h>
-
-#define FALSE 0
-#define TRUE 1
+#include <unistd.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <locale.h>
+#include <sysexits.h>
/*
- * We allocate space to record the names of folders
- * (foldersToDo array), this number of elements at a time.
- */
+** We allocate space to record the names of folders
+** (foldersToDo array), this number of elements at a time.
+*/
#define MAXFOLDERS 100
static struct swit switches[] = {
-#define SEQSW 0
- { "sequence name", 0 },
-#define ALLSW 1
- { "all", 0 },
-#define NOALLSW 2
- { "noall", 0 },
-#define RECURSE 3
- { "recurse", 0 },
-#define NORECURSE 4
- { "norecurse", 0 },
-#define SHOWZERO 5
- { "showzero", 0 },
-#define NOSHOWZERO 6
- { "noshowzero", 0 },
-#define ALPHASW 7
- { "alpha", 0 },
-#define NOALPHASW 8
- { "noalpha", 0 },
-#define FASTSW 9
- { "fast", 0 },
-#define NOFASTSW 10
- { "nofast", 0 },
-#define TOTALSW 11
- { "total", -5 },
-#define NOTOTALSW 12
- { "nototal", -7 },
-#define VERSIONSW 13
- { "version", 0 },
-#define HELPSW 14
- { "help", 0 },
- { NULL, 0 }
+#define SEQSW 0
+ { "sequence name", 0 },
+#define ALLSW 1
+ { "all", 0 },
+#define NOALLSW 2
+ { "noall", 2 },
+#define RECURSE 3
+ { "recurse", 0 },
+#define NORECURSE 4
+ { "norecurse", 2 },
+#define SHOWZERO 5
+ { "showzero", 0 },
+#define NOSHOWZERO 6
+ { "noshowzero", 2 },
+#define ALPHASW 7
+ { "alpha", 0 },
+#define NOALPHASW 8
+ { "noalpha", 2 },
+#define FASTSW 9
+ { "fast", 0 },
+#define NOFASTSW 10
+ { "nofast", 2 },
+#define VERSIONSW 11
+ { "Version", 0 },
+#define HELPSW 12
+ { "help", 0 },
+ { NULL, 0 }
};
struct Folder {
- char *name; /* name of folder */
- int priority;
- int error; /* error == 1 for unreadable folder */
- int nMsgs; /* number of messages in folder */
- int nSeq[NUMATTRS]; /* number of messages in each sequence */
- int private[NUMATTRS]; /* is given sequence, public or private */
+ char *name; /* name of folder */
+ int priority;
+ int error; /* error == 1 for unreadable folder */
+ int nMsgs; /* number of messages in folder */
+ int nSeq[NUMATTRS]; /* number of messages in each sequence */
+ int private[NUMATTRS]; /* is given sequence, public or private */
};
static struct Folder *orders = NULL;
static int nOrders = 0;
static int nOrdersAlloced = 0;
static struct Folder *folders = NULL;
-static int nFolders = 0;
+static unsigned int nFolders = 0;
static int nFoldersAlloced = 0;
/* info on folders to search */
/* info on sequences to search for */
static char *sequencesToDo[NUMATTRS];
-static int numsequences;
+static unsigned int numsequences;
-static int all = FALSE; /* scan all folders in top level? */
-static int alphaOrder = FALSE; /* want alphabetical order only */
-static int recurse = FALSE; /* show nested folders? */
-static int showzero = TRUE; /* show folders even if no messages in seq? */
-static int Total = TRUE; /* display info on number of messages in *
- * sequence found, and total num messages */
+static int all = FALSE; /* scan all folders in top level? */
+static int alphaOrder = FALSE; /* want alphabetical order only */
+static int recurse = FALSE; /* show nested folders? */
+static int showzero = TRUE; /* show folders even if no messages in seq? */
+static int fastsw = FALSE; /* display info on number of messages in
+ * sequence found, and total num messages */
-static char curfolder[BUFSIZ]; /* name of the current folder */
-static char *nmhdir; /* base nmh mail directory */
+static char curfol[BUFSIZ]; /* name of the current folder */
+static char *nmhdir; /* base nmh mail directory */
/*
- * Type for a compare function for qsort. This keeps
- * the compiler happy.
- */
+** Type for a compare function for qsort. This keeps
+** the compiler happy.
+*/
typedef int (*qsort_comp) (const void *, const void *);
/*
- * prototypes
- */
+** prototypes
+*/
int CompareFolders(struct Folder *, struct Folder *);
void GetFolderOrder(void);
void ScanFolders(void);
void BuildFolderList(char *, int);
void BuildFolderListRecurse(char *, struct stat *, int);
void PrintFolders(void);
-static int num_digits (int);
void AllocFolders(struct Folder **, int *, int);
int AssignPriority(char *);
static void do_readonly_folders(void);
int
main(int argc, char **argv)
{
- char *cp, **argp;
- char **arguments;
- char buf[BUFSIZ];
-
-#ifdef LOCALE
- setlocale(LC_ALL, "");
-#endif
- invo_name = r1bindex(argv[0], '/');
-
- /* read user profile/context */
- context_read();
-
- /*
- * If program was invoked with name ending
- * in `s', then add switch `-all'.
- */
- if (argv[0][strlen (argv[0]) - 1] == 's')
- all = TRUE;
-
- arguments = getarguments (invo_name, argc, argv, 1);
- argp = arguments;
-
- /* allocate the initial space to record the folder names */
- numfolders = 0;
- maxfolders = MAXFOLDERS;
- foldersToDo = (char **) mh_xmalloc ((size_t) (maxfolders * sizeof(*foldersToDo)));
-
- /* no sequences yet */
- numsequences = 0;
-
- /* parse arguments */
- while ((cp = *argp++)) {
- if (*cp == '-') {
- switch (smatch(++cp, switches)) {
- case AMBIGSW:
- ambigsw(cp, switches);
- done(1);
- case UNKWNSW:
- adios(NULL, "-%s unknown", cp);
-
- case HELPSW:
- snprintf(buf, sizeof(buf), "%s [+folder1 [+folder2 ...]][switches]",
- invo_name);
- print_help(buf, switches, 1);
- done(1);
- case VERSIONSW:
- print_version(invo_name);
- done (1);
-
- case SEQSW:
- if (!(cp = *argp++) || *cp == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
-
- /* check if too many sequences specified */
- if (numsequences >= NUMATTRS)
- adios (NULL, "too many sequences (more than %d) specified", NUMATTRS);
- sequencesToDo[numsequences++] = cp;
- break;
-
- case ALLSW:
+ char *cp, **argp;
+ char **arguments;
+ char buf[BUFSIZ];
+
+ setlocale(LC_ALL, "");
+ invo_name = mhbasename(argv[0]);
+
+ /* read user profile/context */
+ context_read();
+
+ /*
+ ** If program was invoked with name ending
+ ** in `s', then add switch `-all'.
+ */
+ if (argv[0][strlen(argv[0]) - 1] == 's')
all = TRUE;
- break;
- case NOALLSW:
- all = FALSE;
- break;
-
- case SHOWZERO:
- showzero = TRUE;
- break;
- case NOSHOWZERO:
- showzero = FALSE;
- break;
-
- case ALPHASW:
- alphaOrder = TRUE;
- break;
- case NOALPHASW:
- alphaOrder = FALSE;
- break;
-
- case NOFASTSW:
- case TOTALSW:
- Total = TRUE;
- break;
-
- case FASTSW:
- case NOTOTALSW:
- Total = FALSE;
- break;
-
- case RECURSE:
- recurse = TRUE;
- break;
- case NORECURSE:
- recurse = FALSE;
- break;
- }
- } else {
- /*
- * Check if we need to allocate more space
- * for folder names.
- */
- if (numfolders >= maxfolders) {
- maxfolders += MAXFOLDERS;
- if (!(foldersToDo = (char **) realloc (foldersToDo,
- (size_t) (maxfolders * sizeof(*foldersToDo)))))
- adios (NULL, "unable to reallocate folder name storage");
- }
- if (*cp == '+' || *cp == '@') {
- foldersToDo[numfolders++] =
- path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
- } else
- foldersToDo[numfolders++] = cp;
+
+ arguments = getarguments(invo_name, argc, argv, 1);
+ argp = arguments;
+
+ /* allocate the initial space to record the folder names */
+ numfolders = 0;
+ maxfolders = MAXFOLDERS;
+ foldersToDo = mh_xcalloc(maxfolders, sizeof(*foldersToDo));
+
+ /* no sequences yet */
+ numsequences = 0;
+
+ /* parse arguments */
+ while ((cp = *argp++)) {
+ if (*cp == '-') {
+ switch (smatch(++cp, switches)) {
+ case AMBIGSW:
+ ambigsw(cp, switches);
+ exit(EX_USAGE);
+ case UNKWNSW:
+ adios(EX_USAGE, NULL, "-%s unknown", cp);
+
+ case HELPSW:
+ snprintf(buf, sizeof(buf), "%s [+folder1 [+folder2 ...]][switches]", invo_name);
+ print_help(buf, switches, 1);
+ exit(argc == 2 ? EX_OK : EX_USAGE);
+
+ case VERSIONSW:
+ print_version(invo_name);
+ exit(argc == 2 ? EX_OK : EX_USAGE);
+
+ case SEQSW:
+ if (!(cp = *argp++) || *cp == '-')
+ adios(EX_USAGE, NULL, "missing argument to %s",
+ argp[-2]);
+
+ /* check if too many sequences specified */
+ if (numsequences >= NUMATTRS)
+ adios(EX_USAGE, NULL, "too many sequences (more than %d) specified", NUMATTRS);
+ sequencesToDo[numsequences++] = cp;
+ break;
+
+ case ALLSW:
+ all = TRUE;
+ break;
+ case NOALLSW:
+ all = FALSE;
+ break;
+
+ case SHOWZERO:
+ showzero = TRUE;
+ break;
+ case NOSHOWZERO:
+ showzero = FALSE;
+ break;
+
+ case ALPHASW:
+ alphaOrder = TRUE;
+ break;
+ case NOALPHASW:
+ alphaOrder = FALSE;
+ break;
+
+ case FASTSW:
+ fastsw = TRUE;
+ break;
+ case NOFASTSW:
+ fastsw = FALSE;
+ break;
+
+ case RECURSE:
+ recurse = TRUE;
+ break;
+ case NORECURSE:
+ recurse = FALSE;
+ break;
+ }
+ } else {
+ /*
+ ** Check if we need to allocate more space
+ ** for folder names.
+ */
+ if (numfolders >= maxfolders) {
+ maxfolders += MAXFOLDERS;
+ foldersToDo = mh_xrealloc(foldersToDo, maxfolders * sizeof(*foldersToDo));
+ }
+ if (*cp == '+' || *cp == '@') {
+ foldersToDo[numfolders++] = mh_xstrdup(expandfol(cp));
+ } else
+ foldersToDo[numfolders++] = cp;
+ }
}
- }
-
- if (!context_find ("path"))
- free (path ("./", TFOLDER));
-
- /* get current folder */
- strncpy (curfolder, getfolder(1), sizeof(curfolder));
-
- /* get nmh base directory */
- nmhdir = m_maildir ("");
-
- /*
- * If we didn't specify any sequences, we search
- * for the "Unseen-Sequence" profile entry and use
- * all the sequences defined there. We check to
- * make sure that the Unseen-Sequence entry doesn't
- * contain more than NUMATTRS sequences.
- */
- if (numsequences == 0) {
- if ((cp = context_find(usequence)) && *cp) {
- char **ap, *dp;
-
- dp = getcpy(cp);
- ap = brkstring (dp, " ", "\n");
- for (; ap && *ap; ap++) {
- if (numsequences >= NUMATTRS)
- adios (NULL, "too many sequences (more than %d) in %s profile entry",
- NUMATTRS, usequence);
- else
- sequencesToDo[numsequences++] = *ap;
- }
- } else {
- adios (NULL, "no sequence specified or %s profile entry found", usequence);
+
+ /* get current folder */
+ strncpy(curfol, getcurfol(), sizeof(curfol));
+
+ /* get nmh base directory */
+ nmhdir = toabsdir("+");
+
+ /*
+ ** If no sequences specified, we use the `unseen' sequence(s)
+ ** We check to make sure that the Unseen-Sequence entry doesn't
+ ** contain too many sequences.
+ */
+ if (numsequences == 0) {
+ char **ap, *dp;
+
+ if ((cp = context_find(usequence))) {
+ if (!*cp) {
+ adios(EX_CONFIG, NULL, "profile entry %s set, but empty, and no sequence given", usequence);
+ }
+ } else {
+ cp = seq_unseen; /* use default */
+ }
+ dp = mh_xstrdup(cp);
+ ap = brkstring(dp, " ", "\n");
+ for (; ap && *ap; ap++) {
+ if (numsequences >= NUMATTRS) {
+ adios(EX_USAGE, NULL, "too many sequences (more than %d) in %s profile entry", NUMATTRS, usequence);
+ } else {
+ sequencesToDo[numsequences++] = *ap;
+ }
+ }
}
- }
- GetFolderOrder();
- ScanFolders();
- qsort(folders, nFolders, sizeof(struct Folder), (qsort_comp) CompareFolders);
- PrintFolders();
- return done (0);
+ GetFolderOrder();
+ ScanFolders();
+ qsort(folders, nFolders, sizeof(struct Folder),
+ (qsort_comp) CompareFolders);
+ PrintFolders();
+ return EX_OK;
}
/*
- * Read the Flist-Order profile entry to determine
- * how to sort folders for output.
- */
+** Read the Flist-Order profile entry to determine
+** how to sort folders for output.
+*/
void
GetFolderOrder(void)
{
- char *p, *s;
- int priority = 1;
- struct Folder *o;
-
- if (!(p = context_find("Flist-Order")))
- return;
- for (;;) {
- while (isspace(*p))
- ++p;
- s = p;
- while (*p && !isspace(*p))
- ++p;
- if (p != s) {
- /* Found one. */
- AllocFolders(&orders, &nOrdersAlloced, nOrders + 1);
- o = &orders[nOrders++];
- o->priority = priority++;
- o->name = (char *) mh_xmalloc(p - s + 1);
- strncpy(o->name, s, p - s);
- o->name[p - s] = 0;
- } else
- break;
- }
+ unsigned char *p, *s;
+ int priority = 1;
+ struct Folder *o;
+
+ if (!(p = context_find("Flist-Order")))
+ return;
+ for (;;) {
+ while (isspace(*p))
+ ++p;
+ s = p;
+ while (*p && !isspace(*p))
+ ++p;
+ if (p != s) {
+ /* Found one. */
+ AllocFolders(&orders, &nOrdersAlloced, nOrders + 1);
+ o = &orders[nOrders++];
+ o->priority = priority++;
+ o->name = mh_xcalloc(p - s + 1, sizeof(char));
+ strncpy(o->name, s, p - s);
+ o->name[p - s] = 0;
+ } else
+ break;
+ }
}
/*
- * Scan all the necessary folders
- */
+** Scan all the necessary folders
+*/
void
ScanFolders(void)
{
- int i;
-
- /*
- * change directory to base of nmh directory
- */
- if (chdir (nmhdir) == NOTOK)
- adios (nmhdir, "unable to change directory to");
-
- if (numfolders > 0) {
- /* Update context */
- strncpy (curfolder, foldersToDo[numfolders - 1], sizeof(curfolder));
- context_replace (pfolder, curfolder);/* update current folder */
- context_save (); /* save the context file */
+ int i;
/*
- * Scan each given folder. If -all is given,
- * then also scan the 1st level subfolders under
- * each given folder.
+ * change directory to base of nmh directory
*/
- for (i = 0; i < numfolders; ++i)
- BuildFolderList(foldersToDo[i], all ? 1 : 0);
- } else {
- if (all) {
- /*
- * Do the readonly folders
- */
- do_readonly_folders();
-
- /*
- * Now scan the entire nmh directory for folders
- */
- BuildFolderList(".", 0);
+ if (chdir(nmhdir) == NOTOK)
+ adios(EX_OSERR, nmhdir, "unable to change directory to");
+
+ if (numfolders > 0) {
+ /* Update context */
+ strncpy(curfol, foldersToDo[numfolders - 1], sizeof(curfol));
+ context_replace(curfolder, curfol); /* update current folder */
+ context_save(); /* save the context file */
+
+ /*
+ ** Scan each given folder. If -all is given,
+ ** then also scan the 1st level subfolders under
+ ** each given folder.
+ */
+ for (i = 0; i < numfolders; ++i)
+ BuildFolderList(foldersToDo[i], all ? 1 : 0);
} else {
- /*
- * Else scan current folder
- */
- BuildFolderList(curfolder, 0);
+ if (all) {
+ /* Do the readonly folders */
+ do_readonly_folders();
+
+ /* Now scan the entire nmh directory for folders */
+ BuildFolderList(".", 0);
+ } else {
+ /* Else scan current folder */
+ BuildFolderList(curfol, 0);
+ }
}
- }
}
/*
- * Initial building of folder list for
- * the top of our search tree.
- */
+** Initial building of folder list for
+** the top of our search tree.
+*/
void
BuildFolderList(char *dirName, int searchdepth)
{
- struct stat st;
-
- /* Make sure we have a directory */
- if ((stat(dirName, &st) == -1) || !S_ISDIR(st.st_mode))
- return;
-
- /*
- * If base directory, don't add it to the
- * folder list. We just recurse into it.
- */
- if (!strcmp (dirName, ".")) {
- BuildFolderListRecurse (".", &st, 0);
- return;
- }
-
- /*
- * Add this folder to the list.
- * If recursing and directory has subfolders,
- * then build folder list for subfolders.
- */
- if (AddFolder(dirName, showzero) && (recurse || searchdepth) && st.st_nlink > 2)
- BuildFolderListRecurse(dirName, &st, searchdepth - 1);
+ struct stat st;
+
+ /* Make sure we have a directory */
+ if ((stat(dirName, &st) == -1) || !S_ISDIR(st.st_mode))
+ return;
+
+ /*
+ ** If base directory, don't add it to the
+ ** folder list. We just recurse into it.
+ */
+ if (strcmp(dirName, ".")==0) {
+ BuildFolderListRecurse(".", &st, 0);
+ return;
+ }
+
+ /*
+ ** Add this folder to the list.
+ ** If recursing and directory has subfolders,
+ ** then build folder list for subfolders.
+ */
+ if (AddFolder(dirName, showzero) && (recurse || searchdepth) &&
+ st.st_nlink > 2)
+ BuildFolderListRecurse(dirName, &st, searchdepth - 1);
}
/*
- * Recursive building of folder list
- */
+** Recursive building of folder list
+*/
void
BuildFolderListRecurse(char *dirName, struct stat *s, int searchdepth)
{
- char *base, *n, name[PATH_MAX];
- int nlinks;
- DIR *dir;
- struct dirent *dp;
- struct stat st;
-
- /*
- * Keep track of number of directories we've seen so we can
- * stop stat'ing entries in this directory once we've seen
- * them all. This optimization will fail if you have extra
- * directories beginning with ".", since we don't bother to
- * stat them. But that shouldn't generally be a problem.
- */
- nlinks = s->st_nlink;
-
- if (!(dir = opendir(dirName)))
- adios(dirName, "can't open directory");
-
- /*
- * A hack so that we don't see a
- * leading "./" in folder names.
- */
- base = strcmp (dirName, ".") ? dirName : dirName + 1;
-
- while (nlinks && (dp = readdir(dir))) {
- if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) {
- nlinks--;
- continue;
- }
- if (dp->d_name[0] == '.')
- continue;
- /* Check to see if the name of the file is a number
- * if it is, we assume it's a mail file and skip it
- */
- for (n = dp->d_name; *n && isdigit(*n); n++);
- if (!*n)
- continue;
- strncpy (name, base, sizeof(name) - 2);
- if (*base)
- strcat(name, "/");
- strncat(name, dp->d_name, sizeof(name) - strlen(name) - 1);
- if ((stat(name, &st) != -1) && S_ISDIR(st.st_mode)) {
- /*
- * Check if this was really a symbolic link pointing
- * to a directory. If not, then decrement link count.
- */
- if (lstat (name, &st) == -1)
- nlinks--;
- /* Add this folder to the list */
- if (AddFolder(name, showzero) &&
- (recurse || searchdepth) && st.st_nlink > 2)
- BuildFolderListRecurse(name, &st, searchdepth - 1);
+ char *base, name[PATH_MAX];
+ unsigned char *n;
+ int nlinks;
+ DIR *dir;
+ struct dirent *dp;
+ struct stat st;
+
+ /*
+ ** Keep track of number of directories we've seen so we can
+ ** stop stat'ing entries in this directory once we've seen
+ ** them all. This optimization will fail if you have extra
+ ** directories beginning with ".", since we don't bother to
+ ** stat them. But that shouldn't generally be a problem.
+ */
+ nlinks = s->st_nlink;
+
+ if (!(dir = opendir(dirName)))
+ adios(EX_IOERR, dirName, "can't open directory");
+
+ /*
+ ** A hack so that we don't see a
+ ** leading "./" in folder names.
+ */
+ base = (strcmp(dirName, ".")==0) ? dirName + 1 : dirName;
+
+ while (nlinks && (dp = readdir(dir))) {
+ if (strcmp(dp->d_name, ".")==0 ||
+ strcmp(dp->d_name, "..")==0) {
+ nlinks--;
+ continue;
+ }
+ if (dp->d_name[0] == '.')
+ continue;
+ /* Check to see if the name of the file is a number
+ ** if it is, we assume it's a mail file and skip it
+ */
+ for (n = dp->d_name; *n && isdigit(*n); n++);
+ if (!*n)
+ continue;
+ strncpy(name, base, sizeof(name) - 2);
+ if (*base)
+ strcat(name, "/");
+ strncat(name, dp->d_name, sizeof(name) - strlen(name) - 1);
+ if ((stat(name, &st) != -1) && S_ISDIR(st.st_mode)) {
+ /*
+ ** Check if this was really a symbolic link pointing
+ ** to a directory. If not, then decrement link count.
+ */
+ if (lstat(name, &st) == -1)
+ nlinks--;
+ /* Add this folder to the list */
+ if (AddFolder(name, showzero) &&
+ (recurse || searchdepth) &&
+ st.st_nlink > 2)
+ BuildFolderListRecurse(name, &st,
+ searchdepth - 1);
+ }
}
- }
- closedir(dir);
+ closedir(dir);
}
/*
- * Add this folder to our list, counting the total number of
- * messages and the number of messages in each sequence.
- */
+** Add this folder to our list, counting the total number of
+** messages and the number of messages in each sequence.
+*/
int
AddFolder(char *name, int force)
{
- int i, msgnum, nonzero;
- int seqnum[NUMATTRS], nSeq[NUMATTRS];
- struct Folder *f;
- struct msgs *mp;
-
- /* Read folder and create message structure */
- if (!(mp = folder_read (name))) {
- /* Oops, error occurred. Record it and continue. */
- AllocFolders(&folders, &nFoldersAlloced, nFolders + 1);
- f = &folders[nFolders++];
- f->name = getcpy(name);
- f->error = 1;
- f->priority = AssignPriority(f->name);
- return 0;
- }
-
- for (i = 0; i < numsequences; i++) {
- /* Convert sequences to their sequence numbers */
- if (sequencesToDo[i])
- seqnum[i] = seq_getnum(mp, sequencesToDo[i]);
- else
- seqnum[i] = -1;
-
- /* Now count messages in this sequence */
- nSeq[i] = 0;
- if (mp->nummsg > 0 && seqnum[i] != -1) {
- for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) {
- if (in_sequence(mp, seqnum[i], msgnum))
- nSeq[i]++;
- }
+ unsigned int i;
+ int msgnum, nonzero;
+ int seqnum[NUMATTRS], nSeq[NUMATTRS];
+ struct Folder *f;
+ struct msgs *mp;
+
+ /* Read folder and create message structure */
+ if (!(mp = folder_read(name))) {
+ /* Oops, error occurred. Record it and continue. */
+ AllocFolders(&folders, &nFoldersAlloced, nFolders + 1);
+ f = &folders[nFolders++];
+ f->name = mh_xstrdup(name);
+ f->error = 1;
+ f->priority = AssignPriority(f->name);
+ return 0;
}
- }
-
- /* Check if any of the sequence checks were nonzero */
- nonzero = 0;
- for (i = 0; i < numsequences; i++) {
- if (nSeq[i] > 0) {
- nonzero = 1;
- break;
+
+ for (i = 0; i < numsequences; i++) {
+ /* Convert sequences to their sequence numbers */
+ if (sequencesToDo[i])
+ seqnum[i] = seq_getnum(mp, sequencesToDo[i]);
+ else
+ seqnum[i] = -1;
+
+ /* Now count messages in this sequence */
+ nSeq[i] = 0;
+ if (mp->nummsg > 0 && seqnum[i] != -1) {
+ for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg;
+ msgnum++) {
+ if (in_sequence(mp, seqnum[i], msgnum))
+ nSeq[i]++;
+ }
+ }
}
- }
-
- if (nonzero || force) {
- /* save general folder information */
- AllocFolders(&folders, &nFoldersAlloced, nFolders + 1);
- f = &folders[nFolders++];
- f->name = getcpy(name);
- f->nMsgs = mp->nummsg;
- f->error = 0;
- f->priority = AssignPriority(f->name);
-
- /* record the sequence information */
+
+ /* Check if any of the sequence checks were nonzero */
+ nonzero = 0;
for (i = 0; i < numsequences; i++) {
- f->nSeq[i] = nSeq[i];
- f->private[i] = (seqnum[i] != -1) ? is_seq_private(mp, seqnum[i]) : 0;
+ if (nSeq[i] > 0) {
+ nonzero = 1;
+ break;
+ }
+ }
+
+ if (nonzero || force) {
+ /* save general folder information */
+ AllocFolders(&folders, &nFoldersAlloced, nFolders + 1);
+ f = &folders[nFolders++];
+ f->name = mh_xstrdup(name);
+ f->nMsgs = mp->nummsg;
+ f->error = 0;
+ f->priority = AssignPriority(f->name);
+
+ /* record the sequence information */
+ for (i = 0; i < numsequences; i++) {
+ f->nSeq[i] = nSeq[i];
+ f->private[i] = (seqnum[i] != -1) ?
+ is_seq_private(mp, seqnum[i]) : 0;
+ }
}
- }
- folder_free (mp); /* free folder/message structure */
- return 1;
+ folder_free(mp); /* free folder/message structure */
+ return 1;
}
/*
- * Print the folder/sequence information
- */
+** Print the folder/sequence information
+*/
void
PrintFolders(void)
{
- char tmpname[BUFSIZ];
- int i, j, len, has_private = 0;
- int maxfolderlen = 0, maxseqlen = 0;
- int maxnum = 0, maxseq = 0;
-
- if (!Total) {
- for (i = 0; i < nFolders; i++)
- printf("%s\n", folders[i].name);
- return;
- }
-
- /*
- * Find the width we need for various fields
- */
- for (i = 0; i < nFolders; ++i) {
- /* find the length of longest folder name */
- len = strlen(folders[i].name);
- if (len > maxfolderlen)
- maxfolderlen = len;
-
- /* If folder had error, skip the rest */
- if (folders[i].error)
- continue;
-
- /* find the maximum total messages */
- if (folders[i].nMsgs > maxnum)
- maxnum = folders[i].nMsgs;
-
- for (j = 0; j < numsequences; j++) {
- /* find maximum width of sequence name */
- len = strlen (sequencesToDo[j]);
- if ((folders[i].nSeq[j] > 0 || showzero) && (len > maxseqlen))
- maxseqlen = len;
-
- /* find the maximum number of messages in sequence */
- if (folders[i].nSeq[j] > maxseq)
- maxseq = folders[i].nSeq[j];
-
- /* check if this sequence is private in any of the folders */
- if (folders[i].private[j])
- has_private = 1;
+ char tmpname[BUFSIZ];
+ unsigned int i, j, len, has_private = 0;
+ unsigned int maxfolderlen = 0, maxseqlen = 0;
+ int maxnum = 0, maxseq = 0;
+
+ if (fastsw) {
+ for (i = 0; i < nFolders; i++)
+ printf("%s\n", folders[i].name);
+ return;
}
- }
-
- /* Now print all the folder/sequence information */
- for (i = 0; i < nFolders; i++) {
- for (j = 0; j < numsequences; j++) {
- if (folders[i].nSeq[j] > 0 || showzero) {
- /* Add `+' to end of name of current folder */
- if (strcmp(curfolder, folders[i].name))
- snprintf(tmpname, sizeof(tmpname), "%s", folders[i].name);
- else
- snprintf(tmpname, sizeof(tmpname), "%s+", folders[i].name);
- if (folders[i].error) {
- printf("%-*s is unreadable\n", maxfolderlen+1, tmpname);
- continue;
+ /*
+ ** Find the width we need for various fields
+ */
+ for (i = 0; i < nFolders; ++i) {
+ /* find the length of longest folder name */
+ len = strlen(folders[i].name);
+ if (len > maxfolderlen)
+ maxfolderlen = len;
+
+ /* If folder had error, skip the rest */
+ if (folders[i].error)
+ continue;
+
+ /* find the maximum total messages */
+ if (folders[i].nMsgs > maxnum)
+ maxnum = folders[i].nMsgs;
+
+ for (j = 0; j < numsequences; j++) {
+ /* find maximum width of sequence name */
+ len = strlen(sequencesToDo[j]);
+ if ((folders[i].nSeq[j] > 0 || showzero) &&
+ (len > maxseqlen))
+ maxseqlen = len;
+
+ /* find the maximum number of messages in sequence */
+ if (folders[i].nSeq[j] > maxseq)
+ maxseq = folders[i].nSeq[j];
+
+ /*
+ ** check if this sequence is private in any of
+ ** the folders
+ */
+ if (folders[i].private[j])
+ has_private = 1;
}
-
- printf("%-*s has %*d in sequence %-*s%s; out of %*d\n",
- maxfolderlen+1, tmpname,
- num_digits(maxseq), folders[i].nSeq[j],
- maxseqlen, sequencesToDo[j],
- !has_private ? "" : folders[i].private[j] ? " (private)" : " ",
- num_digits(maxnum), folders[i].nMsgs);
- }
}
- }
-}
-
-/*
- * Calculate the number of digits in a nonnegative integer
- */
-static int
-num_digits (int n)
-{
- int ndigits = 0;
-
- /* Sanity check */
- if (n < 0)
- adios (NULL, "oops, num_digits called with negative value");
-
- if (n == 0)
- return 1;
-
- while (n) {
- n /= 10;
- ndigits++;
- }
- return ndigits;
+ /* Now print all the folder/sequence information */
+ for (i = 0; i < nFolders; i++) {
+ for (j = 0; j < numsequences; j++) {
+ if (folders[i].nSeq[j] > 0 || showzero) {
+ /* Add `+' to end of name of current folder */
+ if (strcmp(curfol, folders[i].name)!=0)
+ snprintf(tmpname, sizeof(tmpname),
+ "%s", folders[i].name);
+ else
+ snprintf(tmpname, sizeof(tmpname),
+ "%s+",
+ folders[i].name);
+
+ if (folders[i].error) {
+ printf("%-*s is unreadable\n",
+ maxfolderlen+1,
+ tmpname);
+ continue;
+ }
+
+ printf("%-*s has %*d in sequence %-*s%s; out of %*d\n", maxfolderlen+1, tmpname, num_digits(maxseq), folders[i].nSeq[j], maxseqlen, sequencesToDo[j], !has_private ? "" : folders[i].private[j] ? " (private)" : " ", num_digits(maxnum), folders[i].nMsgs);
+ }
+ }
+ }
}
/*
- * Put them in priority order.
- */
+** Put them in priority order.
+*/
int
CompareFolders(struct Folder *f1, struct Folder *f2)
{
- if (!alphaOrder && f1->priority != f2->priority)
- return f1->priority - f2->priority;
- else
- return strcmp(f1->name, f2->name);
+ if (!alphaOrder && f1->priority != f2->priority)
+ return f1->priority - f2->priority;
+ else
+ return strcmp(f1->name, f2->name);
}
/*
- * Make sure we have at least n folders allocated.
- */
+** Make sure we have at least n folders allocated.
+*/
void
AllocFolders(struct Folder **f, int *nfa, int n)
{
- if (n <= *nfa)
- return;
- if (*f == NULL) {
- *nfa = 10;
- *f = (struct Folder *) mh_xmalloc (*nfa * (sizeof(struct Folder)));
- } else {
- *nfa *= 2;
- *f = (struct Folder *) realloc (*f, *nfa * (sizeof(struct Folder)));
- }
+ if (n <= *nfa)
+ return;
+ if (*f == NULL) {
+ *nfa = 10;
+ *f = mh_xcalloc(*nfa, sizeof(struct Folder));
+ } else {
+ *nfa *= 2;
+ *f = mh_xrealloc(*f, *nfa * sizeof(struct Folder));
+ }
}
/*
- * Return the priority for a name. The highest comes from an exact match.
- * After that, the longest match (then first) assigns the priority.
- */
+** Return the priority for a name. The highest comes from an exact match.
+** After that, the longest match (then first) assigns the priority.
+*/
int
AssignPriority(char *name)
{
- int i, ol, nl;
- int best = nOrders;
- int bestLen = 0;
- struct Folder *o;
-
- nl = strlen(name);
- for (i = 0; i < nOrders; ++i) {
- o = &orders[i];
- if (!strcmp(name, o->name))
- return o->priority;
- ol = strlen(o->name);
- if (nl < ol - 1)
- continue;
- if (ol < bestLen)
- continue;
- if (o->name[0] == '*' && !strcmp(o->name + 1, name + (nl - ol + 1))) {
- best = o->priority;
- bestLen = ol;
- } else if (o->name[ol - 1] == '*' && strncmp(o->name, name, ol - 1) == 0) {
- best = o->priority;
- bestLen = ol;
+ int i, ol, nl;
+ int best = nOrders;
+ int bestLen = 0;
+ struct Folder *o;
+
+ nl = strlen(name);
+ for (i = 0; i < nOrders; ++i) {
+ o = &orders[i];
+ if (strcmp(name, o->name)==0)
+ return o->priority;
+ ol = strlen(o->name);
+ if (nl < ol - 1)
+ continue;
+ if (ol < bestLen)
+ continue;
+ if (o->name[0] == '*' &&
+ strcmp(o->name + 1, name + (nl - ol + 1))==0) {
+ best = o->priority;
+ bestLen = ol;
+ } else if (o->name[ol - 1] == '*' &&
+ strncmp(o->name, name, ol - 1) == 0) {
+ best = o->priority;
+ bestLen = ol;
+ }
}
- }
- return best;
+ return best;
}
/*
- * Do the read only folders
- */
+** Do the read only folders
+*/
static void
-do_readonly_folders (void)
+do_readonly_folders(void)
{
- int atrlen;
- char atrcur[BUFSIZ];
- register struct node *np;
-
- snprintf (atrcur, sizeof(atrcur), "atr-%s-", current);
- atrlen = strlen (atrcur);
-
- for (np = m_defs; np; np = np->n_next)
- if (ssequal (atrcur, np->n_name)
- && !ssequal (nmhdir, np->n_name + atrlen))
- BuildFolderList (np->n_name + atrlen, 0);
+ int atrlen;
+ char atrcur[BUFSIZ];
+ struct node *np;
+
+ snprintf(atrcur, sizeof(atrcur), "atr-%s-", seq_cur);
+ atrlen = strlen(atrcur);
+
+ for (np = m_defs; np; np = np->n_next)
+ if (strncmp(np->n_name, atrcur, atrlen)==0
+ && strncmp(np->n_name+atrlen, nmhdir, strlen(nmhdir))!=0)
+ /* Why do we exclude absolute path names? --meillo */
+ BuildFolderList(np->n_name + atrlen, 0);
}