diff --git a/NEWS b/NEWS index d128483f..6ecf7bed 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,7 @@ NEWS * New lighttpd man page (moved it to section 8) (fixes #1875) * Create rrd file for empty rrdfile in mod_rrdtool (#1788) * Fix workaround for incorrect path info/scriptname if fastcgi prefix is "/" (fixes #729) + * Finally removed spawn-fcgi - 1.4.22 - 2009-03-07 * Fix wrong lua type for CACHE_MISS/CACHE_HIT in mod_cml (fixes #533) diff --git a/doc/Makefile.am b/doc/Makefile.am index 85fdb0aa..5b2d0c89 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,4 +1,3 @@ -dist_man1_MANS=spawn-fcgi.1 dist_man8_MANS=lighttpd.8 DOCS=accesslog.txt \ diff --git a/doc/spawn-fcgi.1 b/doc/spawn-fcgi.1 deleted file mode 100644 index 2ad5bd9e..00000000 --- a/doc/spawn-fcgi.1 +++ /dev/null @@ -1,13 +0,0 @@ -.TH SPAWNFCGI 1 2003-12-21 -.SH NAME -spawn-fcgi \- spawning FastCGI processes -.SH SYNOPSIS -spawn-fcgi -f [-p | -s ] [-C ] [-c ] [-u ] [-g ] -spawn-fcgi -v -spawn-fcgi -h -.SH DESCRIPTION -spawn-fcgi is used to spawn remote FastCGI processes. -.SH SEE ALSO -lighttpd(1) -.SH AUTHOR -jan@kneschke.de diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8882cced..bc1c2655 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -433,9 +433,6 @@ LEMON_PARSER(mod_ssi_exprparser.y) SET(L_INSTALL_TARGETS) -ADD_EXECUTABLE(spawn-fcgi spawn-fcgi.c) -SET(L_INSTALL_TARGETS ${L_INSTALL_TARGETS} spawn-fcgi) - ADD_EXECUTABLE(lighttpd-angel lighttpd-angel.c) SET(L_INSTALL_TARGETS ${L_INSTALL_TARGETS} lighttpd-angel) ADD_TARGET_PROPERTIES(lighttpd-angel COMPILE_FLAGS "-DSBIN_DIR=\\\\\"${CMAKE_INSTALL_PREFIX}/${SBINDIR}\\\\\"") diff --git a/src/Makefile.am b/src/Makefile.am index 1008b36c..97a182d7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,7 +2,6 @@ AM_CFLAGS = $(FAM_CFLAGS) noinst_PROGRAMS=proc_open lemon # simple-fcgi #graphic evalo bench ajp ssl error_test adserver gen-license sbin_PROGRAMS=lighttpd lighttpd-angel -bin_PROGRAMS=spawn-fcgi LEMON=$(top_builddir)/src/lemon$(EXEEXT) lemon_SOURCES=lemon.c @@ -58,8 +57,6 @@ common_src=buffer.c log.c \ src = server.c response.c connections.c network.c \ configfile.c configparser.c request.c proc_open.c -spawn_fcgi_SOURCES=spawn-fcgi.c - lib_LTLIBRARIES = if NO_RDYNAMIC diff --git a/src/SConscript b/src/SConscript index 21dabf6a..9c7b090b 100644 --- a/src/SConscript +++ b/src/SConscript @@ -153,8 +153,6 @@ else: instbin = env.Program(bin_targets, src, LINKFLAGS = bin_linkflags, LIBS= [ env['LIBS'], common_lib, env['LIBDL'] ]) env.Depends(instbin, configparser) -spawn_fcgi = env.Program("spawn-fcgi", "spawn-fcgi.c") - if env['COMMON_LIB'] == 'bin': common_lib = instbin[1] @@ -168,9 +166,6 @@ for module in modules.keys(): inst = [] -Default(spawn_fcgi) -inst += env.Install('${bindir}', spawn_fcgi) - if env['build_dynamic']: Default(instbin[0], instlib) inst += env.Install('${sbindir}', instbin[0]) diff --git a/src/spawn-fcgi.c b/src/spawn-fcgi.c deleted file mode 100644 index afa9f05e..00000000 --- a/src/spawn-fcgi.c +++ /dev/null @@ -1,481 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - -#ifdef HAVE_PWD_H -#include -#include -#endif - -#ifdef HAVE_GETOPT_H -#include -#endif - -#define FCGI_LISTENSOCK_FILENO 0 - -#include "sys-socket.h" - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -/* for solaris 2.5 and netbsd 1.3.x */ -#ifndef HAVE_SOCKLEN_T -typedef int socklen_t; -#endif - -#ifdef HAVE_SYS_UN_H -static int fcgi_spawn_connection(char *appPath, char **appArgv, char *addr, unsigned short port, const char *unixsocket, int fork_count, int child_count, int pid_fd, int nofork) { - int fcgi_fd; - int socket_type, status, rc = 0; - struct timeval tv = { 0, 100 * 1000 }; - - struct sockaddr_un fcgi_addr_un; - struct sockaddr_in fcgi_addr_in; - struct sockaddr *fcgi_addr; - - socklen_t servlen; - - if (child_count < 2) { - child_count = 5; - } - - if (child_count > 256) { - child_count = 256; - } - - - if (unixsocket) { - memset(&fcgi_addr_un, 0, sizeof(fcgi_addr_un)); - - fcgi_addr_un.sun_family = AF_UNIX; - strcpy(fcgi_addr_un.sun_path, unixsocket); - -#ifdef SUN_LEN - servlen = SUN_LEN(&fcgi_addr_un); -#else - /* stevens says: */ - servlen = strlen(fcgi_addr_un.sun_path) + sizeof(fcgi_addr_un.sun_family); -#endif - socket_type = AF_UNIX; - fcgi_addr = (struct sockaddr *) &fcgi_addr_un; - } else { - memset(&fcgi_addr_in, 0, sizeof(fcgi_addr_in)); - fcgi_addr_in.sin_family = AF_INET; - if (addr != NULL) { - fcgi_addr_in.sin_addr.s_addr = inet_addr(addr); - } else { - fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY); - } - fcgi_addr_in.sin_port = htons(port); - servlen = sizeof(fcgi_addr_in); - - socket_type = AF_INET; - fcgi_addr = (struct sockaddr *) &fcgi_addr_in; - } - - if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) { - fprintf(stderr, "%s.%d\n", - __FILE__, __LINE__); - return -1; - } - - if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) { - /* server is not up, spawn in */ - pid_t child; - int val; - - if (unixsocket) unlink(unixsocket); - - close(fcgi_fd); - - /* reopen socket */ - if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) { - fprintf(stderr, "%s.%d\n", - __FILE__, __LINE__); - return -1; - } - - val = 1; - if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) { - fprintf(stderr, "%s.%d\n", - __FILE__, __LINE__); - return -1; - } - - /* create socket */ - if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) { - fprintf(stderr, "%s.%d: bind failed: %s\n", - __FILE__, __LINE__, - strerror(errno)); - return -1; - } - - if (-1 == listen(fcgi_fd, 1024)) { - fprintf(stderr, "%s.%d: fd = -1\n", - __FILE__, __LINE__); - return -1; - } - - while (fork_count-- > 0) { - - if (!nofork) { - child = fork(); - } else { - child = 0; - } - - switch (child) { - case 0: { - char cgi_childs[64]; - int max_fd = 0; - - int i = 0; - - /* loose control terminal */ - setsid(); - - /* is safe as we limit to 256 childs */ - sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count); - - if(fcgi_fd != FCGI_LISTENSOCK_FILENO) { - close(FCGI_LISTENSOCK_FILENO); - dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO); - close(fcgi_fd); - } - - max_fd = open("/dev/null", O_RDWR); - close(STDERR_FILENO); - dup2(max_fd, STDERR_FILENO); - close(max_fd); - - max_fd = open("/dev/null", O_RDWR); - close(STDOUT_FILENO); - dup2(max_fd, STDOUT_FILENO); - close(max_fd); - - /* we don't need the client socket */ - for (i = 3; i < max_fd; i++) { - if (i != FCGI_LISTENSOCK_FILENO) close(i); - } - - /* create environment */ - - putenv(cgi_childs); - - /* fork and replace shell */ - if (appArgv) { - execv(appArgv[0], appArgv); - - } else { - char *b = malloc(strlen("exec ") + strlen(appPath) + 1); - strcpy(b, "exec "); - strcat(b, appPath); - - /* exec the cgi */ - execl("/bin/sh", "sh", "-c", b, (char *)NULL); - } - - exit(errno); - - break; - } - case -1: - /* error */ - break; - default: - /* father */ - - /* wait */ - select(0, NULL, NULL, NULL, &tv); - - switch (waitpid(child, &status, WNOHANG)) { - case 0: - fprintf(stdout, "%s.%d: child spawned successfully: PID: %d\n", - __FILE__, __LINE__, - child); - - /* write pid file */ - if (pid_fd != -1) { - /* assume a 32bit pid_t */ - char pidbuf[12]; - - snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child); - - write(pid_fd, pidbuf, strlen(pidbuf)); - /* avoid eol for the last one */ - if (fork_count != 0) { - write(pid_fd, "\n", 1); - } - } - - break; - case -1: - break; - default: - if (WIFEXITED(status)) { - fprintf(stderr, "%s.%d: child exited with: %d\n", - __FILE__, __LINE__, WEXITSTATUS(status)); - rc = WEXITSTATUS(status); - } else if (WIFSIGNALED(status)) { - fprintf(stderr, "%s.%d: child signaled: %d\n", - __FILE__, __LINE__, - WTERMSIG(status)); - rc = 1; - } else { - fprintf(stderr, "%s.%d: child died somehow: %d\n", - __FILE__, __LINE__, - status); - rc = status; - } - } - - break; - } - } - close(pid_fd); - pid_fd = -1; - } else { - fprintf(stderr, "%s.%d: socket is already used, can't spawn\n", - __FILE__, __LINE__); - return -1; - } - - close(fcgi_fd); - - return rc; -} - - -static void show_version () { - char *b = "spawn-fcgi" "-" PACKAGE_VERSION \ -" - spawns fastcgi processes\n" -; - write(1, b, strlen(b)); -} - -static void show_help () { - char *b = \ -"Usage: spawn-fcgi [options] -- [fcgi app arguments]\n" \ -"\n" \ -"spawn-fcgi v" PACKAGE_VERSION " - spawns fastcgi processes\n" \ -"\n" \ -"Options:\n" \ -" -f filename of the fcgi-application\n" \ -" -a bind to ip address\n" \ -" -p bind to tcp-port\n" \ -" -s bind to unix-domain socket\n" \ -" -C (PHP only) numbers of childs to spawn (default 5)\n" \ -" -F numbers of childs to fork (default 1)\n" \ -" -P name of PID-file for spawed process\n" \ -" -n no fork (for daemontools)\n" \ -" -v show version\n" \ -" -h show this help\n" \ -"(root only)\n" \ -" -c chroot to directory\n" \ -" -u change to user-id\n" \ -" -g change to group-id\n" \ -; - write(1, b, strlen(b)); -} - - -int main(int argc, char **argv) { - char *fcgi_app = NULL, *changeroot = NULL, *username = NULL, - *groupname = NULL, *unixsocket = NULL, *pid_file = NULL, - *addr = NULL; - char **fcgi_app_argv = { NULL }; - unsigned short port = 0; - int child_count = 5; - int fork_count = 1; - int i_am_root, o; - int pid_fd = -1; - int nofork = 0; - struct sockaddr_un un; - - i_am_root = (getuid() == 0); - - while (-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:F:s:P:"))) { - switch(o) { - case 'f': fcgi_app = optarg; break; - case 'a': addr = optarg;/* ip addr */ break; - case 'p': port = strtol(optarg, NULL, 10);/* port */ break; - case 'C': child_count = strtol(optarg, NULL, 10);/* */ break; - case 'F': fork_count = strtol(optarg, NULL, 10);/* */ break; - case 's': unixsocket = optarg; /* unix-domain socket */ break; - case 'c': if (i_am_root) { changeroot = optarg; }/* chroot() */ break; - case 'u': if (i_am_root) { username = optarg; } /* set user */ break; - case 'g': if (i_am_root) { groupname = optarg; } /* set group */ break; - case 'n': nofork = 1; break; - case 'P': pid_file = optarg; /* PID file */ break; - case 'v': show_version(); return 0; - case 'h': show_help(); return 0; - default: - show_help(); - return -1; - } - } - - if (optind < argc) { - fcgi_app_argv = &argv[optind]; - } - - if ((fcgi_app == NULL && fcgi_app_argv == NULL) || (port == 0 && unixsocket == NULL)) { - show_help(); - return -1; - } - - if (unixsocket && port) { - fprintf(stderr, "%s.%d: %s\n", - __FILE__, __LINE__, - "either a unix domain socket or a tcp-port, but not both\n"); - - return -1; - } - - if (unixsocket && strlen(unixsocket) > sizeof(un.sun_path) - 1) { - fprintf(stderr, "%s.%d: %s\n", - __FILE__, __LINE__, - "path of the unix socket is too long\n"); - - return -1; - } - - /* UID handling */ - if (!i_am_root && (geteuid() == 0 || getegid() == 0)) { - /* we are setuid-root */ - - fprintf(stderr, "%s.%d: %s\n", - __FILE__, __LINE__, - "Are you nuts ? Don't apply a SUID bit to this binary\n"); - - return -1; - } - - if (pid_file && - (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)))) { - struct stat st; - if (errno != EEXIST) { - fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n", - __FILE__, __LINE__, - pid_file, strerror(errno)); - - return -1; - } - - /* ok, file exists */ - - if (0 != stat(pid_file, &st)) { - fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n", - __FILE__, __LINE__, - pid_file, strerror(errno)); - - return -1; - } - - /* is it a regular file ? */ - - if (!S_ISREG(st.st_mode)) { - fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n", - __FILE__, __LINE__, - pid_file); - - return -1; - } - - if (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { - fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n", - __FILE__, __LINE__, - pid_file, strerror(errno)); - - return -1; - } - } - - if (i_am_root) { - struct group *grp = NULL; - struct passwd *pwd = NULL; - - /* set user and group */ - - if (username) { - if (NULL == (pwd = getpwnam(username))) { - fprintf(stderr, "%s.%d: %s, %s\n", - __FILE__, __LINE__, - "can't find username", username); - return -1; - } - - if (pwd->pw_uid == 0) { - fprintf(stderr, "%s.%d: %s\n", - __FILE__, __LINE__, - "I will not set uid to 0\n"); - return -1; - } - } - - if (groupname) { - if (NULL == (grp = getgrnam(groupname))) { - fprintf(stderr, "%s.%d: %s %s\n", - __FILE__, __LINE__, - "can't find groupname", - groupname); - return -1; - } - if (grp->gr_gid == 0) { - fprintf(stderr, "%s.%d: %s\n", - __FILE__, __LINE__, - "I will not set gid to 0\n"); - return -1; - } - - /* do the change before we do the chroot() */ - setgid(grp->gr_gid); - setgroups(0, NULL); - - if (username) { - initgroups(username, grp->gr_gid); - } - - } - - if (changeroot) { - if (-1 == chroot(changeroot)) { - fprintf(stderr, "%s.%d: %s %s\n", - __FILE__, __LINE__, - "chroot failed: ", strerror(errno)); - return -1; - } - if (-1 == chdir("/")) { - fprintf(stderr, "%s.%d: %s %s\n", - __FILE__, __LINE__, - "chdir failed: ", strerror(errno)); - return -1; - } - } - - /* drop root privs */ - if (username) { - setuid(pwd->pw_uid); - } - } - - return fcgi_spawn_connection(fcgi_app, fcgi_app_argv, addr, port, unixsocket, fork_count, child_count, pid_fd, nofork); -} -#else -int main() { - return -1; -} -#endif diff --git a/tests/LightyTest.pm b/tests/LightyTest.pm index 8d814dec..84f246cf 100755 --- a/tests/LightyTest.pm +++ b/tests/LightyTest.pm @@ -6,7 +6,8 @@ use IO::Socket; use Test::More; use Socket; use Cwd 'abs_path'; -use POSIX ":sys_wait_h"; +use POSIX qw(:sys_wait_h dup2); +use Errno qw(EADDRINUSE); sub mtime { my $file = shift; @@ -344,8 +345,14 @@ sub spawnfcgi { return -1; } if ($child == 0) { - my $cmd = $self->{BINDIR}.'/spawn-fcgi -n -p '.$port.' -f "'.$binary.'"'; - exec $cmd or die($?); + my $iaddr = inet_aton('localhost') || die "no host: localhost"; + my $proto = getprotobyname('tcp'); + socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; + setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) || die "setsockopt: $!"; + bind(SOCK, sockaddr_in($port, $iaddr)) || die "bind: $!"; + listen(SOCK, 1024) || die "listen: $!"; + dup2(fileno(SOCK), 0) || die "dup2: $!"; + exec $binary or die($?); } else { if (0 != $self->wait_for_port_with_proc($port, $child)) { diag(sprintf('The process %i is not up (port %i, %s)', $child, $port, $binary));