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

📄 unix.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
				/* only after finishing */  if (elt->valid) elt->private.dirty = LOCAL->dirty = T;}/* UNIX mail ping mailbox * Accepts: MAIL stream * Returns: T if stream alive, else NIL */long unix_ping (MAILSTREAM *stream){  DOTLOCK lock;  struct stat sbuf;  long reparse;				/* big no-op if not readwrite */  if (LOCAL && (LOCAL->ld >= 0) && !stream->lock) {    if (stream->rdonly) {	/* does he want to give up readwrite? */				/* checkpoint if we changed something */      if (LOCAL->dirty) unix_check (stream);      flock (LOCAL->ld,LOCK_UN);/* release readwrite lock */      close (LOCAL->ld);	/* close the readwrite lock file */      LOCAL->ld = -1;		/* no more readwrite lock fd */      unlink (LOCAL->lname);	/* delete the readwrite lock file */    }    else {			/* see if need to reparse */      if (!(reparse = (long) mail_parameters (NIL,GET_NETFSSTATBUG,NIL))) {				/* get current mailbox size */	if (LOCAL->fd >= 0) fstat (LOCAL->fd,&sbuf);	else if (stat (stream->mailbox,&sbuf)) {	  sprintf (LOCAL->buf,"Mailbox stat failed, aborted: %s",		   strerror (errno));	  MM_LOG (LOCAL->buf,ERROR);	  unix_abort (stream);	  return NIL;	}	reparse = (sbuf.st_size != LOCAL->filesize);      }				/* parse if mailbox changed */      if ((LOCAL->ddirty || reparse) && unix_parse (stream,&lock,LOCK_EX)) {				/* force checkpoint if double-dirty */	if (LOCAL->ddirty) unix_rewrite (stream,NIL,&lock,NIL);				/* unlock mailbox */	else unix_unlock (LOCAL->fd,stream,&lock);	mail_unlock (stream);	/* and stream */	MM_NOCRITICAL (stream);	/* done with critical */      }    }  }  return LOCAL ? LONGT : NIL;	/* return if still alive */}/* UNIX mail check mailbox * Accepts: MAIL stream */void unix_check (MAILSTREAM *stream){  DOTLOCK lock;				/* parse and lock mailbox */  if (LOCAL && (LOCAL->ld >= 0) && !stream->lock &&      unix_parse (stream,&lock,LOCK_EX)) {				/* any unsaved changes? */    if (LOCAL->dirty && unix_rewrite (stream,NIL,&lock,NIL)) {      if (!stream->silent) MM_LOG ("Checkpoint completed",NIL);    }				/* no checkpoint needed, just unlock */    else unix_unlock (LOCAL->fd,stream,&lock);    mail_unlock (stream);	/* unlock the stream */    MM_NOCRITICAL (stream);	/* done with critical */  }}/* 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;  DOTLOCK lock;  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];  DOTLOCK lock;  time_t tp[2];  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;  DRIVER *d;  for (d = (DRIVER *) mail_parameters (NIL,GET_DRIVERS,NIL);       (d && strcmp (d->name,"mbox") && !(d->flags & DR_DISABLE));       d = d->next);		/* see if mbox driver active */  if (!((options & CP_UID) ? mail_uid_sequence (stream,sequence) :	mail_sequence (stream,sequence))) return NIL;				/* make sure destination is valid */  if (!((d && mbox_valid (mailbox) && (mailbox = "mbox")) ||	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_WRONLY|O_APPEND,		       (long) mail_parameters (NIL,GET_MBXPROTECTION,NIL),		       &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 (write (fd,LOCAL->buf,elt->private.special.text.size) < 0) ret = NIL;      else {			/* internal header succeeded */	s = unix_header (stream,i,&j,FT_INTERNAL);				/* header size, sans trailing newline */	if (j && (s[j - 2] == '\n')) j--;	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,FT_INTERNAL);	    if ((write (fd,s,j) < 0) || (write (fd,"\n",1) < 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 = 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);  }  tp[1] = time (0);		/* set mtime to now */  if (ret) tp[0] = tp[1] - 1;	/* set atime to now-1 if successful copy */  else tp[0] =			/* else preserve \Marked status */	 ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ?	 sbuf.st_atime : tp[1];  utime (file,tp);		/* 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];  time_t tp[2];  FILE *sf,*df;  MESSAGECACHE elt;  DOTLOCK lock;  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 (!MM_APPEND (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 (MM_APPEND (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;  }

⌨️ 快捷键说明

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