Skip site navigation (1)Skip section navigation (2)
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>