📄 imapd.c
字号:
PSOUT (")\015\012"); } } else { /* driver changed */ 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; } } } } } if (shutdowntime && (time (0) > shutdowntime + SHUTDOWNTIMER)) { PSOUT ("* BYE Server shutting down\015\012"); state = LOGOUT; } /* don't do these stat()s every cycle */ else if (time (0) > alerttime + ALERTTIMER) { struct stat sbuf; /* have a shutdown file? */ if (!stat (SHUTDOWNFILE,&sbuf)) { PSOUT ("* OK [ALERT] Server shutting down shortly\015\012"); shutdowntime = time (0); } 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 */#if 0 s->size = size; /* message size */ s->curpos = s->chunk = /* load header */ mail_fetchheader_full (md->stream,md->msgno,NIL,&s->data1, FT_PREFETCHTEXT | FT_PEEK);#else /* This kludge is necessary because of broken mail stores */ mail_fetchtext_full (md->stream,md->msgno,&s->size,FT_PEEK); s->curpos = s->chunk = /* load header */ mail_fetchheader_full (md->stream,md->msgno,NIL,&s->data1,FT_PEEK); s->size += s->data1; /* header + body size */#endif s->cursize = s->chunksize = s->data1; s->offset = 0; /* offset is start of message */}/* 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 (' '); nflags = i + 1; } 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");}/* Set timeout * Accepts: desired interval */void settimeout (unsigned int i){ /* limit if not logged in */ if (i) alarm ((state == LOGIN) ? LOGINTIMEOUT : i); else alarm (0);}/* Clock interrupt * Returns only if critical code in progress */void clkint (void){ settimeout (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); logout = "Autologout"; goodbye = "Autologout (idle for too long)"; if (critical) { /* must defer if in critical code(?) */ close (0); /* kill stdin */ state = LOGOUT; /* die as soon as we can */ } else longjmp (jmpenv,1); /* die now */}/* Kiss Of Death interrupt * Returns only if critical code in progress */void kodint (void){ settimeout (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); logout = goodbye = "Killed (lost mailbox lock)"; if (critical) { /* must defer if in critical code */ close (0); /* kill stdin */ state = LOGOUT; /* die as soon as we can */ } else longjmp (jmpenv,1); /* die now */}/* Hangup interrupt * Returns only if critical code in progress */void hupint (void){ settimeout (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); logout = "Hangup"; goodbye = NIL; /* other end is already gone */ if (critical) { /* must defer if in critical code */ close (0); /* kill stdin */ close (1); /* and stdout */ state = LOGOUT; /* die as soon as we can */ } else longjmp (jmpenv,1); /* die now */}/* Termination interrupt * Returns only if critical code in progress */void trmint (void){ settimeout (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); logout = goodbye = "Killed (terminated)"; /* Make no attempt at graceful closure since a shutdown may be in * progress, and we won't have any time to do mail_close() actions */ stream = NIL; if (critical) { /* must defer if in critical code */ close (0); /* kill stdin */ close (1); /* and stdout */ state = LOGOUT; /* die as soon as we can */ } else longjmp (jmpenv,1); /* die now */}/* The routines on this and the next page eschew the use of non-syscall libc * routines (especially stdio) for a reason. Also, these hideous #if * condtionals need to be replaced. */#ifndef unix#define unix 0#endif/* Status request interrupt * Always returns */void staint (void){#if unix int fd; char *s,buf[8*MAILTMPLEN]; unsigned long pid = getpid (); /* build file name */ s = nout (sout (buf,"/tmp/imapd-status."),pid,10); if (user) s = sout (sout (s,"."),user); *s = '\0'; /* tie off file name */ if ((fd = open (buf,O_WRONLY | O_CREAT | O_TRUNC,0666)) >= 0) { fchmod (fd,0666); s = nout (sout (buf,"PID="),pid,10); if (user) s = sout (sout (s,", user="),user); switch (state) { case LOGIN: s = sout (s,", not logged in"); break; case SELECT: s = sout (s,", logged in"); break; case OPEN: s = sout (s,", mailbox open"); break; case LOGOUT: s = sout (s,", logging out"); break; } if (stream && stream->mailbox) s = sout (sout (s,"\nmailbox="),stream->mailbox); *s++ = '\n'; if (status) { s = sout (s,status); if (cmd) s = sout (sout (s,", last command="),cmd); } else s = sout (sout (s,cmd)," in progress"); *s++ = '\n'; write (fd,buf,s-buf); close (fd); }#endif}/* Write string * Accepts: destination string pointer * string * Returns: updated string pointer */char *sout (char *s,char *t){ while (*t) *s++ = *t++; return s;}/* Write number * Accepts: destination string pointer * number * base * Returns: updated string pointer */char *nout (char *s,unsigned long n,unsigned long base){ char stack[256]; char *t = stack; /* push PID digits on stack */ do *t++ = (char) (n % base) + '0'; while (n /= base); /* pop digits from stack */ while (t > stack) *s++ = *--t; return s;}/* Slurp a command line * Accepts: buffer pointer * buffer size * input timeout */void slurp (char *s,int n,unsigned long timeout){ memset (s,'\0',n); /* zap buffer */ if (state != LOGOUT) { /* get a command under timeout */ settimeout (timeout); clearerr (stdin); /* clear stdin errors */ status = "reading line"; if (!PSIN (s,n-1)) ioerror (stdin,status); settimeout (0); /* make sure timeout disabled */ status = NIL; }}/* Read a literal * Accepts: destination buffer (must be size+1 for trailing NUL) * size of buffer (must be less than 4294967295) */void inliteral (char *s,unsigned long n){ unsigned long i; if (litplus.ok) { /* no more LITERAL+ to worry about */ litplus.ok = NIL; litplus.size = 0; } else { /* otherwise tell client ready for argument */ PSOUT ("+ Ready for argument\015\012"); PFLUSH (); /* dump output buffer */ } clearerr (stdin); /* clear stdin errors */ memset (s,'\0',n+1); /* zap buffer */ status
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -