11 #define ARCHIVE_PREFIX "Archive-"
 
  13 char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 
  15 char fromdirectory[512];
 
  18 struct folder_list_t {
 
  21   struct folder_list_t *next;
 
  24 struct folder_list_t *folderhead;
 
  26 void move_email(const char *name, const char *folder)
 
  28   struct folder_list_t *lp;
 
  30   char oldfilename[512];
 
  33   for (lp = folderhead; lp->next; lp = lp->next)
 
  34     if (!strcmp(folder, lp->name))
 
  41     lp = malloc(sizeof(*folderhead));
 
  42     lp->next = folderhead;
 
  44     lp->name = strdup(folder);
 
  47     /* create the folder */
 
  48     sprintf(filename, ".INBOX.%s", folder);
 
  49     mkdir(filename, 0700);
 
  51     sprintf(filename, ".INBOX.%s/cur", folder);
 
  52     if (mkdir(filename, 0700) && (errno != EEXIST))
 
  58     sprintf(filename, ".INBOX.%s/new", folder);
 
  59     if (mkdir(filename, 0700) && (errno != EEXIST))
 
  65     sprintf(filename, ".INBOX.%s/tmp", folder);
 
  66     if (mkdir(filename, 0700) && (errno != EEXIST))
 
  72     sprintf(filename, ".INBOX.%s/maildirfolder", folder);
 
  73     if ((fd = open(filename, O_CREAT | O_WRONLY, 0700)) < 0)
 
  75       perror("open(maildirfolder)");
 
  83   sprintf(oldfilename, "%s/%s", fromdirectory, name);
 
  84   sprintf(filename, ".INBOX.%s/cur/%s", folder, name);
 
  86   /* skipped if it's the same thing, since the link won't catch it, and the unlink will kill it */
 
  87   if (!strcmp(oldfilename, filename))
 
  93   if (link(oldfilename, filename) && (errno != EEXIST))
 
  96     sprintf(theerror, "link(%s, %s)", oldfilename, filename);
 
 101   if (unlink(oldfilename))
 
 104     sprintf(theerror, "unlink(%s)", oldfilename);
 
 110 int spinnerstate = 0;
 
 111 char spinner[] = "/-\\|";
 
 112 #define SPINNERSTATES 4
 
 113 #define MAXAGE 7*24*60*60
 
 115 void main(int argc, char **argv)
 
 120   int emails = 0, notemails = 0, toonew = 0, starttime = time(NULL);
 
 124     strcpy(fromfolder, argv[1]);
 
 125     sprintf(fromdirectory, ".INBOX.%s/cur", fromfolder);
 
 126   } else if (argc == 1) {
 
 127     strcpy(fromdirectory, "cur");
 
 128     strcpy(fromfolder, "");
 
 130     printf("maildir-archiver: Usage: %s [<folder name>]\n", argv[0]);
 
 134   folderhead = malloc(sizeof(*folderhead));
 
 135   folderhead->next = NULL;
 
 137   printf("maildir-archiver: Opening %s/... ", fromdirectory);
 
 139   cur = opendir(fromdirectory);
 
 142     perror("opendir(cur)");
 
 145   dirstart = telldir(cur);
 
 148   printf("maildir-archiver: Doing preliminary scan of e-mails... .");
 
 150   while ((de = readdir(cur)))
 
 154     char archivefolder[128];
 
 156     tt = atoi(de->d_name);
 
 162     if ((starttime - tt) < MAXAGE)
 
 168     if ((emails % 10000) == 0)
 
 170       printf("\b%c", spinner[(spinnerstate++) % SPINNERSTATES]);
 
 174   printf("\bdone (%d mails to archive, %d too new, %d invalid)\n", emails, toonew, notemails);
 
 175   seekdir(cur, dirstart);
 
 177   printf("maildir-archiver: Archiving e-mail... [>                               ]");
 
 179   while ((de = readdir(cur)))
 
 181     static int progresscounter = 0;
 
 182     static int archived = 0;
 
 185     char archivefolder[128];
 
 190     tt = atoi(de->d_name);
 
 193     if ((starttime - tt) < MAXAGE)
 
 198     /* Open the file to determine if it's a mailing list or what */
 
 199     sprintf(fn, "%s/%s", fromdirectory, de->d_name);
 
 203       perror("fopen(fn, r)");
 
 208       while (fgets(line, 512, fp))
 
 210         if (!strncmp(line, "X-BeenThere: ", 13))
 
 212         if (!strncmp(line, "List-Unsubscribe: ", 18))
 
 214         if (!strncmp(line, "X-Mailing-List", 14))
 
 216         if (!strncmp(line, "Precedence: bulk", 16))
 
 225     /* sprintf(archivefolder, ARCHIVE_PREFIX "%d-%02d", 1900 + tm->tm_year, tm->tm_mon + 1); */
 
 226     sprintf(archivefolder, ARCHIVE_PREFIX "%d-Q%d-%s", 1900 + tm->tm_year, (tm->tm_mon) / 3 + 1, islist ? "List" : "Personal");
 
 227     move_email(de->d_name, archivefolder);
 
 230     if (((archived % 10) == 0) || (archived == emails))
 
 233       progresscounter = archived * 32 / emails;
 
 234       printf("\rmaildir-archiver: Archiving e-mail... [");
 
 235       for (i=0; i < progresscounter; i++)
 
 237       if (progresscounter != 32)
 
 239       for (i=0; i < (31 - progresscounter); i++)
 
 242       printf("%c ", spinner[(spinnerstate++) % SPINNERSTATES]);
 
 243       printf("%d/%d", archived, emails);
 
 248   printf("maildir-archiver: Statistics:\n");
 
 249   printf("maildir-archiver: All operations performed in %d seconds\n", time(NULL)-starttime);
 
 250   printf("maildir-archiver:\n");
 
 251   printf("maildir-archiver: -------------------------------+----------\n");
 
 252   printf("maildir-archiver: %-30s | Emails\n", "Status");
 
 253   printf("maildir-archiver: -------------------------------+----------\n");
 
 254   printf("maildir-archived: %-30s | %6d\n", "Processed", emails);
 
 255   printf("maildir-archived: %-30s | %6d\n", "Too new", toonew);
 
 256   printf("maildir-archived: %-30s | %6d\n", "Not an e-mail", notemails);
 
 257   printf("maildir-archived: %-30s | %6d\n", "Already in correct folder", skipped);
 
 258   printf("maildir-archiver: -------------------------------+----------\n");
 
 259   printf("maildir-archiver:\n");
 
 260   printf("maildir-archiver: -------------------------------+----------\n");
 
 261   printf("maildir-archiver: %-30s | Emails\n", "Folder");
 
 262   printf("maildir-archiver: -------------------------------+----------\n");
 
 264     struct folder_list_t *lp;
 
 267     for (lp = folderhead; lp->next; lp = lp->next)
 
 269       printf("maildir-archiver: %-30s | %6d\n", lp->name, lp->emails);
 
 272     printf("maildir-archiver: %-30s | %6d\n", "Total", total);
 
 274   printf("maildir-archiver: -------------------------------+----------\n");