/*
- * 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.
- */
+** 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 TRUE 1
/*
- * 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 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 */
+ * sequence found, and total num messages */
-static char curfolder[BUFSIZ]; /* name of the current folder */
+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);
#ifdef LOCALE
setlocale(LC_ALL, "");
#endif
- invo_name = r1bindex(argv[0], '/');
+ 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')
+ ** 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);
+ 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)));
+ foldersToDo = (char **) mh_xmalloc((size_t)
+ (maxfolders * sizeof(*foldersToDo)));
/* no sequences yet */
numsequences = 0;
adios(NULL, "-%s unknown", cp);
case HELPSW:
- snprintf(buf, sizeof(buf), "%s [+folder1 [+folder2 ...]][switches]",
- invo_name);
+ 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);
+ done(1);
case SEQSW:
if (!(cp = *argp++) || *cp == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
+ 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);
+ adios(NULL, "too many sequences (more than %d) specified", NUMATTRS);
sequencesToDo[numsequences++] = cp;
break;
}
} else {
/*
- * Check if we need to allocate more space
- * for folder names.
- */
+ ** Check if we need to allocate more space
+ ** for folder names.
+ */
if (numfolders >= maxfolders) {
maxfolders += MAXFOLDERS;
- foldersToDo = (char **) mh_xrealloc (foldersToDo,
- (size_t) (maxfolders * sizeof(*foldersToDo)));
+ foldersToDo = (char **) mh_xrealloc(foldersToDo, (size_t) (maxfolders * sizeof(*foldersToDo)));
}
if (*cp == '+' || *cp == '@') {
- foldersToDo[numfolders++] =
- pluspath (cp);
+ foldersToDo[numfolders++] = getcpy(expandfol(cp));
} else
foldersToDo[numfolders++] = cp;
}
}
- if (!context_find ("path"))
- free (path ("./", TFOLDER));
-
/* get current folder */
- strncpy (curfolder, getfolder(1), sizeof(curfolder));
+ strncpy(curfol, getcurfol(), sizeof(curfol));
/* get nmh base directory */
- nmhdir = m_maildir ("");
+ nmhdir = toabsdir("+");
/*
- * 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 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) {
- if ((cp = context_find(usequence)) && *cp) {
- char **ap, *dp;
+ 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;
+ if ((cp = context_find(usequence))) {
+ if (!*cp) {
+ adios(NULL, "profile entry %s set, but empty, and no sequence given", usequence);
}
} else {
- adios (NULL, "no sequence specified or %s profile entry found", usequence);
+ cp = seq_unseen; /* use default */
+ }
+ 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;
+ }
}
}
GetFolderOrder();
ScanFolders();
- qsort(folders, nFolders, sizeof(struct Folder), (qsort_comp) CompareFolders);
+ qsort(folders, nFolders, sizeof(struct Folder),
+ (qsort_comp) CompareFolders);
PrintFolders();
- done (0);
+ done(0);
return 1;
}
/*
- * 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)
}
/*
- * Scan all the necessary folders
- */
+** Scan all the necessary folders
+*/
void
ScanFolders(void)
/*
* change directory to base of nmh directory
*/
- if (chdir (nmhdir) == NOTOK)
- adios (nmhdir, "unable to change directory to");
+ 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 */
+ 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.
- */
+ ** 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 {
if (all) {
- /*
- * Do the readonly folders
- */
+ /* Do the readonly folders */
do_readonly_folders();
- /*
- * Now scan the entire nmh directory for folders
- */
+ /* Now scan the entire nmh directory for folders */
BuildFolderList(".", 0);
} else {
- /*
- * Else scan current folder
- */
- BuildFolderList(curfolder, 0);
+ /* 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)
return;
/*
- * If base directory, don't add it to the
- * folder list. We just recurse into it.
- */
- if (!strcmp (dirName, ".")) {
- BuildFolderListRecurse (".", &st, 0);
+ ** 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)
+ ** 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)
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.
- */
+ ** 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;
+ ** 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, ".") || !strcmp(dp->d_name, "..")) {
+ 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
- */
+ ** 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);
+ 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)
+ ** 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);
+ (recurse || searchdepth) &&
+ st.st_nlink > 2)
+ BuildFolderListRecurse(name, &st,
+ searchdepth - 1);
}
}
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)
struct msgs *mp;
/* Read folder and create message structure */
- if (!(mp = folder_read (name))) {
+ if (!(mp = folder_read(name))) {
/* Oops, error occurred. Record it and continue. */
AllocFolders(&folders, &nFoldersAlloced, nFolders + 1);
f = &folders[nFolders++];
/* Now count messages in this sequence */
nSeq[i] = 0;
if (mp->nummsg > 0 && seqnum[i] != -1) {
- for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) {
+ for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg;
+ msgnum++) {
if (in_sequence(mp, seqnum[i], msgnum))
nSeq[i]++;
}
/* 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;
+ f->private[i] = (seqnum[i] != -1) ?
+ is_seq_private(mp, seqnum[i]) : 0;
}
}
- folder_free (mp); /* free folder/message structure */
+ folder_free(mp); /* free folder/message structure */
return 1;
}
/*
- * Print the folder/sequence information
- */
+** Print the folder/sequence information
+*/
void
PrintFolders(void)
}
/*
- * Find the width we need for various fields
- */
+ ** 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);
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))
+ 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 */
+ /*
+ ** check if this sequence is private in any of
+ ** the folders
+ */
if (folders[i].private[j])
has_private = 1;
}
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);
+ if (strcmp(curfol, folders[i].name)!=0)
+ snprintf(tmpname, sizeof(tmpname),
+ "%s", folders[i].name);
else
- snprintf(tmpname, sizeof(tmpname), "%s+", folders[i].name);
+ snprintf(tmpname, sizeof(tmpname),
+ "%s+",
+ folders[i].name);
if (folders[i].error) {
- printf("%-*s is unreadable\n", maxfolderlen+1, tmpname);
+ 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);
+ 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)
}
/*
- * 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)
return;
if (*f == NULL) {
*nfa = 10;
- *f = (struct Folder *) mh_xmalloc (*nfa * (sizeof(struct Folder)));
+ *f = (struct Folder *) mh_xmalloc(
+ *nfa * (sizeof(struct Folder)));
} else {
*nfa *= 2;
- *f = (struct Folder *) mh_xrealloc (*f, *nfa * (sizeof(struct Folder)));
+ *f = (struct Folder *) 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)
{
nl = strlen(name);
for (i = 0; i < nOrders; ++i) {
o = &orders[i];
- if (!strcmp(name, o->name))
+ 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))) {
+ 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) {
+ } else if (o->name[ol - 1] == '*' &&
+ strncmp(o->name, name, ol - 1) == 0) {
best = o->priority;
bestLen = ol;
}
}
/*
- * 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);
+ snprintf(atrcur, sizeof(atrcur), "atr-%s-", seq_cur);
+ 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);
+ 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);
}