📄 mbx.c
字号:
d.pos = i + j; d.chunk = LOCAL->buf; /* initial buffer chunk */ d.chunksize = CHUNKSIZE; INIT (bs,fd_string,&d,elt->rfc822_size - j); return LONGT; /* success */}/* MBX mail modify flags * Accepts: MAIL stream * sequence * flag(s) * option flags * Unlocks flag lock */void mbx_flag (MAILSTREAM *stream,char *sequence,char *flag,long flags){ time_t tp[2]; struct stat sbuf; unsigned long oldpid = LOCAL->lastpid; /* make sure the update takes */ if (!stream->rdonly && LOCAL && (LOCAL->fd >= 0) && (LOCAL->ld >= 0)) { fsync (LOCAL->fd); fstat (LOCAL->fd,&sbuf); /* get current write time */ tp[1] = LOCAL->filetime = sbuf.st_mtime; /* we are the last flag updater */ LOCAL->lastpid = (unsigned long) getpid (); /* update header if needed */ if (((LOCAL->ffuserflag < NUSERFLAGS) && stream->user_flags[LOCAL->ffuserflag]) || (oldpid != LOCAL->lastpid)) mbx_update_header (stream); tp[0] = time (0); /* make sure read comes after all that */ utime (stream->mailbox,tp); } if (LOCAL->ld >= 0) { /* unlock now */ unlockfd (LOCAL->ld,LOCAL->lock); LOCAL->ld = -1; }}/* MBX mail per-message modify flags * Accepts: MAIL stream * message cache element */void mbx_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt){ if (mbx_flaglock (stream)) mbx_update_status (stream,elt->msgno,NIL);}/* MBX mail ping mailbox * Accepts: MAIL stream * Returns: T if stream still alive, NIL if not */long mbx_ping (MAILSTREAM *stream){ unsigned long i,pos; long ret = NIL; int ld; char lock[MAILTMPLEN]; MESSAGECACHE *elt; struct stat sbuf; if (stream && LOCAL) { /* only if stream already open */ int snarf = stream->inbox && !stream->rdonly; ret = LONGT; /* assume OK */ fstat (LOCAL->fd,&sbuf); /* get current file poop */ /* allow expunge if permitted at ping */ if (mail_parameters (NIL,GET_EXPUNGEATPING,NIL)) LOCAL->expok = T; /* if external modification */ if (LOCAL->filetime && (LOCAL->filetime < sbuf.st_mtime)) LOCAL->flagcheck = T; /* upgrade to flag checking */ /* new mail or flagcheck handling needed? */ if (((sbuf.st_size - LOCAL->filesize) || LOCAL->flagcheck || !stream->nmsgs || snarf) && ((ld = lockfd (LOCAL->fd,lock,LOCK_EX)) >= 0)) { /* reparse header if not flagchecking */ if (!LOCAL->flagcheck) ret = mbx_parse (stream); /* sweep mailbox for changed message status */ else if (ret = mbx_parse (stream)) { unsigned long recent = 0; LOCAL->filetime = sbuf.st_mtime; for (i = 1; i <= stream->nmsgs; ) if (elt = mbx_elt (stream,i,LOCAL->expok)) { if (elt->recent) ++recent; ++i; } mail_recent (stream,recent); LOCAL->flagcheck = NIL; /* got all the updates */ } /* always reparse header at least */ if (ret && snarf) { /* snarf new messages if still OK */ mbx_snarf (stream); /* parse snarfed messages */ ret = mbx_parse (stream); } unlockfd (ld,lock); /* release shared parse/append permission */ } if (ret) { /* must still be alive */ if (!LOCAL->expunged) /* look for holes if none known yet */ for (i = 1, pos = HDRSIZE; !LOCAL->expunged && (i <= stream->nmsgs); i++, pos += elt->private.special.text.size + elt->rfc822_size) if ((elt = mail_elt (stream,i))->private.special.offset != pos) LOCAL->expunged = T;/* found a hole */ /* burp any holes */ if (LOCAL->expunged && !stream->rdonly) { if (mbx_rewrite (stream,&i,NIL)) fatal ("expunge on check"); if (i) { /* any space reclaimed? */ LOCAL->expunged = NIL;/* no more pending expunge */ sprintf (LOCAL->buf,"Reclaimed %lu bytes of expunged space",i); MM_LOG (LOCAL->buf,(long) NIL); } } LOCAL->expok = NIL; /* no more expok */ } } return ret; /* return result of the parse */}/* MBX mail check mailbox (reparses status too) * Accepts: MAIL stream */void mbx_check (MAILSTREAM *stream){ if (LOCAL) LOCAL->expok = T; /* mark that a check is desired */ if (mbx_ping (stream)) MM_LOG ("Check completed",(long) NIL);}/* MBX mail expunge mailbox * Accepts: MAIL stream * sequence to expunge if non-NIL * expunge options * Returns: T if success, NIL if failure */long mbx_expunge (MAILSTREAM *stream,char *sequence,long options){ long ret; unsigned long nexp,reclaimed; if (ret = sequence ? ((options & EX_UID) ? mail_uid_sequence (stream,sequence) : mail_sequence (stream,sequence)) : LONGT) { if (!mbx_ping (stream)); /* do nothing if stream dead */ else if (stream->rdonly) /* won't do on readonly files! */ MM_LOG ("Expunge ignored on readonly mailbox",WARN); /* if expunged any messages */ else if (nexp = mbx_rewrite (stream,&reclaimed,sequence ? -1 : 1)) { sprintf (LOCAL->buf,"Expunged %lu messages",nexp); MM_LOG (LOCAL->buf,(long) NIL); } else if (reclaimed) { /* or if any prior expunged space reclaimed */ sprintf (LOCAL->buf,"Reclaimed %lu bytes of expunged space",reclaimed); MM_LOG (LOCAL->buf,(long) NIL); } else MM_LOG ("No messages deleted, so no update needed",(long) NIL); } return ret;}/* MBX mail snarf messages from system inbox * Accepts: MAIL stream, already locked */void mbx_snarf (MAILSTREAM *stream){ unsigned long i = 0; unsigned long j,r,hdrlen,txtlen; struct stat sbuf; char *hdr,*txt,tmp[MAILTMPLEN]; MESSAGECACHE *elt; MAILSTREAM *sysibx = NIL; /* give up if can't get exclusive permission */ if ((time (0) >= (LOCAL->lastsnarf + (long) mail_parameters (NIL,GET_SNARFINTERVAL,NIL))) && strcmp (sysinbox (),stream->mailbox)) { MM_CRITICAL (stream); /* go critical */ /* sizes match and anything in sysinbox? */ if (!stat (sysinbox (),&sbuf) && sbuf.st_size && !fstat (LOCAL->fd,&sbuf) && (sbuf.st_size == LOCAL->filesize) && (sysibx = mail_open (sysibx,sysinbox (),OP_SILENT)) && (!sysibx->rdonly) && (r = sysibx->nmsgs)) { /* yes, go to end of file in our mailbox */ lseek (LOCAL->fd,sbuf.st_size,L_SET); /* for each message in sysibx mailbox */ while (r && (++i <= sysibx->nmsgs)) { /* snarf message from system INBOX */ hdr = cpystr (mail_fetchheader_full (sysibx,i,NIL,&hdrlen,NIL)); txt = mail_fetchtext_full (sysibx,i,&txtlen,FT_PEEK); /* if have a message */ if (j = hdrlen + txtlen) { /* build header line */ mail_date (LOCAL->buf,elt = mail_elt (sysibx,i)); sprintf (LOCAL->buf + strlen (LOCAL->buf), ",%lu;00000000%04x-00000000\015\012",j,(unsigned) ((fSEEN * elt->seen) + (fDELETED * elt->deleted) + (fFLAGGED * elt->flagged) + (fANSWERED * elt->answered) + (fDRAFT * elt->draft))); /* copy message */ if ((write (LOCAL->fd,LOCAL->buf,strlen (LOCAL->buf)) < 0) || (write (LOCAL->fd,hdr,hdrlen) < 0) || (write (LOCAL->fd,txt,txtlen) < 0)) r = 0; } fs_give ((void **) &hdr); } /* make sure all the updates take */ if (fsync (LOCAL->fd)) r = 0; if (r) { /* delete all the messages we copied */ if (r == 1) strcpy (tmp,"1"); else sprintf (tmp,"1:%lu",r); mail_setflag (sysibx,tmp,"\\Deleted"); mail_expunge (sysibx); /* now expunge all those messages */ } else { sprintf (LOCAL->buf,"Can't copy new mail: %s",strerror (errno)); MM_LOG (LOCAL->buf,WARN); ftruncate (LOCAL->fd,sbuf.st_size); } fstat (LOCAL->fd,&sbuf); /* yes, get current file size */ LOCAL->filetime = sbuf.st_mtime; } if (sysibx) mail_close (sysibx); MM_NOCRITICAL (stream); /* release critical */ LOCAL->lastsnarf = time (0);/* note time of last snarf */ }}/* MBX mail copy message(s) * Accepts: MAIL stream * sequence * destination mailbox * copy options * Returns: T if success, NIL if failed */long mbx_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options){ struct stat sbuf; time_t tp[2]; MESSAGECACHE *elt; unsigned long i,j,k,m; long ret = LONGT; int fd,ld; char *s,*t,file[MAILTMPLEN],lock[MAILTMPLEN]; mailproxycopy_t pc = (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL); copyuid_t cu = (copyuid_t) mail_parameters (NIL,GET_COPYUID,NIL); SEARCHSET *source = cu ? mail_newsearchset () : NIL; SEARCHSET *dest = cu ? mail_newsearchset () : NIL; MAILSTREAM *dstream = NIL; if (!((options & CP_UID) ? mail_uid_sequence (stream,sequence) : mail_sequence (stream,sequence))) return NIL; /* make sure valid mailbox */ if ((fd = mbx_isvalid (&dstream,mailbox,file,&ld,lock, cu ? MBXISVALIDUID : MBXISVALIDNOUID)) < 0) switch (errno) { case ENOENT: /* no such file? */ MM_NOTIFY (stream,"[TRYCREATE] Must create mailbox before copy",NIL); return NIL; case EACCES: /* file protected */ sprintf (LOCAL->buf,"Can't access destination: %.80s",mailbox); MM_LOG (LOCAL->buf,ERROR); return NIL; case EINVAL: if (pc) return (*pc) (stream,sequence,mailbox,options); sprintf (LOCAL->buf,"Invalid MBX-format mailbox name: %.80s",mailbox); MM_LOG (LOCAL->buf,ERROR); return NIL; default: if (pc) return (*pc) (stream,sequence,mailbox,options); sprintf (LOCAL->buf,"Not a MBX-format mailbox: %.80s",mailbox); MM_LOG (LOCAL->buf,ERROR); return NIL; } MM_CRITICAL (stream); /* go critical */ fstat (fd,&sbuf); /* get current file size */ lseek (fd,sbuf.st_size,L_SET);/* move to end of file */ /* for each requested message */ for (i = 1; ret && (i <= stream->nmsgs); i++) if ((elt = mail_elt (stream,i))->sequence) { lseek (LOCAL->fd,elt->private.special.offset + elt->private.special.text.size,L_SET); mail_date(LOCAL->buf,elt);/* build target header */ /* get target keyword mask */ for (j = elt->user_flags, k = 0; j; ) if (s = stream->user_flags[find_rightmost_bit (&j)]) for (m = 0; (m < NUSERFLAGS) && (t = dstream->user_flags[m]); m++) if (!compare_cstring (s,t) && (k |= 1 << m)) break; sprintf (LOCAL->buf+strlen(LOCAL->buf),",%lu;%08lx%04x-%08lx\015\012", elt->rfc822_size,k,(unsigned) ((fSEEN * elt->seen) + (fDELETED * elt->deleted) + (fFLAGGED * elt->flagged) + (fANSWERED * elt->answered) + (fDRAFT * elt->draft)),cu ? ++dstream->uid_last : 0); /* write target header */ if (ret = (write (fd,LOCAL->buf,strlen (LOCAL->buf)) > 0)) { for (k = elt->rfc822_size; ret && (j = min (k,LOCAL->buflen)); k -= j){ read (LOCAL->fd,LOCAL->buf,j); ret = write (fd,LOCAL->buf,j) >= 0; } if (cu) { /* need to pass back new UID? */ mail_append_set (source,mail_uid (stream,i)); mail_append_set (dest,dstream->uid_last); } } } /* make sure all the updates take */ if (!(ret && (ret = !fsync (fd)))) { sprintf (LOCAL->buf,"Unable to write message: %s",strerror (errno)); MM_LOG (LOCAL->buf,ERROR); ftruncate (fd,sbuf.st_size); } if (cu && ret) { /* return sets if doing COPYUID */ (*cu) (stream,mailbox,dstream->uid_validity,source,dest); lseek (fd,15,L_SET); /* update UIDLAST */ sprintf (LOCAL->buf,"%08lx",dstream->uid_last); write (fd,LOCAL->buf,8); } else { /* flush any sets we may have built */ mail_free_searchset (&source); mail_free_searchset (&dest); } if (ret) tp[0] = time (0) - 1;/* set atime to now-1 if successful copy */ /* else preserve \Marked status */ else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0); tp[1] = sbuf.st_mtime; /* preserve mtime */ utime (file,tp); /* set the times */ close (fd); /* close the file */ MM_NOCRITICAL (stream); /* release critical */ unlockfd (ld,lock); /* release exclusive parse/append permission */ /* delete all requested messages */ if (ret && (options & CP_MOVE) && mbx_flaglock (stream)) { for (i = 1; i <= stream->nmsgs; i++) if (mail_elt (stream,i)->sequence) { /* mark message deleted */ mbx_elt (stream,i,NIL)->deleted = T; /* recalculate status */ mbx_update_status (stream,i,NIL); } /* update flags */ mbx_flag (stream,NIL,NIL,NIL); } if (dstream != stream) mail_close (dstream); return ret;}/* MBX mail append message from stringstruct * Accepts: MAIL stream * destination mailbox * append callback * data for callback * Returns: T if append successful, else NIL */long mbx_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){ struct stat sbuf; int fd,ld; char *flags,*date,tmp[MAILTMPLEN],file[MAILTMPLEN],lock[MAILTMPLEN]; time_t tp[2]; FILE *df; MESSAGECACHE elt; long f; unsigned long i,uf; STRING *message; long ret = NIL; MAILSTREAM *dstream = NIL; appenduid_t au = (appenduid_t) mail_parameters (NIL,GET_APPENDUID,NIL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -