Kernel/Userspace: Add basic init process
This process parses /etc/passwd and promps login screen. When an username is entered, it will launch that users shell
This commit is contained in:
parent
cce2f3e19a
commit
78536f9678
|
@ -0,0 +1,2 @@
|
||||||
|
root:x:0:0::/root:/bin/Shell
|
||||||
|
user:x:1000:1000::/home/user:/bin/Shell
|
|
@ -300,8 +300,6 @@ namespace Kernel
|
||||||
delete range;
|
delete range;
|
||||||
m_mapped_ranges.clear();
|
m_mapped_ranges.clear();
|
||||||
|
|
||||||
m_open_files.clear();
|
|
||||||
|
|
||||||
load_elf_to_memory(*elf);
|
load_elf_to_memory(*elf);
|
||||||
|
|
||||||
m_userspace_info.entry = elf->file_header_native().e_entry;
|
m_userspace_info.entry = elf->file_header_native().e_entry;
|
||||||
|
|
|
@ -180,7 +180,7 @@ static void init2(void* tty1)
|
||||||
|
|
||||||
((TTY*)tty1)->initialize_device();
|
((TTY*)tty1)->initialize_device();
|
||||||
|
|
||||||
MUST(Process::create_userspace({ 0, 0, 0, 0 }, "/usr/bin/Shell"sv));
|
MUST(Process::create_userspace({ 0, 0, 0, 0 }, "/usr/bin/init"sv));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Process::create_kernel(
|
Process::create_kernel(
|
||||||
|
|
|
@ -27,15 +27,6 @@ FILE* stdin = &s_files[0];
|
||||||
FILE* stdout = &s_files[1];
|
FILE* stdout = &s_files[1];
|
||||||
FILE* stderr = &s_files[2];
|
FILE* stderr = &s_files[2];
|
||||||
|
|
||||||
extern "C" void _init_stdio()
|
|
||||||
{
|
|
||||||
char tty[L_ctermid];
|
|
||||||
ctermid(tty);
|
|
||||||
if (open(tty, O_RDONLY) != 0) _exit(1);
|
|
||||||
if (open(tty, O_WRONLY) != 1) _exit(1);
|
|
||||||
if (open(tty, O_WRONLY) != 2) _exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearerr(FILE* file)
|
void clearerr(FILE* file)
|
||||||
{
|
{
|
||||||
file->eof = false;
|
file->eof = false;
|
||||||
|
|
|
@ -11,12 +11,9 @@
|
||||||
|
|
||||||
char** environ;
|
char** environ;
|
||||||
|
|
||||||
extern "C" void _init_stdio();
|
|
||||||
|
|
||||||
extern "C" void _init_libc(char** _environ)
|
extern "C" void _init_libc(char** _environ)
|
||||||
{
|
{
|
||||||
environ = _environ;
|
environ = _environ;
|
||||||
_init_stdio();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _exit(int status)
|
void _exit(int status)
|
||||||
|
|
|
@ -5,6 +5,7 @@ project(userspace CXX)
|
||||||
set(USERSPACE_PROJECTS
|
set(USERSPACE_PROJECTS
|
||||||
cat
|
cat
|
||||||
echo
|
echo
|
||||||
|
init
|
||||||
ls
|
ls
|
||||||
Shell
|
Shell
|
||||||
test
|
test
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
cmake_minimum_required(VERSION 3.26)
|
||||||
|
|
||||||
|
project(init CXX)
|
||||||
|
|
||||||
|
set(SOURCES
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(init ${SOURCES})
|
||||||
|
target_compile_options(init PUBLIC -O2 -g)
|
||||||
|
target_link_libraries(init PUBLIC libc ban)
|
||||||
|
|
||||||
|
add_custom_target(init-install
|
||||||
|
COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/init ${BANAN_BIN}/
|
||||||
|
DEPENDS init
|
||||||
|
)
|
|
@ -0,0 +1,153 @@
|
||||||
|
#include <BAN/String.h>
|
||||||
|
#include <BAN/Optional.h>
|
||||||
|
#include <BAN/Vector.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
struct User
|
||||||
|
{
|
||||||
|
BAN::String name;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
BAN::String home;
|
||||||
|
BAN::String shell;
|
||||||
|
};
|
||||||
|
|
||||||
|
BAN::Optional<id_t> parse_id(BAN::StringView value)
|
||||||
|
{
|
||||||
|
// NOTE: we only allow 10^9 uids
|
||||||
|
if (value.size() < 1 || value.size() > 9)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
id_t id { 0 };
|
||||||
|
for (char c : value)
|
||||||
|
{
|
||||||
|
if (!isdigit(c))
|
||||||
|
return {};
|
||||||
|
id = (id * 10) + (c - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::Optional<User> parse_user(BAN::StringView line)
|
||||||
|
{
|
||||||
|
auto parts = MUST(line.split(':', true));
|
||||||
|
if (parts.size() != 7)
|
||||||
|
return {};
|
||||||
|
User user;
|
||||||
|
user.name = parts[0];
|
||||||
|
user.uid = ({ auto id = parse_id(parts[2]); if (!id.has_value()) return {}; id.value(); });
|
||||||
|
user.gid = ({ auto id = parse_id(parts[3]); if (!id.has_value()) return {}; id.value(); });
|
||||||
|
user.home = parts[5];
|
||||||
|
user.shell = parts[6];
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::Vector<User> parse_users()
|
||||||
|
{
|
||||||
|
FILE* fp = fopen("/etc/passwd", "r");
|
||||||
|
if (fp == nullptr)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "could not open /etc/passwd\n");
|
||||||
|
perror("fopen");
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::Vector<User> users;
|
||||||
|
|
||||||
|
char buffer[1024];
|
||||||
|
while (fgets(buffer, sizeof(buffer), fp))
|
||||||
|
{
|
||||||
|
*strchrnul(buffer, '\n') = '\0';
|
||||||
|
auto user = parse_user(buffer);
|
||||||
|
if (user.has_value())
|
||||||
|
MUST(users.push_back(user.release_value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ferror(fp))
|
||||||
|
{
|
||||||
|
perror("fread");
|
||||||
|
fclose(fp);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize_stdio()
|
||||||
|
{
|
||||||
|
char tty[L_ctermid];
|
||||||
|
ctermid(tty);
|
||||||
|
if (open(tty, O_RDONLY) != 0) _exit(1);
|
||||||
|
if (open(tty, O_WRONLY) != 1) _exit(1);
|
||||||
|
if (open(tty, O_WRONLY) != 2) _exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
initialize_stdio();
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
auto users = parse_users();
|
||||||
|
|
||||||
|
char name_buffer[128];
|
||||||
|
BAN::StringView name;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
printf("username: ");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
size_t nread = fread(name_buffer, 1, sizeof(name_buffer) - 1, stdin);
|
||||||
|
if (nread == 0)
|
||||||
|
{
|
||||||
|
if (ferror(stdin))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Could not read from stdin\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (nread == 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
name = BAN::StringView(name_buffer, nread - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const User& user : users)
|
||||||
|
{
|
||||||
|
if (user.name == name)
|
||||||
|
{
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == 0)
|
||||||
|
{
|
||||||
|
printf("Welcome back %s!\n", user.name.data());
|
||||||
|
|
||||||
|
execl(user.shell.data(), user.shell.data(), nullptr);
|
||||||
|
perror("execl");
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid == -1)
|
||||||
|
{
|
||||||
|
perror("fork");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status;
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue