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

📄 mix.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
long mix_unsubscribe (MAILSTREAM *stream,char *mailbox){  return sm_unsubscribe (mailbox);}/* MIX mail create mailbox * Accepts: mail stream *	    mailbox name to create * Returns: T on success, NIL on failure */long mix_create (MAILSTREAM *stream,char *mailbox){  DRIVER *test;  FILE *f;  int c,i;  char *t,tmp[MAILTMPLEN],file[MAILTMPLEN];  char *s = strrchr (mailbox,'/');  unsigned long now = time (NIL);  long ret = NIL;				/* always create \NoSelect if trailing /  */  if (s && !s[1]) return dummy_create (stream,mailbox);				/* validate name */  if (mix_dirfmttest (s ? s + 1 : mailbox))    sprintf(tmp,"Can't create mailbox %.80s: invalid MIX-format name",mailbox);				/* must not already exist */  else if ((test = mail_valid (NIL,mailbox,NIL)) &&	   strcmp (test->name,"dummy"))    sprintf (tmp,"Can't create mailbox %.80s: mailbox already exists",mailbox);				/* create directory and metadata */  else if (!dummy_create_path (stream,			       mix_file (file,mix_dir (tmp,mailbox),MIXMETA),			       get_dir_protection (mailbox)))    sprintf (tmp,"Can't create mailbox %.80s: %.80s",mailbox,strerror (errno));  else if (!(f = fopen (file,"w")))    sprintf (tmp,"Can't re-open metadata %.80s: %.80s",mailbox,	     strerror (errno));  else {			/* success, write initial metadata */    fprintf (f,SEQFMT,now);    fprintf (f,MTAFMT,now,0,now);    for (i = 0, c = 'K'; (i < NUSERFLAGS) &&	   (t = (stream && stream->user_flags[i]) ? stream->user_flags[i] :	    default_user_flag (i)) && *t; ++i) {      putc (c,f);		/* write another keyword */      fputs (t,f);      c = ' ';			/* delimiter is now space */    }    fclose (f);    set_mbx_protections (mailbox,file);				/* point to suffix */    s = file + strlen (file) - (sizeof (MIXMETA) - 1);    strcpy (s,MIXINDEX);	/* create index */    if (!dummy_create_path (stream,file,get_dir_protection (mailbox)))      sprintf (tmp,"Can't create mix mailbox index: %.80s",strerror (errno));    else {      set_mbx_protections (mailbox,file);      strcpy (s,MIXSTATUS);	/* create status */      if (!dummy_create_path (stream,file,get_dir_protection (mailbox)))	sprintf (tmp,"Can't create mix mailbox status: %.80s",		 strerror (errno));      else {	set_mbx_protections (mailbox,file);	sprintf (s,"%08lx",now);/* message file */	if (!dummy_create_path (stream,file,get_dir_protection (mailbox)))	  sprintf (tmp,"Can't create mix mailbox data: %.80s",		   strerror (errno));	else {	  set_mbx_protections (mailbox,file);	  ret = LONGT;	/* declare success at this point */	}      }    }  }  if (!ret) MM_LOG (tmp,ERROR);	/* some error */  return ret;}/* MIX mail delete mailbox *	    mailbox name to delete * Returns: T on success, NIL on failure */long mix_delete (MAILSTREAM *stream,char *mailbox){  DIR *dirp;  struct direct *d;  int fd = -1;  char *s,tmp[MAILTMPLEN];  if (!mix_isvalid (mailbox,tmp))    sprintf (tmp,"Can't delete mailbox %.80s: no such mailbox",mailbox);  else if (((fd = open (tmp,O_RDWR,NIL)) < 0) || flock (fd,LOCK_EX|LOCK_NB))    sprintf (tmp,"Can't lock mailbox for delete: %.80s",mailbox);				/* delete metadata */  else if (unlink (tmp)) sprintf (tmp,"Can't delete mailbox %.80s index: %80s",				  mailbox,strerror (errno));  else {    close (fd);			/* close descriptor on deleted metadata */				/* get directory name */    *(s = strrchr (tmp,'/')) = '\0';    if (dirp = opendir (tmp)) {	/* open directory */      *s++ = '/';		/* restore delimiter */				/* massacre messages */      while (d = readdir (dirp)) if (mix_dirfmttest (d->d_name)) {	strcpy (s,d->d_name);	/* make path */	unlink (tmp);		/* sayonara */      }      closedir (dirp);		/* flush directory */      *(s = strrchr (tmp,'/')) = '\0';      if (rmdir (tmp)) {	/* try to remove the directory */	sprintf (tmp,"Can't delete name %.80s: %.80s",		 mailbox,strerror (errno));	MM_LOG (tmp,WARN);      }    }    return T;			/* always success */  }  if (fd >= 0) close (fd);	/* close any descriptor on metadata */  MM_LOG (tmp,ERROR);		/* something failed */  return NIL;}/* MIX mail rename mailbox * Accepts: MIX mail stream *	    old mailbox name *	    new mailbox name * Returns: T on success, NIL on failure */long mix_rename (MAILSTREAM *stream,char *old,char *newname){  char c,*s,tmp[MAILTMPLEN],tmp1[MAILTMPLEN];  struct stat sbuf;  int fd = -1;  if (!mix_isvalid (old,tmp))    sprintf (tmp,"Can't rename mailbox %.80s: no such mailbox",old);  else if (((fd = open (tmp,O_RDWR,NIL)) < 0) || flock (fd,LOCK_EX|LOCK_NB))    sprintf (tmp,"Can't lock mailbox for rename: %.80s",old);  else if (mix_dirfmttest ((s = strrchr (newname,'/')) ? s + 1 : newname))    sprintf (tmp,"Can't rename to mailbox %.80s: invalid MIX-format name",	     newname);				/* new mailbox name must not be valid */  else if (mix_isvalid (newname,tmp))    sprintf (tmp,"Can't rename to mailbox %.80s: destination already exists",	     newname);  else {    mix_dir (tmp,old);		/* build old directory name */    mix_dir (tmp1,newname);	/* and new directory name */				/* easy if not INBOX */    if (compare_cstring (old,"INBOX")) {				/* found superior to destination name? */      if (s = strrchr (tmp1,'/')) {	c = *++s;		/* remember first character of inferior */	*s = '\0';		/* tie off to get just superior */				/* name doesn't exist, create it */	if ((stat (tmp1,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) &&	    !dummy_create_path (stream,tmp1,get_dir_protection (newname)))	  return NIL;	*s = c;			/* restore full name */      }      if (!rename (tmp,tmp1)) {	close (fd);		/* close descriptor on metadata */	return LONGT;      }    }				/* RFC 3501 requires this */    else if (dummy_create_path (stream,strcat (tmp1,"/"),				get_dir_protection (newname))) {      void *a;      int i,n,lasterror;      char *src,*dst;      struct direct **names = NIL;      size_t srcl = strlen (tmp);      size_t dstl = strlen (tmp1);				/* rename each mix file to new directory */      for (i = lasterror = 0,n = scandir (tmp,&names,mix_rselect,alphasort);	   i < n; ++i) {	size_t len = strlen (names[i]->d_name);	sprintf (src = (char *) fs_get (srcl + len + 2),"%s/%s",		 tmp,names[i]->d_name);	sprintf (dst = (char *) fs_get (dstl + len + 1),"%s%s",		 tmp1,names[i]->d_name);	if (rename (src,dst)) lasterror = errno;	fs_give ((void **) &src);	fs_give ((void **) &dst);	fs_give ((void **) &names[i]);      }				/* free directory list */      if (a = (void *) names) fs_give ((void **) &a);      if (lasterror) errno = lasterror;      else {	close (fd);		/* close descriptor on metadata */	return mix_create (NIL,"INBOX");      }    }    sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",	     old,newname,strerror (errno));  }  if (fd >= 0) close (fd);	/* close any descriptor on metadata */  MM_LOG (tmp,ERROR);		/* something failed */  return NIL;}/* MIX test for mix name * Accepts: candidate directory name * Returns: T if mix file name, NIL otherwise */int mix_rselect (struct direct *name){  return mix_dirfmttest (name->d_name);}/* MIX mail open * Accepts: stream to open * Returns: stream on success, NIL on failure */MAILSTREAM *mix_open (MAILSTREAM *stream){  short silent;				/* return prototype for OP_PROTOTYPE call */  if (!stream) return user_flags (&mixproto);  if (stream->local) fatal ("mix recycle stream");  stream->local = memset (fs_get (sizeof (MIXLOCAL)),0,sizeof (MIXLOCAL));				/* note if an INBOX or not */  stream->inbox = !compare_cstring (stream->mailbox,"INBOX");				/* make temporary buffer */  LOCAL->buf = (char *) fs_get (CHUNKSIZE);  LOCAL->buflen = CHUNKSIZE - 1;				/* set stream->mailbox to be directory name */  mix_dir (LOCAL->buf,stream->mailbox);  fs_give ((void **) &stream->mailbox);  stream->mailbox = cpystr (LOCAL->buf);  LOCAL->msgfd = -1;		/* currently no file open */  if (!(((!stream->rdonly &&	/* open metadata file */	  ((LOCAL->mfd = open (mix_file (LOCAL->buf,stream->mailbox,MIXMETA),			       O_RDWR,NIL)) >= 0)) ||	 ((stream->rdonly = T) &&	  ((LOCAL->mfd = open (mix_file (LOCAL->buf,stream->mailbox,MIXMETA),			       O_RDONLY,NIL)) >= 0))) &&	!flock (LOCAL->mfd,LOCK_SH))) {    MM_LOG ("Error opening mix metadata file",ERROR);    mix_abort (stream);    stream = NIL;		/* open fails */  }  else {			/* metadata open, complete open */    LOCAL->index = cpystr (mix_file (LOCAL->buf,stream->mailbox,MIXINDEX));    LOCAL->status = cpystr (mix_file (LOCAL->buf,stream->mailbox,MIXSTATUS));    LOCAL->sortcache = cpystr (mix_file (LOCAL->buf,stream->mailbox,					 MIXSORTCACHE));    stream->sequence++;		/* bump sequence number */				/* parse mailbox */    stream->nmsgs = stream->recent = 0;    if (silent = stream->silent) LOCAL->internal = T;    stream->silent = T;    if (mix_ping (stream)) {	/* do initial ping */				/* try burping in case we are exclusive */      if (!stream->rdonly) mix_expunge (stream,"",NIL);      if (!(stream->nmsgs || stream->silent))	MM_LOG ("Mailbox is empty",(long) NIL);      stream->silent = silent;	/* now notify upper level */      mail_exists (stream,stream->nmsgs);      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;      stream->kwd_create =	/* can we create new user flags? */	(stream->user_flags[NUSERFLAGS-1] || stream->rdonly) ? NIL : T;    }    else {			/* got murdelyzed in ping */      mix_abort (stream);      stream = NIL;    }  }  return stream;		/* return stream to caller */}/* MIX mail close * Accepts: MAIL stream *	    close options */void mix_close (MAILSTREAM *stream,long options){  if (LOCAL) {			/* only if a file is open */    int silent = stream->silent;    stream->silent = T;		/* note this stream is dying */				/* burp-only or expunge */    mix_expunge (stream,(options & CL_EXPUNGE) ? NIL : "",NIL);    mix_abort (stream);    stream->silent = silent;	/* reset silent state */  }}/* MIX mail abort stream * Accepts: MAIL stream */void mix_abort (MAILSTREAM *stream){  if (LOCAL) {			/* only if a file is open */				/* close current message file if open */    if (LOCAL->msgfd >= 0) close (LOCAL->msgfd);				/* close current metadata file if open */    if (LOCAL->mfd >= 0) close (LOCAL->mfd);    if (LOCAL->index) fs_give ((void **) &LOCAL->index);    if (LOCAL->status) fs_give ((void **) &LOCAL->status);    if (LOCAL->sortcache) fs_give ((void **) &LOCAL->sortcache);				/* free local scratch 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 */  }}/* MIX 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 *mix_header (MAILSTREAM *stream,unsigned long msgno,unsigned long *length,		  long flags){  unsigned long i,j,k;  int fd;  char *s,tmp[MAILTMPLEN];  MESSAGECACHE *elt;  if (length) *length = 0;	/* default return */  if (flags & FT_UID) return "";/* UID call "impossible" */  elt = mail_elt (stream,msgno);/* get elt */				/* 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 "";				/* got file */    LOCAL->curmsg = elt->private.spare.data;  }      lseek (LOCAL->msgfd,elt->private.special.offset,L_SET);				/* size of special data and header */  j = elt->private.msg.header.offset + elt->private.msg.header.text.size;  if (j > LOCAL->buflen) {	/* is buffer big enough? */				/* no, make one that is */    fs_give ((void **) &LOCAL->buf);    LOCAL->buf = (char *) fs_get ((LOCAL->buflen = j) + 1);  }  /* Maybe someday validate internaldate too */				/* slurp special data + header, validate */  if ((read (LOCAL->msgfd,LOCAL->buf,j) == j) &&      !strncmp (LOCAL->buf,MSGTOK,MSGTSZ) &&      (elt->private.uid == strtoul ((char *) LOCAL->buf + MSGTSZ,&s,16)) &&      (*s++ == ':') && (s = strchr (s,':')) &&      (k = strtoul (s+1,&s,16)) && (*s++ == ':') &&      (s < (char *) (LOCAL->buf + elt->private.msg.header.offset))) {				/* won, set offset and size of message */    i = elt->private.msg.header.offset;    *length = elt->private.msg.header.text.size;    if (k != elt->rfc822_size) {      sprintf (tmp,"Inconsistency in mix message size, uid=%lx (%lu != %lu)",	       elt->private.uid,elt->rfc822_size,k);      MM_LOG (tmp,WARN);    }  }  else {			/* document the problem */    LOCAL->buf[100] = '\0';	/* tie off buffer at no more than 100 octets */				/* or at newline, whichever is first */    if (s = strpbrk (LOCAL->buf,"\015\012")) *s = '\0';    sprintf (tmp,"Error reading mix message header, uid=%lx, s=%.0lx, h=%s",	     elt->private.uid,elt->rfc822_size,LOCAL->buf);    MM_LOG (tmp,ERROR);    *length = i = j = 0;	/* default to empty */  }  LOCAL->buf[j] = '\0';		/* tie off buffer at the end */

⌨️ 快捷键说明

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