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

📄 unixnt.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
  }}/* UNIX mail expunge mailbox * Accepts: MAIL stream *	    sequence to expunge if non-NIL *	    expunge options * Returns: T, always */long unix_expunge (MAILSTREAM *stream,char *sequence,long options){  long ret;  unsigned long i;  char lock[MAILTMPLEN];  char *msg = NIL;				/* parse and lock mailbox */  if (ret = (sequence ? ((options & EX_UID) ?			 mail_uid_sequence (stream,sequence) :			 mail_sequence (stream,sequence)) : LONGT) &&      LOCAL && (LOCAL->ld >= 0) && !stream->lock &&      unix_parse (stream,lock,LOCK_EX)) {				/* check expunged messages if not dirty */    for (i = 1; !LOCAL->dirty && (i <= stream->nmsgs); i++) {      MESSAGECACHE *elt = mail_elt (stream,i);      if (mail_elt (stream,i)->deleted) LOCAL->dirty = T;    }    if (!LOCAL->dirty) {	/* not dirty and no expunged messages */      unix_unlock (LOCAL->fd,stream,lock);      msg = "No messages deleted, so no update needed";    }    else if (unix_rewrite (stream,&i,lock,sequence ? LONGT : NIL)) {      if (i) sprintf (msg = LOCAL->buf,"Expunged %lu messages",i);      else msg = "Mailbox checkpointed, but no messages expunged";    }				/* rewrite failed */    else unix_unlock (LOCAL->fd,stream,lock);    mail_unlock (stream);	/* unlock the stream */    mm_nocritical (stream);	/* done with critical */    if (msg && !stream->silent) mm_log (msg,NIL);  }  else if (!stream->silent) mm_log("Expunge ignored on readonly mailbox",WARN);  return ret;}/* UNIX mail copy message(s) * Accepts: MAIL stream *	    sequence *	    destination mailbox *	    copy options * Returns: T if copy successful, else NIL */long unix_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options){  struct stat sbuf;  int fd;  char *s,file[MAILTMPLEN],lock[MAILTMPLEN];  struct utimbuf times;  unsigned long i,j;  MESSAGECACHE *elt;  long ret = T;  mailproxycopy_t pc =    (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL);  copyuid_t cu = (copyuid_t) (mail_parameters (NIL,GET_USERHASNOLIFE,NIL) ?			      NIL : mail_parameters (NIL,GET_COPYUID,NIL));  SEARCHSET *source = cu ? mail_newsearchset () : NIL;  SEARCHSET *dest = cu ? mail_newsearchset () : NIL;  MAILSTREAM *tstream = NIL;  if (!((options & CP_UID) ? mail_uid_sequence (stream,sequence) :	mail_sequence (stream,sequence))) return NIL;				/* make sure destination is valid */  if (!(unix_valid (mailbox) || !errno))    switch (errno) {    case ENOENT:			/* no such file? */      if (compare_cstring (mailbox,"INBOX")) {	mm_notify (stream,"[TRYCREATE] Must create mailbox before copy",NIL);	return NIL;      }      if (pc) return (*pc) (stream,sequence,mailbox,options);      unix_create (NIL,"INBOX");/* create empty INBOX */    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 UNIX-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 UNIX-format mailbox: %.80s",mailbox);      mm_log (LOCAL->buf,ERROR);      return NIL;    }				/* try to open rewrite for UIDPLUS */  if ((tstream = mail_open_work (&unixdriver,NIL,mailbox,				 OP_SILENT|OP_NOKOD)) && tstream->rdonly)    tstream = mail_close (tstream);  if (cu && !tstream) {		/* wanted a COPYUID? */    sprintf (LOCAL->buf,"Unable to write-open mailbox for COPYUID: %.80s",	     mailbox);    MM_LOG (LOCAL->buf,WARN);    cu = NIL;			/* don't try to do COPYUID */  }  LOCAL->buf[0] = '\0';  mm_critical (stream);		/* go critical */  if ((fd = unix_lock (dummy_file (file,mailbox),		       O_BINARY|O_WRONLY|O_APPEND|O_CREAT,S_IREAD|S_IWRITE,		       lock,LOCK_EX)) < 0) {    mm_nocritical (stream);	/* done with critical */    sprintf (LOCAL->buf,"Can't open destination mailbox: %s",strerror (errno));    mm_log (LOCAL->buf,ERROR);	/* log the error */    return NIL;			/* failed */  }  fstat (fd,&sbuf);		/* get current file size */				/* write all requested messages to mailbox */  for (i = 1; ret && (i <= stream->nmsgs); i++)    if ((elt = mail_elt (stream,i))->sequence) {      lseek (LOCAL->fd,elt->private.special.offset,L_SET);      read (LOCAL->fd,LOCAL->buf,elt->private.special.text.size);      if (LOCAL->buf[(j = elt->private.special.text.size) - 2] != '\r') {	LOCAL->buf[j - 1] = '\r';	LOCAL->buf[j++] = '\n';      }      if (write (fd,LOCAL->buf,j) < 0) ret = NIL;      else {			/* internal header succeeded */	s = unix_header (stream,i,&j,NIL);				/* header size, sans trailing newline */	if (j && (s[j - 4] == '\r')) j -= 2;	if (write (fd,s,j) < 0) ret = NIL;	else {			/* message header succeeded */	  j = tstream ?		/* write UIDPLUS data if have readwrite */	    unix_xstatus (stream,LOCAL->buf,elt,++(tstream->uid_last),LONGT) :	    unix_xstatus (stream,LOCAL->buf,elt,NIL,NIL);	  if (write (fd,LOCAL->buf,j) < 0) ret = NIL;	  else {		/* message status succeeded */	    s = unix_text_work (stream,elt,&j,NIL);	    if ((write (fd,s,j) < 0) || (write (fd,"\r\n",2) < 0))	      ret = NIL;	    else if (cu) {	/* need to pass back new UID? */	      mail_append_set (source,mail_uid (stream,i));	      mail_append_set (dest,tstream->uid_last);	    }	  }	}      }    }  if (!ret || fsync (fd)) {	/* force out the update */    sprintf (LOCAL->buf,"Message copy failed: %s",strerror (errno));    ftruncate (fd,sbuf.st_size);    ret = NIL;  }				/* force UIDVALIDITY assignment now */  if (tstream && !tstream->uid_validity)    tstream->uid_validity = (unsigned long) time (0);				/* return sets if doing COPYUID */  if (cu && ret) (*cu) (stream,mailbox,tstream->uid_validity,source,dest);  else {			/* flush any sets we may have built */    mail_free_searchset (&source);    mail_free_searchset (&dest);  }  times.modtime = time (0);	/* set mtime to now */				/* set atime to now-1 if successful copy */  if (ret) times.actime = times.modtime - 1;		  else times.actime =		/* else preserve \Marked status */	 ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ?	 sbuf.st_atime : times.modtime;  utime (file,&times);		/* set the times */  unix_unlock (fd,NIL,lock);	/* unlock and close mailbox */  if (tstream) {		/* update last UID if we can */    UNIXLOCAL * local = (UNIXLOCAL *) tstream->local;    local->dirty = T;		/* do a rewrite */    local->appending = T;	/* but not at the cost of marking as old */    tstream = mail_close (tstream);  }				/* log the error */  if (!ret) mm_log (LOCAL->buf,ERROR);				/* delete if requested message */  else if (options & CP_MOVE) for (i = 1; i <= stream->nmsgs; i++)    if ((elt = mail_elt (stream,i))->sequence)      elt->deleted = elt->private.dirty = LOCAL->dirty = T;  mm_nocritical (stream);	/* release critical */  return ret;}/* UNIX mail append message from stringstruct * Accepts: MAIL stream *	    destination mailbox *	    append callback *	    data for callback * Returns: T if append successful, else NIL */#define BUFLEN 8*MAILTMPLENlong unix_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){  struct stat sbuf;  int fd;  unsigned long i;  char *flags,*date,buf[BUFLEN],tmp[MAILTMPLEN],file[MAILTMPLEN],    lock[MAILTMPLEN];  struct utimbuf times;  FILE *sf,*df;  MESSAGECACHE elt;  STRING *message;  unsigned long uidlocation = 0;  appenduid_t au = (appenduid_t)    (mail_parameters (NIL,GET_USERHASNOLIFE,NIL) ? NIL :     mail_parameters (NIL,GET_APPENDUID,NIL));  SEARCHSET *dst = au ? mail_newsearchset () : NIL;  long ret = LONGT;  MAILSTREAM *tstream = NIL;  if (!stream) {		/* stream specified? */    stream = &unixproto;	/* no, default stream to prototype */    for (i = 0; i < NUSERFLAGS && stream->user_flags[i]; ++i)      fs_give ((void **) &stream->user_flags[i]);  }  if (!unix_valid (mailbox)) switch (errno) {  case ENOENT:			/* no such file? */    if (!compare_cstring (mailbox,"INBOX")) {      mm_notify (stream,"[TRYCREATE] Must create mailbox before append",NIL);      return NIL;    }    unix_create (NIL,"INBOX");	/* create empty INBOX */  case 0:			/* merely empty file? */    tstream = stream;    break;  case EACCES:			/* file protected */    sprintf (tmp,"Can't access destination: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  case EINVAL:    sprintf (tmp,"Invalid UNIX-format mailbox name: %.80s",mailbox);    mm_log (tmp,ERROR);    return NIL;  default:    sprintf (tmp,"Not a UNIX-format mailbox: %.80s",mailbox);    mm_log (tmp,ERROR);    return NIL;  }				/* get sniffing stream for keywords */  else if (!(tstream = mail_open (NIL,mailbox,				  OP_READONLY|OP_SILENT|OP_NOKOD|OP_SNIFF))) {    sprintf (tmp,"Unable to examine mailbox for APPEND: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  }				/* get first message */  if (!(*af) (tstream,data,&flags,&date,&message)) return NIL;  if (!(sf = tmpfile ())) {	/* must have scratch file */    sprintf (tmp,".%lx.%lx",(unsigned long) time (0),(unsigned long)getpid ());    if (!stat (tmp,&sbuf) || !(sf = fopen (tmp,"wb+"))) {      sprintf (tmp,"Unable to create scratch file: %.80s",strerror (errno));      mm_log (tmp,ERROR);      return NIL;    }    unlink (tmp);  }  do {				/* parse date */    if (!date) rfc822_date (date = tmp);    if (!mail_parse_date (&elt,date)) {      sprintf (tmp,"Bad date in append: %.80s",date);      mm_log (tmp,ERROR);    }    else {			/* user wants to suppress time zones? */      if (mail_parameters (NIL,GET_NOTIMEZONES,NIL)) {	time_t when = mail_longdate (&elt);	date = ctime (&when);	/* use traditional date */      }				/* use POSIX-style date */      else date = mail_cdate (tmp,&elt);      if (!SIZE (message)) mm_log ("Append of zero-length message",ERROR);      else if (!unix_collect_msg (tstream,sf,flags,date,message)) {	sprintf (tmp,"Error writing scratch file: %.80s",strerror (errno));	mm_log (tmp,ERROR);      }				/* get next message */      else if ((*af) (tstream,data,&flags,&date,&message)) continue;    }    fclose (sf);		/* punt scratch file */    return NIL;			/* give up */  } while (message);		/* until no more messages */  if (fflush (sf)) {    sprintf (tmp,"Error finishing scratch file: %.80s",strerror (errno));    mm_log (tmp,ERROR);    fclose (sf);		/* punt scratch file */    return NIL;			/* give up */  }  i = ftell (sf);		/* size of scratch file */				/* close sniffing stream */  if (tstream != stream) tstream = mail_close (tstream);  mm_critical (stream);		/* go critical */				/* try to open readwrite for UIDPLUS */  if ((tstream = mail_open_work (&unixdriver,NIL,mailbox,				 OP_SILENT|OP_NOKOD)) && tstream->rdonly)    tstream = mail_close (tstream);  if (au && !tstream) {		/* wanted an APPENDUID? */    sprintf (tmp,"Unable to re-open mailbox for APPENDUID: %.80s",mailbox);    MM_LOG (tmp,WARN);    au = NIL;  }  if (((fd = unix_lock (dummy_file (file,mailbox),			O_BINARY|O_WRONLY|O_APPEND|O_CREAT,S_IREAD|S_IWRITE,			lock,LOCK_EX)) < 0) || !(df = fdopen (fd,"ab"))) {    mm_nocritical (stream);	/* done with critical */    sprintf (tmp,"Can't open append mailbox: %s",strerror (errno));    mm_log (tmp,ERROR);    return NIL;  }  fstat (fd,&sbuf);		/* get current file size */  rewind (sf);  times.modtime = time (0);	/* set mtime to now */				/* write all messages */  if (!unix_append_msgs (tstream,sf,df,au ? dst : NIL) ||      (fflush (df) == EOF) || fsync (fd)) {    sprintf (buf,"Message append failed: %s",strerror (errno));    mm_log (buf,ERROR);    ftruncate (fd,sbuf.st_size);/* revert file */    times.actime =		/* preserve \Marked status */      ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ?      sbuf.st_atime : times.modtime;    ret = NIL;			/* return error */  }				/* set atime to now-1 if successful copy */  else times.actime = times.modtime - 1;  utime (file,&times);		/* set the times */  fclose (sf);			/* done with scratch file */				/* force UIDVALIDITY assignment now */  if (tstream && !tstream->uid_validity)    tstream->uid_validity = (unsigned long) time (0);				/* return sets if doing APPENDUID */  if (au && ret) (*au) (mailbox,tstream->uid_validity,dst);  else mail_free_searchset (&dst);  flock (fd,LOCK_UN);		/* unlock mailbox (can't use unix_unlock() */  if (lock && *lock) unlink (lock);  fclose (df);			/* close mailbox */  if (tstream) {		/* update last UID if we can */    UNIXLOCAL * local = (UNIXLOCAL *) tstream->local;    local->dirty = T;		/* do a rewrite */    local->appending = T;	/* but not at the cost of marking as old */    tstream = mail_close (tstream);  }  mm_nocritical (stream);	/* release critical */  return ret;}/* Collect and write single message to append scratch file * Accepts: MAIL stream *	    scratch file *	    flags *	    date *	    message stringstruct * Returns: NIL if write error, else T */int unix_collect_msg (MAILSTREAM *stream,FILE *sf,char *flags,char *date,		     STRING *msg){  unsigned char *s,*t;  unsigned long uf;  long f = mail_parse_flags (stream,flags,&uf);				/* write metadata */  if (fprintf (sf,"%ld %lu ",f,SIZE (msg) + 2) < 0) return NIL;  for (s = date; *s; *s++) switch (*s) {  default:    if (putc (*s,sf) == EOF) return NIL;  case '\r': case '\n':

⌨️ 快捷键说明

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