This is compactmail.m in view mode; [Download] [Up]
/* -*-C-*- ******************************************************************************* * * File: compactmail.m * RCS: /usr/local/sources/CVS/mailapp-utilities/compactmail.m,v 1.5 1997/05/31 21:52:27 tom Exp * Description: Compact Mail.app mailboxes (expunge deleted messages) * Author: Carl Edman * Created: Fri Mar 12 18:21:23 1993 * Modified: Sat May 31 18:08:13 1997 Tom Hageman <tom@basil.icce.rug.nl> * Language: Objective C * Package: mailapp-utilities * Status: First release. * * (C) Copyright 1993, but otherwise this file is perfect freeware. * ******************************************************************************* */ #import <libc.h> #import <errno.h> //#import <stdlib.h> //#import <stdio.h> //#import <string.h> //#import <time.h> #import <regex.h> //#import <sys/file.h> //#import <sys/param.h> //#import <sys/types.h> //#import <sys/stat.h> #import <defaults/defaults.h> #import "mailutil.h" #import "mailtoc.h" #import "optutil.h" #define USAGE "\ Usage: %s [-nruv] [-d days] [-f from] [-s subject] [-V|-H] mbox...\n" #define HELP "\ -n skip mailbox if locked\n\ -r expunge read messages too (default deleted messages only)\n\ -u expunge all messages (even unread)\n\ -v talkative mode\n\ -d days restrict to messages of at least `days' days old.\n\ -f from restrict to messages whose From: header matches (regexp)\n\ -s subject restrict to messages whose Subject: header matches (regexp)\n\ -V show version\n\ -H this help\n\ " char line[LINELEN]; int main(int ac,char *av[]) { char *buf=0; int c,pos; int nowaitflg=0,verboseflg=0,deletereadflg=0,deleteunreadflg=0; int days=-1; struct regex *subjectregexp=0,*fromregexp=0; time_t mboxtime; int mboxdis,tocdis,msgdis,changed; int mboxfd=-1; FILE *tocf=NULL; struct table_of_contents_header *toch=0; struct message_index *mi=0; int status=EXIT_SUCCESS; set_progname(av[0]); while((c=getopt(ac,av,"d:s:f:nruvVH"))!=EOF) switch(c) { case 'd': if (days!=-1 || (days=atoi(optarg))<=0) status=EXIT_USAGE; break; case 's': if (subjectregexp || !(subjectregexp=re_compile(optarg,0))) status=EXIT_USAGE; break; case 'f': if (fromregexp || !(fromregexp=re_compile(optarg,0))) status=EXIT_USAGE; break; case 'n': nowaitflg++; break; case 'r': deletereadflg++; break; case 'u': deleteunreadflg++; break; case 'v': verboseflg++; break; case 'V': status=EXIT_VERSION; break; case 'H': status=EXIT_HELP; break; case '?': default: status=EXIT_USAGE; } if (status==EXIT_SUCCESS && optind>=ac) status=EXIT_USAGE; handle_usage_help_version(status, USAGE, HELP); for(;optind<ac;optind++) { if (verboseflg) fprintf(stderr,"Entering %s...\n",av[optind]); if (cd_mbox(av[optind],1)) goto next; if (lock_mbox(nowaitflg)) goto next; mboxtime=mtime("mbox"); if (((mboxfd=open("mbox",O_RDWR))==-1) || ((tocf=fopen("table_of_contents","r+b"))==NULL)) { fprintf(stderr,"%s: opening %s: %s\n",progname(),av[optind],strerror(errno)); status=EXIT_FAILURE; goto unlock; } toch=get_table_of_contents_header(tocf,0); if (!toch) { fprintf(stderr,"%s: %s: invalid old table_of_contents\n",progname(),av[optind]); status=EXIT_FAILURE; goto unlock; } if (toch->mbox_time!=mboxtime) { fprintf(stderr,"%s: %s: table of contents out of sync\n",progname(),av[optind]); status=EXIT_FAILURE; goto unlock; } for(changed=FALSE,msgdis=mboxdis=tocdis=c=0;c<toch->num_msgs;c++) { if ((mi=get_message_index(tocf))==0) { fprintf(stderr,"%s: %s: reading old mbox entries: %s\n",progname(),av[optind],(errno?strerror(errno):"invalid")); status=EXIT_FAILURE; goto unlock; } if ((mi->status=='d' || mi->status=='D' || deleteunreadflg || (mi->status!='*' && deletereadflg)) && (days==-1 || message_age(mi)>=days) && (!subjectregexp || re_match(message_subject(mi),subjectregexp)) && (!fromregexp || re_match(message_from(mi),fromregexp))) { if (verboseflg>1) { fprintf(stderr,"Expunging \"%s\" from %s (%d days old).\n",message_subject(mi),message_from(mi),message_age(mi)); } if (mi->msgtype=='r') { char *dir=mi->data; dir+=strlen(dir)+1; dir+=strlen(dir)+1; if (*dir) { int pid,childpid=fork(); union wait status; switch (childpid) { case -1: break; case 0: execl("/bin/rm", "rm", "-rf", dir, NULL); _exit(255); default: while ((pid=wait(&status))>=0 && pid!=childpid) ; } } } changed=TRUE; msgdis++; tocdis +=mi->record_length; mboxdis+=mi->mes_length; } else { if (verboseflg>2) { fprintf(stderr,"Keeping \"%s\" from %s (%d days old).\n",message_subject(mi),message_from(mi),message_age(mi)); } if (mboxdis!=0) { lseek(mboxfd,mi->mes_offset,SEEK_SET); buf=malloc(mi->mes_length); read(mboxfd,buf,mi->mes_length); mi->mes_offset -= mboxdis; lseek(mboxfd,mi->mes_offset,SEEK_SET); write(mboxfd,buf,mi->mes_length); free(buf); buf=0; } if (tocdis!=0 || mboxdis!=0) { pos=ftell(tocf); fseek(tocf,-mi->record_length-tocdis,SEEK_CUR); put_message_index(tocf,mi); fseek(tocf,pos,SEEK_SET); } } free(mi); mi=0; } if (tocdis!=0) { fflush(tocf); pos=fseek(tocf,0,SEEK_END); ftruncate(fileno(tocf),pos-tocdis); } if (mboxdis!=0) { pos=lseek(mboxfd,0,SEEK_END); ftruncate(mboxfd,pos-mboxdis); } close(mboxfd), mboxfd=-1; toch->num_msgs-=msgdis; mboxtime=mtime("mbox"); if ((toch->mbox_time!=mboxtime) || changed) { toch->mbox_time=mboxtime; fseek(tocf,0,SEEK_SET); if (put_table_of_contents_header(tocf,toch)) { fprintf(stderr,"%s: %s: writing updated table_of_contents: %s\n",progname(),av[optind],strerror(errno)); status=EXIT_FAILURE; goto unlock; } } unlock: if(mboxfd>=0) close(mboxfd), mboxfd=-1; if(tocf!=NULL) fclose(tocf), tocf=NULL; unlock_mbox(); next:; if (toch) { free(toch); toch=0; } if (mi) { free(mi); mi=0; } if (buf) { free(buf); buf=0; } uncd_mbox(); } exit(status); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.