/*-*- mode: C; tab-width:4 -*-*/ /* execve */ #include #include /* fcntl */ #include /* strings */ #include /* setenv */ #include /* signal */ #include /* poll */ #include /* miscellaneous */ #include #include #include /* path and dir separators */ #include "php.h" #include "zend.h" #include "php_java.h" void java_get_server_args(struct cfg*cfg, char*env[N_SENV], char*args[N_SARGS]) { char *s, *p; char*program=cfg->java; char*cp=cfg->classpath; char*lib_path=cfg->ld_library_path; char*home=cfg->java_home; args[0]=strdup(program); s="-Djava.library.path="; p=malloc(strlen(s)+strlen(lib_path)+1); strcpy(p, s); strcat(p, lib_path); args[1] = p; /* library path */ s="-Djava.class.path="; p=malloc(strlen(s)+strlen(cp)+1); strcpy(p, s); strcat(p, cp); args[2] = p; /* user classes */ args[3] = strdup("-Djava.awt.headless=true"); /* disabled due to problems with IBM java, it could not find default mime table anymore */ //s="-Djava.home="; //p=malloc(strlen(s)+strlen(home)+1); //strcpy(p, s); strcat(p, home); //args[4] = p; /* java home */ args[4] = strdup("JavaBridge"); args[5] = strdup(cfg->sockname); args[6] = strdup(cfg->logLevel); args[7] = strdup(cfg->logFile); args[8] = NULL; s="JAVA_HOME="; p=malloc(strlen(s)+strlen(home)+1); strcpy(p, s); strcat(p, home); env[0] = p; /* java home */ s="LD_LIBRARY_PATH="; p=malloc(strlen(s)+strlen(lib_path)+1); strcpy(p, s); strcat(p, lib_path); env[1] = p; /* library path */ env[2] = NULL; } static void exec_vm(struct cfg*cfg) { static char*env[N_SENV]; static char*args[N_SARGS]; java_get_server_args(cfg, env, args); putenv(env[0]); putenv(env[1]); #ifdef CFG_JAVA_INPROCESS { extern int java_bridge_main(int argc, char**argv) ; java_bridge_main(N_SARGS, args); } #else execv(args[0], args); #endif } /* return 0 if user has hard-coded the socketname */ static short can_fork() { #ifndef CFG_JAVA_SOCKET_ANON return (java_ini_updated&U_SOCKNAME)==0; #else return 1; /* ignore the already running JVM and start a new JVM with the anonymous socket */ #endif } void java_start_server(struct cfg*cfg) { int pid=0, err=0, p[2], p1[2]; if(pipe(p)!=-1) { if(can_fork()) { if(!(pid=fork())) { /* daemon */ close(p[0]); if(!fork()) { /* guard */ if(!(pid=fork())) { /* java */ setsid(); close(p[1]); exec_vm(cfg); exit(105); } /* protect guard */ signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); write(p[1], &pid, sizeof pid); waitpid(pid, &err, 0); write(p[1], &err, sizeof err); exit(0); } exit(0); } close(p[1]); wait(&err); if((read(p[0], &pid, sizeof pid))!=(sizeof pid)) pid=0; } } cfg->cid=pid; cfg->err=p[0]; } static void wait_for_daemon(struct cfg*cfg TSRMLS_DC) { struct pollfd pollfd[1] = {cfg->err, POLLIN, 0}; int err, c; assert(cfg->err); assert(cfg->cid); for(c=10; c>0 && cfg->cid && (!cfg->err || (cfg->err && !(err=poll(pollfd, 1, 0)))); c--) { kill(cfg->cid, SIGTERM); sleep(1); } if(!c) kill(cfg->cid, SIGKILL); if(cfg->err) { if((read(cfg->err, &err, sizeof err))!=sizeof err) err=0; //printf("VM terminated with code: %ld\n", err); close(cfg->err); cfg->err=0; } } void php_java_shutdown_library(struct cfg*cfg TSRMLS_DC) { if(cfg->cid) wait_for_daemon(cfg TSRMLS_CC); }