⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unixprocess_md.c

📁 This is a resource based on j2me embedded,if you dont understand,you can connection with me .
💻 C
字号:
/* * @(#)UNIXProcess_md.c	1.67 06/10/10 *  * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation.  *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt).  *  * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA  *  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions.  */#include "jni.h"#include "jvm.h"#include "jvm_md.h"#include "jni_util.h"/* * Platform-specific support for java.lang.UNIXProcess */#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <signal.h>#include <string.h>#include <errno.h>#ifndef __solaris__#define fork1 fork#endif#ifdef JDK/* path in the environment */static char **PATH = 0;/* effective uid */static uid_t uid;/* effective group id */static gid_t gid;#else#include "jni_statics.h"#define PATH	JNI_STATIC_MD(java_lang_UNIXProcess, PATH)#define uid	JNI_STATIC_MD(java_lang_UNIXProcess, uid)#define gid	JNI_STATIC_MD(java_lang_UNIXProcess, gid)#endifstatic voidparsePath () {    char *path, *c, *len;    int count = 0;    int i;    /* get uid, gid */    uid = geteuid();    gid = getegid();    if ((path = getenv("PATH")) == 0) {	return;    }    path = strdup(path);    len = path + strlen(path);    /* count path elements */    for (c = path; c < len; c++) {	if (*c == ':')	    count++;    }    PATH = (char **)malloc((++count+1) * sizeof(char*));    /* fill it in */    PATH[0] = path;    PATH[count] = 0;    for (i = 1; i < count; i++) {	c = strchr(path, ':');	if (c == 0) { /* shouldn't happen */	    /*	    jio_fprintf(stderr, "processmd.c: wrong count parsing path: i=%d, count=%d\n", i, count); */	    break;	}	*c++ = 0;	PATH[i] = path = c;    }}/* return 0 if it is executable && readable by this process * -1 if no such file, -2 if it cannot be executed. */static intstatExecutable(char *exe, struct stat *b) {    if (stat(exe, b)) { /* doesn't exist */	return -1;    }    if (S_ISDIR(b->st_mode)) {	/* cannot execute */	return -2;    }    /* check for user permissions */    if (b->st_uid == uid) {	return (b->st_mode & S_IXUSR) ? 0 : -2;    }    /* check for group permissions */    if (b->st_gid == gid) {	return (b->st_mode & S_IXGRP) ? 0 : -2;    }    /* check for world permissions */    return b->st_mode & S_IXOTH ? 0 : -2;}/* Find the command like a shell would. * signal an error for things not executable || not readable || not found. */static char *fullPath(JNIEnv *env, char *part, char *full) {    char **tmp;    struct stat b;    int ret;    /*     * If the filename we want to exec has any slashes in it then     * we shouldn't do a path search, as in /foo ./foo or foo/bar.     */    if ((strchr(part, '/') == NULL) && PATH) {	for (tmp = PATH; *tmp; tmp++) {	    strcpy(full, *tmp);	    /*	     * empty path elements are like '.' so we don't want to append	     * a slash to them.  Otherwise foo becomes /foo.	     */	    if (full[0] != '\0') {		strcat(full, "/");	    }	    strcat(full, part);	    ret = statExecutable(full, &b);	    if (ret == -1) { /* doesn't exist */		continue;	    } else if (ret == -2) { /* can't execute */		continue;    /* bug 4199993 - got to keep searching. */	    } else {		return full;	    }	}    } else if (!(ret = statExecutable(part, &b))) {	/* always copy value to be returned so `part' may always be freed	 * after call (if needed) */	strcpy(full, part);	return full;    } else if (ret == -2) { /* cannot execute */	jio_snprintf(full, MAXPATHLEN, "%s: cannot execute", part);	JNU_ThrowIOException(env, full);	return 0;    }    /* not found if we got here */    jio_snprintf(full, MAXPATHLEN, "%s: not found", part);    JNU_ThrowIOException(env, full);    return 0;}#ifdef JDKstatic jfieldID field_fd = 0;static jfieldID field_exitcode = 0;#else#define field_fd	JNI_STATIC_MD(java_lang_UNIXProcess, field_fd)#define field_exitcode	JNI_STATIC_MD(java_lang_UNIXProcess, field_exitcode)#endifstatic intinitFieldIDs(JNIEnv *env, jobject process, jobject fd) {    jclass tmpC;    if (field_exitcode != 0) return 0;    tmpC = (*env)->GetObjectClass(env, process);;    field_exitcode = (*env)->GetFieldID(env, tmpC, "exitcode", "I");    if (field_exitcode == 0) {	JNU_ThrowInternalError(env, "Can't find field UNIXProcess.exitcode");	return -1;    }    tmpC = (*env)->GetObjectClass(env, fd);    field_fd = (*env)->GetFieldID(env, tmpC, "fd", "I");    if (field_fd == 0) {	JNU_ThrowInternalError(env, "Can't find field FileDescriptor.fd");	field_exitcode = 0;	return -1;    }    return 0;}/* Block until a child process exits and return its exit code.   Note, can only be called once for any given pid. */JNIEXPORT jint JNICALLJava_java_lang_UNIXProcess_waitForProcessExit(JNIEnv* env,					      jobject junk,					      jint pid){    int status = 0;    int info;    int r;    /* Wait for the child process to exit.  This returns immediately if       the child has already exited. */    while ((r = waitpid(pid, &info, 0)) == -1 && errno == EINTR)	continue;    if (r == -1) {        if (errno == ECHILD) {	    /* someone else has waited for the process */	    return 0;	} else {	    return -1;	}    }    if (WIFEXITED(info)) {	/*	 * The child exited normally, get its exit code	 */	status = WEXITSTATUS(info);    } else if (WIFSIGNALED(info)) {	/*	 * The child exited because of a signal,	 * compute its exit code based on the signal number.	 */	 status = 0x80 + WTERMSIG(status);    } else {	/*	 * Unknown exit code, pass it through.	 */	status = info;    }    return status;}int closeDescriptors(){#ifdef NO_PROC_FILESYSTEM    return 0;#else    DIR *dp;    struct dirent *dirp;    char procdir[20];    long desc;    pid_t pid;    if ((pid = getpid()) < 0)        return 0;    sprintf(procdir, "/proc/%d/fd", (int)pid);    close(3); /* to be sure a descriptor is available for opendir */    if ((dp = opendir(procdir)) == NULL)        return 0;    while ((dirp = readdir(dp)) != NULL) {        if (*(dirp->d_name) != '.') { /* first symbol not a dot */            if ((desc = strtol(dirp->d_name, NULL, 10)) > 2 &&                                              desc != dp->dd_fd) {                close(desc);            }        }    }    closedir(dp);    return 1;#endif}JNIEXPORT jint JNICALLJava_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,				       jobject process,				       jobjectArray cmdarray,				       jobjectArray envp,                                       jstring path,				       jobject stdin_fd,				       jobject stdout_fd,				       jobject stderr_fd){    jstring str;    int resultPid = -1;    int fdin[2], fdout[2], fderr[2], k;    char **cmdv, **envv;    int cmdlen, envlen = 0;    char fullpath[MAXPATHLEN+1];    int i, j;    char *cwd = NULL;     if (initFieldIDs(env, process, stdin_fd) != 0)	return -1;    cmdlen = (*env)->GetArrayLength(env, cmdarray);    if (cmdlen == 0) {	JNU_ThrowIllegalArgumentException(env, NULL);	return -1;    }    cmdv = (char **)malloc((cmdlen + 1) * sizeof(char *));    if (cmdv == NULL) {	JNU_ThrowOutOfMemoryError(env, 0);	return -1;    }    cmdv[cmdlen] = NULL;    for (i = 0; i < cmdlen; ++i) {	str = (*env)->GetObjectArrayElement(env, cmdarray, i);	if (str == 0) {	    JNU_ThrowNullPointerException(env, NULL);	    for (j = 0; j < i; ++j) free(cmdv[j]);	    goto cleanup1;	}	cmdv[i] = (char *) JNU_GetStringPlatformChars(env, str, NULL);	if (cmdv[i] == NULL) {	    for (j = 0; j < i; ++j) free(cmdv[j]);	    goto cleanup1;	}    }    if (PATH == 0) {	parsePath();    }    if (fullPath(env, cmdv[0], fullpath) == NULL) {	/* fullPath has signalled an exception so we just return */	free(cmdv[0]);	goto cleanup2;    }    free(cmdv[0]);    cmdv[0] = fullpath;    if (0 != envp) {	envlen = (*env)->GetArrayLength(env, envp);    }    envv = (char **)malloc((envlen+1) * sizeof(char *));    if (envv == NULL) {	JNU_ThrowOutOfMemoryError(env, 0);	goto cleanup2;    }    envv[envlen] = NULL;    if (envlen != 0) {	for (i = 0; i < envlen; ++i) {	    str = (*env)->GetObjectArrayElement(env, envp, i);	    if (str == 0) {		JNU_ThrowNullPointerException(env, NULL);		for (j = 0; j < i; ++j) free(envv[j]);		goto cleanup3;	    }	    envv[i] = (char *) JNU_GetStringPlatformChars(env, str, NULL);	    if (envv[i] == NULL) {		for (j = 0; j < i; ++j) free(envv[j]);		goto cleanup3; 	    }	}    }    if ((k=0, pipe(fdin)<0) || (k=1, pipe(fdout)<0) || (k=2, pipe(fderr)<0)) {	char errmsg[128];        sprintf(errmsg, "errno: %d, error: %s\n", errno, "Bad file descriptor");        JNU_ThrowIOExceptionWithLastError(env, errmsg);	/* make sure we clean up */	switch (k) {	case 2:	close(fdout[0]);		close(fdout[1]);	case 1:	close(fdin[0]);		close(fdin[1]);	case 0: ;	}	goto cleanup4;    }    /*     * Can't do this after the fork1 in child, because child can deadlock     * on locks if they are held in parent     */    if (path != NULL) {        cwd = (char *)JNU_GetStringPlatformChars(env, path, NULL);    }     resultPid = fork1();    if (resultPid < 0) {	char errmsg[128];        sprintf(errmsg, "errno: %d, error: %s\n", errno, "Fork failed");        JNU_ThrowIOExceptionWithLastError(env, errmsg);	/* make sure we clean up our side of the pipes */	close(fdin[1]);	close(fdout[0]);	close(fderr[0]);	goto cleanup5;    }    if (resultPid == 0) {	/* Child process */	int i, max_fd;	/* 0 open for reading, 1 open for writing */	/* (Note: it is possible for fdin[0] == 0 - 4180429) */	dup2(fdin[0], 0);	dup2(fdout[1], 1);	dup2(fderr[1], 2);	/* Close pipe fds here since they don't always show up	 * in /proc/<pid>/fd	 */	 if (fdin[0] > 2)	     close(fdin[0]);	 if (fdout[1] > 2)	     close(fdout[1]);	 if (fderr[1] > 2)	     close(fderr[1]);        /* close everything */        if (closeDescriptors() == 0) { /* failed,  close the old way */            max_fd = (int)sysconf(_SC_OPEN_MAX);            for (i = 3; i < max_fd; i++) close(i);        }        /* change to the new cwd */        if (cwd != NULL) {            if (chdir(cwd) < 0) {                /* failed to change directory, cleanup */                char errmsg[128];                sprintf(errmsg, "errno: %d, error: %s\n", errno, "Failed to change directory");                JNU_ThrowByNameWithLastError(env, "java/io/IOException", errmsg);                goto cleanup5;            }        }#ifdef __solaris__#define environ _environ#endif	if (0 != envp) {	    /* So why isn't there an execvpe(), then? */	    extern char **environ;	    environ = envv;	} 	execvp(cmdv[0], cmdv);	_exit(-1);    }    /* parent process */    if (cwd != NULL)        JNU_ReleaseStringPlatformChars(env, path, cwd);            (*env)->SetIntField(env, stdin_fd, field_fd, fdin[1]);    (*env)->SetIntField(env, stdout_fd, field_fd, fdout[0]);    (*env)->SetIntField(env, stderr_fd, field_fd, fderr[0]); cleanup5:    /* clean up the child's side of the pipes */    close(fdin[0]);    close(fdout[1]);    close(fderr[1]); cleanup4:    for (j = 0; j < envlen; ++j) free(envv[j]); cleanup3:    free(envv); cleanup2:    for (j = 1; j < cmdlen; ++j) free(cmdv[j]); cleanup1:    free(cmdv);    return resultPid;}JNIEXPORT void JNICALLJava_java_lang_UNIXProcess_destroyProcess(JNIEnv *env, jobject junk, jint pid) {    kill(pid, SIGTERM);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -