diff -ur ./i386/linux/linux_sysvec.c /usr/src/sys/i386/linux/linux_sysvec.c --- ./i386/linux/linux_sysvec.c Tue Mar 26 21:58:57 1996 +++ /usr/src/sys/i386/linux/linux_sysvec.c Tue Mar 26 21:02:37 1996 @@ -405,6 +405,7 @@ Elf32_Interp_info linux_interp = { &elf_linux_sysvec, "/lib/ld-linux.so.1", + "linux", "/compat/linux" }; diff -ur ./kern/imgact_elf.c /usr/src/sys/kern/imgact_elf.c --- ./kern/imgact_elf.c Tue Mar 26 22:00:55 1996 +++ /usr/src/sys/kern/imgact_elf.c Tue Mar 26 21:54:35 1996 @@ -92,6 +92,7 @@ static Elf32_Interp_info freebsd_interp = { &elf_freebsd_sysvec, "/usr/libexec/ld-elf.so.1", + "freebsd", "" }; static Elf32_Interp_info *interp_list[MAX_INTERP] = { @@ -475,6 +476,8 @@ u_long addr, entry = 0, proghdr = 0; int error, i, header_size = 0, interp_len = 0; char *interp = NULL; + char path[MAXPATHLEN]; + char *sp; /* * Do we have a valid ELF header ? @@ -608,31 +611,67 @@ addr = 2*MAXDSIZ; /* May depend on OS type XXX */ - if (interp) { - char path[MAXPATHLEN]; + /* + * See if the user wants to override the sysvec with the sysvec + * in the COMPAT_SYSVEC environment variable + */ + sp = imgp->stringbase; + + for (i = 0; i < imgp->argc; i++) { + while (*sp++); /* Constructed by kernel, should be valid */ + } + + for (i = 0; i < imgp->envc; i++) { + while (*sp++); /* Constructed by kernel, should be valid */ + + if (bcmp (sp, "COMPAT_SYSVEC=", 13) == 0) { + sp += 14; /* sp points to the osname */ + break; + } + } + + if (*sp == NULL) + sp = NULL; + else + UPRINTF ("sysvec %s requested by user\n", sp); + + if (interp || sp) { /* * So which kind of ELF binary do we have at hand * FreeBSD, SVR4 or Linux ?? */ for (i=0; ipath)) { - imgp->proc->p_sysent = - interp_list[i]->sysvec; - strcpy(path, interp_list[i]->emul_path); - strcat(path, interp_list[i]->path); - UPRINTF("interpreter=<%s> %s\n", - interp_list[i]->path, - interp_list[i]->emul_path); - break; - } - } + if (interp_list[i] == NULL) + continue; + + /* User's sysvec always overrides the interp section */ + if (sp && (strcmp(sp, interp_list[i]->osname))) + continue; + + if (interp && (strcmp(interp, interp_list[i]->path))) + continue; + + imgp->proc->p_sysent = interp_list[i]->sysvec; + strcpy(path, interp_list[i]->emul_path); + strcat(path, interp_list[i]->path); + UPRINTF("interpreter=<%s> %s\n", interp_list[i]->path, + interp_list[i]->emul_path); + break; } if (i == MAX_INTERP) { - uprintf("ELF interpreter %s not known\n", interp); + if (sp == 0) { + uprintf("ELF interpreter %s not known\n", + interp); + } else { + uprintf("COMPAT_SYSVEC %s not known\n", + sp); + } error = ENOEXEC; goto fail; } + } + + if (interp) { if (error = elf_load_file(imgp->proc, path, &addr, /* XXX */ diff -ur ./sys/imgact_elf.h /usr/src/sys/sys/imgact_elf.h --- ./sys/imgact_elf.h Tue Mar 26 21:59:04 1996 +++ /usr/src/sys/sys/imgact_elf.h Tue Mar 26 21:01:30 1996 @@ -202,6 +202,7 @@ typedef struct { struct sysentvec *sysvec; char *path; + char *osname; /* OS name for user specified override */ char *emul_path; } Elf32_Interp_info;