📄 bezrkdos.c
字号:
/* * Program: Berkeley mail 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: 24 June 1992 * Last Edited: 25 February 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. * *//* Dedication: * This file is dedicated with affection to those Merry Marvels of Musical * Madness . . . * -> The Incomparable Leland Stanford Junior University Marching Band <- * who entertain, awaken, and outrage Stanford fans in the fact of repeated * losing seasons and shattered Rose Bowl dreams [Cardinal just don't have * HUSKY FEVER!!!]. * */#include <ctype.h>#include <errno.h>#include <fcntl.h>#include "mail.h"#include "osdep.h"#include <time.h>#include <sys\stat.h>#include <dos.h>#include "bezrkdos.h"#include "rfc822.h"#include "dummy.h"#include "misc.h"#include "fdstring.h"/* Berkeley mail routines *//* Driver dispatch used by MAIL */DRIVER bezerkdriver = { "bezerk", /* driver name */ /* driver flags */ DR_LOCAL|DR_MAIL|DR_LOWMEM|DR_CRLF|DR_NOSTICKY, (DRIVER *) NIL, /* next driver */ bezerk_valid, /* mailbox is valid for us */ bezerk_parameters, /* manipulate parameters */ bezerk_scan, /* scan mailboxes */ bezerk_list, /* list mailboxes */ bezerk_lsub, /* list subscribed mailboxes */ NIL, /* subscribe to mailbox */ NIL, /* unsubscribe from mailbox */ bezerk_create, /* create mailbox */ bezerk_delete, /* delete mailbox */ bezerk_rename, /* rename mailbox */ NIL, /* status of mailbox */ bezerk_open, /* open mailbox */ bezerk_close, /* close mailbox */ NIL, /* fetch message "fast" attributes */ NIL, /* fetch message flags */ NIL, /* fetch overview */ NIL, /* fetch message envelopes */ bezerk_header, /* fetch message header */ bezerk_text, /* fetch message text */ 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 */ bezerk_ping, /* ping mailbox to see if still alive */ bezerk_check, /* check for new messages */ bezerk_expunge, /* expunge deleted messages */ bezerk_copy, /* copy messages to another mailbox */ bezerk_append, /* append string message to mailbox */ NIL /* garbage collect stream */}; /* prototype stream */MAILSTREAM bezerkproto = {&bezerkdriver};/* Berkeley mail validate mailbox * Accepts: mailbox name * Returns: our driver if name is valid, NIL otherwise */DRIVER *bezerk_valid (char *name){ char tmp[MAILTMPLEN]; return bezerk_isvalid (name,tmp) ? &bezerkdriver : (DRIVER *) NIL;}/* Berkeley mail test for valid mailbox * Accepts: mailbox name * Returns: T if valid, NIL otherwise */long bezerk_isvalid (char *name,char *tmp){ int fd; long ret = NIL; struct stat sbuf; errno = EINVAL; /* assume invalid argument */ /* if file, get its status */ if ((*name != '{') && mailboxfile (tmp,name) && !stat (tmp,&sbuf)) { if (!sbuf.st_size)errno = 0;/* empty file */ else if ((fd = open (tmp,O_BINARY|O_RDONLY,NIL)) >= 0) { memset (tmp,'\0',MAILTMPLEN); errno = -1; /* in case bezerk_valid_line fails */ if (read (fd,tmp,MAILTMPLEN-1) >= 0) ret = bezerk_valid_line (tmp,NIL,NIL); close (fd); /* close the file */ } } /* in case INBOX but not bezerk format */ else if ((errno == ENOENT) && ((name[0] == 'I') || (name[0] == 'i')) && ((name[1] == 'N') || (name[1] == 'n')) && ((name[2] == 'B') || (name[2] == 'b')) && ((name[3] == 'O') || (name[3] == 'o')) && ((name[4] == 'X') || (name[4] == 'x')) && !name[5]) errno = -1; return ret; /* return what we should */}/* Validate line * Accepts: pointer to candidate string to validate as a From header * return pointer to end of date/time field * return pointer to offset from t of time (hours of ``mmm dd hh:mm'') * return pointer to offset from t of time zone (if non-zero) * Returns: t,ti,zn set if valid From string, else ti is NIL */int bezerk_valid_line (char *s,char **rx,int *rzn){ char *x; int zn; int ti = 0; /* line must begin with "From " */ if ((*s != 'F') || (s[1] != 'r') || (s[2] != 'o') || (s[3] != 'm') || (s[4] != ' ')) return NIL; /* find end of line */ for (x = s + 5; *x && *x != '\012'; x++); if (!x) return NIL; /* end of line not found */ if (x[-1] == '\015') x--; /* ignore CR */ if ((x - s < 27)) return NIL; /* line too short */ if (x - s >= 41) { /* possible search for " remote from " */ for (zn = -1; x[zn] != ' '; zn--); if ((x[zn-1] == 'm') && (x[zn-2] == 'o') && (x[zn-3] == 'r') && (x[zn-4] == 'f') && (x[zn-5] == ' ') && (x[zn-6] == 'e') && (x[zn-7] == 't') && (x[zn-8] == 'o') && (x[zn-9] == 'm') && (x[zn-10] == 'e') && (x[zn-11] == 'r') && (x[zn-12] == ' ')) x += zn - 12; } if (x[-5] == ' ') { /* ends with year? */ /* no timezone? */ if (x[-8] == ':') zn = 0,ti = -5; /* three letter timezone? */ else if (x[-9] == ' ') ti = zn = -9; /* numeric timezone? */ else if ((x[-11]==' ') && ((x[-10]=='+') || (x[-10]=='-'))) ti = zn = -11; } else if (x[-4] == ' ') { /* no year and three leter timezone? */ if (x[-9] == ' ') zn = -4,ti = -9; } else if (x[-6] == ' ') { /* no year and numeric timezone? */ if ((x[-11] == ' ') && ((x[-5] == '+') || (x[-5] == '-'))) zn = -6,ti = -11; } /* time must be www mmm dd hh:mm[:ss] */ if (ti && !((x[ti - 3] == ':') && (x[ti -= ((x[ti - 6] == ':') ? 9 : 6)] == ' ') && (x[ti - 3] == ' ') && (x[ti - 7] == ' ') && (x[ti - 11] == ' '))) return NIL; if (rx) *rx = x; /* set return values */ if (rzn) *rzn = zn; return ti;}/* Berkeley manipulate driver parameters * Accepts: function code * function-dependent value * Returns: function-dependent return value */void *bezerk_parameters (long function,void *value){ return NIL;}/* Berkeley mail scan mailboxes * Accepts: mail stream * reference * pattern to search * string to scan */void bezerk_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents){ if (stream) dummy_scan (NIL,ref,pat,contents);}/* Berkeley mail list mailboxes * Accepts: mail stream * reference * pattern to search */void bezerk_list (MAILSTREAM *stream,char *ref,char *pat){ if (stream) dummy_list (stream,ref,pat);}/* Berkeley mail list subscribed mailboxes * Accepts: mail stream * reference * pattern to search */void bezerk_lsub (MAILSTREAM *stream,char *ref,char *pat){ if (stream) dummy_lsub (stream,ref,pat);}/* Berkeley mail create mailbox * Accepts: MAIL stream * mailbox name to create * Returns: T on success, NIL on failure */long bezerk_create (MAILSTREAM *stream,char *mailbox){ return dummy_create (stream,mailbox);}/* Berkeley mail delete mailbox * Accepts: MAIL stream * mailbox name to delete * Returns: T on success, NIL on failure */long bezerk_delete (MAILSTREAM *stream,char *mailbox){ return dummy_delete (stream,mailbox);}/* Berkeley mail rename mailbox * Accepts: MAIL stream * old mailbox name * new mailbox name (or NIL for delete) * Returns: T on success, NIL on failure */long bezerk_rename (MAILSTREAM *stream,char *old,char *newname){ return dummy_rename (stream,old,newname);}/* Berkeley mail open * Accepts: stream to open * Returns: stream on success, NIL on failure */MAILSTREAM *bezerk_open (MAILSTREAM *stream){ long i; int fd; char *s; char tmp[MAILTMPLEN]; /* return prototype for OP_PROTOTYPE call */ if (!stream) return &bezerkproto; if (stream->local) fatal ("bezerk recycle stream"); if (!mailboxfile (tmp,stream->mailbox)) return (MAILSTREAM *) bezerk_badname (tmp,stream->mailbox); if (((fd = open (tmp,O_BINARY|O_RDONLY,NIL)) < 0)) { sprintf (tmp,"Can't open mailbox: %s",strerror (errno)); mm_log (tmp,ERROR); return NIL; } stream->rdonly = T; /* this driver is readonly */ stream->local = fs_get (sizeof (BEZERKLOCAL)); /* canonicalize the stream mailbox name */ fs_give ((void **) &stream->mailbox); if (s = strchr ((s = strrchr (tmp,'\\')) ? s : tmp,'.')) *s = '\0'; stream->mailbox = cpystr (tmp); LOCAL->fd = fd; /* note the file */ LOCAL->filesize = 0; /* initialize parsed file size */ LOCAL->buf = NIL; /* initially no local buffer */ stream->sequence++; /* bump sequence number */ stream->uid_validity = time (0); /* parse mailbox */ stream->nmsgs = stream->recent = 0; if (!bezerk_ping (stream)) return NIL; if (!stream->nmsgs) mm_log ("Mailbox is empty",(long) NIL); stream->perm_seen = stream->perm_deleted = stream->perm_flagged = stream->perm_answered = stream->perm_draft = NIL; stream->perm_user_flags = NIL; return stream; /* return stream to caller */}/* Berkeley mail close * Accepts: MAIL stream * close options */void bezerk_close (MAILSTREAM *stream,long options){ if (stream && LOCAL) { /* only if a file is open */ int silent = stream->silent; stream->silent = T; if (options & CL_EXPUNGE) bezerk_expunge (stream); close (LOCAL->fd); /* close the local file */ if (LOCAL->buf) fs_give ((void **) &LOCAL->buf); /* nuke the local data */ fs_give ((void **) &stream->local); stream->dtb = NIL; /* log out the DTB */ }}/* Berkeley mail fetch message header * Accepts: MAIL stream * message # to fetch * pointer to returned header text length * option flags * Returns: message header in RFC822 format */char *bezerk_header (MAILSTREAM *stream,unsigned long msgno, unsigned long *length,long flags){ char tmp[MAILTMPLEN]; *length = 0; /* default to empty */ if (flags & FT_UID) return "";/* UID call "impossible" */ /* get to header position */ lseek (LOCAL->fd,bezerk_hdrpos (stream,msgno,length),L_SET); /* is buffer big enough? */ if (LOCAL->buf) fs_give ((void **) &LOCAL->buf); LOCAL->buf = (char *) fs_get ((size_t) *length + 1); LOCAL->buf[*length] = '\0'; /* tie off string */ /* slurp the data */ read (LOCAL->fd,LOCAL->buf,(size_t) *length); return LOCAL->buf;}/* Berkeley mail fetch message text (body only) * Accepts: MAIL stream * message # to fetch * pointer to returned header text length * option flags * Returns: T, always */long bezerk_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags){ MESSAGECACHE *elt; FDDATA d; unsigned long hdrsize,hdrpos; /* UID call "impossible" */ if (flags & FT_UID) return NIL; elt = mail_elt (stream,msgno);/* if message not seen */ /* mark message as seen */ if (elt->seen && !(flags & FT_PEEK)) { elt->seen = T; mm_flags (stream,msgno); } /* get location of text data */ hdrpos = bezerk_hdrpos (stream,msgno,&hdrsize); d.fd = LOCAL->fd; /* set initial stringstruct */ d.pos = hdrpos + hdrsize; /* flush old buffer */ if (LOCAL->buf) fs_give ((void **) &LOCAL->buf); d.chunk = LOCAL->buf = (char *) fs_get ((size_t) d.chunksize = CHUNK); INIT (bs,fd_string,(void *) &d,elt->rfc822_size - hdrsize); return T; /* success */}/* Berkeley mail ping mailbox * Accepts: MAIL stream * Returns: T if stream still alive, NIL if not */long bezerk_ping (MAILSTREAM *stream){ /* punt if stream no longer alive */ if (!(stream && LOCAL)) return NIL; /* parse mailbox, punt if parse dies */ return (bezerk_parse (stream)) ? T : NIL;}/* Berkeley mail check mailbox (reparses status too) * Accepts: MAIL stream */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -