Diff for /embedaddon/lighttpd/src/server.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2014/06/15 20:20:06 version 1.1.1.3, 2016/11/02 10:35:00
Line 1 Line 1
   #include "first.h"
   
 #include "server.h"  #include "server.h"
 #include "buffer.h"  #include "buffer.h"
 #include "network.h"  #include "network.h"
Line 76  static int l_issetugid(void) { Line 78  static int l_issetugid(void) {
 # endif  # endif
 #endif  #endif
   
   static int oneshot_fd = 0;
 static volatile sig_atomic_t srv_shutdown = 0;  static volatile sig_atomic_t srv_shutdown = 0;
 static volatile sig_atomic_t graceful_shutdown = 0;  static volatile sig_atomic_t graceful_shutdown = 0;
 static volatile sig_atomic_t handle_sig_alarm = 1;  static volatile sig_atomic_t handle_sig_alarm = 1;
Line 145  static void signal_handler(int sig) { Line 148  static void signal_handler(int sig) {
 #endif  #endif
   
 #ifdef HAVE_FORK  #ifdef HAVE_FORK
static void daemonize(void) {static int daemonize(void) {
         int pipefd[2];
         pid_t pid;
 #ifdef SIGTTOU  #ifdef SIGTTOU
         signal(SIGTTOU, SIG_IGN);          signal(SIGTTOU, SIG_IGN);
 #endif  #endif
Line 155  static void daemonize(void) { Line 160  static void daemonize(void) {
 #ifdef SIGTSTP  #ifdef SIGTSTP
         signal(SIGTSTP, SIG_IGN);          signal(SIGTSTP, SIG_IGN);
 #endif  #endif
         if (0 != fork()) exit(0);  
   
           if (pipe(pipefd) < 0) exit(-1);
   
           if (0 > (pid = fork())) exit(-1);
   
           if (0 < pid) {
                   char buf;
                   ssize_t bytes;
   
                   close(pipefd[1]);
                   /* parent waits for grandchild to be ready */
                   do {
                           bytes = read(pipefd[0], &buf, sizeof(buf));
                   } while (bytes < 0 && EINTR == errno);
                   close(pipefd[0]);
   
                   if (bytes <= 0) {
                           /* closed fd (without writing) == failure in grandchild */
                           fputs("daemonized server failed to start; check error log for details\n", stderr);
                           exit(-1);
                   }
   
                   exit(0);
           }
   
           close(pipefd[0]);
   
         if (-1 == setsid()) exit(0);          if (-1 == setsid()) exit(0);
   
         signal(SIGHUP, SIG_IGN);          signal(SIGHUP, SIG_IGN);
Line 164  static void daemonize(void) { Line 194  static void daemonize(void) {
         if (0 != fork()) exit(0);          if (0 != fork()) exit(0);
   
         if (0 != chdir("/")) exit(0);          if (0 != chdir("/")) exit(0);
   
           fd_close_on_exec(pipefd[1]);
           return pipefd[1];
 }  }
 #endif  #endif
   
Line 243  static server *server_init(void) { Line 276  static server *server_init(void) {
         srv->srvconf.network_backend = buffer_init();          srv->srvconf.network_backend = buffer_init();
         srv->srvconf.upload_tempdirs = array_init();          srv->srvconf.upload_tempdirs = array_init();
         srv->srvconf.reject_expect_100_with_417 = 1;          srv->srvconf.reject_expect_100_with_417 = 1;
           srv->srvconf.xattr_name = buffer_init_string("Content-Type");
           srv->srvconf.http_header_strict  = 1;
           srv->srvconf.http_host_strict    = 1; /*(implies http_host_normalize)*/
           srv->srvconf.http_host_normalize = 0;
           srv->srvconf.high_precision_timestamps = 0;
   
         /* use syslog */          /* use syslog */
         srv->errorlog_fd = STDERR_FILENO;          srv->errorlog_fd = STDERR_FILENO;
Line 260  static void server_free(server *srv) { Line 298  static void server_free(server *srv) {
                 buffer_free(srv->mtime_cache[i].str);                  buffer_free(srv->mtime_cache[i].str);
         }          }
   
           if (oneshot_fd > 0) {
                   close(oneshot_fd);
           }
   
 #define CLEAN(x) \  #define CLEAN(x) \
         buffer_free(srv->x);          buffer_free(srv->x);
   
Line 283  static void server_free(server *srv) { Line 325  static void server_free(server *srv) {
         CLEAN(srvconf.pid_file);          CLEAN(srvconf.pid_file);
         CLEAN(srvconf.modules_dir);          CLEAN(srvconf.modules_dir);
         CLEAN(srvconf.network_backend);          CLEAN(srvconf.network_backend);
           CLEAN(srvconf.xattr_name);
   
         CLEAN(tmp_chunk_len);          CLEAN(tmp_chunk_len);
 #undef CLEAN  #undef CLEAN
Line 309  static void server_free(server *srv) { Line 352  static void server_free(server *srv) {
                         buffer_free(s->ssl_dh_file);                          buffer_free(s->ssl_dh_file);
                         buffer_free(s->ssl_ec_curve);                          buffer_free(s->ssl_ec_curve);
                         buffer_free(s->error_handler);                          buffer_free(s->error_handler);
                           buffer_free(s->error_handler_404);
                         buffer_free(s->errorfile_prefix);                          buffer_free(s->errorfile_prefix);
                         array_free(s->mimetypes);                          array_free(s->mimetypes);
                         buffer_free(s->ssl_verifyclient_username);                          buffer_free(s->ssl_verifyclient_username);
Line 347  static void server_free(server *srv) { Line 391  static void server_free(server *srv) {
         if (srv->ssl_is_init) {          if (srv->ssl_is_init) {
                 CRYPTO_cleanup_all_ex_data();                  CRYPTO_cleanup_all_ex_data();
                 ERR_free_strings();                  ERR_free_strings();
                 #if   OPENSSL_VERSION_NUMBER >= 0x10100000L \
                   && !defined(LIBRESSL_VERSION_NUMBER)
                   /*(OpenSSL libraries handle thread init and deinit)
                    * https://github.com/openssl/openssl/pull/1048 */
                 #elif OPENSSL_VERSION_NUMBER >= 0x10000000L
                   ERR_remove_thread_state(NULL);
                 #else
                 ERR_remove_state(0);                  ERR_remove_state(0);
                 #endif
                 EVP_cleanup();                  EVP_cleanup();
         }          }
 #endif  #endif
Line 355  static void server_free(server *srv) { Line 407  static void server_free(server *srv) {
         free(srv);          free(srv);
 }  }
   
   static void remove_pid_file(server *srv, int *pid_fd) {
           if (!buffer_string_is_empty(srv->srvconf.pid_file) && 0 <= *pid_fd) {
                   if (0 != ftruncate(*pid_fd, 0)) {
                           log_error_write(srv, __FILE__, __LINE__, "sbds",
                                           "ftruncate failed for:",
                                           srv->srvconf.pid_file,
                                           errno,
                                           strerror(errno));
                   }
           }
           if (0 <= *pid_fd) {
                   close(*pid_fd);
                   *pid_fd = -1;
           }
           if (!buffer_string_is_empty(srv->srvconf.pid_file) &&
               buffer_string_is_empty(srv->srvconf.changeroot)) {
                   if (0 != unlink(srv->srvconf.pid_file->ptr)) {
                           if (errno != EACCES && errno != EPERM) {
                                   log_error_write(srv, __FILE__, __LINE__, "sbds",
                                                   "unlink failed for:",
                                                   srv->srvconf.pid_file,
                                                   errno,
                                                   strerror(errno));
                           }
                   }
           }
   }
   
   
   static server_socket * server_oneshot_getsock(server *srv, sock_addr *cnt_addr) {
           server_socket *srv_socket, *srv_socket_wild = NULL;
           size_t i;
           for (i = 0; i < srv->srv_sockets.used; ++i) {
                   srv_socket = srv->srv_sockets.ptr[i];
                   if (cnt_addr->plain.sa_family != srv_socket->addr.plain.sa_family) continue;
                   switch (cnt_addr->plain.sa_family) {
                   case AF_INET:
                           if (srv_socket->addr.ipv4.sin_port != cnt_addr->ipv4.sin_port) continue;
                           if (srv_socket->addr.ipv4.sin_addr.s_addr == cnt_addr->ipv4.sin_addr.s_addr) {
                                   return srv_socket;
                           }
                           if (srv_socket->addr.ipv4.sin_addr.s_addr == htonl(INADDR_ANY)) {
                                   srv_socket_wild = srv_socket;
                           }
                           continue;
                   #ifdef HAVE_IPV6
                   case AF_INET6:
                           if (srv_socket->addr.ipv6.sin6_port != cnt_addr->ipv6.sin6_port) continue;
                           if (0 == memcmp(&srv_socket->addr.ipv6.sin6_addr, &cnt_addr->ipv6.sin6_addr, sizeof(struct in6_addr))) {
                                   return srv_socket;
                           }
                           if (0 == memcmp(&srv_socket->addr.ipv6.sin6_addr, &in6addr_any, sizeof(struct in6_addr))) {
                                   srv_socket_wild = srv_socket;
                           }
                           continue;
                   #endif
                   #ifdef HAVE_SYS_UN_H
                   case AF_UNIX:
                           if (0 == strcmp(srv_socket->addr.un.sun_path, cnt_addr->un.sun_path)) {
                                   return srv_socket;
                           }
                           continue;
                   #endif
                   default: continue;
                   }
           }
   
           if (NULL != srv_socket_wild) {
                   return srv_socket_wild;
           } else if (srv->srv_sockets.used) {
                   return srv->srv_sockets.ptr[0];
           } else {
                   log_error_write(srv, __FILE__, __LINE__, "s", "no sockets configured");
                   return NULL;
           }
   }
   
   
   static int server_oneshot_init(server *srv, int fd) {
           /* Note: does not work with netcat due to requirement that fd be socket.
            * STDOUT_FILENO was not saved earlier in startup, and that is to where
            * netcat expects output to be sent.  Since lighttpd expects connections
            * to be sockets, con->fd is where output is sent; separate fds are not
            * stored for input and output, but netcat has different fds for stdin
            * and * stdout.  To support netcat, would additionally need to avoid
            * S_ISSOCK(), getsockname(), and getpeername() below, reconstructing
            * addresses from environment variables:
            *   NCAT_LOCAL_ADDR   NCAT_LOCAL_PORT
            *   NCAT_REMOTE_ADDR  NCAT_REMOTE_PORT
            *   NCAT_PROTO
            */
           connection *con;
           server_socket *srv_socket;
           sock_addr cnt_addr;
           socklen_t cnt_len;
           struct stat st;
   
           if (0 != fstat(fd, &st)) {
                   log_error_write(srv, __FILE__, __LINE__, "ss", "fstat:", strerror(errno));
                   return 0;
           }
   
           if (!S_ISSOCK(st.st_mode)) {
                   /* require that fd is a socket
                    * (modules might expect STDIN_FILENO and STDOUT_FILENO opened to /dev/null) */
                   log_error_write(srv, __FILE__, __LINE__, "s", "lighttpd -1 stdin is not a socket");
                   return 0;
           }
   
           cnt_len = sizeof(cnt_addr);
           if (0 != getsockname(fd, (struct sockaddr *)&cnt_addr, &cnt_len)) {
                   log_error_write(srv, __FILE__, __LINE__, "ss", "getsockname:", strerror(errno));
                   return 0;
           }
   
           srv_socket = server_oneshot_getsock(srv, &cnt_addr);
           if (NULL == srv_socket) return 0;
   
           cnt_len = sizeof(cnt_addr);
           if (0 != getpeername(fd, (struct sockaddr *)&cnt_addr, &cnt_len)) {
                   log_error_write(srv, __FILE__, __LINE__, "ss", "getpeername:", strerror(errno));
                   return 0;
           }
   
           if (cnt_addr.plain.sa_family != AF_UNIX) {
                   network_accept_tcp_nagle_disable(fd);
           }
   
           con = connection_accepted(srv, srv_socket, &cnt_addr, fd);
           if (NULL == con) return 0;
   
           connection_state_machine(srv, con);
           return 1;
   }
   
   
 static void show_version (void) {  static void show_version (void) {
 #ifdef USE_OPENSSL  #ifdef USE_OPENSSL
 # define TEXT_SSL " (ssl)"  # define TEXT_SSL " (ssl)"
Line 366  static void show_version (void) { Line 554  static void show_version (void) {
 "Build-Date: " __DATE__ " " __TIME__ "\n";  "Build-Date: " __DATE__ " " __TIME__ "\n";
 ;  ;
 #undef TEXT_SSL  #undef TEXT_SSL
        write(STDOUT_FILENO, b, strlen(b));        write_all(STDOUT_FILENO, b, strlen(b));
 }  }
   
 static void show_features (void) {  static void show_features (void) {
Line 422  static void show_features (void) { Line 610  static void show_features (void) {
 #else  #else
       "\t- freebsd-sendfile\n"        "\t- freebsd-sendfile\n"
 #endif  #endif
   #if defined USE_DARWIN_SENDFILE
         "\t+ darwin-sendfile\n"
   #else
         "\t- darwin-sendfile\n"
   #endif
 #if defined USE_SOLARIS_SENDFILEV  #if defined USE_SOLARIS_SENDFILEV
       "\t+ solaris-sendfilev\n"        "\t+ solaris-sendfilev\n"
 #else  #else
Line 454  static void show_features (void) { Line 647  static void show_features (void) {
 #else  #else
       "\t- bzip2 support\n"        "\t- bzip2 support\n"
 #endif  #endif
#ifdef HAVE_LIBCRYPT#if defined(HAVE_CRYPT) || defined(HAVE_CRYPT_R) || defined(HAVE_LIBCRYPT)
       "\t+ crypt support\n"        "\t+ crypt support\n"
 #else  #else
       "\t- crypt support\n"        "\t- crypt support\n"
Line 479  static void show_features (void) { Line 672  static void show_features (void) {
 #else  #else
       "\t- LDAP support\n"        "\t- LDAP support\n"
 #endif  #endif
#ifdef HAVE_MEMCACHE_H#ifdef USE_MEMCACHED
       "\t+ memcached support\n"        "\t+ memcached support\n"
 #else  #else
       "\t- memcached support\n"        "\t- memcached support\n"
Line 525  static void show_help (void) { Line 718  static void show_help (void) {
 "usage:\n" \  "usage:\n" \
 " -f <name>  filename of the config-file\n" \  " -f <name>  filename of the config-file\n" \
 " -m <name>  module directory (default: "LIBRARY_DIR")\n" \  " -m <name>  module directory (default: "LIBRARY_DIR")\n" \
   " -i <secs>  graceful shutdown after <secs> of inactivity\n" \
   " -1         process single (one) request on stdin socket, then exit\n" \
 " -p         print the parsed config-file in internal form, and exit\n" \  " -p         print the parsed config-file in internal form, and exit\n" \
" -t         test the config-file, and exit\n" \" -t         test config-file syntax, then exit\n" \
 " -tt        test config-file syntax, load and init modules, then exit\n" \
 " -D         don't go to background (default: go to background)\n" \  " -D         don't go to background (default: go to background)\n" \
 " -v         show version\n" \  " -v         show version\n" \
 " -V         show compile-time features\n" \  " -V         show compile-time features\n" \
Line 535  static void show_help (void) { Line 731  static void show_help (void) {
 ;  ;
 #undef TEXT_SSL  #undef TEXT_SSL
 #undef TEXT_IPV6  #undef TEXT_IPV6
        write(STDOUT_FILENO, b, strlen(b));        write_all(STDOUT_FILENO, b, strlen(b));
 }  }
   
 int main (int argc, char **argv) {  int main (int argc, char **argv) {
Line 547  int main (int argc, char **argv) { Line 743  int main (int argc, char **argv) {
         int num_childs = 0;          int num_childs = 0;
         int pid_fd = -1, fd;          int pid_fd = -1, fd;
         size_t i;          size_t i;
           time_t idle_limit = 0, last_active_ts = time(NULL);
 #ifdef HAVE_SIGACTION  #ifdef HAVE_SIGACTION
         struct sigaction act;          struct sigaction act;
 #endif  #endif
Line 554  int main (int argc, char **argv) { Line 751  int main (int argc, char **argv) {
         struct rlimit rlim;          struct rlimit rlim;
 #endif  #endif
   
   #ifdef HAVE_FORK
           int parent_pipe_fd = -1;
   #endif
   
 #ifdef USE_ALARM  #ifdef USE_ALARM
         struct itimerval interval;          struct itimerval interval;
   
Line 563  int main (int argc, char **argv) { Line 764  int main (int argc, char **argv) {
         interval.it_value.tv_usec = 0;          interval.it_value.tv_usec = 0;
 #endif  #endif
   
   
         /* for nice %b handling in strfime() */          /* for nice %b handling in strfime() */
         setlocale(LC_TIME, "C");          setlocale(LC_TIME, "C");
   
Line 581  int main (int argc, char **argv) { Line 781  int main (int argc, char **argv) {
         i_am_root = 0;          i_am_root = 0;
 #endif  #endif
         srv->srvconf.dont_daemonize = 0;          srv->srvconf.dont_daemonize = 0;
           srv->srvconf.preflight_check = 0;
   
        while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {        while(-1 != (o = getopt(argc, argv, "f:m:i:hvVD1pt"))) {
                 switch(o) {                  switch(o) {
                 case 'f':                  case 'f':
                         if (srv->config_storage) {                          if (srv->config_storage) {
Line 600  int main (int argc, char **argv) { Line 801  int main (int argc, char **argv) {
                 case 'm':                  case 'm':
                         buffer_copy_string(srv->srvconf.modules_dir, optarg);                          buffer_copy_string(srv->srvconf.modules_dir, optarg);
                         break;                          break;
                   case 'i': {
                           char *endptr;
                           long timeout = strtol(optarg, &endptr, 0);
                           if (!*optarg || *endptr || timeout < 0) {
                                   log_error_write(srv, __FILE__, __LINE__, "ss",
                                                   "Invalid idle timeout value:", optarg);
                                   server_free(srv);
                                   return -1;
                           }
                           idle_limit = (time_t)timeout;
                           break;
                   }
                 case 'p': print_config = 1; break;                  case 'p': print_config = 1; break;
                case 't': test_config = 1; break;                case 't': ++test_config; break;
                 case '1': oneshot_fd = dup(STDIN_FILENO); break;
                 case 'D': srv->srvconf.dont_daemonize = 1; break;                  case 'D': srv->srvconf.dont_daemonize = 1; break;
                case 'v': show_version(); return 0;                case 'v': show_version(); server_free(srv); return 0;
                case 'V': show_features(); return 0;                case 'V': show_features(); server_free(srv); return 0;
                case 'h': show_help(); return 0;                case 'h': show_help(); server_free(srv); return 0;
                 default:                  default:
                         show_help();                          show_help();
                         server_free(srv);                          server_free(srv);
Line 633  int main (int argc, char **argv) { Line 847  int main (int argc, char **argv) {
         }          }
   
         if (test_config) {          if (test_config) {
                printf("Syntax OK\n");                if (1 == test_config) {
                         printf("Syntax OK\n");
                 } else { /*(test_config > 1)*/
                         test_config = 0;
                         srv->srvconf.preflight_check = 1;
                         srv->srvconf.dont_daemonize = 1;
                         buffer_reset(srv->srvconf.pid_file);
                 }
         }          }
   
         if (test_config || print_config) {          if (test_config || print_config) {
Line 641  int main (int argc, char **argv) { Line 862  int main (int argc, char **argv) {
                 return 0;                  return 0;
         }          }
   
           if (oneshot_fd) {
                   if (oneshot_fd <= STDERR_FILENO) {
                           log_error_write(srv, __FILE__, __LINE__, "s",
                                           "Invalid fds at startup with lighttpd -1");
                           server_free(srv);
                           return -1;
                   }
                   graceful_shutdown = 1;
                   srv->sockets_disabled = 1;
                   srv->srvconf.dont_daemonize = 1;
                   buffer_reset(srv->srvconf.pid_file);
                   if (srv->srvconf.max_worker) {
                           srv->srvconf.max_worker = 0;
                           log_error_write(srv, __FILE__, __LINE__, "s",
                                           "server one-shot command line option disables server.max-worker config file option.");
                   }
           }
   
         /* close stdin and stdout, as they are not needed */          /* close stdin and stdout, as they are not needed */
         openDevNull(STDIN_FILENO);          openDevNull(STDIN_FILENO);
         openDevNull(STDOUT_FILENO);          openDevNull(STDOUT_FILENO);
Line 666  int main (int argc, char **argv) { Line 905  int main (int argc, char **argv) {
 #endif  #endif
   
         /* check document-root */          /* check document-root */
        if (srv->config_storage[0]->document_root->used <= 1) {        if (buffer_string_is_empty(srv->config_storage[0]->document_root)) {
                 log_error_write(srv, __FILE__, __LINE__, "s",                  log_error_write(srv, __FILE__, __LINE__, "s",
                                 "document-root is not set\n");                                  "document-root is not set\n");
   
Line 686  int main (int argc, char **argv) { Line 925  int main (int argc, char **argv) {
         }          }
   
         /* open pid file BEFORE chroot */          /* open pid file BEFORE chroot */
        if (srv->srvconf.pid_file->used) {        if (!buffer_string_is_empty(srv->srvconf.pid_file)) {
                 if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {                  if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
                         struct stat st;                          struct stat st;
                         if (errno != EEXIST) {                          if (errno != EEXIST) {
Line 712  int main (int argc, char **argv) { Line 951  int main (int argc, char **argv) {
                                 return -1;                                  return -1;
                         }                          }
                 }                  }
                   fd_close_on_exec(pid_fd);
         }          }
   
         if (srv->event_handler == FDEVENT_HANDLER_SELECT) {          if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
Line 756  int main (int argc, char **argv) { Line 996  int main (int argc, char **argv) {
                 }                  }
   
                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {                  if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
                        srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;                        srv->max_fds = rlim.rlim_cur < (rlim_t)FD_SETSIZE - 200 ? (int)rlim.rlim_cur : (int)FD_SETSIZE - 200;
                 } else {                  } else {
                         srv->max_fds = rlim.rlim_cur;                          srv->max_fds = rlim.rlim_cur;
                 }                  }
Line 780  int main (int argc, char **argv) { Line 1020  int main (int argc, char **argv) {
   
 #ifdef HAVE_PWD_H  #ifdef HAVE_PWD_H
                 /* set user and group */                  /* set user and group */
                if (srv->srvconf.username->used) {                if (!buffer_string_is_empty(srv->srvconf.groupname)) {
                         if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
                                 log_error_write(srv, __FILE__, __LINE__, "sb",
                                         "can't find groupname", srv->srvconf.groupname);
                                 return -1;
                         }
                 }
 
                 if (!buffer_string_is_empty(srv->srvconf.username)) {
                         if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {                          if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
                                 log_error_write(srv, __FILE__, __LINE__, "sb",                                  log_error_write(srv, __FILE__, __LINE__, "sb",
                                                 "can't find username", srv->srvconf.username);                                                  "can't find username", srv->srvconf.username);
Line 792  int main (int argc, char **argv) { Line 1040  int main (int argc, char **argv) {
                                                 "I will not set uid to 0\n");                                                  "I will not set uid to 0\n");
                                 return -1;                                  return -1;
                         }                          }
                 }  
   
                if (srv->srvconf.groupname->used) {                        if (NULL == grp && NULL == (grp = getgrgid(pwd->pw_gid))) {
                        if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {                                log_error_write(srv, __FILE__, __LINE__, "sd",
                                log_error_write(srv, __FILE__, __LINE__, "sb",                                        "can't find group id", pwd->pw_gid);
                                        "can't find groupname", srv->srvconf.groupname); 
                                 return -1;                                  return -1;
                         }                          }
                   }
   
                   if (NULL != grp) {
                         if (grp->gr_gid == 0) {                          if (grp->gr_gid == 0) {
                                 log_error_write(srv, __FILE__, __LINE__, "s",                                  log_error_write(srv, __FILE__, __LINE__, "s",
                                                 "I will not set gid to 0\n");                                                  "I will not set gid to 0\n");
Line 828  int main (int argc, char **argv) { Line 1077  int main (int argc, char **argv) {
                                 log_error_write(srv, __FILE__, __LINE__, "ss", "setgroups failed: ", strerror(errno));                                  log_error_write(srv, __FILE__, __LINE__, "ss", "setgroups failed: ", strerror(errno));
                                 return -1;                                  return -1;
                         }                          }
                        if (srv->srvconf.username->used) {                        if (!buffer_string_is_empty(srv->srvconf.username)) {
                                 initgroups(srv->srvconf.username->ptr, grp->gr_gid);                                  initgroups(srv->srvconf.username->ptr, grp->gr_gid);
                         }                          }
                 }                  }
 #endif  #endif
 #ifdef HAVE_CHROOT  #ifdef HAVE_CHROOT
                if (srv->srvconf.changeroot->used) {                if (!buffer_string_is_empty(srv->srvconf.changeroot)) {
                         tzset();                          tzset();
   
                         if (-1 == chroot(srv->srvconf.changeroot->ptr)) {                          if (-1 == chroot(srv->srvconf.changeroot->ptr)) {
Line 875  int main (int argc, char **argv) { Line 1124  int main (int argc, char **argv) {
                 }                  }
   
                 /**                  /**
                 * we are not root can can't increase the fd-limit, but we can reduce it                 * we are not root can can't increase the fd-limit above rlim_max, but we can reduce it
                  */                   */
                if (srv->srvconf.max_fds && srv->srvconf.max_fds < rlim.rlim_cur) {                if (srv->srvconf.max_fds && srv->srvconf.max_fds <= rlim.rlim_max) {
                         /* set rlimits */                          /* set rlimits */
   
                         rlim.rlim_cur = srv->srvconf.max_fds;                          rlim.rlim_cur = srv->srvconf.max_fds;
Line 891  int main (int argc, char **argv) { Line 1140  int main (int argc, char **argv) {
                 }                  }
   
                 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {                  if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
                        srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;                        srv->max_fds = rlim.rlim_cur < (rlim_t)FD_SETSIZE - 200 ? (int)rlim.rlim_cur : (int)FD_SETSIZE - 200;
                 } else {                  } else {
                         srv->max_fds = rlim.rlim_cur;                          srv->max_fds = rlim.rlim_cur;
                 }                  }
Line 946  int main (int argc, char **argv) { Line 1195  int main (int argc, char **argv) {
   
 #ifdef HAVE_FORK  #ifdef HAVE_FORK
         /* network is up, let's deamonize ourself */          /* network is up, let's deamonize ourself */
        if (srv->srvconf.dont_daemonize == 0) daemonize();        if (srv->srvconf.dont_daemonize == 0) {
                 parent_pipe_fd = daemonize();
         }
 #endif  #endif
   
   
Line 968  int main (int argc, char **argv) { Line 1219  int main (int argc, char **argv) {
         sigaction(SIGTERM, &act, NULL);          sigaction(SIGTERM, &act, NULL);
         sigaction(SIGHUP,  &act, NULL);          sigaction(SIGHUP,  &act, NULL);
         sigaction(SIGALRM, &act, NULL);          sigaction(SIGALRM, &act, NULL);
   
           /* it should be safe to restart syscalls after SIGCHLD */
           act.sa_flags |= SA_RESTART | SA_NOCLDSTOP;
         sigaction(SIGCHLD, &act, NULL);          sigaction(SIGCHLD, &act, NULL);
   
 #elif defined(HAVE_SIGNAL)  #elif defined(HAVE_SIGNAL)
Line 999  int main (int argc, char **argv) { Line 1253  int main (int argc, char **argv) {
   
         /* write pid file */          /* write pid file */
         if (pid_fd != -1) {          if (pid_fd != -1) {
                buffer_copy_long(srv->tmp_buf, getpid());                buffer_copy_int(srv->tmp_buf, getpid());
                 buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("\n"));                  buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("\n"));
                force_assert(srv->tmp_buf->used > 0);                if (-1 == write_all(pid_fd, CONST_BUF_LEN(srv->tmp_buf))) {
                write(pid_fd, srv->tmp_buf->ptr, srv->tmp_buf->used - 1);                        log_error_write(srv, __FILE__, __LINE__, "ss", "Couldn't write pid file:", strerror(errno));
                close(pid_fd);                        close(pid_fd);
                pid_fd = -1;                        return -1;
                 }
         }          }
   
         /* Close stderr ASAP in the child process to make sure that nothing          /* Close stderr ASAP in the child process to make sure that nothing
          * is being written to that fd which may not be valid anymore. */           * is being written to that fd which may not be valid anymore. */
        if (-1 == log_error_open(srv)) {        if (!srv->srvconf.preflight_check && -1 == log_error_open(srv)) {
                 log_error_write(srv, __FILE__, __LINE__, "s", "Opening errorlog failed. Going down.");                  log_error_write(srv, __FILE__, __LINE__, "s", "Opening errorlog failed. Going down.");
   
                 plugins_free(srv);                  plugins_free(srv);
Line 1028  int main (int argc, char **argv) { Line 1283  int main (int argc, char **argv) {
                 return -1;                  return -1;
         }          }
   
           /* settings might be enabled during module config set defaults */
           srv->config_storage[0]->high_precision_timestamps = srv->srvconf.high_precision_timestamps;
   
         /* dump unused config-keys */          /* dump unused config-keys */
         for (i = 0; i < srv->config_context->used; i++) {          for (i = 0; i < srv->config_context->used; i++) {
                 array *config = ((data_config *)srv->config_context->data[i])->value;                  array *config = ((data_config *)srv->config_context->data[i])->value;
Line 1068  int main (int argc, char **argv) { Line 1326  int main (int argc, char **argv) {
                 return -1;                  return -1;
         }          }
   
           if (srv->srvconf.preflight_check) {
                   /*printf("Preflight OK");*//*(stdout reopened to /dev/null)*/
                   plugins_free(srv);
                   network_close(srv);
                   server_free(srv);
   
                   exit(0);
           }
   
   
 #ifdef HAVE_FORK  #ifdef HAVE_FORK
           /**
            * notify daemonize-grandparent of successful startup
            * do this before any further forking is done (workers)
            */
           if (srv->srvconf.dont_daemonize == 0) {
                   if (0 > write(parent_pipe_fd, "", 1)) return -1;
                   close(parent_pipe_fd);
           }
   
           if (idle_limit && srv->srvconf.max_worker) {
                   srv->srvconf.max_worker = 0;
                   log_error_write(srv, __FILE__, __LINE__, "s",
                                   "server idle time limit command line option disables server.max-worker config file option.");
           }
   
         /* start watcher and workers */          /* start watcher and workers */
         num_childs = srv->srvconf.max_worker;          num_childs = srv->srvconf.max_worker;
         if (num_childs > 0) {          if (num_childs > 0) {
Line 1111  int main (int argc, char **argv) { Line 1393  int main (int argc, char **argv) {
                                                          *                                                            * 
                                                          * we also send it ourself                                                           * we also send it ourself
                                                          */                                                           */
                                                        if (!forwarded_sig_hup) {                                                        if (!forwarded_sig_hup && 0 != srv->srvconf.max_worker) {
                                                                 forwarded_sig_hup = 1;                                                                  forwarded_sig_hup = 1;
                                                                 kill(0, SIGHUP);                                                                  kill(0, SIGHUP);
                                                         }                                                          }
Line 1137  int main (int argc, char **argv) { Line 1419  int main (int argc, char **argv) {
                                 kill(0, SIGTERM);                                  kill(0, SIGTERM);
                         }                          }
   
                           remove_pid_file(srv, &pid_fd);
                         log_error_close(srv);                          log_error_close(srv);
                         network_close(srv);                          network_close(srv);
                         connections_free(srv);                          connections_free(srv);
Line 1144  int main (int argc, char **argv) { Line 1427  int main (int argc, char **argv) {
                         server_free(srv);                          server_free(srv);
                         return 0;                          return 0;
                 }                  }
   
                   /**
                    * make sure workers do not muck with pid-file
                    */
                   if (0 <= pid_fd) {
                           close(pid_fd);
                           pid_fd = -1;
                   }
                   buffer_reset(srv->srvconf.pid_file);
         }          }
 #endif  #endif
   
Line 1204  int main (int argc, char **argv) { Line 1496  int main (int argc, char **argv) {
   
         for (i = 0; i < srv->srv_sockets.used; i++) {          for (i = 0; i < srv->srv_sockets.used; i++) {
                 server_socket *srv_socket = srv->srv_sockets.ptr[i];                  server_socket *srv_socket = srv->srv_sockets.ptr[i];
                   if (srv->sockets_disabled) continue; /* lighttpd -1 (one-shot mode) */
                 if (-1 == fdevent_fcntl_set(srv->ev, srv_socket->fd)) {                  if (-1 == fdevent_fcntl_set(srv->ev, srv_socket->fd)) {
                         log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed:", strerror(errno));                          log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed:", strerror(errno));
                         return -1;                          return -1;
                 }                  }
         }          }
   
           if (oneshot_fd && server_oneshot_init(srv, oneshot_fd)) {
                   oneshot_fd = -1;
           }
   
         /* main-loop */          /* main-loop */
         while (!srv_shutdown) {          while (!srv_shutdown) {
                 int n;                  int n;
Line 1263  int main (int argc, char **argv) { Line 1560  int main (int argc, char **argv) {
                         min_ts = time(NULL);                          min_ts = time(NULL);
   
                         if (min_ts != srv->cur_ts) {                          if (min_ts != srv->cur_ts) {
   #ifdef DEBUG_CONNECTION_STATES
                                 int cs = 0;                                  int cs = 0;
   #endif
                                 connections *conns = srv->conns;                                  connections *conns = srv->conns;
                                 handler_t r;                                  handler_t r;
   
Line 1281  int main (int argc, char **argv) { Line 1580  int main (int argc, char **argv) {
                                 /* trigger waitpid */                                  /* trigger waitpid */
                                 srv->cur_ts = min_ts;                                  srv->cur_ts = min_ts;
   
                                   /* check idle time limit, if enabled */
                                   if (idle_limit && idle_limit < min_ts - last_active_ts && !graceful_shutdown) {
                                           log_error_write(srv, __FILE__, __LINE__, "sDs", "[note] idle timeout", (int)idle_limit,
                                                           "s exceeded, initiating graceful shutdown");
                                           graceful_shutdown = 2; /* value 2 indicates idle timeout */
                                   }
   
                                 /* cleanup stat-cache */                                  /* cleanup stat-cache */
                                 stat_cache_trigger_cleanup(srv);                                  stat_cache_trigger_cleanup(srv);
                                 /**                                  /**
Line 1288  int main (int argc, char **argv) { Line 1594  int main (int argc, char **argv) {
                                  *                                   *
                                  */                                   */
                                 for (ndx = 0; ndx < conns->used; ndx++) {                                  for (ndx = 0; ndx < conns->used; ndx++) {
                                           connection * const con = conns->ptr[ndx];
                                           const int waitevents = fdevent_event_get_interest(srv->ev, con->fd);
                                         int changed = 0;                                          int changed = 0;
                                         connection *con;  
                                         int t_diff;                                          int t_diff;
   
                                        con = conns->ptr[ndx];                                        if (con->state == CON_STATE_CLOSE) {
                                                if (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) {
                                        if (con->state == CON_STATE_READ ||                                                        changed = 1;
                                            con->state == CON_STATE_READ_POST) {                                                }
                                                if (con->request_count == 1) {                                        } else if (waitevents & FDEVENT_IN) {
                                                 if (con->request_count == 1 || con->state != CON_STATE_READ) { /* e.g. CON_STATE_READ_POST || CON_STATE_WRITE */
                                                         if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {                                                          if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
                                                                 /* time - out */                                                                  /* time - out */
#if 0                                                                if (con->conf.log_request_handling) {
                                                                log_error_write(srv, __FILE__, __LINE__, "sd",                                                                        log_error_write(srv, __FILE__, __LINE__, "sd",
                                                                                "connection closed - read-timeout:", con->fd);                                                                                "connection closed - read timeout:", con->fd);
#endif                                                                }
 
                                                                 connection_set_state(srv, con, CON_STATE_ERROR);                                                                  connection_set_state(srv, con, CON_STATE_ERROR);
                                                                 changed = 1;                                                                  changed = 1;
                                                         }                                                          }
                                                 } else {                                                  } else {
                                                         if (srv->cur_ts - con->read_idle_ts > con->keep_alive_idle) {                                                          if (srv->cur_ts - con->read_idle_ts > con->keep_alive_idle) {
                                                                 /* time - out */                                                                  /* time - out */
#if 0                                                                if (con->conf.log_request_handling) {
                                                                log_error_write(srv, __FILE__, __LINE__, "sd",                                                                        log_error_write(srv, __FILE__, __LINE__, "sd",
                                                                                "connection closed - read-timeout:", con->fd);                                                                                "connection closed - keep-alive timeout:", con->fd);
#endif                                                                }
 
                                                                 connection_set_state(srv, con, CON_STATE_ERROR);                                                                  connection_set_state(srv, con, CON_STATE_ERROR);
                                                                 changed = 1;                                                                  changed = 1;
                                                         }                                                          }
                                                 }                                                  }
                                         }                                          }
   
                                           /* max_write_idle timeout currently functions as backend timeout,
                                            * too, after response has been started.
                                            * future: have separate backend timeout, and then change this
                                            * to check for write interest before checking for timeout */
                                           /*if (waitevents & FDEVENT_OUT)*/
                                         if ((con->state == CON_STATE_WRITE) &&                                          if ((con->state == CON_STATE_WRITE) &&
                                             (con->write_request_ts != 0)) {                                              (con->write_request_ts != 0)) {
 #if 0  #if 0
Line 1331  int main (int argc, char **argv) { Line 1646  int main (int argc, char **argv) {
                                                 if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {                                                  if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
                                                         /* time - out */                                                          /* time - out */
                                                         if (con->conf.log_timeouts) {                                                          if (con->conf.log_timeouts) {
                                                                log_error_write(srv, __FILE__, __LINE__, "sbsosds",                                                                log_error_write(srv, __FILE__, __LINE__, "sbsbsosds",
                                                                        "NOTE: a request for",                                                                        "NOTE: a request from",
                                                                         con->dst_addr_buf,
                                                                         "for",
                                                                         con->request.uri,                                                                          con->request.uri,
                                                                         "timed out after writing",                                                                          "timed out after writing",
                                                                         con->bytes_written,                                                                          con->bytes_written,
Line 1345  int main (int argc, char **argv) { Line 1662  int main (int argc, char **argv) {
                                                 }                                                  }
                                         }                                          }
   
                                         if (con->state == CON_STATE_CLOSE && (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT)) {  
                                                 changed = 1;  
                                         }  
   
                                         /* we don't like div by zero */                                          /* we don't like div by zero */
                                         if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;                                          if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
   
Line 1367  int main (int argc, char **argv) { Line 1680  int main (int argc, char **argv) {
                                         con->bytes_written_cur_second = 0;                                          con->bytes_written_cur_second = 0;
                                         *(con->conf.global_bytes_per_second_cnt_ptr) = 0;                                          *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
   
#if 0#if DEBUG_CONNECTION_STATES
                                         if (cs == 0) {                                          if (cs == 0) {
                                                 fprintf(stderr, "connection-state: ");                                                  fprintf(stderr, "connection-state: ");
                                                 cs = 1;                                                  cs = 1;
Line 1380  int main (int argc, char **argv) { Line 1693  int main (int argc, char **argv) {
 #endif  #endif
                                 }                                  }
   
   #ifdef DEBUG_CONNECTION_STATES
                                 if (cs == 1) fprintf(stderr, "\n");                                  if (cs == 1) fprintf(stderr, "\n");
   #endif
                         }                          }
                 }                  }
   
Line 1408  int main (int argc, char **argv) { Line 1723  int main (int argc, char **argv) {
   
                                 for (i = 0; i < srv->srv_sockets.used; i++) {                                  for (i = 0; i < srv->srv_sockets.used; i++) {
                                         server_socket *srv_socket = srv->srv_sockets.ptr[i];                                          server_socket *srv_socket = srv->srv_sockets.ptr[i];
                                         fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);  
   
                                         if (graceful_shutdown) {                                          if (graceful_shutdown) {
                                                 /* we don't want this socket anymore,                                                  /* we don't want this socket anymore,
Line 1417  int main (int argc, char **argv) { Line 1731  int main (int argc, char **argv) {
                                                  * the next lighttpd to take over (graceful restart)                                                   * the next lighttpd to take over (graceful restart)
                                                  *  */                                                   *  */
   
                                                   fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
                                                 fdevent_unregister(srv->ev, srv_socket->fd);                                                  fdevent_unregister(srv->ev, srv_socket->fd);
                                                 close(srv_socket->fd);                                                  close(srv_socket->fd);
                                                 srv_socket->fd = -1;                                                  srv_socket->fd = -1;
   
                                                 /* network_close() will cleanup after us */                                                  /* network_close() will cleanup after us */
                                        } else {
                                                if (srv->srvconf.pid_file->used &&                                                fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, 0);
                                                    srv->srvconf.changeroot->used == 0) { 
                                                        if (0 != unlink(srv->srvconf.pid_file->ptr)) { 
                                                                if (errno != EACCES && errno != EPERM) { 
                                                                        log_error_write(srv, __FILE__, __LINE__, "sbds", 
                                                                                        "unlink failed for:", 
                                                                                        srv->srvconf.pid_file, 
                                                                                        errno, 
                                                                                        strerror(errno)); 
                                                                } 
                                                        } 
                                                } 
                                         }                                          }
                                 }                                  }
   
                                 if (graceful_shutdown) {                                  if (graceful_shutdown) {
                                           remove_pid_file(srv, &pid_fd);
                                         log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");                                          log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
                                 } else if (srv->conns->used >= srv->max_conns) {                                  } else if (srv->conns->used >= srv->max_conns) {
                                         log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached");                                          log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached");
Line 1454  int main (int argc, char **argv) { Line 1759  int main (int argc, char **argv) {
                         /* we are in graceful shutdown phase and all connections are closed                          /* we are in graceful shutdown phase and all connections are closed
                          * we are ready to terminate without harming anyone */                           * we are ready to terminate without harming anyone */
                         srv_shutdown = 1;                          srv_shutdown = 1;
                           break;
                 }                  }
   
                 /* we still have some fds to share */                  /* we still have some fds to share */
Line 1473  int main (int argc, char **argv) { Line 1779  int main (int argc, char **argv) {
                         /* n is the number of events */                          /* n is the number of events */
                         int revents;                          int revents;
                         int fd_ndx;                          int fd_ndx;
#if 0                        last_active_ts = srv->cur_ts;
                        if (n > 0) { 
                                log_error_write(srv, __FILE__, __LINE__, "sd", 
                                                "polls:", n); 
                        } 
#endif 
                         fd_ndx = -1;                          fd_ndx = -1;
                         do {                          do {
                                 fdevent_handler handler;                                  fdevent_handler handler;
                                 void *context;                                  void *context;
                                 handler_t r;  
   
                                 fd_ndx  = fdevent_event_next_fdndx (srv->ev, fd_ndx);                                  fd_ndx  = fdevent_event_next_fdndx (srv->ev, fd_ndx);
                                 if (-1 == fd_ndx) break; /* not all fdevent handlers know how many fds got an event */                                  if (-1 == fd_ndx) break; /* not all fdevent handlers know how many fds got an event */
Line 1492  int main (int argc, char **argv) { Line 1792  int main (int argc, char **argv) {
                                 fd      = fdevent_event_get_fd     (srv->ev, fd_ndx);                                  fd      = fdevent_event_get_fd     (srv->ev, fd_ndx);
                                 handler = fdevent_get_handler(srv->ev, fd);                                  handler = fdevent_get_handler(srv->ev, fd);
                                 context = fdevent_get_context(srv->ev, fd);                                  context = fdevent_get_context(srv->ev, fd);
                                (*handler)(srv, context, revents);
                                /* connection_handle_fdevent needs a joblist_append */ 
#if 0 
                                log_error_write(srv, __FILE__, __LINE__, "sdd", 
                                                "event for", fd, revents); 
#endif 
                                switch (r = (*handler)(srv, context, revents)) { 
                                case HANDLER_FINISHED: 
                                case HANDLER_GO_ON: 
                                case HANDLER_WAIT_FOR_EVENT: 
                                case HANDLER_WAIT_FOR_FD: 
                                        break; 
                                case HANDLER_ERROR: 
                                        /* should never happen */ 
                                        SEGFAULT(); 
                                        break; 
                                default: 
                                        log_error_write(srv, __FILE__, __LINE__, "d", r); 
                                        break; 
                                } 
                         } while (--n > 0);                          } while (--n > 0);
                 } else if (n < 0 && errno != EINTR) {                  } else if (n < 0 && errno != EINTR) {
                         log_error_write(srv, __FILE__, __LINE__, "ss",                          log_error_write(srv, __FILE__, __LINE__, "ss",
Line 1521  int main (int argc, char **argv) { Line 1802  int main (int argc, char **argv) {
   
                 for (ndx = 0; ndx < srv->joblist->used; ndx++) {                  for (ndx = 0; ndx < srv->joblist->used; ndx++) {
                         connection *con = srv->joblist->ptr[ndx];                          connection *con = srv->joblist->ptr[ndx];
                         handler_t r;  
   
                         connection_state_machine(srv, con);                          connection_state_machine(srv, con);
   
                         switch(r = plugins_call_handle_joblist(srv, con)) {  
                         case HANDLER_FINISHED:  
                         case HANDLER_GO_ON:  
                                 break;  
                         default:  
                                 log_error_write(srv, __FILE__, __LINE__, "d", r);  
                                 break;  
                         }  
   
                         con->in_joblist = 0;                          con->in_joblist = 0;
                 }                  }
   
                 srv->joblist->used = 0;                  srv->joblist->used = 0;
         }          }
   
        if (srv->srvconf.pid_file->used &&        if (0 == graceful_shutdown) {
            srv->srvconf.changeroot->used == 0 &&                remove_pid_file(srv, &pid_fd);
            0 == graceful_shutdown) { 
                if (0 != unlink(srv->srvconf.pid_file->ptr)) { 
                        if (errno != EACCES && errno != EPERM) { 
                                log_error_write(srv, __FILE__, __LINE__, "sbds", 
                                                "unlink failed for:", 
                                                srv->srvconf.pid_file, 
                                                errno, 
                                                strerror(errno)); 
                        } 
                } 
         }          }
   
           if (2 == graceful_shutdown) { /* value 2 indicates idle timeout */
                   log_error_write(srv, __FILE__, __LINE__, "s",
                                   "server stopped after idle timeout");
           } else {
 #ifdef HAVE_SIGACTION  #ifdef HAVE_SIGACTION
        log_error_write(srv, __FILE__, __LINE__, "sdsd",                 log_error_write(srv, __FILE__, __LINE__, "sdsd",
                        "server stopped by UID =",                                "server stopped by UID =",
                        last_sigterm_info.si_uid,                                last_sigterm_info.si_uid,
                        "PID =",                                "PID =",
                        last_sigterm_info.si_pid);                                last_sigterm_info.si_pid);
 #else  #else
        log_error_write(srv, __FILE__, __LINE__, "s",                 log_error_write(srv, __FILE__, __LINE__, "s",
                        "server stopped");                                "server stopped");
 #endif  #endif
           }
   
         /* clean-up */          /* clean-up */
         log_error_close(srv);          log_error_close(srv);

Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>