1/* 2 * Copyright (c) 1989 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7#include <popper.h> 8RCSID("$Id$"); 9 10int hangup = FALSE ; 11 12static RETSIGTYPE 13catchSIGHUP(int sig) 14{ 15 hangup = TRUE ; 16 17 /* This should not be a problem on BSD systems */ 18 signal(SIGHUP, catchSIGHUP); 19 signal(SIGPIPE, catchSIGHUP); 20 SIGRETURN(0); 21} 22 23int pop_timeout = POP_TIMEOUT; 24 25jmp_buf env; 26 27static RETSIGTYPE 28ring(int sig) 29{ 30 longjmp(env,1); 31} 32 33/* 34 * fgets, but with a timeout 35 */ 36static char * 37tgets(char *str, int size, FILE *fp, int timeout) 38{ 39 char *ret; 40 41 signal(SIGALRM, ring); 42 alarm(timeout); 43 if (setjmp(env)) { 44 alarm(0); 45 signal(SIGALRM, SIG_DFL); 46 return NULL; 47 } 48 ret = fgets(str, size, fp); 49 alarm(0); 50 signal(SIGALRM, SIG_DFL); 51 return ret; 52} 53 54/* 55 * popper: Handle a Post Office Protocol version 3 session 56 */ 57int 58main (int argc, char **argv) 59{ 60 POP p; 61 state_table * s; 62 char message[MAXLINELEN]; 63 64 signal(SIGHUP, catchSIGHUP); 65 signal(SIGPIPE, catchSIGHUP); 66 67 /* Start things rolling */ 68 pop_init(&p,argc,argv); 69 70 /* Tell the user that we are listenting */ 71 pop_msg(&p,POP_SUCCESS, "POP3 server ready"); 72 73 /* State loop. The POP server is always in a particular state in 74 which a specific suite of commands can be executed. The following 75 loop reads a line from the client, gets the command, and processes 76 it in the current context (if allowed) or rejects it. This continues 77 until the client quits or an error occurs. */ 78 79 for (p.CurrentState=auth1;p.CurrentState!=halt&&p.CurrentState!=error;) { 80 if (hangup) { 81 pop_msg(&p, POP_FAILURE, "POP hangup: %s", p.myhost); 82 if (p.CurrentState > auth2 && !pop_updt(&p)) 83 pop_msg(&p, POP_FAILURE, 84 "POP mailbox update failed: %s", p.myhost); 85 p.CurrentState = error; 86 } else if (tgets(message, MAXLINELEN, p.input, pop_timeout) == NULL) { 87 pop_msg(&p, POP_FAILURE, "POP timeout: %s", p.myhost); 88 if (p.CurrentState > auth2 && !pop_updt(&p)) 89 pop_msg(&p,POP_FAILURE, 90 "POP mailbox update failed: %s", p.myhost); 91 p.CurrentState = error; 92 } 93 else { 94 /* Search for the command in the command/state table */ 95 if ((s = pop_get_command(&p,message)) == NULL) continue; 96 97 /* Call the function associated with this command in 98 the current state */ 99 if (s->function) p.CurrentState = s->result[(*s->function)(&p)]; 100 101 /* Otherwise assume NOOP and send an OK message to the client */ 102 else { 103 p.CurrentState = s->success_state; 104 pop_msg(&p,POP_SUCCESS,"time passes"); 105 } 106 } 107 } 108 109 /* Say goodbye to the client */ 110 pop_msg(&p,POP_SUCCESS,"Pop server at %s signing off.",p.myhost); 111 112 /* Log the end of activity */ 113 pop_log(&p,POP_PRIORITY, 114 "(v%s) Ending request from \"%s\" at %s\n",VERSION,p.client,p.ipaddr); 115 116 /* Stop logging */ 117 closelog(); 118 119 return(0); 120} 121