+/*----- Messing with file descriptors -------------------------------------*/
+
+static void fdguts(JNIEnv *jni, jclass *cls, jfieldID *fid)
+{
+ *cls = (*jni)->FindClass(jni, "java/io/FileDescriptor"); assert(cls);
+ *fid = (*jni)->GetFieldID(jni, *cls, "fd", "I"); // OpenJDK
+ if (!*fid) *fid = (*jni)->GetFieldID(jni, *cls, "descriptor", "I"); // Android
+ assert(*fid);
+}
+
+static int fdint(JNIEnv *jni, jobject jfd)
+{
+ jclass cls;
+ jfieldID fid;
+
+ fdguts(jni, &cls, &fid);
+ return ((*jni)->GetIntField(jni, jfd, fid));
+}
+
+static jobject newfd(JNIEnv *jni, int fd)
+{
+ jobject jfd;
+ jclass cls;
+ jmethodID init;
+ jfieldID fid;
+
+ fdguts(jni, &cls, &fid);
+ init = (*jni)->GetMethodID(jni, cls, "<init>", "()V"); assert(init);
+ jfd = (*jni)->NewObject(jni, cls, init);
+ (*jni)->SetIntField(jni, jfd, fid, fd);
+ return (jfd);
+}
+
+JNIEXPORT jint JNIFUNC(fdint)(JNIEnv *jni, jobject cls, jobject jfd)
+ { return (fdint(jni, jfd)); }
+
+JNIEXPORT jobject JNIFUNC(newfd)(JNIEnv *jni, jobject cls, jint fd)
+ { return (newfd(jni, fd)); }
+
+JNIEXPORT jboolean JNIFUNC(isatty)(JNIEnv *jni, jobject cls, jobject jfd)
+ { return (isatty(fdint(jni, jfd))); }
+