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

📄 mx.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 3 页
字号:
	}				/* note uncached */	LOCAL->cachedtexts -= ((elt->private.msg.header.text.data ?				elt->private.msg.header.text.size : 0) +			       (elt->private.msg.text.text.data ?				elt->private.msg.text.text.size : 0));	mail_gc_msg (&elt->private.msg,GC_ENV | GC_TEXTS);	if(elt->recent)--recent;/* if recent, note one less recent message */	mail_expunged(stream,i);/* notify upper levels */	n++;			/* count up one more expunged message */      }      else i++;			/* otherwise try next message */    }    if (n) {			/* output the news if any expunged */      sprintf (LOCAL->buf,"Expunged %lu messages",n);      MM_LOG (LOCAL->buf,(long) NIL);    }    else MM_LOG ("No messages deleted, so no update needed",(long) NIL);    MM_NOCRITICAL (stream);	/* release critical */    mx_unlockindex (stream);	/* finished with index */				/* notify upper level of new mailbox size */    mail_exists (stream,stream->nmsgs);    mail_recent (stream,recent);  }  return ret;}/* MX mail copy message(s) * Accepts: MAIL stream *	    sequence *	    destination mailbox *	    copy options * Returns: T if copy successful, else NIL */long mx_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options){  FDDATA d;  STRING st;  MESSAGECACHE *elt;  MAILSTREAM *astream;  struct stat sbuf;  int fd;  unsigned long i,j,uid,uidv;  char *t,tmp[MAILTMPLEN];  long ret;  mailproxycopy_t pc =    (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL);				/* make sure valid mailbox */  if (!mx_valid (mailbox)) switch (errno) {  case NIL:			/* no error in stat() */    if (pc) return (*pc) (stream,sequence,mailbox,options);    sprintf (LOCAL->buf,"Not a MX-format mailbox: %.80s",mailbox);    MM_LOG (LOCAL->buf,ERROR);    return NIL;  default:			/* some stat() error */    MM_NOTIFY (stream,"[TRYCREATE] Must create mailbox before copy",NIL);    return NIL;  }				/* copy the messages */  if (!(ret = ((options & CP_UID) ? mail_uid_sequence (stream,sequence) :	       mail_sequence (stream,sequence))));				/* acquire stream to append to */  else if (!(astream = mail_open (NIL,mailbox,OP_SILENT))) {    MM_LOG ("Can't open copy mailbox",ERROR);    ret = NIL;  }  else {    MM_CRITICAL (stream);	/* go critical */    if (!(ret = mx_lockindex (astream)))      MM_LOG ("Message copy failed: unable to lock index",ERROR);    else {      copyuid_t cu = (copyuid_t) mail_parameters (NIL,GET_COPYUID,NIL);      SEARCHSET *source = cu ? mail_newsearchset () : NIL;      SEARCHSET *dest = cu ? mail_newsearchset () : NIL;      for (i = 1,uid = uidv = 0; ret && (i <= stream->nmsgs); i++)       if ((elt = mail_elt (stream,i))->sequence) {	if (ret = ((fd = open (mx_fast_work (stream,elt),O_RDONLY,NIL))		   >= 0)) {	  fstat (fd,&sbuf);	/* get size of message */	  d.fd = fd;		/* set up file descriptor */	  d.pos = 0;		/* start of file */	  d.chunk = LOCAL->buf;	  d.chunksize = CHUNKSIZE;	  INIT (&st,fd_string,&d,sbuf.st_size);				/* init flag string */	  tmp[0] = tmp[1] = '\0';	  if (j = elt->user_flags) do	    if (t = stream->user_flags[find_rightmost_bit (&j)])	      strcat (strcat (tmp," "),t);	  while (j);	  if (elt->seen) strcat (tmp," \\Seen");	  if (elt->deleted) strcat (tmp," \\Deleted");	  if (elt->flagged) strcat (tmp," \\Flagged");	  if (elt->answered) strcat (tmp," \\Answered");	  if (elt->draft) strcat (tmp," \\Draft");	  tmp[0] = '(';		/* open list */	  strcat (tmp,")");	/* close list */	  if (ret = mx_append_msg (astream,tmp,elt,&st,dest)) {				/* add to source set if needed */	    if (source) mail_append_set (source,mail_uid (stream,i));				/* delete if doing a move */	    if (options & CP_MOVE) elt->deleted = T;	  }	}      }				/* return sets if doing COPYUID */      if (cu && ret) (*cu) (stream,mailbox,astream->uid_validity,source,dest);      else {			/* flush any sets we may have built */	mail_free_searchset (&source);	mail_free_searchset (&dest);      }      mx_unlockindex (astream);	/* unlock index */    }    MM_NOCRITICAL (stream);    mail_close (astream);	/* finished with append stream */  }  return ret;			/* return success */}/* MX mail append message from stringstruct * Accepts: MAIL stream *	    destination mailbox *	    append callback *	    data for callback * Returns: T if append successful, else NIL */long mx_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){  MESSAGECACHE elt;  MAILSTREAM *astream;  char *flags,*date,tmp[MAILTMPLEN];  STRING *message;  long ret = LONGT;				/* default stream to prototype */  if (!stream) stream = user_flags (&mxproto);				/* N.B.: can't use LOCAL->buf for tmp */				/* make sure valid mailbox */  if (!mx_isvalid (mailbox,tmp)) switch (errno) {  case ENOENT:			/* no such file? */    if (!compare_cstring (mailbox,"INBOX")) mx_create (NIL,"INBOX");    else {      MM_NOTIFY (stream,"[TRYCREATE] Must create mailbox before append",NIL);      return NIL;    }				/* falls through */  case 0:			/* merely empty file? */    break;  case EINVAL:    sprintf (tmp,"Invalid MX-format mailbox name: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  default:    sprintf (tmp,"Not a MX-format mailbox: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  }				/* get first message */  if (!MM_APPEND (af) (stream,data,&flags,&date,&message)) return NIL;  if (!(astream = mail_open (NIL,mailbox,OP_SILENT))) {    MM_LOG ("Can't open append mailbox",ERROR);    return NIL;  }  MM_CRITICAL (astream);	/* go critical */				/* lock the index */  if (!(ret = mx_lockindex (astream)))    MM_LOG ("Message append failed: unable to lock index",ERROR);  else {    appenduid_t au = (appenduid_t) mail_parameters (NIL,GET_APPENDUID,NIL);    SEARCHSET *dst = au ? mail_newsearchset () : NIL;    do {				/* guard against zero-length */      if (!(ret = SIZE (message)))	MM_LOG ("Append of zero-length message",ERROR);      else if (date && !(ret = mail_parse_date (&elt,date))) {	sprintf (tmp,"Bad date in append: %.80s",date);	MM_LOG (tmp,ERROR);      }      else ret = mx_append_msg (astream,flags,date ? &elt : NIL,message,dst)&&	     MM_APPEND (af) (stream,data,&flags,&date,&message);    } while (ret && message);				/* return sets if doing APPENDUID */    if (au && ret) (*au) (mailbox,astream->uid_validity,dst);    else mail_free_searchset (&dst);    mx_unlockindex (astream);	/* unlock index */  }  MM_NOCRITICAL (astream);	/* release critical */  mail_close (astream);  return ret;}/* MX mail append single message * Accepts: MAIL stream *	    flags for new message if non-NIL *	    elt with source date if non-NIL *	    stringstruct of message text *	    searchset to place UID * Returns: T if success, NIL if failure */long mx_append_msg (MAILSTREAM *stream,char *flags,MESSAGECACHE *elt,		    STRING *st,SEARCHSET *set){  char tmp[MAILTMPLEN];  int fd;  unsigned long uf;  long f = mail_parse_flags (stream,flags,&uf);				/* make message file name */  sprintf (tmp,"%s/%lu",stream->mailbox,++stream->uid_last);  if ((fd = open (tmp,O_WRONLY|O_CREAT|O_EXCL,		  (long) mail_parameters (NIL,GET_MBXPROTECTION,NIL))) < 0) {    sprintf (tmp,"Can't create append message: %s",strerror (errno));    MM_LOG (tmp,ERROR);    return NIL;  }  while (SIZE (st)) {		/* copy the file */    if (st->cursize && (write (fd,st->curpos,st->cursize) < 0)) {      unlink (tmp);		/* delete file */      close (fd);		/* close the file */      sprintf (tmp,"Message append failed: %s",strerror (errno));      MM_LOG (tmp,ERROR);      return NIL;    }    SETPOS (st,GETPOS (st) + st->cursize);  }  close (fd);			/* close the file */  if (elt) mx_setdate (tmp,elt);/* set file date */				/* swell the cache */  mail_exists (stream,++stream->nmsgs);				/* copy flags */  mail_append_set (set,(elt = mail_elt (stream,stream->nmsgs))->private.uid =		   stream->uid_last);  if (f&fSEEN) elt->seen = T;  if (f&fDELETED) elt->deleted = T;  if (f&fFLAGGED) elt->flagged = T;  if (f&fANSWERED) elt->answered = T;  if (f&fDRAFT) elt->draft = T;  elt->user_flags |= uf;  return LONGT;}/* Internal routines *//* MX file name selection test * Accepts: candidate directory entry * Returns: T to use file name, NIL to skip it */int mx_select (struct direct *name){  char c;  char *s = name->d_name;  while (c = *s++) if (!isdigit (c)) return NIL;  return T;}/* MX file name comparision * Accepts: first candidate directory entry *	    second candidate directory entry * Returns: negative if d1 < d2, 0 if d1 == d2, postive if d1 > d2 */int mx_numsort (const void *d1,const void *d2){  return atoi ((*(struct direct **) d1)->d_name) -    atoi ((*(struct direct **) d2)->d_name);}/* MX mail build file name * Accepts: destination string *          source * Returns: destination */char *mx_file (char *dst,char *name){  char *s;				/* empty string if mailboxfile fails */  if (!mailboxfile (dst,name)) *dst = '\0';				/* driver-selected INBOX  */  else if (!*dst) mailboxfile (dst,"~/INBOX");				/* tie off unnecessary trailing / */  else if ((s = strrchr (dst,'/')) && !s[1]) *s = '\0';  return dst;}/* MX read and lock index * Accepts: MAIL stream * Returns: T if success, NIL if failure */long mx_lockindex (MAILSTREAM *stream){  unsigned long uf,sf,uid;  int k = 0;  unsigned long msgno = 1;  struct stat sbuf;  char *s,*t,*idx,tmp[2*MAILTMPLEN];  MESSAGECACHE *elt;  blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);  if ((LOCAL->fd < 0) &&	/* get index file, no-op if already have it */      (LOCAL->fd = open (strcat (strcpy (tmp,stream->mailbox),MXINDEXNAME),			 O_RDWR|O_CREAT,			 (long) mail_parameters (NIL,GET_MBXPROTECTION,NIL)))      >= 0) {    (*bn) (BLOCK_FILELOCK,NIL);    flock (LOCAL->fd,LOCK_EX);	/* get exclusive lock */    (*bn) (BLOCK_NONE,NIL);    fstat (LOCAL->fd,&sbuf);	/* get size of index */				/* slurp index */    read (LOCAL->fd,s = idx = (char *) fs_get (sbuf.st_size + 1),sbuf.st_size);    idx[sbuf.st_size] = '\0';	/* tie off index */				/* parse index */    if (sbuf.st_size) while (s && *s) switch (*s) {    case 'V':			/* UID validity record */      stream->uid_validity = strtoul (s+1,&s,16);      break;    case 'L':			/* UID last record */      stream->uid_last = strtoul (s+1,&s,16);      break;    case 'K':			/* keyword */				/* find end of keyword */      if (s = strchr (t = ++s,'\n')) {	*s++ = '\0';		/* tie off keyword */				/* copy keyword */	if ((k < NUSERFLAGS) && !stream->user_flags[k] &&	    (strlen (t) <= MAXUSERFLAG)) stream->user_flags[k] = cpystr (t);	k++;			/* one more keyword */      }      break;    case 'M':			/* message status record */      uid = strtoul (s+1,&s,16);/* get UID for this message */      if (*s == ';') {		/* get user flags */	uf = strtoul (s+1,&s,16);	if (*s == '.') {	/* get system flags */	  sf = strtoul (s+1,&s,16);	  while ((msgno <= stream->nmsgs) && (mail_uid (stream,msgno) < uid))	    msgno++;		/* find message number for this UID */	  if ((msgno <= stream->nmsgs) && (mail_uid (stream,msgno) == uid)) {	    (elt = mail_elt (stream,msgno))->valid = T;	    elt->user_flags=uf; /* set user and system flags in elt */	    if (sf & fSEEN) elt->seen = T;	    if (sf & fDELETED) elt->deleted = T;	    if (sf & fFLAGGED) elt->flagged = T;	    if (sf & fANSWERED) elt->answered = T;	    if (sf & fDRAFT) elt->draft = T;	  }	  break;	}      }    default:			/* bad news */      sprintf (tmp,"Error in index: %.80s",s);      MM_LOG (tmp,ERROR);      *s = NIL;			/* ignore remainder of index */    }    else {			/* new index */      stream->uid_validity = time (0);      user_flags (stream);	/* init stream with default user flags */    }    fs_give ((void **) &idx);	/* flush index */  }  return (LOCAL->fd >= 0) ? T : NIL;}/* MX write and unlock index * Accepts: MAIL stream */#define MXIXBUFLEN 2048void mx_unlockindex (MAILSTREAM *stream){  unsigned long i,j;  off_t size = 0;  char *s,tmp[MXIXBUFLEN + 64];  MESSAGECACHE *elt;  if (LOCAL->fd >= 0) {    lseek (LOCAL->fd,0,L_SET);	/* rewind file */				/* write header */    sprintf (s = tmp,"V%08lxL%08lx",stream->uid_validity,stream->uid_last);    for (i = 0; (i < NUSERFLAGS) && stream->user_flags[i]; ++i)      sprintf (s += strlen (s),"K%s\n",stream->user_flags[i]);				/* write messages */    for (i = 1; i <= stream->nmsgs; i++) {				/* filled buffer? */      if (((s += strlen (s)) - tmp) > MXIXBUFLEN) {	write (LOCAL->fd,tmp,j = s - tmp);	size += j;	*(s = tmp) = '\0';	/* dump out and restart buffer */      }      elt = mail_elt (stream,i);      sprintf(s,"M%08lx;%08lx.%04x",elt->private.uid,elt->user_flags,(unsigned)	      ((fSEEN * elt->seen) + (fDELETED * elt->deleted) +	       (fFLAGGED * elt->flagged) + (fANSWERED * elt->answered) +	       (fDRAFT * elt->draft)));    }				/* write tail end of buffer */    if ((s += strlen (s)) != tmp) {      write (LOCAL->fd,tmp,j = s - tmp);      size += j;    }    ftruncate (LOCAL->fd,size);    flock (LOCAL->fd,LOCK_UN);	/* unlock the index */    close (LOCAL->fd);		/* finished with file */    LOCAL->fd = -1;		/* no index now */  }}/* Set date for message * Accepts: file name *	    elt containing date */void mx_setdate (char *file,MESSAGECACHE *elt){  time_t tp[2];  tp[0] = time (0);		/* atime is now */  tp[1] = mail_longdate (elt);	/* modification time */  utime (file,tp);		/* set the times */}

⌨️ 快捷键说明

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