/* *---------------------------------------------------------------------- * * OS_FcgiConnect -- * * Create the socket and connect to the remote application if * possible. * * This was lifted from the cgi-fcgi application and was abstracted * out because Windows NT does not have a domain socket and must * use a named pipe which has a different API altogether. * * Results: * -1 if fail or a valid file descriptor if connection succeeds. * * Side effects: * Remote connection established. * *---------------------------------------------------------------------- */ int OS_FcgiConnect(char *bindPath) { union SockAddrUnion sa; int servLen, resultSock; int connectStatus; char *tp; char host[MAXPATHLEN]; short port = 0; int tcp = FALSE; strcpy(host, bindPath); if((tp = strchr(host, ':')) != 0) { *tp++ = 0; if((port = atoi(tp)) == 0) { *--tp = ':'; } else { tcp = TRUE; } } if(tcp == TRUE) { struct hostent *hp; if((hp = gethostbyname((*host ? host : "localhost"))) == NULL) { fprintf(stderr, "Unknown host: %s\n", bindPath); exit(1000); } sa.inetVariant.sin_family = AF_INET; memcpy(&sa.inetVariant.sin_addr, hp->h_addr, hp->h_length); sa.inetVariant.sin_port = htons(port); servLen = sizeof(sa.inetVariant); resultSock = socket(AF_INET, SOCK_STREAM, 0); } else { if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) { fprintf(stderr, "Listening socket's path name is too long.\n"); exit(1000); } resultSock = socket(AF_UNIX, SOCK_STREAM, 0); } ASSERT(resultSock >= 0); connectStatus = connect(resultSock, (struct sockaddr *) &sa.unixVariant, servLen); if(connectStatus >= 0) { return resultSock; } else { /* * Most likely (errno == ENOENT || errno == ECONNREFUSED) * and no FCGI application server is running. */ close(resultSock); return -1; } }
/* * OS_CreateLocalIpcFd -- * * This procedure is responsible for creating the listener socket * on Unix for local process communication. It will create a * domain socket or a TCP/IP socket bound to "localhost" and return * a file descriptor to it to the caller. * * Results: * Listener socket created. This call returns either a valid * file descriptor or -1 on error. * * Side effects: * None. * *---------------------------------------------------------------------- */ int OS_CreateLocalIpcFd(const char *bindPath, int backlog) { int listenSock, servLen; union SockAddrUnion sa; int tcp = FALSE; unsigned long tcp_ia = 0; char *tp; short port = 0; char host[MAXPATHLEN]; strcpy(host, bindPath); if((tp = strchr(host, ':')) != 0) { *tp++ = 0; if((port = atoi(tp)) == 0) { *--tp = ':'; } else { tcp = TRUE; } } if(tcp) { if (!*host || !strcmp(host,"*")) { tcp_ia = htonl(INADDR_ANY); } else { tcp_ia = inet_addr(host); if (tcp_ia == 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 -- exiting!\n", host); exit(1); } if (hep->h_addr_list[1]) { fprintf(stderr, "Host %s has multiple addresses ---\n", host); fprintf(stderr, "you must choose one explicitly!!!\n"); exit(1); } tcp_ia = ((struct in_addr *) (hep->h_addr))->s_addr; } } } if(tcp) { listenSock = socket(AF_INET, SOCK_STREAM, 0); if(listenSock >= 0) { int flag = 1; if(setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, sizeof(flag)) < 0) { fprintf(stderr, "Can't set SO_REUSEADDR.\n"); exit(1001); } } } else { listenSock = socket(AF_UNIX, SOCK_STREAM, 0); } if(listenSock < 0) { return -1; } /* * Bind the listening socket. */ if(tcp) { memset((char *) &sa.inetVariant, 0, sizeof(sa.inetVariant)); sa.inetVariant.sin_family = AF_INET; sa.inetVariant.sin_addr.s_addr = tcp_ia; sa.inetVariant.sin_port = htons(port); servLen = sizeof(sa.inetVariant); } else { unlink(bindPath); if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) { fprintf(stderr, "Listening socket's path name is too long.\n"); exit(1000); } } if(bind(listenSock, (struct sockaddr *) &sa.unixVariant, servLen) < 0 || listen(listenSock, backlog) < 0) { perror("bind/listen"); exit(errno); } return listenSock; }
/* * OS_CreateLocalIpcFd -- * * This procedure is responsible for creating the listener socket * on Unix for local process communication. It will create a * domain socket or a TCP/IP socket bound to "localhost" and return * a file descriptor to it to the caller. * * Results: * Listener socket created. This call returns either a valid * file descriptor or -1 on error. * * Side effects: * None. * *---------------------------------------------------------------------- */ int OS_CreateLocalIpcFd(const char *bindPath, int backlog) { int listenSock, servLen; union SockAddrUnion sa; int tcp = FALSE; char *tp; short port; char host[MAXPATHLEN]; strcpy(host, bindPath); if((tp = strchr(host, ':')) != 0) { *tp++ = 0; if((port = atoi(tp)) == 0) { *--tp = ':'; } else { tcp = TRUE; } } if(tcp && (*host && strcmp(host, "localhost") != 0)) { fprintf(stderr, "To start a service on a TCP port can not " "specify a host name.\n" "You should either use \"localhost:<port>\" or " " just use \":<port>.\"\n"); exit(1); } if(tcp) { listenSock = socket(AF_INET, SOCK_STREAM, 0); if(listenSock >= 0) { int flag = 1; if(setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, sizeof(flag)) < 0) { fprintf(stderr, "Can't set SO_REUSEADDR.\n"); exit(1001); } } } else { listenSock = socket(AF_UNIX, SOCK_STREAM, 0); } if(listenSock < 0) { return -1; } /* * Bind the listening socket. */ if(tcp) { memset((char *) &sa.inetVariant, 0, sizeof(sa.inetVariant)); sa.inetVariant.sin_family = AF_INET; sa.inetVariant.sin_addr.s_addr = htonl(INADDR_ANY); sa.inetVariant.sin_port = htons(port); servLen = sizeof(sa.inetVariant); } else { unlink(bindPath); if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) { fprintf(stderr, "Listening socket's path name is too long.\n"); exit(1000); } } if(bind(listenSock, (struct sockaddr *) &sa.unixVariant, servLen) < 0 || listen(listenSock, backlog) < 0) { perror("bind/listen"); exit(errno); } return listenSock; }