| /* |
| Copyright 2003 by Marc J. Rochkind. All rights reserved. |
| May be copied only for purposes and under conditions described |
| on the Web page www.basepath.com/aup/copyright.htm. |
| |
| The Example Files are provided "as is," without any warranty; |
| without even the implied warranty of merchantability or fitness |
| for a particular purpose. The author and his publisher are not |
| responsible for any damages, direct or incidental, resulting |
| from the use or non-use of these Example Files. |
| |
| The Example Files may contain defects, and some contain deliberate |
| coding mistakes that were included for educational reasons. |
| You are responsible for determining if and how the Example Files |
| are to be used. |
| |
| */ |
| #ifdef SOLARIS |
| // needed for setegid and seteuid |
| #define __EXTENSIONS__ |
| #endif |
| |
| /* |
| Need to prevent GNU from using the wrong prototype for functions declared in |
| sys/resource.h (see comment there). As sys/wait.h (included by defs.h) brings |
| in this include (on GNU systems, anyway), there is a special symbol (AUP2_SKIP_WAIT) |
| used in defs.h to suppress that include. Also, we should not have to undef __USE_GNU |
| (I think), we seem to have to do that as well. |
| |
| (It would have been much better if the GNU folks had not tried to improve things!) |
| */ |
| |
| #define AUP2_SKIP_WAIT |
| #include "defs.h" |
| |
| #ifdef _GNU_SOURCE |
| #define _GNU_SOURCE_WAS_DEFINED |
| #undef _GNU_SOURCE |
| #undef __USE_GNU |
| #endif |
| #include <sys/resource.h> |
| #ifdef _GNU_SOURCE_WAS_DEFINED |
| #define _GNU_SOURCE |
| #undef _GNU_SOURCE_WAS_DEFINED |
| #endif |
| |
| #include <sys/wait.h> // now it is OK to bring it in |
| #include <sys/times.h> |
| #include <pthread.h> |
| #include "JtuxProcess.h" // generated by javah |
| #include "JtuxProcess$sigset_t.h" // generated by javah |
| #include "jtux_util.h" |
| #include "JNI_macros.h" |
| |
| static long get_max_pathname(const char *path) |
| { |
| long max_path; |
| errno = 0; |
| max_path = pathconf(path, _PC_PATH_MAX); |
| if (max_path == -1) { |
| if (errno == 0) |
| max_path = 4096; /* guess */ |
| else |
| max_path = 4096; /* bury the error -- return guess here, too */ |
| } |
| return max_path + 1; |
| } |
| |
| JNIEXPORT jint JNICALL Java_jtux_UProcess_00024sigset_1t_GetSize_1sigset_1t(JNIEnv *env, jclass obj) |
| { |
| |
| return sizeof(sigset_t); |
| } |
| |
| #if 0 // all obsolete -- get rid of this stuff |
| static jbyteArray get_bytearray_sigset(JNIEnv *env, jclass obj) |
| { |
| jclass sigset_t_class = (*env)->FindClass(env, "jtux/UProcess$sigset_t"); |
| jfieldID fid; |
| |
| if (sigset_t_class == NULL) |
| return NULL; |
| if ((fid = (*env)->GetFieldID(env, sigset_t_class, "set", "[B")) == NULL) |
| return NULL; |
| return (*env)->GetObjectField(env, obj, fid); |
| } |
| |
| static bool get_sigset(JNIEnv *env, jclass obj, sigset_t *set) |
| { |
| jbyteArray bytes = get_bytearray_sigset(env, obj); |
| |
| if (bytes == NULL) |
| return false; |
| (*env)->GetByteArrayRegion(env, bytes, 0, sizeof(sigset_t), (jbyte *)set); |
| return true; |
| } |
| |
| static bool set_sigset(JNIEnv *env, jclass obj, sigset_t *set) |
| { |
| jbyteArray bytes = get_bytearray_sigset(env, obj); |
| |
| if (bytes == NULL) |
| return false; |
| (*env)->SetByteArrayRegion(env, bytes, 0, sizeof(sigset_t), (jbyte *)set); |
| return true; |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_00024sigset_1t_sigaddset(JNIEnv *env, jclass obj, |
| jint signum) |
| { |
| sigset_t set; |
| |
| if (!get_sigset(env, obj, &set)) |
| return; |
| JTHROW_neg1(sigaddset(&set, signum)) |
| (void)set_sigset(env, obj, &set); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_00024sigset_1t_sigdelset(JNIEnv *env, jclass obj, |
| jint signum) |
| { |
| sigset_t set; |
| |
| if (!get_sigset(env, obj, &set)) |
| return; |
| JTHROW_neg1(sigdelset(&set, signum)) |
| (void)set_sigset(env, obj, &set); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_00024sigset_1t_sigemptyset(JNIEnv *env, jclass obj) |
| { |
| sigset_t set; |
| |
| if (!get_sigset(env, obj, &set)) |
| return; |
| JTHROW_neg1(sigemptyset(&set)) |
| (void)set_sigset(env, obj, &set); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_00024sigset_1t_sigfillset(JNIEnv *env, jclass obj) |
| { |
| sigset_t set; |
| |
| if (!get_sigset(env, obj, &set)) |
| return; |
| JTHROW_neg1(sigfillset(&set)) |
| (void)set_sigset(env, obj, &set); |
| } |
| |
| JNIEXPORT jboolean JNICALL Java_jtux_UProcess_00024sigset_1t_sigismember(JNIEnv *env, jclass obj, |
| jint signum) |
| { |
| sigset_t set; |
| int r; |
| |
| if (!get_sigset(env, obj, &set)) |
| return; |
| JTHROW_neg1(r = sigismember(&set, signum)) |
| return r != 0; |
| } |
| #endif// all obsolete -- get rid of this stuff |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_abort(JNIEnv *env, jclass obj) |
| { |
| abort(); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_chdir(JNIEnv *env, jclass obj, jstring s) |
| { |
| JSTR_GET_DECL(s_c, s) |
| |
| JSTR_NULLTEST(s_c) |
| JTHROW_neg1(chdir(s_c)) |
| JSTR_REL(s_c, s) |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_chroot(JNIEnv *env, jclass obj, jstring s) |
| { |
| JSTR_GET_DECL(s_c, s) |
| |
| JSTR_NULLTEST(s_c) |
| JTHROW_neg1(chroot(s_c)) |
| JSTR_REL(s_c, s) |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_clock(JNIEnv *env, jclass obj) |
| { |
| clock_t c; |
| |
| errno = 0; // because SUS doesn't say it's set |
| JTHROW_neg1(c = clock()) |
| return c; |
| } |
| |
| /** |
| Calls ::clock. |
| */ |
| /* static clock_t UProcess::clock(void) |
| { |
| clock_t c; |
| |
| errno = 0; |
| if ((c = ::clock()) == -1) { |
| if (errno == 0) |
| throw Error(EINVAL); |
| else |
| throw Error(errno); |
| } |
| return c; |
| }*/ |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_execvp(JNIEnv *env, jclass obj, jstring s, jobjectArray a) |
| { |
| JSTR_GET_DECL(s_c, s) |
| const char **argv = NULL; |
| int i, argc; |
| jsize array_size = (*env)->GetArrayLength(env, a); |
| jobject arg; |
| |
| JSTR_NULLTEST(s_c) |
| for (argc = 0; argc < array_size && (*env)->GetObjectArrayElement(env, a, argc) != NULL; argc++) |
| ; |
| argv = malloc((argc + 1) * sizeof(char *)); |
| if (argv == NULL) { |
| (void)setup_throw_errno(env, errno); |
| return; |
| } |
| for (i = 0; i < argc; i++) { |
| arg = (*env)->GetObjectArrayElement(env, a, i); |
| if ((*env)->ExceptionCheck(env)) { // why isn't this a check on arg == NULL? |
| free(argv); |
| JSTR_REL(s_c, s) |
| return; |
| } |
| argv[i] = (*env)->GetStringUTFChars(env, arg, NULL); |
| } |
| argv[i] = NULL; |
| JTHROW_neg1(execvp(s_c, (char **)argv)) |
| /* |
| Release arguments only when execvp fails |
| ************ Code is suspect -- jython complains! |
| */ |
| for (i = 0; i < argc; i++) |
| JSTR_REL(argv[i], (*env)->GetObjectArrayElement(env, a, i)) |
| JSTR_REL(s_c, s) |
| free(argv); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_exit(JNIEnv *env, jclass obj, jint n) |
| { |
| exit(n); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess__1exit(JNIEnv *env, jclass obj, jint n) |
| { |
| _exit(n); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_fchdir(JNIEnv *env, jclass obj, jint n) |
| { |
| JTHROW_neg1(fchdir(n)) |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_fork(JNIEnv *env, jclass obj) |
| { |
| jlong n; |
| JavaVM *vm; |
| |
| (void)(*env)->GetJavaVM(env, &vm); |
| JTHROW_neg1(n = fork()) |
| if (n == 0) { |
| JNIEnv *envnew; // not clear what to do with this |
| (void)(*vm)->AttachCurrentThread(vm, (void **)&envnew, NULL); |
| } |
| return n; |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_getcwd(JNIEnv *env, jclass obj, jobject path) |
| { |
| char *pathbuf, *r; |
| long maxpath; |
| |
| JTHROW_null(pathbuf = malloc(maxpath = get_max_pathname("."))) |
| if (pathbuf == NULL) |
| return; |
| JTHROW_null(r = getcwd(pathbuf, maxpath)) |
| if (r != NULL) |
| (void)string_buffer_set(env, path, pathbuf); |
| free(pathbuf); |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_getegid(JNIEnv *env, jclass obj) |
| { |
| return getegid(); |
| } |
| |
| JNIEXPORT jstring JNICALL Java_jtux_UProcess_getenv(JNIEnv *env, jclass obj, jstring s) |
| { |
| JSTR_GET_DECL(s_c, s) |
| char *r = NULL; |
| |
| JSTR_NULLTEST_V(s_c, NULL) |
| r = getenv(s_c); |
| JSTR_REL(s_c, s) |
| JSTR_RETURN(r) |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_geteuid(JNIEnv *env, jclass obj) |
| { |
| return geteuid(); |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_getgid(JNIEnv *env, jclass obj) |
| { |
| return getgid(); |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_getpgid(JNIEnv *env, jclass obj, jlong pid) |
| { |
| long r; |
| |
| JTHROW_neg1(r = getpgid(pid)) |
| return r; |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_getpid(JNIEnv *env, jclass obj) |
| { |
| return getpid(); |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_getppid(JNIEnv *env, jclass obj) |
| { |
| return getppid(); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_getrlimit(JNIEnv *env, jclass obj, |
| jint resource, jobject rl) |
| { |
| struct rlimit rlim; |
| jclass rlclass = (*env)->FindClass(env, "jtux/UProcess$s_rlimit"); |
| jfieldID fid; |
| |
| if (rlclass == NULL) |
| return; |
| JTHROW_neg1(getrlimit(resource, &rlim)) |
| if ((*env)->ExceptionCheck(env)) |
| return; |
| if ((fid = (*env)->GetFieldID(env, rlclass, "rlim_cur", "J")) == NULL) |
| return; |
| (*env)->SetLongField(env, rl, fid, rlim.rlim_cur); |
| if ((fid = (*env)->GetFieldID(env, rlclass, "rlim_max", "J")) == NULL) |
| return; |
| (*env)->SetLongField(env, rl, fid, rlim.rlim_max); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_getrusage(JNIEnv *env, jclass obj, |
| jint who, jobject r_usage) |
| { |
| struct rusage ru; |
| jclass ruclass = (*env)->FindClass(env, "jtux/UProcess$s_rusage"); |
| jclass tmsclass; |
| jfieldID fid, fid_tv_sec, fid_tv_usec; |
| jobject objtms; |
| |
| if (ruclass == NULL) |
| return; |
| JTHROW_neg1(getrusage(who, &ru)) |
| if ((*env)->ExceptionCheck(env)) |
| return; |
| if ((tmsclass = (*env)->FindClass(env, "jtux/UProcess$s_timeval")) == NULL) |
| return; |
| if ((fid_tv_sec = (*env)->GetFieldID(env, tmsclass, "tv_sec", "J")) == NULL) |
| return; |
| if ((fid_tv_usec = (*env)->GetFieldID(env, tmsclass, "tv_usec", "J")) == NULL) |
| return; |
| // set ru_utime |
| if ((fid = (*env)->GetFieldID(env, ruclass, "ru_utime", "Ljtux/UProcess$s_timeval;")) |
| == NULL) |
| return; |
| if ((objtms = (*env)->GetObjectField(env, r_usage, fid)) == NULL) |
| return; |
| (*env)->SetLongField(env, objtms, fid_tv_sec, ru.ru_utime.tv_sec); |
| (*env)->SetLongField(env, objtms, fid_tv_usec, ru.ru_utime.tv_usec); |
| // set ru_stime |
| if ((fid = (*env)->GetFieldID(env, ruclass, "ru_stime", "Ljtux/UProcess$s_timeval;")) |
| == NULL) |
| return; |
| if ((objtms = (*env)->GetObjectField(env, r_usage, fid)) == NULL) |
| return; |
| (*env)->SetLongField(env, objtms, fid_tv_sec, ru.ru_stime.tv_sec); |
| (*env)->SetLongField(env, objtms, fid_tv_usec, ru.ru_stime.tv_usec); |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_getsid(JNIEnv *env, jclass obj, jlong pid) |
| { |
| long r; |
| |
| JTHROW_neg1(r = getsid(pid)) |
| return r; |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_getuid(JNIEnv *env, jclass obj) |
| { |
| return getuid(); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_kill(JNIEnv *env, jclass obj, jlong pid, jlong signum) |
| { |
| JTHROW_neg1(kill(pid, (int)signum)) |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_nice(JNIEnv *env, jclass obj, jint incr) |
| { |
| JTHROW_neg1(nice(incr)) |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_pause(JNIEnv *env, jclass obj) |
| { |
| JTHROW_neg1(pause()); |
| } |
| |
| /* |
| See comment for sigprocmask. |
| */ |
| JNIEXPORT void JNICALL Java_jtux_UProcess_pthread_1sigmask(JNIEnv *env, jclass obj, jint how, |
| jobject set, jobject oset) |
| { |
| (void)setup_throw_errno(env, ENOSYS); |
| #if 0 // not redone for new sigset_t approach |
| sigset_t set_c, oset_c; |
| |
| if (get_sigset(env, set, &set_c)) { |
| JTHROW_rv(pthread_sigmask(how, &set_c, &oset_c)) |
| if (!(*env)->ExceptionCheck(env) && oset != NULL) |
| (void)set_sigset(env, oset, &oset_c); |
| } |
| #endif |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_putenv(JNIEnv *env, jclass obj, |
| jstring string) |
| { |
| JSTR_GET_DECL(string_c, string) |
| |
| JSTR_NULLTEST(string_c) |
| JTHROW_nzero(putenv((char *)string_c)) |
| // Do not release string_c -- it is now in the environment |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_setenv(JNIEnv *env, jclass obj, |
| jstring var, jstring val, jboolean overwrite) |
| { |
| #if _XOPEN_VERSION >= 600 || defined(LINUX) || defined(FREEBSD) |
| JSTR_GET_DECL(var_c, var) |
| JSTR_GET_DECL(val_c, val) |
| |
| JSTR_NULLTEST(var_c) |
| JSTR_NULLTEST(val_c) |
| JTHROW_neg1(setenv(var_c, val_c, overwrite)) |
| JSTR_REL(var_c, var) |
| JSTR_REL(var_c, val) |
| #else |
| (void)setup_throw_errno(env, ENOSYS); |
| #endif |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_setegid(JNIEnv *env, jclass obj, jlong gid) |
| { |
| JTHROW_neg1(setegid(gid)) |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_seteuid(JNIEnv *env, jclass obj, jlong uid) |
| { |
| JTHROW_neg1(seteuid(uid)) |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_setgid(JNIEnv *env, jclass obj, jlong gid) |
| { |
| JTHROW_neg1(setgid(gid)) |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_setpgid(JNIEnv *env, jclass obj, jlong pid, jlong pgid) |
| { |
| JTHROW_neg1(setpgid(pid, pgid)) |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_setrlimit(JNIEnv *env, jclass obj, |
| jint resource, jobject rl) |
| { |
| struct rlimit rlim; |
| jclass rlclass = (*env)->FindClass(env, "jtux/UProcess$s_rlimit"); |
| jfieldID fid; |
| |
| if (rlclass == NULL) |
| return; |
| if ((fid = (*env)->GetFieldID(env, rlclass, "rlim_cur", "J")) == NULL) |
| return; |
| rlim.rlim_cur = (*env)->GetLongField(env, rl, fid); |
| if ((fid = (*env)->GetFieldID(env, rlclass, "rlim_max", "J")) == NULL) |
| return; |
| rlim.rlim_max = (*env)->GetLongField(env, rl, fid); |
| JTHROW_neg1(setrlimit(resource, &rlim)) |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_setsid(JNIEnv *env, jclass obj) |
| { |
| long r; |
| |
| JTHROW_neg1(r = setsid()) |
| return r; |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_setuid(JNIEnv *env, jclass obj, jlong uid) |
| { |
| JTHROW_neg1(setuid(uid)) |
| } |
| |
| JNIEXPORT jint JNICALL Java_jtux_UProcess_sig_1get_1SIGRTMIN(JNIEnv *env, jclass obj) |
| { |
| return SIGRTMIN; |
| } |
| |
| JNIEXPORT jint JNICALL Java_jtux_UProcess_sig_1get_1SIGRTMAX(JNIEnv *env, jclass obj) |
| { |
| return SIGRTMAX; |
| } |
| |
| static JavaVM *vm; |
| |
| static void fcn_handler(int signum) |
| { |
| JNIEnv *env; |
| jmethodID mid_sig; |
| jclass Processclass; |
| |
| (void)write(STDOUT_FILENO, "Got signal\n", 11); |
| if ((*vm)->AttachCurrentThread(vm, (void **)&env, NULL) == 0) { |
| Processclass = (*env)->FindClass(env, "jtux/UProcess"); |
| if (Processclass == NULL) { |
| return; |
| } |
| mid_sig = (*env)->GetStaticMethodID(env, Processclass, "CatchSignal", "(I)V"); |
| if (mid_sig == NULL) { |
| return; |
| } |
| (*env)->CallStaticVoidMethod(env, Processclass, mid_sig, (jint)signum); |
| } |
| } |
| |
| static void fcn_sigaction(int signum, siginfo_t *info, void *context) |
| { |
| JNIEnv *env; |
| jmethodID mid_sig; |
| jclass cls_Process; |
| |
| (void)write(STDOUT_FILENO, "fcn_sigaction got signal\n", 25); |
| { |
| // Just a test -- not part of the algorithm. |
| JavaVM *jvmbuf[100]; |
| jsize nvms; |
| int i; |
| |
| if (JNI_GetCreatedJavaVMs(jvmbuf, sizeof(jvmbuf), &nvms) == -1) |
| printf("JNI_GetCreatedJavaVMs failed"); |
| for (i = 0; i < nvms; i++) |
| printf("JVM #%d: 0x%lx\n", i, (long)jvmbuf[i]); |
| printf("JVM passed as vm: 0x%lx\n", (long)vm); |
| } |
| if ((*vm)->AttachCurrentThread(vm, (void **)&env, NULL) == 0) { |
| jclass cls_siginfo_t = (*env)->FindClass(env, "jtux/UProcess$siginfo_t"); |
| jclass cls_u_sigval_int = (*env)->FindClass(env, "jtux/UProcess$u_sigval_int"); |
| jmethodID mid; |
| jobject si = NULL, sval; |
| |
| if (cls_u_sigval_int == NULL) { |
| fprintf(stderr, "*** Jtux: fcn_sigaction -- can't get class jtux/UProcess$cls_u_sigval_int\n"); |
| return; |
| } |
| if (cls_siginfo_t == NULL) { |
| fprintf(stderr, "*** Jtux: fcn_sigaction -- can't get class jtux/UProcess$siginfo_t\n"); |
| return; |
| } |
| /* |
| When a NewObject is created in this signal handler, it's passed OK to the |
| Java signal handler, but later in another part of the program a child process |
| waiting on a semaphore (totally unrelated) gets hung up (not even in a |
| sem_wait). This indicates that something is seriously amiss. Until it's |
| solved, this part is disabled so a 3-arg sa_sigaction handler can't get |
| the info argument as anything other than NULL. |
| */ |
| if (info != NULL && false /* temporary disabling*/) { |
| if ((mid = (*env)->GetMethodID(env, cls_siginfo_t, "<init>", "()V")) == NULL) |
| return; |
| if ((si = (*env)->NewObject(env, cls_siginfo_t, mid)) == NULL) |
| return; |
| if ((mid = (*env)->GetMethodID(env, cls_u_sigval_int, "<init>", "()V")) == NULL) |
| return; |
| if ((sval = (*env)->NewObject(env, cls_u_sigval_int, mid)) == NULL) |
| return; |
| if (!field_ctoj_int(env, cls_siginfo_t, "si_signo", si, info->si_signo)) |
| return; |
| if (!field_ctoj_int(env, cls_siginfo_t, "si_errno", si, info->si_errno)) |
| return; |
| if (!field_ctoj_int(env, cls_siginfo_t, "si_code", si, info->si_code)) |
| return; |
| if (!field_ctoj_long(env, cls_siginfo_t, "si_pid", si, info->si_pid)) |
| return; |
| if (!field_ctoj_long(env, cls_siginfo_t, "si_uid", si, info->si_uid)) |
| return; |
| if (!field_ctoj_long(env, cls_siginfo_t, "si_addr", si, (intptr_t)info->si_addr)) |
| return; |
| if (!field_ctoj_int(env, cls_siginfo_t, "si_status", si, info->si_status)) |
| return; |
| if (!field_ctoj_long(env, cls_siginfo_t, "si_band", si, info->si_band)) |
| return; |
| |
| // Always assume int, since there's no way to tell if the ptr member was used |
| // anyway. |
| if (!field_ctoj_int(env, cls_u_sigval_int, "sival_int", sval, info->si_value.sival_int)) |
| return; |
| if (!field_ctoj_object(env, cls_siginfo_t, "si_value", "Ljtux/UProcess$u_sigval;", si, sval)) |
| return; |
| } |
| if ((cls_Process = (*env)->FindClass(env, "jtux/UProcess")) == NULL) |
| return; |
| if ((mid_sig = (*env)->GetStaticMethodID(env, cls_Process, "CatchSignal", "(ILjtux/UProcess$siginfo_t;J)V")) |
| == NULL) |
| return; |
| (*env)->CallStaticVoidMethod(env, cls_Process, mid_sig, (jint)signum, si, (jlong)(intptr_t)context); |
| } |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigaction_1x(JNIEnv *env, jclass obj, jint signum, |
| jobject act, jobject oact) |
| { |
| jclass sclass = (*env)->FindClass(env, "jtux/UProcess$s_sigaction"); |
| struct sigaction sigact; |
| int actiontype; |
| |
| #ifdef WANT_LIST_OF_SIGNALS |
| { |
| int n; |
| |
| for (n = 1; n <= 30; n++) { |
| if (sigaction(n, NULL, &sigact) == -1) |
| continue; |
| if (sigact.sa_handler == SIG_IGN || sigact.sa_handler == SIG_DFL) |
| printf("%s is ignored or defaulted\n", get_macrostr("signal", n, NULL)); |
| else |
| printf("%s is caught\n", get_macrostr("signal", n, NULL)); |
| } |
| } |
| #endif |
| memset(&sigact, 0, sizeof(sigact)); |
| if (!field_jtoc_int(env, sclass, "sa_actiontype", act, &actiontype)) |
| return; |
| if (!field_jtoc_int(env, sclass, "sa_flags", act, &sigact.sa_flags)) |
| return; |
| if (actiontype == (int)SIG_IGN || actiontype == (int)SIG_DFL) |
| sigact.sa_handler = (void (*)(int))actiontype; |
| else if ((sigact.sa_flags & SA_SIGINFO) == SA_SIGINFO) { |
| sigact.sa_sigaction = fcn_sigaction; |
| } |
| else { |
| sigact.sa_handler = fcn_handler; |
| } |
| //pthread_sigmask(SIG_SETMASK, &sigact.sa_mask, NULL); |
| JTHROW_neg1(sigaction(signum, &sigact, NULL)) |
| |
| #if 0 |
| int sa_actiontype; |
| Method sa_handler; |
| sigset_t sa_mask; |
| int sa_flags; |
| #endif |
| if ((*env)->GetJavaVM(env, &vm) < 0) |
| return; |
| |
| |
| #if 0 |
| act.sa_handler = SIG_DFL; |
| JTHROW_neg1(sigaction(SIGQUIT, &act, NULL)) |
| #endif |
| //printf("signals setup\n"); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigaddset(JNIEnv *env, jclass obj, |
| jobject set, jint signum) |
| { |
| jbyteArray ba; |
| jbyte *b = get_sigset(env, set, &ba); |
| |
| if (b != NULL) { |
| JTHROW_neg1(sigaddset((sigset_t *)b, signum)) |
| release_sigset(env, ba, b); |
| } |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigaltstack(JNIEnv *env, jclass obj, |
| jobject stack, jobject ostack) |
| { |
| (void)setup_throw_errno(env, ENOSYS); |
| } |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigdelset(JNIEnv *env, jclass obj, |
| jobject set, jint signum) |
| { |
| jbyteArray ba; |
| jbyte *b = get_sigset(env, set, &ba); |
| |
| if (b != NULL) { |
| JTHROW_neg1(sigdelset((sigset_t *)b, signum)) |
| release_sigset(env, ba, b); |
| } |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigemptyset(JNIEnv *env, jclass obj, |
| jobject set) |
| { |
| jbyteArray ba; |
| jbyte *b = get_sigset(env, set, &ba); |
| |
| if (b != NULL) { |
| JTHROW_neg1(sigemptyset((sigset_t *)b)) |
| release_sigset(env, ba, b); |
| } |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigfillset(JNIEnv *env, jclass obj, |
| jobject set) |
| { |
| jbyteArray ba; |
| jbyte *b = get_sigset(env, set, &ba); |
| |
| if (b != NULL) { |
| JTHROW_neg1(sigfillset((sigset_t *)b)) |
| release_sigset(env, ba, b); |
| } |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_siginterrupt(JNIEnv *env, jclass obj, |
| jint signum, jint on) |
| { |
| (void)setup_throw_errno(env, ENOSYS); |
| } |
| |
| JNIEXPORT jboolean JNICALL Java_jtux_UProcess_sigismember(JNIEnv *env, jclass obj, |
| jobject set, jint signum) |
| { |
| jbyteArray ba; |
| jbyte *b = get_sigset(env, set, &ba); |
| int r = 0; |
| |
| if (b != NULL) { |
| JTHROW_neg1(r = sigismember((sigset_t *)b, signum)) |
| release_sigset(env, ba, b); |
| } |
| return r != 0; |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigpending(JNIEnv *env, jclass obj, jobject set) |
| { |
| jbyteArray ba; |
| jbyte *b = get_sigset(env, set, &ba); |
| |
| if (b != NULL) { |
| JTHROW_neg1(sigpending((sigset_t *)b)) |
| release_sigset(env, ba, b); |
| } |
| } |
| |
| /* |
| Ineffective because of multithreaded JVM environment. Mask affects only thread, but |
| other threads (over which we have no control) with the signal unblocked will still |
| get the signal. |
| */ |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigprocmask(JNIEnv *env, jclass obj, jint how, |
| jobject set, jobject oset) |
| { |
| (void)setup_throw_errno(env, ENOSYS); |
| #if 0 // not redone for new sigset_t approach |
| sigset_t set_c, oset_c; |
| |
| #if 0 |
| { |
| sigset_t s; |
| |
| if (sigemptyset(&s) == -1 || |
| sigaddset(&s, SIGPROF) == -1 || |
| sigprocmask(SIG_SETMASK, &s, NULL) == -1 || |
| kill(getpid(), SIGPROF) == -1) |
| printf("bad sys call in Java_jtux_UProcess_sigprocmask\n"); |
| else |
| printf("^^^^^^^^^^^^^^^^ I am still alive.\n"); |
| } |
| #endif |
| if (get_sigset(env, set, &set_c)) { |
| JTHROW_neg1(sigprocmask(how, &set_c, &oset_c)) |
| if (!(*env)->ExceptionCheck(env) && oset != NULL) |
| (void)set_sigset(env, oset, &oset_c); |
| } |
| #endif |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigqueue(JNIEnv *env, jclass obj, |
| jlong pid, jint signum, jobject value) |
| { |
| (void)setup_throw_errno(env, ENOSYS); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigsuspend(JNIEnv *env, jclass obj, |
| jobject set) |
| { |
| (void)setup_throw_errno(env, ENOSYS); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigtimedwait(JNIEnv *env, jclass obj, |
| jobject set, jobject info, jobject ts) |
| { |
| (void)setup_throw_errno(env, ENOSYS); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigwait(JNIEnv *env, jclass obj, |
| jobject set, jobject signum) |
| { |
| (void)setup_throw_errno(env, ENOSYS); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_sigwaitinfo(JNIEnv *env, jclass obj, |
| jobject set, jobject info) |
| { |
| (void)setup_throw_errno(env, ENOSYS); |
| } |
| |
| JNIEXPORT jint JNICALL Java_jtux_UProcess_system(JNIEnv *env, jclass obj, jstring s) |
| { |
| JSTR_GET_DECL(s_c, s) |
| jint n; |
| |
| JSTR_NULLTEST_V(s_c, -1) |
| JTHROW_neg1(n = system(s_c)) |
| JSTR_REL(s_c, s) |
| return n; |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_times(JNIEnv *env, jclass obj, jobject buffer) |
| { |
| clock_t t; |
| struct tms tbuf; |
| jclass tmsclass = (*env)->FindClass(env, "jtux/UProcess$s_tms"); |
| |
| JTHROW_neg1(t = times(&tbuf)) |
| if (!field_ctoj_long(env, tmsclass, "tms_utime", buffer, tbuf.tms_utime)) |
| return -1; |
| if (!field_ctoj_long(env, tmsclass, "tms_stime", buffer, tbuf.tms_stime)) |
| return -1; |
| if (!field_ctoj_long(env, tmsclass, "tms_cutime", buffer, tbuf.tms_cutime)) |
| return -1; |
| if (!field_ctoj_long(env, tmsclass, "tms_cstime", buffer, tbuf.tms_cstime)) |
| return -1; |
| return t; |
| } |
| |
| JNIEXPORT jint JNICALL Java_jtux_UProcess_umask(JNIEnv *env, jclass obj, |
| jint cmask) |
| { |
| return umask(cmask); |
| } |
| |
| JNIEXPORT void JNICALL Java_jtux_UProcess_unsetenv(JNIEnv *env, jclass obj, |
| jstring var) |
| { |
| #if _XOPEN_VERSION >= 600 || defined(LINUX) || defined(FREEBSD) |
| JSTR_GET_DECL(var_c, var) |
| |
| JSTR_NULLTEST(var_c) |
| JTHROW_neg1(unsetenv(var_c)) |
| JSTR_REL(var_c, var) |
| #else |
| (void)setup_throw_errno(env, ENOSYS); |
| #endif |
| } |
| |
| JNIEXPORT jlong JNICALL Java_jtux_UProcess_waitpid(JNIEnv *env, jclass obj, jlong pid, |
| jobject status, jint options) |
| { |
| pid_t rtn_pid; |
| int status_c; |
| |
| JTHROW_neg1(rtn_pid = waitpid(pid, &status_c, options)) |
| if (rtn_pid == -1) |
| return -1; |
| if (status != NULL) { |
| jclass ExitStatusclass; |
| jmethodID mid; |
| |
| ExitStatusclass = (*env)->GetObjectClass(env, status); |
| if ((mid = (*env)->GetMethodID(env, ExitStatusclass, "set", "(I)V")) == NULL) |
| return -1; |
| (*env)->CallIntMethod(env, status, mid, status_c); |
| } |
| return rtn_pid; |
| } |