Embedded finit for small embedded Linux systems and servers.

o Make finit-alt.c the new finit.c, save old finit.c as finit-org.c
o Keep original finit-alt.c for reference.
o Update README and ChangeLog with direction of this fork
o Correct ChangeLog date for v0.1 and set release date for
  the 0.6-pre release to 20100614, which is the last commit
  by the original author.
o Add standard LICENSE file for MIT License
o Add standard AUTHORS file to document history of project
o Bump version to 1.0-pre to distance fork from original

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson committed 2012-09-14 13:10:39 +02:00
1 parent f92438d42a
commit 5816c9cab9
8 files changed
+801 -133

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
Current Maintainer(s):
* Joachim Nilsson <troglobit@gmail.com>
Original Author(s):
* Claudio Matsuoka <cmatsuoka@gmail.com>
+9 -2
View File
@@ -1,4 +1,11 @@
0.6 ()
1.0 (UNRELEASED)
- New maintainer at GitHub http://github.com/troglobit/finit
- Make the unused finit.c finit-org.c for archival purposes
- Make finit-alt.c the new default finit.c
- Add standard LICENSE and AUTHORS files
- New focus: embedded systems and small headless servers
0.6 (20100614)
- don't start consolekit manually, dbus starts it (rtp)
- unmount all filesystems before rebooting
- disable USE_VAR_RUN_RESOLVCONF for Mandriva
@@ -43,5 +50,5 @@ O.4 (20080516)
- moved finit-mod and finit-alt helpers to helpers.c
- replace system("echo;cat") to draw shutdown splash with C calls
0.1 (20081214)
0.1 (20080214)
- initial release
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2008 Claudio Matsuoka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+10 -10
View File
@@ -3,17 +3,17 @@ CFLAGS = -Os -Wall -DVERSION=\"$(VERSION)\" -DWHOAMI=\"`whoami`@`hostname`\"
LD = gcc
LDFLAGS =
LIBS =
VERSION = 0.6-pre
VERSION = 1.0-pre
PKG = finit-$(VERSION)
DFILES = Makefile README finit.c finit-mod.c finit-alt.c helpers.c helpers.h \
DFILES = Makefile README finit.c finit-mod.c finit-org.c helpers.c helpers.h \
patches/*patch contrib/services.sh* contrib/Makefile.*
BINS = finit-mod finit-alt finit-mdv #finit-exb
BINS = finit finit-mod finit-mdv #finit-exb
#### Configurable parameters
# Default user for finit-alt if not "user"
# Default user for finit if not "user"
#DEFUSER = fred
# Disable annoying gcc warning
@@ -46,7 +46,7 @@ endif
all: $(BINS)
finit: finit.o
finit-org: finit-org.o
$(LD) $(LDFLAGS) -o $@ $+ $(LIBS)
strip $@
@@ -54,7 +54,7 @@ finit-mod: finit-mod.o helpers.o
$(LD) $(LDFLAGS) -o $@ $+ $(LIBS)
strip $@
finit-alt: finit-alt.o helpers.o
finit: finit.o helpers.o
$(LD) $(LDFLAGS) -o $@ $+ $(LIBS)
strip $@
@@ -62,15 +62,15 @@ finit-mdv: finit-mdv.o helpers.o
$(LD) $(LDFLAGS) -o $@ $+ $(LIBS)
strip $@
finit-mdv.o: finit-alt.c Makefile
$(CC) -c $(CFLAGS) -DDIST_MDV -o $@ finit-alt.c
finit-mdv.o: finit.c Makefile
$(CC) -c $(CFLAGS) -DDIST_MDV -o $@ finit.c
finit-exb: finit-exb.o helpers.o
$(LD) $(LDFLAGS) -o $@ $+ $(LIBS)
strip $@
finit-exb.o: finit-alt.c Makefile
$(CC) -c $(CFLAGS) -DDIST_EEEXUBUNTU -o $@ finit-alt.c
finit-exb.o: finit.c Makefile
$(CC) -c $(CFLAGS) -DDIST_EEEXUBUNTU -o $@ finit.c
clean:
rm -f *.o core *~ $(BINS)
+35 -20
View File
@@ -1,36 +1,50 @@
Finit -- A reimplementation of the EeePC SysV init replacement "fastinit"
=========================================================================
Finit is a reimplementation of the Eeepc "fastinit" program based on its
Finit is a reimplementation of the EeePC "fastinit" program based on its
system calls with gaps filled with frog DNA.
Finit's purpose is to build upon the general workings of fastinit and
improve/optimize it for Xandros or alternative distributions running on
the Eeepc. Finit comes in three flavors: finit is a replica of the Asus
fastinit, finit-mod is an improved drop-in replacement for fastinit,
and finit-alt is a generic replacement for other systems. Finit-mod
and finit-alt were much improved with patches from Metalshark.
Finit's original purpose was to build upon the general workings of the
EeePC fastinit and improve/optimize it for Xandros or alternative
distributions running on the Eeepc. However, focus has now shifted to
small embedded Linux systems and headless miniature servers with a need
for extremely fast boot.
See more information at http://helllabs.org/finit/
Nevertheless, finit comes in three flavors:
o finit-org is a replica of the Asus fastinit,
o finit-mod is an improved drop-in replacement for fastinit, and
o finit is a generic replacement for other systems.
Finit-mod and finit (previously finit-alt) were much improved with
patches from Metalshark.
See the GitHub project's Wiki at https://github.com/troglobit/finit, or
the original author's home page at http://helllabs.org/finit/ for more
information.
Usage scenarios
---------------
1. Replace the original Eeepc 702 fastinit (finit-mod)
1. Provide an extremely fine tuned and fast boot on embedded systems or
Linux distributions for the EeePC or other netbooks. (finit)
2. Allow fast booting in alternative Linux distributions running on the
Eeepc and other netbooks (finit-alt)
2. Replace the original Eeepc 702 fastinit (finit-mod)
3. Provide a reverse engineered document of the original EeePC fastinit
implementation. (finit-org)
Finit is distribution-specific. Currently it generates a finit-mdv
executable for Mandriva 2008/2008.1 systems. Smurfy ported it to
eeeXubuntu, and parts of his port have been merged to finit.
Finit-alt is distribution-specific. Currently it generates a finit-mdv
executable for Mandriva 2008/2008.1 systems. Smurfy ported it to
eeeXubuntu, and parts of his port have been merged to finit-alt.
Finit features
--------------
Finit-alt features
------------------
Finit-alt reads configuration information from /etc/finit.conf. See
the source code for available options.
Finit reads configuration information from /etc/finit.conf. See the
source code for available options.
Rebooting and halting
@@ -46,3 +60,4 @@ Debugging
Add finit_debug to the kernel parameter line to enable trace messages
and to run a shell after the X server.
+10 -10
View File
@@ -3,17 +3,17 @@ CFLAGS = -Os -Wall -DVERSION=\"$(VERSION)\" -DWHOAMI=\"`whoami`@`hostname`\"
LD = gcc
LDFLAGS =
LIBS =
VERSION = 0.6-pre
VERSION = 0.7-pre
PKG = finit-$(VERSION)
DFILES = Makefile README finit.c finit-mod.c finit-alt.c helpers.c helpers.h \
DFILES = Makefile README finit-org.c finit-mod.c finit.c helpers.c helpers.h \
patches/*patch contrib/services.sh*
BINS = finit-mod finit-alt finit-mdv #finit-exb
BINS = finit-mod finit finit-mdv #finit-exb
#### Configurable parameters
# Default user for finit-alt if not "user"
# Default user for finit if not "user"
#DEFUSER = fred
# Use -march=pentium-m to build for Eeepc
@@ -51,7 +51,7 @@ finit-mod: finit-mod.o helpers.o
$(LD) $(LDFLAGS) -o $@ $+ $(LIBS)
strip $@
finit-alt: finit-alt.o helpers.o
finit: finit.o helpers.o
$(LD) $(LDFLAGS) -o $@ $+ $(LIBS)
strip $@
@@ -59,20 +59,20 @@ finit-mdv: finit-mdv.o helpers.o
$(LD) $(LDFLAGS) -o $@ $+ $(LIBS)
strip $@
finit-mdv.o: finit-alt.c Makefile
$(CC) -c $(CFLAGS) -DDIST_MDV -o $@ finit-alt.c
finit-mdv.o: finit.c Makefile
$(CC) -c $(CFLAGS) -DDIST_MDV -o $@ finit.c
finit-exb: finit-exb.o helpers.o
$(LD) $(LDFLAGS) -o $@ $+ $(LIBS)
strip $@
finit-exb.o: finit-alt.c Makefile
$(CC) -c $(CFLAGS) -DDIST_EEEXUBUNTU -o $@ finit-alt.c
finit-exb.o: finit.c Makefile
$(CC) -c $(CFLAGS) -DDIST_EEEXUBUNTU -o $@ finit.c
clean:
rm -f *.o core *~ $(BINS)
finit.o: finit.c Makefile
finit.o: finit-org.c Makefile
finit-mod.o: finit-mod.c Makefile
+282
View File
@@ -0,0 +1,282 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/reboot.h>
#include <sys/wait.h>
#include <linux/fs.h>
/* From sysvinit */
/* Set a signal handler. */
#define SETSIG(sa, sig, fun, flags) \
do { \
sa.sa_handler = fun; \
sa.sa_flags = flags; \
sigemptyset(&sa.sa_mask); \
sigaction(sig, &sa, NULL); \
} while(0)
#define touch(x) close(open((x), O_CREAT|O_WRONLY|O_TRUNC, 0644))
void shutdown(int);
void signal_handler(int);
void chld_handler(int);
int main()
{
int i;
FILE *f;
char line[2096];
int fd;
DIR *dir;
struct dirent *d;
char filename[1024];
struct sigaction sa, act;
char hline[1024];
char *x;
sigset_t nmask, nmask2;
chdir("/");
umask(022);
/*
* Signal management
*/
for (i = 1; i < NSIG; i++)
SETSIG(sa, i, SIG_IGN, SA_RESTART);
SETSIG(sa, SIGINT, shutdown, 0);
SETSIG(sa, SIGPWR, signal_handler, 0);
SETSIG(sa, SIGUSR1, shutdown, 0);
SETSIG(sa, SIGUSR2, shutdown, 0);
SETSIG(sa, SIGTERM, signal_handler, 0);
SETSIG(sa, SIGKILL, signal_handler, 0);
SETSIG(sa, SIGALRM, signal_handler, 0);
SETSIG(sa, SIGHUP, signal_handler, 0);
SETSIG(sa, SIGSTOP, signal_handler, SA_RESTART);
SETSIG(sa, SIGCONT, signal_handler, SA_RESTART);
SETSIG(sa, SIGCHLD, chld_handler, SA_RESTART);
/* Block sigchild while forking */
sigemptyset(&nmask);
sigaddset(&nmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &nmask, NULL);
reboot(RB_DISABLE_CAD);
/*
* Parse kernel parameters
*/
if ((f = fopen("/proc/cmdline", "r")) != NULL) {
fgets(line, 2095, f);
if (strstr(line, "quiet")) {
close(0);
close(1);
close(2);
}
fclose(f);
}
setsid();
/*
* Mount filesystems
*/
mount("proc", "/proc", "proc", 0, NULL);
mount("sysfs", "/sys", "sysfs", 0, NULL);
mount("devpts", "/dev/pts", "devpts", 0, "gid=5,mode=620");
mount("tmpfs", "/dev/shm", "tmpfs", 0, NULL);
mount("tmpfs", "/tmp", "tmpfs", 0, "mode=1777,size=128m");
mount("/mnt", "/", NULL, MS_MOVE, NULL);
/*
* Time adjustments
*/
if ((fd = open("/etc/adjtime", O_CREAT|O_WRONLY|O_TRUNC, 0644)) >= 0) {
write(fd, "0.0 0 0.0\n", 10);
close(fd);
}
system("/sbin/hwclock --hctosys --localtime");
/*
* Network stuff
*/
system("mkdir -p /dev/shm/network");
system("mkdir -p /dev/shm/resolvconf/interface");
if ((dir = opendir("/etc/resolvconf/run/interface")) != NULL) {
while ((d = readdir(dir)) != NULL) {
if (isalnum(d->d_name[0]))
continue;
sprintf(filename, "/etc/resolvconf/run/interface/%s",
d->d_name);
unlink(filename);
}
closedir(dir);
}
touch("/var/run/utmp");
touch("/etc/resolvconf/run/enable-updates");
chdir("/etc/resolvconf/run/interface");
system("/bin/run-parts --arg=-i /etc/resolvconf/update.d");
chdir("/");
touch("/etc/network/run/ifstate");
if ((f = fopen("/etc/hostname", "r")) != NULL) {
fgets(hline, 1023, f);
if ((x = strchr(hline, 0x0a)) != NULL)
*x = 0;
sethostname(hline, strlen(hline));
fclose(f);
}
system("/sbin/ifconfig lo 127.0.0.1 netmask 255.0.0.0 up > /dev/null");
/*
* Set random seed
*/
/* Bug: the eeepc never sets its random seed from file */
system("/bin/cat /var/lib/urandom/random-seed >/dev/urandom "
"> /dev/null 2>&1");
unlink("/var/lib/urandom/random-seed");
umask(077);
system("/bin/dd if=/dev/urandom of=/var/lib/urandom/random-seed "
"bs=4096 count=1 >/dev/null 2>&1");
/*
* Misc setup
*/
/* not really needed, /tmp is a fresh mounted tmpfs */
system("/bin/rm -rf /tmp/* /tmp/.* 2>/dev/null");
unlink("/var/run/.clean");
unlink("/var/lock/.clean");
umask(0);
mkdir("/tmp/.X11-unix", 01777);
mkdir("/tmp/.ICE-unix", 01777);
umask(022);
if (!fork()) {
/* child process */
vhangup();
close(2);
close(1);
close(0);
if (open("/dev/tty1", O_RDWR, 0))
exit(1);
sigemptyset(&act.sa_mask);
act.sa_handler = SIG_DFL;
sigemptyset(&nmask2);
sigaddset(&nmask2, SIGCHLD);
sigprocmask(SIG_UNBLOCK, &nmask2, NULL);
/* Bug: no signal 0 */
for (i = 0; i < NSIG; i++)
sigaction(i, &sa, NULL);
dup2(0, 0);
dup2(0, 1);
dup2(0, 2);
touch("/tmp/nologin");
while (access("/tmp/shutdown", F_OK) < 0)
system("su -c startx -l user &> /dev/null");
exit(0);
}
/* parent process */
system("/sbin/getty 38400 tty3 &");
sleep(1);
system("/usr/sbin/services.sh &> /dev/null &");
while (1) {
sigemptyset(&nmask);
pselect(0, NULL, NULL, NULL, NULL, &nmask);
}
}
/*
* Shut down on INT USR1 USR2
*/
void shutdown(int sig)
{
int fd;
system("/usr/bin/touch /tmp/shutdown");
kill(-1, SIGTERM);
system("/bin/echo -e \"\033[?25l\033[30;40m\"; "
"/bin/cp /boot/shutdown.fb /dev/fb/0");
sleep(1);
sleep(1);
system("/usr/sbin/alsactl store > /dev/null 2>&1");
system("/sbin/hwclock --systohc --localtime");
kill(-1, SIGKILL);
sync();
sync();
system("/bin/mount -n -o remount,ro /");
system("/sbin/unionctl.static / --remove / > /dev/null 2>&1");
if (sig == SIGINT || sig == SIGUSR1)
reboot(RB_AUTOBOOT);
if ((fd = open("/proc/acpi/sleep", O_WRONLY)) >= 0) {
write(fd, "5", 1);
close(fd);
}
}
/*
* SIGCHLD: one of our children has died
*/
void chld_handler(int sig)
{
int status;
while (waitpid(-1, &status, WNOHANG) != 0) {
if (errno == ECHILD)
break;
}
}
/*
* We got a signal (PWR TERM ALRM HUP STOP CONT)
*/
void signal_handler(int sig)
{
/* do nothing */
}
+430 -91
View File
@@ -1,3 +1,26 @@
/*
Improved fast init
Copyright (c) 2008 Claudio Matsuoka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
@@ -14,6 +37,51 @@
#include <sys/reboot.h>
#include <sys/wait.h>
#include <linux/fs.h>
#include <utmp.h>
#include "helpers.h"
#ifndef DEFUSER
#define DEFUSER "user"
#endif
/* Distribution configuration */
#if defined DIST_MDV /* Mandriva */
#define RANDOMSEED "/var/lib/random-seed"
#define SYSROOT "/sysroot"
#define GETTY "/usr/bin/openvt /sbin/mingetty tty2"
#define RUNPARTS "/usr/bin/run-parts"
#define REMOUNT_ROOTFS_RW
#define MAKE_DEVICES
#define MAKE_DEV_VCS
#define PAM_CONSOLE
#define LISTEN_INITCTL
#define RUNLEVEL 5
#define USE_MESSAGE_BUS
#elif defined DIST_EEEXUBUNTU /* eeeXubuntu */
#define RANDOMSEED "/var/lib/urandom/random-seed"
#define SYSROOT "/sysroot"
#define GETTY "/usr/bin/openvt /sbin/getty 38400 tty2"
#define RUNPARTS "/bin/run-parts"
#define REMOUNT_ROOTFS_RW
#define MAKE_DEVICES
#define TOUCH_ETC_NETWORK_RUN_IFSTATE
#define LISTEN_INITCTL
#else /* original Eeepc distribution */
#define RANDOMSEED "/var/lib/urandom/random-seed"
#define SYSROOT "/mnt"
#define GETTY "/usr/bin/openvt /sbin/getty 38400 tty2"
#define RUNPARTS "/bin/run-parts"
#define TOUCH_ETC_NETWORK_RUN_IFSTATE
#define USE_ETC_RESOLVCONF_RUN
#endif
#ifdef DIRECTISA
#define HWCLOCK_DIRECTISA " --directisa"
#else
#define HWCLOCK_DIRECTISA
#endif
/* From sysvinit */
@@ -24,29 +92,124 @@
sa.sa_flags = flags; \
sigemptyset(&sa.sa_mask); \
sigaction(sig, &sa, NULL); \
} while(0)
} while (0)
#define touch(x) close(open((x), O_CREAT|O_WRONLY|O_TRUNC, 0644))
#ifdef LISTEN_INITCTL
#define INIT_MAGIC 0x03091969
#define INIT_CMD_RUNLVL 1
struct init_request {
int magic; /* Magic number */
int cmd; /* What kind of request */
int runlevel; /* Runlevel to change to */
int sleeptime; /* Time between TERM and KILL */
char data[368];
};
#endif
#define touch(x) mknod((x), S_IFREG|0644, 0)
#define chardev(x,m,maj,min) mknod((x), S_IFCHR|(m), makedev((maj),(min)))
#define blkdev(x,m,maj,min) mknod((x), S_IFBLK|(m), makedev((maj),(min)))
#define MATCH_CMD(l,c,x) \
((!strncmp((l), (c), strlen((c)))) && ((x) = (l) + strlen((c))))
#define _d(x...) do { if (debug) { printf(x); printf("\n"); } } while (0)
#define LINE_SIZE 1024
#define CMD_SIZE 256
#define USERNAME_SIZE 16
#define HOSTNAME_SIZE 32
void shutdown(int);
void signal_handler(int);
void chld_handler(int);
static int debug = 0;
static char sdown[CMD_SIZE];
static void build_cmd(char *cmd, char *x, int len)
{
int l;
char *c;
c = cmd + strlen(cmd);
/* skip spaces */
for (; *x && (*x == ' ' || *x == '\t'); x++);
/* copy next arg */
for (l = 0; *x && *x != '#' && *x != '\t' && l < len; l++)
*c++ = *x++;
*c = 0;
_d("cmd = %s", cmd);
}
#ifdef LISTEN_INITCTL
/* Standard reboot/shutdown utilities talk to init using /dev/initctl.
* We should check if the fifo was recreated and reopen it.
*/
static void listen_initctl()
{
if (!fork()) {
int ctl;
fd_set fds;
struct init_request request;
mkfifo("/dev/initctl", 0600);
ctl = open("/dev/initctl", O_RDONLY);
while (1) {
FD_ZERO(&fds);
FD_SET(ctl, &fds);
if (select(ctl + 1, &fds, NULL, NULL, NULL) <= 0)
continue;
read(ctl, &request, sizeof(request));
if (request.magic != INIT_MAGIC)
continue;
if (request.cmd == INIT_CMD_RUNLVL) {
switch (request.runlevel) {
case '0':
shutdown(SIGUSR2);
break;
case '6':
shutdown(SIGUSR1);
}
}
}
}
}
#endif
int main()
{
int i;
FILE *f;
char line[2096];
int fd;
char line[LINE_SIZE];
struct sigaction sa, act;
sigset_t nmask, nmask2;
char username[USERNAME_SIZE] = DEFUSER;
char hostname[HOSTNAME_SIZE] = "eviltwin";
char cmd[CMD_SIZE];
char startx[CMD_SIZE] = "xinit";
#ifdef USE_ETC_RESOLVCONF_RUN
DIR *dir;
struct dirent *d;
char filename[1024];
struct sigaction sa, act;
char hline[1024];
char *x;
sigset_t nmask, nmask2;
#endif
#ifdef RUNLEVEL
struct utmp entry;
#endif
#ifdef PAM_CONSOLE
int fd;
#endif
chdir("/");
umask(022);
@@ -57,17 +220,15 @@ int main()
for (i = 1; i < NSIG; i++)
SETSIG(sa, i, SIG_IGN, SA_RESTART);
SETSIG(sa, SIGINT, shutdown, 0);
SETSIG(sa, SIGPWR, signal_handler, 0);
SETSIG(sa, SIGUSR1, shutdown, 0);
SETSIG(sa, SIGUSR2, shutdown, 0);
SETSIG(sa, SIGTERM, signal_handler, 0);
SETSIG(sa, SIGKILL, signal_handler, 0);
SETSIG(sa, SIGALRM, signal_handler, 0);
SETSIG(sa, SIGHUP, signal_handler, 0);
SETSIG(sa, SIGSTOP, signal_handler, SA_RESTART);
SETSIG(sa, SIGCONT, signal_handler, SA_RESTART);
SETSIG(sa, SIGCHLD, chld_handler, SA_RESTART);
SETSIG(sa, SIGINT, shutdown, 0);
SETSIG(sa, SIGPWR, SIG_IGN, 0);
SETSIG(sa, SIGUSR1, shutdown, 0);
SETSIG(sa, SIGUSR2, shutdown, 0);
SETSIG(sa, SIGTERM, SIG_IGN, 0);
SETSIG(sa, SIGALRM, SIG_IGN, 0);
SETSIG(sa, SIGHUP, SIG_IGN, 0);
SETSIG(sa, SIGCONT, SIG_IGN, SA_RESTART);
SETSIG(sa, SIGCHLD, chld_handler, SA_RESTART);
/* Block sigchild while forking */
sigemptyset(&nmask);
@@ -76,11 +237,17 @@ int main()
reboot(RB_DISABLE_CAD);
mount("none", "/proc", "proc", 0, NULL);
mount("none", "/sys", "sysfs", 0, NULL);
/*
* Parse kernel parameters
*/
if ((f = fopen("/proc/cmdline", "r")) != NULL) {
fgets(line, 2095, f);
fgets(line, LINE_SIZE, f);
if ((strstr(line, "finit_debug"))) {
debug = 1;
}
if (strstr(line, "quiet")) {
close(0);
close(1);
@@ -89,91 +256,249 @@ int main()
fclose(f);
}
_d("finit " VERSION " (built " __DATE__ " " __TIME__ " by " WHOAMI ")");
setsid();
/*
* Parse configuration file
*/
if ((f = fopen("/etc/finit.conf", "r")) != NULL) {
char *x;
while (!feof(f)) {
fgets(line, LINE_SIZE, f);
chomp(line);
_d("conf: %s", line);
/* Do this before mounting / read-write */
if (MATCH_CMD(line, "check ", x)) {
strcpy(cmd, "/sbin/fsck -C -a ");
build_cmd(cmd, x, CMD_SIZE);
system(cmd);
continue;
}
if (MATCH_CMD(line, "user ", x)) {
*username = 0;
build_cmd(username, x, USERNAME_SIZE);
continue;
}
if (MATCH_CMD(line, "startx ", x)) {
*startx = 0;
build_cmd(startx, x, CMD_SIZE);
continue;
}
if (MATCH_CMD(line, "host ", x)) {
*hostname = 0;
build_cmd(hostname, x, HOSTNAME_SIZE);
continue;
}
if (MATCH_CMD(line, "shutdown ", x)) {
*sdown = 0;
build_cmd(sdown, x, CMD_SIZE);
continue;
}
if (MATCH_CMD(line, "module ", x)) {
strcpy(cmd, "/sbin/modprobe ");
build_cmd(cmd, x, CMD_SIZE);
system(cmd);
continue;
}
#ifdef MAKE_DEVICES
/* This is used if the system uses udev and doesn't
* mount /dev as tmpfs in the initrd, or if it doesn't
* use an initrd. Mount /dev as tmpfs and create basic
* device nodes.
*/
if (MATCH_CMD(line, "mountdev", x)) {
mount("none", "/dev", "tmpfs", 0, "mode=0755");
chardev("/dev/null", 0666, 1, 3);
blkdev("/dev/sda1", 0660, 8, 1);
blkdev("/dev/sda2", 0660, 8, 2);
blkdev("/dev/sda3", 0660, 8, 3);
blkdev("/dev/sda4", 0660, 8, 4);
blkdev("/dev/sda5", 0660, 8, 5);
blkdev("/dev/sda6", 0660, 8, 6);
#ifdef MAKE_DEV_VCS
/* Caio reports that newer X.org needs these */
blkdev("/dev/vcs1", 0660, 7, 1);
blkdev("/dev/vcs2", 0660, 7, 2);
blkdev("/dev/vcs3", 0660, 7, 3);
blkdev("/dev/vcs4", 0660, 7, 4);
blkdev("/dev/vcsa1", 0660, 7, 129);
blkdev("/dev/vcsa2", 0660, 7, 130);
blkdev("/dev/vcsa3", 0660, 7, 131);
blkdev("/dev/vcsa4", 0660, 7, 132);
#endif
continue;
}
/* This works only if /dev is tmpfs! If not, create
* devices statically on the filesystem
*/
if (MATCH_CMD(line, "mknod ", x)) {
strcpy(cmd, "/bin/mknod ");
build_cmd(cmd, x, CMD_SIZE);
system(cmd);
continue;
}
#endif
}
fclose(f);
}
/*
* Mount filesystems
*/
mount("proc", "/proc", "proc", 0, NULL);
mount("sysfs", "/sys", "sysfs", 0, NULL);
mount("devpts", "/dev/pts", "devpts", 0, "gid=5,mode=620");
mount("tmpfs", "/dev/shm", "tmpfs", 0, NULL);
mount("tmpfs", "/tmp", "tmpfs", 0, "mode=1777,size=128m");
mount("/mnt", "/", NULL, MS_MOVE, NULL);
_d("mount filesystems");
#ifdef REMOUNT_ROOTFS_RW
system("/bin/mount -n -o remount,rw /");
#endif
umask(0);
#ifdef MAKE_DEVICES
mkdir("/dev/shm", 0755);
mkdir("/dev/pts", 0755);
#endif
mount("none", "/dev/pts", "devpts", 0, "gid=5,mode=620");
mount("none", "/dev/shm", "tmpfs", 0, NULL);
mount("none", "/tmp", "tmpfs", 0, "mode=1777,size=128m");
mount("none", "/var/run", "tmpfs", 0, "mode=0755");
mount("none", "/var/lock", "tmpfs", 0, "mode=1777");
mount("none", "/proc/bus/usb", "usbfs", 0, NULL);
mount(SYSROOT, "/", NULL, MS_MOVE, NULL);
_d("make devices");
#ifdef MAKE_DEVICES
mkdir("/dev/input", 0755);
chardev("/dev/urandom", 0666, 1, 9);
chardev("/dev/ptmx", 0666, 5, 2);
chardev("/dev/null", 0666, 1, 3);
chmod("/dev/null", 0666);
chardev("/dev/mem", 0640, 1, 1);
chardev("/dev/tty0", 0660, 4, 0);
chardev("/dev/tty1", 0660, 4, 1);
chardev("/dev/tty2", 0660, 4, 2);
chardev("/dev/tty3", 0660, 4, 3);
chardev("/dev/input/mice", 0660, 13, 63);
chardev("/dev/input/event0", 0660, 13, 64);
chardev("/dev/agpgart", 0660, 10, 175);
blkdev("/dev/loop0", 0600, 7, 0);
#endif
unlink("/etc/mtab");
system("mount -a");
umask(0022);
/*
* Time adjustments
*/
if ((fd = open("/etc/adjtime", O_CREAT|O_WRONLY|O_TRUNC, 0644)) >= 0) {
write(fd, "0.0 0 0.0\n", 10);
close(fd);
}
system("/sbin/hwclock --hctosys --localtime");
_d("adjust clock");
#ifndef NO_HCTOSYS
system("/sbin/hwclock --hctosys" HWCLOCK_DIRECTISA);
#endif
/*
* Network stuff
*/
system("mkdir -p /dev/shm/network");
system("mkdir -p /dev/shm/resolvconf/interface");
#ifdef USE_ETC_RESOLVCONF_RUN
makepath("/dev/shm/network");
makepath("/dev/shm/resolvconf/interface");
if ((dir = opendir("/etc/resolvconf/run/interface")) != NULL) {
while ((d = readdir(dir)) != NULL) {
if (isalnum(d->d_name[0]))
continue;
sprintf(filename, "/etc/resolvconf/run/interface/%s",
d->d_name);
unlink(filename);
snprintf(line, LINE_SIZE,
"/etc/resolvconf/run/interface/%s", d->d_name);
unlink(line);
}
closedir(dir);
}
#endif
#ifdef USE_VAR_RUN_RESOLVCONF
makepath("/var/run/resolvconf/interface");
symlink("../../../etc/resolv.conf", "/var/run/resolvconf/resolv.conf");
#endif
touch("/var/run/utmp");
chown("/var/run/utmp", 0, getgroup("utmp"));
chmod("/var/run/utmp", 0664);
#ifdef RUNLEVEL
memset(&entry, 0, sizeof(struct utmp));
entry.ut_type = RUN_LVL;
entry.ut_pid = '0' + RUNLEVEL;
setutent();
pututline(&entry);
endutent();
#endif
#ifdef USE_ETC_RESOLVCONF_RUN
touch("/etc/resolvconf/run/enable-updates");
chdir("/etc/resolvconf/run/interface");
system("/bin/run-parts --arg=-i /etc/resolvconf/update.d");
#ifdef BUILTIN_RUNPARTS
run_parts("/etc/resolvconf/update.d", "-i", NULL);
#else
system(RUNPARTS " --arg=i /etc/resolvconf/update.d");
#endif
chdir("/");
#endif
#ifdef TOUCH_ETC_NETWORK_RUN_IFSTATE
touch("/etc/network/run/ifstate");
#endif
if ((f = fopen("/etc/hostname", "r")) != NULL) {
fgets(hline, 1023, f);
if ((x = strchr(hline, 0x0a)) != NULL)
*x = 0;
sethostname(hline, strlen(hline));
fgets(hostname, HOSTNAME_SIZE, f);
chomp(hostname);
fclose(f);
}
system("/sbin/ifconfig lo 127.0.0.1 netmask 255.0.0.0 up > /dev/null");
sethostname(hostname, strlen(hostname));
ifconfig("lo", "127.0.0.1", "255.0.0.0", 1);
/*
* Set random seed
*/
/* Bug: the eeepc never sets its random seed from file */
system("/bin/cat /var/lib/urandom/random-seed >/dev/urandom "
"> /dev/null 2>&1");
unlink("/var/lib/urandom/random-seed");
copyfile(RANDOMSEED, "/dev/urandom", 0);
unlink(RANDOMSEED);
umask(077);
system("/bin/dd if=/dev/urandom of=/var/lib/urandom/random-seed "
"bs=4096 count=1 >/dev/null 2>&1");
copyfile("/dev/urandom", RANDOMSEED, 4096);
umask(0);
/*
* Console setup (for X)
*/
makepath("/var/run/console");
snprintf(line, LINE_SIZE, "/var/run/console/%s", username);
touch(line);
#ifdef PAM_CONSOLE
if ((fd = open("/var/run/console/console.lock", O_CREAT|O_WRONLY|O_TRUNC, 0644)) >= 0) {
write(fd, username, strlen(username));
close(fd);
system("/sbin/pam_console_apply");
}
#endif
/*
* Misc setup
*/
/* not really needed, /tmp is a fresh mounted tmpfs */
system("/bin/rm -rf /tmp/* /tmp/.* 2>/dev/null");
unlink("/var/run/.clean");
unlink("/var/lock/.clean");
umask(0);
mkdir("/tmp/.X11-unix", 01777);
mkdir("/tmp/.ICE-unix", 01777);
umask(022);
system(GETTY "&");
_d("forking");
if (!fork()) {
/* child process */
@@ -183,7 +508,7 @@ int main()
close(1);
close(0);
if (open("/dev/tty1", O_RDWR, 0))
if (open("/dev/tty1", O_RDWR) != 0)
exit(1);
sigemptyset(&act.sa_mask);
@@ -193,27 +518,53 @@ int main()
sigaddset(&nmask2, SIGCHLD);
sigprocmask(SIG_UNBLOCK, &nmask2, NULL);
/* Bug: no signal 0 */
for (i = 0; i < NSIG; i++)
for (i = 1; i < NSIG; i++)
sigaction(i, &sa, NULL);
dup2(0, 0);
dup2(0, 1);
dup2(0, 2);
touch("/tmp/nologin");
while (access("/tmp/shutdown", F_OK) < 0)
system("su -c startx -l user &> /dev/null");
#ifdef USE_MESSAGE_BUS
_d("dbus");
mkdir("/var/run/dbus", 0755);
mkdir("/var/lock/subsys/messagebus", 0755);
system("dbus-uuidgen --ensure;dbus-daemon --system");
#endif
#ifdef LISTEN_INITCTL
listen_initctl();
#endif
/* Prevents bash from running loadkeys */
unsetenv("TERM");
/* ConsoleKit needs this */
setenv("DISPLAY", ":0", 1);
while (access("/tmp/shutdown", F_OK) < 0) {
_d("start X as %s\n", username);
if (debug) {
snprintf(line, LINE_SIZE,
"su -l %s -c \"%s\"", username, startx);
system(line);
system("/bin/sh");
} else {
snprintf(line, LINE_SIZE,
"su -l %s -c \"%s\" &> /dev/null",
username, startx);
system(line);
}
}
exit(0);
}
/* parent process */
system("/sbin/getty 38400 tty3 &");
sleep(1);
system("/usr/sbin/services.sh &> /dev/null &");
/* sleep(1); */
system("/usr/sbin/services.sh &>/dev/null&");
while (1) {
sigemptyset(&nmask);
@@ -227,34 +578,31 @@ int main()
*/
void shutdown(int sig)
{
int fd;
system("/usr/bin/touch /tmp/shutdown");
touch("/tmp/shutdown");
if (sdown) {
system(sdown);
}
kill(-1, SIGTERM);
system("/bin/echo -e \"\033[?25l\033[30;40m\"; "
"/bin/cp /boot/shutdown.fb /dev/fb/0");
sleep(1);
sleep(1);
write(1, "\033[?25l\033[30;40m", 14);
copyfile("/boot/shutdown.fb", "/dev/fb/0", 0);
sleep(2);
system("/usr/sbin/alsactl store > /dev/null 2>&1");
system("/sbin/hwclock --systohc --localtime");
system("/sbin/hwclock --systohc" HWCLOCK_DIRECTISA);
kill(-1, SIGKILL);
sync();
sync();
system("/bin/mount -n -o remount,ro /");
system("/sbin/unionctl.static / --remove / > /dev/null 2>&1");
system("/bin/umount -a;/bin/mount -n -o remount,ro /");
//system("/sbin/unionctl.static / --remove / > /dev/null 2>&1");
if (sig == SIGINT || sig == SIGUSR1)
reboot(RB_AUTOBOOT);
if ((fd = open("/proc/acpi/sleep", O_WRONLY)) >= 0) {
write(fd, "5", 1);
close(fd);
}
reboot(RB_POWER_OFF);
}
@@ -271,12 +619,3 @@ void chld_handler(int sig)
}
}
/*
* We got a signal (PWR TERM ALRM HUP STOP CONT)
*/
void signal_handler(int sig)
{
/* do nothing */
}