popper.c
上传用户:dayuan858
上传日期:2007-01-04
资源大小:194k
文件大小:9k
源码类别:

网络编程

开发平台:

Unix_Linux

  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.  * Copyright (c) 1997 by Qualcomm Incorporated.
  8.  */
  9. #include <config.h>
  10. #include <stdio.h>
  11. #include <sys/types.h>
  12. #include <signal.h>
  13. #include <setjmp.h>
  14. #include <ctype.h>
  15. #ifdef POPSCO
  16. # include <sys/security.h>
  17. # include <sys/audit.h>
  18. # include <prot.h>
  19. # define VOIDSTAR
  20. # ifdef SCOR5
  21. #  define VOIDSTAR (void (*)(int))
  22. # endif
  23. #else
  24. # ifdef AIX
  25. #  define VOIDSTAR (void (*)(int))
  26. # else
  27. #  define VOIDSTAR (void *)
  28. # endif
  29. #endif
  30. #if defined(AUTH_SPECIAL)
  31. # ifdef HAVE_SYS_SECURITY_H 
  32. #  include <sys/security.h>
  33. # endif
  34. # ifdef HAVE_PROTO_H
  35. #  include <prot.h>
  36. # endif
  37. #endif
  38. #include <popper.h>
  39. #ifndef HAVE_STRERROR
  40. char * strerror();
  41. #endif
  42. extern  state_table *   pop_get_command();
  43. int hangup = FALSE ;
  44. int catchSIGHUP();
  45. int poptimeout = 0;
  46. int pop_timeout = POP_TIMEOUT;
  47. FILE *debuglog;
  48. /* 
  49.  *  popper: Handle a Post Office Protocol version 3 session
  50.  */
  51. main (argc, argv)
  52. int         argc;
  53. char    **  argv;
  54. {
  55.     POP                 p;
  56.     state_table     *   s;
  57.     char                message[MAXLINELEN];
  58.     char            *   tgets();
  59. #if defined(AUTH_SPECIAL) && defined(HAVE_SET_AUTH_PARAMETERS)
  60.     (void) set_auth_parameters(argc, argv);
  61. #endif
  62. #ifdef AUX
  63.     (void)set42sig();
  64. #endif
  65.     /* Set umask for better security */
  66. #ifdef BINMAIL_IS_SETGID
  67.     umask(0007); /* Trust the mail delivery group */
  68. #else
  69.     umask(0077); /* Trust no-one */
  70. #endif
  71.     (void) signal(SIGHUP,VOIDSTAR catchSIGHUP);
  72.     (void) signal(SIGPIPE,VOIDSTAR catchSIGHUP);
  73.     /*  Start things rolling */
  74.     if (pop_init(&p,argc,argv) != POP_SUCCESS)
  75. exit(1);
  76.     /*  Tell the user that we are listenting */
  77. #ifdef APOP
  78.     sprintf(p.md5str, "<%d.%d@%s>", getpid(), time((TIME_T *)0), p.myhost);
  79. #else
  80.     p.md5str[0] = '';
  81. #endif
  82.     pop_msg(&p, POP_SUCCESS, "QPOP (version %s) at %s starting.  %s",
  83. VERSION, p.myhost, p.md5str);
  84.     /*  State loop.  The POP server is always in a particular state in 
  85.         which a specific suite of commands can be executed.  The following 
  86.         loop reads a line from the client, gets the command, and processes 
  87.         it in the current context (if allowed) or rejects it.  This continues 
  88.         until the client quits or an error occurs. */
  89.     for (p.CurrentState=auth1;p.CurrentState!=halt&&p.CurrentState!=error;) {
  90. #ifdef SETPROCTITLE
  91. setproctitle("%s@%s [%s]: cmd read", p.user, p.client, p.ipaddr);
  92. #endif
  93.         if (hangup) {
  94.             pop_msg(&p,POP_FAILURE,"POP hangup",p.myhost);
  95. #ifndef NOUPDATEONABORT
  96.             if ((p.CurrentState != auth1) && (p.CurrentState != auth2) &&
  97. !pop_updt(&p))
  98.                 pop_msg(&p,POP_FAILURE,"POP mailbox update failed.",p.myhost);
  99. #else
  100.     if ((p.CurrentState != auth1) && (p.CurrentState != auth2) &&
  101. !pop_restore(&p))
  102.       pop_msg(&p, POP_FAILURE,"POP mailbox restoration failed.",p.myhost);
  103. #endif
  104.             p.CurrentState = error;
  105.         } else if (tgets(message,MAXLINELEN,p.input,pop_timeout) == NULL) {
  106.     if (poptimeout) {
  107.                 if (p.xmitting) pop_xmit_clean(&p);
  108. pop_msg(&p,POP_FAILURE,"POP timeout",p.myhost); 
  109.             }
  110.             
  111.     else
  112. pop_msg(&p,POP_FAILURE,"POP EOF received",p.myhost);
  113. #ifndef NOUPDATEONABORT
  114.             if ((p.CurrentState != auth1) && (p.CurrentState != auth2) &&
  115. !pop_updt(&p))
  116.                 pop_msg(&p,POP_FAILURE,"POP mailbox update failed!",p.myhost);
  117. #else
  118.             if ((p.CurrentState != auth1) && (p.CurrentState != auth2) &&
  119.                 !pop_restore(&p))
  120.                 pop_msg(&p,POP_FAILURE,"POP mailbox restoration failed!",p.myhost);
  121. #endif
  122.             p.CurrentState = error;
  123.         } else if (p.xmitting) { /* After the xtnd xmit initiates the mail txfer */
  124.             pop_xmit_recv(&p,message);
  125.         } else if ((s = pop_get_command(&p,message)) != NULL) {
  126.             if (s->function != NULL) {
  127. #ifdef SETPROCTITLE
  128. int i;
  129. char command[10];
  130. for (i = 0; s->command[i]; i++)
  131.     command[i] = toupper(s->command[i]);
  132. command[i] = 0;
  133. setproctitle("%s@%s [%s]: %s",
  134.     p.user, p.client, p.ipaddr, command);
  135. #endif
  136.                 p.CurrentState = s->result[(*s->function)(&p)];
  137.             } else {
  138.                 p.CurrentState = s->success_state;
  139.                 pop_msg(&p,POP_SUCCESS,NULL);
  140.             }
  141.         }
  142.     }
  143.     /*  Say goodbye to the client */
  144.     pop_msg(&p,POP_SUCCESS,"Pop server at %s signing off.",p.myhost);
  145. #ifdef DEBUG
  146.     /*  Log the end of activity */
  147.     if (p.debug)
  148. pop_log(&p,POP_PRIORITY,
  149.     "(v%s) Ending request from "%s" at (%s) %s",
  150. VERSION,p.user,p.client,p.ipaddr);
  151. #endif
  152.     /*  Stop logging */
  153.     closelog();
  154.     return(0);
  155. }
  156. jmp_buf env;
  157. /*
  158.  *  There seems to be a problem with the AIX fgets.  This is suppose to
  159.  *  fix it.
  160.  */
  161. char *
  162. myfgets(str, size, fp)
  163. char *str;
  164. int size;
  165. FILE *fp;
  166. {
  167. char *cp;
  168. char ch;
  169. int nbytes;
  170. int found_nl = 0;
  171. cp = str;
  172. while (--size > 0) {
  173.     if ((nbytes = read(fileno(fp), cp, 1)) <= 0)
  174. break;
  175.     if (*cp == 'n') {
  176. *++cp = '';
  177. found_nl++;
  178. break;
  179.     }
  180.     ++cp;
  181. }
  182. if ((nbytes <= 0) || (cp == str)) {
  183.     return(NULL);
  184. } else {
  185.     if (!found_nl)
  186. while ((read(fileno(fp), &ch, 1) == 1) && ch != 'n');
  187.     return(str);
  188. }
  189. }
  190. /*
  191.  * fgets, but with a timeout
  192.  */
  193. char *tgets(str,size,fp,timeout)
  194. char *str;
  195. int size;
  196. FILE *fp;
  197. int timeout;
  198. {
  199.   int ring();
  200.   (void) signal(SIGALRM, VOIDSTAR ring);
  201.   alarm(timeout);
  202.   if (setjmp(env))
  203.     str = NULL;
  204.   else
  205.     str = myfgets(str,size,fp);
  206. /*    str = fgets(str,size,fp); */
  207.   alarm(0);
  208.   signal(SIGALRM,SIG_DFL);
  209.   return(str);
  210. }
  211. int ring()
  212. {
  213.   poptimeout = 1;
  214.   longjmp(env,1);
  215. }
  216.   
  217. #ifdef STRNCASECMP
  218. /*
  219.  *  Perform a case-insensitive string comparision
  220.  */
  221. strncasecmp(str1,str2,len)
  222. register char   *   str1;
  223. register char   *   str2;
  224. register int        len;
  225. {
  226.     register int    i;
  227.     char            a,
  228.                     b;
  229.     for (i=len-1;i>=0;i--){
  230.         a = str1[i];
  231.         b = str2[i];
  232.         if (isupper(a)) a = tolower(str1[i]);
  233.         if (isupper(b)) b = tolower(str2[i]);
  234.         if (a > b) return (1);
  235.         if (a < b) return(-1);
  236.     }
  237.     return(0);
  238. }
  239. #endif
  240. int catchSIGHUP()
  241. {
  242.     extern int hangup ;
  243.     hangup = TRUE ;
  244.     /* This should not be a problem on BSD systems */
  245.     signal(SIGHUP,  VOIDSTAR catchSIGHUP);
  246.     signal(SIGPIPE,  VOIDSTAR catchSIGHUP);
  247. }
  248. #ifndef HAVE_STRERROR
  249. char *
  250. strerror(e)
  251. int e;
  252. {
  253. extern char *sys_errlist[];
  254. extern int sys_nerr;
  255. if(e < sys_nerr)
  256. return(sys_errlist[e]);
  257. else
  258. return("unknown error");
  259. }
  260. #endif
  261. #ifdef POPSCO
  262. /*
  263.  * Ftruncate() for non-BSD systems.
  264.  *
  265.  * This module gives the basic functionality for ftruncate() which
  266.  * truncates the given file descriptor to the given length.
  267.  * ftruncate() is a Berkeley system call, but does not exist in any
  268.  * form on many other versions of UNIX such as SysV. Note that Xenix
  269.  * has chsize() which changes the size of a given file descriptor,
  270.  * so that is used if M_XENIX is defined.
  271.  *
  272.  * Since there is not a known way to support this under generic SysV,
  273.  * there is no code generated for those systems.
  274.  *
  275.  * SPECIAL NOTE: On Xenix, using this call in the BSD library
  276.  * will REQUIRE the use of -lx for the extended library since chsize()
  277.  * is not in the standard C library.
  278.  *
  279.  * By Marc Frajola, 3/27/87
  280.  */
  281. #include <fcntl.h>
  282. ftruncate(fd,length)
  283.     int fd; /* File descriptor to truncate */
  284.     off_t length; /* Length to truncate file to */
  285. {
  286.     int status; /* Status returned from truncate proc */
  287.     status = chsize(fd,length);
  288. /*
  289.     status = -1;
  290.     NON-XENIX SYSTEMS CURRENTLY NOT SUPPORTED
  291. */
  292.     return(status);
  293. }
  294. #endif
  295. #ifndef HAVE_FTRUNCATE
  296. /* ftruncate emulations that work on some System V's.
  297.    This file is in the public domain.  */
  298. #ifdef HAVE_CONFIG_H
  299. #include <config.h>
  300. #endif
  301. #include <sys/types.h>
  302. #include <fcntl.h>
  303. #ifdef F_CHSIZE
  304. int
  305. ftruncate (fd, length)
  306.      int fd;
  307.      off_t length;
  308. {
  309.   return fcntl (fd, F_CHSIZE, length);
  310. }
  311. #else /* not F_CHSIZE */
  312. #ifdef F_FREESP
  313. /* By William Kucharski <kucharsk@netcom.com>.  */
  314. #include <sys/stat.h>
  315. #include <errno.h>
  316. #ifdef HAVE_UNISTD_H
  317. #include <unistd.h>
  318. #endif
  319. int
  320. ftruncate (fd, length)
  321.      int fd;
  322.      off_t length;
  323. {
  324.   struct flock fl;
  325.   struct stat filebuf;
  326.   if (fstat (fd, &filebuf) < 0)
  327.     return -1;
  328.   if (filebuf.st_size < length)
  329.     {
  330.       /* Extend file length. */
  331.       if (lseek (fd, (length - 1), SEEK_SET) < 0)
  332. return -1;
  333.       /* Write a "0" byte. */
  334.       if (write (fd, "", 1) != 1)
  335. return -1;
  336.     }
  337.   else
  338.     {
  339.       /* Truncate length. */
  340.       fl.l_whence = 0;
  341.       fl.l_len = 0;
  342.       fl.l_start = length;
  343.       fl.l_type = F_WRLCK; /* write lock on file space */
  344.       /* This relies on the *undocumented* F_FREESP argument to fcntl,
  345.  which truncates the file so that it ends at the position
  346.  indicated by fl.l_start.  Will minor miracles never cease?  */
  347.       if (fcntl (fd, F_FREESP, &fl) < 0)
  348. return -1;
  349.     }
  350.   return 0;
  351. }
  352. #else /* not F_CHSIZE nor F_FREESP */
  353. #ifdef HAVE_CHSIZE
  354. int
  355. ftruncate (fd, length)
  356.      int fd;
  357.      off_t length;
  358. {
  359.   return chsize (fd, length);
  360. }
  361. #else /* not F_CHSIZE nor F_FREESP nor HAVE_CHSIZE */
  362. #include <errno.h>
  363. #ifndef errno
  364. extern int errno;
  365. #endif
  366. int
  367. ftruncate (fd, length)
  368.      int fd;
  369.      off_t length;
  370. {
  371.   errno = EIO;
  372.   return -1;
  373. }
  374. #endif /* not HAVE_CHSIZE */
  375. #endif /* not F_FREESP */
  376. #endif /* not F_CHSIZE */
  377. #endif /*! HAVE_FTRUNCATE */