int fcgi_listen(const char *path, int backlog) { char *s; int tcp = 0; char host[MAXPATHLEN]; short port = 0; int listen_socket; sa_t sa; socklen_t sock_len; #ifdef SO_REUSEADDR # ifdef _WIN32 BOOL reuse = 1; # else int reuse = 1; # endif #endif if ((s = strchr(path, ':'))) { port = atoi(s+1); if (port != 0 && (s-path) < MAXPATHLEN) { strncpy(host, path, s-path); host[s-path] = '\0'; tcp = 1; } } else if (is_port_number(path)) { port = atoi(path); if (port != 0) { host[0] = '\0'; tcp = 1; } } /* Prepare socket address */ if (tcp) { memset(&sa.sa_inet, 0, sizeof(sa.sa_inet)); sa.sa_inet.sin_family = AF_INET; sa.sa_inet.sin_port = htons(port); sock_len = sizeof(sa.sa_inet); if (!*host || !strncmp(host, "*", sizeof("*")-1)) { sa.sa_inet.sin_addr.s_addr = htonl(INADDR_ANY); } else { sa.sa_inet.sin_addr.s_addr = inet_addr(host); if (sa.sa_inet.sin_addr.s_addr == INADDR_NONE) { struct hostent *hep; hep = gethostbyname(host); if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) { fprintf(stderr, "Cannot resolve host name '%s'!\n", host); return -1; } else if (hep->h_addr_list[1]) { fprintf(stderr, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host); return -1; } sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr; } } } else { #ifdef _WIN32 SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES sa; PACL acl; HANDLE namedPipe; memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa); sa.bInheritHandle = FALSE; acl = prepare_named_pipe_acl(&sd, &sa); namedPipe = CreateNamedPipe(path, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_READMODE_BYTE, PIPE_UNLIMITED_INSTANCES, 8192, 8192, 0, &sa); if (namedPipe == INVALID_HANDLE_VALUE) { return -1; } listen_socket = _open_osfhandle((long)namedPipe, 0); if (!is_initialized) { fcgi_init(); } is_fastcgi = 1; return listen_socket; #else int path_len = strlen(path); if (path_len >= sizeof(sa.sa_unix.sun_path)) { fprintf(stderr, "Listening socket's path name is too long.\n"); return -1; } memset(&sa.sa_unix, 0, sizeof(sa.sa_unix)); sa.sa_unix.sun_family = AF_UNIX; memcpy(sa.sa_unix.sun_path, path, path_len + 1); sock_len = (size_t)(((struct sockaddr_un *)0)->sun_path) + path_len; #ifdef HAVE_SOCKADDR_UN_SUN_LEN sa.sa_unix.sun_len = sock_len; #endif unlink(path); #endif } /* Create, bind socket and start listen on it */ if ((listen_socket = socket(sa.sa.sa_family, SOCK_STREAM, 0)) < 0 || #ifdef SO_REUSEADDR setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) < 0 || #endif bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 || listen(listen_socket, backlog) < 0) { fprintf(stderr, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno)); return -1; } if (!tcp) { chmod(path, 0777); } else { char *ip = getenv("FCGI_WEB_SERVER_ADDRS"); char *cur, *end; int n; if (ip) { ip = strdup(ip); cur = ip; n = 0; while (*cur) { if (*cur == ',') n++; cur++; } allowed_clients = malloc(sizeof(in_addr_t) * (n+2)); n = 0; cur = ip; while (cur) { end = strchr(cur, ','); if (end) { *end = 0; end++; } allowed_clients[n] = inet_addr(cur); if (allowed_clients[n] == INADDR_NONE) { fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur); } n++; cur = end; } allowed_clients[n] = INADDR_NONE; free(ip); } } if (!is_initialized) { fcgi_init(); } is_fastcgi = 1; #ifdef _WIN32 if (tcp) { listen_socket = _open_osfhandle((long)listen_socket, 0); } #else fcgi_setup_signals(); #endif return listen_socket; }
int fcgi_listen(const char *path, int backlog) { #ifdef _WIN32 /* TODO: Support for manual binding on TCP sockets (php -b <port>) */ return -1; #else char *s; int tcp = 0; char host[MAXPATHLEN]; short port = 0; int listen_socket; sa_t sa; socklen_t sock_len; if ((s = strchr(path, ':'))) { port = atoi(s+1); if (port != 0 && (s-path) < MAXPATHLEN) { strncpy(host, path, s-path); host[s-path] = '\0'; tcp = 1; } } /* Prepare socket address */ if (tcp) { memset(&sa.sa_inet, 0, sizeof(sa.sa_inet)); sa.sa_inet.sin_family = AF_INET; sa.sa_inet.sin_port = htons(port); sock_len = sizeof(sa.sa_inet); if (!*host || !strncmp(host, "*", sizeof("*")-1)) { sa.sa_inet.sin_addr.s_addr = htonl(INADDR_ANY); } else { sa.sa_inet.sin_addr.s_addr = inet_addr(host); if (sa.sa_inet.sin_addr.s_addr == INADDR_NONE) { struct hostent *hep; hep = gethostbyname(host); if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) { fprintf(stderr, "Cannot resolve host name '%s'!\n", host); return -1; } else if (hep->h_addr_list[1]) { fprintf(stderr, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host); return -1; } sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr; } } } else { int path_len = strlen(path); if (path_len >= sizeof(sa.sa_unix.sun_path)) { fprintf(stderr, "Listening socket's path name is too long.\n"); return -1; } memset(&sa.sa_unix, 0, sizeof(sa.sa_unix)); sa.sa_unix.sun_family = AF_UNIX; memcpy(sa.sa_unix.sun_path, path, path_len + 1); sock_len = (size_t)(((struct sockaddr_un *)0)->sun_path) + path_len; #ifdef HAVE_SOCKADDR_UN_SUN_LEN sa.sa_unix.sun_len = sock_len; #endif unlink(path); } /* Create, bind socket and start listen on it */ if ((listen_socket = socket(sa.sa.sa_family, SOCK_STREAM, 0)) < 0 || bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 || listen(listen_socket, backlog) < 0) { fprintf(stderr, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno)); return -1; } if (!tcp) { chmod(path, 0777); } if (!is_initialized) { fcgi_init(); } is_fastcgi = 1; return listen_socket; #endif }