environment variables for processes
This commit is contained in:
parent
285da1dc46
commit
7d90ac7d3d
11 changed files with 293 additions and 19 deletions
|
|
@ -18,6 +18,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <kernel-public/framebuffer.h>
|
#include <kernel-public/framebuffer.h>
|
||||||
|
#include <kernel-public/process.h>
|
||||||
#include <kernel-public/files.h>
|
#include <kernel-public/files.h>
|
||||||
#include <kernel-public/input.h>
|
#include <kernel-public/input.h>
|
||||||
#include <kernel-public/ipc.h>
|
#include <kernel-public/ipc.h>
|
||||||
|
|
@ -41,7 +42,7 @@ void *map_pages(uint64_t count);
|
||||||
void sleep_ms(uint64_t ms_to_sleep);
|
void sleep_ms(uint64_t ms_to_sleep);
|
||||||
|
|
||||||
//1 on success, 0 on failure.
|
//1 on success, 0 on failure.
|
||||||
int start_elf(const char *path);
|
int start_elf(const char *path, const struct process_start_info *info);
|
||||||
|
|
||||||
enum ipc_dgram_result ipc_create_dgram_receiver(const char *address, ipc_dgram_receiver_handle_t *handle_out);
|
enum ipc_dgram_result ipc_create_dgram_receiver(const char *address, ipc_dgram_receiver_handle_t *handle_out);
|
||||||
enum ipc_dgram_result ipc_create_dgram_sender(const char *address, ipc_dgram_sender_handle_t *handle_out);
|
enum ipc_dgram_result ipc_create_dgram_sender(const char *address, ipc_dgram_sender_handle_t *handle_out);
|
||||||
|
|
@ -56,3 +57,11 @@ enum ipc_dgram_result ipc_send_dgram(ipc_dgram_sender_handle_t handle, const voi
|
||||||
|
|
||||||
//f should not return
|
//f should not return
|
||||||
void create_thread(void (*f)(uint64_t x), uint64_t x);
|
void create_thread(void (*f)(uint64_t x), uint64_t x);
|
||||||
|
|
||||||
|
//value_space must be positive at entry.
|
||||||
|
//looks up the environment variable with this key. if there is no such
|
||||||
|
//variable, sets value_space to 0. otherwise, sets value_space to the
|
||||||
|
//length of the value including null terminator (which will be positive),
|
||||||
|
//and if that is at most what value_space was set to at entry, also
|
||||||
|
//copies the value including null terminator to value_out.
|
||||||
|
void get_envvar(const char *key, char *value_out, int *value_space);
|
||||||
|
|
|
||||||
32
include/kernel-public/process.h
Normal file
32
include/kernel-public/process.h
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
/* Calcite, include/kernel-public/process.h
|
||||||
|
* Copyright 2025 Benji Dial
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct process_start_info {
|
||||||
|
|
||||||
|
//keys of envvars to copy to new process.
|
||||||
|
const char **forwared_envvars;
|
||||||
|
int forwared_envvar_count;
|
||||||
|
|
||||||
|
//keys and values to set in new process.
|
||||||
|
//entry i has key set_envvars[i * 2] and value set_envvars[i * 2 + 1].
|
||||||
|
//set_envvar_count is number of envvars, not twice that.
|
||||||
|
const char **set_envvars;
|
||||||
|
int set_envvar_count;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -32,5 +32,6 @@ enum {
|
||||||
SYSCALL_IPC_CREATE_DGRAM_SENDER,
|
SYSCALL_IPC_CREATE_DGRAM_SENDER,
|
||||||
SYSCALL_IPC_RECEIVE_DGRAM,
|
SYSCALL_IPC_RECEIVE_DGRAM,
|
||||||
SYSCALL_IPC_SEND_DGRAM,
|
SYSCALL_IPC_SEND_DGRAM,
|
||||||
SYSCALL_CREATE_THREAD
|
SYSCALL_CREATE_THREAD,
|
||||||
|
SYSCALL_GET_ENVVAR
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -271,6 +271,7 @@ static const char *cmdline_look_up(const char *key) {
|
||||||
register_syscall(SYSCALL_IPC_RECEIVE_DGRAM, (void *)&syscall_ipc_receive_dgram);
|
register_syscall(SYSCALL_IPC_RECEIVE_DGRAM, (void *)&syscall_ipc_receive_dgram);
|
||||||
register_syscall(SYSCALL_IPC_SEND_DGRAM, (void *)&syscall_ipc_send_dgram);
|
register_syscall(SYSCALL_IPC_SEND_DGRAM, (void *)&syscall_ipc_send_dgram);
|
||||||
register_syscall(SYSCALL_CREATE_THREAD, (void *)&syscall_create_thread);
|
register_syscall(SYSCALL_CREATE_THREAD, (void *)&syscall_create_thread);
|
||||||
|
register_syscall(SYSCALL_GET_ENVVAR, (void *)&syscall_get_envvar);
|
||||||
|
|
||||||
//probe for drives
|
//probe for drives
|
||||||
|
|
||||||
|
|
@ -298,7 +299,7 @@ static const char *cmdline_look_up(const char *key) {
|
||||||
|
|
||||||
init_scheduler();
|
init_scheduler();
|
||||||
|
|
||||||
if (!start_elf("root://calcite/apps/init/init.elf"))
|
if (start_elf("root://calcite/apps/init/init.elf") == 0)
|
||||||
panic("could not start init.elf")
|
panic("could not start init.elf")
|
||||||
|
|
||||||
resume_next_continuation();
|
resume_next_continuation();
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
|
||||||
|
#include <kernel-public/process.h>
|
||||||
#include <kernel-public/files.h>
|
#include <kernel-public/files.h>
|
||||||
#include <kernel-public/ipc.h>
|
#include <kernel-public/ipc.h>
|
||||||
|
|
||||||
|
|
@ -66,6 +67,7 @@ void create_process(struct process *process_out) {
|
||||||
process_out->n_threads = 0;
|
process_out->n_threads = 0;
|
||||||
process_out->files = 0;
|
process_out->files = 0;
|
||||||
process_out->ipc_dgram_handles = 0;
|
process_out->ipc_dgram_handles = 0;
|
||||||
|
process_out->env_pairs = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -345,7 +347,8 @@ int load_elf(
|
||||||
// all other registers zeroed
|
// all other registers zeroed
|
||||||
extern uint8_t thread_start;
|
extern uint8_t thread_start;
|
||||||
|
|
||||||
int start_elf(const char *uri) {
|
//returns 0 on failure
|
||||||
|
struct process *start_elf(const char *uri) {
|
||||||
|
|
||||||
struct process *process = heap_alloc(sizeof(struct process));
|
struct process *process = heap_alloc(sizeof(struct process));
|
||||||
create_process(process);
|
create_process(process);
|
||||||
|
|
@ -376,7 +379,7 @@ int start_elf(const char *uri) {
|
||||||
|
|
||||||
add_to_queue(&ready_continuations, &ci);
|
add_to_queue(&ready_continuations, &ci);
|
||||||
|
|
||||||
return 1;
|
return process;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -399,14 +402,45 @@ void syscall_create_thread(void (*f)(uint64_t), uint64_t x) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int syscall_start_elf(const char *uri) {
|
int syscall_start_elf(const char *path, const struct process_start_info *info) {
|
||||||
|
|
||||||
assert(running_thread != 0)
|
assert(running_thread != 0)
|
||||||
|
|
||||||
if (!is_mapped_readable_string(running_thread->process, uri))
|
if (!is_mapped_readable_string(running_thread->process, path) ||
|
||||||
|
!is_mapped_readable(
|
||||||
|
running_thread->process, info, sizeof(struct process_start_info)) ||
|
||||||
|
!is_mapped_readable(
|
||||||
|
running_thread->process,
|
||||||
|
info->forwared_envvars,
|
||||||
|
info->forwared_envvar_count * sizeof(const char *)) ||
|
||||||
|
!is_mapped_readable(
|
||||||
|
running_thread->process,
|
||||||
|
info->set_envvars,
|
||||||
|
2 * info->set_envvar_count * sizeof(const char *)))
|
||||||
syscall_illegal_args();
|
syscall_illegal_args();
|
||||||
|
|
||||||
return start_elf(uri);
|
for (int i = 0; i < info->forwared_envvar_count; ++i)
|
||||||
|
if (!is_mapped_readable_string(running_thread->process, info->forwared_envvars[i]))
|
||||||
|
syscall_illegal_args();
|
||||||
|
|
||||||
|
for (int i = 0; i < 2 * info->set_envvar_count; ++i)
|
||||||
|
if (!is_mapped_readable_string(running_thread->process, info->set_envvars[i]))
|
||||||
|
syscall_illegal_args();
|
||||||
|
|
||||||
|
struct process *process = start_elf(path);
|
||||||
|
if (process == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < info->forwared_envvar_count; ++i) {
|
||||||
|
struct process_env_pair *pair = get_envvar(running_thread->process, info->forwared_envvars[i]);
|
||||||
|
if (pair != 0)
|
||||||
|
set_envvar(process, info->forwared_envvars[i], pair->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < info->set_envvar_count; ++i)
|
||||||
|
set_envvar(process, info->set_envvars[2 * i], info->set_envvars[2 * i + 1]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -428,6 +462,16 @@ void destroy_process(struct process *process) {
|
||||||
process->ipc_dgram_handles_buffer_size * sizeof(struct process_ipc_dgram_handle_info));
|
process->ipc_dgram_handles_buffer_size * sizeof(struct process_ipc_dgram_handle_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process->env_pairs) {
|
||||||
|
for (int i = 0; i < process->env_pairs_buffer_size; ++i)
|
||||||
|
if (process->env_pairs[i].key_length != 0) {
|
||||||
|
heap_dealloc(process->env_pairs[i].key, process->env_pairs[i].key_length + 1);
|
||||||
|
heap_dealloc(process->env_pairs[i].value, process->env_pairs[i].value_length + 1);
|
||||||
|
}
|
||||||
|
heap_dealloc(
|
||||||
|
process->env_pairs, process->env_pairs_buffer_size * sizeof(struct process_env_pair));
|
||||||
|
}
|
||||||
|
|
||||||
for (int p3i = 0; p3i < 512; ++p3i)
|
for (int p3i = 0; p3i < 512; ++p3i)
|
||||||
if (process->p3_virtual_base[p3i]) {
|
if (process->p3_virtual_base[p3i]) {
|
||||||
for (int p2i = 0; p2i < 512; ++p2i)
|
for (int p2i = 0; p2i < 512; ++p2i)
|
||||||
|
|
@ -804,3 +848,113 @@ enum ipc_dgram_result syscall_ipc_send_dgram(
|
||||||
return send_ipc_dgram(box, data, bytes);
|
return send_ipc_dgram(box, data, bytes);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define INITIAL_ENVVAR_BUFFER_SIZE 32
|
||||||
|
|
||||||
|
void set_envvar(struct process *process, const char *key, const char *value) {
|
||||||
|
|
||||||
|
if (!process->env_pairs) {
|
||||||
|
process->env_pairs = heap_alloc(INITIAL_ENVVAR_BUFFER_SIZE * sizeof(struct process_env_pair));
|
||||||
|
process->env_pairs_buffer_size = INITIAL_ENVVAR_BUFFER_SIZE;
|
||||||
|
for (int i = 0; i < INITIAL_ENVVAR_BUFFER_SIZE; ++i)
|
||||||
|
process->env_pairs[i].key_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int key_length = 0;
|
||||||
|
while (key[key_length] != 0)
|
||||||
|
++key_length;
|
||||||
|
|
||||||
|
int value_length = 0;
|
||||||
|
while (value[value_length] != 0)
|
||||||
|
++value_length;
|
||||||
|
|
||||||
|
assert(key_length != 0)
|
||||||
|
assert(value_length != 0)
|
||||||
|
|
||||||
|
for (int i = 0; i < process->env_pairs_buffer_size; ++i) {
|
||||||
|
if (process->env_pairs[i].key_length != key_length)
|
||||||
|
continue;
|
||||||
|
for (int j = 0; j < key_length; ++j)
|
||||||
|
if (process->env_pairs[i].key[j] != key[j])
|
||||||
|
continue;
|
||||||
|
heap_dealloc(process->env_pairs[i].value, process->env_pairs[i].value_length + 1);
|
||||||
|
char *value_copy = heap_alloc(value_length + 1);
|
||||||
|
memcpy(value_copy, value, value_length + 1);
|
||||||
|
process->env_pairs[i].value = value_copy;
|
||||||
|
process->env_pairs[i].value_length = value_length;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct process_env_pair *pair;
|
||||||
|
for (int i = 0; i < process->env_pairs_buffer_size; ++i)
|
||||||
|
if (process->env_pairs[i].key_length == 0) {
|
||||||
|
pair = &process->env_pairs[i];
|
||||||
|
goto got_pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
double_buffer_zero(
|
||||||
|
(void **)&process->env_pairs,
|
||||||
|
&process->env_pairs_buffer_size,
|
||||||
|
sizeof(struct process_env_pair));
|
||||||
|
|
||||||
|
pair = &process->env_pairs[process->env_pairs_buffer_size / 2];
|
||||||
|
|
||||||
|
got_pair:
|
||||||
|
char *key_copy = heap_alloc(key_length + 1);
|
||||||
|
memcpy(key_copy, key, key_length + 1);
|
||||||
|
pair->key = key_copy;
|
||||||
|
pair->key_length = key_length;
|
||||||
|
char *value_copy = heap_alloc(value_length + 1);
|
||||||
|
memcpy(value_copy, value, value_length + 1);
|
||||||
|
pair->value = value_copy;
|
||||||
|
pair->value_length = value_length;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct process_env_pair *get_envvar(struct process *process, const char *key) {
|
||||||
|
|
||||||
|
int key_length = 0;
|
||||||
|
while (key[key_length] != 0)
|
||||||
|
++key_length;
|
||||||
|
|
||||||
|
assert(key_length > 0)
|
||||||
|
|
||||||
|
for (int i = 0; i < process->env_pairs_buffer_size; ++i) {
|
||||||
|
if (process->env_pairs[i].key_length != key_length)
|
||||||
|
continue;
|
||||||
|
for (int j = 0; j < key_length; ++j)
|
||||||
|
if (process->env_pairs[i].key[j] != key[j])
|
||||||
|
continue;
|
||||||
|
return &process->env_pairs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void syscall_get_envvar(const char *key, char *value_out, int *value_space) {
|
||||||
|
|
||||||
|
assert(running_thread != 0)
|
||||||
|
|
||||||
|
if (!is_mapped_readable_string(running_thread->process, key) ||
|
||||||
|
!is_mapped_writable(running_thread->process, value_space, sizeof(int)) ||
|
||||||
|
*value_space <= 0 ||
|
||||||
|
!is_mapped_writable(running_thread->process, value_out, *value_space))
|
||||||
|
syscall_illegal_args();
|
||||||
|
|
||||||
|
struct process_env_pair *pair = get_envvar(running_thread->process, key);
|
||||||
|
|
||||||
|
if (pair == 0) {
|
||||||
|
*value_space = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*value_space < pair->value_length + 1) {
|
||||||
|
*value_space = pair->value_length + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value_space = pair->value_length + 1;
|
||||||
|
memcpy(value_out, pair->value, pair->value_length + 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
|
||||||
#include <kernel-public/framebuffer.h>
|
#include <kernel-public/framebuffer.h>
|
||||||
|
#include <kernel-public/process.h>
|
||||||
#include <kernel-public/files.h>
|
#include <kernel-public/files.h>
|
||||||
#include <kernel-public/ipc.h>
|
#include <kernel-public/ipc.h>
|
||||||
|
|
||||||
|
|
@ -38,6 +39,16 @@ struct process_ipc_dgram_handle_info {
|
||||||
int is_receiver;
|
int is_receiver;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//lengths don't include null terminators, buffers do.
|
||||||
|
//key and value should not be empty.
|
||||||
|
struct process_env_pair {
|
||||||
|
//0 for unused
|
||||||
|
int key_length;
|
||||||
|
int value_length;
|
||||||
|
char *key;
|
||||||
|
char *value;
|
||||||
|
};
|
||||||
|
|
||||||
struct process {
|
struct process {
|
||||||
|
|
||||||
uint64_t p4_physical_base;
|
uint64_t p4_physical_base;
|
||||||
|
|
@ -55,6 +66,9 @@ struct process {
|
||||||
struct process_ipc_dgram_handle_info *ipc_dgram_handles;
|
struct process_ipc_dgram_handle_info *ipc_dgram_handles;
|
||||||
int ipc_dgram_handles_buffer_size;
|
int ipc_dgram_handles_buffer_size;
|
||||||
|
|
||||||
|
struct process_env_pair *env_pairs;
|
||||||
|
int env_pairs_buffer_size;
|
||||||
|
|
||||||
//0 for missing levels. just bottom p3 of address space.
|
//0 for missing levels. just bottom p3 of address space.
|
||||||
uint64_t *p2_virtual_bases[512];
|
uint64_t *p2_virtual_bases[512];
|
||||||
uint64_t **p1_virtual_bases[512];
|
uint64_t **p1_virtual_bases[512];
|
||||||
|
|
@ -104,13 +118,13 @@ int load_elf(
|
||||||
struct process *process, uint64_t *entry_out,
|
struct process *process, uint64_t *entry_out,
|
||||||
const struct fs_info *fs_info, void *fs_node);
|
const struct fs_info *fs_info, void *fs_node);
|
||||||
|
|
||||||
//returns 0 on failure, 1 on success.
|
//returns 0 on failure.
|
||||||
//creates a process and a thread in that process, loads the elf into the process,
|
//creates a process and a thread in that process, loads the elf into the process,
|
||||||
//and schedules a ready task that sets the running thread to the new thread and
|
//and schedules a ready task that sets the running thread to the new thread and
|
||||||
//starts user mode at the elf's entry point.
|
//starts user mode at the elf's entry point.
|
||||||
int start_elf(const char *uri);
|
struct process *start_elf(const char *uri);
|
||||||
|
|
||||||
int syscall_start_elf(const char *uri);
|
int syscall_start_elf(const char *path, const struct process_start_info *info);
|
||||||
|
|
||||||
void destroy_process(struct process *process);
|
void destroy_process(struct process *process);
|
||||||
void destroy_thread(struct thread *thread);
|
void destroy_thread(struct thread *thread);
|
||||||
|
|
@ -155,3 +169,11 @@ enum ipc_dgram_result syscall_ipc_send_dgram(
|
||||||
|
|
||||||
//f should not return.
|
//f should not return.
|
||||||
void syscall_create_thread(void (*f)(uint64_t x), uint64_t x);
|
void syscall_create_thread(void (*f)(uint64_t x), uint64_t x);
|
||||||
|
|
||||||
|
void set_envvar(struct process *process, const char *key, const char *value);
|
||||||
|
|
||||||
|
//0 if unset
|
||||||
|
struct process_env_pair *get_envvar(struct process *process, const char *key);
|
||||||
|
|
||||||
|
//see comment in include/calcite/syscalls.h
|
||||||
|
void syscall_get_envvar(const char *key, char *value_out, int *value_space);
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
#include "heap.h"
|
||||||
|
|
||||||
int strequ(const char *str1, const char *str2) {
|
int strequ(const char *str1, const char *str2) {
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
@ -35,3 +36,12 @@ uint32_t end_swap_u32(uint32_t value) {
|
||||||
(((value >> 8) & 0xff) << 16) |
|
(((value >> 8) & 0xff) << 16) |
|
||||||
((value & 0xff) << 24);
|
((value & 0xff) << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void double_buffer_zero(void **buffer, int *length, uint64_t bytes_per_entry) {
|
||||||
|
void *new_buffer = heap_alloc(2 * *length * bytes_per_entry);
|
||||||
|
memcpy(new_buffer, *buffer, *length * bytes_per_entry);
|
||||||
|
heap_dealloc(*buffer, *length * bytes_per_entry);
|
||||||
|
memzero(new_buffer + *length * bytes_per_entry, *length * bytes_per_entry);
|
||||||
|
*buffer = new_buffer;
|
||||||
|
*length *= 2;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,3 +27,10 @@ void memzero(void *start, uint64_t bytes);
|
||||||
|
|
||||||
//swaps the endianness of the value
|
//swaps the endianness of the value
|
||||||
uint32_t end_swap_u32(uint32_t value);
|
uint32_t end_swap_u32(uint32_t value);
|
||||||
|
|
||||||
|
//1. allocates a new buffer with 2 * length * bytes_per_entry bytes
|
||||||
|
//2. copies length * bytes_per_entry bytes from old buffer to new buffer
|
||||||
|
//3. deallocates old buffer
|
||||||
|
//4. zeroes rest of new buffer
|
||||||
|
//5. sets buffer and length to new buffer and twice length
|
||||||
|
void double_buffer_zero(void **buffer, int *length, uint64_t bytes_per_entry);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
* with this program. If not, see <https://www.gnu.org/licenses/>.
|
* with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "kernel-public/ipc.h"
|
#include <kernel-public/ipc.h>
|
||||||
#include <calcite/syscalls.h>
|
#include <calcite/syscalls.h>
|
||||||
#include <silver/pam.h>
|
#include <silver/pam.h>
|
||||||
|
|
||||||
|
|
@ -72,20 +72,43 @@ static void copy_frame() {
|
||||||
end_thread();
|
end_thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int strequ(const char *str1, const char *str2) {
|
||||||
|
while (1) {
|
||||||
|
if (*str1 == 0 && *str2 == 0)
|
||||||
|
return 1;
|
||||||
|
if (*str1 != *str2)
|
||||||
|
return 0;
|
||||||
|
++str1;
|
||||||
|
++str2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int memequ(const char *str1, const char *str2, int length) {
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
if (str1[i] != str2[i])
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
map_framebuffer(&fb_info);
|
map_framebuffer(&fb_info);
|
||||||
create_image(fb_info.fb_width, fb_info.fb_height, &fbb);
|
create_image(fb_info.fb_width, fb_info.fb_height, &fbb);
|
||||||
|
|
||||||
|
char buffer[100];
|
||||||
|
|
||||||
|
int bytes = 100;
|
||||||
|
get_envvar("hello", buffer, &bytes);
|
||||||
|
if (bytes != 6 || !strequ(buffer, "world"))
|
||||||
|
panic();
|
||||||
|
|
||||||
ipc_dgram_receiver_handle_t receiver;
|
ipc_dgram_receiver_handle_t receiver;
|
||||||
if (ipc_create_dgram_receiver("calcite-test", &receiver) != IPR_SUCCESS)
|
if (ipc_create_dgram_receiver("calcite-test", &receiver) != IPR_SUCCESS)
|
||||||
panic();
|
panic();
|
||||||
|
|
||||||
char buffer[5];
|
bytes = 100;
|
||||||
int bytes = 5;
|
|
||||||
if (ipc_receive_dgram(receiver, buffer, &bytes) != IPR_SUCCESS ||
|
if (ipc_receive_dgram(receiver, buffer, &bytes) != IPR_SUCCESS ||
|
||||||
bytes != 5 ||
|
bytes != 5 || !memequ(buffer, "hello", 5))
|
||||||
buffer[0] != 'h' || buffer[1] != 'e' || buffer[2] != 'l' || buffer[3] != 'l' || buffer[4] != 'o')
|
|
||||||
panic();
|
panic();
|
||||||
|
|
||||||
if (!load_pam("root://calcite/apps/hello/pointer.pam", &cursor_image))
|
if (!load_pam("root://calcite/apps/hello/pointer.pam", &cursor_image))
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
* with this program. If not, see <https://www.gnu.org/licenses/>.
|
* with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <kernel-public/process.h>
|
||||||
#include <calcite/file-streams.h>
|
#include <calcite/file-streams.h>
|
||||||
#include <kernel-public/files.h>
|
#include <kernel-public/files.h>
|
||||||
#include <kernel-public/ipc.h>
|
#include <kernel-public/ipc.h>
|
||||||
|
|
@ -76,7 +77,15 @@ void main() {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
line[line_length] = 0;
|
line[line_length] = 0;
|
||||||
start_elf(line);
|
|
||||||
|
const char *set_envvars[2] = { "hello", "world" };
|
||||||
|
|
||||||
|
struct process_start_info psi;
|
||||||
|
psi.forwared_envvar_count = 0;
|
||||||
|
psi.set_envvar_count = 1;
|
||||||
|
psi.set_envvars = set_envvars;
|
||||||
|
|
||||||
|
start_elf(line, &psi);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kernel-public/syscall-numbers.h>
|
#include <kernel-public/syscall-numbers.h>
|
||||||
|
#include <kernel-public/process.h>
|
||||||
#include <kernel-public/files.h>
|
#include <kernel-public/files.h>
|
||||||
#include <kernel-public/ipc.h>
|
#include <kernel-public/ipc.h>
|
||||||
#include <calcite/syscalls.h>
|
#include <calcite/syscalls.h>
|
||||||
|
|
@ -66,8 +67,8 @@ void sleep_ms(uint64_t ms_to_sleep) {
|
||||||
do_syscall(ms_to_sleep, 0, 0, SYSCALL_SLEEP_MS);
|
do_syscall(ms_to_sleep, 0, 0, SYSCALL_SLEEP_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
int start_elf(const char *uri) {
|
int start_elf(const char *path, const struct process_start_info *info) {
|
||||||
return do_syscall((uint64_t)uri, 0, 0, SYSCALL_START_ELF);
|
return do_syscall((uint64_t)path, (uint64_t)info, 0, SYSCALL_START_ELF);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ipc_dgram_result ipc_create_dgram_receiver(const char *address, ipc_dgram_receiver_handle_t *handle_out) {
|
enum ipc_dgram_result ipc_create_dgram_receiver(const char *address, ipc_dgram_receiver_handle_t *handle_out) {
|
||||||
|
|
@ -92,3 +93,8 @@ enum ipc_dgram_result ipc_send_dgram(ipc_dgram_sender_handle_t handle, const voi
|
||||||
void create_thread(void (*f)(uint64_t x), uint64_t x) {
|
void create_thread(void (*f)(uint64_t x), uint64_t x) {
|
||||||
do_syscall((uint64_t)f, x, 0, SYSCALL_CREATE_THREAD);
|
do_syscall((uint64_t)f, x, 0, SYSCALL_CREATE_THREAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_envvar(const char *key, char *value_out, int *value_space) {
|
||||||
|
do_syscall(
|
||||||
|
(uint64_t)key, (uint64_t)value_out, (uint64_t)value_space, SYSCALL_GET_ENVVAR);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue