⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mtx.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 4 页
字号:
  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 + -