/* This software is distributed under GNU General Public License, ver. 2 or higher (at your option), released by Free Software Foundation. You should receive text of the GNU GPL along with this software. If not, you can find it at: http://sageshome.net/GPL.php or http://www.gnu.org/ http://www.opensource.org/ Copyright(C) Sergey A. Galin, 2002-2004. Change Log: * Thu Nov 11 2004 Sergey Galin - v. 1.3 - Changed signature to allow processing of Eudora's mailboxes. - v. 1.2 - Added patch by Florian Feucht (fixed a bug of skipping first 2 chars from "From:" in the first message). */ #include #include #include #include #include #include #include #include #define VERSION "1.3" // Signature which separates messages: const char *const Separator="\nFrom "; // Number of symbols to skip in signature to start of the message: const int Rewind_Count=1; int Silent=0; #define MAXPATH 65535 #define NSPRINTF if(!Silent) printf int OutFile(const char *mdir){ char buf[MAXPATH]; sprintf(buf, "%s/mbox2mdirXXXXXX", mdir); return mkstemp(buf); } long strpos(const char *haystack, const char *needle){ size_t nl=strlen(needle); for(size_t i=0; haystack[i]!='\0'; i++) if(memcmp((haystack+i), needle, nl)==0) return i; return -1; } size_t strdistance(const char *haystack, const char *needle){ size_t nl=strlen(needle); for(size_t i=0; haystack[i]!='\0'; i++) if(memcmp((haystack+i), needle, nl)==0) return i; return strlen(haystack); } int FlushMail(const char *data, size_t sz, const char *dir){ int f; if((f=OutFile(dir))<0){ perror("Unable to create output file"); return 1; } write(f, data, sz); fchmod(f, 0666); close(f); return 0; } int Process(const char *ifile, const char *odir, int truncate){ int inf; size_t sz; struct stat buf; char *data, *seek; int count=0; inf=open(ifile, O_RDWR); NSPRINTF("Processing %s to %s...\n", ifile, odir); if(inf<0){ perror("Unable to open input file"); return 1; } if(flock(inf, LOCK_EX)==-1){ perror("Unable to lock input file"); return 1; } fstat(inf, &buf); sz=buf.st_size; if(sz>0){ data=(char *)malloc(sz+1); if(data==NULL){ perror("Cannot allocate buffer"); return 1; } read(inf, data, sz); data[sz]=0; seek=data; //size_t total=0; do{ size_t mailsz=strdistance(seek+1, Separator)+1; // printf("MAIL %d\n", mailsz); // Added patch by Florian Feucht (fixed a bug of skipping first 2 chars // from "From:" in the first message if (count==0) { // for the first time, no \n\n before mail starts. if(FlushMail(seek, mailsz, odir)){ perror("Error processing mail, terminating"); close(inf); return 1; }; }else{ if(FlushMail(seek+Rewind_Count, mailsz, odir)){ perror("Error processing mail, terminating"); close(inf); return 1; }; } count++; //total+=mailsz; seek++; }while((seek=strstr(seek, Separator))!=NULL); //printf("Total: %d\n", total); free(data); } if(truncate) if(ftruncate(inf, 0)<0) perror("Unable to truncate input file"); else NSPRINTF("Input Mailbox truncated."); close(inf); NSPRINTF("Processing %s to %s successful, %d messages (%d bytes) processed.\n", ifile, odir, count, sz); return 0; } int FindParam(const char *par, int argc, char *argv[]){ for(int i=0; i [options]\n" "OPTIONS: -t - Truncate input Maildir file after successful conversion.\n" " -s - Silent mode (error reporting only).\n" "EXAMPLE: $ mbox2mdir /var/qmail/alias/Mailbox /home/sergey/Maildir/cur -t\n"); }else{ int truncate=0; if(FindParam("-t", argc-3, argv+3)>=0) truncate=1; if(FindParam("-s", argc-3, argv+3)>=0) Silent=1; ifile=argv[1]; odir=argv[2]; return Process(ifile, odir, truncate); } }