📄 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: 4 November 2004 * * The IMAP toolkit provided in this Distribution is * Copyright 1988-2004 University of Washington. * The full text of our legal notices is contained in the file called * CPYRIGHT, included with this Distribution. */#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 I/O stream local data */ typedef struct mx_local { int fd; /* file descriptor of open index */ char *dir; /* spool directory name */ 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);void *mx_parameters (long function,void *value);void mx_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);void mx_list (MAILSTREAM *stream,char *ref,char *pat);void mx_lsub (MAILSTREAM *stream,char *ref,char *pat);void mx_list_work (MAILSTREAM *stream,char *dir,char *pat,long level);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);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);void mx_expunge (MAILSTREAM *stream);long mx_copy (MAILSTREAM *stream,char *sequence,char *mailbox, long options);long mx_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);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, (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 */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]; if (dir && *dir) { /* make mailbox and directory names */ sprintf (name,"%s/",dir); /* print name starts at directory */ mx_file (curdir,dir); /* path starts from mx_file() name */ } else { /* no directory, use mailbox home dir */ mx_file (curdir,mailboxdir (name,NIL,NIL)); name[0] = '\0'; /* dummy name */ } if (dp = opendir (curdir)) { /* open directory */ np = name + strlen (name); cp = curdir + strlen (strcat (curdir,"/")); 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),"/"), get_dir_protection (mailbox))) sprintf (tmp,"Can't create mailbox leaf %.80s: %s", mailbox,strerror (errno)); else { /* create index file */ int mask = umask (0); 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)); else { /* success */ set_mbx_protections (mailbox,mbx); set_mbx_protections (mailbox,tmp); tmp[0] = NIL; } umask (mask); /* restore mask */ } if (!tmp[0]) return LONGT; /* success */ 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 */ } /* try to remove the directory */ if (rmdir (mx_file (tmp,mailbox))) { 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -