home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / CONTRIB / HTTPD / HTTPD_SO.TAR / httpd_1.3 / src / httpd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-07  |  6.5 KB  |  269 lines

  1. /*
  2.  * httpd.c: simple http daemon for answering WWW file requests
  3.  *
  4.  * 
  5.  * Rob McCool 3/21/93
  6.  * 
  7.  */
  8.  
  9.  
  10. #include "httpd.h"
  11.  
  12. void usage(char *bin) {
  13.     fprintf(stderr,"Usage: %s [-d directory] [-f file] [-v]\n",bin);
  14.     fprintf(stderr,"-d directory : specify an alternate initial ServerRoot\n");
  15.     fprintf(stderr,"-f file : specify an alternate ServerConfigFile\n");
  16.     exit(1);
  17. }
  18.  
  19. void htexit(int status, FILE *out) {
  20. #ifdef PEM_AUTH
  21.     pem_cleanup(status,out);
  22. #endif
  23.     exit(status);
  24. }
  25.  
  26. int sd;
  27. pid_t pgrp;
  28.  
  29. void detach() {
  30.     int x;
  31.  
  32.     chdir("/");
  33.     if((x = fork()) > 0)
  34.         exit(0);
  35.     else if(x == -1) {
  36.         fprintf(stderr,"httpd: unable to fork new process\n");
  37.         perror("fork");
  38.         exit(1);
  39.     }
  40. #ifndef NO_SETSID
  41.     if((pgrp=setsid()) == -1) {
  42.         fprintf(stderr,"httpd: setsid failed\n");
  43.         perror("setsid");
  44.         exit(1);
  45.     }
  46. #else
  47.     if((pgrp=setpgrp(getpid(),0)) == -1) {
  48.         fprintf(stderr,"httpd: setpgrp failed\n");
  49.         perror("setpgrp");
  50.         exit(1);
  51.     }
  52. #endif    
  53. }
  54.  
  55. void sig_term() {
  56.     log_error("httpd: caught SIGTERM, shutting down");
  57. #ifndef NO_KILLPG
  58.     killpg(pgrp,SIGKILL);
  59. #else
  60.     kill(-pgrp,SIGKILL);
  61. #endif
  62.     shutdown(sd,2);
  63.     close(sd);
  64. }
  65.  
  66. #ifdef BSD
  67. void ign() {
  68. #ifndef NEXT
  69.     int status;
  70. #else
  71.     union wait status;
  72. #endif
  73.     pid_t pid;
  74.  
  75.     while( (pid = wait3(&status, WNOHANG, NULL)) > 0);
  76. }
  77. #endif
  78.  
  79. void bus_error() {
  80.     log_error("httpd: caught SIGBUS, dumping core");
  81.     chdir(server_root);
  82.     abort();         
  83. }
  84.  
  85. void seg_fault() {
  86.     log_error("httpd: caught SIGSEGV, dumping core");
  87.     chdir(server_root);
  88.     abort();
  89. }
  90.  
  91. void set_signals();
  92.  
  93. void restart() {
  94.     log_error_noclose("httpd: caught SIGHUP, restarting");
  95.     kill_mime();
  96.     kill_security();
  97.     kill_indexing();
  98.     if(server_hostname) {
  99.         free(server_hostname);
  100.         server_hostname = NULL;
  101.     }
  102.     read_config(error_log);
  103.     close_logs();
  104.     open_logs();
  105.     log_error_noclose("httpd: successful restart");
  106.     get_local_host();
  107.     set_signals();
  108. }
  109.  
  110. void set_signals() {
  111.     signal(SIGSEGV,(void (*)())seg_fault);
  112.     signal(SIGBUS,(void (*)())bus_error);
  113.     signal(SIGTERM,(void (*)())sig_term);
  114.     signal(SIGHUP,(void (*)())restart);
  115.  
  116. #ifdef BSD
  117.     signal(SIGCHLD,(void (*)())ign);
  118. #else
  119.     signal(SIGCHLD,SIG_IGN);
  120. #endif
  121. }
  122.  
  123.  
  124. void standalone_main() {
  125.     int csd, clen,pid, one=1;
  126. #ifdef NEXT
  127.     struct sockaddr_in sa_server;
  128.     struct sockaddr sa_client;
  129. #else
  130.     struct sockaddr_in sa_server,sa_client;
  131. #endif
  132.  
  133.     detach();
  134.  
  135.     if ((sd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) {
  136.         fprintf(stderr,"httpd: could not get socket\n");
  137.         perror("socket");
  138.         exit(1);
  139.     }
  140.  
  141.     if((setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one))) == -1) {
  142.         fprintf(stderr,"httpd: could not set socket option\n");
  143.         perror("setsockopt");
  144.         exit(1);
  145.     }
  146.     bzero((char *) &sa_server, sizeof(sa_server));
  147.     sa_server.sin_family=AF_INET;
  148.     sa_server.sin_addr.s_addr=htonl(INADDR_ANY);
  149.     sa_server.sin_port=htons(port);
  150.     if(bind(sd,(struct sockaddr *) &sa_server,sizeof(sa_server)) == -1) {
  151.         fprintf(stderr,"httpd: could not bind to port %d\n",port);
  152.         perror("bind");
  153.         exit(1);
  154.     }
  155.     listen(sd,5);
  156.  
  157.     set_signals();
  158.     log_pid();
  159.  
  160.     while(1) {
  161.       retry:
  162.         clen=sizeof(sa_client);
  163.         if((csd=accept(sd,&sa_client,&clen)) == -1) {
  164.             if(errno == EINTR)  {
  165. #ifdef BSD
  166.                 ign();
  167. #endif
  168.                 goto retry;
  169.             }
  170.             log_error("socket error: accept failed");
  171.             goto retry;
  172.         }
  173.     /* we do this here so that logs can be opened as root */
  174.         if((pid = fork()) == -1)
  175.             log_error("unable to fork new process");
  176.         else if(!pid) {
  177.         struct passwd* pwent;
  178.             struct linger sl;
  179.  
  180.             sl.l_onoff = 1;
  181.             sl.l_linger = 600; /* currently ignored anyway */
  182.             /* this should check error status, but it's not crucial */
  183.             setsockopt(csd,SOL_SOCKET,SO_LINGER,&sl,sizeof(sl));
  184.  
  185.             close(0);
  186.             close(1);
  187.             dup2(csd,0);
  188.             dup2(csd,1);
  189.             close(sd);
  190.  
  191.             remote_logname = (!do_rfc931 ? NULL :
  192.                               rfc931((struct sockaddr_in *)&sa_client,
  193.                                      &sa_server));
  194.  
  195.             /* Only try to switch if we're running as root */
  196.             if(!getuid()) {
  197.                 /* Now, make absolutely certain we don't have any privileges
  198.                  * except those mentioned in the configuration file. */
  199.                 if ((pwent = getpwuid(user_id)) == NULL)
  200.                     die(SERVER_ERROR,"couldn't determine user name from uid",
  201.                         stdout);
  202.                 /* Reset `groups' attribute. */
  203.                 if (initgroups(pwent->pw_name, group_id) == -1)
  204.                     die(SERVER_ERROR,"unable to setgroups",stdout);
  205.  
  206.                 /* Note the order, first setgid() and then setuid(), it
  207.                  * wouldn't work the other way around. */
  208.                 if (setgid(group_id) == -1)
  209.                     die(SERVER_ERROR,"unable to change gid",stdout);
  210.                 if (setuid(user_id) == -1)
  211.                     die(SERVER_ERROR,"unable to change uid",stdout);
  212.             }
  213.             process_request(0,stdout);
  214.             fclose(stdin);
  215.             fclose(stdout);
  216.             shutdown(csd,2);
  217.             close(csd);
  218.             exit(0);
  219.         }
  220.         close(csd);
  221.     }
  222. }
  223.  
  224. extern char *optarg;
  225. extern int optind;
  226.  
  227. main(int argc, char *argv[])
  228. {
  229.     int c;
  230.  
  231.     strcpy(server_root,HTTPD_ROOT);
  232.     make_full_path(server_root,SERVER_CONFIG_FILE,server_confname);
  233.  
  234.     while((c = getopt(argc,argv,"d:f:v")) != -1) {
  235.         switch(c) {
  236.           case 'd':
  237.             strcpy(server_root,optarg);
  238.       make_full_path(server_root,SERVER_CONFIG_FILE,server_confname);
  239.             break;
  240.           case 'f':
  241.             strcpy(server_confname,optarg);
  242.             break;
  243.           case 'v':
  244.             printf("NCSA httpd version %s.\n",SERVER_VERSION);
  245.             exit(1);
  246.           case '?':
  247.             usage(argv[0]);
  248.         }
  249.     }
  250.     read_config(stderr);
  251.     open_logs();
  252.     get_local_host();
  253.  
  254.     if(standalone)
  255.         standalone_main();
  256.     else {
  257.         user_id = getuid();
  258.         group_id = getgid();
  259.  
  260.         port = get_portnum(fileno(stdout),stdout);
  261.         if(do_rfc931)
  262.             remote_logname = get_remote_logname(stdout);
  263.         process_request(0,stdout);
  264.     }
  265.     fclose(stdin);
  266.     fclose(stdout);
  267.     exit(0);
  268. }
  269.