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

📄 mbxnt.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 4 页
字号:
      if (k & fDRAFT) elt->draft = T;      t[8] = '\0';		/* get user flags value */      elt->user_flags = strtoul (t,NIL,16);				/* UID already assigned? */      if (!(elt->private.uid = m) || !(k & fOLD)) {	elt->recent = T;	/* no, mark as recent */	++recent;		/* count up a new recent message */	dirty = T;		/* and must rewrite header */				/* assign new UID */	if (!elt->private.uid) elt->private.uid = ++stream->uid_last;	mbx_update_status (stream,elt->msgno,NIL);      }				/* update last parsed UID */      lastuid = elt->private.uid;    }    curpos += i + j;		/* update position */  }  if (dirty && !stream->rdonly){/* update header */    mbx_update_header (stream);    fsync (LOCAL->fd);		/* make sure all the UID updates take */  }				/* update parsed file size and time */  LOCAL->filesize = sbuf.st_size;  fstat (LOCAL->fd,&sbuf);	/* get status again to ensure time is right */  LOCAL->filetime = sbuf.st_mtime;  if (added && !stream->rdonly){/* make sure atime updated */    struct utimbuf times;    times.actime = time (0);    times.modtime = LOCAL->filetime;    utime (stream->mailbox,&times);  }  stream->silent = silent;	/* can pass up events now */  mail_exists (stream,nmsgs);	/* notify upper level of new mailbox size */  mail_recent (stream,recent);	/* and of change in recent messages */  return LONGT;			/* return the winnage */}/* MBX get cache element with status updating from file * Accepts: MAIL stream *	    message number *	    expunge OK flag * Returns: cache element */MESSAGECACHE *mbx_elt (MAILSTREAM *stream,unsigned long msgno,long expok){  MESSAGECACHE *elt = mail_elt (stream,msgno);  struct {			/* old flags */    unsigned int seen : 1;    unsigned int deleted : 1;    unsigned int flagged : 1;    unsigned int answered : 1;    unsigned int draft : 1;    unsigned long user_flags;  } old;  old.seen = elt->seen; old.deleted = elt->deleted; old.flagged = elt->flagged;  old.answered = elt->answered; old.draft = elt->draft;  old.user_flags = elt->user_flags;				/* get new flags */  if (mbx_read_flags (stream,elt) && expok) {    mail_expunged (stream,elt->msgno);    return NIL;			/* return this message was expunged */  }  if ((old.seen != elt->seen) || (old.deleted != elt->deleted) ||      (old.flagged != elt->flagged) || (old.answered != elt->answered) ||      (old.draft != elt->draft) || (old.user_flags != elt->user_flags))    mm_flags (stream,msgno);	/* let top level know */  return elt;}/* MBX read flags from file * Accepts: MAIL stream *	    cache element * Returns: non-NIL if message expunged */unsigned long mbx_read_flags (MAILSTREAM *stream,MESSAGECACHE *elt){  unsigned long i;  struct stat sbuf;  fstat (LOCAL->fd,&sbuf);	/* get status */				/* make sure file size is good */  if (sbuf.st_size < LOCAL->filesize) {    sprintf (LOCAL->buf,"Mailbox shrank from %lu to %lu in flag read!",	     (unsigned long) LOCAL->filesize,(unsigned long) sbuf.st_size);    fatal (LOCAL->buf);  }				/* set the seek pointer */  lseek (LOCAL->fd,(off_t) elt->private.special.offset +	 elt->private.special.text.size - 24,L_SET);				/* read the new flags */  if (read (LOCAL->fd,LOCAL->buf,14) < 0) {    sprintf (LOCAL->buf,"Unable to read new status: %s",strerror (errno));    fatal (LOCAL->buf);  }  if ((LOCAL->buf[0] != ';') || (LOCAL->buf[13] != '-')) {    LOCAL->buf[14] = '\0';	/* tie off buffer for error message */    sprintf (LOCAL->buf+50,"Invalid flags for message %lu (%lu %lu): %s",	     elt->msgno,elt->private.special.offset,	     elt->private.special.text.size,(char *) LOCAL->buf);    fatal (LOCAL->buf+50);  }  LOCAL->buf[13] = '\0';	/* tie off buffer */				/* calculate system flags */  i = strtoul (LOCAL->buf+9,NIL,16);  elt->seen = i & fSEEN ? T : NIL;  elt->deleted = i & fDELETED ? T : NIL;  elt->flagged = i & fFLAGGED ? T : NIL;  elt->answered = i & fANSWERED ? T : NIL;  elt->draft = i & fDRAFT ? T : NIL;  LOCAL->expunged |= i & fEXPUNGED ? T : NIL;  LOCAL->buf[9] = '\0';		/* tie off flags */				/* get user flags value */  elt->user_flags = strtoul (LOCAL->buf+1,NIL,16);  elt->valid = T;		/* have valid flags now */  return i & fEXPUNGED;}/* MBX update header * Accepts: MAIL stream */#define NTKLUDGEOFFSET 7void mbx_update_header (MAILSTREAM *stream){  int i;  char *s = LOCAL->buf;  memset (s,'\0',HDRSIZE);	/* initialize header */  sprintf (s,"*mbx*\015\012%08lx%08lx\015\012",	   stream->uid_validity,stream->uid_last);  for (i = 0; (i < NUSERFLAGS) && stream->user_flags[i]; ++i)    sprintf (s += strlen (s),"%s\015\012",stream->user_flags[i]);  LOCAL->ffuserflag = i;	/* first free user flag */				/* can we create more user flags? */  stream->kwd_create = (i < NUSERFLAGS) ? T : NIL;				/* write reserved lines */  while (i++ < NUSERFLAGS) strcat (s,"\015\012");  while (T) {			/* rewind file */    lseek (LOCAL->fd,NTKLUDGEOFFSET,L_SET);				/* write new header */    if (write (LOCAL->fd,LOCAL->buf + NTKLUDGEOFFSET,	       HDRSIZE - NTKLUDGEOFFSET) > 0) break;    mm_notify (stream,strerror (errno),WARN);    mm_diskerror (stream,errno,T);  }}/* MBX update status string * Accepts: MAIL stream *	    message number *	    flags */void mbx_update_status (MAILSTREAM *stream,unsigned long msgno,long flags){  struct stat sbuf;  MESSAGECACHE *elt = mail_elt (stream,msgno);				/* readonly */  if (stream->rdonly || !elt->valid) mbx_read_flags (stream,elt);  else {			/* readwrite */    fstat (LOCAL->fd,&sbuf);	/* get status */				/* make sure file size is good */    if (sbuf.st_size < LOCAL->filesize) {      sprintf (LOCAL->buf,"Mailbox shrank from %lu to %lu in flag update!",	       (unsigned long) LOCAL->filesize,(unsigned long) sbuf.st_size);      fatal (LOCAL->buf);    }				/* set the seek pointer */    lseek (LOCAL->fd,(off_t) elt->private.special.offset +	   elt->private.special.text.size - 24,L_SET);				/* read the new flags */    if (read (LOCAL->fd,LOCAL->buf,14) < 0) {      sprintf (LOCAL->buf,"Unable to read old status: %s",strerror (errno));      fatal (LOCAL->buf);    }    if ((LOCAL->buf[0] != ';') || (LOCAL->buf[13] != '-')) {      LOCAL->buf[14] = '\0';	/* tie off buffer for error message */      sprintf (LOCAL->buf+50,"Invalid flags for message %lu (%lu %lu): %s",	       elt->msgno,elt->private.special.offset,	       elt->private.special.text.size,(char *) LOCAL->buf);      fatal (LOCAL->buf+50);    }				/* print new flag string */    sprintf (LOCAL->buf,"%08lx%04x-%08lx",elt->user_flags,(unsigned)	     (((elt->deleted && flags) ?	       fEXPUNGED : (strtoul (LOCAL->buf+9,NIL,16)) & fEXPUNGED) +	      (fSEEN * elt->seen) + (fDELETED * elt->deleted) +	      (fFLAGGED * elt->flagged) + (fANSWERED * elt->answered) +	      (fDRAFT * elt->draft) + fOLD),elt->private.uid);    while (T) {			/* get to that place in the file */      lseek (LOCAL->fd,(off_t) elt->private.special.offset +	     elt->private.special.text.size - 23,L_SET);				/* write new flags and UID */      if (write (LOCAL->fd,LOCAL->buf,21) > 0) break;      mm_notify (stream,strerror (errno),WARN);      mm_diskerror (stream,errno,T);    }  }}/* MBX locate header for a message * Accepts: MAIL stream *	    message number *	    pointer to returned header size *	    pointer to possible returned header * Returns: position of header in file */#define HDRBUFLEN 16384		/* good enough for most headers */#define SLOP 4			/* CR LF CR LF */unsigned long mbx_hdrpos (MAILSTREAM *stream,unsigned long msgno,			  unsigned long *size,char **hdr){  unsigned long siz,done;  long i;  unsigned char *s,*t,*te;  MESSAGECACHE *elt = mail_elt (stream,msgno);  unsigned long ret = elt->private.special.offset +    elt->private.special.text.size;  if (hdr) *hdr = NIL;		/* assume no header returned */				/* is header size known? */   if (*size = elt->private.msg.header.text.size) return ret;				/* paranoia check */  if (LOCAL->buflen < (HDRBUFLEN + SLOP))    fatal ("LOCAL->buf smaller than HDRBUFLEN");  lseek (LOCAL->fd,ret,L_SET);	/* get to header position */				/* read HDRBUFLEN chunks with 4 byte slop */  for (done = siz = 0, s = LOCAL->buf;       (i = min ((long) (elt->rfc822_size - done),(long) HDRBUFLEN)) &&       (read (LOCAL->fd,s,i) == i);       done += i, siz += (t - LOCAL->buf) - SLOP, s = LOCAL->buf + SLOP) {    te = (t = s + i) - 12;	/* calculate end of fast scan */				/* fast scan for CR */    for (s = LOCAL->buf; s < te;)      if (((*s++ == '\015') || (*s++ == '\015') || (*s++ == '\015') ||	   (*s++ == '\015') || (*s++ == '\015') || (*s++ == '\015') ||	   (*s++ == '\015') || (*s++ == '\015') || (*s++ == '\015') ||	   (*s++ == '\015') || (*s++ == '\015') || (*s++ == '\015')) &&	  (*s == '\012') && (*++s == '\015') && (*++s == '\012')) {	*size = elt->private.msg.header.text.size = siz + (++s - LOCAL->buf);	if (hdr) *hdr = LOCAL->buf;	return ret;      }    for (te = t - 3; (s < te);)	/* final character-at-a-time scan */      if ((*s++ == '\015') && (*s == '\012') && (*++s == '\015') &&	  (*++s == '\012')) {	*size = elt->private.msg.header.text.size = siz + (++s - LOCAL->buf);	if (hdr) *hdr = LOCAL->buf;	return ret;      }    if (i <= SLOP) break;	/* end of data */				/* slide over last 4 bytes */    memmove (LOCAL->buf,t - SLOP,SLOP);    hdr = NIL;			/* can't return header this way */  }				/* not found: header consumes entire message */  elt->private.msg.header.text.size = *size = elt->rfc822_size;  if (hdr) *hdr = LOCAL->buf;	/* possibly return header too */  return ret;}/* MBX mail rewrite mailbox * Accepts: MAIL stream *	    pointer to return reclaimed size *	    flags (0 = no expunge, 1 = expunge deleted, -1 = expunge sequence) * Returns: number of expunged messages */unsigned long mbx_rewrite (MAILSTREAM *stream,unsigned long *reclaimed,			   long flags){  struct utimbuf times;  struct stat sbuf;  off_t pos,ppos;  int ld;  unsigned long i,j,k,m,delta;  unsigned long n = *reclaimed = 0;  unsigned long recent = 0;  char lock[MAILTMPLEN];  MESSAGECACHE *elt;				/* get parse/append permission */  if ((ld = lockname (lock,stream->mailbox,LOCK_EX)) < 0) {    mm_log ("Unable to lock expunge mailbox",ERROR);    return 0;  }  fstat (LOCAL->fd,&sbuf);	/* get current write time */  if (LOCAL->filetime && !LOCAL->flagcheck &&      (LOCAL->filetime < sbuf.st_mtime)) LOCAL->flagcheck = T;  if (!mbx_parse (stream)) {	/* make sure see any newly-arrived messages */    unlockfd (ld,lock);		/* failed?? */    return 0;  }  if (LOCAL->flagcheck) {	/* sweep flags if need flagcheck */    LOCAL->filetime = sbuf.st_mtime;    for (i = 1; i <= stream->nmsgs; ++i) mbx_elt (stream,i,NIL);    LOCAL->flagcheck = NIL;  }				/* get exclusive access */  if (!flock (LOCAL->fd,LOCK_EX|LOCK_NB)) {    mm_critical (stream);	/* go critical */    for (i = 1,delta = 0,pos = ppos = HDRSIZE; i <= stream->nmsgs; ) {				/* note if message not at predicted location */      if (m = (elt = mbx_elt (stream,i,NIL))->private.special.offset - ppos) {	ppos = elt->private.special.offset;	*reclaimed += m;	/* note reclaimed message space */	delta += m;		/* and as expunge delta  */      }				/* number of bytes to smash or preserve */      ppos += (k = elt->private.special.text.size + elt->rfc822_size);				/* if need to expunge this message*/      if (flags && elt->deleted && ((flags > 0) || elt->sequence)) {	delta += k;		/* number of bytes to delete */	mail_expunged(stream,i);/* notify upper levels */	n++;			/* count up one more expunged message */      }      else {			/* preserved message */	i++;			/* count this message */	if (elt->recent) ++recent;	if (delta) {		/* moved, note 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 yet */	else pos = elt->private.special.offset + k;      }    }				/* deltaed file size match position? */    if (m = (LOCAL->filesize -= delta) - pos) {      *reclaimed += m;		/* probably an fEXPUNGED msg */      LOCAL->filesize = pos;	/* set correct size */    }				/* truncate file after last message */    ftruncate (LOCAL->fd,LOCAL->filesize);    fsync (LOCAL->fd);		/* force disk update */    mm_nocritical (stream);	/* release critical */    flock (LOCAL->fd,LOCK_SH);	/* allow sharers again */  }  else {			/* can't get exclusive */    flock (LOCAL->fd,LOCK_SH);	/* recover previous shared mailbox lock */				/* do hide-expunge when shared */    if (flags) for (i = 1; i <= stream->nmsgs; ) {      if (elt = mbx_elt (stream,i,T)) {				/* make the message invisible */	if (elt->deleted && ((flags > 0) || elt->sequence)) {	  mbx_update_status (stream,elt->msgno,LONGT);				/* notify upper levels */	  mail_expunged (stream,i);	  n++;			/* count up one more expunged message */	}	else {	  i++;			/* preserved message */	  if (elt->recent) ++recent;	}      }      else n++;			/* count up one more expunged message */    }    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);  unlockfd (ld,lock);		/* release exclusive parse/append permission */				/* notify upper level of new mailbox size */  mail_exists (stream,stream->nmsgs);  mail_recent (stream,recent);  return n;			/* return number of expunged messages */}/* MBX mail lock for flag updating * Accepts: stream * Returns: T if successful, NIL if failure */long mbx_flaglock (MAILSTREAM *stream){  struct stat sbuf;  unsigned long i;  int ld;  char lock[MAILTMPLEN];				/* no-op if readonly or already locked */  if (!stream->rdonly && LOCAL && (LOCAL->fd >= 0) && (LOCAL->ld < 0)) {				/* lock now */    if ((ld = lockname (lock,stream->mailbox,LOCK_EX)) < 0) return NIL;    if (!LOCAL->flagcheck) {	/* don't do this if flagcheck already needed */      if (LOCAL->filetime) {	/* know previous time? */	fstat (LOCAL->fd,&sbuf);/* get current write time */	if (LOCAL->filetime < sbuf.st_mtime) LOCAL->flagcheck = T;	LOCAL->filetime = 0;	/* don't do this test for any other messages */      }      if (!mbx_parse (stream)) {/* parse mailbox */	unlockfd (ld,lock);	/* shouldn't happen */	return NIL;      }      if (LOCAL->flagcheck)	/* invalidate cache if flagcheck */	for (i = 1; i <= stream->nmsgs; ++i) mail_elt (stream,i)->valid = NIL;    }    LOCAL->ld = ld;		/* copy to stream for subsequent calls */    memcpy (LOCAL->lock,lock,MAILTMPLEN);  }  return LONGT;}

⌨️ 快捷键说明

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