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

📄 mh.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ======================================================================== * Copyright 1988-2007 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:	MH 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:	23 February 1992 * Last Edited:	11 October 2007 */#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"/* Build parameters */#define MHINBOX "#mhinbox"	/* corresponds to namespace in env_unix.c */#define MHINBOXDIR "inbox"#define MHPROFILE ".mh_profile"#define MHCOMMA ','#define MHSEQUENCE ".mh_sequence"#define MHSEQUENCES ".mh_sequences"#define MHPATH "Mail"/* mh_load_message() flags */#define MLM_HEADER 0x1		/* load message text */#define MLM_TEXT 0x2		/* load message text *//* MH I/O stream local data */	typedef struct mh_local {  char *dir;			/* spool directory name */  unsigned char buf[CHUNKSIZE];	/* temporary buffer */  unsigned long cachedtexts;	/* total size of all cached texts */  time_t scantime;		/* last time directory scanned */} MHLOCAL;/* Convenient access to local data */#define LOCAL ((MHLOCAL *) stream->local)/* Function prototypes */DRIVER *mh_valid (char *name);int mh_isvalid (char *name,char *tmp,long synonly);int mh_namevalid (char *name);char *mh_path (char *tmp);void *mh_parameters (long function,void *value);long mh_dirfmttest (char *name);void mh_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);void mh_list (MAILSTREAM *stream,char *ref,char *pat);void mh_lsub (MAILSTREAM *stream,char *ref,char *pat);void mh_list_work (MAILSTREAM *stream,char *dir,char *pat,long level);long mh_subscribe (MAILSTREAM *stream,char *mailbox);long mh_unsubscribe (MAILSTREAM *stream,char *mailbox);long mh_create (MAILSTREAM *stream,char *mailbox);long mh_delete (MAILSTREAM *stream,char *mailbox);long mh_rename (MAILSTREAM *stream,char *old,char *newname);MAILSTREAM *mh_open (MAILSTREAM *stream);void mh_close (MAILSTREAM *stream,long options);void mh_fast (MAILSTREAM *stream,char *sequence,long flags);void mh_load_message (MAILSTREAM *stream,unsigned long msgno,long flags);char *mh_header (MAILSTREAM *stream,unsigned long msgno,unsigned long *length,		 long flags);long mh_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);long mh_ping (MAILSTREAM *stream);void mh_check (MAILSTREAM *stream);long mh_expunge (MAILSTREAM *stream,char *sequence,long options);long mh_copy (MAILSTREAM *stream,char *sequence,char *mailbox,	      long options);long mh_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);int mh_select (struct direct *name);int mh_numsort (const void *d1,const void *d2);char *mh_file (char *dst,char *name);long mh_canonicalize (char *pattern,char *ref,char *pat);void mh_setdate (char *file,MESSAGECACHE *elt);/* MH mail routines *//* Driver dispatch used by MAIL */DRIVER mhdriver = {  "mh",				/* driver name */				/* driver flags */  DR_MAIL|DR_LOCAL|DR_NOFAST|DR_NAMESPACE|DR_NOSTICKY|DR_DIRFMT,  (DRIVER *) NIL,		/* next driver */  mh_valid,			/* mailbox is valid for us */  mh_parameters,		/* manipulate parameters */  mh_scan,			/* scan mailboxes */  mh_list,			/* find mailboxes */  mh_lsub,			/* find subscribed mailboxes */  mh_subscribe,			/* subscribe to mailbox */  mh_unsubscribe,		/* unsubscribe from mailbox */  mh_create,			/* create mailbox */  mh_delete,			/* delete mailbox */  mh_rename,			/* rename mailbox */  mail_status_default,		/* status of mailbox */  mh_open,			/* open mailbox */  mh_close,			/* close mailbox */  mh_fast,			/* fetch message "fast" attributes */  NIL,				/* fetch message flags */  NIL,				/* fetch overview */  NIL,				/* fetch message envelopes */  mh_header,			/* fetch message header */  mh_text,			/* fetch message body */  NIL,				/* fetch partial message text */  NIL,				/* unique identifier */  NIL,				/* message number */  NIL,				/* modify flags */  NIL,				/* per-message modify flags */  NIL,				/* search for message based on criteria */  NIL,				/* sort messages */  NIL,				/* thread messages */  mh_ping,			/* ping mailbox to see if still alive */  mh_check,			/* check for new messages */  mh_expunge,			/* expunge deleted messages */  mh_copy,			/* copy messages to another mailbox */  mh_append,			/* append string message to mailbox */  NIL				/* garbage collect stream */};				/* prototype stream */MAILSTREAM mhproto = {&mhdriver};static char *mh_profile = NIL;	/* holds MH profile */static char *mh_pathname = NIL;	/* holds MH path name */static long mh_once = 0;	/* already snarled once */static long mh_allow_inbox =NIL;/* allow INBOX as well as MHINBOX *//* MH mail validate mailbox * Accepts: mailbox name * Returns: our driver if name is valid, NIL otherwise */DRIVER *mh_valid (char *name){  char tmp[MAILTMPLEN];  return mh_isvalid (name,tmp,T) ? &mhdriver : NIL;}/* MH mail test for valid mailbox * Accepts: mailbox name *	    temporary buffer to use *	    syntax only test flag * Returns: T if valid, NIL otherwise */int mh_isvalid (char *name,char *tmp,long synonly){  struct stat sbuf;  char *s,*t,altname[MAILTMPLEN];  unsigned long i;  int ret = NIL;  errno = NIL;			/* zap any error condition */				/* mh name? */  if ((mh_allow_inbox && !compare_cstring (name,"INBOX")) ||      !compare_cstring (name,MHINBOX) ||      ((name[0] == '#') && ((name[1] == 'm') || (name[1] == 'M')) &&       ((name[2] == 'h') || (name[2] == 'H')) && (name[3] == '/') && name[4])){    if (mh_path (tmp))		/* validate name if INBOX or not synonly */      ret = (synonly && compare_cstring (name,"INBOX")) ?	T : ((stat (mh_file (tmp,name),&sbuf) == 0) &&	     (sbuf.st_mode & S_IFMT) == S_IFDIR);    else if (!mh_once++) {	/* only report error once */      sprintf (tmp,"%.900s not found, mh format names disabled",mh_profile);      mm_log (tmp,WARN);    }  }				/* see if non-NS name within mh hierarchy */  else if ((name[0] != '#') && (s = mh_path (tmp)) && (i = strlen (s)) &&	   (t = mailboxfile (tmp,name)) && !strncmp (t,s,i) &&	   (tmp[i] == '/') && tmp[i+1]) {    sprintf (altname,"#mh%.900s",tmp+i);				/* can't do synonly here! */    ret = mh_isvalid (altname,tmp,NIL);  }  else errno = EINVAL;		/* bogus name */  return ret;}/* MH mail test for valid mailbox * Accepts: mailbox name * Returns: T if valid, NIL otherwise */int mh_namevalid (char *name){  char *s;  if (name[0] == '#' && (name[1] == 'm' || name[1] == 'M') &&      (name[2] == 'h' || name[2] == 'H') && name[3] == '/')    for (s = name; s && *s;) {	/* make sure no all-digit nodes */      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 */}/* Return MH path * Accepts: temporary buffer * Returns: MH path or NIL if MH disabled */char *mh_path (char *tmp){  char *s,*t,*v,*r;  int fd;  struct stat sbuf;  if (!mh_profile) {		/* build mh_profile and mh_pathname now */    sprintf (tmp,"%s/%s",myhomedir (),MHPROFILE);    if ((fd = open (mh_profile = cpystr (tmp),O_RDONLY,NIL)) >= 0) {      fstat (fd,&sbuf);		/* yes, get size and read file */      read (fd,(t = (char *) fs_get (sbuf.st_size + 1)),sbuf.st_size);      close (fd);		/* don't need the file any more */      t[sbuf.st_size] = '\0';	/* tie it off */				/* parse profile file */      for (s = strtok_r (t,"\r\n",&r); s && *s; s = strtok_r (NIL,"\r\n",&r)) {				/* found space in line? */	if (v = strpbrk (s," \t")) {	  *v++ = '\0';		/* tie off, is keyword "Path:"? */	  if (!compare_cstring (s,"Path:")) {				/* skip whitespace */	    while ((*v == ' ') || (*v == '\t')) ++v;				/* absolute path? */	    if (*v == '/') s = v;	    else sprintf (s = tmp,"%s/%s",myhomedir (),v);				/* copy name */	    mh_pathname = cpystr (s);	    break;		/* don't need to look at rest of file */	  }	}      }      fs_give ((void **) &t);	/* flush profile text */      if (!mh_pathname) {	/* default path if not in the profile */	sprintf (tmp,"%s/%s",myhomedir (),MHPATH);	mh_pathname = cpystr (tmp);      }    }  }  return mh_pathname;}/* MH manipulate driver parameters * Accepts: function code *	    function-dependent value * Returns: function-dependent return value */void *mh_parameters (long function,void *value){  void *ret = NIL;  switch ((int) function) {  case GET_INBOXPATH:    if (value) ret = mh_file ((char *) value,"INBOX");    break;  case GET_DIRFMTTEST:    ret = (void *) mh_dirfmttest;    break;  case SET_MHPROFILE:    if (mh_profile) fs_give ((void **) &mh_profile);    mh_profile = cpystr ((char *) value);  case GET_MHPROFILE:    ret = (void *) mh_profile;    break;  case SET_MHPATH:    if (mh_pathname) fs_give ((void **) &mh_pathname);    mh_pathname = cpystr ((char *) value);  case GET_MHPATH:    ret = (void *) mh_pathname;    break;  case SET_MHALLOWINBOX:    mh_allow_inbox = value ? T : NIL;  case GET_MHALLOWINBOX:    ret = (void *) (mh_allow_inbox ? VOIDT : NIL);  }  return ret;}/* MH test for directory format internal node * Accepts: candidate node name * Returns: T if internal name, NIL otherwise */long mh_dirfmttest (char *s){  int c;				/* sequence(s) file is an internal name */  if (strcmp (s,MHSEQUENCE) && strcmp (s,MHSEQUENCES)) {    if (*s == MHCOMMA) ++s;	/* else comma + all numeric name */				/* success if all-numeric */    while (c = *s++) if (!isdigit (c)) return NIL;  }  return LONGT;}/* MH scan mailboxes * Accepts: mail stream *	    reference *	    pattern to search *	    string to scan */void mh_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents){  char *s,test[MAILTMPLEN],file[MAILTMPLEN];  long i = 0;  if (!pat || !*pat) {		/* empty pattern? */    if (mh_canonicalize (test,ref,"*")) {				/* tie off name at root */      if (s = strchr (test,'/')) *++s = '\0';      else test[0] = '\0';      mm_list (stream,'/',test,LATT_NOSELECT);    }  }				/* get canonical form of name */  else if (mh_canonicalize (test,ref,pat)) {    if (contents) {		/* maybe I'll implement this someday */      mm_log ("Scan not valid for mh mailboxes",ERROR);      return;    }    if (test[3] == '/') {	/* looking down levels? */				/* yes, found any wildcards? */      if (s = strpbrk (test,"%*")) {				/* yes, copy name up to that point */	strncpy (file,test+4,i = s - (test+4));	file[i] = '\0';		/* tie off */      }      else strcpy (file,test+4);/* use just that name then */				/* find directory name */      if (s = strrchr (file,'/')) {	*s = '\0';		/* found, tie off at that point */	s = file;      }				/* do the work */      mh_list_work (stream,s,test,0);    }				/* always an INBOX */    if (!compare_cstring (test,MHINBOX))      mm_list (stream,NIL,MHINBOX,LATT_NOINFERIORS);  }}/* MH list mailboxes * Accepts: mail stream *	    reference *	    pattern to search */void mh_list (MAILSTREAM *stream,char *ref,char *pat){  mh_scan (stream,ref,pat,NIL);}/* MH list subscribed mailboxes * Accepts: mail stream *	    reference *	    pattern to search */void mh_lsub (MAILSTREAM *stream,char *ref,char *pat){  void *sdb = NIL;  char *s,test[MAILTMPLEN];				/* get canonical form of name */  if (mh_canonicalize (test,ref,pat) && (s = sm_read (&sdb))) {    do if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,NIL);    while (s = sm_read (&sdb)); /* until no more subscriptions */  }}/* MH list mailboxes worker routine * Accepts: mail stream *	    directory name to search *	    search pattern *	    search level */void mh_list_work (MAILSTREAM *stream,char *dir,char *pat,long level){  DIR *dp;  struct direct *d;  struct stat sbuf;  char *cp,*np,curdir[MAILTMPLEN],name[MAILTMPLEN];				/* build MH name to search */  if (dir) sprintf (name,"#mh/%s/",dir);  else strcpy (name,"#mh/");				/* make directory name, punt if bogus */  if (!mh_file (curdir,name)) return;

⌨️ 快捷键说明

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