summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-06-13 19:16:27 -0400
committerIan Moffett <ian@osmora.org>2025-06-13 19:16:27 -0400
commit68fbe4a2292dc5b4025dd4201fd4b892605079b7 (patch)
treeb2683975dc48116a57a7c7911712b63749a176b1
parent9f534c75cd0e29b5b829c412ced28fa846c7d911 (diff)
kernel: spawn: Add argv + stub envp arguments
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--lib/libc/src/hyra/spawn.c7
-rw-r--r--sys/include/sys/limits.h1
-rw-r--r--sys/include/sys/spawn.h2
-rw-r--r--sys/kern/kern_spawn.c52
-rw-r--r--usr.bin/osh/osh.c3
-rw-r--r--usr.sbin/install/install.c4
6 files changed, 56 insertions, 13 deletions
diff --git a/lib/libc/src/hyra/spawn.c b/lib/libc/src/hyra/spawn.c
index 227d8f7..b4c92ef 100644
--- a/lib/libc/src/hyra/spawn.c
+++ b/lib/libc/src/hyra/spawn.c
@@ -35,10 +35,13 @@
* Spawn a process
*
* @pathname: Path to executable.
+ * @argv: Argument vector
+ * @envp: Environment vector
* @flags: Spawn flags.
*/
pid_t
-spawn(const char *pathname, int flags)
+spawn(const char *pathname, char **argv, char **envp, int flags)
{
- return syscall(SYS_spawn, (uintptr_t)pathname, flags);
+ return syscall(SYS_spawn, (uintptr_t)pathname, (uintptr_t)argv,
+ (uintptr_t)envp, flags);
}
diff --git a/sys/include/sys/limits.h b/sys/include/sys/limits.h
index 198c963..f56958e 100644
--- a/sys/include/sys/limits.h
+++ b/sys/include/sys/limits.h
@@ -32,6 +32,7 @@
#define PATH_MAX 1024
#define SSIZE_MAX 32767
+#define ARG_MAX 4096
#define CHAR_BIT 8
#if defined(_KERNEL)
#define CPU_MAX 256
diff --git a/sys/include/sys/spawn.h b/sys/include/sys/spawn.h
index 9d823db..0c54e4c 100644
--- a/sys/include/sys/spawn.h
+++ b/sys/include/sys/spawn.h
@@ -36,6 +36,6 @@
#define SPAWN_WAIT BIT(0)
#if !defined(_KERNEL)
-pid_t spawn(const char *pathname, int flags);
+pid_t spawn(const char *pathname, char **argv, char **envp, int flags);
#endif /* _KERNEL */
#endif /* !_SYS_SPAWN_H_ */
diff --git a/sys/kern/kern_spawn.c b/sys/kern/kern_spawn.c
index 6addf8f..a953a6e 100644
--- a/sys/kern/kern_spawn.c
+++ b/sys/kern/kern_spawn.c
@@ -45,10 +45,17 @@
#define pr_trace(fmt, ...) kprintf("spawn: " fmt, ##__VA_ARGS__)
#define pr_error(...) pr_trace(__VA_ARGS__)
+#define ARGVP_MAX (ARG_MAX / sizeof(void *))
+
static volatile size_t nthreads = 0;
+/*
+ * TODO: envp
+ */
struct spawn_args {
char path[PATH_MAX];
+ char argv_blk[ARG_MAX];
+ char *argv[ARGVP_MAX];
};
static inline void
@@ -67,7 +74,6 @@ spawn_thunk(void)
struct proc *cur;
struct execve_args execve_args;
struct spawn_args *args;
- char *argv[] = { NULL, NULL };
char *envp[] = { NULL };
cur = this_td();
@@ -76,11 +82,9 @@ spawn_thunk(void)
memset(pathbuf, 0, sizeof(pathbuf));
memcpy(pathbuf, path, strlen(path));
- argv[0] = (char *)pathbuf;
- execve_args.pathname = argv[0];
- execve_args.argv = argv;
+ execve_args.pathname = pathbuf;
+ execve_args.argv = (char **)&args->argv[0];
execve_args.envp = envp;
-
path = NULL;
if (execve(cur, &execve_args) != 0) {
@@ -210,19 +214,26 @@ get_child(struct proc *cur, pid_t pid)
/*
* arg0: The file /path/to/executable
- * arg1: Optional flags (`flags')
+ * arg1: Argv
+ * arg2: Envp (TODO)
+ * arg3: Optional flags (`flags')
*/
scret_t
sys_spawn(struct syscall_args *scargs)
{
struct spawn_args *args;
- const char *u_path;
+ char *path;
+ const char *u_path, **u_argv;
+ const char *u_p = NULL;
struct proc *td;
int flags, error;
+ size_t len, bytes_copied = 0;
+ size_t argv_i = 0;
td = this_td();
- flags = scargs->arg1;
u_path = (const char *)scargs->arg0;
+ u_argv = (const char **)scargs->arg1;
+ flags = scargs->arg3;
args = dynalloc(sizeof(*args));
if (args == NULL) {
@@ -235,5 +246,30 @@ sys_spawn(struct syscall_args *scargs)
return error;
}
+ memset(args->argv, 0, ARG_MAX);
+ for (size_t i = 0; i < ARG_MAX - 1; ++i) {
+ error = copyin(&u_argv[argv_i], &u_p, sizeof(u_p));
+ if (error < 0) {
+ dynfree(args);
+ return error;
+ }
+ if (u_p == NULL) {
+ args->argv[argv_i++] = NULL;
+ break;
+ }
+
+ path = &args->argv_blk[i];
+ error = copyinstr(u_p, path, ARG_MAX - bytes_copied);
+ if (error < 0) {
+ dynfree(args);
+ return error;
+ }
+
+ args->argv[argv_i++] = &args->argv_blk[i];
+ len = strlen(path);
+ bytes_copied += (len + 1);
+ i += len;
+ }
+
return spawn(td, spawn_thunk, args, flags, NULL);
}
diff --git a/usr.bin/osh/osh.c b/usr.bin/osh/osh.c
index 93ac876..aaa4502 100644
--- a/usr.bin/osh/osh.c
+++ b/usr.bin/osh/osh.c
@@ -219,6 +219,7 @@ static int
cmd_run(const char *input, int argc, char *argv[])
{
char bin_path[256];
+ char *envp[1] = { NULL };
int error;
snprintf(bin_path, sizeof(bin_path), "/usr/bin/%s", input);
@@ -228,7 +229,7 @@ cmd_run(const char *input, int argc, char *argv[])
return -1;
}
- if ((error = spawn(bin_path, SPAWN_WAIT)) < 0) {
+ if ((error = spawn(bin_path, argv, envp, SPAWN_WAIT)) < 0) {
return error;
}
diff --git a/usr.sbin/install/install.c b/usr.sbin/install/install.c
index 5cedc06..91f75df 100644
--- a/usr.sbin/install/install.c
+++ b/usr.sbin/install/install.c
@@ -82,6 +82,8 @@ installer_clearscr(uint32_t color, bool setattr)
static void
pre_installer(void)
{
+ char *argv[] = { "/usr/bin/osh", NULL };
+ char *envp[] = { NULL };
char c;
puts("[S]hell/[I]nstall");
@@ -90,7 +92,7 @@ pre_installer(void)
if (c == 's') {
puts("\033[0m");
installer_clearscr(0x000000, false);
- spawn("/usr/bin/osh", SPAWN_WAIT);
+ spawn(argv[0], argv, envp, SPAWN_WAIT);
installer_clearscr(INSTALLER_BG, true);
break;
} else if (c == 'i') {