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

📄 mmdf.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
  if ((t = dummy_file (file,name)) && !stat (t,&sbuf)) {    if (!sbuf.st_size)errno = 0;/* empty file */    else if ((fd = open (file,O_RDONLY,NIL)) >= 0) {				/* error -1 for invalid format */      if (!(ret = mmdf_isvalid_fd (fd,tmp))) errno = -1;      close (fd);		/* close the file */				/* \Marked status? */      if ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) {	tp[0] = sbuf.st_atime;	/* preserve atime and mtime */	tp[1] = sbuf.st_mtime;	utime (file,tp);	/* set the times */      }    }  }  return ret;			/* return what we should */}/* MMDF mail test for valid mailbox * Accepts: file descriptor *	    scratch buffer * Returns: T if valid, NIL otherwise */long mmdf_isvalid_fd (int fd,char *tmp){  int ret = NIL;  memset (tmp,'\0',MAILTMPLEN);  if (read (fd,tmp,MAILTMPLEN-1) >= 0) ret = ISMMDF (tmp) ? T : NIL;  return ret;			/* return what we should */}/* MMDF manipulate driver parameters * Accepts: function code *	    function-dependent value * Returns: function-dependent return value */void *mmdf_parameters (long function,void *value){  void *ret = NIL;  switch ((int) function) {  case GET_INBOXPATH:    if (value) ret = dummy_file ((char *) value,"INBOX");    break;  }  return ret;}/* MMDF mail scan mailboxes * Accepts: mail stream *	    reference *	    pattern to search *	    string to scan */void mmdf_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents){  if (stream) dummy_scan (NIL,ref,pat,contents);}/* MMDF mail list mailboxes * Accepts: mail stream *	    reference *	    pattern to search */void mmdf_list (MAILSTREAM *stream,char *ref,char *pat){  if (stream) dummy_list (NIL,ref,pat);}/* MMDF mail list subscribed mailboxes * Accepts: mail stream *	    reference *	    pattern to search */void mmdf_lsub (MAILSTREAM *stream,char *ref,char *pat){  if (stream) dummy_lsub (NIL,ref,pat);}/* MMDF mail create mailbox * Accepts: MAIL stream *	    mailbox name to create * Returns: T on success, NIL on failure */long mmdf_create (MAILSTREAM *stream,char *mailbox){  char *s,mbx[MAILTMPLEN],tmp[MAILTMPLEN];  long ret = NIL;  int i,fd;  time_t ti = time (0);  if (!(s = dummy_file (mbx,mailbox))) {    sprintf (tmp,"Can't create %.80s: invalid name",mailbox);    MM_LOG (tmp,ERROR);  }				/* create underlying file */  else if (dummy_create_path (stream,s,get_dir_protection (mailbox))) {				/* done if dir-only or whiner */    if (((s = strrchr (s,'/')) && !s[1]) ||	mail_parameters (NIL,GET_USERHASNOLIFE,NIL)) ret = T;    else if ((fd = open (mbx,O_WRONLY,		    (long) mail_parameters (NIL,GET_MBXPROTECTION,NIL))) < 0) {      sprintf (tmp,"Can't reopen mailbox node %.80s: %s",mbx,strerror (errno));      MM_LOG (tmp,ERROR);      unlink (mbx);		/* delete the file */    }    else {			/* initialize header */      memset (tmp,'\0',MAILTMPLEN);      sprintf (tmp,"%sFrom %s %sDate: ",mmdfhdr,pseudo_from,ctime (&ti));      rfc822_date (s = tmp + strlen (tmp));      sprintf (s += strlen (s),	/* write the pseudo-header */	       "\nFrom: %s <%s@%s>\nSubject: %s\nX-IMAP: %010lu 0000000000",	       pseudo_name,pseudo_from,mylocalhost (),pseudo_subject,	       (unsigned long) ti);      for (i = 0; i < NUSERFLAGS; ++i) if (default_user_flag (i))	sprintf (s += strlen (s)," %s",default_user_flag (i));      sprintf (s += strlen (s),"\nStatus: RO\n\n%s\n%s",pseudo_msg,mmdfhdr);      if (write (fd,tmp,strlen (tmp)) > 0) ret = T;      else {	sprintf (tmp,"Can't initialize mailbox node %.80s: %s",mbx,		 strerror (errno));	MM_LOG (tmp,ERROR);	unlink (mbx);		/* delete the file */      }      close (fd);		/* close file */    }  }				/* set proper protections */  return ret ? set_mbx_protections (mailbox,mbx) : NIL;}/* MMDF mail delete mailbox * Accepts: MAIL stream *	    mailbox name to delete * Returns: T on success, NIL on failure */long mmdf_delete (MAILSTREAM *stream,char *mailbox){  return mmdf_rename (stream,mailbox,NIL);}/* MMDF mail rename mailbox * Accepts: MAIL stream *	    old mailbox name *	    new mailbox name (or NIL for delete) * Returns: T on success, NIL on failure */long mmdf_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 = mmdf_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))) {	    mmdf_unlock (fd,NIL,&lockx);	    mmdf_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 */      mmdf_unlock (fd,NIL,&lockx);    }    mmdf_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 */}/* MMDF mail open * Accepts: Stream to open * Returns: Stream on success, NIL on failure */MAILSTREAM *mmdf_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 (&mmdfproto);  retry = stream->silent ? 1 : KODRETRY;  if (stream->local) fatal ("mmdf recycle stream");  stream->local = memset (fs_get (sizeof (MMDFLOCAL)),0,sizeof (MMDFLOCAL));				/* 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))    mmdf_abort (stream);	/* abort if can't get RW silent stream */				/* parse mailbox */  else if (mmdf_parse (stream,&lock,LOCK_SH)) {    mmdf_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 */}/* MMDF mail close * Accepts: MAIL stream *	    close options */void mmdf_close (MAILSTREAM *stream,long options){  int silent = stream->silent;  stream->silent = T;		/* go silent */				/* expunge if requested */  if (options & CL_EXPUNGE) mmdf_expunge (stream,NIL,NIL);				/* else dump final checkpoint */  else if (LOCAL->dirty) mmdf_check (stream);  stream->silent = silent;	/* restore old silence state */  mmdf_abort (stream);		/* now punt the file and local data */}/* MMDF 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 *mmdf_hlines = NIL;char *mmdf_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 (!mmdf_hlines) {		/* once only code */    STRINGLIST *lines = mmdf_hlines = mail_newstringlist ();    lines->text.size = strlen ((char *) (lines->text.data =					 (unsigned char *) "Status"));    lines = lines->next = mail_newstringlist ();

⌨️ 快捷键说明

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