Skip to content

Commit

Permalink
[sb2] Add support for posix_spawnp(). Contributes to JB#51819
Browse files Browse the repository at this point in the history
Signed-off-by: Björn Bidar <bjorn.bidar@jolla.com>
  • Loading branch information
Thaodan committed Dec 5, 2020
1 parent cb48390 commit e79ab61
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 2 deletions.
4 changes: 2 additions & 2 deletions scratchbox2/execs/sb_exec.c
Expand Up @@ -12,8 +12,8 @@
* Brief description of the algorithm follows:
*
* 0. When an application wants to execute another program, it makes a call
* to one of execl(), execle(), execlp(), execv(), execve(), execvp() or
* posix_spawn().
* to one of execl(), execle(), execlp(), execv(), execve(), execvp(),
* posix_spawn() or posix_spawnp().
* That call will be handled by one of the gate functions in
* preload/libsb2.c. Eventually, the gate function will call "do_exec()"
* from this file; do_exec() calls prepare_exec() and that is the place
Expand Down
149 changes: 149 additions & 0 deletions scratchbox2/preload/execgates.c
Expand Up @@ -475,6 +475,136 @@ static int do_execvep(
return -1;
}

static int do_posix_spawnp(
int *result_errno_ptr,
const char *realfnname, pid_t *pid, const char *file,
const posix_spawn_file_actions_t *file_actions,
const posix_spawnattr_t *attrp,
char *const *argv, char *const *envp)
{
int result;
if (*file == '\0') {
/* We check the simple case first. */
*result_errno_ptr = ENOENT;
return ENOENT;
}

if (strchr (file, '/') != NULL) {
/* Try to execute this name. If it works, execv will not return. */
result = do_posix_spawn(result_errno_ptr,
realfnname, pid, file,
file_actions, attrp,
argv, envp);

if (*result_errno_ptr == ENOEXEC) {
char **new_argv = create_argv_for_script_exec(
file, argv);
result = do_posix_spawn(result_errno_ptr,
realfnname, pid, new_argv[0],
file_actions, attrp,
new_argv, envp);
free(new_argv);
}

return(result);
} else {
int got_eacces = 0;
const char *p;
const char *path;
char *name;
size_t len;
size_t pathlen;

path = getenv ("PATH");
if (path) path = strdup(path);
if (path == NULL) {
/* There is no `PATH' in the environment.
The default search path is the current directory
followed by the path `confstr' returns for `_CS_PATH'. */
char *new_path;
len = confstr (_CS_PATH, (char *) NULL, 0);
new_path = (char *) alloca (1 + len);
new_path[0] = ':';
(void) confstr (_CS_PATH, new_path + 1, len);
path = new_path;
}

len = strlen (file) + 1;
pathlen = strlen (path);
name = alloca (pathlen + len + 1);
/* Copy the file name at the top. */
name = (char *) memcpy (name + pathlen + 1, file, len);
/* And add the slash. */
*--name = '/';

p = path;
do {
char *startp;

path = p;
p = sb2_strchrnul (path, ':');

if (p == path) {
/* Two adjacent colons, or a colon at the beginning or the end
of `PATH' means to search the current directory. */
startp = name + 1;
} else {
startp = (char *) memcpy (name - (p - path), path, p - path);
}
result = do_posix_spawn(result_errno_ptr,
realfnname, pid, startp,
file_actions, attrp, argv, envp);

if (*result_errno_ptr == ENOEXEC) {
char **new_argv = create_argv_for_script_exec(
startp, argv);
result = do_posix_spawn(result_errno_ptr,
realfnname, pid, new_argv[0],
file_actions, attrp,
new_argv, envp);
free(new_argv);
}
if (result == 0)
return result;

switch (*result_errno_ptr) {
case EACCES:
/* Record the we got a `Permission denied' error. If we end
up finding no executable we can use, we want to diagnose
that we did find one but were denied access. */
got_eacces = 1;
case ENOENT:
case ESTALE:
case ENOTDIR:
/* Those errors indicate the file is missing or not executable
by us, in which case we want to just try the next path
directory. */
break;

default:
/* Some other error means we found an executable file, but
something went wrong executing it; return the error to our
caller. */
SB_LOG(SB_LOGLEVEL_WARNING,
"%s: unkown errno, "
"something may be wrong: %i",
realfnname, *result_errno_ptr);
return result;
}
} while (*p++ != '\0');

/* We tried every element and none of them worked. */
if (got_eacces)
/* At least one failure was due to permissions, so report that
error. */
*result_errno_ptr = EACCES;
}

/* Return the error from the last attempt (probably ENOENT). */
return result;
}


int sb_execvep(
const char *file,
char *const argv [],
Expand Down Expand Up @@ -531,6 +661,25 @@ int posix_spawn_gate(
file_actions, attrp, argv, envp);
}

int posix_spawnp_gate(
int *result_errno_ptr,
int (*real_posix_spawnp_ptr)(pid_t *pid, const char *file,
const posix_spawn_file_actions_t *file_actions,
const posix_spawnattr_t *attrp,
char *const argv[], char *const envp[]),
const char *realfnname,
pid_t *pid,
const char *file,
const posix_spawn_file_actions_t *file_actions,
const posix_spawnattr_t *attrp,
char *const argv[],
char *const envp[])
{
(void)real_posix_spawnp_ptr;
return do_posix_spawnp(result_errno_ptr, realfnname, pid, file,
file_actions, attrp, argv, envp);
}

/* SETRLIMIT_ARG1_TYPE is defined in interface.master */

int setrlimit_gate(
Expand Down
4 changes: 4 additions & 0 deletions scratchbox2/preload/interface.master
Expand Up @@ -115,6 +115,10 @@ GATE: int posix_spawn (pid_t *pid, const char *path, \
const posix_spawn_file_actions_t *file_actions, \
const posix_spawnattr_t *attrp, \
char *const argv[], char *const envp[])
GATE: int posix_spawnp (pid_t *pid, const char *file, \
const posix_spawn_file_actions_t *file_actions, \
const posix_spawnattr_t *attrp, \
char *const argv[], char *const envp[])

GATE: char * getcwd (char *buf, size_t size) : \
returns_string create_nomap_nolog_version
Expand Down

0 comments on commit e79ab61

Please sign in to comment.