Massive cleanup to be able to boot Debian 6.0

Update license and copyright information details in all files.
Much cleanup by moving hard coded strings/data to #defines and using more
common default values for each such #define.

finit.c:
        o Make sdown[], startx[] allocated strings by default NULL
        o This fixes the issues where the shutdown handler segfaulted
        o Add ability to handle NULL input to build_cmd() by allocating space
        o Ignore kernel cmdline "quiet" if in debug mode
        o Add support for "network" stanza in finit.conf
        o Mount -n to skip removing /etc/mtab
        o Call swapon to enable swap if enabled in /etc/fstab
        o Cleanup /tmp, /var/run and /var/lock
        o Move sig_setup() *after* mount, sig_init() otoh runs early
        o Start initctl monitor before forking off startx/getty process
        o The startx process is now the console process. Only a getty is
          started when in debug mode. Otherwise only X is started if it
          is properly setup in /etc/finit.conf
        o NOTE: Currently X evdev does not work!
        o Support for /usr/sbin/services.sh has been replaced with finit
          now instead supporting builtin run-parts for /etc/finit.d/

helpers.c:
        o Bug fixes in run_parts() and also added chdir(oldpwd) at bottom.
        o New functions:
          - getuser() similar to getgroup()
          - cls() clear screen, only runs when not in debug mode
          - set_procname() used to set name "console" on console process
          - set_hostname() encapsulates /etc/hostname and sethostname()

signal.c:
        o Split sig_setup() in two: sig_init() and sig_setup()
          The former to be called as soon as possible, while latter is
          supposed to run when the base filesystem is properly up.
        o Remove hard coded distribution specific progress bar write()
        o Add debug messages to do_shutdown()
        o Remove any lingering sync files in sig_setup()

initctl.c:
        o Add debug messages and a new default: case to catch stray runlevels

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson
2012-09-19 18:06:12 +02:00
parent 855c7d8251
commit c0356b5c7a
10 changed files with 451 additions and 245 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
Copyright (c) 2009-2012 Joachim Nilsson <troglobit@gmail.com>
Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+1 -2
View File
@@ -35,8 +35,7 @@ CFLAGS += -W -Wall -Werror -Os
# Disable annoying gcc warning for "warn_unused_result", see GIT 37af997
CPPFLAGS += -U_FORTIFY_SOURCE
CPPFLAGS += -I$(ROOTDIR)/$(CONFIG_LINUXDIR)/include/
# Build for embedded systems, not notebook by default, see finit.h
CPPFLAGS += -DEMBEDDED_SYSTEM -DBUILTIN_RUNPARTS
CPPFLAGS += -DBUILTIN_RUNPARTS
CPPFLAGS += -DVERSION=\"$(VERSION)\" -DWHOAMI=\"`whoami`@`hostname`\"
CPPFLAGS += -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE
+3
View File
@@ -0,0 +1,3 @@
# finit.conf
check /dev/vda1
+6
View File
@@ -0,0 +1,6 @@
#!/bin/sh
run-parts /etc/rcS.d --arg=start
run-parts /etc/rc2.d --arg=start
#service acpid start
#service networking start
#service ssh start
+131 -107
View File
@@ -1,26 +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.
*/
/* Improved fast init
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
*
* 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 <string.h>
#include <ctype.h>
@@ -32,36 +32,44 @@
#include "finit.h"
#include "helpers.h"
int debug = 0;
char sdown[CMD_SIZE] = "";
int debug = 0;
char *sdown = NULL;
char *network = NULL;
char *startx = NULL;
static void build_cmd(char *cmd, char *x, int len)
static char *build_cmd(char *cmd, char *line, int len)
{
int l;
char *c;
/* Trim leading whitespace */
while (*line && (*line == ' ' || *line == '\t'))
line++;
if (!cmd) {
cmd = malloc (strlen(line) + 1);
if (!cmd) {
fprintf (stderr, "finit: No memory left for '%s'", line);
return NULL;
}
*cmd = 0;
}
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++;
for (l = 0; *line && *line != '#' && *line != '\t' && l < len; l++)
*c++ = *line++;
*c = 0;
_d("cmd = %s", cmd);
return cmd;
}
int main(void)
int main(int UNUSED(args), char *argv[])
{
FILE *f;
FILE *fp;
char line[LINE_SIZE];
char username[USERNAME_SIZE] = DEFUSER;
char hostname[HOSTNAME_SIZE] = DEFHOST;
char cmd[CMD_SIZE];
char startx[CMD_SIZE] = "xinit";
#ifdef USE_ETC_RESOLVCONF_RUN
DIR *dir;
struct dirent *d;
@@ -73,15 +81,16 @@ int main(void)
int fd;
#endif
/* Setup signals */
/*
* Initial setup of signals, ignore all until we're up.
*/
sig_init();
chdir("/");
umask(022);
/*
* Mount base file system, kernel is assumed to run devtmpfs for /dev
*/
chdir("/");
umask(0);
mount("none", "/proc", "proc", 0, NULL);
mount("none", "/proc/bus/usb", "usbfs", 0, NULL);
mount("none", "/sys", "sysfs", 0, NULL);
@@ -89,44 +98,49 @@ int main(void)
mkdir("/dev/shm", 0755);
mount("none", "/dev/pts", "devpts", 0, "gid=5,mode=620");
mount("none", "/dev/shm", "tmpfs", 0, NULL);
umask(022);
/*
* Populate /dev and prepare for runtime events from kernel.
*/
#ifdef MDEV
system("sysctl -w kernel.hotplug=" MDEV);
system(MDEV " -s");
#if defined(USE_UDEV)
system("udevd --daemon");
#elif defined (MDEV)
system(MDEV "-s");
#endif
/*
* Parse kernel parameters
*/
if ((f = fopen("/proc/cmdline", "r")) != NULL) {
fgets(line, LINE_SIZE, f);
if ((fp = fopen("/proc/cmdline", "r")) != NULL) {
fgets(line, LINE_SIZE, fp);
if (strstr(line, "finit_debug") ||
strstr(line, "--verbose")) {
strstr(line, "--verbose") ||
strstr(line, "--debug"))
debug = 1;
}
if (strstr(line, "quiet")) {
if (!debug && strstr(line, "quiet")) {
close(0);
close(1);
close(2);
}
fclose(f);
fclose(fp);
}
cls();
_d("finit " VERSION " (built " __DATE__ " " __TIME__ " by " WHOAMI ")");
/*
* Parse configuration file
*/
if ((f = fopen("/etc/finit.conf", "r")) != NULL) {
if ((fp = fopen(FINIT_CONF, "r")) != NULL) {
char *x;
while (!feof(f)) {
if (!fgets(line, LINE_SIZE, f))
_d("Parse %s ...", FINIT_CONF);
while (!feof(fp)) {
if (!fgets(line, LINE_SIZE, fp))
continue;
chomp(line);
@@ -148,19 +162,14 @@ int main(void)
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);
if (sdown) free(sdown);
sdown = build_cmd(NULL, x, CMD_SIZE);
continue;
}
if (MATCH_CMD(line, "module ", x)) {
@@ -175,14 +184,24 @@ int main(void)
system(cmd);
continue;
}
if (MATCH_CMD(line, "network ", x)) {
if (network) free(network);
network = build_cmd(NULL, x, CMD_SIZE);
continue;
}
if (MATCH_CMD(line, "startx ", x)) {
if (startx) free(startx);
startx = build_cmd(NULL, x, CMD_SIZE);
continue;
}
}
fclose(f);
fclose(fp);
}
/*
* Mount filesystems
*/
_d("mount filesystems");
_d("Mount filesystems in /etc/fstab ...");
#ifdef REMOUNT_ROOTFS_RW
system("/bin/mount -n -o remount,rw /");
@@ -191,15 +210,23 @@ int main(void)
mount(SYSROOT, "/", NULL, MS_MOVE, NULL);
#endif
umask(0);
unlink("/etc/mtab");
system("mount -a");
system("mount -na");
system("swapon -ea");
umask(0022);
/* Cleanup stale files, if any still linger on. */
system("rm -rf /tmp/* /var/run/* /var/lock/*");
/*
* Base FS up, enable standard SysV init signals
*/
sig_setup();
/*
* Time adjustments
*/
_d("adjust clock");
#ifndef NO_HCTOSYS
_d("Adjust system clock ...");
system("/sbin/hwclock --hctosys");
#endif
@@ -229,11 +256,11 @@ int main(void)
symlink("../../../etc/resolv.conf", "/var/run/resolvconf/resolv.conf");
#endif
#ifdef RUNLEVEL
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;
@@ -259,15 +286,13 @@ int main(void)
#endif
/* Set initial hostname. */
if ((f = fopen("/etc/hostname", "r")) != NULL) {
fgets(hostname, HOSTNAME_SIZE, f);
chomp(hostname);
fclose(f);
}
sethostname(hostname, strlen(hostname));
set_hostname(hostname);
ifconfig("lo", "127.0.0.1", "255.0.0.0", 1);
if (network) {
_d("Starting networking: %s", network);
system(network);
}
/*
* Set random seed
@@ -302,13 +327,14 @@ int main(void)
mkdir("/tmp/.ICE-unix", 01777);
umask(022);
/* Start console login. */
system(GETTY "&");
#ifdef LISTEN_INITCTL
listen_initctl();
#endif
_d("forking");
if (!fork()) {
/* child process */
int i;
char c;
sigset_t nmask;
struct sigaction sa;
@@ -331,55 +357,53 @@ int main(void)
for (i = 1; i < NSIG; i++)
sigaction(i, &sa, NULL);
dup2(0, 0);
dup2(0, 1);
dup2(0, 2);
dup2(0, STDIN_FILENO);
dup2(0, STDOUT_FILENO);
dup2(0, STDERR_FILENO);
#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");
set_procname(argv, "console");
/* ConsoleKit needs this */
setenv("DISPLAY", ":0", 1);
#ifdef USE_MESSAGE_BUS
_d("Starting D-Bus ...");
mkdir("/var/run/dbus", 0755);
mkdir("/var/lock/subsys/messagebus", 0755);
system("dbus-uuidgen --ensure");
system("su -c \"dbus-daemon --system\" messagebus");
#endif
/* Run startup scripts in /etc/finit.d/, if any. */
run_parts(FINIT_RCSD);
while (!fexist(SYNC_SHUTDOWN)) {
if (fexist(SYNC_STOPPED)) {
sleep(2);
sleep(1);
continue;
}
_d("start X as %s\n", username);
if (debug) {
snprintf(line, LINE_SIZE,
"su -l %s -c \"%s\"", username, startx);
if (startx && !debug) {
snprintf(line, sizeof(line), "su -c \"%s\" -l %s", startx, username);
system(line);
system("/bin/sh");
} else {
snprintf(line, LINE_SIZE,
"su -l %s -c \"%s\" &> /dev/null",
username, startx);
system(line);
static const char msg[] = "\nPlease press Enter to activate this console. ";
i = write(STDERR_FILENO, msg, sizeof(msg) - 1);
while (read(STDIN_FILENO, &c, 1) == 1 && c != '\n')
continue;
if (fexist(SYNC_STOPPED))
continue;
system(GETTY);
}
}
exit(0);
}
/* parent process */
/* sleep(1); */
system("/usr/sbin/services.sh &>/dev/null&");
/* We're the grim reaper of innocent orphaned children ... */
while (1) {
sigset_t nmask;
+52 -38
View File
@@ -1,29 +1,29 @@
/*
Improved fast init
/* Improved fast init
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
*
* 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.
*/
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.
*/
#ifndef FINIT_H__
#define FINIT_H__
#ifndef FINIT_H_
#define FINIT_H_
#include <errno.h>
#include <fcntl.h>
@@ -45,6 +45,10 @@
#define DEBUG(fmt, args...) DO_LOG(LOG_DEBUG, fmt, ##args)
#define ERROR(fmt, args...) DO_LOG(LOG_CRIT, fmt, ##args)
#define FINIT_FIFO "/dev/initctl"
#define FINIT_CONF "/etc/finit.conf"
#define FINIT_RCSD "/etc/finit.d"
/* Distribution configuration */
#if defined EMBEDDED_SYSTEM
@@ -82,19 +86,20 @@
# define USE_ETC_RESOLVCONF_RUN
#else /* Ubuntu */
# define RANDOMSEED "/var/lib/urandom/random-seed"
# define CONSOLE "/dev/console"
# define MDEV "\"/bin/busybox mdev\""
# define GETTY "/usr/bin/openvt /sbin/getty 38400 tty2"
# define CONSOLE "/dev/tty1"
# define GETTY "/sbin/getty -8 38400 tty1"
# define REMOUNT_ROOTFS_RW
# define TOUCH_ETC_NETWORK_RUN_IFSTATE
# define RUNLEVEL 2
# define LISTEN_INITCTL
# define USE_UDEV
# define USE_MESSAGE_BUS
#endif
#define SYNC_SHUTDOWN "/var/lock/finit.shutdown"
#define SYNC_STOPPED "/var/lock/finit.stopped"
#ifndef DEFUSER
# define DEFUSER "user"
# define DEFUSER "root"
#endif
#ifndef DEFHOST
# define DEFHOST "noname"
@@ -118,19 +123,28 @@
# define fexist(x) (access(x, F_OK) != -1)
#endif
#ifndef UNUSED
#define UNUSED(x) UNUSED_ ## x __attribute__ ((unused))
#endif
/* Match one command. */
#define MATCH_CMD(l,c,x) \
((!strncmp((l), (c), strlen((c)))) && ((x) = (l) + strlen((c))))
#define MATCH_CMD(l, c, x) \
(!strncmp(l, c, strlen(c)) && (x = (l) + strlen(c)))
#define _d(fmt, args...) do { if (debug) { fprintf(stderr, "%s(): " fmt "\n", __func__, ##args); } } while (0)
#define _d(fmt, args...) do { if (debug) { fprintf(stderr, "finit:%s() - " fmt "\n", __func__, ##args); } } while (0)
extern int debug;
extern int debug;
extern char *sdown;
void do_shutdown(int sig);
void sig_init(void);
void listen_initctl(void);
/* signal.c */
void do_shutdown (int sig);
void sig_init (void);
void sig_setup (void);
#endif /* FINIT_H__ */
/* initctl.c */
void listen_initctl (void);
#endif /* FINIT_H_ */
/**
* Local Variables:
+99 -7
View File
@@ -1,3 +1,26 @@
/* Misc. utility functions and C-library extensions to simplify finit system setup.
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
*
* 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 <string.h>
#include <limits.h>
@@ -7,6 +30,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -19,7 +43,9 @@
#endif
#include <grp.h>
#include <pwd.h>
#include "finit.h"
#include "helpers.h"
/*
@@ -115,16 +141,21 @@ int run_parts(char *dir, ...)
DIR *d;
struct dirent *e;
struct stat st;
char *oldpwd = NULL;
char *ent[NUM_SCRIPTS];
int i, num = 0, argnum = 1;
char *args[NUM_ARGS];
va_list ap;
if (chdir(dir))
oldpwd = getcwd (NULL, 0);
if (chdir(dir)) {
if (oldpwd) free(oldpwd);
return -1;
if ((d = opendir(dir)) == NULL)
}
if ((d = opendir(dir)) == NULL) {
if (oldpwd) free(oldpwd);
return -1;
}
va_start(ap, dir);
while (argnum < NUM_ARGS && (args[argnum++] = va_arg(ap, char *)));
@@ -132,6 +163,7 @@ int run_parts(char *dir, ...)
while ((e = readdir(d))) {
if (e->d_type == DT_REG && stat(e->d_name, &st) == 0) {
_d("Found %s/%s ...", dir, e->d_name);
if (st.st_mode & S_IXUSR) {
ent[num++] = strdup(e->d_name);
if (num >= NUM_SCRIPTS)
@@ -142,23 +174,46 @@ int run_parts(char *dir, ...)
closedir(d);
if (num == 0)
if (num == 0) {
if (oldpwd) free(oldpwd);
return 0;
}
qsort(ent, num, sizeof(char *), cmp);
for (i = 0; i < num; i++) {
pid_t pid = 0;
int status;
args[0] = ent[i];
if (!fork()) {
args[1] = NULL;
pid = fork();
if (!pid) {
_d("Calling %s ...", ent[i]);
execv(ent[i], args);
exit(0);
}
wait(NULL);
waitpid(pid, &status, 0);
free(ent[i]);
}
chdir(oldpwd);
free(oldpwd);
return 0;
}
#endif /* BUILTIN_RUNPARTS */
int getuser(char *s)
{
struct passwd *usr;
if ((usr = getpwnam(s)) == NULL)
return -1;
return usr->pw_uid;
}
int getgroup(char *s)
{
@@ -174,6 +229,14 @@ int getgroup(char *s)
* Other convenience functions
*/
void cls(void)
{
static const char cls[] = "\e[2J\e[1;1H";
if (!debug)
fprintf (stderr, "%s", cls);
}
void chomp(char *s)
{
char *x;
@@ -182,4 +245,33 @@ void chomp(char *s)
*x = 0;
}
#endif
void set_procname(char *args[], char *name)
{
size_t len = strlen(args[0]) + 1; /* Include terminating '\0' */
prctl(PR_SET_NAME, name, 0, 0, 0);
memset(args[0], 0, len);
strncpy(args[0], name, len);
}
void set_hostname(char *hostname)
{
FILE *fp;
_d("Set hostname: %s", hostname);
if ((fp = fopen("/etc/hostname", "r")) != NULL) {
fgets(hostname, HOSTNAME_SIZE, fp);
chomp(hostname);
fclose(fp);
}
sethostname(hostname, strlen(hostname));
}
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+40 -4
View File
@@ -1,14 +1,50 @@
#ifndef __FINIT_HELPERS_H
#define __FINIT_HELPERS_H
/* Misc. utility functions and C-library extensions to simplify finit system setup.
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
*
* 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.
*/
#ifndef FINIT_HELPERS_H_
#define FINIT_HELPERS_H_
int makepath (char *);
void ifconfig (char *, char *, char *, int);
void copyfile (char *, char *, int);
void cls (void);
void chomp (char *);
int getuser (char *);
int getgroup (char *);
void set_procname (char *args[], char *name);
void set_hostname (char *hostname);
#ifdef BUILTIN_RUNPARTS
int run_parts (char *, ...);
int run_parts (char *dir, ...);
#endif
#endif
#endif /* FINIT_HELPERS_H_ */
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+39 -25
View File
@@ -1,26 +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.
*/
/* Optional /dev/initctl FIFO monitor
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
*
* 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 <features.h>
#include <fcntl.h>
@@ -50,32 +50,45 @@ struct init_request {
*/
void listen_initctl(void)
{
_d("Forking %s watcher...", FINIT_FIFO);
if (!fork()) {
int ctl;
fd_set fds;
struct init_request request;
mkfifo("/dev/initctl", 0600);
ctl = open("/dev/initctl", O_RDONLY);
_d("Setting up %s", FINIT_FIFO);
mkfifo(FINIT_FIFO, 0600);
ctl = open(FINIT_FIFO, O_RDONLY);
while (1) {
FD_ZERO(&fds);
FD_SET(ctl, &fds);
_d("Pending %s activity...", FINIT_FIFO);
if (select(ctl + 1, &fds, NULL, NULL, NULL) <= 0)
continue;
_d("Receiving request on %s...", FINIT_FIFO);
read(ctl, &request, sizeof(request));
if (request.magic != INIT_MAGIC)
continue;
_d("Magic OK...");
if (request.cmd == INIT_CMD_RUNLVL) {
switch (request.runlevel) {
case '0':
_d("Halting system (SIGUSR2)");
do_shutdown(SIGUSR2);
break;
case '6':
_d("Rebooting system (SIGUSR1)");
do_shutdown(SIGUSR1);
break;
default:
_d("Unsupported runlevel: %d", request.runlevel);
break;
}
}
}
@@ -87,6 +100,7 @@ void listen_initctl(void)
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+79 -61
View File
@@ -1,26 +1,42 @@
/*
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.
*/
/* Signal management - Be conservative with what finit responds to!
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
*
* 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.
*
* The standard SysV init only responds to the following signals:
* SIGHUP
* Has the same effect as telinit q.
*
* SIGUSR1
* On receipt of this signals, init closes and re-opens its control
* fifo, /dev/initctl. Useful for bootscripts when /dev is remounted.
*
* SIGINT
* Normally the kernel sends this signal to init when CTRL-ALT-DEL is
* pressed. It activates the ctrlaltdel action.
*
* SIGWINCH
* The kernel sends this signal when the KeyboardSignal key is hit.
* It activates the kbrequest action.
*/
#include <signal.h>
#include <sys/reboot.h>
@@ -45,31 +61,32 @@
} while (0)
static int stopped = 0;
extern char *sdown;
void do_shutdown (int sig)
{
touch(SYNC_SHUTDOWN);
if (sdown[0] != 0) {
if (sdown) {
_d("Calling shutdown hook: %s", sdown);
system(sdown);
}
_d("Sending SIGTERM to all processes.");
kill(-1, SIGTERM);
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");
_d("Saving the system clock.");
system("/sbin/hwclock --systohc");
_d("Sending SIGKILL to remaining processes.");
kill(-1, SIGKILL);
sync();
sync();
system("/bin/umount -a;/bin/mount -n -o remount,ro /");
//system("/sbin/unionctl.static / --remove / > /dev/null 2>&1");
_d("Unmounting file systems, remounting / read-only.");
system("/bin/umount -fa 2>/dev/null");
system("/bin/mount -n -o remount,ro / 2>/dev/null");
_d("%s.", sig == SIGINT || sig == SIGUSR1 ? "Rebooting" : "Halting");
if (sig == SIGINT || sig == SIGUSR1)
reboot(RB_AUTOBOOT);
@@ -79,9 +96,9 @@ void do_shutdown (int sig)
/*
* Shut down on INT USR1 USR2
*/
static void shutdown_handler(int sig, siginfo_t *info, void *ctx __attribute__ ((unused)))
static void shutdown_handler(int sig, siginfo_t *info, void *UNUSED(ctx))
{
_d("finit: Rebooting on signal %d from pid %d with code %d", sig, info->si_pid, info->si_code);
_d("Rebooting on signal %d from pid %d with code %d", sig, info->si_pid, info->si_code);
do_shutdown(sig);
}
@@ -89,11 +106,12 @@ static void shutdown_handler(int sig, siginfo_t *info, void *ctx __attribute__ (
/*
* SIGCHLD: one of our children has died
*/
static void chld_handler(int sig, siginfo_t *info, void *ctx __attribute__ ((unused)))
static void chld_handler(int sig, siginfo_t *info, void *UNUSED(ctx))
{
int status;
_d("finit: Child died, harvesting... signal %d from pid %d with code %d", sig, info->si_pid, info->si_code);
/* XXX: Add (procname) to debug output, add get_procname(pid) to helpers.c */
_d("Child died, harvesting. Signal %d from pid %d code %d", sig, info->si_pid, info->si_code);
while (waitpid(-1, &status, WNOHANG) != 0) {
if (errno == ECHILD)
break;
@@ -103,48 +121,47 @@ static void chld_handler(int sig, siginfo_t *info, void *ctx __attribute__ ((unu
/*
* SIGSTOP: Paused by user or netflash
*/
static void sigstop_handler(int sig, siginfo_t *info, void *ctx __attribute__ ((unused)))
static void sigstop_handler(int sig, siginfo_t *info, void *UNUSED(ctx))
{
_d("finit: Received SIGSTOP(%d) from pid %d with code %d", sig, info->si_pid, info->si_code);
_d("Received SIGSTOP(%d) from pid %d code %d", sig, info->si_pid, info->si_code);
touch(SYNC_STOPPED);
stopped ++;
}
static void sigcont_handler(int sig, siginfo_t *info, void *ctx __attribute__ ((unused)))
static void sigcont_handler(int sig, siginfo_t *info, void *UNUSED(ctx))
{
_d("finit: Received SIGCONT(%d) from pid %d with code %d", sig, info->si_pid, info->si_code);
_d("Received SIGCONT(%d) from pid %d code %d", sig, info->si_pid, info->si_code);
stopped = 0;
remove(SYNC_STOPPED);
}
/*
* Signal management - Be conservative with what finit responds to!
*
* The standard SysV init only responds to the following signals:
* SIGHUP
* Has the same effect as telinit q.
*
* SIGUSR1
* On receipt of this signals, init closes and re-opens its control
* fifo, /dev/initctl. Useful for bootscripts when /dev is remounted.
*
* SIGINT
* Normally the kernel sends this signal to init when CTRL-ALT-DEL is
* pressed. It activates the ctrlaltdel action.
*
* SIGWINCH
* The kernel sends this signal when the KeyboardSignal key is hit.
* It activates the kbrequest action.
* Inital signal setup - ignore everything until we're capable of responding
*/
void sig_init(void)
{
int i;
sigset_t nmask;
struct sigaction sa;
for (i = 1; i < NSIG; i++)
IGNSIG(sa, i, SA_RESTART);
}
SETSIG(sa, SIGINT, shutdown_handler, 0); /* Standard SysV init calls ctrl-alt-delete handler */
/*
* Setup limited set of SysV compatible signals to respond to
*/
void sig_setup(void)
{
sigset_t nmask;
struct sigaction sa;
_d("Setup signals");
/* Cleanup any stale finit control files */
remove(SYNC_SHUTDOWN);
remove(SYNC_STOPPED);
/* Standard SysV init calls ctrl-alt-delete handler */
SETSIG(sa, SIGINT, shutdown_handler, 0);
SETSIG(sa, SIGPWR, shutdown_handler, 0);
/* Ignore SIGUSR1/2 for now, only BusyBox init implements them as reboot+halt. */
@@ -171,7 +188,7 @@ void sig_init(void)
sigaddset(&nmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &nmask, NULL);
/* Disable CTRL-ALT-DELETE from kernel, we handle shutdown gracefully with SIGINT */
/* Disable CTRL-ALT-DELETE from kernel, we handle shutdown gracefully with SIGINT, above */
reboot(RB_DISABLE_CAD);
setsid();
}
@@ -179,6 +196,7 @@ void sig_init(void)
/**
* Local Variables:
* version-control: t
* c-file-style: "ellemtel"
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/