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

📄 mix.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
  return (char *) LOCAL->buf + i;}/* MIX mail fetch message text (body only) * Accepts: MAIL stream *	    message # to fetch *	    pointer to returned stringstruct *	    option flags * Returns: T on success, NIL on failure */long mix_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags){  unsigned long i;  FDDATA d;  MESSAGECACHE *elt;				/* UID call "impossible" */  if (flags & FT_UID) return NIL;  elt = mail_elt (stream,msgno);				/* is message in current message file? */  if ((LOCAL->msgfd < 0) || (elt->private.spare.data != LOCAL->curmsg)) {    if (LOCAL->msgfd >= 0) close (LOCAL->msgfd);    if ((LOCAL->msgfd = open (mix_file_data (LOCAL->buf,stream->mailbox,					     elt->private.spare.data),					     O_RDONLY,NIL)) < 0) return NIL;				/* got file */    LOCAL->curmsg = elt->private.spare.data;  }    				/* doing non-peek fetch? */  if (!(flags & FT_PEEK) && !elt->seen) {    FILE *idxf;			/* yes, process metadata/index/status */    FILE *statf = mix_parse (stream,&idxf,NIL,LONGT);    elt->seen = T;		/* mark as seen */    MM_FLAGS (stream,elt->msgno);				/* update status file if possible */    if (statf && !stream->rdonly) {      elt->private.mod = LOCAL->statusseq = mix_modseq (LOCAL->statusseq);      mix_status_update (stream,statf,NIL);    }    if (idxf) fclose (idxf);	/* release index and status file */    if (statf) fclose (statf);  }   d.fd = LOCAL->msgfd;		/* set up file descriptor */				/* offset of message text */  d.pos = elt->private.special.offset + elt->private.msg.header.offset +    elt->private.msg.header.text.size;  d.chunk = LOCAL->buf;		/* initial buffer chunk */  d.chunksize = CHUNKSIZE;	/* chunk size */  INIT (bs,fd_string,&d,elt->rfc822_size - elt->private.msg.header.text.size);  return T;}/* MIX mail modify flags * Accepts: MAIL stream *	    sequence *	    flag(s) *	    option flags */void mix_flag (MAILSTREAM *stream,char *sequence,char *flag,long flags){  MESSAGECACHE *elt;  unsigned long i,uf,ffkey;  long f;  short nf;  FILE *idxf;  FILE *statf = mix_parse (stream,&idxf,NIL,LONGT);  unsigned long seq = mix_modseq (LOCAL->statusseq);				/* find first free key */  for (ffkey = 0; (ffkey < NUSERFLAGS) && stream->user_flags[ffkey]; ++ffkey);				/* parse sequence and flags */  if (((flags & ST_UID) ? mail_uid_sequence (stream,sequence) :       mail_sequence (stream,sequence)) &&      ((f = mail_parse_flags (stream,flag,&uf)) || uf)) {				/* alter flags */    for (i = 1,nf = (flags & ST_SET) ? T : NIL; i <= stream->nmsgs; i++)      if ((elt = mail_elt (stream,i))->sequence) {	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;	if (f&fSEEN) elt->seen = nf;	if (f&fDELETED) elt->deleted = nf;	if (f&fFLAGGED) elt->flagged = nf;	if (f&fANSWERED) elt->answered = nf;	if (f&fDRAFT) elt->draft = nf;				/* user flags */	if (flags & ST_SET) elt->user_flags |= uf;	else elt->user_flags &= ~uf;	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)) {	  if (!stream->rdonly) elt->private.mod = LOCAL->statusseq = seq;	  MM_FLAGS (stream,elt->msgno);	}      }				/* update status file after change */    if (statf && (seq == LOCAL->statusseq))      mix_status_update (stream,statf,NIL);				/* update metadata if created a keyword */    if ((ffkey < NUSERFLAGS) && stream->user_flags[ffkey] &&	!mix_meta_update (stream))      MM_LOG ("Error updating mix metadata after keyword creation",ERROR);  }  if (statf) fclose (statf);	/* release status file if still open */  if (idxf) fclose (idxf);	/* release index file */}/* MIX mail sort messages * Accepts: mail stream *	    character set *	    search program *	    sort program *	    option flags * Returns: vector of sorted message sequences or NIL if error */unsigned long *mix_sort (MAILSTREAM *stream,char *charset,SEARCHPGM *spg,			 SORTPGM *pgm,long flags){  unsigned long *ret;  FILE *sortcache = mix_sortcache_open (stream);  ret = mail_sort_msgs (stream,charset,spg,pgm,flags);  mix_sortcache_update (stream,&sortcache);  return ret;}/* MIX mail thread messages * Accepts: mail stream *	    thread type *	    character set *	    search program *	    option flags * Returns: thread node tree or NIL if error */THREADNODE *mix_thread (MAILSTREAM *stream,char *type,char *charset,			SEARCHPGM *spg,long flags){  THREADNODE *ret;  FILE *sortcache = mix_sortcache_open (stream);  ret = mail_thread_msgs (stream,type,charset,spg,flags,mail_sort_msgs);  mix_sortcache_update (stream,&sortcache);  return ret;}/* MIX mail ping mailbox * Accepts: MAIL stream * Returns: T if stream alive, else NIL */static int snarfing = 0;	/* lock against recursive snarfing */long mix_ping (MAILSTREAM *stream){  FILE *idxf,*statf;  struct stat sbuf;  STRING msg;  MESSAGECACHE *elt;  int mfd,ifd,sfd;  unsigned long i,msglen;  char *message,date[MAILTMPLEN],flags[MAILTMPLEN];  MAILSTREAM *sysibx = NIL;  long ret = NIL;  long snarfok = LONGT;				/* time to snarf? */  if (stream->inbox && !stream->rdonly && !snarfing &&      (time (0) >= (LOCAL->lastsnarf +		    (time_t) mail_parameters (NIL,GET_SNARFINTERVAL,NIL)))) {    appenduid_t au = (appenduid_t) mail_parameters (NIL,GET_APPENDUID,NIL);    copyuid_t cu = (copyuid_t) mail_parameters (NIL,GET_COPYUID,NIL);    MM_CRITICAL (stream);	/* go critical */    snarfing = T;		/* don't recursively snarf */				/* disable APPENDUID/COPYUID callbacks */    mail_parameters (NIL,SET_APPENDUID,NIL);    mail_parameters (NIL,SET_COPYUID,NIL);				/* sizes match and anything in sysinbox? */    if (!stat (sysinbox (),&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFREG) &&	sbuf.st_size &&	(sysibx = mail_open (sysibx,sysinbox (),OP_SILENT)) &&	!sysibx->rdonly && sysibx->nmsgs) {				/* for each message in sysibx mailbox */      for (i = 1; snarfok && (i <= sysibx->nmsgs); ++i)	if (!(elt = mail_elt (sysibx,i))->deleted &&	    (message = mail_fetch_message (sysibx,i,&msglen,FT_PEEK)) &&	    msglen) {	  mail_date (date,elt);	/* make internal date string */				/* make flag string */	  flags[0] = flags[1] = '\0';	  if (elt->seen) strcat (flags," \\Seen");	  if (elt->flagged) strcat (flags," \\Flagged");	  if (elt->answered) strcat (flags," \\Answered");	  if (elt->draft) strcat (flags," \\Draft");	  flags[0] = '(';	  strcat (flags,")");	  INIT (&msg,mail_string,message,msglen);	  if (snarfok = mail_append_full (stream,"INBOX",flags,date,&msg)) {	    char sequence[15];	    sprintf (sequence,"%lu",i);	    mail_flag (sysibx,sequence,"\\Deleted",ST_SET);	  }	}				/* now expunge all those messages */      if (snarfok) mail_expunge (sysibx);      else {	sprintf (LOCAL->buf,"Can't copy new mail at message: %lu",i - 1);	MM_LOG (LOCAL->buf,WARN);      }    }    if (sysibx) mail_close (sysibx);				/* reenable APPENDUID/COPYUID */    mail_parameters (NIL,SET_APPENDUID,(void *) au);    mail_parameters (NIL,SET_COPYUID,(void *) cu);    snarfing = NIL;		/* no longer snarfing */    MM_NOCRITICAL (stream);	/* release critical */    LOCAL->lastsnarf = time (0);/* note time of last snarf */  }				/* expunging OK if global flag set */  if (mail_parameters (NIL,GET_EXPUNGEATPING,NIL)) LOCAL->expok = T;				/* process metadata/index/status */  if (statf = mix_parse (stream,&idxf,LONGT,			 (LOCAL->internal ? NIL : LONGT))) {    fclose (statf);		/* just close the status file */    ret = LONGT;		/* declare success */  }  if (idxf) fclose (idxf);	/* release index file */  LOCAL->expok = NIL;		/* expunge no longer OK */  if (!ret) mix_abort (stream);	/* murdelyze stream if ping fails */  return ret;}/* MIX mail checkpoint mailbox (burp only) * Accepts: MAIL stream */void mix_check (MAILSTREAM *stream){  if (stream->rdonly)		/* won't do on readonly files! */    MM_LOG ("Checkpoint ignored on readonly mailbox",NIL);				/* do burp-only expunge action */  if (mix_expunge (stream,"",NIL)) MM_LOG ("Check completed",(long) NIL);}/* MIX mail expunge mailbox * Accepts: MAIL stream *	    sequence to expunge if non-NIL, empty string for burp only *	    expunge options * Returns: T on success, NIL if failure */long mix_expunge (MAILSTREAM *stream,char *sequence,long options){  FILE *idxf = NIL;  FILE *statf = NIL;  MESSAGECACHE *elt;  int ifd,sfd;  long ret;  unsigned long i;  unsigned long nexp = 0;  unsigned long reclaimed = 0;  int burponly = (sequence && !*sequence);  LOCAL->expok = T;		/* expunge during ping is OK */  if (!(ret = burponly || !sequence ||	((options & EX_UID) ?	 mail_uid_sequence (stream,sequence) :	 mail_sequence (stream,sequence))) || stream->rdonly);				/* read index and open status exclusive */  else if (statf = mix_parse (stream,&idxf,LONGT,			      LOCAL->internal ? NIL : LONGT)) {				/* expunge unless just burping */    if (!burponly) for (i = 1; i <= stream->nmsgs;) {      elt = mail_elt (stream,i);/* need to expunge this message? */      if (sequence ? elt->sequence : elt->deleted) {	++nexp;			/* yes, make it so */	mail_expunged (stream,i);      }      else ++i;		       /* otherwise advance to next message */    }				/* burp if can get exclusive access */    if (!flock (LOCAL->mfd,LOCK_EX|LOCK_NB)) {      void *a;      struct direct **names = NIL;      long nfiles = scandir (stream->mailbox,&names,mix_select,mix_msgfsort);      if (nfiles > 0) {		/* if have message files */	MIXBURP *burp,*cur;				/* initialize burp list */	for (i = 0, burp = cur = NIL; i < nfiles; ++i) {	  MIXBURP *nxt = (MIXBURP *) memset (fs_get (sizeof (MIXBURP)),0,					     sizeof (MIXBURP));				/* another file found */	  if (cur) cur = cur->next = nxt;	  else cur = burp = nxt;	  cur->name = names[i]->d_name;	  cur->fileno = strtoul (cur->name + sizeof (MIXNAME) - 1,NIL,16);	  cur->tail = &cur->set;	  fs_give ((void **) &names[i]);	}				/* now load ranges */	for (i = 1, cur = burp; ret && (i <= stream->nmsgs); i++) {				/* is this message in current set? */	  elt = mail_elt (stream,i);	  if (cur && (elt->private.spare.data != cur->fileno)) {				/* restart if necessary */	    if (elt->private.spare.data < cur->fileno) cur = burp;				/* hunt for appropriate mailbox */	    while (cur && (elt->private.spare.data > cur->fileno))	      cur = cur->next;				/* ought to have found it now... */	    if (cur && (elt->private.spare.data != cur->fileno)) cur = NIL;	  }				/* if found, add to set */	  if (cur) ret = mix_addset (&cur->tail,elt->private.special.offset,				     elt->private.msg.header.offset +				     elt->rfc822_size);	  else {		/* uh-oh */	    sprintf (LOCAL->buf,"Can't locate mix message file %.08lx",		     elt->private.spare.data);	    MM_LOG (LOCAL->buf,ERROR);	    ret = NIL;	  }	}	if (ret) 		/* if no errors, burp all files */	  for (cur = burp; ret && cur; cur = cur->next) {				/* if non-empty, burp it */	    if (cur->set.last) ret = mix_burp (stream,cur,&reclaimed);				/* empty, delete it unless new msg file */	    else if (mix_file_data (LOCAL->buf,stream->mailbox,cur->fileno) &&		     ((cur->fileno == LOCAL->newmsg) ?		      truncate (LOCAL->buf,0) : unlink (LOCAL->buf))) {	      sprintf (LOCAL->buf,		       "Can't delete empty message file %.80s: %.80s",		       cur->name,strerror (errno));	      MM_LOG (LOCAL->buf,WARN);	    }	  }      }      else MM_LOG ("No mix message files found during expunge",WARN);				/* free directory list */      if (a = (void *) names) fs_give ((void **) &a);    }				/* either way, re-acquire shared lock */    if (flock (LOCAL->mfd,LOCK_SH|LOCK_NB))      fatal ("Unable to re-acquire metadata shared lock!");    /* Do this step even if ret is NIL (meaning some burp problem)! */    if (nexp || reclaimed) {	/* rewrite index and status if changed */      LOCAL->indexseq = mix_modseq (LOCAL->indexseq);      if (mix_index_update (stream,idxf,NIL)) {	LOCAL->statusseq = mix_modseq (LOCAL->statusseq);				/* set failure if update fails */	ret = mix_status_update (stream,statf,NIL);      }    }  }  if (statf) fclose (statf);	/* close status if still open */  if (idxf) fclose (idxf);	/* close index if still open */  LOCAL->expok = NIL;		/* cancel expok */  if (ret) {			/* only if success */    char *s = NIL;    if (nexp) sprintf (s = LOCAL->buf,"Expunged %lu messages",nexp);    else if (reclaimed)      sprintf (s=LOCAL->buf,"Reclaimed %lu bytes of expunged space",reclaimed);    else if (!burponly)      s = stream->rdonly ? "Expunge ignored on readonly mailbox" :	   "No messages deleted, so no update needed";    if (s) MM_LOG (s,(long) NIL);  }  return ret;}

⌨️ 快捷键说明

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