Sisyphus repositório
Última atualização: 1 outubro 2023 | SRPMs: 18631 | Visitas: 37583549
en ru br
ALT Linux repositórios
S:1.6.4-alt5

Group :: Sistema/Servidores
RPM: spawn-fcgi

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs e FR  Repocop 

pax_global_header00006660000000000000000000000064112564120420014507gustar00rootroot0000000000000052 comment=6e8bac8a22ab1a00d56dadc4faaf28bd906fe81f
spawn-fcgi-1.6.3/000075500000000000000000000000001125641204200135525ustar00rootroot00000000000000spawn-fcgi-1.6.3/AUTHORS000064400000000000000000000001061125641204200146170ustar00rootroot00000000000000jan kneschke <jan@kneschke.de>
stefan bühler <lighttpd@stbuehler.de>
spawn-fcgi-1.6.3/CMakeLists.txt000064400000000000000000000012651125641204200163160ustar00rootroot00000000000000CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR)

cmake_policy(VERSION 2.6.0)

PROJECT(spawn-fcgi)
SET(PACKAGE_NAME ${CMAKE_PROJECT_NAME})
SET(PACKAGE_VERSION 1.6.3)

SET(CMAKE_MAN_DIR "share/man" CACHE STRING
"Install location for man pages (relative to prefix).")
MARK_AS_ADVANCED(CMAKE_MAN_DIR)

# Set Default build type to RelWithDebInfo
IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." FORCE)
ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")

ADD_SUBDIRECTORY(src)

INSTALL(FILES spawn-fcgi.1 DESTINATION ${CMAKE_MAN_DIR}/man1)
spawn-fcgi-1.6.3/COPYING000064400000000000000000000027371125641204200146160ustar00rootroot00000000000000

Copyright (c) 2004, Jan Kneschke, incremental
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

- Neither the name of the 'incremental' nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.

spawn-fcgi-1.6.3/Makefile.am000064400000000000000000000001321125641204200156020ustar00rootroot00000000000000SUBDIRS=src doc

EXTRA_DIST=autogen.sh spawn-fcgi.1 CMakeLists.txt
man1_MANS=spawn-fcgi.1
spawn-fcgi-1.6.3/NEWS000064400000000000000000000032731125641204200142560ustar00rootroot00000000000000
====
NEWS
====

- 1.6.3 -
* Fix unix socket mode change to work without specifying user/group for socket
* Add some ./run script examples for use with daemontools or runit
* Fix Invalid Argument in chmod if mode=-1 (fixes 2033)
* Add deprecated and /bin/sh info for -f option; wrap syntax output (fixes #2044)
* Add run script examples in automake dist build

- 1.6.2 - 2009-04-18
* Add homepage to README
* Add IPv6 support
* Fix problems with usernames starting with a digit and non-existent uids; add warning if only user privs are dropped. (fixes #1959)
* Add check to link against socket/nsl if needed (fixes #1960)
* List IPv6 as feature after the version if it is supported

- 1.6.1 - 2009-03-29

* Add build date to show-version
* Added options to chown/chmod the socket and to create the socket before chroot() (fixes #1906)
* Updated man page
* Add proper SUID bit detection
* Added option to change the directory before spawning (fixes #1847)

- 1.6.0 - 2009-02-28

* Separated spawn-fcgi from lighttpd
* Remove limits for php children; per default the PHP_FCGI_CHILDREN var is not changed (php defaults to no children, one worker)
* Modified the log messages format (more details on errors, no source line)
* Only try to connect to unix socket (not tcp) before spawning (fixes again #1575)
* Only disconnect from terminal in fork mode (keep stderr/stdout open in nofork mode)
* Allow numerical user and group ids for -u/-g (fixes #1141)
* Ignore pid-file option in no-fork mode (instead of producing empty file)
* Fix error handling for unix-socket-connect test
* Man page update
* Use header include order from 1.4.x
* Fix segfault due to uninitialized var
spawn-fcgi-1.6.3/README000064400000000000000000000011611125641204200144310ustar00rootroot00000000000000
==========
spawn-fcgi
==========

:authors: Jan Kneschke, Stefan Bühler

:homepage:
http://redmine.lighttpd.net/projects/spawn-fcgi

:abstract:
spawn-fcgi is used to spawn FastCGI applications

Features
--------
- binds to IPv4/IPv6 and Unix domain sockets
- supports privilege separation: chmod/chown socket, drop to uid/gid
- supports chroot
- supports daemontools supervise

Build
=====

If ./configure is missing, run ./autogen.sh.

./configure
make
make install

Alternatively you can use the cmake build system (may not work
on every platform):

cmake .
make
make install


Usage
=====

See man page.
spawn-fcgi-1.6.3/autogen.sh000075500000000000000000000006711125641204200155570ustar00rootroot00000000000000#!/bin/sh
# Run this to generate all the initial makefiles, etc.

ACLOCAL=${ACLOCAL:-aclocal}
AUTOHEADER=${AUTOHEADER:-autoheader}
AUTOMAKE=${AUTOMAKE:-automake}
AUTOMAKE_FLAGS="--add-missing --copy"
AUTOCONF=${AUTOCONF:-autoconf}

ARGV0=$0

set -e


run() {
echo "$ARGV0: running \`$@'"
$@
}

run $ACLOCAL $ACLOCAL_FLAGS
run $AUTOHEADER
run $AUTOMAKE $AUTOMAKE_FLAGS
run $AUTOCONF
echo "Now type './configure ...' and 'make' to compile."
spawn-fcgi-1.6.3/configure.ac000064400000000000000000000051571125641204200160500ustar00rootroot00000000000000# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ(2.61)
AC_INIT([spawn-fcgi],[1.6.3])
AC_CONFIG_SRCDIR([src/spawn-fcgi.c])
AC_CONFIG_HEADER([config.h])

AM_INIT_AUTOMAKE([-Wall -Werror foreign])

# Checks for programs.
AC_PROG_CC
AC_PROG_MAKE_SET

# Checks for libraries.

# Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([arpa/inet.h errno.h fcntl.h getopt.h grp.h netdb.h \
netinet/in.h netinet/tcp.h pwd.h stdio.h stdlib.h \
string.h sys/ioctl.h sys/socket.h sys/stat.h sys/time.h \
sys/types.h sys/un.h sys/wait.h unistd.h])


# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_UID_T
AC_TYPE_PID_T
AC_HEADER_TIME
AC_CHECK_TYPES(socklen_t,,,[#include <sys/types.h>
#include <sys/socket.h>])

## solaris needs -lsocket -lnsl
AC_SEARCH_LIBS([socket],[socket])
AC_SEARCH_LIBS([inet_addr],[nsl socket])

# Checks for library functions.
AC_FUNC_CHOWN
AC_FUNC_FORK
AC_FUNC_MALLOC
AC_FUNC_SELECT_ARGTYPES
AC_FUNC_STAT
AC_CHECK_FUNCS([dup2 memset putenv select socket strerror strtol issetugid inet_pton])


# Check for IPv6 support

AC_ARG_ENABLE(ipv6,
AC_HELP_STRING([--disable-ipv6],[disable IPv6 support]),
[case "${enableval}" in
yes) ipv6=true ;;
no) ipv6=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ipv6) ;;
esac],[ipv6=true])

if test x$ipv6 = xtrue; then
AC_CACHE_CHECK([for IPv6 support], ac_cv_ipv6_support,
[AC_TRY_LINK([ #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>], [struct sockaddr_in6 s; struct in6_addr t=in6addr_any; int i=AF_INET6; s; t.s6_addr[0] = 0; ],
[ac_cv_ipv6_support=yes], [ac_cv_ipv6_support=no])])

if test "$ac_cv_ipv6_support" = yes; then
AC_DEFINE(HAVE_IPV6,1,[Whether to enable IPv6 support])
fi
fi


# check for extra compiler options (warning options)
if test "${GCC}" = "yes"; then
CFLAGS="${CFLAGS} -Wall -W -Wshadow -pedantic -std=gnu99"
fi

AC_ARG_ENABLE(extra-warnings,
AC_HELP_STRING([--enable-extra-warnings],[enable extra warnings (gcc specific)]),
[case "${enableval}" in
yes) extrawarnings=true ;;
no) extrawarnings=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-extra-warnings) ;;
esac],[extrawarnings=false])

if test x$extrawarnings = xtrue; then
CFLAGS="${CFLAGS} -g -O2 -g2 -Wall -Wmissing-declarations -Wdeclaration-after-statement -Wcast-align -Winline -Wsign-compare -Wnested-externs -Wpointer-arith -Wl,--as-needed -Wformat-security"
fi

AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile])
AC_OUTPUT
spawn-fcgi-1.6.3/doc/000075500000000000000000000000001125641204200143175ustar00rootroot00000000000000spawn-fcgi-1.6.3/doc/Makefile.am000064400000000000000000000000511125641204200163470ustar00rootroot00000000000000EXTRA_DIST=run-generic run-php run-rails
spawn-fcgi-1.6.3/doc/run-generic000064400000000000000000000020651125641204200164630ustar00rootroot00000000000000#!/bin/bash
# Use this as a run script with daemontools or runit

## ABSOLUTE path to the spawn-fcgi binary
SPAWNFCGI="/usr/bin/spawn-fcgi"

## ABSOLUTE path to the FastCGI application (php-cgi, dispatch.fcgi, ...)
FCGIPROGRAM="/usr/bin/php5-cgi"

## bind to unix socket
FCGISOCKET="/var/run/lighttpd/your-fcgi-app.sock"

# allowed environment variables separated by spaces
ALLOWED_ENV="PATH USER"

## if this script is run as root switch to the following user
USERID=xxx
SOCKUSERID=www-data
#CHROOT=/home/www/

#RAILS_ENV="production"
#export RAILS_ENV


################## no config below this line

exec 2>&1

if test x$PHP_FCGI_CHILDREN = x; then
PHP_FCGI_CHILDREN=4
fi

ALLOWED_ENV="$ALLOWED_ENV RAILS_ENV"

if test x$UID = x0; then
EX="$SPAWNFCGI -n -s $FCGISOCKET -u $USERID -U $SOCKUSERID -C $PHP_FCGI_CHILDREN -- $FCGIPROGRAM"
else
EX="$SPAWNFCGI -n -s $FCGISOCKET -C $PHP_FCGI_CHILDREN -- $FCGIPROGRAM"
fi

# copy the allowed environment variables
E=

for i in $ALLOWED_ENV; do
E="$E $i=${!i}"
done

# clean environment and set up a new one
exec env - $E $EX
spawn-fcgi-1.6.3/doc/run-php000064400000000000000000000005221125641204200156320ustar00rootroot00000000000000#!/bin/sh
# Use this as a ./run script with daemontools or runit
# You should replace xxx with the user you want php to run as (and www-data with the user lighty runs as)

exec 2>&1
PHP_FCGI_CHILDREN=2 \
PHP_FCGI_MAX_REQUESTS=1000 \
exec /usr/bin/spawn-fcgi -n -s /var/run/lighttpd/php-xxx.sock -n -u xxx -U www-data -- /usr/bin/php5-cgi
spawn-fcgi-1.6.3/doc/run-rails000064400000000000000000000006141125641204200161570ustar00rootroot00000000000000#!/bin/sh
# Use this as a ./run script with daemontools or runit
# You should replace xxx with the user you want rails to run as (and www-data with the user lighty runs as)
# /path-to-rails should be replaced with the correct path too :)

exec 2>&1
RAILS_ENV="production" \
exec /usr/bin/spawn-fcgi -n -s /var/run/lighttpd/rails-xxx.sock -u xxx -U www-data -- /path-to-rails/public/dispatch.fcgi
spawn-fcgi-1.6.3/spawn-fcgi.1000064400000000000000000000065571125641204200157070ustar00rootroot00000000000000.TH spawn-fcgi 1 "26 March 2009"
.
.SH NAME
.
spawn-fcgi \- Spawns FastCGI processes
.
.SH SYNOPSIS
.
.B spawn-fcgi
[options] [ -- <fcgiapp> [fcgi app arguments]]
.P
.B spawn-fcgi
\-v
.P
.B spawn-fcgi
\-h
.
.SH DESCRIPTION
.
\fIspawn-fcgi\fP is used to spawn remote and local FastCGI processes.
.P
While it is obviously needed to spawn remote FastCGI backends (the web server
can only spawn local ones), it is recommended to spawn local backends
with spawn-fcgi, too.
.P
Reasons why you may want to use spawn-fcgi instead of something else:
.IP * 3
Privilege separation without needing a suid-binary or running a server as root.
.IP * 3
You can restart your web server and the FastCGI applications without restarting the others.
.IP * 3
You can run them in different chroot()s.
.IP * 3
Running your FastCGI applications doesn't depend on the web server you are running,
which allows for easier testing of other web servers.
.
.SH OPTIONS
.
\fIspawn-fcgi\fP accepts the following options:
.TP 8
.B \-f <path>
Filename of the FastCGI application to spawn. This option is deprecated and it
is recommend to always specify the application (absolute path) and its parameters after "--";
the fcgiapp parameter is directly used for the exec() call, while for starting the binary given
with \-f /bin/sh is needed (which may not be available in a chroot).
.IP
This option is ignored if fcgiapp is given.
.TP 8
.B \-d <path>
Change the current directory before spawning the application.
.TP 8
.B \-a <address>
IPv4/IPv6 address to bind to; only used if \-p is given too. Defaults to "0.0.0.0" (IPv4).
.TP 8
.B \-p <port>
TCP port to bind to; you cannot combine this with the \-s option.
.TP 8
.B \-s <path>
Path to the Unix domain socket to bind to; you cannot combine this with the \-p option.
.TP 8
.B \-C <children>
(PHP only) Number of children to spawn by setting the PHP_FCGI_CHILDREN
environment variable. Default is not to overwrite the environment variable;
php will spawn no children if the variable is not set (same as setting it to 0).
.TP 8
.B \-F <children>
Number of children to fork, defaults to 1. This option doesn't work with \-n,
have a look at
.BR multiwatch(1)
if you want to supervise multiple forks on the same socket.
.TP 8
.B \-P <path>
Name of the PID file for spawned processes (ignored in no-fork mode)
.TP 8
.B \-n
No forking should take place (for daemontools)
.TP 8
.B \-M <mode>
Change file mode of the Unix domain socket; only used if \-s is given too.
.TP 8
.B \-?, \-h
General usage instructions
.TP 8
.B \-v
Shows version information and exits
.P
.
The following options are only available if you invoke spawn-fcgi as root:
.TP 8
.B \-c <directory>
Chroot to specified directory; the Unix domain socket is created inside the chroot unless \-S is given.
.TP 8
.B \-S
Create Unix domain socket before chroot().
.TP 8
.B \-u
User ID to change to.
.TP 8
.B \-g
Group ID to change to. Defaults to primary group of the user given for \-u.
.TP 8
.B \-U
Change user of the Unix domain socket, defaults to the value of \-u. (only used if \-s is given)
.TP 8
.B \-G
Change group of the Unix domain socket, defaults to the primary group of the user given for \-U;
if \-U wasn't given, defaults to the value of \-g. (only used if \-s is given)
.
.SH "SEE ALSO"
.
.BR svc(8),
.BR supervise(8),
see http://cr.yp.to/daemontools.html
.P
.BR multiwatch(1),
see http://cgit.stbuehler.de/gitosis/multiwatch/about/
spawn-fcgi-1.6.3/src/000075500000000000000000000000001125641204200143415ustar00rootroot00000000000000spawn-fcgi-1.6.3/src/CMakeLists.txt000064400000000000000000000053221125641204200171030ustar00rootroot00000000000000INCLUDE(CheckCSourceCompiles)
INCLUDE(CheckIncludeFiles)
INCLUDE(CheckFunctionExists)
INCLUDE(CheckVariableExists)
INCLUDE(CheckTypeSize)
INCLUDE(CMakeDetermineCCompiler)

IF(CMAKE_COMPILER_IS_GNUCC)
OPTION(BUILD_EXTRA_WARNINGS "extra warnings")

IF(BUILD_EXTRA_WARNINGS)
SET(WARN_FLAGS "-g -O2 -g2 -Wall -Wmissing-declarations -Wdeclaration-after-statement -Wcast-align -Winline -Wsign-compare -Wnested-externs -Wpointer-arith -Wl,--as-needed -Wformat-security")
# -Wno-pointer-sign -Werror -Wbad-function-cast -Wmissing-prototypes
ELSE(BUILD_EXTRA_WARNINGS)
SET(WARN_FLAGS "")
ENDIF(BUILD_EXTRA_WARNINGS)
ENDIF(CMAKE_COMPILER_IS_GNUCC)

# awk '/#include <(.*)>/ { h = substr($2,2,length($2)-2); h2=toupper(h); gsub("\\.|\\/", "_", h2); printf "%s%s%s%s%s", "CHECK_INCLUDE_FILES(", h, " HAVE_", h2, ")\n" }' spawn-fcgi.c | sort
CHECK_INCLUDE_FILES(arpa/inet.h HAVE_ARPA_INET_H)
CHECK_INCLUDE_FILES(errno.h HAVE_ERRNO_H)
CHECK_INCLUDE_FILES(fcntl.h HAVE_FCNTL_H)
CHECK_INCLUDE_FILES(getopt.h HAVE_GETOPT_H)
CHECK_INCLUDE_FILES(grp.h HAVE_GRP_H)
CHECK_INCLUDE_FILES(netdb.h HAVE_NETDB_H)
CHECK_INCLUDE_FILES(netinet/in.h HAVE_NETINET_IN_H)
CHECK_INCLUDE_FILES(netinet/tcp.h HAVE_NETINET_TCP_H)
CHECK_INCLUDE_FILES(pwd.h HAVE_PWD_H)
CHECK_INCLUDE_FILES(stdio.h HAVE_STDIO_H)
CHECK_INCLUDE_FILES(stdlib.h HAVE_STDLIB_H)
CHECK_INCLUDE_FILES(string.h HAVE_STRING_H)
CHECK_INCLUDE_FILES(sys/ioctl.h HAVE_SYS_IOCTL_H)
CHECK_INCLUDE_FILES(sys/socket.h HAVE_SYS_SOCKET_H)
CHECK_INCLUDE_FILES(sys/stat.h HAVE_SYS_STAT_H)
CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H)
CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H)
CHECK_INCLUDE_FILES(sys/un.h HAVE_SYS_UN_H)
CHECK_INCLUDE_FILES(sys/wait.h HAVE_SYS_WAIT_H)
CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H)
CHECK_INCLUDE_FILES(winsock2.h HAVE_WINSOCK2_H)

CHECK_FUNCTION_EXISTS(issetugid HAVE_ISSETUGID)
CHECK_FUNCTION_EXISTS(inet_pton HAVE_INET_PTON)

CHECK_C_SOURCE_COMPILES("
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
struct sockaddr_in6 s; struct in6_addr t=in6addr_any; int i=AF_INET6; s; t.s6_addr[0] = 0;
return 0;
}" HAVE_IPV6)

SET(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h)
CHECK_TYPE_SIZE(socklen_t HAVE_SOCKLEN_T)
SET(CMAKE_EXTRA_INCLUDE_FILES)

## Write out config.h
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)

ADD_DEFINITIONS(-DHAVE_CONFIG_H)

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})

ADD_EXECUTABLE(spawn-fcgi spawn-fcgi.c)

IF(CMAKE_COMPILER_IS_GNUCC)
SET_TARGET_PROPERTIES(spawn-fcgi PROPERTIES COMPILE_FLAGS "-std=gnu99 -Wall -g -Wshadow -W -pedantic -fPIC -D_GNU_SOURCE ${WARN_FLAGS}")
ENDIF(CMAKE_COMPILER_IS_GNUCC)

INSTALL(TARGETS spawn-fcgi DESTINATION bin)
spawn-fcgi-1.6.3/src/Makefile.am000064400000000000000000000001431125641204200163730ustar00rootroot00000000000000
bin_PROGRAMS=spawn-fcgi
spawn_fcgi_SOURCES=spawn-fcgi.c

EXTRA_DIST=CMakeLists.txt config.h.cmake
spawn-fcgi-1.6.3/src/config.h.cmake000064400000000000000000000016731125641204200170450ustar00rootroot00000000000000
/* generated by cmake, do not modify. modify config.h.cmake instead */

/* Package data */

#define PACKAGE_NAME "${PACKAGE_NAME}"
#define PACKAGE_VERSION "${PACKAGE_VERSION}"

/* grep HAVE_ CMakeLists.txt | sed -e 's/.*\(HAVE_[A-Z_]*\).*/#cmakedefine \1/' */

#cmakedefine HAVE_ARPA_INET_H
#cmakedefine HAVE_ERRNO_H
#cmakedefine HAVE_FCNTL_H
#cmakedefine HAVE_GETOPT_H
#cmakedefine HAVE_GRP_H
#cmakedefine HAVE_NETDB_H
#cmakedefine HAVE_NETINET_IN_H
#cmakedefine HAVE_NETINET_TCP_H
#cmakedefine HAVE_PWD_H
#cmakedefine HAVE_STDIO_H
#cmakedefine HAVE_STDLIB_H
#cmakedefine HAVE_STRING_H
#cmakedefine HAVE_SYS_IOCTL_H
#cmakedefine HAVE_SYS_SOCKET_H
#cmakedefine HAVE_SYS_STAT_H
#cmakedefine HAVE_SYS_TIME_H
#cmakedefine HAVE_SYS_TYPES_H
#cmakedefine HAVE_SYS_UN_H
#cmakedefine HAVE_SYS_WAIT_H
#cmakedefine HAVE_UNISTD_H
#cmakedefine HAVE_WINSOCK
#cmakedefine HAVE_SOCKLEN_T

#cmakedefine HAVE_ISSETUGID
#cmakedefine HAVE_INET_PTON

#cmakedefine HAVE_IPV6
spawn-fcgi-1.6.3/src/spawn-fcgi.c000064400000000000000000000401731125641204200165500ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

#ifdef HAVE_PWD_H
# include <grp.h>
# include <pwd.h>
#endif

#ifdef HAVE_GETOPT_H
# include <getopt.h>
#endif

#define FCGI_LISTENSOCK_FILENO 0

/* "sys-socket.h" */
#ifdef __WIN32

# include <winsock2.h>

# define ECONNRESET WSAECONNRESET
# define EINPROGRESS WSAEINPROGRESS
# define EALREADY WSAEALREADY
# define ECONNABORTED WSAECONNABORTED
# define ioctl ioctlsocket
# define hstrerror(x) ""

#else /* _WIN32 */

# include <sys/socket.h>
# include <sys/ioctl.h>
# include <netinet/in.h>
# include <netinet/tcp.h>
# include <sys/un.h>
# include <arpa/inet.h>

# include <netdb.h>

#endif /* _WIN32 */
/* end "sys-socket.h" */

#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif

/* for solaris 2.5 and netbsd 1.3.x */
#ifndef HAVE_SOCKLEN_T
typedef int socklen_t;
#endif

#ifndef HAVE_ISSETUGID
static int issetugid() {
return (geteuid() != getuid() || getegid() != getgid());
}
#endif

#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON)
# define USE_IPV6
#endif

#ifdef USE_IPV6
#define PACKAGE_FEATURES " (ipv6)"
#else
#define PACKAGE_FEATURES ""
#endif

#define PACKAGE_DESC "spawn-fcgi v" PACKAGE_VERSION PACKAGE_FEATURES " - spawns FastCGI processes\n"

#define CONST_STR_LEN(s) s, sizeof(s) - 1

static int bind_socket(const char *addr, unsigned short port, const char *unixsocket, uid_t uid, gid_t gid, int mode) {
int fcgi_fd, socket_type, val;

struct sockaddr_un fcgi_addr_un;
struct sockaddr_in fcgi_addr_in;
#ifdef USE_IPV6
struct sockaddr_in6 fcgi_addr_in6;
#endif
struct sockaddr *fcgi_addr;

socklen_t servlen;

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;

/* check if some backend is listening on the socket
* as if we delete the socket-file and rebind there will be no "socket already in use" error
*/
if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
fprintf(stderr, "spawn-fcgi: couldn't create socket: %s\n", strerror(errno));
return -1;
}

if (0 == connect(fcgi_fd, fcgi_addr, servlen)) {
fprintf(stderr, "spawn-fcgi: socket is already in use, can't spawn\n");
close(fcgi_fd);
return -1;
}

/* cleanup previous socket if it exists */
if (-1 == unlink(unixsocket)) {
switch (errno) {
case ENOENT:
break;
default:
fprintf(stderr, "spawn-fcgi: removing old socket failed: %s\n", strerror(errno));
return -1;
}
}

close(fcgi_fd);
} else {
memset(&fcgi_addr_in, 0, sizeof(fcgi_addr_in));
fcgi_addr_in.sin_family = AF_INET;
fcgi_addr_in.sin_port = htons(port);

servlen = sizeof(fcgi_addr_in);
socket_type = AF_INET;
fcgi_addr = (struct sockaddr *) &fcgi_addr_in;

#ifdef USE_IPV6
memset(&fcgi_addr_in6, 0, sizeof(fcgi_addr_in6));
fcgi_addr_in6.sin6_family = AF_INET6;
fcgi_addr_in6.sin6_port = fcgi_addr_in.sin_port;
#endif

if (addr == NULL) {
fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
#ifdef HAVE_INET_PTON
} else if (1 == inet_pton(AF_INET, addr, &fcgi_addr_in.sin_addr)) {
/* nothing to do */
#ifdef HAVE_IPV6
} else if (1 == inet_pton(AF_INET6, addr, &fcgi_addr_in6.sin6_addr)) {
servlen = sizeof(fcgi_addr_in6);
socket_type = AF_INET6;
fcgi_addr = (struct sockaddr *) &fcgi_addr_in6;
#endif
} else {
fprintf(stderr, "spawn-fcgi: '%s' is not a valid IP address\n", addr);
return -1;
#else
} else {
if ((in_addr_t)(-1) == (fcgi_addr_in.sin_addr.s_addr = inet_addr(addr))) {
fprintf(stderr, "spawn-fcgi: '%s' is not a valid IPv4 address\n", addr);
return -1;
}
#endif
}
}


if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
fprintf(stderr, "spawn-fcgi: couldn't create socket: %s\n", strerror(errno));
return -1;
}

val = 1;
if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
fprintf(stderr, "spawn-fcgi: couldn't set SO_REUSEADDR: %s\n", strerror(errno));
return -1;
}

if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
fprintf(stderr, "spawn-fcgi: bind failed: %s\n", strerror(errno));
return -1;
}

if (unixsocket) {
if (0 != uid || 0 != gid) {
if (0 == uid) uid = -1;
if (0 == gid) gid = -1;
if (-1 == chown(unixsocket, uid, gid)) {
fprintf(stderr, "spawn-fcgi: couldn't chown socket: %s\n", strerror(errno));
close(fcgi_fd);
unlink(unixsocket);
return -1;
}
}

if (-1 != mode && -1 == chmod(unixsocket, mode)) {
fprintf(stderr, "spawn-fcgi: couldn't chmod socket: %s\n", strerror(errno));
close(fcgi_fd);
unlink(unixsocket);
return -1;
}
}

if (-1 == listen(fcgi_fd, 1024)) {
fprintf(stderr, "spawn-fcgi: listen failed: %s\n", strerror(errno));
return -1;
}

return fcgi_fd;
}

static int fcgi_spawn_connection(char *appPath, char **appArgv, int fcgi_fd, int fork_count, int child_count, int pid_fd, int nofork) {
int status, rc = 0;
struct timeval tv = { 0, 100 * 1000 };

pid_t child;

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;

if (child_count >= 0) {
snprintf(cgi_childs, sizeof(cgi_childs), "PHP_FCGI_CHILDREN=%d", child_count);
putenv(cgi_childs);
}

if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
close(FCGI_LISTENSOCK_FILENO);
dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
close(fcgi_fd);
}

/* loose control terminal */
if (!nofork) {
setsid();

max_fd = open("/dev/null", O_RDWR);
if (-1 != max_fd) {
if (max_fd != STDOUT_FILENO) dup2(max_fd, STDOUT_FILENO);
if (max_fd != STDERR_FILENO) dup2(max_fd, STDERR_FILENO);
if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO) close(max_fd);
} else {
fprintf(stderr, "spawn-fcgi: couldn't open and redirect stdout/stderr to '/dev/null': %s\n", strerror(errno));
}
}

/* we don't need the client socket */
for (i = 3; i < max_fd; i++) {
if (i != FCGI_LISTENSOCK_FILENO) close(i);
}

/* fork and replace shell */
if (appArgv) {
execv(appArgv[0], appArgv);

} else {
char *b = malloc((sizeof("exec ") - 1) + strlen(appPath) + 1);
strcpy(b, "exec ");
strcat(b, appPath);

/* exec the cgi */
execl("/bin/sh", "sh", "-c", b, (char *)NULL);
}

/* in nofork mode stderr is still open */
fprintf(stderr, "spawn-fcgi: exec failed: %s\n", strerror(errno));
exit(errno);

break;
}
case -1:
/* error */
fprintf(stderr, "spawn-fcgi: fork failed: %s\n", strerror(errno));
break;
default:
/* father */

/* wait */
select(0, NULL, NULL, NULL, &tv);

switch (waitpid(child, &status, WNOHANG)) {
case 0:
fprintf(stdout, "spawn-fcgi: child spawned successfully: PID: %d\n", 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, "spawn-fcgi: child exited with: %d\n",
WEXITSTATUS(status));
rc = WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) {
fprintf(stderr, "spawn-fcgi: child signaled: %d\n",
WTERMSIG(status));
rc = 1;
} else {
fprintf(stderr, "spawn-fcgi: child died somehow: exit status = %d\n",
status);
rc = status;
}
}

break;
}
}
close(pid_fd);

close(fcgi_fd);

return rc;
}

static int find_user_group(const char *user, const char *group, uid_t *uid, gid_t *gid, const char **username) {
uid_t my_uid = 0;
gid_t my_gid = 0;
struct passwd *my_pwd = NULL;
struct group *my_grp = NULL;
char *endptr = NULL;
*uid = 0; *gid = 0;
if (username) *username = NULL;

if (user) {
my_uid = strtol(user, &endptr, 10);

if (my_uid <= 0 || *endptr) {
if (NULL == (my_pwd = getpwnam(user))) {
fprintf(stderr, "spawn-fcgi: can't find user name %s\n", user);
return -1;
}
my_uid = my_pwd->pw_uid;

if (my_uid == 0) {
fprintf(stderr, "spawn-fcgi: I will not set uid to 0\n");
return -1;
}

if (username) *username = user;
} else {
my_pwd = getpwuid(my_uid);
if (username && my_pwd) *username = my_pwd->pw_name;
}
}

if (group) {
my_gid = strtol(group, &endptr, 10);

if (my_gid <= 0 || *endptr) {
if (NULL == (my_grp = getgrnam(group))) {
fprintf(stderr, "spawn-fcgi: can't find group name %s\n", group);
return -1;
}
my_gid = my_grp->gr_gid;

if (my_gid == 0) {
fprintf(stderr, "spawn-fcgi: I will not set gid to 0\n");
return -1;
}
}
} else if (my_pwd) {
my_gid = my_pwd->pw_gid;

if (my_gid == 0) {
fprintf(stderr, "spawn-fcgi: I will not set gid to 0\n");
return -1;
}
}

*uid = my_uid;
*gid = my_gid;
return 0;
}

static void show_version () {
write(1, CONST_STR_LEN(
PACKAGE_DESC \
"Build-Date: " __DATE__ " " __TIME__ "\n"
));
}

static void show_help () {
write(1, CONST_STR_LEN(
"Usage: spawn-fcgi [options] [-- <fcgiapp> [fcgi app arguments]]\n" \
"\n" \
PACKAGE_DESC \
"\n" \
"Options:\n" \
" -f <path> filename of the fcgi-application (deprecated; ignored if\n" \
" <fcgiapp> is given; needs /bin/sh)\n" \
" -d <directory> chdir to directory before spawning\n" \
" -a <address> bind to IPv4/IPv6 address (defaults to 0.0.0.0)\n" \
" -p <port> bind to TCP-port\n" \
" -s <path> bind to Unix domain socket\n" \
" -M <mode> change Unix domain socket mode\n" \
" -C <children> (PHP only) numbers of childs to spawn (default: not setting\n" \
" the PHP_FCGI_CHILDREN environment variable - PHP defaults to 0)\n" \
" -F <children> number of children to fork (default 1)\n" \
" -P <path> name of PID-file for spawned process (ignored in no-fork mode)\n" \
" -n no fork (for daemontools)\n" \
" -v show version\n" \
" -?, -h show this help\n" \
"(root only)\n" \
" -c <directory> chroot to directory\n" \
" -S create socket before chroot() (default is to create the socket\n" \
" in the chroot)\n" \
" -u <user> change to user-id\n" \
" -g <group> change to group-id (default: primary group of user if -u\n" \
" is given)\n" \
" -U <user> change Unix domain socket owner to user-id\n" \
" -G <group> change Unix domain socket group to group-id\n" \
));
}


int main(int argc, char **argv) {
char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
*groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
*sockusername = NULL, *sockgroupname = NULL, *fcgi_dir = NULL,
*addr = NULL;
char **fcgi_app_argv = { NULL };
char *endptr = NULL;
unsigned short port = 0;
int sockmode = -1;
int child_count = -1;
int fork_count = 1;
int i_am_root, o;
int pid_fd = -1;
int nofork = 0;
int sockbeforechroot = 0;
struct sockaddr_un un;
int fcgi_fd = -1;

if (argc < 2) { /* no arguments given */
show_help();
return -1;
}

i_am_root = (getuid() == 0);

while (-1 != (o = getopt(argc, argv, "c:d:f:g:?hna:p:u:vC:F:s:P:U:G:M:S"))) {
switch(o) {
case 'f': fcgi_app = optarg; break;
case 'd': fcgi_dir = optarg; break;
case 'a': addr = optarg;/* ip addr */ break;
case 'p': port = strtol(optarg, &endptr, 10);/* port */
if (*endptr) {
fprintf(stderr, "spawn-fcgi: invalid port: %u\n", (unsigned int) port);
return -1;
}
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 'U': if (i_am_root) { sockusername = optarg; } /* set socket user */ break;
case 'G': if (i_am_root) { sockgroupname = optarg; } /* set socket group */ break;
case 'S': if (i_am_root) { sockbeforechroot = 1; } /* open socket before chroot() */ break;
case 'M': sockmode = strtol(optarg, NULL, 0); /* set socket mode */ break;
case 'n': nofork = 1; break;
case 'P': pid_file = optarg; /* PID file */ break;
case 'v': show_version(); return 0;
case '?':
case 'h': show_help(); return 0;
default:
show_help();
return -1;
}
}

if (optind < argc) {
fcgi_app_argv = &argv[optind];
}

if (NULL == fcgi_app && NULL == fcgi_app_argv) {
fprintf(stderr, "spawn-fcgi: no FastCGI application given\n");
return -1;
}

if (0 == port && NULL == unixsocket) {
fprintf(stderr, "spawn-fcgi: no socket given (use either -p or -s)\n");
return -1;
} else if (0 != port && NULL != unixsocket) {
fprintf(stderr, "spawn-fcgi: 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, "spawn-fcgi: path of the Unix domain socket is too long\n");
return -1;
}

/* SUID handling */
if (!i_am_root && issetugid()) {
fprintf(stderr, "spawn-fcgi: Are you nuts? Don't apply a SUID bit to this binary\n");
return -1;
}

if (nofork) pid_file = NULL; /* ignore pid file in no-fork mode */

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, "spawn-fcgi: opening PID-file '%s' failed: %s\n",
pid_file, strerror(errno));
return -1;
}

/* ok, file exists */

if (0 != stat(pid_file, &st)) {
fprintf(stderr, "spawn-fcgi: stating PID-file '%s' failed: %s\n",
pid_file, strerror(errno));
return -1;
}

/* is it a regular file ? */

if (!S_ISREG(st.st_mode)) {
fprintf(stderr, "spawn-fcgi: PID-file exists and isn't regular file: '%s'\n",
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, "spawn-fcgi: opening PID-file '%s' failed: %s\n",
pid_file, strerror(errno));
return -1;
}
}

if (i_am_root) {
uid_t uid, sockuid;
gid_t gid, sockgid;
const char* real_username;

if (-1 == find_user_group(username, groupname, &uid, &gid, &real_username))
return -1;

if (-1 == find_user_group(sockusername, sockgroupname, &sockuid, &sockgid, NULL))
return -1;

if (uid != 0 && gid == 0) {
fprintf(stderr, "spawn-fcgi: WARNING: couldn't find the user for uid %i and no group was specified, so only the user privileges will be dropped\n", (int) uid);
}

if (0 == sockuid) sockuid = uid;
if (0 == sockgid) sockgid = gid;

if (sockbeforechroot && -1 == (fcgi_fd = bind_socket(addr, port, unixsocket, sockuid, sockgid, sockmode)))
return -1;

/* Change group before chroot, when we have access
* to /etc/group
*/
if (gid != 0) {
setgid(gid);
setgroups(0, NULL);
if (real_username) {
initgroups(real_username, gid);
}
}

if (changeroot) {
if (-1 == chroot(changeroot)) {
fprintf(stderr, "spawn-fcgi: chroot('%s') failed: %s\n", changeroot, strerror(errno));
return -1;
}
if (-1 == chdir("/")) {
fprintf(stderr, "spawn-fcgi: chdir('/') failed: %s\n", strerror(errno));
return -1;
}
}

if (!sockbeforechroot && -1 == (fcgi_fd = bind_socket(addr, port, unixsocket, sockuid, sockgid, sockmode)))
return -1;

/* drop root privs */
if (uid != 0) {
setuid(uid);
}
} else {
if (-1 == (fcgi_fd = bind_socket(addr, port, unixsocket, 0, 0, sockmode)))
return -1;
}

if (fcgi_dir && -1 == chdir(fcgi_dir)) {
fprintf(stderr, "spawn-fcgi: chdir('%s') failed: %s\n", fcgi_dir, strerror(errno));
return -1;
}

return fcgi_spawn_connection(fcgi_app, fcgi_app_argv, fcgi_fd, fork_count, child_count, pid_fd, nofork);
}
 
projeto & código: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
mantenedor atual: Michael Shigorin
mantenedor da tradução: Fernando Martini aka fmartini © 2009