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

📄 mtxnt.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 3 页
字号:
				/* 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 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){  struct utimbuf times;  struct stat sbuf;  if (!stream->rdonly) {	/* make sure the update takes */    fsync (LOCAL->fd);    fstat (LOCAL->fd,&sbuf);	/* get current write time */    times.modtime = LOCAL->filetime = sbuf.st_mtime;    times.actime = time (0);	/* make sure read comes after all that */    utime (stream->mailbox,&times);  }}/* 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 = lockname (lock,stream->mailbox,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 expunge mailbox *	    sequence to expunge if non-NIL *	    expunge options * Returns: T, always */long mtx_expunge (MAILSTREAM *stream,char *sequence,long options){  long ret;  struct utimbuf times;  struct stat sbuf;  off_t pos = 0;  int ld;  unsigned long i = 1;  unsigned long j,k,m,recent;  unsigned long n = 0;  unsigned long delta = 0;  char lock[MAILTMPLEN];  MESSAGECACHE *elt;  if (!(ret = (sequence ? ((options & EX_UID) ?			   mail_uid_sequence (stream,sequence) :			   mail_sequence (stream,sequence)) : LONGT) &&	mtx_ping (stream)));	/* parse sequence if given, ping stream */  else if (stream->rdonly) mm_log ("Expunge ignored on readonly mailbox",WARN);  else {    if (LOCAL->filetime && !LOCAL->shouldcheck) {      fstat (LOCAL->fd,&sbuf);	/* get current write time */      if (LOCAL->filetime < sbuf.st_mtime) LOCAL->shouldcheck = T;    }				/* get exclusive parse/append permission */    if ((ld = lockname (lock,stream->mailbox,LOCK_EX)) < 0)      mm_log ("Unable to lock expunge mailbox",ERROR);				/* make sure see any newly-arrived messages */    else if (!mtx_parse (stream));				/* get exclusive access */    else if (flock (LOCAL->fd,LOCK_EX|LOCK_NB)) {      flock (LOCAL->fd,LOCK_SH);/* recover previous lock */      mm_log ("Can't expunge because mailbox is in use by another process",	      ERROR);      unlockfd (ld,lock);	/* release exclusive parse/append permission */    }    else {      mm_critical (stream);	/* go critical */      recent = stream->recent;	/* get recent now that pinged and locked */				/* for each message */      while (i <= stream->nmsgs) {				/* get cache element */	elt = mtx_elt (stream,i);				/* number of bytes to smash or preserve */	k = elt->private.special.text.size + elt->rfc822_size;				/* if need to expunge this message */	if (elt->deleted && (sequence ? elt->sequence : T)) {				/* if recent, note one less recent message */	  if (elt->recent) --recent;	  delta += k;		/* number of bytes to delete */				/* notify upper levels */	  mail_expunged (stream,i);	  n++;			/* count up one more expunged message */	}	else if (i++ && delta) {/* preserved message */				/* first byte to preserve */	  j = elt->private.special.offset;	  do {			/* read from source position */	    m = min (k,LOCAL->buflen);	    lseek (LOCAL->fd,j,L_SET);	    read (LOCAL->fd,LOCAL->buf,m);	    pos = j - delta;	/* write to destination position */	    while (T) {	      lseek (LOCAL->fd,pos,L_SET);	      if (write (LOCAL->fd,LOCAL->buf,m) > 0) break;	      mm_notify (stream,strerror (errno),WARN);	      mm_diskerror (stream,errno,T);	    }	    pos += m;		/* new position */	    j += m;		/* next chunk, perhaps */	  } while (k -= m);	/* until done */				/* note the new address of this text */	  elt->private.special.offset -= delta;	}				/* preserved but no deleted messages */	else pos = elt->private.special.offset + k;      }      if (n) {			/* truncate file after last message */	if (pos != (LOCAL->filesize -= delta)) {	  sprintf (LOCAL->buf,		   "Calculated size mismatch %lu != %lu, delta = %lu",		   (unsigned long) pos,(unsigned long) LOCAL->filesize,delta);	  mm_log (LOCAL->buf,WARN);	  LOCAL->filesize = pos;/* fix it then */	}	ftruncate (LOCAL->fd,LOCAL->filesize);	sprintf (LOCAL->buf,"Expunged %lu messages",n);				/* output the news */	mm_log (LOCAL->buf,(long) NIL);      }      else mm_log ("No messages deleted, so no update needed",(long) NIL);      fsync (LOCAL->fd);	/* force disk update */      fstat (LOCAL->fd,&sbuf);	/* get new write time */      times.modtime = LOCAL->filetime = sbuf.st_mtime;      times.actime = time (0);	/* reset atime to now */      utime (stream->mailbox,&times);      mm_nocritical (stream);	/* release critical */				/* notify upper level of new mailbox size */      mail_exists (stream,stream->nmsgs);      mail_recent (stream,recent);      flock (LOCAL->fd,LOCK_SH);/* allow sharers again */      unlockfd (ld,lock);	/* release exclusive parse/append permission */    }  }  return ret;}/* MTX mail copy message(s) * Accepts: MAIL stream *	    sequence *	    destination mailbox *	    copy options * Returns: T if success, NIL if failed */long mtx_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options){  struct stat sbuf;  struct utimbuf times;  MESSAGECACHE *elt;  unsigned long i,j,k;  long ret = LONGT;  int fd,ld;  char file[MAILTMPLEN],lock[MAILTMPLEN];  mailproxycopy_t pc =    (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL);				/* make sure valid mailbox */  if (!mtx_isvalid (mailbox,file)) switch (errno) {  case ENOENT:			/* no such file? */    mm_notify (stream,"[TRYCREATE] Must create mailbox before copy",NIL);    return NIL;  case 0:			/* merely empty file? */    break;  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 MTX-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 MTX-format mailbox: %.80s",mailbox);    mm_log (LOCAL->buf,ERROR);    return NIL;  }  if (!((options & CP_UID) ? mail_uid_sequence (stream,sequence) :	mail_sequence (stream,sequence))) return NIL;				/* got file? */  if ((fd = open (file,O_BINARY|O_RDWR|O_CREAT,S_IREAD|S_IWRITE)) < 0) {    sprintf (LOCAL->buf,"Unable to open copy mailbox: %.80s",strerror (errno));    mm_log (LOCAL->buf,ERROR);    return NIL;  }  mm_critical (stream);		/* go critical */				/* get exclusive parse/append permission */  if (flock (fd,LOCK_SH) || ((ld = lockname (lock,file,LOCK_EX)) < 0)) {    mm_log ("Unable to lock copy mailbox",ERROR);    mm_nocritical (stream);    return NIL;  }  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,L_SET);				/* number of bytes to copy */      k = elt->private.special.text.size + elt->rfc822_size;      do {			/* read from source position */	j = min (k,LOCAL->buflen);	read (LOCAL->fd,LOCAL->buf,j);	if (write (fd,LOCAL->buf,j) < 0) ret = NIL;      } while (ret && (k -= j));/* until done */    }				/* 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);  }				/* set atime to now-1 if successful copy */  if (ret) times.actime = time (0) - 1;				/* else preserved \Marked status */  else times.actime = (sbuf.st_ctime > sbuf.st_atime) ?	 sbuf.st_atime : time (0);  times.modtime = sbuf.st_mtime;/* preserve mtime */  utime (file,&times);		/* set the times */  unlockfd (ld,lock);		/* release exclusive parse/append permission */  close (fd);			/* close the file */  mm_nocritical (stream);	/* release critical */				/* delete all requested messages */  if (ret && (options & CP_MOVE)) {    for (i = 1; i <= stream->nmsgs; i++)      if ((elt = mtx_elt (stream,i))->sequence) {	elt->deleted = T;	/* mark message deleted */				/* recalculate status */	mtx_update_status (stream,i,NIL);      }    if (!stream->rdonly) {	/* make sure the update takes */      fsync (LOCAL->fd);      fstat (LOCAL->fd,&sbuf);	/* get current write time */      times.modtime = LOCAL->filetime = sbuf.st_mtime;      times.actime = time (0);	/* make sure atime remains greater */      utime (stream->mailbox,&times);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -