📄 client
字号:
} } /* see if special driver hack */ if (!strncmp (tmp,"#driver.",8)) { /* tie off name at likely delimiter */ if (s = strpbrk (tmp+8,"/\\:")) *s++ = '\0'; else { sprintf (tmp,"Can't create mailbox %.80s: bad driver syntax",mailbox); mm_log (tmp,ERROR); return NIL; } for (d = maildrivers; d && strcmp (d->name,tmp+8); d = d->next); if (d) mailbox += s - tmp; /* skip past driver specification */ else { sprintf (tmp,"Can't create mailbox %.80s: unknown driver",mailbox); mm_log (tmp,ERROR); return NIL; } } /* use stream if one given or deterministic */ else if ((stream && stream->dtb) || (((*mailbox == '{') || (*mailbox == '#')) && (stream = mail_open (NIL,mailbox,OP_PROTOTYPE | OP_SILENT)))) d = stream->dtb; else if ((*mailbox != '{') && (ts = default_proto (NIL))) d = ts->dtb; else { /* failed utterly */ sprintf (tmp,"Can't create mailbox %.80s: indeterminate format",mailbox); mm_log (tmp,ERROR); return NIL; } return (*d->create) (stream,mailbox);}/* Mail delete mailbox * Accepts: mail stream * mailbox name to delete * Returns: T on success, NIL on failure */long mail_delete (MAILSTREAM *stream,char *mailbox){ long ret = NIL; DRIVER *dtb = mail_valid (stream,mailbox,"delete mailbox"); if (((mailbox[0] == 'I') || (mailbox[0] == 'i')) && ((mailbox[1] == 'N') || (mailbox[1] == 'n')) && ((mailbox[2] == 'B') || (mailbox[2] == 'b')) && ((mailbox[3] == 'O') || (mailbox[3] == 'o')) && ((mailbox[4] == 'X') || (mailbox[4] == 'x')) && !mailbox[5]) { mm_log ("Can't delete INBOX",ERROR); } else SAFE_DISPATCH (dtb,ret,mbxdel,(stream,mailbox)) return ret;}/* Mail rename mailbox * Accepts: mail stream * old mailbox name * new mailbox name * Returns: T on success, NIL on failure */long mail_rename (MAILSTREAM *stream,char *old,char *newname){ long ret = NIL; char tmp[MAILTMPLEN]; DRIVER *dtb = mail_valid (stream,old,"rename mailbox"); if ((*old != '{') && (*old != '#') && mail_valid (NIL,newname,NIL)) { sprintf (tmp,"Can't rename to mailbox %.80s: mailbox already exists", newname); mm_log (tmp,ERROR); } else SAFE_DISPATCH (dtb,ret,mbxren,(stream,old,newname)) return ret;}/* Mail status of mailbox * Accepts: mail stream * mailbox name * status flags * Returns: T on success, NIL on failure */long mail_status (MAILSTREAM *stream,char *mbx,long flags){ long ret = NIL; DRIVER *factory = mail_valid (stream,mbx,"get status of mailbox"); if (factory) { /* use driver's routine if have one */ if (factory->status) return (*factory->status) (stream,mbx,flags); /* foolish status of selected mbx? */ if (stream && !strcmp (mbx,stream->mailbox)) ret = mail_status_default (stream,mbx,flags); else SAFE_FUNCTION (factory,ret,mail_status_default,(stream,mbx,flags)) } return ret;}/* Mail status of mailbox default handler * Accepts: mail stream * mailbox name * status flags * Returns: T on success, NIL on failure */long mail_status_default (MAILSTREAM *stream,char *mbx,long flags){ MAILSTATUS status; unsigned long i; MAILSTREAM *tstream = NIL; /* make temporary stream (unless this mbx) */ if ((!stream || strcmp (mbx,stream->mailbox)) && !(stream = tstream = mail_open (NIL,mbx,OP_READONLY|OP_SILENT))) return NIL; status.flags = flags; /* return status values */ status.messages = stream->nmsgs; status.recent = stream->recent; if (flags & SA_UNSEEN) /* must search to get unseen messages */ for (i = 1,status.unseen = 0; i <= stream->nmsgs; i++) if (!mail_elt (stream,i)->seen) status.unseen++; status.uidnext = stream->uid_last + 1; status.uidvalidity = stream->uid_validity; /* pass status to main program */ mm_status (stream,mbx,&status); if (tstream) mail_close (tstream); return T; /* success */}/* Mail open * Accepts: candidate stream for recycling * mailbox name * open options * Returns: stream to use on success, NIL on failure */MAILSTREAM *mail_open (MAILSTREAM *stream,char *name,long options){ int i; char *s,tmp[MAILTMPLEN]; NETMBX mb; DRIVER *d; /* see if special driver hack */ if ((options & OP_PROTOTYPE) && (name[0] == '#') && ((name[1] == 'D') || (name[1] == 'd')) && ((name[2] == 'R') || (name[2] == 'r')) && ((name[3] == 'I') || (name[3] == 'i')) && ((name[4] == 'V') || (name[4] == 'v')) && ((name[5] == 'E') || (name[5] == 'e')) && ((name[6] == 'R') || (name[6] == 'r')) && (name[7] == '.')) { sprintf (tmp,"%.80s",name+8); /* tie off name at likely delimiter */ if (s = strpbrk (lcase (tmp),"/\\:")) *s++ = '\0'; else { sprintf (tmp,"Can't resolve mailbox %.80s: bad driver syntax",name); mm_log (tmp,ERROR); return NIL; } for (d = maildrivers; d && strcmp (d->name,tmp); d = d->next); if (d) return (*d->open) (NIL); else { sprintf (tmp,"Can't resolve mailbox %.80s: unknown driver",name); mm_log (tmp,ERROR); return NIL; } } else d = mail_valid (NIL,name,(options & OP_SILENT) ? (char *) NIL : "open mailbox"); if (d) { /* must have a factory */ if (options & OP_PROTOTYPE) return (*d->open) (NIL); if (stream) { /* recycling requested? */ /* yes, recycleable stream? */ if ((stream->dtb == d) && (d->flags & DR_RECYCLE) && mail_usable_network_stream (stream,name)) { mail_free_cache(stream);/* yes, clean up stream */ if (stream->mailbox) fs_give ((void **) &stream->mailbox); /* flush user flags */ for (i = 0; i < NUSERFLAGS; i++) if (stream->user_flags[i]) fs_give ((void **)&stream->user_flags[i]); } else { /* stream not recycleable, babble if net */ if (!stream->silent && stream->dtb && !(stream->dtb->flags&DR_LOCAL) && mail_valid_net_parse (stream->mailbox,&mb)) { sprintf (tmp,"Closing connection to %.80s",mb.host); mm_log (tmp,(long) NIL); } /* flush the old stream */ stream = mail_close (stream); } } /* instantiate new stream if not recycling */ if (!stream) (*mailcache) (stream = (MAILSTREAM *) memset (fs_get (sizeof (MAILSTREAM)),0, sizeof (MAILSTREAM)),(long) 0,CH_INIT); stream->dtb = d; /* set dispatch */ /* set mailbox name */ stream->mailbox = cpystr (name); /* initialize stream flags */ stream->inbox = stream->lock = NIL; stream->debug = (options & OP_DEBUG) ? T : NIL; stream->rdonly = (options & OP_READONLY) ? T : NIL; stream->anonymous = (options & OP_ANONYMOUS) ? T : NIL; stream->scache = (options & OP_SHORTCACHE) ? T : NIL; stream->silent = (options & OP_SILENT) ? T : NIL; stream->halfopen = (options & OP_HALFOPEN) ? T : NIL; stream->secure = (options & OP_SECURE) ? T : NIL; stream->tryalt = (options & OP_TRYALT) ? T : NIL; stream->mulnewsrc = (options & OP_MULNEWSRC) ? T : NIL; stream->perm_seen = stream->perm_deleted = stream->perm_flagged = stream->perm_answered = stream->perm_draft = stream->kwd_create = NIL; stream->uid_nosticky = (d->flags & DR_NOSTICKY) ? T : NIL; stream->uid_last = 0; /* default UID validity */ stream->uid_validity = time (0); /* have driver open, flush if failed */ if (!(*d->open) (stream)) stream = mail_close (stream); } return stream; /* return the stream */}/* Mail close * Accepts: mail stream * close options * Returns: NIL, always */MAILSTREAM *mail_close_full (MAILSTREAM *stream,long options){ int i; if (stream) { /* make sure argument given */ /* do the driver's close action */ if (stream->dtb) (*stream->dtb->close) (stream,options); if (stream->mailbox) fs_give ((void **) &stream->mailbox); stream->sequence++; /* invalidate sequence */ /* flush user flags */ for (i = 0; i < NUSERFLAGS; i++) if (stream->user_flags[i]) fs_give ((void **) &stream->user_flags[i]); mail_free_cache (stream); /* finally free the stream's storage */ if (!stream->use) fs_give ((void **) &stream); } return NIL;}/* Mail make handle * Accepts: mail stream * Returns: handle * * Handles provide a way to have multiple pointers to a stream yet allow the * stream's owner to nuke it or recycle it. */MAILHANDLE *mail_makehandle (MAILSTREAM *stream){ MAILHANDLE *handle = (MAILHANDLE *) fs_get (sizeof (MAILHANDLE)); handle->stream = stream; /* copy stream */ /* and its sequence */ handle->sequence = stream->sequence; stream->use++; /* let stream know another handle exists */ return handle;}/* Mail release handle * Accepts: Mail handle */void mail_free_handle (MAILHANDLE **handle){ MAILSTREAM *s; if (*handle) { /* only free if exists */ /* resign stream, flush unreferenced zombies */ if ((!--(s = (*handle)->stream)->use) && !s->dtb) fs_give ((void **) &s); fs_give ((void **) handle); /* now flush the handle */ }}/* Mail get stream handle * Accepts: Mail handle * Returns: mail stream or NIL if stream gone */MAILSTREAM *mail_stream (MAILHANDLE *handle){ MAILSTREAM *s = handle->stream; return (s->dtb && (handle->sequence == s->sequence)) ? s : NIL;}/* Mail fetch cache element * Accepts: mail stream * message # to fetch * Returns: cache element of this message * Can also be used to create cache elements for new messages. */MESSAGECACHE *mail_elt (MAILSTREAM *stream,unsigned long msgno){ if (msgno < 1 || msgno > stream->nmsgs) { char tmp[MAILTMPLEN]; sprintf (tmp,"Bad msgno %lu in mail_elt, nmsgs = %lu",msgno,stream->nmsgs); fatal (tmp); } return (MESSAGECACHE *) (*mailcache) (stream,msgno,CH_MAKEELT);}/* Mail fetch fast information * Accepts: mail stream * sequence * option flags * * Generally, mail_fetch_structure is preferred */void mail_fetch_fast (MAILSTREAM *stream,char *sequence,long flags){ /* do the driver's action */ if (stream->dtb && stream->dtb->fast) (*stream->dtb->fast) (stream,sequence,flags);}/* Mail fetch flags * Accepts: mail stream * sequence * option flags */void mail_fetch_flags (MAILSTREAM *stream,char *sequence,long flags){ /* do the driver's action */ if (stream->dtb && stream->dtb->msgflags) (*stream->dtb->msgflags) (stream,sequence,flags);}/* Mail fetch message overview * Accepts: mail stream * UID sequence to fetch * pointer to overview return function */void mail_fetch_overview (MAILSTREAM *stream,char *sequence,overview_t ofn){ if (stream->dtb && !(stream->dtb->overview && (*stream->dtb->overview) (stream,sequence,ofn)) && mail_uid_sequence (stream,sequence) && mail_ping (stream)) { MESSAGECACHE *elt; ENVELOPE *env; OVERVIEW ov; unsigned long i; ov.optional.lines = 0; ov.optional.xref = NIL; for (i = 1; i <= stream->nmsgs; i++) if (((elt = mail_elt (stream,i))->sequence) && (env = mail_fetch_structure (stream,i,NIL,NIL)) && ofn) { ov.subject = env->subject; ov.from = env->from; ov.date = env->date; ov.message_id = env->message_id; ov.references = env->references; ov.optional.octets = elt->rfc822_size; (*ofn) (stream,mail_uid (stream,i),&ov); } }}/* Mail fetch message structure * Accepts: mail stream * message # to fetch * pointer to return body * option flags * Returns: envelope of this message, body returned in body value * * Fetches the "fast" information as well */ENVELOPE *mail_fetch_structure (MAILSTREAM *stream,unsigned long msgno, BODY **body,long flags){ ENVELOPE **env; BODY **b; MESSAGECACHE *elt; char c,*s,*hdr; unsigned long hdrsize; STRING bs; /* do the driver's action if specified */ if (stream->dtb && stream->dtb->structure) return (*stream->dtb->structure) (stream,msgno,body,flags); if (flags & FT_UID) { /* UID form of call */ if (msgno = mail_msgno (stream,msgno)) flags &= ~FT_UID; else return NIL; /* must get UID/msgno map first */ } elt = mail_elt (stream,msgno);/* get elt for real message number */ if (stream->scache) { /* short caching */ if (msgno != stream->msgno){/* garbage collect if not same message */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -