diff --git a/bsd-user/bsdload.c b/bsd-user/bsdload.c index dcf6f66..83ff852 100644 --- a/bsd-user/bsdload.c +++ b/bsd-user/bsdload.c @@ -154,19 +154,77 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, return sp; } +static int +is_there(const char *candidate) +{ + struct stat fin; + + /* XXX work around access(2) false positives for superuser */ + if (access(candidate, X_OK) == 0 && + stat(candidate, &fin) == 0 && + S_ISREG(fin.st_mode) && + (getuid() != 0 || + (fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) { + return (1); + } + return (0); +} + +static int +find_in_path(char *path, const char *filename, char *retpath, size_t rpsize) +{ + const char *d; + int found; + + if (strchr(filename, '/') != NULL) + return (is_there(filename) ? 0 : -1); + found = 0; + while ((d = strsep(&path, ":")) != NULL) { + if (*d == '\0') + d = "."; + if (snprintf(retpath, rpsize, "%s/%s", d, + filename) >= (int)rpsize) + continue; + if (is_there((const char *)retpath)) { + found = 1; + break; + } + } + return (found); +} + int loader_exec(const char * filename, char ** argv, char ** envp, struct target_pt_regs * regs, struct image_info *infop, struct bsd_binprm *bprm) { int retval; int i; + char *p, *path, fullpath[PATH_MAX]; + ssize_t pathlen; bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES /*-sizeof(unsigned int) XXX */; for (i=0 ; ipage[i] = NULL; - retval = open(filename, O_RDONLY); + + /* Find target executable in path, if not already fullpath. */ + if ((p = getenv("PATH")) != NULL) { + pathlen = strlen(p) + 1; + path = malloc(pathlen); + if (NULL == path) { + fprintf(stderr, "Out of memory\n"); + return (-1); + } + memcpy(path, p, pathlen); + if (find_in_path(path, filename, fullpath, sizeof(fullpath))) + retval = open(fullpath, O_RDONLY); + else + retval = open(filename, O_RDONLY); + + } else + retval = open(filename, O_RDONLY); if (retval < 0) return retval; + bprm->fd = retval; bprm->filename = (char *)filename; bprm->argc = count(argv); diff --git a/bsd-user/main.c b/bsd-user/main.c index 99b94c1..9b526b3 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -1022,7 +1022,7 @@ void cpu_loop(CPUMIPSState *env) switch(trapnr) { case EXCP_SYSCALL: /* syscall exception */ syscall_num = env->active_tc.gpr[2]; /* v0 */ - env->active_tc.PC += 4; + env->active_tc.PC += TARGET_INSN_SIZE; if (syscall_num >= SYS_MAXSYSCALL) { ret = -TARGET_ENOSYS; } else { @@ -1094,7 +1094,11 @@ void cpu_loop(CPUMIPSState *env) */ break; } - /* XXX need to handle ERESTART */ + if (-TARGET_ERESTART == ret) { + /* Backup the pc to point at the swi. */ + env->active_tc.PC -= TARGET_INSN_SIZE; + break; + } if ((unsigned int)ret >= (unsigned int)(-1133)) { env->active_tc.gpr[7] = 1; ret = -ret; diff --git a/bsd-user/mips/target_vmparam.h b/bsd-user/mips/target_vmparam.h index 6eca54f..abdb1dc 100644 --- a/bsd-user/mips/target_vmparam.h +++ b/bsd-user/mips/target_vmparam.h @@ -33,6 +33,8 @@ struct target_ps_strings { #define TARGET_SZSIGCODE 0 +#define TARGET_INSN_SIZE 4 + #else #define TARGET_USRSTACK 0 diff --git a/bsd-user/mips64/target_vmparam.h b/bsd-user/mips64/target_vmparam.h index 3fe93fb..3a3bb6e 100644 --- a/bsd-user/mips64/target_vmparam.h +++ b/bsd-user/mips64/target_vmparam.h @@ -31,6 +31,8 @@ struct target_ps_strings { #define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings)) +#define TARGET_INSN_SIZE 4 + #else #define TARGET_USRSTACK 0 diff --git a/bsd-user/signal.c b/bsd-user/signal.c index c4e8440..a26d40a 100644 --- a/bsd-user/signal.c +++ b/bsd-user/signal.c @@ -122,8 +122,9 @@ int host_to_target_signal(int sig) { - if (sig >= _NSIG) + if (sig < 0 || sig >= _NSIG) return (sig); + return (host_to_target_signal_table[sig]); } @@ -598,11 +599,13 @@ do_sigaction(int sig, const struct target_sigaction *act, if (k->_sa_handler == TARGET_SIG_IGN) { act1.sa_sigaction = (void *)SIG_IGN; } else if (k->_sa_handler == TARGET_SIG_DFL) { - if (fatal_signal(sig)) + if (fatal_signal(sig)) { + act1.sa_flags = SA_SIGINFO; act1.sa_sigaction = host_signal_handler; - else + } else { act1.sa_sigaction = (void *)SIG_DFL; + } } else { act1.sa_flags = SA_SIGINFO; act1.sa_sigaction = host_signal_handler; diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c index 0f337e2..490227c 100644 --- a/bsd-user/syscall.c +++ b/bsd-user/syscall.c @@ -3120,6 +3120,15 @@ do_lock_umutex(abi_ulong target_addr, uint32_t id, struct timespec *ts, 0, ts)); } + if (NULL == ts) { + /* + * In the case of no timeout do a restart on this syscall, + * if interrupted. + */ + if (-TARGET_EINTR == ret) + ret = -TARGET_ERESTART; + } + return (0); }