#include <sys/types.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/exec.h>
#include <sys/modctl.h>
#include <sys/cmn_err.h>
#include <sys/pathname.h>
#if defined(__sparc)
char *jexec = "/usr/java/jre/lib/sparc/jexec";
#elif defined(__x86)
char *jexec = "/usr/java/jre/lib/i386/jexec";
#else
#error "Unknown ISA"
#endif
char *jexec_arg = "-jar";
#define SIGSIZ 4
#define LOCSIG "PK\003\004"
#define LOCHDRSIZ 30
#define CH(b, n) (((unsigned char *)(b))[n])
#define SH(b, n) (CH(b, n) | (CH(b, n+1) << 8))
#define LG(b, n) (SH(b, n) | (SH(b, n+2) << 16))
#define LOCNAM(b) (SH(b, 26))
#define LOCEXT(b) (SH(b, 28))
#define XFHSIZ 4
#define XFHID(b) (SH(b, 0))
#define XFDATASIZ(b) (SH(b, 2))
#define XFJAVASIG 0xcafe
static int
javaexec(vnode_t *vp, struct execa *uap, struct uarg *args,
struct intpdata *idatap, int level, size_t *execsz, int setid,
caddr_t execfile, cred_t *cred, int brand_action)
{
struct intpdata idata;
int error;
ssize_t resid;
vnode_t *nvp;
off_t xoff, xoff_end;
char lochdr[LOCHDRSIZ];
struct pathname lookpn;
struct pathname resolvepn;
char *opath;
if (level)
return (ENOEXEC);
if ((error = vn_rdwr(UIO_READ, vp, lochdr, sizeof (lochdr),
0, UIO_SYSSPACE, 0, (rlim64_t)0, cred, &resid)) != 0)
return (error);
if (resid != 0 || strncmp(lochdr, LOCSIG, SIGSIZ) != 0)
return (ENOEXEC);
xoff = sizeof (lochdr) + LOCNAM(lochdr);
xoff_end = xoff + LOCEXT(lochdr);
while (xoff < xoff_end) {
char xfhdr[XFHSIZ];
if ((error = vn_rdwr(UIO_READ, vp, xfhdr, sizeof (xfhdr),
xoff, UIO_SYSSPACE, 0, (rlim64_t)0, cred, &resid)) != 0)
return (error);
if (resid != 0)
return (ENOEXEC);
if (XFHID(xfhdr) == XFJAVASIG)
break;
xoff += sizeof (xfhdr) + XFDATASIZ(xfhdr);
}
if (xoff >= xoff_end)
return (ENOEXEC);
if (setid)
return (EACCES);
bzero(&idata, sizeof (intpdata_t));
idata.intp = NULL;
idata.intp_name[0] = jexec;
idata.intp_arg[0] = jexec_arg;
if (error = pn_get(idata.intp_name[0], UIO_SYSSPACE, &lookpn))
return (error);
pn_alloc(&resolvepn);
if (error = lookuppn(&lookpn, &resolvepn, FOLLOW, NULLVPP, &nvp)) {
pn_free(&resolvepn);
pn_free(&lookpn);
return (ENOEXEC);
}
opath = args->pathname;
args->pathname = resolvepn.pn_path;
pn_free(&lookpn);
error = gexec(&nvp, uap, args, &idata, level + 1, execsz, execfile,
cred, EBA_NONE);
if (!error) {
(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, cred, NULL);
}
VN_RELE(nvp);
args->pathname = opath;
pn_free(&resolvepn);
return (error);
}
static struct execsw jexecsw = {
javamagicstr,
0,
4,
javaexec,
NULL
};
static struct modlexec jmodlexec = {
&mod_execops, "exec for Java", &jexecsw
};
static struct modlinkage jmodlinkage = {
MODREV_1, &jmodlexec, NULL
};
int
_init(void)
{
return (mod_install(&jmodlinkage));
}
int
_fini(void)
{
return (mod_remove(&jmodlinkage));
}
int
_info(struct modinfo *modinfop)
{
return (mod_info(&jmodlinkage, modinfop));
}