📄 tenex.c
字号:
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 */}/* Tenex mail open * Accepts: stream to open * Returns: stream on success, NIL on failure */MAILSTREAM *tenex_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 (&tenexproto); if (stream->local) fatal ("tenex recycle stream"); user_flags (stream); /* set up user flags */ /* canonicalize the mailbox name */ if (!tenex_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: %s",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 (TENEXLOCAL)); LOCAL->buf = (char *) fs_get (CHUNKSIZE); LOCAL->buflen = CHUNKSIZE - 1; LOCAL->text.data = (unsigned char *) fs_get (CHUNKSIZE); LOCAL->text.size = CHUNKSIZE - 1; /* note if an INBOX or not */ stream->inbox = !compare_cstring (stream->mailbox,"INBOX"); LOCAL->fd = fd; /* bind the file */ /* flush old name */ fs_give ((void **) &stream->mailbox); /* save canonical name */ 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 (tenex_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 */}/* Tenex mail close * Accepts: MAIL stream * close options */void tenex_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) tenex_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); if (LOCAL->text.data) fs_give ((void **) &LOCAL->text.data); /* nuke the local data */ fs_give ((void **) &stream->local); stream->dtb = NIL; /* log out the DTB */ }}/* Tenex mail fetch fast data * Accepts: MAIL stream * sequence * option flags */void tenex_fast (MAILSTREAM *stream,char *sequence,long flags){ STRING bs; MESSAGECACHE *elt; unsigned long i; if (stream && LOCAL && ((flags & FT_UID) ? mail_uid_sequence (stream,sequence) : mail_sequence (stream,sequence))) for (i = 1; i <= stream->nmsgs; i++) if ((elt = mail_elt (stream,i))->sequence) { if (!elt->rfc822_size) { /* have header size yet? */ lseek (LOCAL->fd,elt->private.special.offset + elt->private.special.text.size,L_SET); /* resize bigbuf if necessary */ if (LOCAL->buflen < elt->private.msg.full.text.size) { fs_give ((void **) &LOCAL->buf); LOCAL->buflen = elt->private.msg.full.text.size; LOCAL->buf = (char *) fs_get (LOCAL->buflen + 1); } /* tie off string */ LOCAL->buf[elt->private.msg.full.text.size] = '\0'; /* read in the message */ read (LOCAL->fd,LOCAL->buf,elt->private.msg.full.text.size); INIT (&bs,mail_string,(void *) LOCAL->buf, elt->private.msg.full.text.size); /* calculate its CRLF size */ elt->rfc822_size = strcrlflen (&bs); } tenex_elt (stream,i); /* get current flags from file */ }}/* Tenex mail fetch flags * Accepts: MAIL stream * sequence * option flags * Sniffs at file to get flags */void tenex_flags (MAILSTREAM *stream,char *sequence,long flags){ unsigned long i; if (stream && LOCAL && ((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) tenex_elt (stream,i);}/* TENEX 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 *tenex_header (MAILSTREAM *stream,unsigned long msgno, unsigned long *length,long flags){ char *s; unsigned long i; *length = 0; /* default to empty */ if (flags & FT_UID) return "";/* UID call "impossible" */ /* get to header position */ lseek (LOCAL->fd,tenex_hdrpos (stream,msgno,&i),L_SET); if (flags & FT_INTERNAL) { if (i > LOCAL->buflen) { /* resize if not enough space */ fs_give ((void **) &LOCAL->buf); LOCAL->buf = (char *) fs_get (LOCAL->buflen = i + 1); } /* slurp the data */ read (LOCAL->fd,LOCAL->buf,*length = i); } else { s = (char *) fs_get (i + 1);/* get readin buffer */ s[i] = '\0'; /* tie off string */ read (LOCAL->fd,s,i); /* slurp the data */ /* make CRLF copy of string */ *length = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen,s,i); fs_give ((void **) &s); /* free readin buffer */ } return (char *) LOCAL->buf;}/* TENEX mail fetch message text (body only) * Accepts: MAIL stream * message # to fetch * pointer to returned stringstruct * option flags * Returns: T, always */long tenex_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags){ char *s; unsigned long i,j; MESSAGECACHE *elt; /* UID call "impossible" */ if (flags & FT_UID) return NIL; /* get message status */ elt = tenex_elt (stream,msgno); /* if message not seen */ if (!(flags & FT_PEEK) && !elt->seen) { elt->seen = T; /* mark message as seen */ /* recalculate status */ tenex_update_status (stream,msgno,T); MM_FLAGS (stream,msgno); } if (flags & FT_INTERNAL) { /* if internal representation wanted */ /* find header position */ i = tenex_hdrpos (stream,msgno,&j); if (i > LOCAL->buflen) { /* resize if not enough space */ fs_give ((void **) &LOCAL->buf); LOCAL->buf = (char *) fs_get (LOCAL->buflen = i + 1); } /* go to text position */ lseek (LOCAL->fd,i + j,L_SET); /* slurp the data */ read (LOCAL->fd,LOCAL->buf,i); /* set up stringstruct for internal */ INIT (bs,mail_string,LOCAL->buf,i); } else { /* normal form, previous text cached? */ if (elt->private.uid == LOCAL->uid) i = elt->private.msg.text.text.size; else { /* not cached, cache it now */ LOCAL->uid = elt->private.uid; /* find header position */ i = tenex_hdrpos (stream,msgno,&j); /* go to text position */ lseek (LOCAL->fd,i + j,L_SET); s = (char *) fs_get ((i = tenex_size (stream,msgno) - j) + 1); s[i] = '\0'; /* tie off string */ read (LOCAL->fd,s,i); /* slurp the data */ /* make CRLF copy of string */ i = elt->private.msg.text.text.size = strcrlfcpy (&LOCAL->text.data,&LOCAL->text.size,s,i); fs_give ((void **) &s); /* free readin buffer */ } /* set up stringstruct */ INIT (bs,mail_string,LOCAL->text.data,i); } return T; /* success */}/* Tenex mail modify flags * Accepts: MAIL stream * sequence * flag(s) * option flags */void tenex_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); }}/* Tenex mail per-message modify flags * Accepts: MAIL stream * message cache element */void tenex_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 */ tenex_update_status (stream,elt->msgno,NIL);}/* Tenex mail ping mailbox * Accepts: MAIL stream * Returns: T if stream still alive, NIL if not */long tenex_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) tenex_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 = (tenex_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) { tenex_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 = (tenex_parse (stream)) ? T : NIL; unlockfd (ld,lock); /* release shared parse/append permission */ } } } } return r; /* return result of the parse */}/* Tenex mail check mailbox (reparses status too) * Accepts: MAIL stream */void tenex_check (MAILSTREAM *stream){ /* mark that a check is desired */ if (LOCAL) LOCAL->mustcheck = T;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -