jint Java_com_caucho_bootjni_JniProcess_waitpid(JNIEnv *env, jobject obj, jint pid, jboolean is_block) { int status = 0; int result; #ifdef WIN32 return -1; #else if (pid < 0) { resin_printf_exception(env, "java/lang/IllegalArgumentException", "invalid pid"); return -1; } result = waitpid(pid, &status, is_block ? 0 : WNOHANG); if (result == 0) return -1; if (result < 0) { resin_printf_exception(env, "java/lang/IllegalArgumentException", "invalid result %d", result); return -1; } return WEXITSTATUS(status); #endif }
static struct sockaddr_in * lookup_addr(JNIEnv *env, char *addr_name, int port, char *buffer, int *p_family, int *p_protocol, int *p_sin_length) { struct addrinfo hints; struct addrinfo *addr; struct sockaddr_in *sin; int sin_length; char port_name[16]; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_NUMERICHOST; sprintf(port_name, "%d", port); if (getaddrinfo(addr_name, port_name, &hints, &addr)) { resin_printf_exception(env, "java/net/SocketException", "can't find address %s", addr_name); return 0; } *p_family = addr->ai_family; *p_protocol = addr->ai_protocol; sin_length = addr->ai_addrlen; memcpy(buffer, addr->ai_addr, sin_length); sin = (struct sockaddr_in *) buffer; freeaddrinfo(addr); *p_sin_length = sin_length; return sin; }
static int write_exception_status(connection_t *conn, int error) { if (error == EAGAIN || error == EWOULDBLOCK || error == EINTR) { if (conn->jni_env) { resin_printf_exception(conn->jni_env, "com/caucho/vfs/ClientDisconnectException", "timeout fd=%d errno=%d\n", conn->fd, error); } return TIMEOUT_EXN; } else if (error == EPIPE || error == ECONNRESET) { if (conn->jni_env) { resin_printf_exception(conn->jni_env, "com/caucho/vfs/ClientDisconnectException", "Client disconnect fd=%d errno=%d\n", conn->fd, error); } return DISCONNECT_EXN; } else { return -1; } }
jboolean Java_com_caucho_bootjni_JniProcess_exec(JNIEnv *env, jobject obj, jobjectArray j_argv, jobjectArray j_envp, jstring j_chroot, jstring j_pwd, jstring j_user, jstring j_group) { char **argv; char **envp; char chroot_path[4096]; char pwd[4096]; char user[256]; char group[256]; int uid = -1; int gid = -1; int len; int i; int pipe_fds[2]; int pid; jclass c_jni_process; jfieldID f_stdoutFd; jfieldID f_pid; #ifdef WIN32 if (1) return -1; #endif /* WIN32 */ user[0] = 0; group[0] = 0; chroot_path[0] = 0; if (! j_argv) { resin_printf_exception(env, "java/lang/NullPointerException", "argv"); return 0; } if (! j_envp) { resin_printf_exception(env, "java/lang/NullPointerException", "argv"); return 0; } if (! j_pwd) { resin_printf_exception(env, "java/lang/NullPointerException", "pwd"); return 0; } c_jni_process = (*env)->FindClass(env, "com/caucho/bootjni/JniProcess"); if (! c_jni_process) { resin_printf_exception(env, "java/lang/NullPointerException", "can't load JniProcess"); return 0; } f_stdoutFd = (*env)->GetFieldID(env, c_jni_process, "_stdoutFd", "I"); if (! f_stdoutFd) { resin_printf_exception(env, "java/lang/NullPointerException", "can't load field"); return 0; } f_pid = (*env)->GetFieldID(env, c_jni_process, "_pid", "I"); if (! f_pid) { resin_printf_exception(env, "java/lang/NullPointerException", "can't load field"); return 0; } len = (*env)->GetArrayLength(env, j_argv); argv = malloc((len + 1) * sizeof(char*)); argv[len] = 0; for (i = 0; i < len; i++) { jstring j_string; j_string = (*env)->GetObjectArrayElement(env, j_argv, i); if (j_string) { int strlen = (*env)->GetStringUTFLength(env, j_string); argv[i] = (char *) malloc(strlen + 1); argv[i] = get_utf8(env, j_string, argv[i], strlen + 1); } } len = (*env)->GetArrayLength(env, j_envp); envp = malloc((len + 1) * sizeof(char*)); envp[len] = 0; for (i = 0; i < len; i++) { jstring j_string; j_string = (*env)->GetObjectArrayElement(env, j_envp, i); if (j_string) { int strlen = (*env)->GetStringUTFLength(env, j_string); envp[i] = (char *) malloc(strlen + 1); envp[i] = get_utf8(env, j_string, envp[i], strlen + 1); } } if (j_chroot) { int strlen = (*env)->GetStringUTFLength(env, j_chroot); get_utf8(env, j_chroot, chroot_path, strlen + 1); } else chroot_path[0] = 0; if (j_pwd) { int strlen = (*env)->GetStringUTFLength(env, j_pwd); get_utf8(env, j_pwd, pwd, strlen + 1); } #ifndef WIN32 if (j_user) { struct passwd *passwd; int strlen = (*env)->GetStringUTFLength(env, j_user); get_utf8(env, j_user, user, strlen + 1); passwd = getpwnam(user); if (! passwd) { resin_printf_exception(env, "java/lang/IllegalArgumentException", "%s is an unknown user", user); return 0; } uid = passwd->pw_uid; gid = passwd->pw_gid; } if (j_group) { struct group *group_ent; int strlen = (*env)->GetStringUTFLength(env, j_group); get_utf8(env, j_group, group, strlen + 1); group_ent = getgrnam(group); if (! group_ent) { resin_printf_exception(env, "java/lang/IllegalArgumentException", "%s is an unknown group", group); return 0; } gid = group_ent->gr_gid; } pipe(pipe_fds); pid = fork(); if (pid > 0) { close(pipe_fds[1]); (*env)->SetIntField(env, obj, f_stdoutFd, pipe_fds[0]); (*env)->SetIntField(env, obj, f_pid, pid); return 1; } else if (pid < 0) { close(pipe_fds[0]); close(pipe_fds[1]); resin_printf_exception(env, "java/lang/NullPointerException", "can't fork"); return 0; } close(pipe_fds[0]); /* if (fork()) exit(0); setsid(); */ #ifndef WIN32 if (chroot_path[0]) { chroot(chroot_path); } #endif if (gid >= 0) setregid(gid, gid); if (uid >= 0) { setreuid(uid, uid); if (getuid() != uid) { fprintf(stderr, "Can't setuid to %d, received %d\n", uid, getuid()); exit(1); } } chdir(pwd); #endif dup2(pipe_fds[1], 1); dup2(pipe_fds[1], 2); for (i = 0; envp[i]; i++) putenv(envp[i]); execvp(argv[0], argv); fprintf(stderr, "exec failed %s -> %d\n", argv[0], errno); exit(1); return -1; }
JNIEXPORT jint JNICALL Java_com_caucho_server_boot_ResinBoot_execDaemon(JNIEnv *env, jobject obj, jobjectArray j_argv, jobjectArray j_envp, jstring j_pwd) { char **argv; char **envp; char *pwd; int len; int i; if (! j_argv) resin_printf_exception(env, "java/lang/NullPointerException", "argv"); if (! j_envp) resin_printf_exception(env, "java/lang/NullPointerException", "argv"); if (! j_pwd) resin_printf_exception(env, "java/lang/NullPointerException", "pwd"); #ifdef WIN32 resin_printf_exception(env, "java/lang/UnsupportedOperationException", "win32"); #else len = (*env)->GetArrayLength(env, j_argv); argv = malloc((len + 1) * sizeof(char*)); argv[len] = 0; for (i = 0; i < len; i++) { jstring j_string; j_string = (*env)->GetObjectArrayElement(env, j_argv, i); if (j_string) { int strlen = (*env)->GetStringUTFLength(env, j_string); argv[i] = (char *) malloc(strlen + 1); argv[i] = get_utf8(env, j_string, argv[i], strlen + 1); } } len = (*env)->GetArrayLength(env, j_envp); envp = malloc((len + 1) * sizeof(char*)); envp[len] = 0; for (i = 0; i < len; i++) { jstring j_string; j_string = (*env)->GetObjectArrayElement(env, j_envp, i); if (j_string) { int strlen = (*env)->GetStringUTFLength(env, j_string); envp[i] = (char *) malloc(strlen + 1); envp[i] = get_utf8(env, j_string, envp[i], strlen + 1); } } { int strlen = (*env)->GetStringUTFLength(env, j_pwd); char *pwd; pwd = (char *) malloc(strlen + 1); pwd = get_utf8(env, j_pwd, pwd, strlen + 1); chdir(pwd); } if (fork()) return 1; if (fork()) exit(0); #ifndef WIN32 setsid(); #endif /* WIN32 */ execve(argv[0], argv, envp); fprintf(stderr, "exec failed %s -> %d\n", argv[0], errno); exit(1); #endif return -1; }