📄 mix.c
字号:
return (char *) LOCAL->buf + i;}/* MIX mail fetch message text (body only) * Accepts: MAIL stream * message # to fetch * pointer to returned stringstruct * option flags * Returns: T on success, NIL on failure */long mix_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags){ unsigned long i; FDDATA d; MESSAGECACHE *elt; /* UID call "impossible" */ if (flags & FT_UID) return NIL; elt = mail_elt (stream,msgno); /* is message in current message file? */ if ((LOCAL->msgfd < 0) || (elt->private.spare.data != LOCAL->curmsg)) { if (LOCAL->msgfd >= 0) close (LOCAL->msgfd); if ((LOCAL->msgfd = open (mix_file_data (LOCAL->buf,stream->mailbox, elt->private.spare.data), O_RDONLY,NIL)) < 0) return NIL; /* got file */ LOCAL->curmsg = elt->private.spare.data; } /* doing non-peek fetch? */ if (!(flags & FT_PEEK) && !elt->seen) { FILE *idxf; /* yes, process metadata/index/status */ FILE *statf = mix_parse (stream,&idxf,NIL,LONGT); elt->seen = T; /* mark as seen */ MM_FLAGS (stream,elt->msgno); /* update status file if possible */ if (statf && !stream->rdonly) { elt->private.mod = LOCAL->statusseq = mix_modseq (LOCAL->statusseq); mix_status_update (stream,statf,NIL); } if (idxf) fclose (idxf); /* release index and status file */ if (statf) fclose (statf); } d.fd = LOCAL->msgfd; /* set up file descriptor */ /* offset of message text */ d.pos = elt->private.special.offset + elt->private.msg.header.offset + elt->private.msg.header.text.size; d.chunk = LOCAL->buf; /* initial buffer chunk */ d.chunksize = CHUNKSIZE; /* chunk size */ INIT (bs,fd_string,&d,elt->rfc822_size - elt->private.msg.header.text.size); return T;}/* MIX mail modify flags * Accepts: MAIL stream * sequence * flag(s) * option flags */void mix_flag (MAILSTREAM *stream,char *sequence,char *flag,long flags){ MESSAGECACHE *elt; unsigned long i,uf,ffkey; long f; short nf; FILE *idxf; FILE *statf = mix_parse (stream,&idxf,NIL,LONGT); unsigned long seq = mix_modseq (LOCAL->statusseq); /* find first free key */ for (ffkey = 0; (ffkey < NUSERFLAGS) && stream->user_flags[ffkey]; ++ffkey); /* parse sequence and flags */ if (((flags & ST_UID) ? mail_uid_sequence (stream,sequence) : mail_sequence (stream,sequence)) && ((f = mail_parse_flags (stream,flag,&uf)) || uf)) { /* alter flags */ for (i = 1,nf = (flags & ST_SET) ? T : NIL; i <= stream->nmsgs; i++) if ((elt = mail_elt (stream,i))->sequence) { struct { /* old flags */ unsigned int seen : 1; unsigned int deleted : 1; unsigned int flagged : 1; unsigned int answered : 1; unsigned int draft : 1; unsigned long user_flags; } old; old.seen = elt->seen; old.deleted = elt->deleted; old.flagged = elt->flagged; old.answered = elt->answered; old.draft = elt->draft; old.user_flags = elt->user_flags; if (f&fSEEN) elt->seen = nf; if (f&fDELETED) elt->deleted = nf; if (f&fFLAGGED) elt->flagged = nf; if (f&fANSWERED) elt->answered = nf; if (f&fDRAFT) elt->draft = nf; /* user flags */ if (flags & ST_SET) elt->user_flags |= uf; else elt->user_flags &= ~uf; if ((old.seen != elt->seen) || (old.deleted != elt->deleted) || (old.flagged != elt->flagged) || (old.answered != elt->answered) || (old.draft != elt->draft) || (old.user_flags != elt->user_flags)) { if (!stream->rdonly) elt->private.mod = LOCAL->statusseq = seq; MM_FLAGS (stream,elt->msgno); } } /* update status file after change */ if (statf && (seq == LOCAL->statusseq)) mix_status_update (stream,statf,NIL); /* update metadata if created a keyword */ if ((ffkey < NUSERFLAGS) && stream->user_flags[ffkey] && !mix_meta_update (stream)) MM_LOG ("Error updating mix metadata after keyword creation",ERROR); } if (statf) fclose (statf); /* release status file if still open */ if (idxf) fclose (idxf); /* release index file */}/* MIX mail sort messages * Accepts: mail stream * character set * search program * sort program * option flags * Returns: vector of sorted message sequences or NIL if error */unsigned long *mix_sort (MAILSTREAM *stream,char *charset,SEARCHPGM *spg, SORTPGM *pgm,long flags){ unsigned long *ret; FILE *sortcache = mix_sortcache_open (stream); ret = mail_sort_msgs (stream,charset,spg,pgm,flags); mix_sortcache_update (stream,&sortcache); return ret;}/* MIX mail thread messages * Accepts: mail stream * thread type * character set * search program * option flags * Returns: thread node tree or NIL if error */THREADNODE *mix_thread (MAILSTREAM *stream,char *type,char *charset, SEARCHPGM *spg,long flags){ THREADNODE *ret; FILE *sortcache = mix_sortcache_open (stream); ret = mail_thread_msgs (stream,type,charset,spg,flags,mail_sort_msgs); mix_sortcache_update (stream,&sortcache); return ret;}/* MIX mail ping mailbox * Accepts: MAIL stream * Returns: T if stream alive, else NIL */static int snarfing = 0; /* lock against recursive snarfing */long mix_ping (MAILSTREAM *stream){ FILE *idxf,*statf; struct stat sbuf; STRING msg; MESSAGECACHE *elt; int mfd,ifd,sfd; unsigned long i,msglen; char *message,date[MAILTMPLEN],flags[MAILTMPLEN]; MAILSTREAM *sysibx = NIL; long ret = NIL; long snarfok = LONGT; /* time to snarf? */ if (stream->inbox && !stream->rdonly && !snarfing && (time (0) >= (LOCAL->lastsnarf + (time_t) mail_parameters (NIL,GET_SNARFINTERVAL,NIL)))) { appenduid_t au = (appenduid_t) mail_parameters (NIL,GET_APPENDUID,NIL); copyuid_t cu = (copyuid_t) mail_parameters (NIL,GET_COPYUID,NIL); MM_CRITICAL (stream); /* go critical */ snarfing = T; /* don't recursively snarf */ /* disable APPENDUID/COPYUID callbacks */ mail_parameters (NIL,SET_APPENDUID,NIL); mail_parameters (NIL,SET_COPYUID,NIL); /* sizes match and anything in sysinbox? */ if (!stat (sysinbox (),&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFREG) && sbuf.st_size && (sysibx = mail_open (sysibx,sysinbox (),OP_SILENT)) && !sysibx->rdonly && sysibx->nmsgs) { /* for each message in sysibx mailbox */ for (i = 1; snarfok && (i <= sysibx->nmsgs); ++i) if (!(elt = mail_elt (sysibx,i))->deleted && (message = mail_fetch_message (sysibx,i,&msglen,FT_PEEK)) && msglen) { mail_date (date,elt); /* make internal date string */ /* make flag string */ flags[0] = flags[1] = '\0'; if (elt->seen) strcat (flags," \\Seen"); if (elt->flagged) strcat (flags," \\Flagged"); if (elt->answered) strcat (flags," \\Answered"); if (elt->draft) strcat (flags," \\Draft"); flags[0] = '('; strcat (flags,")"); INIT (&msg,mail_string,message,msglen); if (snarfok = mail_append_full (stream,"INBOX",flags,date,&msg)) { char sequence[15]; sprintf (sequence,"%lu",i); mail_flag (sysibx,sequence,"\\Deleted",ST_SET); } } /* now expunge all those messages */ if (snarfok) mail_expunge (sysibx); else { sprintf (LOCAL->buf,"Can't copy new mail at message: %lu",i - 1); MM_LOG (LOCAL->buf,WARN); } } if (sysibx) mail_close (sysibx); /* reenable APPENDUID/COPYUID */ mail_parameters (NIL,SET_APPENDUID,(void *) au); mail_parameters (NIL,SET_COPYUID,(void *) cu); snarfing = NIL; /* no longer snarfing */ MM_NOCRITICAL (stream); /* release critical */ LOCAL->lastsnarf = time (0);/* note time of last snarf */ } /* expunging OK if global flag set */ if (mail_parameters (NIL,GET_EXPUNGEATPING,NIL)) LOCAL->expok = T; /* process metadata/index/status */ if (statf = mix_parse (stream,&idxf,LONGT, (LOCAL->internal ? NIL : LONGT))) { fclose (statf); /* just close the status file */ ret = LONGT; /* declare success */ } if (idxf) fclose (idxf); /* release index file */ LOCAL->expok = NIL; /* expunge no longer OK */ if (!ret) mix_abort (stream); /* murdelyze stream if ping fails */ return ret;}/* MIX mail checkpoint mailbox (burp only) * Accepts: MAIL stream */void mix_check (MAILSTREAM *stream){ if (stream->rdonly) /* won't do on readonly files! */ MM_LOG ("Checkpoint ignored on readonly mailbox",NIL); /* do burp-only expunge action */ if (mix_expunge (stream,"",NIL)) MM_LOG ("Check completed",(long) NIL);}/* MIX mail expunge mailbox * Accepts: MAIL stream * sequence to expunge if non-NIL, empty string for burp only * expunge options * Returns: T on success, NIL if failure */long mix_expunge (MAILSTREAM *stream,char *sequence,long options){ FILE *idxf = NIL; FILE *statf = NIL; MESSAGECACHE *elt; int ifd,sfd; long ret; unsigned long i; unsigned long nexp = 0; unsigned long reclaimed = 0; int burponly = (sequence && !*sequence); LOCAL->expok = T; /* expunge during ping is OK */ if (!(ret = burponly || !sequence || ((options & EX_UID) ? mail_uid_sequence (stream,sequence) : mail_sequence (stream,sequence))) || stream->rdonly); /* read index and open status exclusive */ else if (statf = mix_parse (stream,&idxf,LONGT, LOCAL->internal ? NIL : LONGT)) { /* expunge unless just burping */ if (!burponly) for (i = 1; i <= stream->nmsgs;) { elt = mail_elt (stream,i);/* need to expunge this message? */ if (sequence ? elt->sequence : elt->deleted) { ++nexp; /* yes, make it so */ mail_expunged (stream,i); } else ++i; /* otherwise advance to next message */ } /* burp if can get exclusive access */ if (!flock (LOCAL->mfd,LOCK_EX|LOCK_NB)) { void *a; struct direct **names = NIL; long nfiles = scandir (stream->mailbox,&names,mix_select,mix_msgfsort); if (nfiles > 0) { /* if have message files */ MIXBURP *burp,*cur; /* initialize burp list */ for (i = 0, burp = cur = NIL; i < nfiles; ++i) { MIXBURP *nxt = (MIXBURP *) memset (fs_get (sizeof (MIXBURP)),0, sizeof (MIXBURP)); /* another file found */ if (cur) cur = cur->next = nxt; else cur = burp = nxt; cur->name = names[i]->d_name; cur->fileno = strtoul (cur->name + sizeof (MIXNAME) - 1,NIL,16); cur->tail = &cur->set; fs_give ((void **) &names[i]); } /* now load ranges */ for (i = 1, cur = burp; ret && (i <= stream->nmsgs); i++) { /* is this message in current set? */ elt = mail_elt (stream,i); if (cur && (elt->private.spare.data != cur->fileno)) { /* restart if necessary */ if (elt->private.spare.data < cur->fileno) cur = burp; /* hunt for appropriate mailbox */ while (cur && (elt->private.spare.data > cur->fileno)) cur = cur->next; /* ought to have found it now... */ if (cur && (elt->private.spare.data != cur->fileno)) cur = NIL; } /* if found, add to set */ if (cur) ret = mix_addset (&cur->tail,elt->private.special.offset, elt->private.msg.header.offset + elt->rfc822_size); else { /* uh-oh */ sprintf (LOCAL->buf,"Can't locate mix message file %.08lx", elt->private.spare.data); MM_LOG (LOCAL->buf,ERROR); ret = NIL; } } if (ret) /* if no errors, burp all files */ for (cur = burp; ret && cur; cur = cur->next) { /* if non-empty, burp it */ if (cur->set.last) ret = mix_burp (stream,cur,&reclaimed); /* empty, delete it unless new msg file */ else if (mix_file_data (LOCAL->buf,stream->mailbox,cur->fileno) && ((cur->fileno == LOCAL->newmsg) ? truncate (LOCAL->buf,0) : unlink (LOCAL->buf))) { sprintf (LOCAL->buf, "Can't delete empty message file %.80s: %.80s", cur->name,strerror (errno)); MM_LOG (LOCAL->buf,WARN); } } } else MM_LOG ("No mix message files found during expunge",WARN); /* free directory list */ if (a = (void *) names) fs_give ((void **) &a); } /* either way, re-acquire shared lock */ if (flock (LOCAL->mfd,LOCK_SH|LOCK_NB)) fatal ("Unable to re-acquire metadata shared lock!"); /* Do this step even if ret is NIL (meaning some burp problem)! */ if (nexp || reclaimed) { /* rewrite index and status if changed */ LOCAL->indexseq = mix_modseq (LOCAL->indexseq); if (mix_index_update (stream,idxf,NIL)) { LOCAL->statusseq = mix_modseq (LOCAL->statusseq); /* set failure if update fails */ ret = mix_status_update (stream,statf,NIL); } } } if (statf) fclose (statf); /* close status if still open */ if (idxf) fclose (idxf); /* close index if still open */ LOCAL->expok = NIL; /* cancel expok */ if (ret) { /* only if success */ char *s = NIL; if (nexp) sprintf (s = LOCAL->buf,"Expunged %lu messages",nexp); else if (reclaimed) sprintf (s=LOCAL->buf,"Reclaimed %lu bytes of expunged space",reclaimed); else if (!burponly) s = stream->rdonly ? "Expunge ignored on readonly mailbox" : "No messages deleted, so no update needed"; if (s) MM_LOG (s,(long) NIL); } return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -