From owner-freebsd-hackers Sun Mar 2 08:40:20 1997 Return-Path: Received: (from root@localhost) by freefall.freebsd.org (8.8.5/8.8.5) id IAA20353 for hackers-outgoing; Sun, 2 Mar 1997 08:40:20 -0800 (PST) Received: from obiwan.aceonline.com.au (obiwan.aceonline.com.au [203.103.90.67]) by freefall.freebsd.org (8.8.5/8.8.5) with ESMTP id IAA20302 for ; Sun, 2 Mar 1997 08:39:17 -0800 (PST) Received: from localhost (adrian@localhost) by obiwan.aceonline.com.au (8.8.5/8.8.5) with SMTP id GAA00256 for ; Mon, 3 Mar 1997 06:42:05 +0800 (WST) Date: Mon, 3 Mar 1997 06:42:04 +0800 (WST) From: Adrian Chadd To: freebsd-hackers@freebsd.org Subject: Re : java support under FreeBSD - test code. Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-hackers@freebsd.org X-Loop: FreeBSD.org Precedence: bulk OK guys - here is the magic file. Stick it under /usr/src/sys/kern/imgact_java.c, and do these two steps : 1) edit /usr/src/sys/conf/files and add under the other imgact_* stuff and add this : kern/imgact_java.c optional java 2) then add in your kernel config file : pseudo-device java # Exec java binaries Recompile, and voila :) Test java support. You'll see three new sysctl variables : kern.java.interpreter kern.java.appletviewer kern.java.classpath The first two are obvious, the third is the location of classes.zip. Note - it MUST be the path to the BINARY java interpreter, not a shell script (why bother with the wrappers anyway?) Set them to wherever your jdk is installed. Now note a couple of things with the source. First - don't blame me that its ugly, cause it is :) Second - don't blame me that its mostly other stuff from the source tree put together, cause it is (thanks bigtime to David Greenman for such a nicely-written imgact_shell.c file which I based a lot of this on :) Third - There are three "library" routines in there, two are modified source from the respective shell commands, and the third is the source for strstr from the libc tree. But since I liked the idea of this being a one-file addon to the kernel during trials, I left them in there instead of moving them to libkern (which I think they should be). Fourth - it doesn't support applets, yet. It doesn't look that much more harder to do, but this is the big thing to get out of the way first. Another thing I've noticed - when I use a small C replacement to print the arguements passed to the java interpreter, I now can see the "full" set of arguements, but when I run the java interpreter, ps only shows : (java) Any ideas on that? (running the java interpreter from the cmd line exhibits the same problem, so it doesn't look like a fault in my coding). Anyway, feel free to find bugs in my code, and suggest large-scale improvements. Cya. Adrian Chadd -- Begin code (/usr/src/sys/kern/imgact_java.c) /* Insert favourite copyright notice / disclaimer here */ #include #include #include #include #include #include #include #include #include #include /* Lets set up reasonable defaults for the system variables ** kern.java.interpreter and kern.java.appletviewer */ static char interpreter[256] = "/usr/local/java/bin/java"; static char appletviewer[256] = "/usr/local/java/bin/appletviewer"; static char classpath[256] = "/usr/local/java/classes.zip"; SYSCTL_NODE(_kern, OID_AUTO, java, CTLFLAG_RW, 0, "Kernel Java support"); SYSCTL_STRING(_kern_java, OID_AUTO, interpreter, CTLFLAG_RW, interpreter, sizeof(interpreter), "Path to Java interpreter"); SYSCTL_STRING(_kern_java, OID_AUTO, appletviewer, CTLFLAG_RW, appletviewer, sizeof(appletviewer), "Path to Java appletviewer"); SYSCTL_STRING(_kern_java, OID_AUTO, classpath, CTLFLAG_RW, classpath, sizeof(classpath), "Path to Java classes"); extern int exec_java_imgact __P((struct image_params *iparams)); int dirname(const char *, char *, int); int basename(const char *, char *, int); char * strstr(const char *, const char *); /* Some utility crap */ int dirname(const char *string, char *newstring, int maxlen) { char *p; int ch; char str[256]; strncpy(str, string, 250); str[250] = '\0'; /* * (1) If string is //, skip steps (2) through (5). * (2) If string consists entirely of slash characters, string * shall be set to a single slash character. In this case, * skip steps (3) through (8). */ for (p = str;; ++p) { if (!*p) { if (p > str) (void)strcpy(newstring, "/"); else (void)strcpy(newstring, "."); return(0); } if (*p != '/') break; } /* * (3) If there are any trailing slash characters in string, they * shall be removed. */ for (; *p; ++p); while (*--p == '/') continue; *++p = '\0'; /* * (4) If there are no slash characters remaining in string, * string shall be set to a single period character. In this * case skip steps (5) through (8). * * (5) If there are any trailing nonslash characters in string, * they shall be removed. */ while (--p >= str) if (*p == '/') break; ++p; if (p == str) { (void)strcpy(newstring, "."); return(0); } /* * (6) If the remaining string is //, it is implementation defined * whether steps (7) and (8) are skipped or processed. * * This case has already been handled, as part of steps (1) and (2). */ /* * (7) If there are any trailing slash characters in string, they * shall be removed. */ while (--p >= str) if (*p != '/') break; ++p; /* * (8) If the remaining string is empty, string shall be set to * a single slash character. */ *p = '\0'; if (p == str) { strcpy(newstring, "/"); } else { strncpy(newstring, str, maxlen); newstring[maxlen] = '\0'; } return(0); } int basename(const char *string, char *newstring, int maxlen) { int ch; char *p; char str[256]; strncpy(str, string, 250); str[250] = '\0'; /* * (1) If string is // it is implementation defined whether steps (2) * through (5) are skipped or processed. * * (2) If string consists entirely of slash characters, string shall * be set to a single slash character. In this case, skip steps * (3) through (5). */ for (p = str;; ++p) { if (!*p) { if (p > str) (void)strcpy(newstring, "/"); else (void)strcpy(newstring, ""); return(0); } if (*p != '/') break; } /* * (3) If there are any trailing slash characters in string, they * shall be removed. */ for (; *p; ++p) continue; while (*--p == '/') continue; *++p = '\0'; /* * (4) If there are any slash characters remaining in string, the * prefix of string up to an including the last slash character * in string shall be removed. */ while (--p >= str) if (*p == '/') break; ++p; /* * (5) If the suffix operand is present, is not identical to the * characters remaining in string, and is identical to a suffix * of the characters remaining in string, the suffix suffix * shall be removed from string. */ if (++*str) { int suffixlen, stringlen, off; suffixlen = strlen(str); stringlen = strlen(p); if (suffixlen < stringlen) { off = stringlen - suffixlen; if (!strcmp(p + off, str)) p[off] = '\0'; } } (void)strncpy(newstring, p, maxlen); return(0); } /* * Find the first occurrence of find in s. */ char * strstr(s, find) register const char *s, *find; { register char c, sc; register size_t len; if ((c = *find++) != 0) { len = strlen(find); do { do { if ((sc = *s++) == 0) return (NULL); } while (sc != c); } while (strncmp(s, find, len) != 0); s--; } return ((char *)s); } /* The real thing */ int exec_java_imgact(imgp) struct image_params *imgp; { const char *image_header = imgp->image_header; const char *ihp, *line_endp; char *interp; static char javabin_name[256]; static char javabin_path[256]; static char cpathstr[256]; static char javatmp[256]; /* A java binary? */ if ((image_header[0] != '\xca') || (image_header[1] != '\xfe') || (image_header[2] != '\xba') || (image_header[3] != '\xbe')) { printf("Failed to run a java binary : invalid signature?\n"); return(-1); } /* Ok, its a java binary, so lets tell the world */ /* Firstly split the path to the binary up into path and filename */ basename(imgp->uap->fname, javabin_name, sizeof(javabin_name)); dirname(imgp->uap->fname, javabin_path, sizeof(javabin_path)); /* Now we are going to take the filename, and if it doesn't contain ** a .class then return with a "non-executable" error */ if (strstr(javabin_name, ".class") == NULL) { return -1; } /* Ok so we'll assume (stupidly) that the .class is at the end of the ** filename, so lets copy the filename over minus the last 6 chars */ strncpy(javatmp, javabin_name, strlen(javabin_name) - 6); strcpy(javabin_name, javatmp); /* Since its interpreted we'll tag it as such. */ imgp->interpreted = 1; /* And we'll set the interpreter name here too (would help) */ strncpy(imgp->interpreter_name, interpreter, sizeof(imgp->interpreter_name)); /* now lets make up our -classpath arguement */ sprintf(cpathstr, "%s -classpath %s:%s", interpreter, classpath, javabin_path); /* Now lets write this into the strings space, just like in the ** _shell.c file... */ ihp = cpathstr; line_endp = cpathstr + strlen(cpathstr); while (ihp < line_endp) { while ((*ihp == ' ') || (*ihp == '\t')) ihp++; if (ihp < line_endp) { while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t')) { *imgp->stringp++ = *ihp++; imgp->stringspace--; } *imgp->stringp++ = 0; imgp->stringspace--; imgp->argc++; } } strcpy(imgp->uap->fname, javabin_name); suword(imgp->uap->argv, (int)imgp->uap->fname); printf("fname : %s\n", imgp->uap->fname); return (0); } /* * Tell kern_execve.c about it, with a little help from the linker. * Since `const' objects end up in the text segment, TEXT_SET is the * correct directive to use. */ static const struct execsw java_execsw = { exec_java_imgact, "\xca\xfe\xba\xbe" }; TEXT_SET(execsw_set, java_execsw);