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

📄 unix.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* UNIX mail rename mailbox * Accepts: MAIL stream *	    old mailbox name *	    new mailbox name (or NIL for delete) * Returns: T on success, NIL on failure */long unix_rename (MAILSTREAM *stream,char *old,char *newname){  long ret = NIL;  char c,*s = NIL;  char tmp[MAILTMPLEN],file[MAILTMPLEN],lock[MAILTMPLEN];  DOTLOCK lockx;  int fd,ld;  long i;  struct stat sbuf;  MM_CRITICAL (stream);		/* get the c-client lock */  if (!dummy_file (file,old) ||      (newname && (!((s = mailboxfile (tmp,newname)) && *s) ||		   ((s = strrchr (tmp,'/')) && !s[1]))))    sprintf (tmp,newname ?	     "Can't rename mailbox %.80s to %.80s: invalid name" :	     "Can't delete mailbox %.80s: invalid name",	     old,newname);				/* lock out other c-clients */  else if ((ld = lockname (lock,file,LOCK_EX|LOCK_NB,&i)) < 0)    sprintf (tmp,"Mailbox %.80s is in use by another process",old);  else {    if ((fd = unix_lock (file,O_RDWR,			 (long) mail_parameters (NIL,GET_MBXPROTECTION,NIL),			 &lockx,LOCK_EX)) < 0)      sprintf (tmp,"Can't lock mailbox %.80s: %s",old,strerror (errno));    else {      if (newname) {		/* want rename? */				/* found superior to destination name? */	if (s = strrchr (s,'/')) {	  c = *++s;		/* remember first character of inferior */	  *s = '\0';		/* tie off to get just superior */				/* name doesn't exist, create it */	  if ((stat (tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) &&	      !dummy_create_path (stream,tmp,get_dir_protection (newname))) {	    unix_unlock (fd,NIL,&lockx);	    unix_unlock (ld,NIL,NIL);	    unlink (lock);	    MM_NOCRITICAL (stream);	    return ret;		/* return success or failure */	  }	  *s = c;		/* restore full name */	}	if (rename (file,tmp))	  sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %s",old,newname,		   strerror (errno));	else ret = T;		/* set success */      }      else if (unlink (file))	sprintf (tmp,"Can't delete mailbox %.80s: %s",old,strerror (errno));      else ret = T;		/* set success */      unix_unlock (fd,NIL,&lockx);    }    unix_unlock (ld,NIL,NIL);	/* flush the lock */    unlink (lock);  }  MM_NOCRITICAL (stream);	/* no longer critical */  if (!ret) MM_LOG (tmp,ERROR);	/* log error */  return ret;			/* return success or failure */}/* UNIX mail open * Accepts: Stream to open * Returns: Stream on success, NIL on failure */MAILSTREAM *unix_open (MAILSTREAM *stream){  long i;  int fd;  char tmp[MAILTMPLEN];  DOTLOCK lock;  long retry;				/* return prototype for OP_PROTOTYPE call */  if (!stream) return user_flags (&unixproto);  retry = stream->silent ? 1 : KODRETRY;  if (stream->local) fatal ("unix recycle stream");  stream->local = memset (fs_get (sizeof (UNIXLOCAL)),0,sizeof (UNIXLOCAL));				/* note if an INBOX or not */  stream->inbox = !compare_cstring (stream->mailbox,"INBOX");				/* canonicalize the stream mailbox name */  if (!dummy_file (tmp,stream->mailbox)) {    sprintf (tmp,"Can't open - invalid name: %.80s",stream->mailbox);    MM_LOG (tmp,ERROR);    return NIL;  }				/* flush old name */  fs_give ((void **) &stream->mailbox);				/* save canonical name */  stream->mailbox = cpystr (tmp);  LOCAL->fd = LOCAL->ld = -1;	/* no file or state locking yet */  LOCAL->buf = (char *) fs_get (CHUNKSIZE);  LOCAL->buflen = CHUNKSIZE - 1;  LOCAL->text.data = (unsigned char *) fs_get (CHUNKSIZE);  LOCAL->text.size = CHUNKSIZE - 1;  LOCAL->linebuf = (char *) fs_get (CHUNKSIZE);  LOCAL->linebuflen = CHUNKSIZE - 1;  stream->sequence++;		/* bump sequence number */				/* make lock for read/write access */  if (!stream->rdonly) while (retry) {				/* try to lock file */    if ((fd = lockname (tmp,stream->mailbox,LOCK_EX|LOCK_NB,&i)) < 0) {				/* suppressing kiss-of-death? */      if (stream->nokod) retry = 0;				/* no, first time through? */      else if (retry-- == KODRETRY) {				/* learned other guy's PID and can signal? */	if (i && !kill ((int) i,SIGUSR2)) {	  sprintf (tmp,"Trying to get mailbox lock from process %ld",i);	  MM_LOG (tmp,WARN);	}	else retry = 0;		/* give up */      }      if (!stream->silent) {	/* nothing if silent stream */	if (retry) sleep (1);	/* wait a second before trying again */	else MM_LOG ("Mailbox is open by another process, access is readonly",		     WARN);      }    }    else {			/* got the lock, nobody else can alter state */      LOCAL->ld = fd;		/* note lock's fd and name */      LOCAL->lname = cpystr (tmp);				/* make sure mode OK (don't use fchmod()) */      chmod (LOCAL->lname,(long) mail_parameters (NIL,GET_LOCKPROTECTION,NIL));      if (stream->silent) i = 0;/* silent streams won't accept KOD */      else {			/* note our PID in the lock */	sprintf (tmp,"%d",getpid ());	write (fd,tmp,(i = strlen (tmp))+1);      }      ftruncate (fd,i);		/* make sure tied off */      fsync (fd);		/* make sure it's available */      retry = 0;		/* no more need to try */    }  }				/* parse mailbox */  stream->nmsgs = stream->recent = 0;				/* will we be able to get write access? */  if ((LOCAL->ld >= 0) && access (stream->mailbox,W_OK) && (errno == EACCES)) {    MM_LOG ("Can't get write access to mailbox, access is readonly",WARN);    flock (LOCAL->ld,LOCK_UN);	/* release the lock */    close (LOCAL->ld);		/* close the lock file */    LOCAL->ld = -1;		/* no more lock fd */    unlink (LOCAL->lname);	/* delete it */  }				/* reset UID validity */  stream->uid_validity = stream->uid_last = 0;  if (stream->silent && !stream->rdonly && (LOCAL->ld < 0))    unix_abort (stream);	/* abort if can't get RW silent stream */				/* parse mailbox */  else if (unix_parse (stream,&lock,LOCK_SH)) {    unix_unlock (LOCAL->fd,stream,&lock);    mail_unlock (stream);    MM_NOCRITICAL (stream);	/* done with critical */  }  if (!LOCAL) return NIL;	/* failure if stream died */				/* make sure upper level knows readonly */  stream->rdonly = (LOCAL->ld < 0);				/* notify about empty mailbox */  if (!(stream->nmsgs || stream->silent)) MM_LOG ("Mailbox is empty",NIL);  if (!stream->rdonly) {	/* flags stick if readwrite */    stream->perm_seen = stream->perm_deleted =      stream->perm_flagged = stream->perm_answered = stream->perm_draft = T;    if (!stream->uid_nosticky) {/* users with lives get permanent keywords */      stream->perm_user_flags = 0xffffffff;				/* and maybe can create them too! */      stream->kwd_create = stream->user_flags[NUSERFLAGS-1] ? NIL : T;    }  }  return stream;		/* return stream alive to caller */}/* UNIX mail close * Accepts: MAIL stream *	    close options */void unix_close (MAILSTREAM *stream,long options){  int silent = stream->silent;  stream->silent = T;		/* go silent */				/* expunge if requested */  if (options & CL_EXPUNGE) unix_expunge (stream,NIL,NIL);				/* else dump final checkpoint */  else if (LOCAL->dirty) unix_check (stream);  stream->silent = silent;	/* restore old silence state */  unix_abort (stream);		/* now punt the file and local data */}/* UNIX mail fetch message header * Accepts: MAIL stream *	    message # to fetch *	    pointer to returned header text length *	    option flags * Returns: message header in RFC822 format */				/* lines to filter from header */static STRINGLIST *unix_hlines = NIL;char *unix_header (MAILSTREAM *stream,unsigned long msgno,		   unsigned long *length,long flags){  MESSAGECACHE *elt;  unsigned char *s,*t,*tl;  *length = 0;			/* default to empty */  if (flags & FT_UID) return "";/* UID call "impossible" */  elt = mail_elt (stream,msgno);/* get cache */  if (!unix_hlines) {		/* once only code */    STRINGLIST *lines = unix_hlines = mail_newstringlist ();    lines->text.size = strlen ((char *) (lines->text.data =					 (unsigned char *) "Status"));    lines = lines->next = mail_newstringlist ();    lines->text.size = strlen ((char *) (lines->text.data =					 (unsigned char *) "X-Status"));    lines = lines->next = mail_newstringlist ();    lines->text.size = strlen ((char *) (lines->text.data =					 (unsigned char *) "X-Keywords"));    lines = lines->next = mail_newstringlist ();    lines->text.size = strlen ((char *) (lines->text.data =					 (unsigned char *) "X-UID"));    lines = lines->next = mail_newstringlist ();    lines->text.size = strlen ((char *) (lines->text.data =					 (unsigned char *) "X-IMAP"));    lines = lines->next = mail_newstringlist ();    lines->text.size = strlen ((char *) (lines->text.data =					 (unsigned char *) "X-IMAPbase"));  }				/* go to header position */  lseek (LOCAL->fd,elt->private.special.offset +	 elt->private.msg.header.offset,L_SET);  if (flags & FT_INTERNAL) {	/* initial data OK? */    if (elt->private.msg.header.text.size > LOCAL->buflen) {      fs_give ((void **) &LOCAL->buf);      LOCAL->buf = (char *) fs_get ((LOCAL->buflen =				     elt->private.msg.header.text.size) + 1);    }				/* read message */    read (LOCAL->fd,LOCAL->buf,elt->private.msg.header.text.size);				/* got text, tie off string */    LOCAL->buf[*length = elt->private.msg.header.text.size] = '\0';				/* squeeze out CRs (in case from PC) */    for (s = t = LOCAL->buf,tl = LOCAL->buf + *length; t < tl; t++)      if (*t != '\r') *s++ = *t;    *s = '\0';    *length = s - LOCAL->buf;	/* adjust length */  }  else {			/* need to make a CRLF version */    read (LOCAL->fd,s = (char *) fs_get (elt->private.msg.header.text.size+1),	  elt->private.msg.header.text.size);				/* tie off string, and convert to CRLF */    s[elt->private.msg.header.text.size] = '\0';    *length = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen,s,			  elt->private.msg.header.text.size);    fs_give ((void **) &s);	/* free readin buffer */				/* squeeze out spurious CRs */    for (s = t = LOCAL->buf,tl = LOCAL->buf + *length; t < tl; t++)      if ((*t != '\r') || (t[1] == '\n')) *s++ = *t;    *s = '\0';    *length = s - LOCAL->buf;	/* adjust length */  }  *length = mail_filter (LOCAL->buf,*length,unix_hlines,FT_NOT);  return (char *) LOCAL->buf;	/* return processed copy */}/* UNIX mail fetch message text * Accepts: MAIL stream *	    message # to fetch *	    pointer to returned stringstruct *	    option flags * Returns: T on success, NIL if failure */long unix_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags){  char *s;  unsigned long i;  MESSAGECACHE *elt;				/* UID call "impossible" */  if (flags & FT_UID) return NIL;  elt = mail_elt (stream,msgno);/* get cache element */				/* if message not seen */  if (!(flags & FT_PEEK) && !elt->seen) {				/* mark message seen and dirty */    elt->seen = elt->private.dirty = LOCAL->dirty = T;    MM_FLAGS (stream,msgno);  }  s = unix_text_work (stream,elt,&i,flags);  INIT (bs,mail_string,s,i);	/* set up stringstruct */  return T;			/* success */}/* UNIX mail fetch message text worker routine * Accepts: MAIL stream *	    message cache element *	    pointer to returned header text length *	    option flags */char *unix_text_work (MAILSTREAM *stream,MESSAGECACHE *elt,		      unsigned long *length,long flags){  FDDATA d;  STRING bs;  unsigned char c,*s,*t,*tl,tmp[CHUNKSIZE];				/* go to text position */  lseek (LOCAL->fd,elt->private.special.offset +	 elt->private.msg.text.offset,L_SET);  if (flags & FT_INTERNAL) {	/* initial data OK? */    if (elt->private.msg.text.text.size > LOCAL->buflen) {      fs_give ((void **) &LOCAL->buf);      LOCAL->buf = (char *) fs_get ((LOCAL->buflen =				     elt->private.msg.text.text.size) + 1);    }				/* read message */    read (LOCAL->fd,LOCAL->buf,elt->private.msg.text.text.size);				/* got text, tie off string */    LOCAL->buf[*length = elt->private.msg.text.text.size] = '\0';				/* squeeze out CRs (in case from PC) */    for (s = t = LOCAL->buf,tl = LOCAL->buf + *length; t < tl; t++)      if (*t != '\r') *s++ = *t;    *s = '\0';    *length = s - LOCAL->buf;	/* adjust length */    return (char *) LOCAL->buf;  }				/* have it cached already? */  if (elt->private.uid != LOCAL->uid) {				/* not cached, cache it now */    LOCAL->uid = elt->private.uid;				/* is buffer big enough? */    if (elt->rfc822_size > LOCAL->text.size) {      /* excessively conservative, but the right thing is too hard to do */      fs_give ((void **) &LOCAL->text.data);      LOCAL->text.data = (unsigned char *)	fs_get ((LOCAL->text.size = elt->rfc822_size) + 1);    }    d.fd = LOCAL->fd;		/* yes, set up file descriptor */    d.pos = elt->private.special.offset + elt->private.msg.text.offset;    d.chunk = tmp;		/* initial buffer chunk */    d.chunksize = CHUNKSIZE;	/* file chunk size */    INIT (&bs,fd_string,&d,elt->private.msg.text.text.size);    for (s = (char *) LOCAL->text.data; SIZE (&bs);) switch (c = SNX (&bs)) {    case '\r':			/* carriage return seen */      break;    case '\n':      *s++ = '\r';		/* insert a CR */    default:      *s++ = c;			/* copy characters */    }    *s = '\0';			/* tie off buffer */				/* calculate length of cached data */    LOCAL->textlen = s - LOCAL->text.data;  }  *length = LOCAL->textlen;	/* return from cache */  return (char *) LOCAL->text.data;}/* UNIX per-message modify flag * Accepts: MAIL stream *	    message cache element */void unix_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt){

⌨️ 快捷键说明

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