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

📄 mx.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ======================================================================== * Copyright 1988-2008 University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * *  * ======================================================================== *//* * Program:	MX mail routines * * Author(s):	Mark Crispin *		Networks and Distributed Computing *		Computing & Communications *		University of Washington *		Administration Building, AG-44 *		Seattle, WA  98195 *		Internet: MRC@CAC.Washington.EDU * * Date:	3 May 1996 * Last Edited:	6 January 2008 */#include <stdio.h>#include <ctype.h>#include <errno.h>extern int errno;		/* just in case */#include "mail.h"#include "osdep.h"#include <pwd.h>#include <sys/stat.h>#include <sys/time.h>#include "misc.h"#include "dummy.h"#include "fdstring.h"/* Index file */#define MXINDEXNAME "/.mxindex"#define MXINDEX(d,s) strcat (mx_file (d,s),MXINDEXNAME)/* MX I/O stream local data */	typedef struct mx_local {  int fd;			/* file descriptor of open index */  unsigned char *buf;		/* temporary buffer */  unsigned long buflen;		/* current size of temporary buffer */  unsigned long cachedtexts;	/* total size of all cached texts */  time_t scantime;		/* last time directory scanned */} MXLOCAL;/* Convenient access to local data */#define LOCAL ((MXLOCAL *) stream->local)/* Function prototypes */DRIVER *mx_valid (char *name);int mx_isvalid (char *name,char *tmp);int mx_namevalid (char *name);void *mx_parameters (long function,void *value);long mx_dirfmttest (char *name);void mx_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);long mx_scan_contents (char *name,char *contents,unsigned long csiz,		       unsigned long fsiz);void mx_list (MAILSTREAM *stream,char *ref,char *pat);void mx_lsub (MAILSTREAM *stream,char *ref,char *pat);long mx_subscribe (MAILSTREAM *stream,char *mailbox);long mx_unsubscribe (MAILSTREAM *stream,char *mailbox);long mx_create (MAILSTREAM *stream,char *mailbox);long mx_delete (MAILSTREAM *stream,char *mailbox);long mx_rename (MAILSTREAM *stream,char *old,char *newname);int mx_rename_work (char *src,size_t srcl,char *dst,size_t dstl,char *name);MAILSTREAM *mx_open (MAILSTREAM *stream);void mx_close (MAILSTREAM *stream,long options);void mx_fast (MAILSTREAM *stream,char *sequence,long flags);char *mx_fast_work (MAILSTREAM *stream,MESSAGECACHE *elt);char *mx_header (MAILSTREAM *stream,unsigned long msgno,unsigned long *length,		 long flags);long mx_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);void mx_flag (MAILSTREAM *stream,char *sequence,char *flag,long flags);void mx_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt);long mx_ping (MAILSTREAM *stream);void mx_check (MAILSTREAM *stream);long mx_expunge (MAILSTREAM *stream,char *sequence,long options);long mx_copy (MAILSTREAM *stream,char *sequence,char *mailbox,	      long options);long mx_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);long mx_append_msg (MAILSTREAM *stream,char *flags,MESSAGECACHE *elt,		    STRING *st,SEARCHSET *set);int mx_select (struct direct *name);int mx_numsort (const void *d1,const void *d2);char *mx_file (char *dst,char *name);long mx_lockindex (MAILSTREAM *stream);void mx_unlockindex (MAILSTREAM *stream);void mx_setdate (char *file,MESSAGECACHE *elt);/* MX mail routines *//* Driver dispatch used by MAIL */DRIVER mxdriver = {  "mx",				/* driver name */				/* driver flags */  DR_MAIL|DR_LOCAL|DR_NOFAST|DR_CRLF|DR_LOCKING|DR_DIRFMT,  (DRIVER *) NIL,		/* next driver */  mx_valid,			/* mailbox is valid for us */  mx_parameters,		/* manipulate parameters */  mx_scan,			/* scan mailboxes */  mx_list,			/* find mailboxes */  mx_lsub,			/* find subscribed mailboxes */  mx_subscribe,			/* subscribe to mailbox */  mx_unsubscribe,		/* unsubscribe from mailbox */  mx_create,			/* create mailbox */  mx_delete,			/* delete mailbox */  mx_rename,			/* rename mailbox */  mail_status_default,		/* status of mailbox */  mx_open,			/* open mailbox */  mx_close,			/* close mailbox */  mx_fast,			/* fetch message "fast" attributes */  NIL,				/* fetch message flags */  NIL,				/* fetch overview */  NIL,				/* fetch message envelopes */  mx_header,			/* fetch message header only */  mx_text,			/* fetch message body only */  NIL,				/* fetch partial message test */  NIL,				/* unique identifier */  NIL,				/* message number */  mx_flag,			/* modify flags */  mx_flagmsg,			/* per-message modify flags */  NIL,				/* search for message based on criteria */  NIL,				/* sort messages */  NIL,				/* thread messages */  mx_ping,			/* ping mailbox to see if still alive */  mx_check,			/* check for new messages */  mx_expunge,			/* expunge deleted messages */  mx_copy,			/* copy messages to another mailbox */  mx_append,			/* append string message to mailbox */  NIL				/* garbage collect stream */};				/* prototype stream */MAILSTREAM mxproto = {&mxdriver};/* MX mail validate mailbox * Accepts: mailbox name * Returns: our driver if name is valid, NIL otherwise */DRIVER *mx_valid (char *name){  char tmp[MAILTMPLEN];  return mx_isvalid (name,tmp) ? &mxdriver : NIL;}/* MX mail test for valid mailbox * Accepts: mailbox name *	    temporary buffer to use * Returns: T if valid, NIL otherwise with errno holding dir stat error */int mx_isvalid (char *name,char *tmp){  struct stat sbuf;  errno = NIL;			/* zap error */  if ((strlen (name) <= NETMAXMBX) && *mx_file (tmp,name) &&      !stat (tmp,&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFDIR)) {				/* name is directory; is it mx? */    if (!stat (MXINDEX (tmp,name),&sbuf) &&	((sbuf.st_mode & S_IFMT) == S_IFREG)) return T;    errno = NIL;		/* directory but not mx */  }  else if (!compare_cstring (name,"INBOX")) errno = NIL;  return NIL;}/* MX mail test for valid mailbox * Accepts: mailbox name * Returns: T if valid, NIL otherwise */int mx_namevalid (char *name){  char *s = (*name == '/') ? name + 1 : name;  while (s && *s) {		/* make sure valid name */    if (isdigit (*s)) s++;	/* digit, check this node further... */    else if (*s == '/') break;	/* all digit node, barf */				/* non-digit, skip to next node or return */    else if (!((s = strchr (s+1,'/')) && *++s)) return T;  }  return NIL;			/* all numeric or empty node */}/* MX manipulate driver parameters * Accepts: function code *	    function-dependent value * Returns: function-dependent return value */void *mx_parameters (long function,void *value){  void *ret = NIL;  switch ((int) function) {  case GET_INBOXPATH:    if (value) ret = mailboxfile ((char *) value,"~/INBOX");    break;  case GET_DIRFMTTEST:    ret = (void *) mx_dirfmttest;    break;  case GET_SCANCONTENTS:    ret = (void *) mx_scan_contents;    break;  }  return ret;}/* MX test for directory format internal node * Accepts: candidate node name * Returns: T if internal name, NIL otherwise */long mx_dirfmttest (char *name){  int c;				/* success if index name or all-numberic */  if (strcmp (name,MXINDEXNAME+1))    while (c = *name++) if (!isdigit (c)) return NIL;  return LONGT;}/* MX scan mailboxes * Accepts: mail stream *	    reference *	    pattern to search *	    string to scan */void mx_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents){  if (stream) dummy_scan (NIL,ref,pat,contents);}/* MX scan mailbox for contents * Accepts: mailbox name *	    desired contents *	    contents size *	    file size (ignored) * Returns: NIL if contents not found, T if found */long mx_scan_contents (char *name,char *contents,unsigned long csiz,			unsigned long fsiz){  long i,nfiles;  void *a;  char *s;  long ret = NIL;  size_t namelen = strlen (name);  struct stat sbuf;  struct direct **names = NIL;  if ((nfiles = scandir (name,&names,mx_select,mx_numsort)) > 0)    for (i = 0; i < nfiles; ++i) {      if (!ret) {	sprintf (s = (char *) fs_get (namelen + strlen (names[i]->d_name) + 2),		 "%s/%s",name,names[i]->d_name);	if (!stat (s,&sbuf) && (csiz <= sbuf.st_size))	  ret = dummy_scan_contents (s,contents,csiz,sbuf.st_size);	fs_give ((void **) &s);      }      fs_give ((void **) &names[i]);    }				/* free directory list */  if (a = (void *) names) fs_give ((void **) &a);  return ret;}/* MX list mailboxes * Accepts: mail stream *	    reference *	    pattern to search */void mx_list (MAILSTREAM *stream,char *ref,char *pat){  if (stream) dummy_list (NIL,ref,pat);}/* MX list subscribed mailboxes * Accepts: mail stream *	    reference *	    pattern to search */void mx_lsub (MAILSTREAM *stream,char *ref,char *pat){  if (stream) dummy_lsub (NIL,ref,pat);}/* MX mail subscribe to mailbox * Accepts: mail stream *	    mailbox to add to subscription list * Returns: T on success, NIL on failure */long mx_subscribe (MAILSTREAM *stream,char *mailbox){  return sm_subscribe (mailbox);}/* MX mail unsubscribe to mailbox * Accepts: mail stream *	    mailbox to delete from subscription list * Returns: T on success, NIL on failure */long mx_unsubscribe (MAILSTREAM *stream,char *mailbox){  return sm_unsubscribe (mailbox);}/* MX mail create mailbox * Accepts: mail stream *	    mailbox name to create * Returns: T on success, NIL on failure */long mx_create (MAILSTREAM *stream,char *mailbox){  DRIVER *test;  int fd;  char *s,tmp[MAILTMPLEN];  int mask = umask (0);  long ret = NIL;  if (!mx_namevalid (mailbox))	/* validate name */    sprintf (tmp,"Can't create mailbox %.80s: invalid MX-format name",mailbox);				/* must not already exist */  else if ((test = mail_valid (NIL,mailbox,NIL)) &&	   strcmp (test->name,"dummy"))    sprintf (tmp,"Can't create mailbox %.80s: mailbox already exists",mailbox);				/* create directory */  else if (!dummy_create_path (stream,MXINDEX (tmp,mailbox),			       get_dir_protection (mailbox)))    sprintf (tmp,"Can't create mailbox %.80s: %s",mailbox,strerror (errno));  else {			/* success */				/* set index protection */    set_mbx_protections (mailbox,tmp);				/* tie off directory name */    *(s = strrchr (tmp,'/') + 1) = '\0';				/* set directory protection */    set_mbx_protections (mailbox,tmp);    ret = LONGT;  }  umask (mask);			/* restore mask */  if (!ret) MM_LOG (tmp,ERROR);	/* some error */  return ret;}/* MX mail delete mailbox *	    mailbox name to delete * Returns: T on success, NIL on failure */long mx_delete (MAILSTREAM *stream,char *mailbox){  DIR *dirp;  struct direct *d;  char *s;  char tmp[MAILTMPLEN];  if (!mx_isvalid (mailbox,tmp))    sprintf (tmp,"Can't delete mailbox %.80s: no such mailbox",mailbox);				/* delete index */  else if (unlink (MXINDEX (tmp,mailbox)))    sprintf (tmp,"Can't delete mailbox %.80s index: %s",	     mailbox,strerror (errno));  else {			/* get directory name */    *(s = strrchr (tmp,'/')) = '\0';    if (dirp = opendir (tmp)) {	/* open directory */      *s++ = '/';		/* restore delimiter */				/* massacre messages */      while (d = readdir (dirp)) if (mx_select (d)) {	strcpy (s,d->d_name);	/* make path */	unlink (tmp);		/* sayonara */      }      closedir (dirp);		/* flush directory */      *(s = strrchr (tmp,'/')) = '\0';      if (rmdir (tmp)) {	/* try to remove the directory */	sprintf (tmp,"Can't delete name %.80s: %s",mailbox,strerror (errno));	MM_LOG (tmp,WARN);      }    }    return T;			/* always success */  }  MM_LOG (tmp,ERROR);		/* something failed */  return NIL;}/* MX mail rename mailbox * Accepts: MX mail stream *	    old mailbox name *	    new mailbox name * Returns: T on success, NIL on failure */long mx_rename (MAILSTREAM *stream,char *old,char *newname){  char c,*s,tmp[MAILTMPLEN],tmp1[MAILTMPLEN];  struct stat sbuf;  if (!mx_isvalid (old,tmp))    sprintf (tmp,"Can't rename mailbox %.80s: no such mailbox",old);  else if (!mx_namevalid (newname))    sprintf (tmp,"Can't rename to mailbox %.80s: invalid MX-format name",	     newname);

⌨️ 快捷键说明

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