📄 mtx.c
字号:
return ret; /* return success */}/* Mtx Mail status * Accepts: mail stream * mailbox name * status flags * Returns: T on success, NIL on failure */long mtx_status (MAILSTREAM *stream,char *mbx,long flags){ MAILSTATUS status; unsigned long i; MAILSTREAM *tstream = NIL; MAILSTREAM *systream = NIL; /* make temporary stream (unless this mbx) */ if (!stream && !(stream = tstream = mail_open (NIL,mbx,OP_READONLY|OP_SILENT))) return NIL; status.flags = flags; /* return status values */ status.messages = stream->nmsgs; status.recent = stream->recent; if (flags & SA_UNSEEN) /* must search to get unseen messages */ for (i = 1,status.unseen = 0; i <= stream->nmsgs; i++) if (!mail_elt (stream,i)->seen) status.unseen++; status.uidnext = stream->uid_last + 1; status.uidvalidity = stream->uid_validity; /* calculate post-snarf results */ if (!status.recent && stream->inbox && (systream = mail_open (NIL,sysinbox (),OP_READONLY|OP_SILENT))) { status.messages += systream->nmsgs; status.recent += systream->recent; if (flags & SA_UNSEEN) /* must search to get unseen messages */ for (i = 1; i <= systream->nmsgs; i++) if (!mail_elt (systream,i)->seen) status.unseen++; /* kludge but probably good enough */ status.uidnext += systream->nmsgs; } MM_STATUS(stream,mbx,&status);/* pass status to main program */ if (tstream) mail_close (tstream); if (systream) mail_close (systream); return T; /* success */}/* MTX mail open * Accepts: stream to open * Returns: stream on success, NIL on failure */MAILSTREAM *mtx_open (MAILSTREAM *stream){ int fd,ld; char tmp[MAILTMPLEN]; blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); /* return prototype for OP_PROTOTYPE call */ if (!stream) return user_flags (&mtxproto); if (stream->local) fatal ("mtx recycle stream"); user_flags (stream); /* set up user flags */ /* canonicalize the mailbox name */ if (!mtx_file (tmp,stream->mailbox)) { sprintf (tmp,"Can't open - invalid name: %.80s",stream->mailbox); MM_LOG (tmp,ERROR); } if (stream->rdonly || (fd = open (tmp,O_RDWR,NIL)) < 0) { if ((fd = open (tmp,O_RDONLY,NIL)) < 0) { sprintf (tmp,"Can't open mailbox: %.80s",strerror (errno)); MM_LOG (tmp,ERROR); return NIL; } else if (!stream->rdonly) { /* got it, but readonly */ MM_LOG ("Can't get write access to mailbox, access is readonly",WARN); stream->rdonly = T; } } stream->local = fs_get (sizeof (MTXLOCAL)); LOCAL->fd = fd; /* bind the file */ LOCAL->buf = (char *) fs_get (CHUNKSIZE); LOCAL->buflen = CHUNKSIZE - 1; /* note if an INBOX or not */ stream->inbox = !compare_cstring (stream->mailbox,"INBOX"); fs_give ((void **) &stream->mailbox); stream->mailbox = cpystr (tmp); /* get shared parse permission */ if ((ld = lockfd (fd,tmp,LOCK_SH)) < 0) { MM_LOG ("Unable to lock open mailbox",ERROR); return NIL; } (*bn) (BLOCK_FILELOCK,NIL); flock (LOCAL->fd,LOCK_SH); /* lock the file */ (*bn) (BLOCK_NONE,NIL); unlockfd (ld,tmp); /* release shared parse permission */ LOCAL->filesize = 0; /* initialize parsed file size */ /* time not set up yet */ LOCAL->lastsnarf = LOCAL->filetime = 0; LOCAL->mustcheck = LOCAL->shouldcheck = NIL; stream->sequence++; /* bump sequence number */ /* parse mailbox */ stream->nmsgs = stream->recent = 0; if (mtx_ping (stream) && !stream->nmsgs) MM_LOG ("Mailbox is empty",(long) NIL); if (!LOCAL) return NIL; /* failure if stream died */ stream->perm_seen = stream->perm_deleted = stream->perm_flagged = stream->perm_answered = stream->perm_draft = stream->rdonly ? NIL : T; stream->perm_user_flags = stream->rdonly ? NIL : 0xffffffff; return stream; /* return stream to caller */}/* MTX mail close * Accepts: MAIL stream * close options */void mtx_close (MAILSTREAM *stream,long options){ if (stream && LOCAL) { /* only if a file is open */ int silent = stream->silent; stream->silent = T; /* note this stream is dying */ if (options & CL_EXPUNGE) mtx_expunge (stream,NIL,NIL); stream->silent = silent; /* restore previous status */ flock (LOCAL->fd,LOCK_UN); /* unlock local file */ close (LOCAL->fd); /* close the local file */ /* free local text buffer */ if (LOCAL->buf) fs_give ((void **) &LOCAL->buf); /* nuke the local data */ fs_give ((void **) &stream->local); stream->dtb = NIL; /* log out the DTB */ }}/* MTX mail fetch flags * Accepts: MAIL stream * sequence * option flags * Sniffs at file to see if some other process changed the flags */void mtx_flags (MAILSTREAM *stream,char *sequence,long flags){ unsigned long i; if (mtx_ping (stream) && /* ping mailbox, get new status for messages */ ((flags & FT_UID) ? mail_uid_sequence (stream,sequence) : mail_sequence (stream,sequence))) for (i = 1; i <= stream->nmsgs; i++) if (mail_elt (stream,i)->sequence) mtx_elt (stream,i);}/* MTX mail fetch message header * Accepts: MAIL stream * message # to fetch * pointer to returned header text length * option flags * Returns: message header in RFC822 format */char *mtx_header (MAILSTREAM *stream,unsigned long msgno,unsigned long *length, long flags){ *length = 0; /* default to empty */ if (flags & FT_UID) return "";/* UID call "impossible" */ /* get to header position */ lseek (LOCAL->fd,mtx_hdrpos (stream,msgno,length),L_SET); /* is buffer big enough? */ if (*length > LOCAL->buflen) { fs_give ((void **) &LOCAL->buf); LOCAL->buf = (char *) fs_get ((LOCAL->buflen = *length) + 1); } LOCAL->buf[*length] = '\0'; /* tie off string */ /* slurp the data */ read (LOCAL->fd,LOCAL->buf,*length); return (char *) LOCAL->buf;}/* MTX mail fetch message text (body only) * Accepts: MAIL stream * message # to fetch * pointer to returned header text length * option flags * Returns: T, always */long mtx_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags){ FDDATA d; unsigned long i,j; MESSAGECACHE *elt; /* UID call "impossible" */ if (flags & FT_UID) return NIL; elt = mtx_elt (stream,msgno); /* get message status */ /* if message not seen */ if (!(flags & FT_PEEK) && !elt->seen) { elt->seen = T; /* mark message as seen */ /* recalculate status */ mtx_update_status (stream,msgno,NIL); MM_FLAGS (stream,msgno); } /* find header position */ i = mtx_hdrpos (stream,msgno,&j); d.fd = LOCAL->fd; /* set up file descriptor */ d.pos = i + j; d.chunk = LOCAL->buf; /* initial buffer chunk */ d.chunksize = CHUNKSIZE; INIT (bs,fd_string,&d,elt->rfc822_size - j); return T; /* success */}/* MTX mail modify flags * Accepts: MAIL stream * sequence * flag(s) * option flags */void mtx_flag (MAILSTREAM *stream,char *sequence,char *flag,long flags){ time_t tp[2]; struct stat sbuf; if (!stream->rdonly) { /* make sure the update takes */ fsync (LOCAL->fd); fstat (LOCAL->fd,&sbuf); /* get current write time */ tp[1] = LOCAL->filetime = sbuf.st_mtime; tp[0] = time (0); /* make sure read comes after all that */ utime (stream->mailbox,tp); }}/* MTX mail per-message modify flags * Accepts: MAIL stream * message cache element */void mtx_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt){ struct stat sbuf; /* maybe need to do a checkpoint? */ if (LOCAL->filetime && !LOCAL->shouldcheck) { fstat (LOCAL->fd,&sbuf); /* get current write time */ if (LOCAL->filetime < sbuf.st_mtime) LOCAL->shouldcheck = T; LOCAL->filetime = 0; /* don't do this test for any other messages */ } /* recalculate status */ mtx_update_status (stream,elt->msgno,NIL);}/* MTX mail ping mailbox * Accepts: MAIL stream * Returns: T if stream still alive, NIL if not */long mtx_ping (MAILSTREAM *stream){ unsigned long i = 1; long r = T; int ld; char lock[MAILTMPLEN]; struct stat sbuf; if (stream && LOCAL) { /* only if stream already open */ fstat (LOCAL->fd,&sbuf); /* get current file poop */ if (LOCAL->filetime && !(LOCAL->mustcheck || LOCAL->shouldcheck) && (LOCAL->filetime < sbuf.st_mtime)) LOCAL->shouldcheck = T; /* check for changed message status */ if (LOCAL->mustcheck || LOCAL->shouldcheck) { LOCAL->filetime = sbuf.st_mtime; if (LOCAL->shouldcheck) /* babble when we do this unilaterally */ MM_NOTIFY (stream,"[CHECK] Checking for flag updates",NIL); while (i <= stream->nmsgs) mtx_elt (stream,i++); LOCAL->mustcheck = LOCAL->shouldcheck = NIL; } /* get shared parse/append permission */ if ((sbuf.st_size != LOCAL->filesize) && ((ld = lockfd (LOCAL->fd,lock,LOCK_SH)) >= 0)) { /* parse resulting mailbox */ r = (mtx_parse (stream)) ? T : NIL; unlockfd (ld,lock); /* release shared parse/append permission */ } if (LOCAL) { /* stream must still be alive */ /* snarf if this is a read-write inbox */ if (stream->inbox && !stream->rdonly) { mtx_snarf (stream); fstat (LOCAL->fd,&sbuf);/* see if file changed now */ if ((sbuf.st_size != LOCAL->filesize) && ((ld = lockfd (LOCAL->fd,lock,LOCK_SH)) >= 0)) { /* parse resulting mailbox */ r = (mtx_parse (stream)) ? T : NIL; unlockfd (ld,lock); /* release shared parse/append permission */ } } } } return r; /* return result of the parse */}/* MTX mail check mailbox (reparses status too) * Accepts: MAIL stream */void mtx_check (MAILSTREAM *stream){ /* mark that a check is desired */ if (LOCAL) LOCAL->mustcheck = T; if (mtx_ping (stream)) MM_LOG ("Check completed",(long) NIL);}/* MTX mail snarf messages from system inbox * Accepts: MAIL stream */void mtx_snarf (MAILSTREAM *stream){ unsigned long i = 0; unsigned long j,r,hdrlen,txtlen; struct stat sbuf; char *hdr,*txt,lock[MAILTMPLEN],tmp[MAILTMPLEN]; MESSAGECACHE *elt; MAILSTREAM *sysibx = NIL; int ld; /* give up if can't get exclusive permission */ if ((time (0) >= (LOCAL->lastsnarf + (long) mail_parameters (NIL,GET_SNARFINTERVAL,NIL))) && strcmp (sysinbox (),stream->mailbox) && ((ld = lockfd (LOCAL->fd,lock,LOCK_EX)) >= 0)) { 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) { /* calculate header line */ mail_date (LOCAL->buf,elt = mail_elt (sysibx,i)); sprintf (LOCAL->buf + strlen (LOCAL->buf),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -