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

📄 unix.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (((fd = unix_lock (dummy_file (file,mailbox),O_WRONLY|O_APPEND,		       (long) mail_parameters (NIL,GET_MBXPROTECTION,NIL),			&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);  tp[1] = 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);    tp[0] =			/* preserve \Marked status */      ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ?      sbuf.st_atime : tp[1];    ret = NIL;			/* return error */  }  else tp[0] = tp[1] - 1;	/* set atime to now-1 if successful copy */  utime (file,tp);		/* set the times */  fclose (sf);			/* done with scratch file */				/* force UIDVALIDITY assignment now */  if (tstream && !tstream->uid_validity) tstream->uid_validity = time (0);				/* return sets if doing APPENDUID */  if (au && ret) (*au) (mailbox,tstream->uid_validity,dst);  else mail_free_searchset (&dst);  unix_unlock (fd,NIL,&lock);	/* unlock and close mailbox */  fclose (df);			/* note that unix_unlock() released the fd */  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, note date ends with NL */  if (fprintf (sf,"%ld %lu %s",f,SIZE (msg) + 1,date) < 0) return NIL;  while (uf)			/* write user flags */        if ((s = stream->user_flags[find_rightmost_bit (&uf)]) &&	(fprintf (sf," %s",s) < 0)) return NIL;  if (putc ('\n',sf) == EOF) return NIL;  while (SIZE (msg)) {		/* copy text to scratch file */    for (s = (unsigned char *) msg->curpos, t = s + msg->cursize; s < t; ++s)      if (!*s) *s = 0x80;	/* disallow NUL */				/* write buffered text */    if (fwrite (msg->curpos,1,msg->cursize,sf) == msg->cursize)      SETPOS (msg,GETPOS (msg) + msg->cursize);    else return NIL;		/* failed */  }				/* write trailing newline and return */  return (putc ('\n',sf) == EOF) ? NIL : T;}/* Append messages from scratch file to mailbox * Accepts: MAIL stream *	    source file *	    destination file *	    uidset to update if non-NIL * Returns: T if success, NIL if failure */int unix_append_msgs (MAILSTREAM *stream,FILE *sf,FILE *df,SEARCHSET *set){  int ti,zn,c;  long f;  unsigned long i,j;  char *x,tmp[MAILTMPLEN];  int hdrp = T;				/* get message metadata line */  while (fgets (tmp,MAILTMPLEN,sf)) {    if (!(isdigit (tmp[0]) && strchr (tmp,'\n'))) return NIL;    f = strtol (tmp,&x,10);	/* get flags */    if (!((*x++ == ' ') && isdigit (*x))) return NIL;    i = strtoul (x,&x,10);	/* get message size */    if ((*x++ != ' ') ||	/* build initial header */	(fprintf (df,"From %s@%s %sStatus: ",myusername(),mylocalhost(),x)<0)||	(f&fSEEN && (putc ('R',df) == EOF)) ||	(fputs ("\nX-Status: ",df) == EOF) ||	(f&fDELETED && (putc ('D',df) == EOF)) ||	(f&fFLAGGED && (putc ('F',df) == EOF)) ||	(f&fANSWERED && (putc ('A',df) == EOF)) ||	(f&fDRAFT && (putc ('T',df) == EOF)) ||	(fputs ("\nX-Keywords:",df) == EOF)) return NIL;				/* copy keywords */    while ((c = getc (sf)) != '\n') switch (c) {    case EOF:      return NIL;    default:      if (putc (c,df) == EOF) return NIL;    }    if ((putc ('\n',df) == EOF) ||	(set && (fprintf (df,"X-UID: %lu\n",++(stream->uid_last)) < 0)))      return NIL;    for (c = '\n'; i && fgets (tmp,MAILTMPLEN,sf); c = tmp[j-1]) {				/* get read line length */      if (i < (j = strlen (tmp))) fatal ("unix_append_msgs overrun");      i -= j;			/* number of bytes left */				/* squish out CRs (note also copies NUL) */      for (x = tmp; x = strchr (x,'\r'); --j) memmove (x,x+1,j-(x-tmp));      if (!j) continue;		/* do nothing if line emptied */				/* start of line? */      if ((c == '\n')) switch (tmp[0]) {      case 'F':			/* possible "From " (case counts here) */	if ((j > 4) && (tmp[0] == 'F') && (tmp[1] == 'r') && (tmp[2] == 'o') &&	    (tmp[3] == 'm') && (tmp[4] == ' ')) {	  if (!unix_fromwidget) {	    VALID (tmp,x,ti,zn);/* conditional, only write widget if */	    if (!ti) break;	/*  it looks like a valid header */	  }			/* write the widget */	  if (putc ('>',df) == EOF) return NIL;	}	break;      case 'S': case 's':	/* possible "Status:" */	if (hdrp && (j > 6) && ((tmp[1] == 't') || (tmp[1] == 'T')) &&	    ((tmp[2] == 'a') || (tmp[2] == 'A')) &&	    ((tmp[3] == 't') || (tmp[3] == 'T')) &&	    ((tmp[4] == 'u') || (tmp[4] == 'U')) &&	    ((tmp[5] == 's') || (tmp[5] == 'S')) && (tmp[6] == ':') &&	    (fputs ("X-Original-",df) == EOF)) return NIL;	break;      case 'X': case 'x':	/* possible X-??? header */	if (hdrp && (tmp[1] == '-') &&				/* possible X-UID: */	    (((j > 5) && ((tmp[2] == 'U') || (tmp[2] == 'u')) &&	      ((tmp[3] == 'I') || (tmp[3] == 'i')) &&	      ((tmp[4] == 'D') || (tmp[4] == 'd')) && (tmp[5] == ':')) ||				/* possible X-IMAP: */	     ((j > 6) && ((tmp[2] == 'I') || (tmp[2] == 'i')) &&	      ((tmp[3] == 'M') || (tmp[3] == 'm')) &&	      ((tmp[4] == 'A') || (tmp[4] == 'a')) &&	      ((tmp[5] == 'P') || (tmp[5] == 'p')) &&	      ((tmp[6] == ':') ||				/* or X-IMAPbase: */	       ((j > 10) && ((tmp[6] == 'b') || (tmp[6] == 'B')) &&		((tmp[7] == 'a') || (tmp[7] == 'A')) &&		((tmp[8] == 's') || (tmp[8] == 'S')) &&		((tmp[9] == 'e') || (tmp[9] == 'E')) && (tmp[10] == ':')))) ||				/* possible X-Status: */	     ((j > 8) && ((tmp[2] == 'S') || (tmp[2] == 's')) &&	      ((tmp[3] == 't') || (tmp[3] == 'T')) &&	      ((tmp[4] == 'a') || (tmp[4] == 'A')) &&	      ((tmp[5] == 't') || (tmp[5] == 'T')) &&	      ((tmp[6] == 'u') || (tmp[6] == 'U')) &&	      ((tmp[7] == 's') || (tmp[7] == 'S')) && (tmp[8] == ':')) ||				/* possible X-Keywords: */	     ((j > 10) && ((tmp[2] == 'K') || (tmp[2] == 'k')) &&	      ((tmp[3] == 'e') || (tmp[3] == 'E')) &&	      ((tmp[4] == 'y') || (tmp[4] == 'Y')) &&	      ((tmp[5] == 'w') || (tmp[5] == 'W')) &&	      ((tmp[6] == 'o') || (tmp[6] == 'O')) &&	      ((tmp[7] == 'r') || (tmp[7] == 'R')) &&	      ((tmp[8] == 'd') || (tmp[8] == 'D')) &&	      ((tmp[9] == 's') || (tmp[9] == 'S')) && (tmp[10] == ':'))) &&	    (fputs ("X-Original-",df) == EOF)) return NIL;      case '\n':		/* blank line */	hdrp = NIL;	break;      default:			/* nothing to do */	break;      }				/* just write the line */      if (fwrite (tmp,1,j,df) != j) return NIL;    }    if (i) return NIL;		/* didn't read entire message */				/* update set */    if (stream) mail_append_set (set,stream->uid_last);  }  return T;}/* Internal routines *//* UNIX mail abort stream * Accepts: MAIL stream */void unix_abort (MAILSTREAM *stream){  if (LOCAL) {			/* only if a file is open */    if (LOCAL->fd >= 0) close (LOCAL->fd);    if (LOCAL->ld >= 0) {	/* have a mailbox lock? */      flock (LOCAL->ld,LOCK_UN);/* yes, release the lock */      close (LOCAL->ld);	/* close the lock file */      unlink (LOCAL->lname);	/* and delete it */    }    if (LOCAL->lname) fs_give ((void **) &LOCAL->lname);				/* free local text buffers */    if (LOCAL->buf) fs_give ((void **) &LOCAL->buf);    if (LOCAL->text.data) fs_give ((void **) &LOCAL->text.data);    if (LOCAL->linebuf) fs_give ((void **) &LOCAL->linebuf);    if (LOCAL->line) fs_give ((void **) &LOCAL->line);				/* nuke the local data */    fs_give ((void **) &stream->local);    stream->dtb = NIL;		/* log out the DTB */  }}/* UNIX open and lock mailbox * Accepts: file name to open/lock *	    file open mode *	    destination buffer for lock file name *	    type of locking operation (LOCK_SH or LOCK_EX) */int unix_lock (char *file,int flags,int mode,DOTLOCK *lock,int op){  int fd;  blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);  (*bn) (BLOCK_FILELOCK,NIL);				/* try locking the easy way */  if (dotlock_lock (file,lock,-1)) {				/* got dotlock file, easy open */    if ((fd = open (file,flags,mode)) >= 0) flock (fd,op);    else dotlock_unlock (lock);	/* open failed, free the dotlock */  }				/* no dot lock file, open file now */  else if ((fd = open (file,flags,mode)) >= 0) {				/* try paranoid way to make a dot lock file */    if (dotlock_lock (file,lock,fd)) {      close (fd);		/* get fresh fd in case of timing race */      if ((fd = open (file,flags,mode)) >= 0) flock (fd,op);				/* open failed, free the dotlock */      else dotlock_unlock (lock);    }    else flock (fd,op);		/* paranoid way failed, just flock() it */  }  (*bn) (BLOCK_NONE,NIL);  return fd;}/* UNIX unlock and close mailbox * Accepts: file descriptor *	    (optional) mailbox stream to check atime/mtime *	    (optional) lock file name */void unix_unlock (int fd,MAILSTREAM *stream,DOTLOCK *lock){  if (stream) {			/* need to muck with times? */    struct stat sbuf;    time_t tp[2];    time_t now = time (0);    fstat (fd,&sbuf);		/* get file times */    if (LOCAL->ld >= 0) {	/* yes, readwrite session? */      tp[0] = now;		/* set atime to now */				/* set mtime to (now - 1) if necessary */      tp[1] = (now > sbuf.st_mtime) ? sbuf.st_mtime : now - 1;    }    else if (stream->recent) {	/* readonly with recent messages */      if ((sbuf.st_atime >= sbuf.st_mtime) ||	  (sbuf.st_atime >= sbuf.st_ctime))				/* keep past mtime, whack back atime */	tp[0] = (tp[1] = (sbuf.st_mtime < now) ? sbuf.st_mtime : now) - 1;      else now = 0;		/* no time change needed */    }				/* readonly with no recent messages */    else if ((sbuf.st_atime < sbuf.st_mtime) ||	     (sbuf.st_atime < sbuf.st_ctime)) {      tp[0] = now;		/* set atime to now */				/* set mtime to (now - 1) if necessary */      tp[1] = (now > sbuf.st_mtime) ? sbuf.st_mtime : now - 1;    }    else now = 0;		/* no time change needed */				/* set the times, note change */    if (now && !utime (stream->mailbox,tp)) LOCAL->filetime = tp[1];  }  flock (fd,LOCK_UN);		/* release flock'ers */  if (!stream) close (fd);	/* close the file if no stream */  dotlock_unlock (lock);	/* flush the lock file if any */}/* UNIX mail parse and lock mailbox * Accepts: MAIL stream *	    space to write lock file name *	    type of locking operation * Returns: T if parse OK, critical & mailbox is locked shared; NIL if failure */int unix_parse (MAILSTREAM *stream,DOTLOCK *lock,int op){  int zn;  unsigned long i,j,k,m;  unsigned char c,*s,*t,*u,tmp[MAILTMPLEN],date[30];  int ti = 0,retain = T;  unsigned long nmsgs = stream->nmsgs;  unsigned long prevuid = nmsgs ? mail_elt (stream,nmsgs)->private.uid : 0;  unsigned long recent = stream->recent;  unsigned long oldnmsgs = stream->nmsgs;  short silent = stream->silent;  short pseudoseen = NIL;  struct stat sbuf;  STRING bs;  FDDATA d;  MESSAGECACHE *elt;  mail_lock (stream);		/* guard against recursion or pingers */				/* toss out previous descriptor */  if (LOCAL->fd >= 0) close (LOCAL->fd);  MM_CRITICAL (stream);		/* open and lock mailbox (shared OK) */  if ((LOCAL->fd = unix_lock (stream->mailbox,(LOCAL->ld >= 0) ?			      O_RDWR : O_RDONLY,			      (long)mail_parameters(NIL,GET_MBXPROTECTION,NIL),			      lock,op)) < 0) {    sprintf (tmp,"Mailbox open failed, aborted: %s",strerror (errno));    MM_LOG (tmp,ERROR);    unix_abort (stream);    mail_unlock (stream);    MM_NOCRITICAL (stream);	/* done with critical */    return NIL;  }  fstat (LOCAL->fd,&sbuf);	/* get status */				/* validate change in size */  if (sbuf.st_size < LOCAL->filesize) {    sprintf (tmp,"Mailbox shrank from %lu to %lu bytes, aborted",	     (unsigned long) LOCAL->filesize,(unsigned long) sbuf.st_size);    MM_LOG (tmp,ERROR);		/* this is pretty bad */    unix_unlock (LOCAL->fd,stream,lock);    unix_abort (stream);    mail_unlock (stream);    MM_NOCRITICAL (stream);	/* done with critical */    return NIL;  }				/* new data? */  else if (i = sbuf.st_size - LOCAL->filesize) {    d.fd = LOCAL->fd;		/* yes, set up file descriptor */    d.pos = LOCAL->filesize;	/* get to that position in the file */    d.chunk = LOCAL->buf;	/* initial buffer chunk */    d.chunksize = CHUNKSIZE;	/* file chunk size */    INIT (&bs,fd_string,&d,i);	/* initialize stringstruct */				/* skip leading whitespace for broken MTAs */    while (((c = CHR (&bs)) == '\n') || (c == '\r') ||	   (c == ' ') || (c == '\t')) SNX (&bs);    if (SIZE (&bs)) {		/* read new data */				/* remember internal header position */      j = LOCAL->filesize + GETPOS (&bs);      s = unix_mbxline (stream,&bs,&i);      t = NIL,zn = 0;      if (i) VALID (s,t,ti,zn);	/* see if valid From line */      if (!ti) {		/* someone pulled the rug from under us */	sprintf (tmp,"Unexpected changes to mailbox (try restarting): %.20s",		 (char *) s);	MM_LOG (tmp,ERROR);	unix_unlock (LOCAL->fd,stream,lock);	unix_abort (stream);	mail_unlock (stream);				/* done with critical */	MM_NOCRITICAL (stream);	return NIL;      }      stream->silent = T;	/* quell main program new message events */      do {			/* found a message */				/* instantiate first new message */	mail_exists (stream,++nmsgs);

⌨️ 快捷键说明

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