-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinit.c
More file actions
69 lines (59 loc) · 1.63 KB
/
init.c
File metadata and controls
69 lines (59 loc) · 1.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <unistd.h>
#define GETTY "/usr/sbin/getty"
extern char **environ;
static void onterm(int sig) { _exit(0); }
int main(void) {
struct sigaction sa = {0};
sa.sa_handler = onterm;
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
pid_t pid = getpid();
if (pid != 1) {
fprintf(stderr, "(init: can only be run as pid=1)\n");
return EXIT_FAILURE;
}
char *ttyfile = ttyname(STDIN_FILENO);
// remove init pgrp as tty controller
if (tcgetpgrp(STDIN_FILENO) == getpgrp()) {
ioctl(STDIN_FILENO, TIOCNOTTY);
}
// usually there would be more background programs
// spawned here, but we have no background tasks
// spawn getty (login+shell)
pid = fork();
if (pid < 0) {
fprintf(stderr, "(init: fork: %s)\n", strerror(errno));
abort();
}
if (pid == 0) {
char *const gettyargv[] = {GETTY, ttyfile, NULL};
if (execve(GETTY, gettyargv, environ) < 0)
fprintf(stderr, "(init: execve: %s)\n", strerror(errno));
abort();
}
// wait for getty to exit (should never happen)
int status;
if (wait(&status) < 0) {
fprintf(stderr, "(init: wait: %s)\n", strerror(errno));
abort();
}
switch (WIFSIGNALED(status) ? WTERMSIG(status) : -1) {
case SIGSEGV:
fprintf(stderr, "(init: child segmentation fault)\n");
break;
case SIGABRT:
fprintf(stderr, "(init: child aborted)\n");
break;
default:
fprintf(stderr, "(init: child exited with status %d)\n", status);
}
abort();
}