Newer
Older
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
SAFEPRINTF3(err,badrsp_err,server,buf,"334 Password");
bounce(&smb,&msg,err,buf[0]=='5');
continue;
}
switch(startup->options&MAIL_OPT_RELAY_AUTH_MASK) {
case MAIL_OPT_RELAY_AUTH_PLAIN:
p=startup->relay_pass;
break;
case MAIL_OPT_RELAY_AUTH_LOGIN:
b64_encode(p=buf,sizeof(buf),startup->relay_pass,0);
break;
default:
p="<unknown>";
break;
}
sockprintf(sock,"%s",p);
}
if(!sockgetrsp(sock,"235",buf,sizeof(buf))) {
SAFEPRINTF3(err,badrsp_err,server,buf,"235");
bounce(&smb,&msg,err,buf[0]=='5');
continue;
}
}
if(msg.from_net.type==NET_INTERNET && msg.reverse_path!=NULL)
SAFECOPY(fromaddr,msg.reverse_path);
usermailaddr(&scfg,fromaddr,msg.from);
truncstr(fromaddr," ");
if(fromaddr[0]=='<')
sockprintf(sock,"MAIL FROM: %s",fromaddr);
else
sockprintf(sock,"MAIL FROM: <%s>",fromaddr);
if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
remove_msg_intransit(&smb,&msg);
SAFEPRINTF3(err,badrsp_err,server,buf,"250");
bounce(&smb,&msg,err,buf[0]=='5');
continue;
}
/* RCPT */
if(msg.forward_path!=NULL) {
SAFECOPY(toaddr,msg.forward_path);
} else {
if((p=strrchr((char*)msg.to_net.addr,'<'))!=NULL)
p++;
else
p=(char*)msg.to_net.addr;
SAFECOPY(toaddr,p);
truncstr(toaddr,"> ");
if((p=strrchr(toaddr,'@'))!=NULL && (tp=strrchr(toaddr,':'))!=NULL
&& tp > p)
*tp=0; /* Remove ":port" designation from envelope */
}
sockprintf(sock,"RCPT TO: <%s>", toaddr);
if(!sockgetrsp(sock,"25", buf, sizeof(buf))) {
remove_msg_intransit(&smb,&msg);
SAFEPRINTF3(err,badrsp_err,server,buf,"25*");
bounce(&smb,&msg,err,buf[0]=='5');
continue;
}
/* DATA */
sockprintf(sock,"DATA");
if(!sockgetrsp(sock,"354", buf, sizeof(buf))) {
remove_msg_intransit(&smb,&msg);
SAFEPRINTF3(err,badrsp_err,server,buf,"354");
bounce(&smb,&msg,err,buf[0]=='5');
continue;
}
lprintf(LOG_DEBUG,"%04d SEND sending message text (%u bytes)"
lines=sockmsgtxt(sock,&msg,msgtxt,-1);
if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
remove_msg_intransit(&smb,&msg);
SAFEPRINTF3(err,badrsp_err,server,buf,"250");
bounce(&smb,&msg,err,buf[0]=='5');
continue;
}
lprintf(LOG_DEBUG,"%04d SEND message transfer complete (%lu lines)", sock, lines);
/* Now lets mark this message for deletion without corrupting the index */
msg.hdr.attr|=MSG_DELETE;
msg.hdr.netattr&=~MSG_INTRANSIT;
if((i=smb_updatemsg(&smb,&msg))!=SMB_SUCCESS)
lprintf(LOG_ERR,"%04d !SEND ERROR %d (%s) deleting message #%lu"
,sock, i, smb.last_error, msg.hdr.number);
if(msg.hdr.auxattr&MSG_FILEATTACH)
delfattach(&scfg,&msg);
if(msg.from_agent==AGENT_PERSON && !(startup->options&MAIL_OPT_NO_AUTO_EXEMPT))
exempt_email_addr("SEND Auto-exempting",msg.from,fromaddr,toaddr);
/* QUIT */
sockprintf(sock,"QUIT");
sockgetrsp(sock,"221", buf, sizeof(buf));

rswindell
committed
mail_close_socket(sock);
sock=INVALID_SOCKET;
}
status(STATUS_WFC);
/* Free up resources here */
if(mail!=NULL)
freemail(mail);
}
if(sock!=INVALID_SOCKET)

rswindell
committed
mail_close_socket(sock);
smb_freemsgtxt(msgtxt);
smb_freemsgmem(&msg);
smb_close(&smb);
if(active_sendmail!=0)
active_sendmail=0, update_clients();
thread_down();
lprintf(LOG_DEBUG,"0000 SendMail thread terminated (%u threads remain)", thread_count);
sendmail_running=FALSE;
}
void DLLCALL mail_terminate(void)
lprintf(LOG_DEBUG,"%04d Mail Server terminate",server_socket);
terminate_server=TRUE;
}
static void cleanup(int code)
{
int i;
semfile_list_free(&recycle_semfiles);
semfile_list_free(&shutdown_semfiles);
if(mailproc_list!=NULL) {
for(i=0;i<mailproc_count;i++)
strListFree(&mailproc_list[i].to);
FREE_AND_NULL(mailproc_list);
}
if(server_socket!=INVALID_SOCKET) {

rswindell
committed
mail_close_socket(server_socket);
server_socket=INVALID_SOCKET;
}
if(submission_socket!=INVALID_SOCKET) {
mail_close_socket(submission_socket);
submission_socket=INVALID_SOCKET;
}
if(pop3_socket!=INVALID_SOCKET) {

rswindell
committed
mail_close_socket(pop3_socket);
pop3_socket=INVALID_SOCKET;
}
update_clients();
#ifdef _WINSOCKAPI_
if(WSAInitialized && WSACleanup()!=0)
lprintf(LOG_ERR,"0000 !WSACleanup ERROR %d",ERROR_VALUE);
thread_down();
if(terminate_server || code)
lprintf(LOG_INFO,"#### Mail Server thread terminated (%u threads remain, %lu clients served)"
,thread_count, served);
if(startup!=NULL && startup->terminated!=NULL)
startup->terminated(startup->cbdata,code);
const char* DLLCALL mail_ver(void)
{
static char ver[256];
char compiler[32];
sscanf("$Revision$", "%*s %s", revision);
sprintf(ver,"Synchronet Mail Server %s%s SMBLIB %s "
#ifdef _DEBUG
," Debug"
#else
,""
#endif
,smb_lib_ver()
,__DATE__, __TIME__, compiler
);
return(ver);
}
void DLLCALL mail_server(void* arg)
char* p;
char path[MAX_PATH+1];
char str[256];
char error[256];
char compiler[32];
SOCKADDR_IN server_addr;
SOCKADDR_IN client_addr;
socklen_t client_addr_len;
SOCKET client_socket;
int i;
int result;
ulong l;
time_t t;
time_t start;
time_t initialized=0;
SOCKET high_socket_set;
pop3_t* pop3;
smtp_t* smtp;

rswindell
committed
struct timeval tv;
FILE* fp;
str_list_t sec_list;
startup=(mail_startup_t*)arg;
#ifdef _THREAD_SUID_BROKEN
if(thread_suid_broken)
startup->seteuid(TRUE);
#endif
sbbs_beep(100,500);
fprintf(stderr, "No startup structure passed!\n");
return;
}
if(startup->size!=sizeof(mail_startup_t)) { /* verify size */
sbbs_beep(100,500);
sbbs_beep(300,500);
sbbs_beep(100,500);
fprintf(stderr, "Invalid startup structure!\n");
return;
}
/* Setup intelligent defaults */
if(startup->relay_port==0) startup->relay_port=IPPORT_SMTP;
if(startup->submission_port==0) startup->submission_port=IPPORT_SUBMISSION;
if(startup->smtp_port==0) startup->smtp_port=IPPORT_SMTP;
if(startup->pop3_port==0) startup->pop3_port=IPPORT_POP3;
if(startup->rescan_frequency==0) startup->rescan_frequency=3600; /* 60 minutes */
if(startup->max_delivery_attempts==0) startup->max_delivery_attempts=50;
if(startup->max_inactivity==0) startup->max_inactivity=120; /* seconds */
if(startup->max_recipients==0) startup->max_recipients=100;
if(startup->sem_chk_freq==0) startup->sem_chk_freq=2;

rswindell
committed
#ifdef JAVASCRIPT
if(startup->js.max_bytes==0) startup->js.max_bytes=JAVASCRIPT_MAX_BYTES;
if(startup->js.cx_stack==0) startup->js.cx_stack=JAVASCRIPT_CONTEXT_STACK;
#endif
uptime=0;
served=0;
startup->recycle_now=FALSE;
startup->shutdown_now=FALSE;
terminate_server=FALSE;
SetThreadName("Mail Server");
do {
thread_up(FALSE /* setuid */);
status("Initializing");
memset(&scfg, 0, sizeof(scfg));
lprintf(LOG_INFO,"Synchronet Mail Server Revision %s%s"
," Debug"
lprintf(LOG_INFO,"Compiled %s %s with %s", __DATE__, __TIME__, compiler);
lprintf(LOG_INFO,"SMBLIB %s (format %x.%02x)",smb_lib_ver(),smb_ver()>>8,smb_ver()&0xff);
sbbs_srand();
if(!winsock_startup()) {

rswindell
committed
cleanup(1);
return;
}
t=time(NULL);
lprintf(LOG_INFO,"Initializing on %.24s with options: %lx"
,ctime_r(&t,str),startup->options);
/* Initial configuration and load from CNF files */
SAFECOPY(scfg.ctrl_dir,startup->ctrl_dir);
lprintf(LOG_INFO,"Loading configuration files from %s", scfg.ctrl_dir);
scfg.size=sizeof(scfg);
SAFECOPY(error,UNKNOWN_LOAD_ERROR);
if(!load_cfg(&scfg, NULL, TRUE, error)) {
lprintf(LOG_ERR,"!ERROR %s",error);
lprintf(LOG_ERR,"!Failed to load configuration files");
cleanup(1);
return;
}
if(startup->temp_dir[0])
SAFECOPY(scfg.temp_dir,startup->temp_dir);
else
SAFECOPY(scfg.temp_dir,"../temp");
prep_dir(scfg.ctrl_dir, scfg.temp_dir, sizeof(scfg.temp_dir));
MKDIR(scfg.temp_dir);
lprintf(LOG_DEBUG,"Temporary file directory: %s", scfg.temp_dir);
if(!isdir(scfg.temp_dir)) {
lprintf(LOG_ERR,"!Invalid temp directory: %s", scfg.temp_dir);
cleanup(1);
return;
}
/* Parse the mailproc[.host].ini */
mailproc_list=NULL;
mailproc_count=0;
iniFileName(path,sizeof(path),scfg.ctrl_dir,"mailproc.ini");
if((fp=iniOpenFile(path, /* create? */FALSE))!=NULL) {
lprintf(LOG_DEBUG,"Reading %s",path);
sec_list = iniReadSectionList(fp,/* prefix */NULL);
if((mailproc_count=strListCount(sec_list))!=0
&& (mailproc_list=malloc(mailproc_count*sizeof(struct mailproc)))!=NULL) {
for(i=0;i<mailproc_count;i++) {
memset(&mailproc_list[i],0,sizeof(struct mailproc));
SAFECOPY(mailproc_list[i].cmdline,sec_list[i]);
mailproc_list[i].to =
iniReadStringList(fp,sec_list[i],"to",",",NULL);
mailproc_list[i].passthru =
iniReadBool(fp,sec_list[i],"passthru",TRUE);
mailproc_list[i].native =
iniReadBool(fp,sec_list[i],"native",FALSE);
}
}
iniFreeStringList(sec_list);
iniCloseFile(fp);
}
if(startup->host_name[0]==0)
SAFECOPY(startup->host_name,scfg.sys_inetaddr);
if((t=checktime())!=0) { /* Check binary time */
lprintf(LOG_ERR,"!TIME PROBLEM (%ld)",t);
}
if(uptime==0)
uptime=time(NULL); /* this must be done *after* setting the timezone */
if(startup->max_clients==0) {
startup->max_clients=scfg.sys_nodes;
if(startup->max_clients<10)
startup->max_clients=10;
}
lprintf(LOG_DEBUG,"Maximum clients: %u",startup->max_clients);
lprintf(LOG_DEBUG,"Maximum inactivity: %u seconds",startup->max_inactivity);
active_clients=0,update_clients();
/* open a socket and wait for a client */
server_socket = mail_open_socket(SOCK_STREAM,"smtp");
if(server_socket == INVALID_SOCKET) {
lprintf(LOG_ERR,"!ERROR %d opening socket", ERROR_VALUE);
cleanup(1);
return;
}
lprintf(LOG_DEBUG,"%04d SMTP socket opened",server_socket);
/*****************************/
/* Listen for incoming calls */
/*****************************/
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_addr.s_addr = htonl(startup->interface_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(startup->smtp_port);
if(startup->smtp_port < IPPORT_RESERVED) {
if(startup->seteuid!=NULL)
startup->seteuid(FALSE);
}
result = retry_bind(server_socket,(struct sockaddr *)&server_addr,sizeof(server_addr)
,startup->bind_retry_count,startup->bind_retry_delay,"SMTP Server",lprintf);
if(startup->smtp_port < IPPORT_RESERVED) {
if(startup->seteuid!=NULL)
startup->seteuid(TRUE);
}
lprintf(LOG_ERR,"%04d %s",server_socket, BIND_FAILURE_HELP);
cleanup(1);
return;
}
lprintf(LOG_DEBUG,"%04d SMTP socket bound to port %u"
,server_socket, startup->smtp_port);
result = listen(server_socket, 1);
lprintf(LOG_ERR,"%04d !ERROR %d (%d) listening on socket"
,server_socket, result, ERROR_VALUE);
cleanup(1);
return;
}
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
if(startup->options&MAIL_OPT_USE_SUBMISSION_PORT) {
submission_socket = mail_open_socket(SOCK_STREAM,"submission");
if(submission_socket == INVALID_SOCKET) {
lprintf(LOG_ERR,"!ERROR %d opening socket", ERROR_VALUE);
cleanup(1);
return;
}
lprintf(LOG_DEBUG,"%04d SUBMISSION socket opened",submission_socket);
/*****************************/
/* Listen for incoming calls */
/*****************************/
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_addr.s_addr = htonl(startup->interface_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(startup->submission_port);
if(startup->submission_port < IPPORT_RESERVED) {
if(startup->seteuid!=NULL)
startup->seteuid(FALSE);
}
result = retry_bind(submission_socket,(struct sockaddr *)&server_addr,sizeof(server_addr)
,startup->bind_retry_count,startup->bind_retry_delay,"SMTP Submission Agent",lprintf);
if(startup->submission_port < IPPORT_RESERVED) {
if(startup->seteuid!=NULL)
startup->seteuid(TRUE);
}
if(result != 0) {
lprintf(LOG_ERR,"%04d %s",submission_socket, BIND_FAILURE_HELP);
cleanup(1);
return;
}
lprintf(LOG_DEBUG,"%04d SUBMISSION socket bound to port %u"
,submission_socket, startup->submission_port);
result = listen(submission_socket, 1);
if(result != 0) {
lprintf(LOG_ERR,"%04d !ERROR %d (%d) listening on socket"
,submission_socket, result, ERROR_VALUE);
cleanup(1);
return;
}
}
if(startup->options&MAIL_OPT_ALLOW_POP3) {
/* open a socket and wait for a client */
pop3_socket = mail_open_socket(SOCK_STREAM,"pop3");
lprintf(LOG_ERR,"!ERROR %d opening POP3 socket", ERROR_VALUE);
cleanup(1);
return;
}
lprintf(LOG_DEBUG,"%04d POP3 socket opened",pop3_socket);
/*****************************/
/* Listen for incoming calls */
/*****************************/
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_addr.s_addr = htonl(startup->interface_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(startup->pop3_port);
if(startup->pop3_port < IPPORT_RESERVED) {
if(startup->seteuid!=NULL)
startup->seteuid(FALSE);
}
result = retry_bind(pop3_socket,(struct sockaddr *)&server_addr,sizeof(server_addr)
,startup->bind_retry_count,startup->bind_retry_delay,"POP3 Server",lprintf);
if(startup->pop3_port < IPPORT_RESERVED) {
if(startup->seteuid!=NULL)
startup->seteuid(FALSE);
}
lprintf(LOG_ERR,"%04d %s",pop3_socket,BIND_FAILURE_HELP);
cleanup(1);
return;
}
lprintf(LOG_DEBUG,"%04d POP3 socket bound to port %u"
,pop3_socket, startup->pop3_port);
result = listen(pop3_socket, 1);
lprintf(LOG_ERR,"%04d !ERROR %d (%d) listening on POP3 socket"
,pop3_socket, result, ERROR_VALUE);
cleanup(1);
return;
sem_init(&sendmail_wakeup_sem,0,0);
if(!(startup->options&MAIL_OPT_NO_SENDMAIL))
_beginthread(sendmail_thread, 0, NULL);
lprintf(LOG_NOTICE,"%04d Mail Server thread started",server_socket);
status(STATUS_WFC);
/* Setup recycle/shutdown semaphore file lists */
shutdown_semfiles=semfile_list_init(scfg.ctrl_dir,"shutdown","mail");
recycle_semfiles=semfile_list_init(scfg.ctrl_dir,"recycle","mail");
SAFEPRINTF(path,"%smailsrvr.rec",scfg.ctrl_dir); /* legacy */
semfile_list_add(&recycle_semfiles,path);
if(!initialized) {
semfile_list_check(&initialized,recycle_semfiles);
semfile_list_check(&initialized,shutdown_semfiles);
/* signal caller that we've started up successfully */
if(startup->started!=NULL)
startup->started(startup->cbdata);
while(server_socket!=INVALID_SOCKET && !terminate_server) {
if(active_clients==0) {
if(!(startup->options&MAIL_OPT_NO_RECYCLE)) {
if((p=semfile_list_check(&initialized,recycle_semfiles))!=NULL) {
lprintf(LOG_INFO,"%04d Recycle semaphore file (%s) detected"
,server_socket,p);
break;
}
if(startup->recycle_now==TRUE) {
lprintf(LOG_NOTICE,"%04d Recycle semaphore signaled", server_socket);
startup->recycle_now=FALSE;
break;
}
if(((p=semfile_list_check(&initialized,shutdown_semfiles))!=NULL
&& lprintf(LOG_INFO,"%04d Shutdown semaphore file (%s) detected"
,server_socket,p))
|| (startup->shutdown_now==TRUE
&& lprintf(LOG_INFO,"%04d Shutdown semaphore signaled",server_socket))) {
startup->shutdown_now=FALSE;
terminate_server=TRUE;
break;
}
/* now wait for connection */
FD_ZERO(&socket_set);
FD_SET(server_socket,&socket_set);
high_socket_set=server_socket+1;
if(startup->options&MAIL_OPT_ALLOW_POP3
&& pop3_socket!=INVALID_SOCKET) {
FD_SET(pop3_socket,&socket_set);
if(pop3_socket+1>high_socket_set)
high_socket_set=pop3_socket+1;
if(startup->options&MAIL_OPT_USE_SUBMISSION_PORT
&& submission_socket!=INVALID_SOCKET) {
FD_SET(submission_socket,&socket_set);
if(submission_socket+1>high_socket_set)
high_socket_set=submission_socket+1;
}
tv.tv_sec=startup->sem_chk_freq;
tv.tv_usec=0;
if((i=select(high_socket_set,&socket_set,NULL,NULL,&tv))<1) {
continue;
if(ERROR_VALUE==EINTR)
lprintf(LOG_DEBUG,"%04d Mail Server listening interrupted",server_socket);
else if(ERROR_VALUE == ENOTSOCK)
lprintf(LOG_NOTICE,"%04d Mail Server sockets closed",server_socket);
lprintf(LOG_WARNING,"%04d !ERROR %d selecting sockets",server_socket,ERROR_VALUE);
continue;
if(server_socket!=INVALID_SOCKET && !terminate_server
&& (FD_ISSET(server_socket,&socket_set)
|| (startup->options&MAIL_OPT_USE_SUBMISSION_PORT
&& FD_ISSET(submission_socket,&socket_set)))) {
client_addr_len = sizeof(client_addr);
client_socket = accept(
FD_ISSET(server_socket,&socket_set) ? server_socket:submission_socket
,(struct sockaddr *)&client_addr
,&client_addr_len);
#if 0 /* is this necessary still? */
if(ERROR_VALUE == ENOTSOCK || ERROR_VALUE == EINVAL) {
lprintf(LOG_NOTICE,"%04d SMTP socket closed while listening"
,server_socket);
break;
}
#endif
lprintf(LOG_WARNING,"%04d SMTP !ERROR %d accepting connection"
,FD_ISSET(server_socket,&socket_set) ? server_socket:submission_socket
,ERROR_VALUE);
#ifdef _WIN32
if(WSAGetLastError()==WSAENOBUFS) /* recycle (re-init WinSock) on this error */
break;
#endif
continue;
}
if(startup->socket_open!=NULL)
startup->socket_open(startup->cbdata,TRUE);
sockets++;
if(trashcan(&scfg,inet_ntoa(client_addr.sin_addr),"ip-silent")) {
mail_close_socket(client_socket);
continue;
}
if(active_clients>=startup->max_clients) {
lprintf(LOG_WARNING,"%04d SMTP !MAXIMUM CLIENTS (%u) reached, access denied"
,client_socket, startup->max_clients);
sockprintf(client_socket,"421 Maximum active clients reached, please try again later.");
mswait(3000);
mail_close_socket(client_socket);
continue;
}
if((i=ioctlsocket(client_socket, FIONBIO, &l))!=0) {
lprintf(LOG_ERR,"%04d SMTP !ERROR %d (%d) disabling blocking on socket"
,client_socket, i, ERROR_VALUE);
mail_close_socket(client_socket);
continue;
}
if((smtp=malloc(sizeof(smtp_t)))==NULL) {
lprintf(LOG_CRIT,"%04d SMTP !ERROR allocating %u bytes of memory for smtp_t"
,client_socket, sizeof(smtp_t));
mail_close_socket(client_socket);
continue;
}
smtp->socket=client_socket;
smtp->client_addr=client_addr;
_beginthread(smtp_thread, 0, smtp);
served++;
if(pop3_socket!=INVALID_SOCKET
&& FD_ISSET(pop3_socket,&socket_set)) {
client_addr_len = sizeof(client_addr);
client_socket = accept(pop3_socket, (struct sockaddr *)&client_addr
,&client_addr_len);
#if 0 /* is this necessary still? */
if(ERROR_VALUE == ENOTSOCK || ERROR_VALUE == EINVAL) {
lprintf(LOG_NOTICE,"%04d POP3 socket closed while listening",pop3_socket);
break;
}
#endif
lprintf(LOG_WARNING,"%04d POP3 !ERROR %d accepting connection"
,pop3_socket, ERROR_VALUE);
#ifdef _WIN32
if(WSAGetLastError()==WSAENOBUFS) /* recycle (re-init WinSock) on this error */
break;
#endif
continue;
}
if(startup->socket_open!=NULL)
startup->socket_open(startup->cbdata,TRUE);
sockets++;
if(trashcan(&scfg,inet_ntoa(client_addr.sin_addr),"ip-silent")) {
mail_close_socket(client_socket);
continue;
}
if(active_clients>=startup->max_clients) {
lprintf(LOG_WARNING,"%04d POP3 !MAXIMUM CLIENTS (%u) reached, access denied"
,client_socket, startup->max_clients);
sockprintf(client_socket,"-ERR Maximum active clients reached, please try again later.");
mswait(3000);
mail_close_socket(client_socket);
continue;
}
l=1;
if((i=ioctlsocket(client_socket, FIONBIO, &l))!=0) {
lprintf(LOG_ERR,"%04d POP3 !ERROR %d (%d) disabling blocking on socket"
,client_socket, i, ERROR_VALUE);
sockprintf(client_socket,"-ERR System error, please try again later.");
mswait(3000);
mail_close_socket(client_socket);
continue;
}
if((pop3=malloc(sizeof(pop3_t)))==NULL) {
lprintf(LOG_CRIT,"%04d POP3 !ERROR allocating %u bytes of memory for pop3_t"
,client_socket,sizeof(pop3_t));
sockprintf(client_socket,"-ERR System error, please try again later.");
mswait(3000);
mail_close_socket(client_socket);
continue;
}
pop3->socket=client_socket;
pop3->client_addr=client_addr;
_beginthread(pop3_thread, 0, pop3);
served++;
if(active_clients) {
lprintf(LOG_DEBUG,"%04d Waiting for %d active clients to disconnect..."
,server_socket, active_clients);
start=time(NULL);
while(active_clients) {
if(time(NULL)-start>startup->max_inactivity) {
lprintf(LOG_WARNING,"%04d !TIMEOUT waiting for %d active clients"
,server_socket, active_clients);
break;
}
mswait(100);
if(sendmail_running) {
terminate_sendmail=TRUE;
sem_post(&sendmail_wakeup_sem);
mswait(100);
}
if(sendmail_running) {
lprintf(LOG_DEBUG,"%04d Waiting for SendMail thread to terminate..."
,server_socket);
start=time(NULL);
while(sendmail_running) {
if(time(NULL)-start>TIMEOUT_THREAD_WAIT) {
lprintf(LOG_WARNING,"%04d !TIMEOUT waiting for sendmail thread to terminate"
,server_socket);
break;
}
mswait(500);
if(!sendmail_running) {
while(sem_destroy(&sendmail_wakeup_sem)==-1 && errno==EBUSY) {
mswait(1);
cleanup(0);
if(!terminate_server) {
lprintf(LOG_INFO,"Recycling server...");
if(startup->recycle!=NULL)
startup->recycle(startup->cbdata);
} while(!terminate_server);