First commit
This commit is contained in:
15
.clang-format
Normal file
15
.clang-format
Normal file
@@ -0,0 +1,15 @@
|
||||
# Tabs
|
||||
UseTab: ForContinuationAndIndentation #ForIndentation
|
||||
# Sized
|
||||
TabWidth: 8
|
||||
IndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
|
||||
# Column Limit
|
||||
ColumnLimit: 80
|
||||
|
||||
# Functions
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
|
||||
# Allman
|
||||
BreakBeforeBraces: Allman
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
**.o
|
||||
poweroff
|
||||
5
LICENSE
Normal file
5
LICENSE
Normal file
@@ -0,0 +1,5 @@
|
||||
Copyright (c) 2025 by PedroEdiaz <ppedroediaz (at) gmail.com>.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
12
Makefile
Normal file
12
Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
OBJ = init.o libexec/boot.o libexec/shut.o libexec/common.o
|
||||
BIN = init
|
||||
|
||||
all: $(BIN) poweroff
|
||||
|
||||
$(BIN): $(OBJ)
|
||||
$(CC) $(LDFLAGS) -o $@ $(OBJ) $(LDLIBS)
|
||||
|
||||
fmt:
|
||||
clang-format -i *.c libexec/*.c
|
||||
clean:
|
||||
rm -f $(BIN) $(OBJ)
|
||||
49
init.c
Normal file
49
init.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void boot(void);
|
||||
void shut(char);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int sig;
|
||||
sigset_t set;
|
||||
size_t i;
|
||||
|
||||
if (getpid() != 1)
|
||||
return 1;
|
||||
|
||||
chdir("/");
|
||||
|
||||
sigfillset(&set);
|
||||
sigprocmask(SIG_BLOCK, &set, NULL);
|
||||
|
||||
nice(15);
|
||||
boot();
|
||||
|
||||
restart:
|
||||
while (1)
|
||||
{
|
||||
sigwait(&set, &sig);
|
||||
|
||||
switch (sig)
|
||||
{
|
||||
case SIGUSR1:
|
||||
shut('p');
|
||||
goto restart;
|
||||
case SIGCHLD:
|
||||
case SIGALRM:
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0)
|
||||
;
|
||||
goto restart;
|
||||
case SIGINT:
|
||||
shut('r');
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
/* not reachable */
|
||||
return 0;
|
||||
}
|
||||
100
libexec/boot.c
Normal file
100
libexec/boot.c
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "config.h"
|
||||
void boot(void)
|
||||
{
|
||||
log("Mounting pseudo filesystem...");
|
||||
{
|
||||
mount("proc", "/proc", "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV,
|
||||
NULL);
|
||||
mount("sys", "/sys", "sysfs", MS_NOSUID | MS_NOEXEC | MS_NODEV,
|
||||
NULL);
|
||||
mount("cache", "/var/cache", "tmpfs",
|
||||
MS_NOSUID | MS_NOEXEC | MS_NODEV, "mode=0777");
|
||||
mount("tmp", "/tmp", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV,
|
||||
"mode=0777");
|
||||
mount("run", "/run", "tmpfs", MS_NOSUID | MS_NODEV,
|
||||
"mode=0777");
|
||||
mount("dev", "/dev", "devtmpfs", MS_NOSUID, "mode=0755");
|
||||
|
||||
mkdir("/dev/pts", 0755);
|
||||
mkdir("/dev/shm", 0755);
|
||||
mount("devpts", "/dev/pts", "devpts", MS_NOSUID | MS_NOEXEC,
|
||||
"mode=0620,gid=5");
|
||||
mount("shm", "/dev/shm", "tmpfs", MS_NOSUID | MS_NODEV,
|
||||
"mode=1777");
|
||||
|
||||
symlink("/proc/self/fd", "/dev/fd");
|
||||
symlink("fd/0", "/dev/stdin");
|
||||
symlink("fd/1", "/dev/stdout");
|
||||
symlink("fd/2", "/dev/stderr");
|
||||
|
||||
mkdir("/run/lock", 0755);
|
||||
}
|
||||
|
||||
log("Set up loopback...");
|
||||
{
|
||||
int fd, i;
|
||||
struct sockaddr_in *addr;
|
||||
struct ifreq iface;
|
||||
const char *ifname = "lo";
|
||||
|
||||
fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
|
||||
iface.ifr_addr.sa_family = AF_INET;
|
||||
for (i = 0; iface.ifr_name[i] = ifname[i]; ++i)
|
||||
;
|
||||
|
||||
addr = (struct sockaddr_in *)&iface.ifr_addr;
|
||||
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_addr.s_addr = 0x0100007f;
|
||||
ioctl(fd, SIOCSIFADDR, &iface);
|
||||
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_addr.s_addr = 0x0000ff;
|
||||
ioctl(fd, SIOCSIFNETMASK, &iface);
|
||||
|
||||
iface.ifr_flags |= (IFF_UP | IFF_RUNNING | IFF_LOOPBACK);
|
||||
ioctl(fd, SIOCSIFFLAGS, &iface);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
log("Setting hostname...");
|
||||
{
|
||||
char buf[64];
|
||||
long result;
|
||||
int input, output;
|
||||
|
||||
#warning callback if HOSTNAME doesnot exists
|
||||
input = open(HOSTFILE, O_RDONLY);
|
||||
output = open("/proc/sys/kernel/hostname", O_WRONLY);
|
||||
|
||||
while (result = read(input, buf, sizeof(buf)))
|
||||
write(output, buf, result);
|
||||
|
||||
close(input);
|
||||
close(output);
|
||||
}
|
||||
log("Seeding urandom...");
|
||||
{
|
||||
char buf[64];
|
||||
long result;
|
||||
int input, output;
|
||||
|
||||
output = open("/dev/urandom", O_WRONLY);
|
||||
|
||||
#warning callback if input doesnot exists
|
||||
if (input = open(SEEDFILE, O_RDONLY))
|
||||
;
|
||||
{
|
||||
while (result = read(input, buf, sizeof(buf)))
|
||||
write(output, buf, result);
|
||||
}
|
||||
|
||||
close(input);
|
||||
close(output);
|
||||
}
|
||||
|
||||
log("Running programs...");
|
||||
runprgs((void *)boot_cmd, sizeof(boot_cmd) / sizeof(boot_cmd[0]));
|
||||
}
|
||||
57
libexec/common.c
Normal file
57
libexec/common.c
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "config.h"
|
||||
|
||||
int len(const char *msg)
|
||||
{
|
||||
char *p;
|
||||
for (p = (char *)msg; *p; ++p)
|
||||
;
|
||||
return p - msg;
|
||||
}
|
||||
|
||||
void log(const char *msg)
|
||||
{
|
||||
write(1, "=> ", 4);
|
||||
write(1, msg, len(msg));
|
||||
write(1, "\n", 1);
|
||||
}
|
||||
|
||||
void runprgs(struct cmd *cmds, int n)
|
||||
{
|
||||
int tty, i;
|
||||
tty = open(LOGTO, O_WRONLY);
|
||||
close(1);
|
||||
close(2);
|
||||
dup2(tty, 1);
|
||||
dup2(tty, 2);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
int pid;
|
||||
|
||||
if (cmds[i].flags == RESPAWN)
|
||||
{
|
||||
if (fork())
|
||||
goto end;
|
||||
}
|
||||
|
||||
loop:
|
||||
pid = fork();
|
||||
|
||||
if (!pid)
|
||||
{
|
||||
execve(cmds[i].args[0], cmds[i].args, NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (cmds[i].flags)
|
||||
{
|
||||
case RESPAWN:
|
||||
waitpid(pid, NULL, 0);
|
||||
sleep(1);
|
||||
goto loop;
|
||||
case WAIT:
|
||||
wait4(pid, NULL, 0, NULL);
|
||||
}
|
||||
end:;
|
||||
}
|
||||
}
|
||||
23
libexec/common.h
Normal file
23
libexec/common.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#define NOFLAGS 0b00
|
||||
#define WAIT 0b01
|
||||
#define RESPAWN 0b10
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/reboot.h>
|
||||
|
||||
struct cmd
|
||||
{
|
||||
char flags;
|
||||
char *args[10];
|
||||
};
|
||||
|
||||
void log( const char * );
|
||||
|
||||
void runprgs( struct cmd * cmds, int n );
|
||||
27
libexec/config.h
Normal file
27
libexec/config.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "common.h"
|
||||
|
||||
#define LOGTO "/dev/tty3"
|
||||
#define SEEDFILE "/var/lib/init/seed"
|
||||
#define HOSTFILE "/etc/hostname"
|
||||
|
||||
static const
|
||||
struct cmd boot_cmd[] =
|
||||
{
|
||||
{ WAIT, { "/bin/mount", "-a", NULL } },
|
||||
{ WAIT, { "/bin/mount", "-o", "rw,remount", "/", NULL } },
|
||||
{ NOFLAGS, { "/bin/smdev", "-s", NULL } },
|
||||
#if 0
|
||||
{ NOFLAGS, { "/bin/alsactl", "restore", NULL } },
|
||||
#endif
|
||||
{ RESPAWN, { "/bin/agetty", "tty1", "38400", "linux", NULL } },
|
||||
{ RESPAWN, { "/bin/agetty", "tty2", "38400", "linux", NULL } },
|
||||
{ RESPAWN, { "/bin/nldev", NULL } },
|
||||
{ RESPAWN, { "/bin/wsupp", "wlan0", NULL } },
|
||||
};
|
||||
|
||||
static const
|
||||
struct cmd shut_cmd[] =
|
||||
{
|
||||
{ WAIT, { "/sbin/killall5", "9", NULL } },
|
||||
{ WAIT, { "/sbin/umount", "-a", NULL } },
|
||||
};
|
||||
23
libexec/shut.c
Normal file
23
libexec/shut.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "config.h"
|
||||
|
||||
void shut(char c)
|
||||
{
|
||||
log("Saving seed...");
|
||||
{
|
||||
char buf[512];
|
||||
int input, output;
|
||||
|
||||
input = open("/dev/urandom", O_RDONLY);
|
||||
output = open(SEEDFILE, O_WRONLY);
|
||||
|
||||
write(output, buf, read(input, buf, sizeof(buf)));
|
||||
|
||||
close(input);
|
||||
close(output);
|
||||
}
|
||||
|
||||
log("Running programs...");
|
||||
runprgs((void *)shut_cmd, sizeof(shut_cmd) / sizeof(shut_cmd[0]));
|
||||
|
||||
reboot((c == 'r') ? RB_AUTOBOOT : RB_POWER_OFF);
|
||||
}
|
||||
6
poweroff.c
Normal file
6
poweroff.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <signal.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return kill(1, (argv[0][0] == 'r') ? SIGINT : SIGUSR1);
|
||||
}
|
||||
Reference in New Issue
Block a user