Date: Mon, 3 Mar 1997 06:42:04 +0800 (WST) From: Adrian Chadd <adrian@obiwan.aceonline.com.au> To: freebsd-hackers@freebsd.org Subject: Re : java support under FreeBSD - test code. Message-ID: <Pine.BSF.3.95q.970303062707.219A-100000@obiwan.aceonline.com.au>
next in thread | raw e-mail | index | archive | help
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) <WHATEVER ARGS PASSED TO THE PROGRAM>
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
<adrian@psinet.net.au>
-- Begin code (/usr/src/sys/kern/imgact_java.c)
/* Insert favourite copyright notice / disclaimer here */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/resourcevar.h>
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/kernel.h>
#include <machine/endian.h>
#include <sys/syslog.h>
#include <sys/sysctl.h>
/* 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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.95q.970303062707.219A-100000>
