📄 dummy.c
字号:
/* * Program: Dummy routines * * Author: Mark Crispin * Networks and Distributed Computing * Computing & Communications * University of Washington * Administration Building, AG-44 * Seattle, WA 98195 * Internet: MRC@CAC.Washington.EDU * * Date: 9 May 1991 * Last Edited: 10 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 "dummy.h"#include "misc.h"#include "mx.h" /* highly unfortunate *//* Function prototypes */DRIVER *dummy_valid (char *name);void *dummy_parameters (long function,void *value);void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents, long level);long dummy_listed (MAILSTREAM *stream,char delimiter,char *name, long attributes,char *contents);long dummy_subscribe (MAILSTREAM *stream,char *mailbox);MAILSTREAM *dummy_open (MAILSTREAM *stream);void dummy_close (MAILSTREAM *stream,long options);long dummy_ping (MAILSTREAM *stream);void dummy_check (MAILSTREAM *stream);void dummy_expunge (MAILSTREAM *stream);long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);/* Dummy routines *//* Driver dispatch used by MAIL */DRIVER dummydriver = { "dummy", /* driver name */ DR_LOCAL|DR_MAIL, /* driver flags */ (DRIVER *) NIL, /* next driver */ dummy_valid, /* mailbox is valid for us */ dummy_parameters, /* manipulate parameters */ dummy_scan, /* scan mailboxes */ dummy_list, /* list mailboxes */ dummy_lsub, /* list subscribed mailboxes */ dummy_subscribe, /* subscribe to mailbox */ NIL, /* unsubscribe from mailbox */ dummy_create, /* create mailbox */ dummy_delete, /* delete mailbox */ dummy_rename, /* rename mailbox */ mail_status_default, /* status of mailbox */ dummy_open, /* open mailbox */ dummy_close, /* close mailbox */ NIL, /* fetch message "fast" attributes */ NIL, /* fetch message flags */ NIL, /* fetch overview */ NIL, /* fetch message structure */ NIL, /* fetch header */ NIL, /* fetch text */ NIL, /* fetch message data */ NIL, /* unique identifier */ NIL, /* message number from UID */ NIL, /* modify flags */ NIL, /* per-message modify flags */ NIL, /* search for message based on criteria */ NIL, /* sort messages */ NIL, /* thread messages */ dummy_ping, /* ping mailbox to see if still alive */ dummy_check, /* check for new messages */ dummy_expunge, /* expunge deleted messages */ dummy_copy, /* copy messages to another mailbox */ dummy_append, /* append string message to mailbox */ NIL /* garbage collect stream */}; /* prototype stream */MAILSTREAM dummyproto = {&dummydriver};/* Dummy validate mailbox * Accepts: mailbox name * Returns: our driver if name is valid, NIL otherwise */DRIVER *dummy_valid (char *name){ char *s,tmp[MAILTMPLEN]; struct stat sbuf; /* must be valid local mailbox */ if (name && *name && (*name != '{') && (s = mailboxfile (tmp,name))) { /* indeterminate clearbox INBOX */ if (!*s) return &dummydriver; else if (!stat (s,&sbuf)) switch (sbuf.st_mode & S_IFMT) { case S_IFREG: case S_IFDIR: return &dummydriver; } /* blackbox INBOX does not exist yet */ else if (!compare_cstring (name,"INBOX")) return &dummydriver; } return NIL;}/* Dummy manipulate driver parameters * Accepts: function code * function-dependent value * Returns: function-dependent return value */void *dummy_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;}/* Dummy scan mailboxes * Accepts: mail stream * reference * pattern to search * string to scan */void dummy_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents){ char *s,test[MAILTMPLEN],file[MAILTMPLEN]; long i; if (!pat || !*pat) { /* empty pattern? */ if (dummy_canonicalize (test,ref,"*")) { /* tie off name at root */ if (s = strchr (test,'/')) *++s = '\0'; else test[0] = '\0'; dummy_listed (stream,'/',test,LATT_NOSELECT,NIL); } } /* get canonical form of name */ else if (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 */ if (s = strrchr (file,'/')){/* find directory name */ *++s = '\0'; /* found, tie off at that point */ s = file; } /* silly case */ else if ((file[0] == '~') || (file[0] == '#')) s = file; /* do the work */ dummy_list_work (stream,s,test,contents,0); /* always an INBOX */ if (pmatch ("INBOX",ucase (test))) dummy_listed (stream,NIL,"INBOX",LATT_NOINFERIORS,contents); }}/* Dummy list mailboxes * Accepts: mail stream * reference * pattern to search */void dummy_list (MAILSTREAM *stream,char *ref,char *pat){ dummy_scan (stream,ref,pat,NIL);}/* Dummy list subscribed mailboxes * Accepts: mail stream * reference * pattern to search */void dummy_lsub (MAILSTREAM *stream,char *ref,char *pat){ void *sdb = NIL; char *s,*t,test[MAILTMPLEN],tmp[MAILTMPLEN]; int showuppers = pat[strlen (pat) - 1] == '%'; /* get canonical form of name */ if (dummy_canonicalize (test,ref,pat) && (s = sm_read (&sdb))) do if (*s != '{') { if (!compare_cstring (s,"INBOX") && pmatch ("INBOX",ucase (strcpy (tmp,test)))) mm_lsub (stream,NIL,s,LATT_NOINFERIORS); else if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,NIL); else while (showuppers && (t = strrchr (s,'/'))) { *t = '\0'; /* tie off the name */ if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,LATT_NOSELECT); } } while (s = sm_read (&sdb)); /* until no more subscriptions */}/* Dummy subscribe to mailbox * Accepts: mail stream * mailbox to add to subscription list * Returns: T on success, NIL on failure */long dummy_subscribe (MAILSTREAM *stream,char *mailbox){ char *s,tmp[MAILTMPLEN]; struct stat sbuf; /* must be valid local mailbox */ if ((s = mailboxfile (tmp,mailbox)) && *s && !stat (s,&sbuf)#if 0 /* disable this temporarily for Netscape */ && ((sbuf.st_mode & S_IFMT) == S_IFREG)#endif ) return sm_subscribe (mailbox); sprintf (tmp,"Can't subscribe %.80s: not a mailbox",mailbox); MM_LOG (tmp,ERROR); return NIL;}/* Dummy list mailboxes worker routine * Accepts: mail stream * directory name to search * search pattern * string to scan * search level */void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents, long level){ DIR *dp; struct direct *d; struct stat sbuf; int ismx; char tmp[MAILTMPLEN]; /* punt if bogus name */ if (!mailboxdir (tmp,dir,NIL)) return; if (dp = opendir (tmp)) { /* do nothing if can't open directory */ /* list it if not at top-level */ if (!level && dir && pmatch_full (dir,pat,'/')) dummy_listed (stream,'/',dir,LATT_NOSELECT,contents); /* scan directory, ignore . and .. */ ismx = (!stat (strcat (tmp,MXINDEXNAME),&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFREG)); if (!dir || dir[strlen (dir) - 1] == '/') while (d = readdir (dp)) if (((d->d_name[0] != '.') || (((int) mail_parameters (NIL,GET_HIDEDOTFILES,NIL)) ? NIL : (d->d_name[1] && (((d->d_name[1] != '.') || d->d_name[2]) && strcmp (d->d_name+1,MXINDEXNAME+2))))) && (strlen (d->d_name) <= NETMAXMBX)) { /* see if name is useful */ if (dir) sprintf (tmp,"%s%s",dir,d->d_name); else strcpy (tmp,d->d_name); /* make sure useful and can get info */ if ((pmatch_full (tmp,pat,'/') || pmatch_full (strcat (tmp,"/"),pat,'/') || dmatch (tmp,pat,'/')) && mailboxdir (tmp,dir,d->d_name) && tmp[0] && !stat (tmp,&sbuf)) { /* now make name we'd return */ if (dir) sprintf (tmp,"%s%s",dir,d->d_name); else strcpy (tmp,d->d_name); /* only interested in file type */ switch (sbuf.st_mode & S_IFMT) { case S_IFDIR: /* directory? */ if (pmatch_full (tmp,pat,'/')) { if (!dummy_listed (stream,'/',tmp,LATT_NOSELECT,contents)) break; strcat (tmp,"/"); /* set up for dmatch call */ } /* try again with trailing / */ else if (pmatch_full (strcat (tmp,"/"),pat,'/') && !dummy_listed (stream,'/',tmp,LATT_NOSELECT,contents)) break; if (dmatch (tmp,pat,'/') && (level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL))) dummy_list_work (stream,tmp,pat,contents,level+1); break; case S_IFREG: /* ordinary name */ /* ignore all-digit names from mx */ /* Must use ctime for systems that don't update mtime properly */ if (!(ismx && mx_select (d)) && pmatch_full (tmp,pat,'/') && compare_cstring (tmp,"INBOX")) dummy_listed (stream,'/',tmp,LATT_NOINFERIORS + ((sbuf.st_size && (sbuf.st_atime < sbuf.st_ctime))? LATT_MARKED : LATT_UNMARKED),contents); break; } } } closedir (dp); /* all done, flush directory */ }}/* Scan file for contents * Accepts: file name * desired contents * Returns: NIL if contents not found, T if found */#define BUFSIZE 4*MAILTMPLENlong dummy_scan_contents (char *name,char *contents,unsigned long csiz, unsigned long fsiz){ int fd; unsigned long ssiz,bsiz; char *buf; /* forget it if can't select or open */ if ((fd = open (name,O_RDONLY,NIL)) >= 0) { /* get buffer including slop */ buf = (char *) fs_get (BUFSIZE + (ssiz = 4 * ((csiz / 4) + 1)) + 1); memset (buf,'\0',ssiz); /* no slop area the first time */ while (fsiz) { /* until end of file */ read (fd,buf+ssiz,bsiz = min (fsiz,BUFSIZE)); if (search ((unsigned char *) buf,bsiz+ssiz, (unsigned char *) contents,csiz)) break; memcpy (buf,buf+BUFSIZE,ssiz); fsiz -= bsiz; /* note that we read that much */ } fs_give ((void **) &buf); /* flush buffer */ close (fd); /* finished with file */ if (fsiz) return T; /* found */ } return NIL; /* not found */}/* Mailbox found * Accepts: MAIL stream * hierarchy delimiter * mailbox name * attributes * contents to search before calling mm_list() * Returns: NIL if should abort hierarchy search, else T (currently always) */long dummy_listed (MAILSTREAM *stream,char delimiter,char *name, long attributes,char *contents){ DRIVER *d = NIL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -