On Mon, Jul 20, 2009 at 07:24:48PM -0400, Tim Gray wrote:
> On Mon 20, Jul'09 at  4:54 PM -0600, lee wrote:
>> Maybe some sort of print statement was missing (cut off).
>
> Yeah I probably left it off or something.  It should look something like  
> this:
>
> for i in dirs:
>       print '"+l/%s"' % i,

Thanks! But see below ...

>> Is there an IMAP server that can handle maildir?
>
> I've not done it yet, but it was my understanding that UW-IMAP and 
> Dovecot at least both serve from maildir.  I think Courier might as well.

Now that would be cool! It's been a few years since I looked for one,
and I didn't find any that were able to use maildir.


Ok, I wrote a program to generate "mailboxes" lines for mutt. It will
print out those lines on stdout; errors and warnings go to
stdout.

Considered as maildirs are directories that have the subdirectories
cur, new and tmp. If the program finds such a directory, it prints a
mailbox line. In case it finds other directories and that directory,
it prints a warning to stdout. It looks like this:


l...@cat:~/src/c/systools/mutt-mailboxes$ ./mutt-mb .
mailboxes = /home/lee/src/c/systools/mutt-mailboxes/rel/tmaildir
warning:     1 strange directory/-ies found in 
/home/lee/src/c/systools/mutt-mailboxes/rel/tmaildir
l...@cat:~/src/c/systools/mutt-mailboxes$ 


If you have an extremely deep directory hierarchy and a low ulimit -s,
the program can run into a stack overflow because it operates recursively.


Here's the program. Let me know how you like it :)


// check a directory hierachy for maildir directories recursively; print
// mailbox commands that can be used for mutt
// error messages are printed to stdout
// print a warning to stderr when there are other directories
//   than cur, new, tmp found in a maildir
//
// (c) H. Wilmer, Mon Jul 20 17:17:45 MDT 2009
// l...@yun.yagibdah.de
// licensed under the GNU GENERAL PUBLIC LICENSE
// use at your own risk
//
// to compile: # gcc mutt-mb.c -o mutt-mb -O2
//
// version 0.1
//
// mutt-mb.c
//   returns !0 on error


#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>


// proto
int main(int argc, char *argv[] );
extern void usage();
int weed_out_nondirectories(const struct dirent *);
int scan_directory(char *dirp);



void usage() {
  fputs("usage: mutt-mb [directory]\n", stderr);
  fflush(stderr);
}


// filter function, see man 3 scandir
int weed_out_nondirectories(const struct dirent *de) {
  // weed out non-directories
  if(de->d_type != DT_DIR) {
    return 0;
  }
  // weed out directory pointers
  if( !strcmp(de->d_name, ".") ) {
    return 0;
  }
  if( !strcmp(de->d_name, "..") ) {
    return 0;
  }
  // it's a directory
  return 1;
}


int scan_directory(char *dirp) {
  static int recursion_level = 0;
  struct dirent **namelist;
  int scan = -1, check = 0;
  int ret = 0;
  int cwd = -1;
  char *this;
  int found_cur;
  int found_new;
  int found_tmp;
  int found_other;

  // change into the directory
  cwd = chdir(dirp);
  if(cwd < 0) {
    fputs(dirp, stderr);
    perror("chdir");
    return 2;
  }
  // and find out where we are
  this = getcwd(NULL, 0);
  if(this == NULL) {
    perror("getcwd");
    // this shouldn't happen, so rather exit
    return -1;
  }

  // scan this directory
  check = scan = scandir(this, &namelist, weed_out_nondirectories, alphasort);
  if(scan < 0) {
    perror("scandir");
    free(this);
    return 1;
  }

  // check if this is a maildir
  found_cur = 1;
  found_new = 1;
  found_tmp = 1;
  found_other = 0;
  while(check--) {
    //    printf("check %s/%s\n", this, namelist[check]->d_name);

    if(found_cur) {
      found_cur = strcmp("cur", namelist[check]->d_name);
    } else {
      found_other++;
    }
    if(found_new) {
      found_new = strcmp("new", namelist[check]->d_name);
    } else {
      found_other++;
    }
    if(found_tmp) {
      found_tmp = strcmp("tmp", namelist[check]->d_name);
    } else {
      found_other++;
    }

    if( !found_cur && !found_new && !found_tmp) {
      // it's a maildir
      printf("mailboxes = %s\n", this);
      found_other -= 3;
      if(found_other) {
        fprintf(stderr, "warning: %5d strange directory/-ies found in %s\n", \
                found_other, this);
      }
    }
  }

  free(this);

  // for each directory in this, look for subdirectories
  while(scan--) {
    recursion_level++;
    ret = scan_directory(namelist[scan]->d_name);
    switch(ret) {
    case 0:
      // means ok
      // there shouldn't be any errors ...
      break;
    case 2:
      fputs("couldn't change into subdirectory\n", stderr);
      fflush(stderr);
      return 2;
      break;
    case -1:
      fputs("coulnd't find out what the current directory is\n", stderr);
      fflush(stderr);
      return -1;
      break;
    case 1:
      fputs("couldn't scan a directory\n", stderr);
      fflush(stderr);
      return 1;
      break;
    case -2:
      fputs("couldn't change back to directory above\n", stderr);
      fflush(stderr);
      return -2;
      break;
    }
    free(namelist[scan]);
  }
  free(namelist);

  cwd = chdir("..");
  if(cwd < 0) {
    perror("chdir");
    // shouldn't happen
    return -2;
  }

  --recursion_level;
  return 0;
}


int main(int argc, char *argv[] ) {
  int ret = 0;
  // check args
  if(argc != 2) {
    usage();
    exit(1);
  }

  // scan the directory

  ret = scan_directory(argv[1]);
  if(ret) {
    fprintf(stderr, "error: %d\n", ret);
    exit(ret);
  }

  exit(0);
}

Reply via email to