]> diplodocus.org Git - nmh/blobdiff - uip/flist.c
Alter HasSuffixC()'s char * to be const.
[nmh] / uip / flist.c
index 0e2b16145a2deab0272e7de2639e7f1249f7dc70..089c76178b835d1541a9157076d8fdbe65ff8578 100644 (file)
  * 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$
  */
 
 #include <h/mh.h>
-
-#define FALSE   0
-#define TRUE    1
+#include <h/utils.h>
 
 /*
  * We allocate space to record the names of folders
 #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", 4 },
-    { NULL, 0 }
-};
+#define FLIST_SWITCHES \
+    X("sequence name", 0, SEQSW) \
+    X("all", 0, ALLSW) \
+    X("noall", 0, NOALLSW) \
+    X("recurse", 0, RECURSE) \
+    X("norecurse", 0, NORECURSE) \
+    X("showzero", 0, SHOWZERO) \
+    X("noshowzero", 0, NOSHOWZERO) \
+    X("alpha", 0, ALPHASW) \
+    X("noalpha", 0, NOALPHASW) \
+    X("fast", 0, FASTSW) \
+    X("nofast", 0, NOFASTSW) \
+    X("total", -5, TOTALSW) \
+    X("nototal", -7, NOTOTALSW) \
+    X("version", 0, VERSIONSW) \
+    X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(FLIST);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(FLIST, switches);
+#undef X
 
 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 */
+    ivector_t nSeq;            /* number of messages in each sequence  */
+    ivector_t private;         /* 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 */
@@ -84,8 +71,7 @@ static int numfolders;
 static int maxfolders;
 
 /* info on sequences to search for */
-static char *sequencesToDo[NUMATTRS];
-static int numsequences;
+static svector_t sequencesToDo;
 
 static int all        = FALSE;  /* scan all folders in top level?           */
 static int alphaOrder = FALSE; /* want alphabetical order only             */
@@ -113,7 +99,6 @@ int AddFolder(char *, int);
 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);
@@ -127,20 +112,13 @@ main(int argc, char **argv)
     char **arguments;
     char buf[BUFSIZ];
 
-#ifdef LOCALE
-    setlocale(LC_ALL, "");
-#endif
-    invo_name = r1bindex(argv[0], '/');
-
-    /* read user profile/context */
-    context_read();
+    if (nmh_init(argv[0], 1)) { return 1; }
 
     /*
      * If program was invoked with name ending
      * in `s', then add switch `-all'.
      */
-    if (argv[0][strlen (argv[0]) - 1] == 's')
-       all = TRUE;
+    all = HasSuffixC(argv[0], 's');
 
     arguments = getarguments (invo_name, argc, argv, 1);
     argp = arguments;
@@ -148,11 +126,10 @@ main(int argc, char **argv)
     /* allocate the initial space to record the folder names */
     numfolders = 0;
     maxfolders = MAXFOLDERS;
-    if (!(foldersToDo = (char **) malloc ((size_t) (maxfolders * sizeof(*foldersToDo)))))
-       adios (NULL, "unable to allocate folder storage");
+    foldersToDo = (char **) mh_xmalloc ((size_t) (maxfolders * sizeof(*foldersToDo)));
 
     /* no sequences yet */
-    numsequences = 0;
+    sequencesToDo = svector_create (0);
 
     /* parse arguments */
     while ((cp = *argp++)) {
@@ -168,19 +145,16 @@ main(int argc, char **argv)
                snprintf(buf, sizeof(buf), "%s [+folder1 [+folder2 ...]][switches]",
                        invo_name);
                print_help(buf, switches, 1);
-               done(1);
+               done(0);
            case VERSIONSW:
                print_version(invo_name);
-               done (1);
+               done (0);
 
            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;
+               svector_push_back (sequencesToDo, cp);
                break;
 
            case ALLSW:
@@ -228,13 +202,14 @@ main(int argc, char **argv)
             */
            if (numfolders >= maxfolders) {
                maxfolders += MAXFOLDERS;
-               if (!(foldersToDo = (char **) realloc (foldersToDo,
-                       (size_t) (maxfolders * sizeof(*foldersToDo)))))
-                   adios (NULL, "unable to reallocate folder name storage");
+               foldersToDo = (char **) mh_xrealloc (foldersToDo,
+                   (size_t) (maxfolders * sizeof(*foldersToDo)));
            }
-           if (*cp == '+')
-               ++cp;
-           foldersToDo[numfolders++] = cp;
+           if (*cp == '+' || *cp == '@') {
+               foldersToDo[numfolders++] =
+                   pluspath (cp);
+           } else
+               foldersToDo[numfolders++] = cp;
        }
     }
 
@@ -250,23 +225,16 @@ main(int argc, char **argv)
     /*
      * 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.
+     * all the sequences defined there.
      */
-    if (numsequences == 0) {
+    if (svector_size (sequencesToDo) == 0) {
        if ((cp = context_find(usequence)) && *cp) {
            char **ap, *dp;
 
-           dp = getcpy(cp);
+           dp = mh_xstrdup(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;
-           }
+           for (; ap && *ap; ap++)
+               svector_push_back (sequencesToDo, *ap);
        } else {
            adios (NULL, "no sequence specified or %s profile entry found", usequence);
        }
@@ -276,7 +244,9 @@ main(int argc, char **argv)
     ScanFolders();
     qsort(folders, nFolders, sizeof(struct Folder), (qsort_comp) CompareFolders);
     PrintFolders();
+    svector_free (sequencesToDo);
     done (0);
+    return 1;
 }
 
 /*
@@ -294,17 +264,17 @@ GetFolderOrder(void)
     if (!(p = context_find("Flist-Order")))
        return;
     for (;;) {
-       while (isspace(*p))
+       while (isspace((unsigned char) *p))
            ++p;
        s = p;
-       while (*p && !isspace(*p))
+       while (*p && !isspace((unsigned char) *p))
            ++p;
        if (p != s) {
            /* Found one. */
            AllocFolders(&orders, &nOrdersAlloced, nOrders + 1);
            o = &orders[nOrders++];
            o->priority = priority++;
-           o->name = (char *) malloc(p - s + 1);
+           o->name = (char *) mh_xmalloc(p - s + 1);
            strncpy(o->name, s, p - s);
            o->name[p - s] = 0;
        } else
@@ -400,6 +370,7 @@ void
 BuildFolderListRecurse(char *dirName, struct stat *s, int searchdepth)
 {
     char *base, name[PATH_MAX];
+    char *n;
     int nlinks;
     DIR *dir;
     struct dirent *dp;
@@ -413,6 +384,12 @@ BuildFolderListRecurse(char *dirName, struct stat *s, int searchdepth)
      * stat them.  But that shouldn't generally be a problem.
      */
     nlinks = s->st_nlink;
+    if (nlinks == 1) {
+      /* Disable the optimization under conditions where st_nlink
+         is set to 1.  That happens on Cygwin, for example:
+         http://cygwin.com/ml/cygwin-apps/2008-08/msg00264.html */
+      nlinks = INT_MAX;
+    }
 
     if (!(dir = opendir(dirName)))
        adios(dirName, "can't open directory");
@@ -430,6 +407,12 @@ BuildFolderListRecurse(char *dirName, struct stat *s, int searchdepth)
        }
        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((unsigned char) *n); n++);
+       if (!*n)
+           continue;
        strncpy (name, base, sizeof(name) - 2);
        if (*base)
            strcat(name, "/");
@@ -458,43 +441,45 @@ BuildFolderListRecurse(char *dirName, struct stat *s, int searchdepth)
 int
 AddFolder(char *name, int force)
 {
-    int i, msgnum, nonzero;
-    int seqnum[NUMATTRS], nSeq[NUMATTRS];
+    unsigned int i;
+    int msgnum, nonzero;
+    ivector_t seqnum = ivector_create (0), nSeq = ivector_create (0);
     struct Folder *f;
     struct msgs *mp;
+    char *cp;
 
     /* Read folder and create message structure */
-    if (!(mp = folder_read (name))) {
+    if (!(mp = folder_read (name, 0))) {
        /* Oops, error occurred.  Record it and continue. */
        AllocFolders(&folders, &nFoldersAlloced, nFolders + 1);
        f = &folders[nFolders++];
-       f->name = getcpy(name);
+       f->name = mh_xstrdup(name);
        f->error = 1;
        f->priority = AssignPriority(f->name);
        return 0;
     }
 
-    for (i = 0; i < numsequences; i++) {
+    for (i = 0; i < svector_size (sequencesToDo); i++) {
        /* Convert sequences to their sequence numbers */
-       if (sequencesToDo[i])
-           seqnum[i] = seq_getnum(mp, sequencesToDo[i]);
+       if ((cp = svector_at (sequencesToDo, i)))
+           ivector_push_back (seqnum, seq_getnum(mp, cp));
        else
-           seqnum[i] = -1;
+           ivector_push_back (seqnum, -1);
 
        /* Now count messages in this sequence */
-       nSeq[i] = 0;
-       if (mp->nummsg > 0 && seqnum[i] != -1) {
+       ivector_push_back (nSeq, 0);
+       if (mp->nummsg > 0 && ivector_at (seqnum, i) != -1) {
            for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) {
-               if (in_sequence(mp, seqnum[i], msgnum))
-                   nSeq[i]++;
+               if (in_sequence(mp, ivector_at (seqnum, i), msgnum))
+                   (*ivector_atp (nSeq, i))++;
            }
        }
     }
 
     /* Check if any of the sequence checks were nonzero */
     nonzero = 0;
-    for (i = 0; i < numsequences; i++) {
-       if (nSeq[i] > 0) {
+    for (i = 0; i < svector_size (sequencesToDo); i++) {
+       if (ivector_at (nSeq, i) > 0) {
            nonzero = 1;
            break;
        }
@@ -504,18 +489,25 @@ AddFolder(char *name, int force)
        /* save general folder information */
        AllocFolders(&folders, &nFoldersAlloced, nFolders + 1);
        f = &folders[nFolders++];
-       f->name = getcpy(name);
+       f->name = mh_xstrdup(name);
        f->nMsgs = mp->nummsg;
+       f->nSeq = ivector_create (0);
+       f->private = ivector_create (0);
        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;
+       for (i = 0; i < svector_size (sequencesToDo); i++) {
+           *ivector_atp (f->nSeq, i) = ivector_at (nSeq, i);
+           ivector_push_back (f->private,
+                              ivector_at (seqnum, i) != -1
+                              ? is_seq_private(mp, ivector_at (seqnum, i))
+                              : 0);
        }
     }
 
+    ivector_free (nSeq);
+    ivector_free (seqnum);
     folder_free (mp);  /* free folder/message structure */
     return 1;
 }
@@ -528,8 +520,8 @@ void
 PrintFolders(void)
 {
     char tmpname[BUFSIZ];
-    int i, j, len, has_private = 0;
-    int maxfolderlen = 0, maxseqlen = 0;
+    unsigned int i, j, len, has_private = 0;
+    unsigned int maxfolderlen = 0, maxseqlen = 0;
     int maxnum = 0, maxseq = 0;
 
     if (!Total) {
@@ -555,26 +547,27 @@ PrintFolders(void)
        if (folders[i].nMsgs > maxnum)
            maxnum = folders[i].nMsgs;
 
-       for (j = 0; j < numsequences; j++) {
+       for (j = 0; j < svector_size (sequencesToDo); j++) {
            /* find maximum width of sequence name */
-           len = strlen (sequencesToDo[j]);
-           if ((folders[i].nSeq[j] > 0 || showzero) && (len > maxseqlen))
+           len = strlen (svector_at (sequencesToDo, j));
+           if ((ivector_at (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];
+           if (ivector_at (folders[i].nSeq, j) > maxseq)
+               maxseq = ivector_at (folders[i].nSeq, j);
 
            /* check if this sequence is private in any of the folders */
-           if (folders[i].private[j])
+           if (ivector_at (folders[i].private, j))
                has_private = 1;
        }
     }
 
     /* 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) {
+       for (j = 0; j < svector_size (sequencesToDo); j++) {
+           if (ivector_at (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);
@@ -588,38 +581,16 @@ PrintFolders(void)
 
                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(maxseq), ivector_at (folders[i].nSeq, j),
+                      maxseqlen, svector_at (sequencesToDo, j),
+                      !has_private ? "" : ivector_at (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;
-}
-
 /*
  * Put them in priority order.
  */
@@ -629,8 +600,7 @@ 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);
+    return strcmp(f1->name, f2->name);
 }
 
 /*
@@ -644,10 +614,10 @@ AllocFolders(struct Folder **f, int *nfa, int n)
        return;
     if (*f == NULL) {
        *nfa = 10;
-       *f = (struct Folder *) malloc (*nfa * (sizeof(struct Folder)));
+       *f = (struct Folder *) mh_xmalloc (*nfa * (sizeof(struct Folder)));
     } else {
        *nfa *= 2;
-       *f = (struct Folder *) realloc (*f, *nfa * (sizeof(struct Folder)));
+       *f = (struct Folder *) mh_xrealloc (*f, *nfa * (sizeof(struct Folder)));
     }
 }
 
@@ -693,11 +663,7 @@ do_readonly_folders (void)
 {
     int atrlen;
     char atrcur[BUFSIZ];
-    register struct node *np;
-
-    /* sanity check - check that context has been read */
-    if (defpath == NULL)
-       adios (NULL, "oops, context hasn't been read yet");
+    struct node *np;
 
     snprintf (atrcur, sizeof(atrcur), "atr-%s-", current);
     atrlen = strlen (atrcur);