mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Improve init.
This commit is contained in:
parent
77cf804ed2
commit
721157defa
1 changed files with 92 additions and 31 deletions
123
init/init.c++
123
init/init.c++
|
@ -16,13 +16,14 @@
|
|||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
init.c++
|
||||
Initializes the system by setting up the terminal and starting the shell.
|
||||
Start the operating system.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
@ -46,15 +47,6 @@
|
|||
|
||||
#include <fsmarshall.h>
|
||||
|
||||
bool has_descriptor(int fd)
|
||||
{
|
||||
struct stat st;
|
||||
int saved_errno = errno;
|
||||
bool ret = fstat(fd, &st) == 0;
|
||||
errno = saved_errno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* read_single_line(FILE* fp)
|
||||
{
|
||||
char* ret = NULL;
|
||||
|
@ -67,18 +59,14 @@ char* read_single_line(FILE* fp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
char* strdup_null(const char* src)
|
||||
{
|
||||
return src ? strdup(src) : NULL;
|
||||
}
|
||||
|
||||
char* print_string(const char* format, ...)
|
||||
{
|
||||
char* ret = NULL;
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vasprintf(&ret, format, ap);
|
||||
int status = vasprintf(&ret, format, ap);
|
||||
va_end(ap);
|
||||
assert(0 <= status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -86,7 +74,8 @@ char* join_paths(const char* a, const char* b)
|
|||
{
|
||||
size_t a_len = strlen(a);
|
||||
bool has_slash = (a_len && a[a_len-1] == '/') || b[0] == '/';
|
||||
return has_slash ? print_string("%s%s", a, b) : print_string("%s/%s", a, b);
|
||||
return has_slash ? print_string("%s%s", a, b)
|
||||
: print_string("%s/%s", a, b);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
|
@ -137,7 +126,7 @@ bool string_array_append(string_array_t* sa, const char* str)
|
|||
sa->strings = new_strings;
|
||||
sa->capacity = new_capacity;
|
||||
}
|
||||
char* copy = strdup_null(str);
|
||||
char* copy = str ? strdup(str) : NULL;
|
||||
if ( str && !copy )
|
||||
return false;
|
||||
sa->strings[sa->length++] = copy;
|
||||
|
@ -186,13 +175,13 @@ int child()
|
|||
int runsystem()
|
||||
{
|
||||
pid_t childpid = fork();
|
||||
if ( childpid < 0 ) { perror("fork"); return 2; }
|
||||
if ( childpid < 0 )
|
||||
error(2, errno, "fork");
|
||||
|
||||
if ( childpid )
|
||||
{
|
||||
int status;
|
||||
waitpid(childpid, &status, 0);
|
||||
while ( 0 < waitpid(-1, NULL, WNOHANG) );
|
||||
// TODO: Use the proper macro!
|
||||
if ( 128 <= WEXITSTATUS(status) || WIFSIGNALED(status) )
|
||||
{
|
||||
|
@ -205,7 +194,7 @@ int runsystem()
|
|||
exit(child());
|
||||
}
|
||||
|
||||
int chain_boot_path(const char* path, pid_t fs_pid = -1)
|
||||
int chain_boot_path(const char* path)
|
||||
{
|
||||
// Run the next init program and restart it in case of a crash.
|
||||
try_reboot_system:
|
||||
|
@ -213,14 +202,6 @@ try_reboot_system:
|
|||
{
|
||||
int status;
|
||||
waitpid(child_pid, &status, 0);
|
||||
while ( 0 < waitpid(-1, NULL, WNOHANG) );
|
||||
if ( 0 < fs_pid )
|
||||
{
|
||||
int fs_status;
|
||||
kill(fs_pid, SIGTERM);
|
||||
waitpid(fs_pid, &fs_status, 0);
|
||||
}
|
||||
while ( 0 < waitpid(-1, NULL, WNOHANG) );
|
||||
// TODO: Use the proper macro!
|
||||
if ( 128 <= WEXITSTATUS(status) || WIFSIGNALED(status) )
|
||||
{
|
||||
|
@ -364,7 +345,20 @@ int chain_boot_device(const char* dev_path)
|
|||
close(new_dev_fd);
|
||||
close(old_dev_fd);
|
||||
|
||||
int ret = chain_boot_path(mount_point, fs_pid);
|
||||
int ret = chain_boot_path(mount_point);
|
||||
|
||||
int root_fd = open(mount_point, O_RDONLY);
|
||||
if ( 0 <= root_fd )
|
||||
{
|
||||
fsync(root_fd);
|
||||
close(root_fd);
|
||||
}
|
||||
|
||||
unmount(mount_point, 0);
|
||||
|
||||
int fs_exitstatus;
|
||||
waitpid(fs_pid, &fs_exitstatus, 0);
|
||||
|
||||
if ( ret == 127 )
|
||||
return init_emergency(errno, "Unable to locate the next init program");
|
||||
return ret;
|
||||
|
@ -441,8 +435,42 @@ retry_ask_root_block_device:
|
|||
return chain_boot_device(root_block_devices.strings[index]);
|
||||
}
|
||||
|
||||
int main(int /*argc*/, char* /*argv*/[])
|
||||
void set_hostname()
|
||||
{
|
||||
FILE* hostname_fp = fopen("/etc/hostname", "r");
|
||||
if ( !hostname_fp )
|
||||
{
|
||||
if ( errno == ENOENT )
|
||||
return;
|
||||
error(0, errno, "unable to open /etc/hostname, hostname is not set");
|
||||
return;
|
||||
}
|
||||
|
||||
char* hostname = read_single_line(hostname_fp);
|
||||
if ( !hostname )
|
||||
{
|
||||
error(0, errno, "unable to read /etc/hostname, hostname is not set");
|
||||
fclose(hostname_fp);
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(hostname_fp);
|
||||
|
||||
if ( sethostname(hostname, strlen(hostname) + 1) < 0 )
|
||||
{
|
||||
error(0, errno, "unable to set hostname to `%s'", hostname);
|
||||
free(hostname);
|
||||
return;
|
||||
}
|
||||
|
||||
free(hostname);
|
||||
}
|
||||
|
||||
int init_main(int argc, char* argv[])
|
||||
{
|
||||
if ( 3 <= argc && !strcmp(argv[1], "--chain") )
|
||||
return chain_boot_device(argv[2]);
|
||||
|
||||
// Reset the terminal's color and the rest of it.
|
||||
printf(BRAND_INIT_BOOT_MESSAGE);
|
||||
fflush(stdout);
|
||||
|
@ -465,6 +493,9 @@ int main(int /*argc*/, char* /*argv*/[])
|
|||
// Make sure that we have a /tmp directory.
|
||||
mkdir("/tmp", 01777);
|
||||
|
||||
// Set the hostname as found in /etc/hostname.
|
||||
set_hostname();
|
||||
|
||||
// Find the uuid of the root filesystem.
|
||||
const char* root_uuid_file = "/etc/init/rootfs.uuid";
|
||||
FILE* root_uuid_fp = fopen(root_uuid_file, "r");
|
||||
|
@ -485,3 +516,33 @@ int main(int /*argc*/, char* /*argv*/[])
|
|||
|
||||
return chain_boot_uuid(root_uuid);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if ( getpid() == 1 )
|
||||
{
|
||||
pid_t direct_child_pid = fork();
|
||||
if ( direct_child_pid < 0 )
|
||||
error(2, errno, "fork");
|
||||
if ( direct_child_pid )
|
||||
{
|
||||
int status;
|
||||
while ( true )
|
||||
{
|
||||
pid_t child_pid = waitpid(-1, &status, 0);
|
||||
if ( child_pid < 0 )
|
||||
error(2, errno, "waitpid");
|
||||
if ( child_pid == direct_child_pid )
|
||||
break;
|
||||
}
|
||||
int exit_value = WEXITSTATUS(status);
|
||||
// TODO: Broadcast SIGKILL and wait for all processes to finish.
|
||||
while ( 0 < waitpid(-1, &status, WNOHANG) )
|
||||
{
|
||||
}
|
||||
return exit_value;
|
||||
}
|
||||
}
|
||||
|
||||
return init_main(argc, argv);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue