📄 imapd.c
字号:
"Fatal mailbox error user=%.80s host=%.80s mbx=%.80s: %.80s", user ? user : "???",tcp_clienthost (), (stream && stream->mailbox) ? stream->mailbox : "???", lasterror ()); return; } /* change in number of messages? */ if (existsquelled || (nmsgs != stream->nmsgs)) { PSOUT ("* "); pnum (nmsgs = stream->nmsgs); PSOUT (" EXISTS\015\012"); } /* change in recent messages? */ if (existsquelled || (recent != stream->recent)) { PSOUT ("* "); pnum (recent = stream->recent); PSOUT (" RECENT\015\012"); } existsquelled = NIL; /* don't do this until asked again */ /* don't bother if driver changed */ if (curdriver == stream->dtb) { for (i = 1; i <= nmsgs; i++) if (mail_elt (stream,i)->spare2) { PSOUT ("* "); pnum (i); PSOUT (" FETCH ("); fetch_flags (i,NIL); /* output changed flags */ if (uid) { /* need to include UIDs in response? */ PBOUT (' '); fetch_uid (i,NIL); } PSOUT (")\015\012"); } } else { /* driver changed */ PSOUT ("* OK [UIDVALIDITY "); pnum (stream->uid_validity); PSOUT ("] UID validity status\015\012* OK [UIDNEXT "); pnum (stream->uid_last + 1); PSOUT ("] Predicted next UID\015\012"); if (stream->uid_nosticky) { PSOUT ("* NO [UIDNOTSTICKY] Non-permanent unique identifiers: "); PSOUT (stream->mailbox); CRLF; } new_flags (stream); /* send mailbox flags */ if (curdriver) { /* note readonly/write if possible change */ PSOUT ("* OK [READ-"); PSOUT (stream->rdonly ? "ONLY" : "WRITE"); PSOUT ("] Mailbox status\015\012"); } curdriver = stream->dtb; if (nmsgs) { /* get flags for all messages */ sprintf (tmp,"1:%lu",nmsgs); mail_fetch_flags (stream,tmp,NIL); /* don't do this if newsrc already did */ if (!(curdriver->flags & DR_NEWS)) { /* find first unseen message */ for (i = 1; i <= nmsgs && mail_elt (stream,i)->seen; i++); if (i <= nmsgs) { PSOUT ("* OK [UNSEEN "); pnum (i); PSOUT ("] first unseen message in "); PSOUT (stream->mailbox); CRLF; } } } } } /* don't do these stat()s every cycle */ if (time (0) > alerttime + ALERTTIMER) { alerttime = time (0); /* output any new alerts */ sysalerttime = palert (ALERTFILE,sysalerttime); if (state != LOGIN) /* do user alert if logged in */ useralerttime = palert (mailboxfile (tmp,USERALERTFILE),useralerttime); }}/* Print an alert file * Accepts: path of alert file * time of last printed alert file * Returns: updated time of last printed alert file */time_t palert (char *file,time_t oldtime){ FILE *alf; struct stat sbuf; int c,lc = '\012'; /* have a new alert file? */ if (stat (file,&sbuf) || (sbuf.st_mtime <= oldtime) || !(alf = fopen (file,"r"))) return oldtime; /* yes, display it */ while ((c = getc (alf)) != EOF) { if (lc == '\012') PSOUT ("* OK [ALERT] "); switch (c) { /* output character */ case '\012': /* newline means do CRLF */ CRLF; case '\015': /* flush CRs */ case '\0': /* flush nulls */ break; default: PBOUT (c); /* output all other characters */ break; } lc = c; /* note previous character */ } fclose (alf); if (lc != '\012') CRLF; /* final terminating CRLF */ return sbuf.st_mtime; /* return updated last alert time */}/* Initialize file string structure for file stringstruct * Accepts: string structure * pointer to message data structure * size of string */void msg_string_init (STRING *s,void *data,unsigned long size){ MSGDATA *md = (MSGDATA *) data; s->data = data; /* note stream/msgno and header length */ mail_fetchheader_full (md->stream,md->msgno,NIL,&s->data1, FT_PREFETCHTEXT | FT_PEEK);#if 0 s->size = size; /* message size */#else /* This kludge is necessary because of broken IMAP servers (sigh!) */ mail_fetchtext_full (md->stream,md->msgno,&s->size,FT_PEEK); s->size += s->data1; /* header + body size */#endif SETPOS (s,0);}/* Get next character from file stringstruct * Accepts: string structure * Returns: character, string structure chunk refreshed */char msg_string_next (STRING *s){ char c = *s->curpos++; /* get next byte */ SETPOS (s,GETPOS (s)); /* move to next chunk */ return c; /* return the byte */}/* Set string pointer position for file stringstruct * Accepts: string structure * new position */void msg_string_setpos (STRING *s,unsigned long i){ MSGDATA *md = (MSGDATA *) s->data; if (i < s->data1) { /* want header? */ s->chunk = mail_fetchheader_full (md->stream,md->msgno,NIL,NIL,FT_PEEK); s->chunksize = s->data1; /* header length */ s->offset = 0; /* offset is start of message */ } else if (i < s->size) { /* want body */ s->chunk = mail_fetchtext_full (md->stream,md->msgno,NIL,FT_PEEK); s->chunksize = s->size - s->data1; s->offset = s->data1; /* offset is end of header */ } else { /* off end of message */ s->chunk = NIL; /* make sure that we crack on this then */ s->chunksize = 1; /* make sure SNX cracks the right way... */ s->offset = i; } /* initial position and size */ s->curpos = s->chunk + (i -= s->offset); s->cursize = s->chunksize - i;}/* Send flags for stream * Accepts: MAIL stream * scratch buffer */void new_flags (MAILSTREAM *stream){ int i,c; PSOUT ("* FLAGS ("); for (i = 0; i < NUSERFLAGS; i++) if (stream->user_flags[i]) { PSOUT (stream->user_flags[i]); PBOUT (' '); } PSOUT ("\\Answered \\Flagged \\Deleted \\Draft \\Seen)\015\012* OK [PERMANENTFLAGS ("); for (i = c = 0; i < NUSERFLAGS; i++) if ((stream->perm_user_flags & (1 << i)) && stream->user_flags[i]) put_flag (&c,stream->user_flags[i]); if (stream->kwd_create) put_flag (&c,"\\*"); if (stream->perm_answered) put_flag (&c,"\\Answered"); if (stream->perm_flagged) put_flag (&c,"\\Flagged"); if (stream->perm_deleted) put_flag (&c,"\\Deleted"); if (stream->perm_draft) put_flag (&c,"\\Draft"); if (stream->perm_seen) put_flag (&c,"\\Seen"); PSOUT (")] Permanent flags\015\012");}/* Clock interrupt */void clkint (void){ alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); if (!quell_events) PSOUT ("* BYE Autologout; idle for too long\015\012"); syslog (LOG_INFO,"Autologout user=%.80s host=%.80s",user ? user : "???", tcp_clienthost ()); PFLUSH; /* make sure output blatted */ if (critical) state = LOGOUT; /* badly hosed if in critical code */ else { /* try to gracefully close the stream */ if ((state == OPEN) && !stream->lock) mail_close (stream); state = LOGOUT; stream = NIL; _exit (1); /* die die die */ }}/* Kiss Of Death interrupt */void kodint (void){ alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); if (!quell_events) PSOUT ("* BYE Lost mailbox lock\015\012"); PFLUSH; /* make sure output blatted */ syslog (LOG_INFO,"Killed (lost mailbox lock) user=%.80s host=%.80s", user ? user : "???",tcp_clienthost ()); if (critical) state = LOGOUT; /* must defer if in critical code */ else { /* try to gracefully close the stream */ if ((state == OPEN) && !stream->lock) mail_close (stream); state = LOGOUT; stream = NIL; _exit (1); /* die die die */ }}/* Hangup interrupt */void hupint (void){ alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); syslog (LOG_INFO,"Hangup user=%.80s host=%.80s",user ? user : "???", tcp_clienthost ()); if (critical) state = LOGOUT; /* must defer if in critical code */ else { /* try to gracefully close the stream */ if ((state == OPEN) && !stream->lock) mail_close (stream); state = LOGOUT; stream = NIL; _exit (1); /* die die die */ }}/* Termination interrupt */void trmint (void){ alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); if (!quell_events) PSOUT ("* BYE Killed\015\012"); syslog (LOG_INFO,"Killed user=%.80s host=%.80s",user ? user : "???", tcp_clienthost ()); if (critical) state = LOGOUT; /* must defer if in critical code */ else { /* try to gracefully close the stream */ if ((state == OPEN) && !stream->lock) mail_close (stream); state = LOGOUT; stream = NIL; _exit (1); /* die die die */ }}/* Slurp a command line * Accepts: buffer pointer * buffer size */void slurp (char *s,int n){ s[--n] = '\0'; /* last buffer character is guaranteed NUL */ /* get a command under timeout */ alarm ((state != LOGIN) ? TIMEOUT : LOGINTIMEOUT); clearerr (stdin); /* clear stdin errors */ while (!PSIN (s,n)) { /* read buffer */ /* ignore if some interrupt */ if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); else { char *e = ferror (stdin) ? strerror (errno) : "Command stream end of file"; alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); syslog (LOG_INFO,"%.80s, while reading line user=%.80s host=%.80s", e,user ? user : "???",tcp_clienthost ()); /* try to gracefully close the stream */ if (state == OPEN) mail_close (stream); state = LOGOUT; stream = NIL; _exit (1); } } alarm (0); /* make sure timeout disabled */}/* Read a character * Returns: character */char inchar (void){ int c; clearerr (stdin); /* clear stdin errors */ while ((c = PBIN ()) == EOF) { /* ignore if some interrupt */ if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); else { char *e = ferror (stdin) ? strerror (errno) : "Command stream end of file"; alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); syslog (LOG_INFO,"%.80s, while reading char user=%.80s host=%.80s", e,user ? user : "???",tcp_clienthost ()); /* try to gracefully close the stream */ if (state == OPEN) mail_close (stream); state = LOGOUT; stream = NIL; _exit (1); } } return c;}/* Flush until newline seen * Returns: NIL, always */char *flush (void){ while (inchar () != '\012'); /* slurp until we find newline */ response = "%.80s BAD Command line too long\015\012"; return NIL;}/* Parse an IMAP astring * Accepts: pointer to argument text pointer * pointer to returned size * pointer to returned delimiter * Returns: argument */char *parse_astring (char **arg,unsigned long *size,char *del){ unsigned long i; char c,*s,*t,*v; if (!*arg) return NIL; /* better be an argument */ switch (**arg) { /* see what the argument is */ default: /* atom */ for (s = t = *arg, i = 0; (*t > ' ') && (*t < 0x7f) && (*t != '(') && (*t != ')') && (*t != '{') && (*t != '%') && (*t != '*') && (*t != '"') && (*t != '\\'); ++t,++i); if (*size = i) break; /* got atom if non-empty */ case ')': case '%': case '*': case '\\': case '\0': case ' ': return NIL; /* empty atom is a bogon */ case '"': /* hunt for trailing quote */ for (s = t = v = *arg + 1; (c = *t++) != '"'; *v++ = c) { if (c == '\\') c = *t++; /* quote next character */ /* else must be a CHAR */ if (!c || (c & 0x80)) return NIL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -