📄 mx.c
字号:
/* * 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: 31 January 2000 * * Copyright 2000 by the University of Washington * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appears in all copies and that both the * above copyright notice and this permission notice appear in supporting * documentation, and that the name of the University of Washington not be * used in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. This software is made * available "as is", and * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */#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 "mx.h"#include "misc.h"#include "dummy.h"/* MX mail routines *//* Driver dispatch used by MAIL */DRIVER mxdriver = { "mx", /* driver name */ /* driver flags */ DR_MAIL|DR_LOCAL|DR_NOFAST|DR_CRLF, (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 */ NIL, /* 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 */int mx_isvalid (char *name,char *tmp){ struct stat sbuf; errno = NIL; /* zap error */ /* validate name as directory */ return (!stat (MXINDEX (tmp,name),&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFREG));}/* MX manipulate driver parameters * Accepts: function code * function-dependent value * Returns: function-dependent return value */void *mx_parameters (long function,void *value){ return NIL;}/* 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) mm_log ("Scan not valid for mx mailboxes",ERROR);}/* MX list mailboxes * Accepts: mail stream * reference * pattern to search */void mx_list (MAILSTREAM *stream,char *ref,char *pat){ char *s,test[MAILTMPLEN],file[MAILTMPLEN]; long i = 0; /* get canonical form of name */ if (stream && dummy_canonicalize (test,ref,pat)) { /* found any wildcards? */ if (s = strpbrk (test,"%*")) { /* yes, copy name up to that point */ strncpy (file,test,i = s - test); file[i] = '\0'; /* tie off */ } else strcpy (file,test); /* 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 */ mx_list_work (stream,s,test,0); }}/* 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 list mailboxes worker routine * Accepts: mail stream * directory name to search * search pattern * search level */void mx_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]; /* make mailbox and directory names */ if ((np = name + strlen (strcpy (name,dir ? dir : ""))) != name) *np++ = '/'; cp = curdir + strlen (strcat ((mx_file(curdir,dir ? dir:myhomedir())),"/")); if (dp = opendir (curdir)) { /* open directory */ while (d = readdir (dp)) { /* scan, ignore . and numeric names */ if ((d->d_name[0] != '.') && !mx_select (d)) { if (level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL)) { strcpy (cp,d->d_name);/* make directory name */ strcpy (np,d->d_name);/* make mx name of directory name */ if (dmatch (name,pat,'/') && !stat (curdir,&sbuf) && ((sbuf.st_mode &= S_IFMT) == S_IFDIR)) mx_list_work (stream,name,pat,level+1); } } else if (!strcmp (d->d_name,MXINDEXNAME+1) && pmatch_full (dir,pat,'/')) mm_list (stream,'/',dir,NIL); } closedir (dp); /* all done, flush directory */ }}/* 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){ int fd; char *s,tmp[MAILTMPLEN],mbx[MAILTMPLEN]; /* assume error */ sprintf (tmp,"Can't create mailbox %.80s: invalid MX-format name",mailbox); /* make sure valid name */ for (s = mailbox; s && *s;) { if (isdigit (*s)) s++; /* digit, check this node further... */ /* all digit node, barf */ else if (*s == '/') s = NIL; /* non-digit in node, skip to next node */ else if (s = strchr (s+1,'/')) s++; else tmp[0] = NIL; /* no more nodes, good name */ } if (tmp[0]); /* was there an error in the name? */ /* must not already exist */ else if (mx_isvalid (mailbox,tmp)) sprintf (tmp,"Can't create mailbox %.80s: mailbox already exists",mailbox); /* create directory */ else if (!dummy_create_path (stream,strcat (mx_file (mbx,mailbox),"/"))) sprintf (tmp,"Can't create mailbox leaf %.80s: %s", mailbox,strerror (errno)); /* create index file */ else if (((fd = open (MXINDEX (tmp,mailbox),O_WRONLY|O_CREAT|O_EXCL, (int) mail_parameters (NIL,GET_MBXPROTECTION,mailbox))) <0 ) || close (fd)) sprintf (tmp,"Can't create mailbox index %.80s: %s", mailbox,strerror (errno)); /* success */ else return set_mbx_protections (mailbox,mbx) && set_mbx_protections (mailbox,tmp); mm_log (tmp,ERROR); /* some error */ return NIL;}/* 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 */ } /* success if can remove the directory */ if (!rmdir (mx_file (tmp,mailbox))) return T; sprintf (tmp,"Can't delete mailbox %.80s: %s",mailbox,strerror (errno)); } 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); /* new mailbox name must not be valid */ else if (mx_isvalid (newname,tmp)) sprintf (tmp,"Can't rename to mailbox %.80s: destination already exists", newname); /* success if can rename the directory */ else { /* found superior to destination name? */ if (s = strrchr (mx_file (tmp1,newname),'/')) { c = *++s; /* remember first character of inferior */ *s = '\0'; /* tie off to get just superior */ /* name doesn't exist, create it */ if ((stat (tmp1,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) && !dummy_create (stream,tmp1)) return NIL; *s = c; /* restore full name */ } if (!rename (mx_file (tmp,old),tmp1)) { /* recreate file if renamed INBOX */ if (!strcmp (ucase (strcpy (tmp,old)),"INBOX")) mx_create (NIL,"INBOX"); return T; } sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %s", old,newname,strerror (errno)); } mm_log (tmp,ERROR); /* something failed */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -