main.c
上传用户:ladybrid91
上传日期:2007-01-04
资源大小:287k
文件大小:21k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** main.c
  3. **
  4. ** Copyright (c) 1994-1997 Peter Eriksson <pen@signum.se>
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <stdio.h>
  20. #include <unistd.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <thread.h>
  24. #include <errno.h>
  25. #include <time.h>
  26. #include <pwd.h>
  27. #include <grp.h>
  28. #include <netdb.h>
  29. #include <fcntl.h>
  30. #include <syslog.h>
  31. #include <signal.h>
  32. #include <sys/filio.h>
  33. #include <sys/systeminfo.h>
  34. #include <sys/uio.h>
  35. #include <sys/wait.h>
  36. #include <sys/types.h>
  37. #include <sys/socket.h>
  38. #include <sys/un.h>
  39. #include <netinet/in.h>
  40. #include <netinet/tcp.h>
  41. #include <arpa/inet.h>
  42. #include <netdb.h>
  43. #include <dlfcn.h>
  44. #ifndef RTLD_GLOBAL
  45. #define RTLD_GLOBAL 0
  46. #endif
  47. #define IN_MAIN_C
  48. #include "phttpd.h"
  49. #define CONFIG_FILE     INSTROOT "/etc/phttpd.conf"
  50. #define SERVER_BIN INSTROOT "/sbin/phttpd"
  51. #define DEFAULT_LOGFILE "/var/log/phttpd/requests"
  52. #define DEFAULT_PIDFILE "/var/log/phttpd/pid"
  53. #define DEFAULT_ERRFILE "/var/log/phttpd/stderr"
  54. #define DEFAULT_CNTFILE "/var/log/phttpd/counts"
  55. static struct table *global_modules = NULL;
  56. struct options global_cfg_table[] =
  57. {
  58.     { "auth-handlers",     T_TABLE, &auth_handlers_table, NULL, 0, 0, NULL },
  59.     { "url-handlers",      T_TABLE, &url_handlers_table, NULL, 0, 0, NULL },
  60.     { "url-redirects",     T_TABLE, &url_redirects_table, NULL, 0, 0, NULL },
  61.     { "url-permanent-redirects",     T_TABLE, &url_predirects_table, NULL, 0, 0, NULL },
  62.     { "url-rewrites",      T_TABLE, &url_rewrites_table, NULL, 0, 0, NULL },
  63.     { "read-authenticate",  T_TABLE, &read_authenticate_table,    NULL, 0, 0, NULL },
  64.     { "write-authenticate",  T_TABLE, &write_authenticate_table,    NULL, 0, 0, NULL },
  65.     { "host-access",        T_TABLE, &host_access_table,          NULL, 0, 0, NULL },
  66.     { "content-language",  T_TABLE, &content_language_table, NULL, 0, 0, NULL },
  67.     { "url-expand",    T_TABLE, &url_expand_table, NULL, 0, 0, NULL },
  68.     { "error-pages",    T_HTABLE, &error_page_table, NULL, 0, 0, NULL },
  69.     { "global-modules",    T_TABLE, &global_modules,            NULL, 0, 0, NULL },
  70.     { "config-file",    T_FILE,   NULL, NULL, 'f', 0, NULL, "Path to additional config file" },
  71.     { "primary-config-file",    T_FILE,   NULL, NULL, 'F', 0, NULL, "Path to primary config file" },
  72.     
  73.     { "database-dir",      T_STRING, &server_home, NULL, 0, 0, NULL, "Path to database directory" },
  74.     { "sub-database-dir",  T_STRING, &sub_server_home, NULL, 0, 0, NULL, "postfix pathpart for virtualservers" },
  75.     { "server-name",       T_STRING, &server_host, NULL, 0, 0, NULL, "Official FQDN name of server" },
  76.     { "server-addr",       T_STRING, &server_addr, NULL, 0, 0, NULL, "Address to bind server to" },
  77.     { "modules-dir",    T_STRING, &modules_home,             NULL, 0, 0, NULL, "Path to modules directory" },
  78.     { "user-dir",          T_STRING, &user_dir, NULL, 0, 0, NULL, "Users public directory" },
  79.     { "user-basedir",      T_STRING, &user_basedir, NULL, 0, 0, NULL, "Base directory for all users" },
  80.     { "logging-file",      T_STRING, &logfile_path, NULL, 'L', 0, DEFAULT_LOGFILE, "Path to requests logging file" },
  81.     { "counting-file",     T_STRING, &cntfile_path,             NULL, 'C', 0, DEFAULT_CNTFILE, "Path to requests counter database" },
  82.     { "pid-file",          T_STRING, &pidfile_path,             NULL, 'P', 0, DEFAULT_PIDFILE, "Path to PID file" },
  83.     { "stderr-file",       T_STRING, &errfile_path,             NULL, 'E', 0, DEFAULT_ERRFILE, "Path to stderr log file" },
  84.     
  85.     { "web-admin-name",    T_STRING, &web_admin_name,           NULL, 0, 0, NULL,  "Webmaster's name" },
  86.     { "web-admin-home",    T_STRING, &web_admin_home,           NULL, 0, 0, NULL,  "Webmaster's home URL" },
  87.     { "web-admin-email",   T_STRING, &web_admin_email,          NULL, 0, 0, NULL,  "Webmaster's email address" },
  88.     { "virtual-admin-email",   T_STRING, &virtual_admin_email,          NULL, 0, 0, NULL,  "Webmaster's relative address for hostingmodes" },
  89.     
  90.     { "server-user",       T_STRING, &server_user, NULL, 'u', 0, NULL, "Server user name or number" },
  91.     { "server-group",      T_STRING, &server_group, NULL, 'g', 0, NULL, "Server group name or number" },
  92.     { "debug-level",    T_NUMBER, &debug, NULL, 'd', 1, NULL, "Debug level" },
  93.     { "isdaemon",    T_NUMBER, &already_daemon, NULL, 0, 0, NULL, "Is already in daemon mode level" },
  94.     { "fscache-size",      T_NUMBER, &fscache_size,             NULL, 0, 0, NULL, "Fscache size" },
  95.     { "fscache-refresh",   T_NUMBER, &fscache_refresh,          NULL, 0, 0, NULL, "Fscache refresh interval" },
  96.     { "fscache-ttl",       T_NUMBER, &fscache_ttl,              NULL, 0, 0, NULL, "Fscache time-to-live" },
  97.     { "fscache-gc-interval", T_NUMBER, &fscache_gc_interval,    NULL, 0, 0, NULL, "Fscache garbage collect interval" },
  98.     { "hostcache-size",      T_NUMBER, &hostcache_size,             NULL, 0, 0, NULL, "Hostcache size" },
  99.     { "hostcache-refresh",   T_NUMBER, &hostcache_refresh,          NULL, 0, 0, NULL, "Hostcache refresh interval" },
  100.     { "hostcache-ttl",       T_NUMBER, &hostcache_ttl,              NULL, 0, 0, NULL, "Hostcache time-to-live" },
  101.     { "hostcache-gc-interval", T_NUMBER, &hostcache_gc_interval,    NULL, 0, 0, NULL, "Hostcache garbage collect interval" },
  102.     { "usercache-size",      T_NUMBER, &usercache_size,             NULL, 0, 0, NULL, "Usercache size" },
  103.     { "usercache-refresh",   T_NUMBER, &usercache_refresh,          NULL, 0, 0, NULL, "Usercache refresh interval" },
  104.     { "usercache-ttl",       T_NUMBER, &usercache_ttl,              NULL, 0, 0, NULL, "Usercache time-to-live" },
  105.     { "usercache-gc-interval", T_NUMBER, &usercache_gc_interval,    NULL, 0, 0, NULL, "Usercache garbage collect interval" },
  106.     { "urlcache-size",      T_NUMBER, &urlcache_size,             NULL, 0, 0, NULL, "Urlcache size" },
  107.     { "urlcache-refresh",  T_NUMBER, &urlcache_refresh,         NULL, 0, 0, NULL, "Urlcache refresh interval" },
  108.     { "urlcache-ttl",      T_NUMBER, &urlcache_ttl,             NULL, 0, 0, NULL, "Urlcache time-to-live" },
  109.     { "urlcache-gc-interval", T_NUMBER, &urlcache_gc_interval,     NULL, 0, 0, NULL, "Urlcache garbage collect interval" },
  110.     
  111.     { "server-port",       T_NUMBER, &server_port, NULL, 'p', 8000, NULL, "Servers' TCP port" },
  112.     { "concurrency",       T_NUMBER, &concurrency, NULL, 0, 0, NULL,   "Threads concurrency level" },
  113.     { "listen-backlog",    T_NUMBER, &n_listen, NULL, 'b', 1024, NULL, "Listen backlog level" },
  114.     { "socket-sndbuf",     T_NUMBER, &so_sndbuf,          NULL, 0, 0, NULL, "Size of socket send buffer" },
  115.     { "socket-rcvbuf",     T_NUMBER, &so_rcvbuf,          NULL, 0, 0, NULL, "Size of socket receive buffer" },
  116.     { "gc-time",           T_NUMBER, &gc_time, NULL, 0, 0, NULL, "Connection time-to-live" },
  117.     { "gc-sleep",          T_NUMBER, &gc_sleep, NULL, 0, 0, NULL, "Connection garbage collect interval" },
  118.     { "restart-requests",  T_NUMBER, &restart_requests, NULL, 0, 0, NULL, "Number of requests to server befor refork" },
  119.     { "restart-grace-time",T_NUMBER, &restart_grace_time, NULL, 0, 20, NULL, "Grace time, an old process wait for connections to finish" },
  120.     { "select-timeout",    T_NUMBER, &select_timeout, NULL, 'T', 0, NULL, "Select timeout limit" },
  121.     { "max-url-size",    T_NUMBER, &maxurlsize, NULL, 0, 0, NULL, "Max length of request URL"},
  122.     { "write-needs-auth",  T_BOOL, &write_needs_auth,           NULL, 0, 1, NULL, "Upload may allways needs auth "},
  123.     { "rkmultimode",       T_BOOL, &rkmultimode, NULL, 0, 0, NULL, "Multimode URL expanding %lx"},
  124.     { "mode-dotted",       T_BOOL, &mode_dotted, NULL, 0, 0, NULL, "Multimode URL expanding hex or dotted ipnr"},
  125.     { "software-virtual-server",T_BOOL, &softvirtserver, NULL, 0, 0, NULL, "Enable Sotware-Virtual-Server via HTTP/1.1"},
  126.     { "logheadervolume",   T_BOOL, &logheadervolume, NULL, 0, 1, NULL, "Add headervolume to size in logfile"},
  127.     { "extended-logging",  T_BOOL, &extended_logging, NULL, 0, 1, NULL, "Enable extended logging" },
  128.     { "keepalive-connections", T_BOOL, &keepalive_enabled,      NULL, 0, 1, NULL, "Enable Keep-Alive connections" },
  129.     { "bound-threads",    T_BOOL,   &bound_threads, NULL, 'B', 1, NULL, "Use bound threads" },
  130.     { "hostname-lookups",  T_BOOL,   &hostname_lookups,         NULL, 'H', 1, NULL, "Perform hostname lookups" },
  131.     { "ident-lookups",     T_BOOL,   &ident_lookups, NULL, 'I', 1, NULL, "Perform IDENT lookups" },
  132.     { "no-copying-info",   T_BOOL,   &no_copying_info,          NULL, 's', 1, NULL, "Don't display the copying info" },
  133.     { "wait-mode",    T_BOOL,   &wait_mode, NULL, 'w', 1, NULL, "Start server in 'wait' mode" },
  134.     
  135.     { NULL,                -1,       NULL, NULL, 0, 0, NULL, NULL }
  136. };
  137. static char *get_local_hostname(char *buf,
  138. int size)
  139. {
  140.     struct hostent *hp, hb;
  141.     char hb_buf[1024];
  142.     int i, len, h_errno;
  143.     
  144.     if (sysinfo(SI_HOSTNAME, buf, size) < 0)
  145. return NULL;
  146.     if (strchr(buf, '.') != NULL)
  147. return buf;
  148.     hp = s_gethostbyname_r(buf, &hb, hb_buf, sizeof(hb_buf), &h_errno);
  149.     if (hp == NULL)
  150.     {
  151. syslog(LOG_WARNING, "unable to find FQDN for %s", buf);
  152. return buf;
  153.     }
  154.     
  155.     if (hp->h_name && strchr(hp->h_name, '.') != NULL)
  156.     {
  157. len = s_strcpy(buf, size, hp->h_name);
  158. if (len > 0 && len < size-1)
  159.     return buf;
  160. /* else name too long, try to find a shorter in the aliases list */
  161.     }
  162.     if (hp->h_aliases)
  163. for (i = 0; hp->h_aliases[i]; i++)
  164. {
  165.     if (strchr(hp->h_aliases[i], '.') != NULL)
  166.     {
  167. len = s_strcpy(buf, size, hp->h_aliases[i]);
  168. if (len > 0 && len < size-1)
  169.     return buf;
  170. /* else name too long, try to find a shorter one later */
  171.     }
  172. }
  173.     
  174.     syslog(LOG_WARNING, "unable to find FQDN for %s", buf);
  175.     return buf;
  176. }
  177. int uidgid_get(const char *user,
  178.        const char *group,
  179.        uid_t *uid,
  180.        gid_t *gid,
  181.        struct passwd **pwp,
  182.        struct passwd *pwb,
  183.        char *pbuf,
  184.        int pbuflen)
  185. {
  186.     struct group *grp, grb;
  187.     char gbuf[2048];
  188.     
  189.     
  190.     if (user != NULL)
  191.     {
  192. if (s_isdigit(user[0]))
  193. {
  194.     *uid = atoi(user);
  195.     *pwp = s_getpwuid_r(*uid, pwb, pbuf, pbuflen);
  196. }
  197. else
  198. {
  199.     *pwp = s_getpwnam_r(user, pwb, pbuf, pbuflen);
  200.     if (*pwp == NULL)
  201. return -1;
  202.     
  203.     *uid = (*pwp)->pw_uid;
  204. }
  205. if (*pwp)
  206.     *gid = (*pwp)->pw_gid;
  207.     }
  208.     if (group != NULL)
  209.     {
  210. if (s_isdigit(group[0]))
  211.     *gid = atoi(group);
  212. else
  213. {
  214.     grp = s_getgrnam_r(group, &grb, gbuf, sizeof(gbuf));
  215.     if (grp == NULL)
  216. return -2;
  217.     
  218.     *gid = grp->gr_gid;
  219. }
  220.     }
  221.     return 0;
  222. }
  223. static int load_global_module(void *value, void *misc)
  224. {
  225.     void *obj;
  226.     char **vp;
  227.     char buf[2048], *cp;
  228.     int (*pm_init)(const char **argv);
  229.     const char *argv[2];
  230.     
  231.     vp = (char **) value;
  232.     if (vp == NULL || vp[0] == NULL)
  233. return 0;
  234.     cp = vp[0];
  235.     
  236.     
  237.     if (debug > 1)
  238. fprintf(stderr, "Loading module %sn", cp);
  239.     
  240.     if (*cp != '/')
  241.     {
  242. s_strcpy(buf, sizeof(buf), modules_home);
  243. s_strcat(buf, sizeof(buf), "/");
  244. s_strcat(buf, sizeof(buf), cp);
  245.     }
  246.     else
  247. s_strcpy(buf, sizeof(buf), cp);
  248.     
  249.     obj = dlopen(buf, RTLD_NOW+RTLD_GLOBAL);
  250.     if (obj == NULL)
  251.     {
  252. syslog(LOG_ERR, "load_global_module("%s") failed: %m", cp);
  253. return 0;
  254.     }
  255.     pm_init = (int (*)(const char **)) dlsym(obj, "pm_init");
  256.     if (pm_init)
  257.     {
  258. argv[0] = cp;
  259. argv[1] = NULL;
  260. if ((*pm_init)(argv) < 0)
  261. {
  262.     syslog(LOG_ERR, "global module %s init failed: %m", cp);
  263.     dlclose(obj);
  264.     return 0;
  265. }
  266.     }
  267.     return 0;
  268. }
  269. static void load_global_modules(struct table *mt)
  270. {
  271.     if (mt == NULL)
  272. return;
  273.     tbl_foreach(mt, &load_global_module, NULL);
  274. }
  275. static int setup_server_host(void)
  276. {
  277.     static char host_name[1024];
  278.     
  279.     if (server_host == NULL)
  280.     {
  281. if (get_local_hostname(host_name, sizeof(host_name)) == NULL)
  282. {
  283.     syslog(LOG_ERR, "get_local_hostname() failed: %m");
  284.     return -1;
  285. }
  286. server_host = host_name;
  287.     }
  288.     return 0;
  289. }
  290. static void display_banner(void)
  291. {
  292.     printf("[Phttpd %s - Copyright (c) 1995-1997 Peter Eriksson <pen@signum.se> 1998-1999 Roland Kaltefleiter <rk@netuse.de>]nn",
  293.     server_version);
  294. }
  295. static void display_copying(void)
  296. {
  297.     puts("tPhttpd comes with ABSOLUTELY NO WARRANTY. This is free software,");
  298.     puts("tand you are welcome to redistribute it under certain conditions;");
  299.     puts("tfor more information about the conditions and non-warranty, see:");
  300.     puts("ntthttp://www.signum.se/phttpd/COPYING.htmln");
  301.     puts("tor read the file COPYING that should have been part of the");
  302.     puts("tsoftware distribution - if not send an email to <pen@signum.se>.");
  303.     puts("");
  304. }
  305. static int setup_uidgid(void)
  306. {
  307.     int x;
  308.     if ( debug > 3 )
  309.       fprintf(stderr,"phttpd: Calling initgroups (%s / %ld )n",server_user,server_gid);
  310.     x=initgroups(server_user,server_gid);
  311.       fprintf(stderr,"phttpd: back from initgroupsn");
  312.     if ( x < 0 )
  313.     {
  314. syslog(LOG_ERR, "initgroups("%s", %d) failed: %m",
  315.        server_user, server_gid);
  316. return -1;
  317.     }
  318.     if (server_gid != -1)
  319. if (setegid(server_gid) < 0)
  320. {
  321.     syslog(LOG_ERR, "setegid(%d) failed: %m", server_gid);
  322.     return -1;
  323. }
  324.     
  325.     if (server_uid != -1)
  326. if (seteuid(server_uid) < 0)
  327. {
  328.     syslog(LOG_ERR, "seteuid(%d) failed: %m", server_uid);
  329.     return -1;
  330. }
  331.     return 0;
  332. }
  333. static void create_pidfile(void)
  334. {
  335.     int fd;
  336.     
  337.     if (pidfile_path == NULL)
  338. return;
  339.     
  340.     fd = fd_open(pidfile_path, O_WRONLY+O_CREAT+O_TRUNC, 0644);
  341.     if (fd < 0)
  342. syslog(LOG_ERR,
  343.        "fd_open("%s", O_WRONLY+O_CREAT+O_TRUNC) failed: %m",
  344.        pidfile_path);
  345.     else
  346.     {
  347. fd_printf(fd, "%dn", getpid());
  348. fd_close(fd);
  349.     }
  350. }
  351. int main(int argc, const char *argv[])
  352. {
  353.     int i, status;
  354.     int leftover;
  355.     struct passwd pwb, *pwp = NULL;
  356.     char pbuf[2048];
  357.     char **nargv;
  358.     char *default_cfg_file = NULL;
  359.     sigset_t sig_set;
  360.     int sig;
  361.     pid_t npid;
  362.     struct serverinfo *sip;
  363.     thread_t acthr_id;
  364.     
  365.     openlog("phttpd", LOG_PID, LOG_DAEMON);
  366.     
  367.     time(&start_time);
  368.     
  369.     for (i = 1; i < argc && argv[i][0] == '-'; i++)
  370.     {
  371. if (argv[i][1] == 'd')
  372. {
  373.     if (argv[i][2])
  374. debug = atoi(argv[i]+2);
  375.     else
  376. debug = 1;
  377. }
  378.         if (argv[i][1] == 'F')
  379. {
  380.     if (argv[i][2])
  381. default_cfg_file=strdup(argv[i]+2);
  382. }
  383.     }
  384.     if ( default_cfg_file == NULL )
  385. default_cfg_file=strdup(CONFIG_FILE);
  386.     
  387.     fd_init();
  388.     
  389.     config_parse_file(default_cfg_file, global_cfg_table, 0);
  390.     i = config_parse_argv(argv+1, global_cfg_table);
  391.     if (i++ < 0)
  392.     {
  393. fprintf(stderr, "phttpd: config_parse_argv() failedn");
  394. exit(1);
  395.     }
  396.     
  397.     if (wait_mode)
  398.     {
  399. listen_sock = 0;
  400. if (debug == 0)
  401.     debug = -1;
  402.     }
  403.     if (server_user == NULL)
  404.     {
  405. fprintf(stderr, "phttpd: server_user is NULLn");
  406. syslog(LOG_ERR, "server_user is NULL");
  407. exit(1);
  408.     }
  409. /* HACK we need to make sub_server_home nice */
  410.    if ( sub_server_home == NULL ) sub_server_home=s_strdup("");
  411.    else
  412.    {
  413. if ( sub_server_home[0]!='/' )
  414. {
  415. fprintf(stderr, "phttpd: sub_server_home MUST have a leading / .n");
  416. syslog(LOG_ERR, "sub_server_home MUST have a leading / .");
  417. exit(1);
  418. }
  419.    }
  420.    if ( restart_requests < 10000 && restart_requests > 0 )
  421. {
  422. fprintf(stderr,"restart-requests is TOO low (%d), should be > 10000 !n",restart_requests);
  423. syslog(LOG_ERR, "WARNING: restart-requests is TOO low, should be > 10000 !");
  424. }
  425.     
  426.    if ( server_addr == NULL)
  427. { server_addr=s_strdup("*"); }
  428.     
  429.     if (uidgid_get(server_user, server_group,
  430.    &server_uid, &server_gid,
  431.    &pwp, &pwb, pbuf, sizeof(pbuf)) < 0)
  432.     {
  433. fprintf(stderr, "phttpd: uidgid_get() failedn");
  434. syslog(LOG_ERR, "uidgid_get("%s", "%s") failed",
  435.        server_user != NULL ? server_user : "",
  436.        server_group != NULL ? server_group : "");
  437. exit(1);
  438.     }
  439.     if (geteuid() != 0 && server_port < 1024)
  440. server_port = 8080;
  441.     
  442.     if (setup_server_host() < 0)
  443.     {
  444. fprintf(stderr, "phttpd: setup_server_host() failedn");
  445. exit(1);
  446.     }
  447.     if (listen_sock < 0)
  448.     {
  449. display_banner();
  450. if (!no_copying_info)
  451.     display_copying();
  452. if (server_port != 80)
  453.     printf("Server will be started on %s:%d as (%d) with debuglevel %dn",
  454.     server_host,
  455.     server_port,
  456.     (int) getpid(),
  457.     debug);
  458.     }
  459.     
  460.     if (i < argc)
  461. server_home = s_strdup(argv[i]);
  462.     
  463.     if (server_home)
  464.     {
  465. status = s_chdir(server_home);
  466. if (status < 0)
  467. {
  468.     perror("phttpd: s_chdir");
  469.     syslog(LOG_ERR, "chdir("%s") failed: %m", server_home);
  470.     exit(1);
  471. }
  472.     }
  473.     sip = create_http_server(server_addr, server_port);
  474.     if (sip == NULL)
  475.     {
  476. fprintf(stderr, "phttpd: create_http_server(%s, %d): failedn",
  477. server_addr, server_port);
  478. exit(1);
  479.     }
  480.     if (getuid() == 0)
  481. if (setup_uidgid() < 0)
  482. {
  483.     fprintf(stderr, "phttpd: setup_uidgid() failedn");
  484.     exit(1);
  485. }
  486.    
  487.     if (!debug && !already_daemon)
  488. become_daemon();
  489.     
  490.     if (debug < 0)
  491. debug = 0;
  492.     
  493.     stderr_open(errfile_path);
  494.     
  495.     syslog(LOG_NOTICE, "restarted");
  496.     
  497.     md_init();
  498.     cn_init();
  499.     
  500.     fscache_init();
  501.     urlcache_init();
  502.     hostcache_init();
  503.     usercache_init();
  504.     log_init(logfile_path, cntfile_path);
  505.     create_pidfile();
  506.     signals_setup(&sig_set);
  507.     if (thr_setconcurrency(concurrency))
  508. syslog(LOG_WARNING, "thr_setconcurrency() failed: %m");
  509.     load_global_modules(global_modules);
  510.     if (gc_time)
  511. cn_start_gc();
  512.     start_http_server(sip, NULL, &acthr_id);
  513.     while (1)
  514.     {
  515. #ifdef USE_PTHREADS
  516. if (sigwait(&sig_set, &sig))
  517.     sig = -1;
  518. #else
  519. sig = sigwait(&sig_set);
  520. #endif
  521. if (sig < 0)
  522.     continue;
  523.     
  524. switch (sig)
  525. {
  526.   case SIGHUP: /* Should close and reopen all log files here */
  527.     if (debug > 0)
  528. fprintf(stderr, "** Got SIGHUPn");
  529.     
  530.     stderr_open(errfile_path);
  531.     log_reopen();
  532.     break;
  533.   case SIGUSR1: /* Increase debugging level */
  534.     debug++;
  535.     if (debug > 0)
  536. fprintf(stderr, "** Got SIGUSR1 - debug now at level %dn",
  537. debug);
  538.     break;
  539.   case SIGUSR2: /* Decrease debugging level */
  540.     if (debug > 0)
  541. debug--;
  542.     if (debug > 0)
  543. fprintf(stderr, "** Got SIGUSR2 - debug now at level %dn",
  544. debug);
  545.     break;
  546.   case SIGTERM: /* Terminate nicely */
  547.     if (debug > 0)
  548. fprintf(stderr, "** Got SIGTERM - terminatingn");
  549.     
  550.     syslog(LOG_NOTICE, "server terminating by SIGTERM request");
  551.     exit(0);
  552.     break;
  553.   case SIGQUIT:  /* restart totally */
  554.             if (debug > 0 )
  555.                 fprintf(stderr, "** Got SIGQUIT(3) - restaringn");
  556. /*     sigrelse(SIGTERM); */
  557.             syslog(LOG_NOTICE, "server restarted by SIGQUIT(3) request");
  558. /* set the global we must end ! */
  559.     do_restart=1;
  560. /* also force close of all active sessins when finished: NO KEEPALIVE */
  561.     keepalive_enabled=0;
  562.             if (sip->fd > 0 )
  563.               {
  564. fprintf(stderr, "** closing socket..%d.n",sip->fd);
  565.                 fprintf(stderr, "** close=%dn",close(sip->fd));
  566. sip->fd=-1;
  567.       }
  568.             fprintf(stderr, "** exec....%sn",SERVER_BIN);
  569. /* we only need one LWP */
  570.     npid=vfork();
  571.     if ( npid == 0 )
  572. /* we are in the child now */
  573. {
  574. /* restore root if avail */
  575. nargv=calloc(argc+2,sizeof(char *));
  576. nargv[0]=strdup(argv[0]);
  577. fprintf(stderr,"%d: nargv[0]: %sn",argc,nargv[0]);
  578. nargv[1]=strdup("--isdaemon=1");
  579. fprintf(stderr,"nargv[1]: %sn",nargv[1]);
  580. for(i=2;i<=argc;i++)
  581. nargv[i]=strdup(argv[i]);
  582. nargv[i]=NULL;
  583. if ( getuid()==0 ) setuid(0);
  584. if ( argv[0][0]=='/' )
  585. execv(argv[0],nargv);
  586. else
  587. execv(SERVER_BIN,nargv);
  588. exit(99);
  589. }
  590. while ( (leftover=cn_active()) > 0 && restart_grace_time > 0 );
  591.      {
  592. fprintf(stderr, "** wait %d seconds for last %d connects to finishn",restart_grace_time,leftover);
  593. sleep(1);
  594. restart_grace_time--;
  595. }
  596. /* force close all */
  597.      cn_closeall();
  598. /* be nice, wait for close to be really done */
  599.      sleep(1);
  600.              fprintf(stderr, "** closing logs...n");
  601.      log_close();
  602.      leftover=cn_active();
  603.              if ( leftover > 0 )
  604. fprintf(stderr, "** ups, could not close %d connectsn",leftover);
  605.             fprintf(stderr, "** old process will die nown");
  606. exit(0);
  607.             break;
  608.   case SIGCHLD:
  609.     break;
  610.     
  611.   default:
  612.     if (debug)
  613. fprintf(stderr, "** Got unknown signal: %dn", sig);
  614.     
  615.     syslog(LOG_ERR, "unknown signal (%d) received - ignored", sig);
  616. }
  617.     }
  618.     
  619.     return 0;
  620. }