Esempio n. 1
0
File: sock.c Progetto: scottg/nsdci
int
Dci_ListenCallback(char *name, char *addr, int port,
	Dci_ListenAcceptProc *acceptProc, Dci_ListenExitProc *exitProc, void *arg)
{
    ListenData *lPtr;
    int sock;
    int ok;

    lPtr = ns_malloc(sizeof(ListenData) + strlen(name));
    lPtr->acceptProc = acceptProc;
    lPtr->exitProc = exitProc;
    lPtr->arg = arg;
    strcpy(lPtr->name, name);
    ok = 0;
    sock = Ns_SockListen(addr, port);
    if (sock != -1) {
	Ns_SockSetNonBlocking(sock);
	if (Ns_SockCallback(sock, ListenProc, lPtr, NS_SOCK_READ|NS_SOCK_EXIT) != NS_OK) {
	    Ns_Log(Error, "Dci_ListenCallback: %s: %s(%d): %s", name, addr, port, strerror(errno));
	    close(sock);
	} else {
	    ok = 1;
	}
    }
    Ns_Log(ok ? Notice : Error, "%s: %s on %s:%d", name,
	   ok ? "listening" : "could not listen", addr ? addr : "*", port);
    if (!ok) {
	ns_free(lPtr);
    }
    return (ok ? NS_OK : NS_ERROR);
}
Esempio n. 2
0
File: sock.c Progetto: scottg/nsdci
static int
ListenProc(int sock, void *arg, int why)
{
    ListenData *lPtr = arg;

    if (why == NS_SOCK_EXIT) {
	Ns_Log(Notice, "%s: shutdown pending", lPtr->name);
	if (lPtr->exitProc != NULL) {
	    (*lPtr->exitProc)(lPtr->arg);
	}
	close(sock);
	Ns_Log(Notice, "%s: shutdown complete", lPtr->name);
	ns_free(lPtr);
	return NS_FALSE;
    }

    sock = Ns_SockAccept(sock, NULL, NULL);
    if (sock == -1) {
	Ns_Log(Error, "%s: accept() failed: %s", lPtr->name, strerror(errno));
    } else {
	DciLogPeer2(sock, lPtr->name, "connected to");
	(lPtr->acceptProc)(sock, lPtr->arg);
    }
    return NS_TRUE;
}
Esempio n. 3
0
/* lazily maintain 1:1 mapping between tcl and perl interpreters */
perl_context *nsperl2_get_assoc_perl_context (Tcl_Interp *interp)
{
    extern perl_master_context *nsperl2_master_context;
    assert (nsperl2_master_context);
    perl_context *context = Tcl_GetAssocData (interp, "nsperl2:perl_context", NULL);
    PerlInterpreter *perl_interp;

    if(context)
        return context;

    Ns_Log (Notice, "cloning perl interpreter for tcl interp");

    PERL_SET_CONTEXT (nsperl2_master_context->perl_master_interp);

    if ((perl_interp = perl_clone (nsperl2_master_context->perl_master_interp, CLONEf_KEEP_PTR_TABLE)) == NULL) {
        Ns_Log (Error, "Couldn't clone perl interp");
        return NULL;
        }

    /* save the perl interp */
    context = ns_malloc (sizeof(perl_context));
    context->perl_interp = perl_interp;
    Tcl_SetAssocData(interp, "nsperl2:perl_context", nsperl2_delete_assoc_perl, context);

    return context;
}
Esempio n. 4
0
static void 
php_ns_config(php_ns_context *ctx, char global)
{
	int i;
	char *path;
	Ns_Set *set;

	path = Ns_ConfigGetPath(ctx->ns_server, ctx->ns_module, NULL);
	set = Ns_ConfigGetSection(path);

	for (i = 0; set && i < Ns_SetSize(set); i++) {
		char *key = Ns_SetKey(set, i);
		char *value = Ns_SetValue(set, i);

		if (global && !strcasecmp(key, "map")) {
			Ns_Log(Notice, "Registering PHP for \"%s\"", value);
			Ns_RegisterRequest(ctx->ns_server, "GET", value, php_ns_request_handler, NULL, ctx, 0);
			Ns_RegisterRequest(ctx->ns_server, "POST", value, php_ns_request_handler, NULL, ctx, 0);
			Ns_RegisterRequest(ctx->ns_server, "HEAD", value, php_ns_request_handler, NULL, ctx, 0);

	/* 
	 * Deactivated for now. The ini system will cause random crashes when 
	 * accessed from here (since there are no locks to protect the global 
	 * known_directives) 
	 */

		} else if (!global && !strcasecmp(key, "php_value")) {
			Ns_Log(Notice, "php_value has been deactivated temporarily. Please use a php.ini file to pass directives to PHP. Thanks.");
#if 0
			char *val;

			val = strchr(value, ' ');
			if (val) {
				char *new_key;
				
				new_key = estrndup(value, val - value);
				
				do { 
					val++; 
				} while(*val == ' ');

				Ns_Log(Debug, "PHP configuration option '%s=%s'", new_key, val);
				zend_alter_ini_entry(new_key, strlen(new_key) + 1, val, 
						strlen(val) + 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
				
				efree(new_key);
			}
#endif
		}
		
	}
}
Esempio n. 5
0
NS_EXPORT int
Ns_ModuleInit(char *server, char *module)
{
	Ns_Log(Notice,"loading jsmin");
	Ns_TclRegisterTrace(server, AddCmds, NULL, NS_TCL_TRACE_CREATE);
	return NS_OK;
}
Esempio n. 6
0
File: sock.c Progetto: scottg/nsdci
static void
SetOpt(int sock, int level, int name, int value)
{
    if (setsockopt(sock, level, name, (char *) &value, sizeof(value)) != 0) {
	Ns_Log(Error, "setsockopt(%d, %d, %d, %d) failed: %s",
	    sock, level, name, value, strerror(errno));
    }
}
Esempio n. 7
0
void nsperl2_delete_assoc_perl( ClientData clientData, Tcl_Interp *interp)
{
    perl_context *context = (perl_context *) clientData;
    Ns_Log (Notice, "in nsperl2_delete_assoc_perl - about to free and destruct interp perl context");
    PERL_SET_CONTEXT (context->perl_interp);
    /* perl_destruct (context->perl_interp); - I don't think we want to run END blocks for each interp shutdown do we?? */
    perl_free (context->perl_interp);
    ns_free ((void*)context);
}
Esempio n. 8
0
void nsperl2_free_master_context (void *context)
{
    extern perl_master_context *nsperl2_master_context;
    assert (nsperl2_master_context);
    Ns_Log (Notice, "in nsperl2_free_master_context - about to free and destruct master perl context");
    PERL_SET_CONTEXT (nsperl2_master_context->perl_master_interp);
    perl_destruct (nsperl2_master_context->perl_master_interp);
    perl_free (nsperl2_master_context->perl_master_interp);
    PERL_SYS_TERM();
}
Esempio n. 9
0
static int
NsThread_Init (Tcl_Interp *interp, void *cd)
{
    struct mydata *md = (struct mydata*)cd;
    int ret = Thread_Init(interp);

    if (ret != TCL_OK) {
        Ns_Log(Warning, "can't load module %s: %s", md->modname,
               Tcl_GetStringResult(interp));
        return TCL_ERROR;
    }
    Tcl_SetAssocData(interp, "thread:nsd", NULL, (ClientData)md);

    return TCL_OK;
}
Esempio n. 10
0
static void
JsCleanup(void *arg) 
{
	jsEnv *jsEnvPtr = arg;
	
	if (jsEnvPtr != NULL) {
		JS_DestroyContext(jsEnvPtr->context); 
		JS_DestroyRuntime(jsEnvPtr->runtime);
		JS_ShutDown();

		Ns_Log(Debug, "JsCleanup: %p", jsEnvPtr);

		ns_free(jsEnvPtr);
	}
}
Esempio n. 11
0
static int
JsInit(Tcl_Interp *interp, void *arg) 
{
	jsEnv *jsEnvPtr;
	
	Ns_TlsAlloc(&tls, JsCleanup);
	
	jsEnvPtr = ns_calloc(1, sizeof(jsEnv));
	
	jsEnvPtr->runtime = JS_NewRuntime(8L * 1024L * 1024L);
	jsEnvPtr->context = JS_NewContext(jsEnvPtr->runtime, 8192);
	jsEnvPtr->object = JS_NewObject(jsEnvPtr->context, NULL, NULL, NULL);
	
	JS_InitStandardClasses(jsEnvPtr->context, jsEnvPtr->object);
	JS_SetErrorReporter(jsEnvPtr->context, JsLogError);
	
	Ns_TlsSet(&tls, jsEnvPtr);
	
	Ns_Log(Debug, "JsInit: %p", jsEnvPtr);
	
	Tcl_CreateObjCommand(interp, "js.eval", JsEvalObjCmd, NULL, NULL);
	
	return TCL_OK;
}
Esempio n. 12
0
int
NsPerl2_ModInit(char *server, char *module)
{
    extern perl_master_context *nsperl2_master_context;
    int perl_exitstatus;
    Ns_Log(Notice,"nsperl2: loading");

    if (!(nsperl2_master_context = ns_malloc (sizeof(perl_master_context))))
        return TCL_ERROR;

    /* determine initial perl script */
    nsperl2_master_context->param_path = Ns_ConfigGetPath(server, module, NULL);
    nsperl2_master_context->init_script = Ns_ConfigGetValue(nsperl2_master_context->param_path, "init_script");
    nsperl2_master_context->init_sub = Ns_ConfigGetValue(nsperl2_master_context->param_path, "init_sub");
    nsperl2_master_context->server = Ns_ConfigGetValue(nsperl2_master_context->param_path, "server");

    /* TODO: what to do if multiple servers? probably need a master context per server */

    Ns_Log (Notice, "nsperl2: init_script is %s", nsperl2_master_context->init_script);
    char *embedding[] = { "", nsperl2_master_context->init_script };
    PerlInterpreter *perl_interp;

    int perl_argc = 0;
    char **perl_argv = NULL;

    PERL_SYS_INIT3( &perl_argc, &perl_argv, environ_h );

    /* create perl interpreter */

    if((perl_interp = perl_alloc()) == NULL) {
        Ns_Log (Error, "Couldn't alloc perl interp");
        return TCL_ERROR;
    }

    perl_construct(perl_interp);
    PL_exit_flags |= PERL_EXIT_DESTRUCT_END; /* run END blocks at destruction */

    PERL_SET_CONTEXT (perl_interp);
    perl_exitstatus = perl_parse(perl_interp, xs_init, 2, embedding, NULL);

    /* TODO: check perl_exitstatus */

    nsperl2_master_context->perl_master_interp = perl_interp;

    /* call the init_sub - eg. where urls are registered etc. 
       you could do the same in a BEGIN block, but this is cleaner */

    dSP;
    PUSHMARK (SP);
    Tcl_Interp *tcl_interp;
    tcl_interp = Ns_TclAllocateInterp (server);
    set_nsperl2_globals (perl_interp, tcl_interp, NULL);
    call_pv (nsperl2_master_context->init_sub, G_NOARGS | G_VOID | G_DISCARD); /* not doing G_EVAL - if init_sub fails, we want to bail. */
    /* should I destroy that tcl interp?? */

    Ns_RegisterShutdown (nsperl2_free_master_context, NULL);
    
    Ns_TclInitInterps(server,NsPerl2InitInterp, NULL);

    return NS_OK;
}
Esempio n. 13
0
void
NsConnThread(void *arg)
{
    ConnData  	    *dataPtr = arg;
    Pool            *poolPtr = dataPtr->poolPtr;
    Conn            *connPtr;
    Ns_Time          wait, *timePtr;
    char             name[100];
    int              status, ncons;
    char            *msg;
    double           spread;
    
    /*
     * Set the conn thread name.
     */

    Ns_TlsSet(&ctdtls, dataPtr);
    Ns_MutexLock(&poolPtr->lock);
    sprintf(name, "-%s:%d-", poolPtr->name, poolPtr->threads.nextid++);
    Ns_MutexUnlock(&poolPtr->lock);
    Ns_ThreadSetName(name);

    /* spread is a value of 1.0 +- specified percentage, 
       i.e. between 0.0 and 2.0 when the configured percentage is 100 */
    spread = 1.0 + (2 * poolPtr->threads.spread * Ns_DRand() - poolPtr->threads.spread) / 100.0;

    ncons = round(poolPtr->threads.maxconns * spread);
    msg = "exceeded max connections per thread";
    
    /*
     * Start handling connections.
     */

    Ns_MutexLock(&poolPtr->lock);

    poolPtr->threads.starting--;
    poolPtr->threads.idle++;

    while (poolPtr->threads.maxconns <= 0 || ncons-- > 0) {

	/*
	 * Wait for a connection to arrive, exiting if one doesn't
	 * arrive in the configured timeout period.
	 */
        
	if (poolPtr->threads.current <= poolPtr->threads.min) {
	    timePtr = NULL;
	} else {
	    Ns_GetTime(&wait);
	    Ns_IncrTime(&wait, round(poolPtr->threads.timeout * spread), 0);
	    timePtr = &wait;
	}

        status = NS_OK;
        while (!poolPtr->shutdown
               && status == NS_OK
               && poolPtr->queue.wait.firstPtr == NULL) {
            /* 
               nothing is queued, we wait for a queue entry 
            */
            poolPtr->threads.waiting++;
            status = Ns_CondTimedWait(&poolPtr->cond, &poolPtr->lock, timePtr);
            poolPtr->threads.waiting--;
        }

	if (poolPtr->queue.wait.firstPtr == NULL) {
	    msg = "timeout waiting for connection";
	    break;
	}

	/*
	 * Pull the first connection off the waiting list.
	 */

    	connPtr = poolPtr->queue.wait.firstPtr;
    	poolPtr->queue.wait.firstPtr = connPtr->nextPtr; 
    	if (poolPtr->queue.wait.lastPtr == connPtr) {
	    poolPtr->queue.wait.lastPtr = NULL;
    	}
	connPtr->nextPtr = NULL;
	connPtr->prevPtr = poolPtr->queue.active.lastPtr;
         if (poolPtr->queue.active.lastPtr != NULL) {
             poolPtr->queue.active.lastPtr->nextPtr = connPtr;
         }
         poolPtr->queue.active.lastPtr = connPtr;
         if (poolPtr->queue.active.firstPtr == NULL) {
             poolPtr->queue.active.firstPtr = connPtr;
         }
         poolPtr->threads.idle--;
         poolPtr->queue.wait.num--;

         Ns_MutexUnlock(&poolPtr->lock);

         /*
          * Run the connection.
          */

         Ns_MutexLock(&connlock);
         dataPtr->connPtr = connPtr;
         Ns_MutexUnlock(&connlock);
         
         Ns_GetTime(&connPtr->times.run);
         ConnRun(connPtr);
         Ns_MutexLock(&connlock);
         dataPtr->connPtr = NULL;
         Ns_MutexUnlock(&connlock);
         
         /*
          * Remove from the active list and push on the free list.
          */

         Ns_MutexLock(&poolPtr->lock);
         if (connPtr->prevPtr != NULL) {
             connPtr->prevPtr->nextPtr = connPtr->nextPtr;
         } else {
             poolPtr->queue.active.firstPtr = connPtr->nextPtr;
         }
         if (connPtr->nextPtr != NULL) {
             connPtr->nextPtr->prevPtr = connPtr->prevPtr;
         } else {
             poolPtr->queue.active.lastPtr = connPtr->prevPtr;
         }
         poolPtr->threads.idle++;
         Ns_MutexUnlock(&poolPtr->lock);
         NsFreeConn(connPtr);
         Ns_MutexLock(&poolPtr->lock);
    }
    
    /*
     * Append this thread to list of threads to reap.
     */
    
    Ns_MutexLock(&joinlock);
    dataPtr->nextPtr = joinPtr;
    joinPtr = dataPtr;
    Ns_MutexUnlock(&joinlock);
    
    /*
     * Mark this thread as no longer active.
     */
    
    if (poolPtr->shutdown) {
        msg = "shutdown pending";
    }
    poolPtr->threads.current--;
    poolPtr->threads.idle--;
    
    if (((poolPtr->queue.wait.num > 0 
          && poolPtr->threads.idle == 0 
          && poolPtr->threads.starting == 0
          )
         || (poolPtr->threads.current < poolPtr->threads.min)
         ) && !poolPtr->shutdown) {
        /* 
           Recreate a thread when on of the condings hold
           - there are more queue entries are still waiting, 
           but no thread is either starting or idle, or
           - there are less than minthreads connection threads alive.
        */
        poolPtr->threads.current ++;
        Ns_MutexUnlock(&poolPtr->lock);
        NsCreateConnThread(poolPtr, 0); /* joinThreads == 0 to avoid deadlock */
    } else if (poolPtr->queue.wait.num > 0 && poolPtr->threads.waiting > 0) {
        /*
          Wake up a waiting thread
        */
        Ns_CondSignal(&poolPtr->cond);
        Ns_MutexUnlock(&poolPtr->lock);
    } else {
        Ns_MutexUnlock(&poolPtr->lock);
    }
    
    Ns_Log(Notice, "exiting: %s", msg);
    Ns_ThreadExit(dataPtr);
}
Esempio n. 14
0
/** Standard AOLserver callback.
 * Initialize jk2, unless already done in another server. Register URI mappping for Tomcat
 * If multiple virtual servers use this module, calls to Ns_ModuleInit will be made serially
 * in order of appearance of those servers in nsd.tcl
 */
int Ns_ModuleInit(char *server, char *module)
{
    jk_env_t *env;
    
    /* configuration-related */
    char* serverName=NULL;
    char* confPath;
    static char cwdBuf[PATH_MAX];
    static char* serverRoot = NULL;

    /* APR-related */
    apr_status_t aprrc;
    char errbuf[512];
    apr_pool_t *jk_globalPool = NULL;

    /* URI registration */
    char *hosts[2] = {"*", NULL};
    jk_map_t *vhosts;
    int i, j, k, l, cnt1, cnt2;
    jk_map_t *uriMap, *webapps, *uriMaps[3];
    jk_uriEnv_t *uriEnv, *hostEnv, *appEnv;


    if (jkInitCount++ == 0) {

        /* Get Tomcat installation root - this value is same for all virtual servers*/
        if (serverRoot == NULL) {
            confPath = Ns_ConfigGetPath (NULL, module, NULL);
            serverRoot = (confPath? Ns_ConfigGetValue (confPath, "serverRoot") : NULL);
        }

        /* not configured in nsd.tcl? try env. variable */
        if (serverRoot == NULL) {
            serverRoot = getenv ("TOMCAT_HOME");
        }

        /* not in env. variables? get it from CWD */
        if (serverRoot == NULL) {
            serverRoot = getcwd (cwdBuf, sizeof(cwdBuf));
        }

	/* Initialize APR */
	if ((aprrc=apr_initialize()) != APR_SUCCESS) {
	    LOG_ERROR2 ("Cannot initialize APR", apr_strerror (aprrc, errbuf, sizeof(errbuf)));
	    return NS_ERROR;
	}

	if ((aprrc=apr_pool_create(&jk_globalPool, NULL)) != APR_SUCCESS) {
	    LOG_ERROR2 ("Cannot create global APR pool", apr_strerror (aprrc, errbuf, sizeof(errbuf)));
	    return NS_ERROR;
	}

	/* Initialize JNI */
	if (workerEnv==NULL && jk2_create_workerEnv(jk_globalPool, serverRoot)==JK_ERR) {
	    return NS_ERROR;
	}

	env=workerEnv->globalEnv;
	env->setAprPool(env, jk_globalPool);

	/* Initialize JK2 */
	if (workerEnv->init(env, workerEnv ) != JK_OK) {
	    LOG_ERROR("Cannot initialize worker environment");
	    return NS_ERROR;
	}

	workerEnv->server_name = apr_pstrcat (jk_globalPool, Ns_InfoServerName(), " ", Ns_InfoServerVersion (), NULL);
	apr_pool_cleanup_register(jk_globalPool, NULL, jk2_shutdown, apr_pool_cleanup_null);

	workerEnv->was_initialized = JK_TRUE; 
    
	if ((aprrc=apr_pool_userdata_set( "INITOK", "Ns_ModuleInit", NULL, jk_globalPool )) != APR_SUCCESS) {
	    LOG_ERROR2 ("Cannot set APR pool user data", apr_strerror (aprrc, errbuf, sizeof(errbuf)));
	    return NS_ERROR;
	}

	if (workerEnv->parentInit( env, workerEnv) != JK_OK) {
	    LOG_ERROR ("Cannot initialize global environment");
	    return NS_ERROR;
	}

	/* Obtain TLS slot - it's destructor will detach threads from JVM */
	jvmGlobal = workerEnv->vm->jvm;
	Ns_TlsAlloc (&jkTls, jkTlsDtor);

	Ns_Log (Notice, "nsjk2: Initialized JK2 environment");

    } else {
      
      env = workerEnv->globalEnv;
    }

    Ns_RegisterShutdown (jk2_shutdown_system, NULL);

    /* Register URI patterns from workers2.properties with AOLserver 
     *  
     * Worker environment has a list of vhosts, including "*" vhost.
     * Each vhost has a list of web applications (contexts) associated with it.
     * Each webapp has a list of exact, prefix, suffix and regexp URI patterns.
     *
     * Will register URIs that are either in vhost "*", or one with name matching
     * this AOLserver virtual server. Will ignore regexp patterns. Will register 
     * exact webapp URIs (context root) as JK2 somehow doesn't include them in URI
     * maps, even if specified in workers2.properties.
     *
     */

    /* virtual server name override if specified */
    confPath = Ns_ConfigGetPath (server, module, NULL);
    if (confPath != NULL)
        serverName = Ns_ConfigGetValue (confPath, "serverName");

    if (serverName == NULL)
        serverName = server;
    
    vhosts=workerEnv->uriMap->vhosts;
    hosts[1]= serverName;

    for (i=0; i<sizeof(hosts)/sizeof(*hosts); i++) {
        hostEnv=vhosts->get (env, vhosts, hosts[i]);

	if (hostEnv==NULL || hostEnv->webapps==NULL)
	    continue;

	webapps=hostEnv->webapps;
	cnt1=webapps->size(env, webapps);

	for (j=0; j<cnt1; j++) {
	    appEnv = webapps->valueAt (env, webapps, j);
	    if (appEnv == NULL)
	        continue;

	    /* register webapp root - registerURI checks if it is "/" */
	    registerURI (env, appEnv, server, serverName);
	    
	    uriMaps[0] = appEnv->exactMatch;
	    uriMaps[1] = appEnv->prefixMatch;
	    uriMaps[2] = appEnv->suffixMatch;

	    for (k=0; k<sizeof(uriMaps)/sizeof(*uriMaps); k++) {
	        if (uriMaps[k] == NULL)
		    continue;

	        cnt2 = uriMaps[k]->size (env, uriMaps[k]);
		
		for (l=0; l<cnt2; l++) {
		     registerURI (env, uriMaps[k]->valueAt (env, uriMaps[k], l), server, serverName);
		}
	    }
	}
    }

    Ns_Log (Notice, "nsjk2: Initialized on %s", server);

    return NS_OK;
}
Esempio n. 15
0
int
Ns_WaitForProcess(int pid, int *exitcodePtr)
{
#ifdef _WIN32
    HANDLE process = (HANDLE) pid;
    int status = NS_OK;
    int exitcode;

    if ((WaitForSingleObject(process, INFINITE) == WAIT_FAILED) ||
        (GetExitCodeProcess(process, &exitcode) != TRUE)) {
        Ns_Log(Error, "exec: failed to get process exit code: %s",
               NsWin32ErrMsg(GetLastError()));
        status = NS_ERROR;
    }
    if (CloseHandle(process) != TRUE) {
        Ns_Log(Warning, "exec: failed to close handle for process %d: %s",
	       pid, NsWin32ErrMsg(GetLastError()));
        status = NS_ERROR;
    }
    if (status == NS_OK) {
        if (exitcodePtr != NULL) {
            *exitcodePtr = exitcode;
        }
        if (nsconf.exec.checkexit && exitcode != 0) {
            Ns_Log(Error, "exec: process %d exited with non-zero status: %d",
                   pid, exitcode);
            status = NS_ERROR;
        }
    }
    return status;

#else
    char *coredump;
    int exitcode, status;
    
    if (waitpid(pid, &status, 0) != pid) {
        Ns_Log(Error, "waitpid(%d) failed: %s", pid, strerror(errno));
	return NS_ERROR;
    }
    if (WIFSIGNALED(status)) {
    	coredump = "";
#ifdef WCOREDUMP
        if (WCOREDUMP(status)) {
	    coredump = " - core dumped";
	}
#endif
        Ns_Log(Error, "process %d killed with signal %d%s", pid,
	    WTERMSIG(status), coredump);
    } else if (!WIFEXITED(status)) {
    	Ns_Log(Error, "waitpid(%d): invalid status: %d", pid, status);
    } else {
    	exitcode = WEXITSTATUS(status);
    	if (exitcode != 0) {
            Ns_Log(Warning, "process %d exited with non-zero exit code: %d",
               pid, exitcode);
    	}
    	if (exitcodePtr != NULL) {
    	    *exitcodePtr = exitcode;
	}
    }
    return NS_OK;
#endif /* _WIN32 */
}
Esempio n. 16
0
int
Ns_ExecArgblk(char *exec, char *dir, int fdin, int fdout,
		char *args, Ns_Set *env)
{
#ifndef _WIN32
    int    pid;
    char **argv;
    Ns_DString vds;

    Ns_DStringInit(&vds);
    if (args == NULL) {
        argv = NULL;
    } else {
	while (*args != '\0') {
            Ns_DStringNAppend(&vds, (char *) &args, sizeof(args));
            args += strlen(args) + 1;
	}
	args = NULL;
	Ns_DStringNAppend(&vds, (char *) &args, sizeof(args));
	argv = (char **) vds.string;
    }
    pid = Ns_ExecArgv(exec, dir, fdin, fdout, argv, env);
    Ns_DStringFree(&vds);
    return pid;
#else
    STARTUPINFO     si;
    PROCESS_INFORMATION pi;
    HANDLE          hCurrentProcess;
    int             pid;
    Ns_DString      cds, xds, eds;
    char           *envp;
    OSVERSIONINFO   oinfo;
    char           *cmd;

    if (exec == NULL) {
        return -1;
    }
    oinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if (GetVersionEx(&oinfo) == TRUE && oinfo.dwPlatformId != VER_PLATFORM_WIN32_NT) {
        cmd = "command.com";
    } else {
        cmd = "cmd.exe";
    }

    /*
     * Setup STARTUPINFO with stdin, stdout, and stderr.
     */
    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdError = (HANDLE) _get_osfhandle(_fileno(stderr));
    hCurrentProcess = GetCurrentProcess();
    if (fdout < 0) {
        fdout = 1;
    }
    if (DuplicateHandle(hCurrentProcess, (HANDLE) _get_osfhandle(fdout), hCurrentProcess,
            &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS) != TRUE) {
        Ns_Log(Error, "exec: failed to duplicate handle: %s",
        NsWin32ErrMsg(GetLastError()));
        return -1;
    }
    if (fdin < 0) {
        fdin = 0;
    }
    if (DuplicateHandle(hCurrentProcess, (HANDLE) _get_osfhandle(fdin), hCurrentProcess,
            &si.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS) != TRUE) {
        Ns_Log(Error, "exec: failed to duplicate handle: %s",
        NsWin32ErrMsg(GetLastError()));
        (void) CloseHandle(si.hStdOutput);
        return -1;
    }

    /*
     * Setup the command line and environment block and create the new
     * subprocess.
     */

    Ns_DStringInit(&cds);
    Ns_DStringInit(&xds);
    Ns_DStringInit(&eds);
    if (args == NULL) {
        /* NB: exec specifies a complete cmd.exe command string. */
        Ns_DStringVarAppend(&cds, cmd, " /c ", exec, NULL);
        exec = NULL;
    } else {
        char           *s;

        s = args;
        while (*s != '\0') {
            int             len;

            len = strlen(s);
            Ns_DStringNAppend(&cds, s, len);
            s += len + 1;
            if (*s != '\0') {
                Ns_DStringNAppend(&cds, " ", 1);
            }
        }
    Ns_NormalizePath(&xds, exec);
    s = xds.string;
    while (*s != '\0') {
        if (*s == '/') {
            *s = '\\';
        }
        ++s;
    }
    exec = xds.string;
    }
    if (env == NULL) {
        envp = NULL;
    } else {
        Set2Argv(&eds, env);
        envp = eds.string;
    }
    if (CreateProcess(exec, cds.string, NULL, NULL, TRUE, 0, envp, dir, &si, &pi) != TRUE) {
        Ns_Log(Error, "exec: failed to create process: %s: %s",
        exec ? exec : cds.string, NsWin32ErrMsg(GetLastError()));
        pid = -1;
    } else {
        CloseHandle(pi.hThread);
        pid = (int) pi.hProcess;
    }
    Ns_DStringFree(&cds);
    Ns_DStringFree(&xds);
    Ns_DStringFree(&eds);
    CloseHandle(si.hStdInput);
    CloseHandle(si.hStdOutput);
    return pid;
#endif
}
Esempio n. 17
0
File: sock.c Progetto: scottg/nsdci
void
DciLogPeer(int sock, char *msg)
{
    Ns_Log(Notice, "%s: %s", msg, DciGetPeer(sock));
}
Esempio n. 18
0
File: sock.c Progetto: scottg/nsdci
void
DciLogPeer2(int sock, char *ident, char *msg)
{
    Ns_Log(Notice, "%s: %s %s", ident, msg, DciGetPeer(sock));
}
Esempio n. 19
0
static int
ExecProc(char *exec, char *dir, int fdin, int fdout, char **argv,
    	 char **envp)
{
    struct iovec iov[2];
    int    pid, nread, errpipe[2], errnum, result;

    /*
     * Create a pipe for child error message.
     */
     
    if (ns_pipe(errpipe) < 0) {
        Ns_Log(Error, "exec: ns_pipe() failed: %s", strerror(errno));
	return -1;
    }

    /*
     * Fork child and read error message (if any).
     */

    pid = ns_fork();
    if (pid < 0) {
        close(errpipe[0]);
        close(errpipe[1]);
        Ns_Log(Error, "exec: ns_fork() failed: %s", strerror(errno));
	return -1;
    }
    iov[0].iov_base = (caddr_t) &result;
    iov[1].iov_base = (caddr_t) &errnum;
    iov[0].iov_len = iov[1].iov_len = sizeof(int);
    if (pid == 0) {

	/*
	 * Setup child and exec the program, writing any error back
	 * to the parent if necessary.
	 */

        close(errpipe[0]);
        if (dir != NULL && chdir(dir) != 0) {
	    result = ERR_CHDIR;
        } else if ((fdin == 1 && (fdin = dup(1)) < 0) ||
    	    	    (fdout == 0 && (fdout = dup(0)) < 0) ||
	    	    (fdin != 0 && dup2(fdin, 0) < 0) ||
    	    	    (fdout != 1 && dup2(fdout, 1) < 0)) {
	    result = ERR_DUP;
	} else {
	    if (fdin > 2) {
		close(fdin);
	    }
	    if (fdout > 2) {
            	close(fdout);
	    }
            NsRestoreSignals();
	    Ns_NoCloseOnExec(0);
	    Ns_NoCloseOnExec(1);
	    Ns_NoCloseOnExec(2);
            execve(exec, argv, envp);
	    /* NB: Not reached on successful execve(). */
	    result = ERR_EXEC;
	}
	errnum = errno;
	(void) writev(errpipe[1], iov, 2);
	_exit(1);
	
    } else {
    
	/*
	 * Read result and errno from the child if any.
	 */

        close(errpipe[1]);
	do {
            nread = readv(errpipe[0], iov, 2);
	} while (nread < 0 && errno == EINTR);
        close(errpipe[0]);
        if (nread == 0) {
	    errnum = 0;
	    result = pid;
	} else {
            if (nread != (sizeof(int) * 2)) {
	    	Ns_Log(Error, "exec: %s: error reading status from child: %s",
			   exec, strerror(errno));
            } else {
		switch (result) {
		    case ERR_CHDIR:
            		Ns_Log(Error, "exec %s: chdir(%s) failed: %s",
				exec, dir, strerror(errnum));
	    		break;
		    case ERR_DUP:
	    		Ns_Log(Error, "exec %s: dup failed: %s",
				exec, strerror(errnum));
	    		break;
		    case ERR_EXEC:
	    		Ns_Log(Error, "exec %s: execve() failed: %s",
				exec, strerror(errnum));
	    		break;
		    default:
	    		Ns_Log(Error, "exec %s: unknown result from child: %d",
				exec, result);
	    		break;
		}
	    }
            (void) waitpid(pid, NULL, 0);
	    errno = errnum;
        }
    }
    return result;
}