⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_unix.c

📁 FastCGI,语言无关的、可伸缩架构的CGI开放扩展
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * os_unix.c -- * *      Description of file. * * *  Copyright (c) 1995 Open Market, Inc. *  All rights reserved. * *  This file contains proprietary and confidential information and *  remains the unpublished property of Open Market, Inc. Use, *  disclosure, or reproduction is prohibited except as permitted by *  express written license agreement with Open Market, Inc. * *  Bill Snapper *  snapper@openmarket.com */#ifndef lintstatic const char rcsid[] = "$Id: os_unix.c,v 1.37 2002/03/05 19:14:49 robs Exp $";#endif /* not lint */#include "fcgi_config.h"#include <sys/types.h>#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif#include <arpa/inet.h>#include <assert.h>#include <errno.h>#include <fcntl.h>      /* for fcntl */#include <math.h>#include <memory.h>     /* for memchr() */#include <netinet/tcp.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/time.h>#include <sys/un.h>#include <signal.h>#ifdef HAVE_NETDB_H#include <netdb.h>#endif#ifdef HAVE_SYS_SOCKET_H#include <sys/socket.h> /* for getpeername */#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "fastcgi.h"#include "fcgimisc.h"#include "fcgios.h"#ifndef INADDR_NONE#define INADDR_NONE ((unsigned long) -1)#endif/* * This structure holds an entry for each oustanding async I/O operation. */typedef struct {    OS_AsyncProc procPtr;	    /* callout completion procedure */    ClientData clientData;	    /* caller private data */    int fd;    int len;    int offset;    void *buf;    int inUse;} AioInfo;/* * Entries in the async I/O table are allocated 2 per file descriptor. * * Read Entry Index  = fd * 2 * Write Entry Index = (fd * 2) + 1 */#define AIO_RD_IX(fd) (fd * 2)#define AIO_WR_IX(fd) ((fd * 2) + 1)static int asyncIoInUse = FALSE;static int asyncIoTableSize = 16;static AioInfo *asyncIoTable = NULL;static int libInitialized = FALSE;static fd_set readFdSet;static fd_set writeFdSet;static fd_set readFdSetPost;static int numRdPosted = 0;static fd_set writeFdSetPost;static int numWrPosted = 0;static int volatile maxFd = -1;static int shutdownPending = FALSE;static int shutdownNow = FALSE;void OS_ShutdownPending(){    shutdownPending = TRUE;}static void OS_Sigusr1Handler(int signo){    OS_ShutdownPending();}static void OS_SigpipeHandler(int signo){    ;}static void installSignalHandler(int signo, const struct sigaction * act, int force){    struct sigaction sa;    sigaction(signo, NULL, &sa);    if (force || sa.sa_handler == SIG_DFL)     {        sigaction(signo, act, NULL);    }}static void OS_InstallSignalHandlers(int force){    struct sigaction sa;    sigemptyset(&sa.sa_mask);    sa.sa_flags = 0;    sa.sa_handler = OS_SigpipeHandler;    installSignalHandler(SIGPIPE, &sa, force);    sa.sa_handler = OS_Sigusr1Handler;    installSignalHandler(SIGUSR1, &sa, force);}/* *-------------------------------------------------------------- * * OS_LibInit -- * *      Set up the OS library for use. * *      NOTE: This function is really only needed for application *            asynchronous I/O.  It will most likely change in the *            future to setup the multi-threaded environment. * * Results: *	Returns 0 if success, -1 if not. * * Side effects: *	Async I/O table allocated and initialized. * *-------------------------------------------------------------- */int OS_LibInit(int stdioFds[3]){    if(libInitialized)        return 0;    asyncIoTable = (AioInfo *)malloc(asyncIoTableSize * sizeof(AioInfo));    if(asyncIoTable == NULL) {        errno = ENOMEM;        return -1;    }    memset((char *) asyncIoTable, 0,           asyncIoTableSize * sizeof(AioInfo));    FD_ZERO(&readFdSet);    FD_ZERO(&writeFdSet);    FD_ZERO(&readFdSetPost);    FD_ZERO(&writeFdSetPost);    OS_InstallSignalHandlers(FALSE);    libInitialized = TRUE;    return 0;}/* *-------------------------------------------------------------- * * OS_LibShutdown -- * *	Shutdown the OS library. * * Results: *	None. * * Side effects: *	Memory freed, fds closed. * *-------------------------------------------------------------- */void OS_LibShutdown(){    if(!libInitialized)        return;    free(asyncIoTable);    asyncIoTable = NULL;    libInitialized = FALSE;    return;}/* *---------------------------------------------------------------------- * * OS_BuildSockAddrUn -- * *      Using the pathname bindPath, fill in the sockaddr_un structure *      *servAddrPtr and the length of this structure *servAddrLen. * *      The format of the sockaddr_un structure changed incompatibly in *      4.3BSD Reno.  Digital UNIX supports both formats, other systems *      support one or the other. * * Results: *      0 for normal return, -1 for failure (bindPath too long). * *---------------------------------------------------------------------- */static int OS_BuildSockAddrUn(const char *bindPath,                              struct sockaddr_un *servAddrPtr,                              int *servAddrLen){    int bindPathLen = strlen(bindPath);#ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */    if(bindPathLen >= sizeof(servAddrPtr->sun_path)) {        return -1;    }#else                           /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */    if(bindPathLen > sizeof(servAddrPtr->sun_path)) {        return -1;    }#endif    memset((char *) servAddrPtr, 0, sizeof(*servAddrPtr));    servAddrPtr->sun_family = AF_UNIX;    memcpy(servAddrPtr->sun_path, bindPath, bindPathLen);#ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */    *servAddrLen = sizeof(servAddrPtr->sun_len)            + sizeof(servAddrPtr->sun_family)            + bindPathLen + 1;    servAddrPtr->sun_len = *servAddrLen;#else                           /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */    *servAddrLen = sizeof(servAddrPtr->sun_family) + bindPathLen;#endif    return 0;}union SockAddrUnion {    struct  sockaddr_un	unixVariant;    struct  sockaddr_in	inetVariant;};/* * 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_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 {        /*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -