home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / WWW / apache_1.0.5 / src / http_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-16  |  26.4 KB  |  1,061 lines

  1.  
  2. /* ====================================================================
  3.  * Copyright (c) 1995 The Apache Group.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer. 
  11.  *
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in
  14.  *    the documentation and/or other materials provided with the
  15.  *    distribution.
  16.  *
  17.  * 3. All advertising materials mentioning features or use of this
  18.  *    software must display the following acknowledgment:
  19.  *    "This product includes software developed by the Apache Group
  20.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  21.  *
  22.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  23.  *    endorse or promote products derived from this software without
  24.  *    prior written permission.
  25.  *
  26.  * 5. Redistributions of any form whatsoever must retain the following
  27.  *    acknowledgment:
  28.  *    "This product includes software developed by the Apache Group
  29.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  30.  *
  31.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  32.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  34.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  35.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  36.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  37.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  38.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  42.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  43.  * ====================================================================
  44.  *
  45.  * This software consists of voluntary contributions made by many
  46.  * individuals on behalf of the Apache Group and was originally based
  47.  * on public domain software written at the National Center for
  48.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  49.  * For more information on the Apache Group and the Apache HTTP server
  50.  * project, please see <http://www.apache.org/>.
  51.  *
  52.  */
  53.  
  54.  
  55. /*
  56.  * httpd.c: simple http daemon for answering WWW file requests
  57.  *
  58.  * 
  59.  * 03-21-93  Rob McCool wrote original code (up to NCSA HTTPd 1.3)
  60.  * 
  61.  * 03-06-95  blong
  62.  *  changed server number for child-alone processes to 0 and changed name
  63.  *   of processes
  64.  *
  65.  * 03-10-95  blong
  66.  *     Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu) 
  67.  *    including set group before fork, and call gettime before to fork
  68.  *     to set up libraries.
  69.  *
  70.  * 04-14-95  rst / rh
  71.  *      Brandon's code snarfed from NCSA 1.4, but tinkered to work with the
  72.  *      Apache server, and also to have child processes do accept() directly.
  73.  *
  74.  * April-July '95 rst
  75.  *      Extensive rework for Shambhala.
  76.  */
  77.  
  78.  
  79. #define CORE_PRIVATE
  80.  
  81. #include "httpd.h"
  82. #include "http_main.h"
  83. #include "http_log.h"
  84. #include "http_config.h"    /* for read_config */
  85. #include "http_protocol.h"    /* for read_request */
  86. #include "http_request.h"    /* for process_request */
  87. #include "http_conf_globals.h"
  88. #include "scoreboard.h"
  89. #include <setjmp.h>
  90.  
  91. /*
  92.  * Actual definitions of config globals... here because this is
  93.  * for the most part the only code that acts on 'em.  (Hmmm... mod_main.c?)
  94.  */
  95.  
  96. int standalone;
  97. uid_t user_id;
  98. char *user_name;
  99. gid_t group_id;
  100. int max_requests_per_child;
  101. char *pid_fname;
  102. char *scoreboard_fname;
  103. char *server_argv0;
  104. struct in_addr bind_address;
  105. int daemons_to_start;
  106. int daemons_min_free;
  107. int daemons_max_free;
  108. int daemons_limit;
  109.  
  110. char server_root[MAX_STRING_LEN];
  111. char server_confname[MAX_STRING_LEN];
  112.  
  113. /* *Non*-shared http_main globals... */
  114.  
  115. server_rec *server_conf;
  116. JMP_BUF jmpbuffer;
  117. JMP_BUF restart_buffer;
  118. int sd;
  119. pid_t pgrp;
  120.  
  121. /* one_process --- debugging mode variable; can be set from the command line
  122.  * with the -X flag.  If set, this gets you the child_main loop running
  123.  * in the process which originally started up (no detach, no make_child),
  124.  * which is a pretty nice debugging environment.  (You'll get a SIGHUP
  125.  * early in standalone_main; just continue through.  This is the server
  126.  * trying to kill off any child processes which it might have lying
  127.  * around --- Shambhala doesn't keep track of their pids, it just sends
  128.  * SIGHUP to the process group, ignoring it in the root process.
  129.  * Continue through and you'll be fine.).
  130.  */
  131.  
  132. int one_process = 0;
  133.  
  134. #ifdef FCNTL_SERIALIZED_ACCEPT
  135. static struct flock lock_it = { F_WRLCK, 0, 0, 0 };
  136. static struct flock unlock_it = { F_UNLCK, 0, 0, 0 };
  137.  
  138. static int lock_fd=-1;
  139.  
  140. /*
  141.  * Initialise mutex lock.
  142.  * Must be safe to call this on a restart.
  143.  */
  144. void
  145. accept_mutex_init(pool *p)
  146. {
  147.     char lock_fname[30];
  148.  
  149.     strcpy(lock_fname, "/usr/tmp/htlock.XXXXXX");
  150.     
  151.     if (mktemp(lock_fname) == NULL || lock_fname[0] == '\0')
  152.     {
  153.     fprintf (stderr, "Cannot assign name to lock file!\n");
  154.     exit (1);
  155.     }
  156.  
  157.     lock_fd = popenf(p, lock_fname, O_CREAT | O_WRONLY, 0644);
  158.     if (lock_fd == -1)
  159.     {
  160.     perror ("open");
  161.     fprintf (stderr, "Cannot open lcok file\n");
  162.     exit (1);
  163.     }
  164.     unlink(lock_fname);
  165. }
  166.  
  167. void accept_mutex_on()
  168. {
  169.     int ret;
  170.     
  171.     while ((ret = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR)
  172.     continue;
  173.  
  174.     if (ret < 0) {
  175.     log_unixerr("fcntl", "F_SETLKW", "Error getting accept lock. Exiting!",
  176.             server_conf);
  177.     exit(1);
  178.     }
  179. }
  180.  
  181. void accept_mutex_off()
  182. {
  183.     if (fcntl (lock_fd, F_SETLKW, &unlock_it) < 0)
  184.     {
  185.     log_unixerr("fcntl", "F_SETLKW", "Error freeing accept lock. Exiting!",
  186.             server_conf);
  187.     exit(1);
  188.     }
  189. }
  190. #else
  191. /* Default --- no serialization.  Other methods *could* go here,
  192.  * as #elifs...
  193.  */
  194. #define accept_mutex_init(x)
  195. #define accept_mutex_on()
  196. #define accept_mutex_off()
  197. #endif
  198.  
  199. void usage(char *bin)
  200. {
  201.     fprintf(stderr,"Usage: %s [-d directory] [-f file] [-v]\n",bin);
  202.     fprintf(stderr,"-d directory : specify an alternate initial ServerRoot\n");
  203.     fprintf(stderr,"-f file : specify an alternate ServerConfigFile\n");
  204.     exit(1);
  205. }
  206.  
  207. /*****************************************************************
  208.  *
  209.  * Timeout handling.  DISTINCTLY not thread-safe, but all this stuff
  210.  * has to change for threads anyway.  Note that this code allows only
  211.  * one timeout in progress at a time...
  212.  */
  213.  
  214. static conn_rec *current_conn;
  215. static request_rec *timeout_req;
  216. static char *timeout_name = NULL;
  217. static int alarms_blocked = 0;
  218. static int alarm_pending = 0;
  219.  
  220. void abort_connection (conn_rec *);
  221.  
  222. void timeout(sig)            /* Also called on SIGPIPE */
  223. int sig;
  224. {
  225.     char errstr[MAX_STRING_LEN];
  226.  
  227.     if (alarms_blocked) {
  228.     alarm_pending = 1;
  229.     return;
  230.     }
  231.     
  232.     if (!current_conn) {
  233. #ifdef NEXT
  234.     longjmp(jmpbuffer,1);
  235. #else
  236.     siglongjmp(jmpbuffer,1);
  237. #endif
  238.     }
  239.     
  240.     if (sig == SIGPIPE) {
  241.         sprintf(errstr,"%s lost connection to client %s",
  242.         timeout_name ? timeout_name : "request",
  243.         current_conn->remote_name);
  244.     } else {
  245.         sprintf(errstr,"%s timed out for %s",
  246.         timeout_name ? timeout_name : "request",
  247.         current_conn->remote_name);
  248.     }
  249.     
  250.     log_error(errstr, current_conn->server);
  251.       
  252.     if (timeout_req) {
  253.     /* Someone has asked for this transaction to just be aborted
  254.      * if it times out...
  255.      */
  256.     
  257.     request_rec *log_req = timeout_req;
  258.     
  259.     while (log_req->main || log_req->prev) {
  260.         /* Get back to original request... */
  261.         if (log_req->main) log_req = log_req->main;
  262.         else log_req = log_req->prev;
  263.     }
  264.     
  265.     log_transaction(log_req);
  266.  
  267.     pfclose (timeout_req->connection->pool,
  268.          timeout_req->connection->client);
  269.     pfclose (timeout_req->connection->pool,
  270.              timeout_req->connection->request_in);
  271.     
  272.     if (!standalone) exit(0);
  273. #ifdef NEXT
  274.     longjmp(jmpbuffer,1);
  275. #else
  276.     siglongjmp(jmpbuffer,1);
  277. #endif
  278.     }
  279.     else {
  280.     abort_connection (current_conn);
  281.     }
  282. }
  283.  
  284. /*
  285.  * These two called from alloc.c to protect its critical sections...
  286.  * Note that they can nest (as when destroying the sub_pools of a pool
  287.  * which is itself being cleared); we have to support that here.
  288.  */
  289.  
  290. void block_alarms() {
  291.     ++alarms_blocked;
  292. }
  293.  
  294. void unblock_alarms() {
  295.     --alarms_blocked;
  296.     if (alarms_blocked == 0 && alarm_pending) {
  297.     alarm_pending = 0;
  298.     timeout(0);
  299.     }
  300. }
  301.  
  302. void hard_timeout (char *name, request_rec *r)
  303. {
  304.     timeout_req = r;
  305.     timeout_name = name;
  306.     
  307.     signal(SIGALRM,(void (*)())timeout);
  308.     alarm (r->server->timeout);
  309. }
  310.  
  311. void soft_timeout (char *name, request_rec *r)
  312. {
  313.     timeout_name = name;
  314.     
  315.     signal(SIGALRM,(void (*)())timeout);
  316.     alarm (r->server->timeout);
  317. }
  318.  
  319. void kill_timeout (request_rec *dummy) {
  320.     alarm (0);
  321.     timeout_req = NULL;
  322.     timeout_name = NULL;
  323. }
  324.  
  325. /* reset_timeout (request_rec *) resets the timeout in effect,
  326.  * as long as it hasn't expired already.
  327.  */
  328.  
  329. void reset_timeout (request_rec *r) {
  330.     int i;
  331.  
  332.     if (timeout_name) { /* timeout has been set */
  333.         i = alarm(r->server->timeout);
  334.         if (i == 0) /* timeout already expired, so set it back to 0 */
  335.         alarm(0);
  336.     }
  337. }
  338.  
  339. /*****************************************************************
  340.  *
  341.  * Dealing with the scoreboard... a lot of these variables are global
  342.  * only to avoid getting clobbered by the longjmp() that happens when
  343.  * a hard timeout expires...
  344.  *
  345.  * We begin with routines which deal with the file itself... 
  346.  */
  347.  
  348. static short_score scoreboard_image[HARD_SERVER_MAX];
  349. static int have_scoreboard_fname = 0;
  350. static int scoreboard_fd;
  351.  
  352. static int force_write (int fd, char *buffer, int bufsz)
  353. {
  354.     int rv, orig_sz = bufsz;
  355.     
  356.     do {
  357.     rv = write (fd, buffer, bufsz);
  358.     if (rv > 0) {
  359.         buffer += rv;
  360.         bufsz -= rv;
  361.     }
  362.     } while (rv > 0 && bufsz > 0);
  363.  
  364.     return rv < 0? rv : orig_sz - bufsz;
  365. }
  366.  
  367. static int force_read (int fd, char *buffer, int bufsz)
  368. {
  369.     int rv, orig_sz = bufsz;
  370.     
  371.     do {
  372.     rv = read (fd, buffer, bufsz);
  373.     if (rv > 0) {
  374.         buffer += rv;
  375.         bufsz -= rv;
  376.     }
  377.     } while (rv > 0 && bufsz > 0);
  378.     
  379.     return rv < 0? rv : orig_sz - bufsz;
  380. }
  381.  
  382. void reinit_scoreboard (pool *p)
  383. {
  384.     scoreboard_fname = server_root_relative (p, scoreboard_fname);
  385.  
  386.     have_scoreboard_fname = 1;
  387.     
  388.     scoreboard_fd = popenf(p, scoreboard_fname, O_CREAT|O_RDWR, 0644);
  389.     if (scoreboard_fd == -1)
  390.     {
  391.     fprintf (stderr, "Cannot open scoreboard file:\n");
  392.     perror (scoreboard_fname);
  393.     exit (1);
  394.     }
  395.  
  396.     memset ((char*)scoreboard_image, 0, sizeof(scoreboard_image));
  397.     force_write (scoreboard_fd, (char*)scoreboard_image,
  398.          sizeof(scoreboard_image));
  399. }
  400.  
  401. void reopen_scoreboard (pool *p)
  402. {
  403.     if (scoreboard_fd != -1) pclosef (p, scoreboard_fd);
  404.     
  405.     scoreboard_fd = popenf(p, scoreboard_fname, O_CREAT|O_RDWR, 0666);
  406.     if (scoreboard_fd == -1)
  407.     {
  408.     fprintf (stderr, "Cannot open scoreboard file:\n");
  409.     perror (scoreboard_fname);
  410.     exit (1);
  411.     }
  412. }
  413.  
  414. void cleanup_scoreboard ()
  415. {
  416.     unlink (scoreboard_fname);
  417. }
  418.  
  419. /* Routines called to deal with the scoreboard image
  420.  * --- note that we do *not* need write locks, since update_child_status
  421.  * only updates a *single* record in place, and only one process writes to
  422.  * a given scoreboard slot at a time (either the child process owning that
  423.  * slot, or the parent, noting that the child has died).
  424.  *
  425.  * As a final note --- setting the score entry to getpid() is always safe,
  426.  * since when the parent is writing an entry, it's only noting SERVER_DEAD
  427.  * anyway.
  428.  */
  429.  
  430. void sync_scoreboard_image ()
  431. {
  432.     lseek (scoreboard_fd, 0L, 0);
  433.     force_read (scoreboard_fd, (char*)scoreboard_image,
  434.         sizeof(scoreboard_image));
  435. }
  436.  
  437. void update_child_status (int child_num, int status)
  438. {
  439.     short_score new_score_rec;
  440.     new_score_rec.pid = getpid();
  441.     new_score_rec.status = status;
  442.  
  443.     lseek (scoreboard_fd, (long)child_num * sizeof(short_score), 0);
  444.     force_write (scoreboard_fd, (char*)&new_score_rec, sizeof(short_score));
  445. }
  446.  
  447. int count_idle_servers ()
  448. {
  449.     int i;
  450.     int res = 0;
  451.  
  452.     for (i = 0; i < HARD_SERVER_MAX; ++i)
  453.     if (scoreboard_image[i].status == SERVER_READY
  454.       || scoreboard_image[i].status == SERVER_STARTING)
  455.         ++res;
  456.  
  457.     return res;
  458. }
  459.  
  460. int find_free_child_num ()
  461. {
  462.     int i;
  463.  
  464.     for (i = 0; i < HARD_SERVER_MAX; ++i)
  465.     if (scoreboard_image[i].status == SERVER_DEAD)
  466.         return i;
  467.  
  468.     return -1;
  469. }
  470.  
  471. int find_child_by_pid (int pid)
  472. {
  473.     int i;
  474.  
  475.     for (i = 0; i < HARD_SERVER_MAX; ++i)
  476.     if (scoreboard_image[i].pid == pid)
  477.         return i;
  478.  
  479.     return -1;
  480. }
  481.  
  482. void reclaim_child_processes ()
  483. {
  484.     int i, status;
  485.     int my_pid = getpid();
  486.  
  487.     sync_scoreboard_image();
  488.     for (i = 0; i < HARD_SERVER_MAX; ++i) {
  489.     int pid = scoreboard_image[i].pid;
  490.  
  491.     if (pid != my_pid && pid != 0)
  492.         waitpid (scoreboard_image[i].pid, &status, 0);
  493.     }
  494. }
  495.  
  496. /* Finally, this routine is used by the caretaker process to wait for
  497.  * a while...
  498.  */
  499.  
  500. static jmp_buf wait_timeout_buf;
  501. static int wait_or_timeout_retval = -1;
  502.  
  503. static void longjmp_out_of_alarm (int sig) {
  504.     longjmp (wait_timeout_buf, 1);
  505. }
  506.  
  507. int wait_or_timeout (int *status)
  508. {
  509.     wait_or_timeout_retval = -1;
  510.     
  511.     if (setjmp(wait_timeout_buf) != 0) {
  512.     errno = ETIMEDOUT;
  513.     alarm(0);
  514.     return wait_or_timeout_retval;
  515.     }
  516.     
  517.     signal (SIGALRM, longjmp_out_of_alarm);
  518.     alarm(1);
  519. #if defined(NEXT)
  520.     wait_or_timeout_retval = wait((union wait *)status);
  521. #else
  522.     wait_or_timeout_retval = wait(status);
  523. #endif
  524.     alarm(0);
  525.     return wait_or_timeout_retval;
  526. }
  527.  
  528.  
  529. /*****************************************************************
  530.  * Here follows a long bunch of generic server bookkeeping stuff...
  531.  */
  532.  
  533. void detach()
  534. {
  535.     int x;
  536.  
  537.     chdir("/");
  538.     if((x = fork()) > 0)
  539.         exit(0);
  540.     else if(x == -1) {
  541.         fprintf(stderr,"httpd: unable to fork new process\n");
  542.         perror("fork");
  543.         exit(1);
  544.     }
  545. #ifndef NO_SETSID
  546.     if((pgrp=setsid()) == -1) {
  547.         fprintf(stderr,"httpd: setsid failed\n");
  548.         perror("setsid");
  549.         exit(1);
  550.     }
  551. #else
  552. #if defined(NEXT)
  553.     if(setpgrp(0,getpid()) == -1 || (pgrp = getpgrp(0)) == -1) {
  554.         fprintf(stderr,"httpd: setpgrp or getpgrp failed\n");
  555.         perror("setpgrp");
  556.         exit(1);
  557.     }
  558. #else
  559.     if((pgrp=setpgrp(getpid(),0)) == -1) {
  560.         fprintf(stderr,"httpd: setpgrp failed\n");
  561.         perror("setpgrp");
  562.         exit(1);
  563.     }
  564. #endif    
  565. #endif
  566. }
  567.  
  568. void sig_term() {
  569.     log_error("httpd: caught SIGTERM, shutting down", server_conf);
  570.     cleanup_scoreboard();
  571. #ifndef NO_KILLPG
  572.     killpg(pgrp,SIGKILL);
  573. #else
  574.     kill(-pgrp,SIGKILL);
  575. #endif
  576.     shutdown(sd,2);
  577.     close(sd);
  578.     exit(1);
  579. }
  580.  
  581. void bus_error() {
  582.     log_error("httpd: caught SIGBUS, dumping core", server_conf);
  583.     chdir(server_root);
  584.     abort();         
  585.     exit(1);
  586. }
  587.  
  588. void seg_fault() {
  589.     log_error("httpd: caught SIGSEGV, dumping core", server_conf);
  590.     chdir(server_root);
  591.     abort();
  592.     exit(1);
  593. }
  594.  
  595. void just_die()            /* SIGHUP to child process??? */
  596. {
  597.     exit (0);
  598. }
  599.  
  600. /* Reset group privileges, after rereading the config files
  601.  * (our uid may have changed, and if so, we want the new perms).
  602.  *
  603.  * Don't reset the uid yet --- we do that only in the child process,
  604.  * so as not to lose any root privs.  But we can set the group stuff
  605.  * now, once, as opposed to once per each new child.
  606.  *
  607.  * Note that we use the username as set in the config files, rather than
  608.  * the lookup of to uid --- the same uid may have multiple passwd entries,
  609.  * with different sets of groups for each.
  610.  */
  611.   
  612. static void set_group_privs()
  613. {
  614.   if(!geteuid()) {
  615.     char *name;
  616.   
  617.     /* Get username if passed as a uid */
  618.     
  619.     if (user_name[0] == '#') {
  620.       struct passwd* ent;
  621.       uid_t uid=atoi(&user_name[1]);
  622.  
  623.       if ((ent = getpwuid(uid)) == NULL) {
  624.      log_error("couldn't determine user name from uid", server_conf);
  625.      exit(1);
  626.       }
  627.       
  628.       name = ent->pw_name;
  629.     } else name = user_name;
  630.  
  631.     /* Reset `groups' attributes. */
  632.     
  633.     if (initgroups(name, group_id) == -1) {
  634.     log_unixerr("initgroups", NULL, "unable to set groups", server_conf);
  635.     exit (1);
  636.     }
  637.  
  638.     if (setgid(group_id) == -1) {
  639.     log_unixerr("setgid", NULL, "unable to set group id", server_conf);
  640.     exit (1);
  641.     }
  642.   }
  643. }
  644.  
  645. void restart() {
  646.     signal (SIGALRM, SIG_IGN);
  647.     alarm (0);
  648. #ifdef NEXT
  649.     longjmp(restart_buffer,1);
  650. #else
  651.     siglongjmp(restart_buffer,1);
  652. #endif
  653. }
  654.  
  655. void set_signals() {
  656.     if(!one_process)
  657.     {
  658.         signal(SIGSEGV,(void (*)())seg_fault);
  659.         signal(SIGBUS,(void (*)())bus_error);
  660.     }
  661.     signal(SIGTERM,(void (*)())sig_term);
  662.     signal(SIGHUP,(void (*)())restart);
  663. }
  664.  
  665. /*****************************************************************
  666.  * Connection structures and accounting...
  667.  * Should these be global?  Only to this file, at least...
  668.  */
  669.  
  670. pool *pconf;            /* Pool for config stuff */
  671. pool *ptrans;            /* Pool for per-transaction stuff */
  672.  
  673. server_rec *find_virtual_server (struct in_addr server_ip, server_rec *server)
  674. {
  675.     server_rec *virt;
  676.  
  677.     for (virt = server->next; virt; virt = virt->next)
  678.     if (virt->host_addr.s_addr == server_ip.s_addr)
  679.         return virt;
  680.  
  681.     return server;
  682. }
  683.  
  684. void default_server_hostnames(server_rec *s)
  685. {
  686.     /* Main host first */
  687.     
  688.     if (!s->server_hostname)
  689.     s->server_hostname = get_local_host(pconf);
  690.  
  691.     /* Then virtual hosts */
  692.     
  693.     for (s = s->next; s; s = s->next)
  694.     if (!s->server_hostname) {
  695.         struct hostent *h = gethostbyaddr ((char *)&(s->host_addr),
  696.                            sizeof (struct in_addr),
  697.                            AF_INET);
  698.         if (h != NULL) {
  699.         s->server_hostname = pstrdup (pconf, (char *)h->h_name);
  700.         }
  701.     }
  702. }
  703.     
  704. void abort_connection (conn_rec *c)
  705. {
  706.     /* Make sure further I/O DOES NOT HAPPEN */
  707.     shutdown (fileno (c->client), 2);
  708.     signal (SIGPIPE, SIG_IGN);    /* Ignore further complaints */
  709.     c->aborted = 1;
  710. }
  711.  
  712. conn_rec *new_connection (pool *p, server_rec *server, FILE *in, FILE *out,
  713.               const struct sockaddr_in *saddr)
  714. {
  715.     conn_rec *conn = (conn_rec *)pcalloc (p, sizeof(conn_rec));
  716.     
  717.     /* Get a connection structure, and initialize what fields we can
  718.      * (the rest are zeroed out by pcalloc).
  719.      */
  720.     
  721.     conn = (conn_rec *)pcalloc(p, sizeof(conn_rec));
  722.     
  723.     conn->pool = p;
  724.     conn->server = find_virtual_server (saddr->sin_addr, server);
  725.     conn->client = out;
  726.     conn->request_in = in;
  727.     
  728.     get_remote_host(conn);
  729.     
  730.     return conn;
  731. }
  732.  
  733. /*****************************************************************
  734.  * Child process main loop.
  735.  * The following vars are static to avoid getting clobbered by longjmp();
  736.  * they are really private to child_main.
  737.  */
  738.  
  739. static int csd;
  740. static int dupped_csd;
  741. static int requests_this_child;
  742. static int child_num;
  743.  
  744. void child_main(int child_num_arg)
  745. {
  746.     int clen;
  747.     struct sockaddr sa_server;
  748.     struct sockaddr sa_client;
  749.  
  750. #ifdef ULTRIX_BRAIN_DEATH
  751.     extern char *rfc931();
  752. #else
  753.     extern char *rfc931 (struct sockaddr_in *, struct sockaddr_in *);
  754. #endif
  755.  
  756.     csd = -1;
  757.     dupped_csd = -1;
  758.     child_num = child_num_arg;
  759.     requests_this_child = 0;
  760.     reopen_scoreboard (pconf);
  761.     update_child_status (child_num, SERVER_READY);
  762.  
  763.     /* Only try to switch if we're running as root */
  764.     if(!geteuid() && setuid(user_id) == -1) {
  765.         log_unixerr("setuid", NULL, "unable to change uid", server_conf);
  766.     exit (1);
  767.     }
  768.  
  769. #ifdef NEXT
  770.     setjmp(jmpbuffer);
  771. #else
  772.     sigsetjmp(jmpbuffer,1);
  773. #endif
  774.     signal(SIGURG, timeout);
  775.  
  776.     while (1) {
  777.     FILE *conn_in, *conn_out;
  778.     request_rec *r;
  779.       
  780.         alarm(0);        /* Cancel any outstanding alarms. */
  781.         timeout_req = NULL;    /* No request in progress */
  782.     current_conn = NULL;
  783.         signal(SIGPIPE, timeout);  
  784.     
  785.     clear_pool (ptrans);
  786.     
  787.     sync_scoreboard_image();
  788.     
  789.     if ((count_idle_servers() >= daemons_max_free)
  790.         || (max_requests_per_child > 0
  791.             && ++requests_this_child >= max_requests_per_child))
  792.     {
  793.         exit(0);
  794.     }
  795.  
  796.     clen=sizeof(sa_client);
  797.     update_child_status (child_num, SERVER_READY);
  798.     
  799.     accept_mutex_on();  /* Lock around "accept", if necessary */
  800.     
  801.     while ((csd=accept(sd, &sa_client, &clen)) == -1) 
  802.            if (errno != EINTR) 
  803.         log_unixerr("accept", "(client socket)", NULL, server_conf);
  804.  
  805.     accept_mutex_off(); /* unlock after "accept" */
  806.  
  807.     clen = sizeof(sa_server);
  808.     if(getsockname(csd, &sa_server, &clen) < 0) {
  809.         log_unixerr("getsockname", NULL, NULL, server_conf);
  810.         continue;
  811.     }
  812.     
  813.     dupped_csd = csd;
  814. #if defined(AUX) || defined(SCO)
  815.     if ((dupped_csd = dup(csd)) < 0) {
  816.         log_unixerr("dup", NULL, "couldn't duplicate csd", server_conf);
  817.         dupped_csd = csd;    /* Oh well... */
  818.     }
  819. #endif
  820.     update_child_status (child_num, SERVER_BUSY);
  821.     conn_in = pfdopen (ptrans, csd, "r");
  822.     conn_out = pfdopen (ptrans, dupped_csd, "w");
  823.  
  824.     current_conn = new_connection (ptrans, server_conf, conn_in, conn_out,
  825.                        (struct sockaddr_in *)&sa_server);
  826.  
  827.     if (current_conn->server->do_rfc931)
  828.         current_conn->remote_logname = 
  829.         rfc931((struct sockaddr_in *)&sa_client,
  830.                (struct sockaddr_in *)&sa_server);
  831.     
  832.     r = read_request (current_conn);
  833.     if (r) process_request (r); /* else premature EOF --- ignore */
  834.         
  835.     if (bytes_in_pool (ptrans) > 80000)
  836.         log_printf(r->server,
  837.                "Memory hog alert: allocated %ld bytes for %s",
  838.                bytes_in_pool (ptrans), r->the_request);
  839.         
  840.     fflush (conn_out);
  841.     pfclose (ptrans,conn_in);
  842.     pfclose (ptrans,conn_out);
  843.     }    
  844. }
  845.  
  846. void make_child(server_rec *server_conf, int child_num)
  847. {
  848.     int pid;
  849.  
  850.     if (one_process) {
  851.     signal (SIGHUP, (void (*)())just_die);
  852.     signal (SIGTERM, (void (*)())just_die);
  853.     child_main (child_num);
  854.     }
  855.  
  856.     if ((pid = fork()) == -1) {
  857.     log_unixerr("fork", NULL, "Unable to fork new process", server_conf);
  858.     return;
  859.     } 
  860.     
  861.     if (!pid) {
  862.     signal (SIGHUP, (void (*)())just_die);
  863.     signal (SIGTERM, (void (*)())just_die);
  864.     child_main (child_num);
  865.     }
  866. }
  867.  
  868. /*****************************************************************
  869.  * Executive routines.
  870.  */
  871.  
  872. static int keepalive_value = 1;  
  873. static int one = 1;
  874. static int num_children = 0;
  875.  
  876. void standalone_main(int argc, char **argv)
  877. {
  878.     struct sockaddr_in sa_server;
  879.  
  880.     standalone = 1;
  881.     sd = -1;
  882.     
  883.     if (!one_process) detach(); 
  884.     
  885. #ifdef NEXT
  886.     setjmp(restart_buffer);
  887. #else
  888.     sigsetjmp(restart_buffer,1);
  889. #endif
  890.  
  891.     signal (SIGHUP, SIG_IGN);    /* Until we're done (re)reading config */
  892.     
  893.     if(!one_process)
  894. #ifndef NO_KILLPG
  895.       killpg(pgrp,SIGHUP);    /* Kill 'em off */
  896. #else
  897.       kill(-pgrp,SIGHUP);
  898. #endif
  899.     
  900.     if (sd != -1) {
  901.     reclaim_child_processes(); /* Not when just starting up */
  902.     log_error ("SIGHUP received.  Attempting to restart", server_conf);
  903.     }
  904.     
  905.     clear_pool (pconf);
  906.     ptrans = make_sub_pool (pconf);
  907.     
  908.     server_conf = read_config(pconf, ptrans, server_confname); 
  909.     open_logs(server_conf, pconf);
  910.     set_group_privs();
  911.     accept_mutex_init(pconf);
  912.     reinit_scoreboard(pconf);
  913.     
  914.     default_server_hostnames (server_conf);
  915.  
  916.     if ((sd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) {
  917.         fprintf(stderr,"httpd: could not get socket\n");
  918.         perror("socket");
  919.         exit(1);
  920.     }
  921.  
  922.     note_cleanups_for_fd (pconf, sd); /* arrange to close on exec or restart */
  923.     
  924.     if((setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)))
  925.        == -1) {
  926.         fprintf(stderr,"httpd: could not set socket option\n");
  927.         perror("setsockopt");
  928.         exit(1);
  929.     }
  930.     if((setsockopt(sd,SOL_SOCKET,SO_KEEPALIVE,(void *)&keepalive_value,
  931.         sizeof(keepalive_value))) == -1) {
  932.         fprintf(stderr,"httpd: could not set socket option SO_KEEPALIVE\n"); 
  933.         perror("setsockopt"); 
  934.         exit(1); 
  935.     }
  936.  
  937.     memset((char *) &sa_server, 0, sizeof(sa_server));
  938.     sa_server.sin_family=AF_INET;
  939.     sa_server.sin_addr=bind_address;
  940.     sa_server.sin_port=htons(server_conf->port);
  941.     if(bind(sd,(struct sockaddr *) &sa_server,sizeof(sa_server)) == -1) {
  942.     if (bind_address.s_addr != htonl(INADDR_ANY))
  943.         fprintf(stderr,"httpd: could not bind to address %s port %d\n",
  944.             inet_ntoa(bind_address), server_conf->port);
  945.     else
  946.         fprintf(stderr,"httpd: could not bind to port %d\n",
  947.             server_conf->port);
  948.         perror("bind");
  949.         exit(1);
  950.     }
  951.     listen(sd, 512);
  952.  
  953.     set_signals();
  954.     log_pid(pconf, pid_fname);
  955.  
  956.     num_children = 0;
  957.     
  958.     if (daemons_max_free < daemons_min_free + 1) /* Don't thrash... */
  959.     daemons_max_free = daemons_min_free + 1;
  960.  
  961.     while (num_children < daemons_to_start) {
  962.     make_child(server_conf, num_children++);
  963.     }
  964.  
  965.     log_error ("Server configured -- resuming normal operations", server_conf);
  966.     
  967.     while (1) {
  968.     int status, child_slot;
  969.     int pid = wait_or_timeout(&status);
  970.     
  971.     if (pid >= 0) {
  972.         /* Child died... note that it's gone in the scoreboard. */
  973.         sync_scoreboard_image();
  974.         child_slot = find_child_by_pid (pid);
  975.         if (child_slot >= 0) update_child_status (child_slot, SERVER_DEAD);
  976.         }
  977.  
  978.     sync_scoreboard_image();
  979.     if ((count_idle_servers() < daemons_min_free)
  980.         && (child_slot = find_free_child_num()) >= 0
  981.         && child_slot <= daemons_limit)
  982.         {
  983.         update_child_status(child_slot,SERVER_STARTING);
  984.         make_child(server_conf, child_slot);
  985.         }
  986.     }
  987.  
  988. } /* standalone_main */
  989.  
  990. extern char *optarg;
  991. extern int optind;
  992.  
  993. int
  994. main(int argc, char *argv[])
  995. {
  996.     int c;
  997.  
  998.     init_alloc();
  999.     pconf = permanent_pool;
  1000.     ptrans = make_sub_pool(pconf);
  1001.     
  1002.     server_argv0 = argv[0];
  1003.     strcpy (server_root, HTTPD_ROOT);
  1004.     strcpy (server_confname, SERVER_CONFIG_FILE);
  1005.  
  1006.     while((c = getopt(argc,argv,"Xd:f:v")) != -1) {
  1007.         switch(c) {
  1008.           case 'd':
  1009.             strcpy (server_root, optarg);
  1010.             break;
  1011.           case 'f':
  1012.             strcpy (server_confname, optarg);
  1013.             break;
  1014.           case 'v':
  1015.             printf("Server version %s.\n",SERVER_VERSION);
  1016.             exit(1);
  1017.       case 'X':
  1018.         ++one_process;    /* Weird debugging mode. */
  1019.         break;
  1020.           case '?':
  1021.             usage(argv[0]);
  1022.         }
  1023.     }
  1024.  
  1025.     setup_prelinked_modules();
  1026.     
  1027.     server_conf = read_config (pconf, ptrans, server_confname);
  1028.     
  1029.     if(standalone) {
  1030.         clear_pool (pconf);    /* standalone_main rereads... */
  1031.         standalone_main(argc, argv);
  1032.     }
  1033.     else {
  1034.         conn_rec *conn;
  1035.     request_rec *r;
  1036.     struct sockaddr sa_server;
  1037.       
  1038.     open_logs(server_conf, pconf);
  1039.     set_group_privs();
  1040.     default_server_hostnames (server_conf);
  1041.  
  1042.         user_id = getuid();
  1043.         group_id = getgid();
  1044.  
  1045.     c = sizeof(sa_server);
  1046.     if(getsockname(csd, &sa_server, &c) < 0) {
  1047.         perror("getsockname");
  1048.         fprintf(stderr, "Error getting local address\n");
  1049.         exit(1);
  1050.     }
  1051.     server_conf->port =ntohs(((struct sockaddr_in *)&sa_server)->sin_port);
  1052.     conn = new_connection (ptrans, server_conf, stdin, stdout,
  1053.                    (struct sockaddr_in *)&sa_server);
  1054.     r = read_request (conn);
  1055.     if (r) process_request (r); /* else premature EOF (ignore) */
  1056.     }
  1057.     exit (0);
  1058. }
  1059.  
  1060.  
  1061.