imapext-2007
diff src/ipopd/ipop3d.c @ 0:ada5e610ab86
imap-2007e
author | yuuji@gentei.org |
---|---|
date | Mon, 14 Sep 2009 15:17:45 +0900 |
parents | |
children | 28a55bc1110c |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/ipopd/ipop3d.c Mon Sep 14 15:17:45 2009 +0900 1.3 @@ -0,0 +1,1082 @@ 1.4 +/* ======================================================================== 1.5 + * Copyright 1988-2008 University of Washington 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * 1.14 + * ======================================================================== 1.15 + */ 1.16 + 1.17 +/* 1.18 + * Program: IPOP3D - IMAP to POP3 conversion server 1.19 + * 1.20 + * Author: Mark Crispin 1.21 + * UW Technology 1.22 + * University of Washington 1.23 + * Seattle, WA 98195 1.24 + * Internet: MRC@Washington.EDU 1.25 + * 1.26 + * Date: 1 November 1990 1.27 + * Last Edited: 19 February 2008 1.28 + */ 1.29 + 1.30 +/* Parameter files */ 1.31 + 1.32 +#include <stdio.h> 1.33 +#include <ctype.h> 1.34 +#include <errno.h> 1.35 +extern int errno; /* just in case */ 1.36 +#include <signal.h> 1.37 +#include <time.h> 1.38 +#include "c-client.h" 1.39 + 1.40 + 1.41 +#define CRLF PSOUT ("\015\012") /* primary output terpri */ 1.42 + 1.43 + 1.44 +/* Autologout timer */ 1.45 +#define KODTIMEOUT 60*5 1.46 +#define LOGINTIMEOUT 60*3 1.47 +#define TIMEOUT 60*10 1.48 + 1.49 + 1.50 +/* Server states */ 1.51 + 1.52 +#define AUTHORIZATION 0 1.53 +#define TRANSACTION 1 1.54 +#define UPDATE 2 1.55 +#define LOGOUT 3 1.56 + 1.57 +/* Eudora food */ 1.58 + 1.59 +#define STATUS "Status: %s%s\015\012" 1.60 +#define SLEN (sizeof (STATUS)-3) 1.61 + 1.62 + 1.63 +/* Global storage */ 1.64 + 1.65 +char *version = "104"; /* edit number of this server */ 1.66 +short state = AUTHORIZATION; /* server state */ 1.67 +short critical = NIL; /* non-zero if in critical code */ 1.68 +MAILSTREAM *stream = NIL; /* mailbox stream */ 1.69 +time_t idletime = 0; /* time we went idle */ 1.70 +unsigned long nmsgs = 0; /* current number of messages */ 1.71 +unsigned long ndele = 0; /* number of deletes */ 1.72 +unsigned long nseen = 0; /* number of mark-seens */ 1.73 +unsigned long last = 0; /* highest message accessed */ 1.74 +unsigned long il = 0; /* initial last message */ 1.75 +char challenge[128]; /* challenge */ 1.76 +char *host = NIL; /* remote host name */ 1.77 +char *user = NIL; /* user name */ 1.78 +char *pass = NIL; /* password */ 1.79 +char *initial = NIL; /* initial response */ 1.80 +long *msg = NIL; /* message translation vector */ 1.81 +short *flags = NIL; /* flags */ 1.82 +char *logout = "Logout"; 1.83 +char *goodbye = "+OK Sayonara\015\012"; 1.84 + 1.85 + 1.86 +/* POP3 flags */ 1.87 + 1.88 +#define DELE 0x1 1.89 +#define SEEN 0x2 1.90 + 1.91 + 1.92 +/* Function prototypes */ 1.93 + 1.94 +int main (int argc,char *argv[]); 1.95 +void sayonara (int status); 1.96 +void clkint (); 1.97 +void kodint (); 1.98 +void hupint (); 1.99 +void trmint (); 1.100 +int pass_login (char *t,int argc,char *argv[]); 1.101 +char *apop_login (char *chal,char *user,char *md5,int argc,char *argv[]); 1.102 +char *responder (void *challenge,unsigned long clen,unsigned long *rlen); 1.103 +int mbxopen (char *mailbox); 1.104 +long blat (char *text,long lines,unsigned long size,STRING *st); 1.105 +void rset (); 1.106 + 1.107 +/* Main program */ 1.108 + 1.109 +int main (int argc,char *argv[]) 1.110 +{ 1.111 + unsigned long i,j,k; 1.112 + char *s,*t; 1.113 + char tmp[MAILTMPLEN]; 1.114 + time_t autologouttime; 1.115 + char *pgmname = (argc && argv[0]) ? 1.116 + (((s = strrchr (argv[0],'/')) || (s = strrchr (argv[0],'\\'))) ? 1.117 + s+1 : argv[0]) : "ipop3d"; 1.118 + /* set service name before linkage */ 1.119 + mail_parameters (NIL,SET_SERVICENAME,(void *) "pop"); 1.120 +#include "linkage.c" 1.121 + /* initialize server */ 1.122 + server_init (pgmname,"pop3","pop3s",clkint,kodint,hupint,trmint,NIL); 1.123 + mail_parameters (NIL,SET_BLOCKENVINIT,VOIDT); 1.124 + s = myusername_full (&i); /* get user name and flags */ 1.125 + mail_parameters (NIL,SET_BLOCKENVINIT,NIL); 1.126 + if (i == MU_LOGGEDIN) { /* allow EXTERNAL if logged in already */ 1.127 + mail_parameters (NIL,UNHIDE_AUTHENTICATOR,(void *) "EXTERNAL"); 1.128 + mail_parameters (NIL,SET_EXTERNALAUTHID,(void *) s); 1.129 + } 1.130 + { /* set up MD5 challenge */ 1.131 + AUTHENTICATOR *auth = mail_lookup_auth (1); 1.132 + while (auth && compare_cstring (auth->name,"CRAM-MD5")) auth = auth->next; 1.133 + /* build challenge -- less than 128 chars */ 1.134 + if (auth && auth->server && !(auth->flags & AU_DISABLE)) 1.135 + sprintf (challenge,"<%lx.%lx@%.64s>",(unsigned long) getpid (), 1.136 + (unsigned long) time (0),tcp_serverhost ()); 1.137 + else challenge[0] = '\0'; /* no MD5 authentication */ 1.138 + } 1.139 + /* There are reports of POP3 clients which get upset if anything appears 1.140 + * between the "+OK" and the "POP3" in the greeting. 1.141 + */ 1.142 + PSOUT ("+OK POP3 "); 1.143 + if (!challenge[0]) { /* if no MD5 enable, output host name */ 1.144 + PSOUT (tcp_serverhost ()); 1.145 + PBOUT (' '); 1.146 + } 1.147 + PSOUT (CCLIENTVERSION); 1.148 + PBOUT ('.'); 1.149 + PSOUT (version); 1.150 + PSOUT (" server ready"); 1.151 + if (challenge[0]) { /* if MD5 enable, output challenge here */ 1.152 + PBOUT (' '); 1.153 + PSOUT (challenge); 1.154 + } 1.155 + CRLF; 1.156 + PFLUSH (); /* dump output buffer */ 1.157 + autologouttime = time (0) + LOGINTIMEOUT; 1.158 + /* command processing loop */ 1.159 + while ((state != UPDATE) && (state != LOGOUT)) { 1.160 + idletime = time (0); /* get a command under timeout */ 1.161 + alarm ((state == TRANSACTION) ? TIMEOUT : LOGINTIMEOUT); 1.162 + clearerr (stdin); /* clear stdin errors */ 1.163 + /* read command line */ 1.164 + while (!PSIN (tmp,MAILTMPLEN)) { 1.165 + /* ignore if some interrupt */ 1.166 + if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); 1.167 + else { 1.168 + char *e = ferror (stdin) ? 1.169 + strerror (errno) : "Unexpected client disconnect"; 1.170 + alarm (0); /* disable all interrupts */ 1.171 + server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); 1.172 + sprintf (logout = tmp,"%.80s, while reading line",e); 1.173 + goodbye = NIL; 1.174 + rset (); /* try to gracefully close the stream */ 1.175 + if (state == TRANSACTION) mail_close (stream); 1.176 + stream = NIL; 1.177 + state = LOGOUT; 1.178 + sayonara (1); 1.179 + } 1.180 + } 1.181 + alarm (0); /* make sure timeout disabled */ 1.182 + idletime = 0; /* no longer idle */ 1.183 + 1.184 + if (!strchr (tmp,'\012')) /* find end of line */ 1.185 + PSOUT ("-ERR Command line too long\015\012"); 1.186 + else if (!(s = strtok (tmp," \015\012"))) 1.187 + PSOUT ("-ERR Null command\015\012"); 1.188 + else { /* dispatch based on command */ 1.189 + ucase (s); /* canonicalize case */ 1.190 + /* snarf argument */ 1.191 + t = strtok (NIL,"\015\012"); 1.192 + /* QUIT command always valid */ 1.193 + if (!strcmp (s,"QUIT")) state = UPDATE; 1.194 + else if (!strcmp (s,"CAPA")) { 1.195 + AUTHENTICATOR *auth; 1.196 + PSOUT ("+OK Capability list follows:\015\012"); 1.197 + PSOUT ("TOP\015\012LOGIN-DELAY 180\015\012UIDL\015\012"); 1.198 + if (s = ssl_start_tls (NIL)) fs_give ((void **) &s); 1.199 + else PSOUT ("STLS\015\012"); 1.200 + if (i = !mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL)) 1.201 + PSOUT ("USER\015\012"); 1.202 + /* display secure server authenticators */ 1.203 + for (auth = mail_lookup_auth (1), s = "SASL"; auth; auth = auth->next) 1.204 + if (auth->server && !(auth->flags & AU_DISABLE) && 1.205 + !(auth->flags & AU_HIDE) && (i || (auth->flags & AU_SECURE))) { 1.206 + if (s) { 1.207 + PSOUT (s); 1.208 + s = NIL; 1.209 + } 1.210 + PBOUT (' '); 1.211 + PSOUT (auth->name); 1.212 + } 1.213 + PSOUT (s ? ".\015\012" : "\015\012.\015\012"); 1.214 + } 1.215 + 1.216 + else switch (state) { /* else dispatch based on state */ 1.217 + case AUTHORIZATION: /* waiting to get logged in */ 1.218 + if (!strcmp (s,"AUTH")) { 1.219 + if (t && *t) { /* mechanism given? */ 1.220 + if (host) fs_give ((void **) &host); 1.221 + if (user) fs_give ((void **) &user); 1.222 + if (pass) fs_give ((void **) &pass); 1.223 + s = strtok (t," "); /* get mechanism name */ 1.224 + /* get initial response */ 1.225 + if (initial = strtok (NIL,"\015\012")) { 1.226 + if ((*initial == '=') && !initial[1]) ++initial; 1.227 + else if (!*initial) initial = NIL; 1.228 + } 1.229 + if (!(user = cpystr (mail_auth (s,responder,argc,argv)))) { 1.230 + PSOUT ("-ERR Bad authentication\015\012"); 1.231 + syslog (LOG_INFO,"AUTHENTICATE %s failure host=%.80s",s, 1.232 + tcp_clienthost ()); 1.233 + } 1.234 + else if ((state = mbxopen ("INBOX")) == TRANSACTION) 1.235 + syslog (LOG_INFO,"Auth user=%.80s host=%.80s nmsgs=%lu/%lu", 1.236 + user,tcp_clienthost (),nmsgs,stream->nmsgs); 1.237 + else syslog (LOG_INFO,"Auth user=%.80s host=%.80s no mailbox", 1.238 + user,tcp_clienthost ()); 1.239 + } 1.240 + else { 1.241 + AUTHENTICATOR *auth; 1.242 + PSOUT ("+OK Supported authentication mechanisms:\015\012"); 1.243 + i = !mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL); 1.244 + for (auth = mail_lookup_auth (1); auth; auth = auth->next) 1.245 + if (auth->server && !(auth->flags & AU_DISABLE) && 1.246 + !(auth->flags & AU_HIDE) && 1.247 + (i || (auth->flags & AU_SECURE))) { 1.248 + PSOUT (auth->name); 1.249 + CRLF; 1.250 + } 1.251 + PBOUT ('.'); 1.252 + CRLF; 1.253 + } 1.254 + } 1.255 + 1.256 + else if (!strcmp (s,"APOP")) { 1.257 + if (challenge[0]) { /* can do it if have an MD5 challenge */ 1.258 + if (host) fs_give ((void **) &host); 1.259 + if (user) fs_give ((void **) &user); 1.260 + if (pass) fs_give ((void **) &pass); 1.261 + /* get user name */ 1.262 + if (!(t && *t && (s = strtok (t," ")) && (t = strtok(NIL,"\012")))) 1.263 + PSOUT ("-ERR Missing APOP argument\015\012"); 1.264 + else if (!(user = apop_login (challenge,s,t,argc,argv))) 1.265 + PSOUT ("-ERR Bad APOP\015\012"); 1.266 + else if ((state = mbxopen ("INBOX")) == TRANSACTION) 1.267 + syslog (LOG_INFO,"APOP user=%.80s host=%.80s nmsgs=%lu/%lu", 1.268 + user,tcp_clienthost (),nmsgs,stream->nmsgs); 1.269 + else syslog (LOG_INFO,"APOP user=%.80s host=%.80s no mailbox", 1.270 + user,tcp_clienthost ()); 1.271 + } 1.272 + else PSOUT ("-ERR Not supported\015\012"); 1.273 + } 1.274 + /* (chuckle) */ 1.275 + else if (!strcmp (s,"RPOP")) 1.276 + PSOUT ("-ERR Nice try, bunkie\015\012"); 1.277 + else if (!strcmp (s,"STLS")) { 1.278 + if (t = ssl_start_tls (pgmname)) { 1.279 + PSOUT ("-ERR STLS failed: "); 1.280 + PSOUT (t); 1.281 + CRLF; 1.282 + } 1.283 + else PSOUT ("+OK STLS completed\015\012"); 1.284 + } 1.285 + else if (!mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL) && 1.286 + !strcmp (s,"USER")) { 1.287 + if (host) fs_give ((void **) &host); 1.288 + if (user) fs_give ((void **) &user); 1.289 + if (pass) fs_give ((void **) &pass); 1.290 + if (t && *t) { /* if user name given */ 1.291 + /* skip leading whitespace (bogus clients!) */ 1.292 + while (*t == ' ') ++t; 1.293 + /* remote user name? */ 1.294 + if (s = strchr (t,':')) { 1.295 + *s++ = '\0'; /* tie off host name */ 1.296 + host = cpystr (t);/* copy host name */ 1.297 + user = cpystr (s);/* copy user name */ 1.298 + } 1.299 + /* local user name */ 1.300 + else user = cpystr (t); 1.301 + PSOUT ("+OK User name accepted, password please\015\012"); 1.302 + } 1.303 + else PSOUT ("-ERR Missing username argument\015\012"); 1.304 + } 1.305 + else if (!mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL) && 1.306 + user && *user && !strcmp (s,"PASS")) 1.307 + state = pass_login (t,argc,argv); 1.308 + else PSOUT ("-ERR Unknown AUTHORIZATION state command\015\012"); 1.309 + break; 1.310 + 1.311 + case TRANSACTION: /* logged in */ 1.312 + if (!strcmp (s,"STAT")) { 1.313 + for (i = 1,j = 0,k = 0; i <= nmsgs; i++) 1.314 + /* message still exists? */ 1.315 + if (msg[i] && !(flags[i] & DELE)) { 1.316 + j++; /* count one more undeleted message */ 1.317 + k += mail_elt (stream,msg[i])->rfc822_size + SLEN; 1.318 + } 1.319 + sprintf (tmp,"+OK %lu %lu\015\012",j,k); 1.320 + PSOUT (tmp); 1.321 + } 1.322 + else if (!strcmp (s,"LIST")) { 1.323 + if (t && *t) { /* argument do single message */ 1.324 + if ((i = strtoul (t,NIL,10)) && (i <= nmsgs) && msg[i] && 1.325 + !(flags[i] & DELE)) { 1.326 + sprintf (tmp,"+OK %lu %lu\015\012",i, 1.327 + mail_elt(stream,msg[i])->rfc822_size + SLEN); 1.328 + PSOUT (tmp); 1.329 + } 1.330 + else PSOUT ("-ERR No such message\015\012"); 1.331 + } 1.332 + else { /* entire mailbox */ 1.333 + PSOUT ("+OK Mailbox scan listing follows\015\012"); 1.334 + for (i = 1,j = 0,k = 0; i <= nmsgs; i++) 1.335 + if (msg[i] && !(flags[i] & DELE)) { 1.336 + sprintf (tmp,"%lu %lu\015\012",i, 1.337 + mail_elt (stream,msg[i])->rfc822_size + SLEN); 1.338 + PSOUT (tmp); 1.339 + } 1.340 + PBOUT ('.'); /* end of list */ 1.341 + CRLF; 1.342 + } 1.343 + } 1.344 + else if (!strcmp (s,"UIDL")) { 1.345 + if (t && *t) { /* argument do single message */ 1.346 + if ((i = strtoul (t,NIL,10)) && (i <= nmsgs) && msg[i] && 1.347 + !(flags[i] & DELE)) { 1.348 + sprintf (tmp,"+OK %lu %08lx%08lx\015\012",i,stream->uid_validity, 1.349 + mail_uid (stream,msg[i])); 1.350 + PSOUT (tmp); 1.351 + } 1.352 + else PSOUT ("-ERR No such message\015\012"); 1.353 + } 1.354 + else { /* entire mailbox */ 1.355 + PSOUT ("+OK Unique-ID listing follows\015\012"); 1.356 + for (i = 1,j = 0,k = 0; i <= nmsgs; i++) 1.357 + if (msg[i] && !(flags[i] & DELE)) { 1.358 + sprintf (tmp,"%lu %08lx%08lx\015\012",i,stream->uid_validity, 1.359 + mail_uid (stream,msg[i])); 1.360 + PSOUT (tmp); 1.361 + } 1.362 + PBOUT ('.'); /* end of list */ 1.363 + CRLF; 1.364 + } 1.365 + } 1.366 + 1.367 + else if (!strcmp (s,"RETR")) { 1.368 + if (t && *t) { /* must have an argument */ 1.369 + if ((i = strtoul (t,NIL,10)) && (i <= nmsgs) && msg[i] && 1.370 + !(flags[i] & DELE)) { 1.371 + MESSAGECACHE *elt; 1.372 + /* update highest message accessed */ 1.373 + if (i > last) last = i; 1.374 + sprintf (tmp,"+OK %lu octets\015\012", 1.375 + (elt = mail_elt (stream,msg[i]))->rfc822_size + SLEN); 1.376 + PSOUT (tmp); 1.377 + /* if not marked seen or noted to be marked */ 1.378 + if (!(elt->seen || (flags[i] & SEEN))) { 1.379 + ++nseen; /* note that we need to mark it seen */ 1.380 + flags[i] |= SEEN; 1.381 + } 1.382 + /* get header */ 1.383 + t = mail_fetch_header (stream,msg[i],NIL,NIL,&k,FT_PEEK); 1.384 + blat (t,-1,k,NIL);/* write up to trailing CRLF */ 1.385 + /* build status */ 1.386 + sprintf (tmp,STATUS,elt->seen ? "R" : " ", 1.387 + elt->recent ? " " : "O"); 1.388 + if (k < 4) CRLF; /* don't write Status: if no header */ 1.389 + /* normal header ending with CRLF CRLF? */ 1.390 + else if (t[k-3] == '\012') { 1.391 + PSOUT (tmp); /* write status */ 1.392 + CRLF; /* then write second CRLF */ 1.393 + } 1.394 + else { /* abnormal - no blank line at end of header */ 1.395 + CRLF; /* write CRLF first then */ 1.396 + PSOUT (tmp); 1.397 + } 1.398 + /* output text */ 1.399 + t = mail_fetch_text (stream,msg[i],NIL,&k, 1.400 + FT_RETURNSTRINGSTRUCT | FT_PEEK); 1.401 + if (k) { /* only if there is a text body */ 1.402 + blat (t,-1,k,&stream->private.string); 1.403 + CRLF; /* end of list */ 1.404 + } 1.405 + PBOUT ('.'); 1.406 + CRLF; 1.407 + } 1.408 + else PSOUT ("-ERR No such message\015\012"); 1.409 + } 1.410 + else PSOUT ("-ERR Missing message number argument\015\012"); 1.411 + } 1.412 + 1.413 + else if (!strcmp (s,"DELE")) { 1.414 + if (t && *t) { /* must have an argument */ 1.415 + if ((i = strtoul (t,NIL,10)) && (i <= nmsgs) && msg[i] && 1.416 + !(flags[i] & DELE)) { 1.417 + /* update highest message accessed */ 1.418 + if (i > last) last = i; 1.419 + flags[i] |= DELE; /* note that deletion is requested */ 1.420 + PSOUT ("+OK Message deleted\015\012"); 1.421 + ++ndele; /* one more message deleted */ 1.422 + } 1.423 + else PSOUT ("-ERR No such message\015\012"); 1.424 + } 1.425 + else PSOUT ("-ERR Missing message number argument\015\012"); 1.426 + } 1.427 + else if (!strcmp (s,"NOOP")) 1.428 + PSOUT ("+OK No-op to you too!\015\012"); 1.429 + else if (!strcmp (s,"LAST")) { 1.430 + sprintf (tmp,"+OK %lu\015\012",last); 1.431 + PSOUT (tmp); 1.432 + } 1.433 + else if (!strcmp (s,"RSET")) { 1.434 + rset (); /* reset the mailbox */ 1.435 + PSOUT ("+OK Reset state\015\012"); 1.436 + } 1.437 + 1.438 + else if (!strcmp (s,"TOP")) { 1.439 + if (t && *t && (i =strtoul (t,&s,10)) && (i <= nmsgs) && msg[i] && 1.440 + !(flags[i] & DELE)) { 1.441 + /* skip whitespace */ 1.442 + while (*s == ' ') s++; 1.443 + /* make sure line count argument good */ 1.444 + if ((*s >= '0') && (*s <= '9')) { 1.445 + MESSAGECACHE *elt = mail_elt (stream,msg[i]); 1.446 + j = strtoul (s,NIL,10); 1.447 + /* update highest message accessed */ 1.448 + if (i > last) last = i; 1.449 + PSOUT ("+OK Top of message follows\015\012"); 1.450 + /* get header */ 1.451 + t = mail_fetch_header (stream,msg[i],NIL,NIL,&k,FT_PEEK); 1.452 + blat (t,-1,k,NIL);/* write up to trailing CRLF */ 1.453 + /* build status */ 1.454 + sprintf (tmp,STATUS,elt->seen ? "R" : " ", 1.455 + elt->recent ? " " : "O"); 1.456 + if (k < 4) CRLF; /* don't write Status: if no header */ 1.457 + /* normal header ending with CRLF CRLF? */ 1.458 + else if (t[k-3] == '\012') { 1.459 + PSOUT (tmp); /* write status */ 1.460 + CRLF; /* then write second CRLF */ 1.461 + } 1.462 + else { /* abnormal - no blank line at end of header */ 1.463 + CRLF; /* write CRLF first then */ 1.464 + PSOUT (tmp); 1.465 + } 1.466 + if (j) { /* want any text lines? */ 1.467 + /* output text */ 1.468 + t = mail_fetch_text (stream,msg[i],NIL,&k, 1.469 + FT_PEEK | FT_RETURNSTRINGSTRUCT); 1.470 + /* tie off final line if full text output */ 1.471 + if (k && (j -= blat (t,j,k,&stream->private.string))) CRLF; 1.472 + } 1.473 + PBOUT ('.'); /* end of list */ 1.474 + CRLF; 1.475 + } 1.476 + else PSOUT ("-ERR Bad line count argument\015\012"); 1.477 + } 1.478 + else PSOUT ("-ERR Bad message number argument\015\012"); 1.479 + } 1.480 + 1.481 + else if (!strcmp (s,"XTND")) 1.482 + PSOUT ("-ERR Sorry I can't do that\015\012"); 1.483 + else PSOUT ("-ERR Unknown TRANSACTION state command\015\012"); 1.484 + break; 1.485 + default: 1.486 + PSOUT ("-ERR Server in unknown state\015\012"); 1.487 + break; 1.488 + } 1.489 + } 1.490 + PFLUSH (); /* make sure output finished */ 1.491 + if (autologouttime) { /* have an autologout in effect? */ 1.492 + /* cancel if no longer waiting for login */ 1.493 + if (state != AUTHORIZATION) autologouttime = 0; 1.494 + /* took too long to login */ 1.495 + else if (autologouttime < time (0)) { 1.496 + goodbye = "-ERR Autologout\015\012"; 1.497 + logout = "Autologout"; 1.498 + state = LOGOUT; /* sayonara */ 1.499 + } 1.500 + } 1.501 + } 1.502 + 1.503 + /* open and need to update? */ 1.504 + if (stream && (state == UPDATE)) { 1.505 + if (nseen) { /* only bother if messages need marking seen */ 1.506 + *(s = tmp) = '\0'; /* clear sequence */ 1.507 + for (i = 1; i <= nmsgs; ++i) if (flags[i] & SEEN) { 1.508 + for (j = i + 1, k = 0; (j <= nmsgs) && (flags[j] & SEEN); ++j) k = j; 1.509 + if (k) sprintf (s,",%lu:%lu",i,k); 1.510 + else sprintf (s,",%lu",i); 1.511 + s += strlen (s); /* point to end of string */ 1.512 + if ((s - tmp) > (MAILTMPLEN - 30)) { 1.513 + mail_setflag (stream,tmp + 1,"\\Seen"); 1.514 + *(s = tmp) = '\0'; /* restart sequence */ 1.515 + } 1.516 + i = j; /* continue after the range */ 1.517 + } 1.518 + if (tmp[0]) mail_setflag (stream,tmp + 1,"\\Seen"); 1.519 + } 1.520 + if (ndele) { /* any messages to delete? */ 1.521 + *(s = tmp) = '\0'; /* clear sequence */ 1.522 + for (i = 1; i <= nmsgs; ++i) if (flags[i] & DELE) { 1.523 + for (j = i + 1, k = 0; (j <= nmsgs) && (flags[j] & DELE); ++j) k = j; 1.524 + if (k) sprintf (s,",%lu:%lu",i,k); 1.525 + else sprintf (s,",%lu",i); 1.526 + s += strlen (s); /* point to end of string */ 1.527 + if ((s - tmp) > (MAILTMPLEN - 30)) { 1.528 + mail_setflag (stream,tmp + 1,"\\Deleted"); 1.529 + *(s = tmp) = '\0'; /* restart sequence */ 1.530 + } 1.531 + i = j; /* continue after the range */ 1.532 + } 1.533 + if (tmp[0]) mail_setflag (stream,tmp + 1,"\\Deleted"); 1.534 + mail_expunge (stream); 1.535 + } 1.536 + syslog (LOG_INFO,"Update user=%.80s host=%.80s nmsgs=%lu ndele=%lu nseen=%lu", 1.537 + user,tcp_clienthost (),stream->nmsgs,ndele,nseen); 1.538 + mail_close (stream); 1.539 + } 1.540 + sayonara (0); 1.541 + return 0; /* stupid compilers */ 1.542 +} 1.543 + 1.544 + 1.545 +/* Say goodbye 1.546 + * Accepts: exit status 1.547 + * 1.548 + * Does not return 1.549 + */ 1.550 + 1.551 +void sayonara (int status) 1.552 +{ 1.553 + logouthook_t lgoh = (logouthook_t) mail_parameters (NIL,GET_LOGOUTHOOK,NIL); 1.554 + if (goodbye) { /* have a goodbye message? */ 1.555 + PSOUT (goodbye); 1.556 + PFLUSH (); /* make sure blatted */ 1.557 + } 1.558 + syslog (LOG_INFO,"%s user=%.80s host=%.80s",logout, 1.559 + user ? (char *) user : "???",tcp_clienthost ()); 1.560 + /* do logout hook if needed */ 1.561 + if (lgoh) (*lgoh) (mail_parameters (NIL,GET_LOGOUTDATA,NIL)); 1.562 + _exit (status); /* all done */ 1.563 +} 1.564 + 1.565 +/* Clock interrupt 1.566 + */ 1.567 + 1.568 +void clkint () 1.569 +{ 1.570 + alarm (0); /* disable all interrupts */ 1.571 + server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); 1.572 + goodbye = "-ERR Autologout; idle for too long\015\012"; 1.573 + logout = "Autologout"; 1.574 + if (critical) state = LOGOUT; /* badly hosed if in critical code */ 1.575 + else { /* try to gracefully close the stream */ 1.576 + if ((state == TRANSACTION) && !stream->lock) { 1.577 + rset (); 1.578 + mail_close (stream); 1.579 + } 1.580 + state = LOGOUT; 1.581 + stream = NIL; 1.582 + sayonara (1); 1.583 + } 1.584 +} 1.585 + 1.586 + 1.587 +/* Kiss Of Death interrupt 1.588 + */ 1.589 + 1.590 +void kodint () 1.591 +{ 1.592 + /* only if idle */ 1.593 + if (idletime && ((time (0) - idletime) > KODTIMEOUT)) { 1.594 + alarm (0); /* disable all interrupts */ 1.595 + server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); 1.596 + goodbye = "-ERR Received Kiss of Death\015\012"; 1.597 + logout = "Killed (lost mailbox lock)"; 1.598 + if (critical) state =LOGOUT;/* must defer if in critical code */ 1.599 + else { /* try to gracefully close the stream */ 1.600 + if ((state == TRANSACTION) && !stream->lock) { 1.601 + rset (); 1.602 + mail_close (stream); 1.603 + } 1.604 + state = LOGOUT; 1.605 + stream = NIL; 1.606 + sayonara (1); /* die die die */ 1.607 + } 1.608 + } 1.609 +} 1.610 + 1.611 + 1.612 +/* Hangup interrupt 1.613 + */ 1.614 + 1.615 +void hupint () 1.616 +{ 1.617 + alarm (0); /* disable all interrupts */ 1.618 + server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); 1.619 + goodbye = NIL; /* nobody left to talk to */ 1.620 + logout = "Hangup"; 1.621 + if (critical) state = LOGOUT; /* must defer if in critical code */ 1.622 + else { /* try to gracefully close the stream */ 1.623 + if ((state == TRANSACTION) && !stream->lock) { 1.624 + rset (); 1.625 + mail_close (stream); 1.626 + } 1.627 + state = LOGOUT; 1.628 + stream = NIL; 1.629 + sayonara (1); /* die die die */ 1.630 + } 1.631 +} 1.632 + 1.633 + 1.634 +/* Termination interrupt 1.635 + */ 1.636 + 1.637 +void trmint () 1.638 +{ 1.639 + alarm (0); /* disable all interrupts */ 1.640 + server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); 1.641 + goodbye = "-ERR Killed\015\012"; 1.642 + logout = "Killed"; 1.643 + if (critical) state = LOGOUT; /* must defer if in critical code */ 1.644 + /* Make no attempt at graceful closure since a shutdown may be in 1.645 + * progress, and we won't have any time to do mail_close() actions. 1.646 + */ 1.647 + else sayonara (1); /* die die die */ 1.648 +} 1.649 + 1.650 +/* Parse PASS command 1.651 + * Accepts: pointer to command argument 1.652 + * Returns: new state 1.653 + */ 1.654 + 1.655 +int pass_login (char *t,int argc,char *argv[]) 1.656 +{ 1.657 + char tmp[MAILTMPLEN]; 1.658 + /* flush old passowrd */ 1.659 + if (pass) fs_give ((void **) &pass); 1.660 + if (!(t && *t)) { /* if no password given */ 1.661 + PSOUT ("-ERR Missing password argument\015\012"); 1.662 + return AUTHORIZATION; 1.663 + } 1.664 + pass = cpystr (t); /* copy password argument */ 1.665 + if (!host) { /* want remote mailbox? */ 1.666 + /* no, delimit user from possible admin */ 1.667 + if (t = strchr (user,'*')) *t++ ='\0'; 1.668 + /* attempt the login */ 1.669 + if (server_login (user,pass,t,argc,argv)) { 1.670 + int ret = mbxopen ("INBOX"); 1.671 + if (ret == TRANSACTION) /* mailbox opened OK? */ 1.672 + syslog (LOG_INFO,"%sLogin user=%.80s host=%.80s nmsgs=%lu/%lu", 1.673 + t ? "Admin " : "",user,tcp_clienthost (),nmsgs,stream->nmsgs); 1.674 + else syslog (LOG_INFO,"%sLogin user=%.80s host=%.80s no mailbox", 1.675 + t ? "Admin " : "",user,tcp_clienthost ()); 1.676 + return ret; 1.677 + } 1.678 + } 1.679 +#ifndef DISABLE_POP_PROXY 1.680 + /* remote; build remote INBOX */ 1.681 + else if (anonymous_login (argc,argv)) { 1.682 + syslog (LOG_INFO,"IMAP login to host=%.80s user=%.80s host=%.80s",host, 1.683 + user,tcp_clienthost ()); 1.684 + sprintf (tmp,"{%.128s/user=%.128s}INBOX",host,user); 1.685 + /* disable rimap just in case */ 1.686 + mail_parameters (NIL,SET_RSHTIMEOUT,0); 1.687 + return mbxopen (tmp); 1.688 + } 1.689 +#endif 1.690 + /* vague error message to confuse crackers */ 1.691 + PSOUT ("-ERR Bad login\015\012"); 1.692 + return AUTHORIZATION; 1.693 +} 1.694 + 1.695 +/* Authentication responder 1.696 + * Accepts: challenge 1.697 + * length of challenge 1.698 + * pointer to response length return location if non-NIL 1.699 + * Returns: response 1.700 + */ 1.701 + 1.702 +#define RESPBUFLEN 8*MAILTMPLEN 1.703 + 1.704 +char *responder (void *challenge,unsigned long clen,unsigned long *rlen) 1.705 +{ 1.706 + unsigned long i,j; 1.707 + unsigned char *t,resp[RESPBUFLEN]; 1.708 + char tmp[MAILTMPLEN]; 1.709 + if (initial) { /* initial response given? */ 1.710 + if (clen) return NIL; /* not permitted */ 1.711 + /* set up response */ 1.712 + t = (unsigned char *) initial; 1.713 + initial = NIL; /* no more initial response */ 1.714 + return (char *) rfc822_base64 (t,strlen ((char *) t),rlen ? rlen : &i); 1.715 + } 1.716 + PSOUT ("+ "); 1.717 + for (t = rfc822_binary (challenge,clen,&i),j = 0; j < i; j++) 1.718 + if (t[j] > ' ') PBOUT (t[j]); 1.719 + fs_give ((void **) &t); 1.720 + CRLF; 1.721 + PFLUSH (); /* dump output buffer */ 1.722 + resp[RESPBUFLEN-1] = '\0'; /* last buffer character is guaranteed NUL */ 1.723 + alarm (LOGINTIMEOUT); /* get a response under timeout */ 1.724 + clearerr (stdin); /* clear stdin errors */ 1.725 + /* read buffer */ 1.726 + while (!PSIN ((char *) resp,RESPBUFLEN)) { 1.727 + /* ignore if some interrupt */ 1.728 + if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); 1.729 + else { 1.730 + char *e = ferror (stdin) ? 1.731 + strerror (errno) : "Command stream end of file"; 1.732 + alarm (0); /* disable all interrupts */ 1.733 + server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); 1.734 + sprintf (logout = tmp,"%.80s, while reading authentication",e); 1.735 + goodbye = NIL; 1.736 + state = LOGOUT; 1.737 + sayonara (1); 1.738 + } 1.739 + } 1.740 + if (!(t = (unsigned char *) strchr ((char *) resp,'\012'))) { 1.741 + int c; 1.742 + while ((c = PBIN ()) != '\012') if (c == EOF) { 1.743 + /* ignore if some interrupt */ 1.744 + if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); 1.745 + else { 1.746 + char *e = ferror (stdin) ? 1.747 + strerror (errno) : "Command stream end of file"; 1.748 + alarm (0); /* disable all interrupts */ 1.749 + server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); 1.750 + sprintf (logout = tmp,"%.80s, while reading auth char",e); 1.751 + goodbye = NIL; 1.752 + state = LOGOUT; 1.753 + sayonara (1); 1.754 + } 1.755 + } 1.756 + return NIL; 1.757 + } 1.758 + alarm (0); /* make sure timeout disabled */ 1.759 + if (t[-1] == '\015') --t; /* remove CR */ 1.760 + *t = '\0'; /* tie off buffer */ 1.761 + return (resp[0] != '*') ? 1.762 + (char *) rfc822_base64 (resp,t-resp,rlen ? rlen : &i) : NIL; 1.763 +} 1.764 + 1.765 +/* Select mailbox 1.766 + * Accepts: mailbox name 1.767 + * Returns: new state 1.768 + */ 1.769 + 1.770 +int mbxopen (char *mailbox) 1.771 +{ 1.772 + unsigned long i,j; 1.773 + char tmp[MAILTMPLEN]; 1.774 + MESSAGECACHE *elt; 1.775 + if (msg) fs_give ((void **) &msg); 1.776 + /* open mailbox */ 1.777 + if (!(stream = mail_open (stream,mailbox,NIL))) 1.778 + goodbye = "-ERR Unable to open user's INBOX\015\012"; 1.779 + else if (stream->rdonly) /* make sure not readonly */ 1.780 + goodbye = "-ERR Can't get lock. Mailbox in use\015\012"; 1.781 + else { 1.782 + nmsgs = 0; /* no messages yet */ 1.783 + if (j = stream->nmsgs) { /* if mailbox non-empty */ 1.784 + sprintf (tmp,"1:%lu",j); /* fetch fast information for all messages */ 1.785 + mail_fetch_fast (stream,tmp,NIL); 1.786 + } 1.787 + /* create 1-origin tables */ 1.788 + msg = (long *) fs_get (++j * sizeof (long)); 1.789 + flags = (short *) fs_get (j * sizeof (short)); 1.790 + /* build map */ 1.791 + for (i = 1; i < j; ++i) if (!(elt = mail_elt (stream,i))->deleted) { 1.792 + msg[++nmsgs] = i; /* note the presence of this message */ 1.793 + if (elt->seen) il = nmsgs;/* and set up initial LAST */ 1.794 + } 1.795 + /* make sure unused map entries are zero */ 1.796 + for (i = nmsgs + 1; i < j; ++i) msg[i] = 0; 1.797 + rset (); /* do implicit RSET */ 1.798 + sprintf (tmp,"+OK Mailbox open, %lu messages\015\012",nmsgs); 1.799 + PSOUT (tmp); 1.800 + return TRANSACTION; 1.801 + } 1.802 + syslog (LOG_INFO,"Error opening or locking INBOX user=%.80s host=%.80s", 1.803 + user,tcp_clienthost ()); 1.804 + return UPDATE; 1.805 +} 1.806 + 1.807 +/* Blat a string with dot checking 1.808 + * Accepts: string 1.809 + * maximum number of lines if greater than zero 1.810 + * maximum number of bytes to output 1.811 + * alternative stringstruct 1.812 + * Returns: number of lines output 1.813 + * 1.814 + * This routine is uglier and kludgier than it should be, just to be robust 1.815 + * in the case of a message which doesn't end in a newline. Yes, this routine 1.816 + * does truncate the last two bytes from the text. Since it is normally a 1.817 + * newline and the main routine adds it back, it usually does not make a 1.818 + * difference. But if it isn't, since the newline is required and the octet 1.819 + * counts have to match, there's no choice but to truncate. 1.820 + */ 1.821 + 1.822 +long blat (char *text,long lines,unsigned long size,STRING *st) 1.823 +{ 1.824 + char c,d,e; 1.825 + long ret = 0; 1.826 + /* no-op if zero lines or empty string */ 1.827 + if (!(lines && (size-- > 2))) return 0; 1.828 + if (text) { 1.829 + c = *text++; d = *text++; /* collect first two bytes */ 1.830 + if (c == '.') PBOUT ('.'); /* double string-leading dot if necessary */ 1.831 + while (lines && --size) { /* copy loop */ 1.832 + e = *text++; /* get next byte */ 1.833 + PBOUT (c); /* output character */ 1.834 + if (c == '\012') { /* end of line? */ 1.835 + ret++; --lines; /* count another line */ 1.836 + /* double leading dot as necessary */ 1.837 + if (lines && size && (d == '.')) PBOUT ('.'); 1.838 + } 1.839 + c = d; d = e; /* move to next character */ 1.840 + } 1.841 + } 1.842 + else { 1.843 + c = SNX (st); d = SNX (st); /* collect first two bytes */ 1.844 + if (c == '.') PBOUT ('.'); /* double string-leading dot if necessary */ 1.845 + while (lines && --size) { /* copy loop */ 1.846 + e = SNX (st); /* get next byte */ 1.847 + PBOUT (c); /* output character */ 1.848 + if (c == '\012') { /* end of line? */ 1.849 + ret++; --lines; /* count another line */ 1.850 + /* double leading dot as necessary */ 1.851 + if (lines && size && (d == '.')) PBOUT ('.'); 1.852 + } 1.853 + c = d; d = e; /* move to next character */ 1.854 + } 1.855 + } 1.856 + return ret; 1.857 +} 1.858 + 1.859 +/* Reset mailbox 1.860 + */ 1.861 + 1.862 +void rset () 1.863 +{ 1.864 + /* clear all flags */ 1.865 + if (flags) memset ((void *) flags,0,(nmsgs + 1) * sizeof (short)); 1.866 + ndele = nseen = 0; /* no more deleted or seen messages */ 1.867 + last = il; /* restore previous LAST value */ 1.868 +} 1.869 + 1.870 +/* Co-routines from MAIL library */ 1.871 + 1.872 + 1.873 +/* Message matches a search 1.874 + * Accepts: MAIL stream 1.875 + * message number 1.876 + */ 1.877 + 1.878 +void mm_searched (MAILSTREAM *stream,unsigned long msgno) 1.879 +{ 1.880 + /* Never called */ 1.881 +} 1.882 + 1.883 + 1.884 +/* Message exists (i.e. there are that many messages in the mailbox) 1.885 + * Accepts: MAIL stream 1.886 + * message number 1.887 + */ 1.888 + 1.889 +void mm_exists (MAILSTREAM *stream,unsigned long number) 1.890 +{ 1.891 + /* Can't use this mechanism. POP has no means of notifying the client of 1.892 + new mail during the session. */ 1.893 +} 1.894 + 1.895 + 1.896 +/* Message expunged 1.897 + * Accepts: MAIL stream 1.898 + * message number 1.899 + */ 1.900 + 1.901 +void mm_expunged (MAILSTREAM *stream,unsigned long number) 1.902 +{ 1.903 + unsigned long i = number + 1; 1.904 + msg[number] = 0; /* I bet that this will annoy someone */ 1.905 + while (i <= nmsgs) --msg[i++]; 1.906 +} 1.907 + 1.908 + 1.909 +/* Message flag status change 1.910 + * Accepts: MAIL stream 1.911 + * message number 1.912 + */ 1.913 + 1.914 +void mm_flags (MAILSTREAM *stream,unsigned long number) 1.915 +{ 1.916 + /* This isn't used */ 1.917 +} 1.918 + 1.919 + 1.920 +/* Mailbox found 1.921 + * Accepts: MAIL stream 1.922 + * hierarchy delimiter 1.923 + * mailbox name 1.924 + * mailbox attributes 1.925 + */ 1.926 + 1.927 +void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes) 1.928 +{ 1.929 + /* This isn't used */ 1.930 +} 1.931 + 1.932 + 1.933 +/* Subscribe mailbox found 1.934 + * Accepts: MAIL stream 1.935 + * hierarchy delimiter 1.936 + * mailbox name 1.937 + * mailbox attributes 1.938 + */ 1.939 + 1.940 +void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes) 1.941 +{ 1.942 + /* This isn't used */ 1.943 +} 1.944 + 1.945 + 1.946 +/* Mailbox status 1.947 + * Accepts: MAIL stream 1.948 + * mailbox name 1.949 + * mailbox status 1.950 + */ 1.951 + 1.952 +void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status) 1.953 +{ 1.954 + /* This isn't used */ 1.955 +} 1.956 + 1.957 +/* Notification event 1.958 + * Accepts: MAIL stream 1.959 + * string to log 1.960 + * error flag 1.961 + */ 1.962 + 1.963 +void mm_notify (MAILSTREAM *stream,char *string,long errflg) 1.964 +{ 1.965 + mm_log (string,errflg); /* just do mm_log action */ 1.966 +} 1.967 + 1.968 + 1.969 +/* Log an event for the user to see 1.970 + * Accepts: string to log 1.971 + * error flag 1.972 + */ 1.973 + 1.974 +void mm_log (char *string,long errflg) 1.975 +{ 1.976 + switch (errflg) { 1.977 + case NIL: /* information message */ 1.978 + case PARSE: /* parse glitch */ 1.979 + break; /* too many of these to log */ 1.980 + case WARN: /* warning */ 1.981 + syslog (LOG_DEBUG,"%s",string); 1.982 + break; 1.983 + case BYE: /* driver broke connection */ 1.984 + if (state != UPDATE) { 1.985 + char tmp[MAILTMPLEN]; 1.986 + alarm (0); /* disable all interrupts */ 1.987 + server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); 1.988 + sprintf (logout = tmp,"Mailbox closed (%.80s)",string); 1.989 + goodbye = NIL; 1.990 + state = LOGOUT; 1.991 + sayonara (1); 1.992 + } 1.993 + break; 1.994 + case ERROR: /* error that broke command */ 1.995 + default: /* default should never happen */ 1.996 + syslog (LOG_NOTICE,"%s",string); 1.997 + break; 1.998 + } 1.999 +} 1.1000 + 1.1001 + 1.1002 +/* Log an event to debugging telemetry 1.1003 + * Accepts: string to log 1.1004 + */ 1.1005 + 1.1006 +void mm_dlog (char *string) 1.1007 +{ 1.1008 + /* Not doing anything here for now */ 1.1009 +} 1.1010 + 1.1011 + 1.1012 +/* Get user name and password for this host 1.1013 + * Accepts: parse of network mailbox name 1.1014 + * where to return user name 1.1015 + * where to return password 1.1016 + * trial count 1.1017 + */ 1.1018 + 1.1019 +void mm_login (NETMBX *mb,char *username,char *password,long trial) 1.1020 +{ 1.1021 + /* set user name */ 1.1022 + strncpy (username,*mb->user ? mb->user : user,NETMAXUSER-1); 1.1023 + if (pass) { 1.1024 + strncpy (password,pass,255);/* and password */ 1.1025 + fs_give ((void **) &pass); 1.1026 + } 1.1027 + else memset (password,0,256); /* no password to send, abort login */ 1.1028 + username[NETMAXUSER] = password[255] = '\0'; 1.1029 +} 1.1030 + 1.1031 +/* About to enter critical code 1.1032 + * Accepts: stream 1.1033 + */ 1.1034 + 1.1035 +void mm_critical (MAILSTREAM *stream) 1.1036 +{ 1.1037 + ++critical; 1.1038 +} 1.1039 + 1.1040 + 1.1041 +/* About to exit critical code 1.1042 + * Accepts: stream 1.1043 + */ 1.1044 + 1.1045 +void mm_nocritical (MAILSTREAM *stream) 1.1046 +{ 1.1047 + --critical; 1.1048 +} 1.1049 + 1.1050 + 1.1051 +/* Disk error found 1.1052 + * Accepts: stream 1.1053 + * system error code 1.1054 + * flag indicating that mailbox may be clobbered 1.1055 + * Returns: abort flag 1.1056 + */ 1.1057 + 1.1058 +long mm_diskerror (MAILSTREAM *stream,long errcode,long serious) 1.1059 +{ 1.1060 + if (serious) { /* try your damnest if clobberage likely */ 1.1061 + syslog (LOG_ALERT, 1.1062 + "Retrying after disk error user=%.80s host=%.80s mbx=%.80s: %.80s", 1.1063 + user,tcp_clienthost (), 1.1064 + (stream && stream->mailbox) ? stream->mailbox : "???", 1.1065 + strerror (errcode)); 1.1066 + alarm (0); /* make damn sure timeout disabled */ 1.1067 + sleep (60); /* give it some time to clear up */ 1.1068 + return NIL; 1.1069 + } 1.1070 + syslog (LOG_ALERT,"Fatal disk error user=%.80s host=%.80s mbx=%.80s: %.80s", 1.1071 + user,tcp_clienthost (), 1.1072 + (stream && stream->mailbox) ? stream->mailbox : "???", 1.1073 + strerror (errcode)); 1.1074 + return T; 1.1075 +} 1.1076 + 1.1077 + 1.1078 +/* Log a fatal error event 1.1079 + * Accepts: string to log 1.1080 + */ 1.1081 + 1.1082 +void mm_fatal (char *string) 1.1083 +{ 1.1084 + mm_log (string,ERROR); /* shouldn't happen normally */ 1.1085 +}