summaryrefslogtreecommitdiff
path: root/package/simpleinit
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2014-08-20 21:11:13 +0200
committerWaldemar Brodkorb <wbx@openadk.org>2014-08-26 12:29:24 +0200
commit8e2707b81b0c90295c9fdf92a576925442d22147 (patch)
treee95ad185bfb7169ddaa1cfdceb6a9b134b3ec8b8 /package/simpleinit
parent62f5a17a49e65c6639460abbf352b158b36301a7 (diff)
add sash, simpleinit and a uclibc config for nonmmu case
Diffstat (limited to 'package/simpleinit')
-rw-r--r--package/simpleinit/Makefile30
-rwxr-xr-xpackage/simpleinit/files/rc47
-rw-r--r--package/simpleinit/src/pathnames.h37
-rw-r--r--package/simpleinit/src/simpleinit.c1046
4 files changed, 1160 insertions, 0 deletions
diff --git a/package/simpleinit/Makefile b/package/simpleinit/Makefile
new file mode 100644
index 000000000..aeeedfc08
--- /dev/null
+++ b/package/simpleinit/Makefile
@@ -0,0 +1,30 @@
+# This file is part of the OpenADK project. OpenADK is copyrighted
+# material, please see the LICENCE file in the top-level directory.
+
+include ${ADK_TOPDIR}/rules.mk
+
+PKG_NAME:= simpleinit
+PKG_VERSION:= 1.0
+PKG_RELEASE:= 1
+PKG_DESCR:= simple init for systems without mmu
+PKG_SECTION:= base/apps
+
+NO_DISTFILES:= 1
+
+include ${ADK_TOPDIR}/mk/package.mk
+
+$(eval $(call PKG_template,SIMPLEINIT,simpleinit,${PKG_VERSION}-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION}))
+
+CONFIG_STYLE:= manual
+BUILD_STYLE:= manual
+INSTALL_STYLE:= manual
+
+do-build:
+ ${TARGET_CC} ${TARGET_CPPFLAGS} ${TARGET_CFLAGS} ${TARGET_LDFLAGS} \
+ -o ${WRKBUILD}/simpleinit ${WRKBUILD}/simpleinit.c
+
+do-install:
+ ${INSTALL_DIR} ${IDIR_SIMPLEINIT}/sbin
+ ${INSTALL_BIN} ${WRKBUILD}/simpleinit ${IDIR_SIMPLEINIT}/sbin/init
+
+include ${ADK_TOPDIR}/mk/pkg-bottom.mk
diff --git a/package/simpleinit/files/rc b/package/simpleinit/files/rc
new file mode 100755
index 000000000..33d60a4b6
--- /dev/null
+++ b/package/simpleinit/files/rc
@@ -0,0 +1,47 @@
+#!/bin/sh
+set -x
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+ln -s /proc/self/fd/2 /dev/stderr
+: ${rcquiet=0}
+if [ $rcquiet -ne 1 ];then
+ echo "System initialization ..."
+fi
+
+# remount /dev with smaller size
+mount -o remount,nosuid,size=128k,mode=0755 -t tmpfs mdev /dev
+
+# start mdev dynamic device node management
+echo >/dev/mdev.seq
+if [ -f /proc/sys/kernel/hotplug ];then
+ echo "/sbin/mdev" >/proc/sys/kernel/hotplug
+fi
+# creates f.e. /dev/root
+mdev -s
+
+# seed some random
+cat /etc/.rnd >/dev/urandom 2>&1
+
+# setup cfgfs
+[ -x /sbin/cfgfs ] && {
+ cfgfs setup
+ mount -o remount,ro /
+}
+
+# remount /tmp with smaller size
+size=$(cat /etc/tmpfs 2>/dev/null)
+[ -z $size ] && size=2048
+mount -o remount,nosuid,nodev,mode=1777,size=${size}k -t tmpfs tmpfs /tmp
+
+# create some useful directories in tmpfs
+mkdir -p /var/log
+mkdir -p /var/run
+mkdir -p /var/tmp
+touch /var/log/lastlog
+touch /var/log/wtmp
+
+HOSTNAME=
+[[ -s /etc/hostname ]] && HOSTNAME=$(cat /etc/hostname)
+HOSTNAME=${HOSTNAME%%.*}
+echo ${HOSTNAME:=openadk} >/proc/sys/kernel/hostname
+
+chown 0:0 /tmp; chmod 1777 /tmp
diff --git a/package/simpleinit/src/pathnames.h b/package/simpleinit/src/pathnames.h
new file mode 100644
index 000000000..92b7d0302
--- /dev/null
+++ b/package/simpleinit/src/pathnames.h
@@ -0,0 +1,37 @@
+/*
+ * @(#)pathnames.h 5.3 (Berkeley) 5/9/89
+ *
+ * Heavily modified by poe@daimi.aau.dk for Linux
+ */
+
+#include <paths.h>
+
+#ifndef __STDC__
+# error "we need an ANSI compiler"
+#endif
+
+#ifndef SBINDIR
+# define SBINDIR "/sbin"
+#endif
+
+#define _PATH_BSHELL "/bin/sh"
+#define _PATH_CSHELL "/bin/csh"
+#define _PATH_TTY "/dev/tty"
+#define TTYTYPES "/etc/ttytype"
+#define SECURETTY "/etc/securetty"
+
+#define _PATH_HUSHLOGIN ".hushlogin"
+#define _PATH_MOTDFILE "/etc/motd"
+#define _PATH_NOLOGIN "/etc/nologin"
+
+#define _PATH_LOGIN "/bin/login"
+#define _PATH_INITTAB "/etc/inittab"
+#define _PATH_RC "/etc/rc"
+#define _PATH_REBOOT "/bin/reboot"
+#define _PATH_SINGLE "/etc/singleboot"
+#define _PATH_SECURE "/etc/securesingle"
+#define _PATH_USERTTY "/etc/usertty"
+
+#define _PATH_CONFIGRC "/etc/config/start"
+#define _PATH_CONFIGTAB "/etc/config/inittab"
+#define _PATH_FIREWALL "/bin/firewall"
diff --git a/package/simpleinit/src/simpleinit.c b/package/simpleinit/src/simpleinit.c
new file mode 100644
index 000000000..291f88f47
--- /dev/null
+++ b/package/simpleinit/src/simpleinit.c
@@ -0,0 +1,1046 @@
+/* simpleinit.c - poe@daimi.aau.dk */
+/* Version 1.21 */
+
+/* gerg@snapgear.com -- modified for direct console support DEC/1999 */
+/* davidm@snapgear.com -- modified for init.conf SEP/2004 */
+/* toby@snapgear.com -- allow the array of commands to grow as needed OCT/2004 */
+/* davidm@snapgear.com -- use dynamically allocated tables APR/2005 */
+
+#define _GNU_SOURCE /* For crypt() and termios defines */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <signal.h>
+#include <pwd.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/termios.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <linux/version.h>
+#include <utmp.h>
+#include <errno.h>
+#include <time.h>
+#include <termios.h>
+#ifdef SHADOW_PWD
+#include <shadow.h>
+#endif
+
+#if __GNU_LIBRARY__ > 5
+#include <sys/reboot.h>
+#endif
+
+#include "pathnames.h"
+
+#define BUF_SIZ 100 /* max size of a line in inittab */
+#define NUMCMD 30 /* step size when realloc more space for the commands */
+#define NUMTOK 20 /* max number of tokens in inittab command */
+
+/* Threshold time for detecting "fast" spawning processes */
+static int testtime = 90;
+/* Number of rapid respawns that counts as too fast */
+static int maxspawn = 5;
+/* Maximum delay between runs */
+static int maxdelay = 595;
+/* Time between successive runs of a process */
+static int delaytime = 5;
+
+#define MAXTRIES 3 /* number of tries allowed when giving the password */
+
+#define RUN_RC /* Use a console if possible */
+
+#ifndef CTRL
+#define CTRL(X) ((X)&037)
+#endif
+
+#ifdef INCLUDE_TIMEZONE
+char tzone[BUF_SIZ];
+#endif
+/* #define DEBUGGING */
+
+/* Define this if you want init to ignore the termcap field in inittab for
+ console ttys. */
+/* #define SPECIAL_CONSOLE_TERM */
+
+struct initline {
+ pid_t pid;
+ time_t lastrun;
+ time_t nextrun;
+ char **toks;
+ short delay;
+ char tty[10];
+ char termcap[30];
+ char *line;
+ char *fullline;
+ unsigned char xcnt;
+};
+
+struct initline *inittab;
+/* How many struct initline's will fit in the memory pointed to by inittab */
+int inittab_size = 0;
+int numcmd;
+int stopped = 0; /* are we stopped */
+int reload = 0; /* are we stopped */
+int run_sigint_processing = 0;
+
+extern void spawn(int);
+extern void hup_handler();
+extern void reload_inittab();
+extern void read_inittab(void);
+static int read_initfile(const char *);
+extern void tstp_handler();
+extern void int_handler();
+extern void sigint_processing();
+extern void cont_handler();
+extern void set_tz(void);
+extern void write_wtmp(void);
+extern void make_ascii_tty(void);
+extern void make_console(const char *);
+extern int boot_single(int singlearg, int argc, char *argv[]);
+#ifdef CONFIG_USER_INIT_CONF
+extern void load_init_conf(void);
+#endif
+
+/* Keep track of console device, if any... */
+#if LINUX_VERSION_CODE < 0x020100
+char *console_device = NULL;
+int console_baud = -1;
+#else
+int have_console = 0;
+#endif
+
+
+static void err(const char *s)
+{
+ struct iovec output[2];
+#if LINUX_VERSION_CODE < 0x020100
+ int fd;
+#endif
+ output[0].iov_base = "init: ";
+ output[0].iov_len = 6;
+ output[1].iov_base = (void *)s;
+ output[1].iov_len = strlen(s);
+#if LINUX_VERSION_CODE < 0x020100
+ if (console_device == NULL) return;
+ if((fd = open(console_device, O_WRONLY)) < 0) return;
+ writev(fd, output, 2);
+ close(fd);
+#else
+ if (have_console)
+ writev(1, output, 2);
+#endif
+}
+
+void
+add_tok(struct initline *p, char *tok)
+{
+ int i;
+ for (i = 0; p->toks && p->toks[i]; i++)
+ ;
+
+ /* allocate space for new entry and terminating NULL */
+ p->toks = (char **) realloc(p->toks, (i + 2) * sizeof(char *));
+ if (!p->toks) {
+ err("malloc failed\n");
+ _exit(1);
+ }
+ p->toks[i++] = tok;
+ p->toks[i] = NULL;
+}
+
+static void enter_single(void)
+{
+ pid_t pid;
+ char *av[2];
+
+ err("Booting to single user mode\n");
+ av[0] = _PATH_BSHELL;
+ av[1] = NULL;
+ if((pid = vfork()) == 0) {
+ extern char **environ;
+ /* the child */
+ execve(_PATH_BSHELL, av, environ);
+ err("exec of single user shell failed\n");
+ _exit(0);
+ } else if(pid > 0) {
+ int i;
+ while(wait(&i) != pid) /* nothing */;
+ } else if(pid < 0) {
+ err("fork of single user shell failed\n");
+ }
+ unlink(_PATH_SINGLE);
+}
+
+
+#if LINUX_VERSION_CODE < 0x020100
+static void
+set_console_baud(int baud)
+{
+ switch (baud) {
+ case 50: console_baud = B50; break;
+ case 75: console_baud = B75; break;
+ case 110: console_baud = B110; break;
+ case 134: console_baud = B134; break;
+ case 150: console_baud = B150; break;
+ case 200: console_baud = B200; break;
+ case 300: console_baud = B300; break;
+ case 600: console_baud = B600; break;
+ case 1200: console_baud = B1200; break;
+ case 1800: console_baud = B1800; break;
+ case 2400: console_baud = B2400; break;
+ case 4800: console_baud = B4800; break;
+ default:
+ case 9600: console_baud = B9600; break;
+ case 19200: console_baud = B19200; break;
+ case 38400: console_baud = B38400; break;
+ case 57600: console_baud = B57600; break;
+ case 115200: console_baud = B115200; break;
+ case 230400: console_baud = B230400; break;
+ case 460800: console_baud = B460800; break;
+ }
+}
+#endif
+
+static int do_command(const char *path, const char *filename, int dowait)
+{
+ pid_t pid, wpid;
+ int stat, st;
+
+ if((pid = vfork()) == 0) {
+ /* the child */
+ char *argv[3];
+#ifdef INCLUDE_TIMEZONE
+ char tz[BUF_SIZ];
+#endif
+ char *env[3];
+
+ /* Use /dev/null for stdin */
+ close(0);
+ open("/dev/null", O_RDONLY);
+
+ argv[0] = (char *)path;
+ argv[1] = (char *)filename;
+ argv[2] = NULL;
+
+ env[0] = "PATH=/bin:/usr/bin:/etc:/sbin:/usr/sbin";
+#ifdef INCLUDE_TIMEZONE
+ strcpy(tz, "TZ=");
+ strcat(tz, tzone);
+ env[1] = tz;
+ env[2] = NULL;
+#else
+ env[1] = NULL;
+#endif
+
+ execve(path, argv, env);
+
+ err("exec rc failed\n");
+ _exit(2);
+ } else if(pid > 0) {
+ if (!dowait)
+ stat = 0;
+ else {
+ /* parent, wait till rc process dies before spawning */
+ while ((wpid = wait(&stat)) != pid)
+ if (wpid == -1 && errno == ECHILD) { /* see wait(2) manpage */
+ stat = 0;
+ break;
+ }
+ }
+ } else if(pid < 0) {
+ err("fork of rc shell failed\n");
+ stat = -1;
+ }
+ st = WEXITSTATUS(stat);
+ return st;
+}
+
+/*
+ * run /etc/rc. The environment is passed to the script, so the RC environment
+ * variable can be used to decide what to do. RC may be set from LILO.
+ */
+static int do_rc(void)
+{
+ int rc;
+
+ rc = do_command(_PATH_BSHELL, _PATH_RC, 1);
+ if (rc)
+ return(rc);
+#ifdef CONFIG_USER_INIT_RUN_FIREWALL
+ rc = do_command(_PATH_FIREWALL, "-i", 1);
+ if (rc)
+ err(_PATH_FIREWALL " failed!");
+#endif
+#ifdef CONFIG_USER_FLATFSD_FLATFSD
+ rc = do_command(_PATH_BSHELL, _PATH_CONFIGRC, 1);
+ if (rc)
+ err(_PATH_CONFIGRC " failed!");
+#endif
+#ifdef CONFIG_USER_INIT_RUN_FIREWALL
+ rc = do_command(_PATH_FIREWALL, NULL, 0);
+ if (rc)
+ err(_PATH_FIREWALL " failed!");
+#endif
+#ifdef INCLUDE_TIMEZONE
+ /* We read the timezone file here, because the flat file system
+ * has probably been created by now.
+ */
+ set_tz();
+#endif
+ return(0);
+}
+
+void respawn_children(int signo) {
+ int i, delta = -1;
+ time_t now;
+ alarm(0);
+ if ((now = time(NULL)) == 0) now = 1;
+ for(i = 0; i < numcmd; i++) {
+ if(inittab[i].pid < 0) { /* Start jobs */
+ if(stopped)
+ inittab[i].pid = -1;
+ /*
+ ** Do not spawn child from signal handler !
+ ** SIGALRM would be blocked for the child
+ */
+ else if (signo == 0)
+ spawn(i);
+ }
+ /* Check for naughty jobs */
+ if (inittab[i].nextrun > now) {
+ int d;
+ d = inittab[i].nextrun - now;
+ if (delta < 0 || d < delta)
+ delta = d;
+ }
+ }
+ if (delta > 0) {
+ alarm(delta);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ struct sigaction sa;
+
+ /*
+ * setup all the signal handlers here
+ */
+
+ memset(&sa, 0, sizeof(sa));
+ /* sa.sa_flags = SA_RESETHAND we want to keep the handlers armed */
+
+ sa.sa_handler = tstp_handler;
+ sigaction(SIGTSTP, &sa, NULL);
+
+ sa.sa_handler = cont_handler;
+ sigaction(SIGCONT, &sa, NULL);
+
+ sa.sa_handler = int_handler;
+ sigaction(SIGINT, &sa, NULL);
+
+ sa.sa_handler = respawn_children;
+ sigaction(SIGALRM, &sa, NULL);
+
+ sa.sa_handler = hup_handler;
+ sigaction(SIGHUP, &sa, NULL);
+
+#if defined(CONSOLE_BAUD_RATE) && LINUX_VERSION_CODE < 0x020100
+ set_console_baud(CONSOLE_BAUD_RATE);
+#endif
+
+ /*
+ * start up in single user mode if /etc/singleboot exists or if
+ * argv[1] is "single".
+ */
+ if(boot_single(0, argc, argv)) enter_single();
+
+#ifdef RUN_RC
+ /* Register console if defined by boot */
+#if LINUX_VERSION_CODE < 0x020100
+ if ((console_device = getenv("CONSOLE"))) {
+ char *sp;
+ unsetenv("CONSOLE");
+ if ((sp = strchr(console_device, ','))) {
+ *sp++ = 0;
+ set_console_baud(atoi(sp));
+ }
+ }
+
+ make_ascii_tty();
+#else
+{
+ struct stat st;
+
+ if (isatty(1)) {
+ have_console = 1;
+ make_ascii_tty();
+ } else if (fstat(1, &st) == -1 && errno == EBADF) {
+ /* No stdout, so send everything to /dev/null */
+ close(0); close(1); close(2);
+ open("/dev/null", O_RDWR);
+ dup(0);
+ dup(0);
+ }
+}
+#endif
+
+ /*If we get a SIGTSTP before multi-user mode, do nothing*/
+ while(stopped)
+ pause();
+ if(do_rc() != 0 && boot_single(1, argc, argv) && !stopped)
+ enter_single();
+ while(stopped) /*Also if /etc/rc fails & we get SIGTSTP*/
+ pause();
+#endif
+
+ /* initialize the array of commands */
+ inittab = (struct initline *)malloc(NUMCMD * sizeof(struct initline));
+ inittab_size = NUMCMD;
+
+ if (!inittab) {
+ /* failure case - what do you do if init fails? */
+ err("malloc failed");
+ _exit(1);
+ }
+
+ write_wtmp(); /* write boottime record */
+ read_inittab();
+
+#ifdef DEBUGGING
+ for(i = 0; i < numcmd; i++) {
+ char **p = inittab[i].toks;
+ printf("toks= %s %s %s %s\n",p[0], p[1], p[2], p[3]);
+ printf("tty= %s\n", inittab[i].tty);
+ printf("termcap= %s\n", inittab[i].termcap);
+ }
+ /*exit(0);*/
+#endif
+
+#if LINUX_VERSION_CODE < 0x020100
+ for(i = 0; i < getdtablesize(); i++) close(i);
+#else
+ /* Always leave 0, 1, and 2 connected (to /dev/null) for the child process */
+ for(i = 3; i < getdtablesize(); i++) close(i);
+#endif
+
+ for (;;) {
+ pid_t pid;
+ int vec;
+
+ if (run_sigint_processing) {
+ run_sigint_processing = 0;
+ sigint_processing();
+ }
+
+ respawn_children(0);
+
+ if (reload) {
+ reload = 0;
+ reload_inittab();
+ continue; /* process all reloads before waiting */
+ }
+
+ pid = wait(&vec);
+ alarm(0);
+
+ /* clear utmp entry, and append to wtmp if possible */
+#if 0 /* DAVIDM */
+ {
+ struct utmp *ut;
+ int ut_fd;
+
+ utmpname(_PATH_UTMP);
+ setutent();
+ while((ut = getutent())) {
+ if(ut->ut_pid == pid) {
+ time(&ut->ut_time);
+ bzero(&ut->ut_user, UT_NAMESIZE);
+ bzero(&ut->ut_host, sizeof(ut->ut_host));
+ ut->ut_type = DEAD_PROCESS;
+ ut->ut_pid = 0;
+ ut->ut_addr = 0;
+ endutent();
+ pututline(ut);
+ if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
+ flock(ut_fd, LOCK_EX|LOCK_NB);
+ write(ut_fd, (const void *)ut, sizeof(struct utmp));
+ flock(ut_fd, LOCK_UN|LOCK_NB);
+ close(ut_fd);
+ }
+ break;
+ }
+ }
+ endutent();
+ }
+#endif
+
+ for(i = 0; i < numcmd; i++) {
+ if(pid == inittab[i].pid) {
+ inittab[i].pid = -1;
+ }
+ }
+ }
+}
+
+
+/*
+ * return true if we should boot up in singleuser mode. If argv[i] is
+ * "single" or the file /etc/singleboot exists, then singleuser mode should
+ * be entered. If /etc/securesingle exists ask for root password first.
+ */
+int boot_single(int singlearg, int argc, char *argv[])
+{
+ char *pass, *rootpass = NULL;
+ struct passwd *pwd;
+ int i;
+
+ for(i = 1; i < argc; i++) {
+ if(argv[i] && !strcmp(argv[i], "single")) singlearg = 1;
+ }
+ return 0;
+}
+
+void spawn(int i)
+{
+ pid_t pid;
+ int j;
+ time_t t;
+ struct initline *it;
+ char buf[150];
+
+ it = inittab + i;
+
+ t = time(NULL);
+ /* Check for held process */
+ if ((unsigned long)(it->nextrun - t - 1) < maxdelay)
+ return;
+ if (it->lastrun + testtime > t) { /* Respawning quickly */
+ if (it->xcnt < 0xff)
+ it->xcnt++;
+ } else { /* Normal respawning */
+ it->xcnt = 0;
+ it->lastrun = t;
+ it->delay = delaytime;
+ }
+ if (it->xcnt >= maxspawn) { /* Too many too quickly */
+ strcpy(buf, it->toks[0]);
+ strcat(buf, " respawning too fast\n");
+ err(buf);
+ it->pid = -1;
+ if (it->delay >= maxdelay)
+ it->delay = maxdelay;
+ else if (it->delay < delaytime)
+ it->delay = delaytime;
+ else if((it->delay *= 2) > maxdelay)
+ it->delay = maxdelay;
+ it->nextrun = t + it->delay;
+ /* Fiddle with the tracking vars to ensure that only
+ * one attempt is made to run this next time around.
+ */
+ it->lastrun = it->nextrun;
+ it->xcnt -= 2;
+ return;
+ }
+ it->nextrun = t + delaytime;
+
+ if((pid = vfork()) < 0) {
+ it->pid = -1;
+ err("fork failed\n");
+ return;
+ }
+ if(pid) {
+ /* this is the parent */
+ it->pid = pid;
+ return;
+ } else {
+ /* this is the child */
+ char term[40];
+ char *prog;
+#ifdef INCLUDE_TIMEZONE
+ char tz[BUF_SIZ];
+#endif
+ char *env[4];
+
+ setsid();
+
+ /* Close everything other than 0, 1 and 2 */
+ for(j = 3; j < getdtablesize(); j++) {
+ close(j);
+ }
+ /* Now set up 0, 1 and 2 */
+ make_console(it->tty);
+
+ strcpy(term, "TERM=");
+ strcat(term, it->termcap);
+ env[0] = term;
+ env[1] = "PATH=/bin:/usr/bin:/etc:/sbin:/usr/sbin";
+#ifdef INCLUDE_TIMEZONE
+ strcpy(tz, "TZ=");
+ strcat(tz, tzone);
+ env[2] = tz;
+ env[3] = NULL;
+#else
+ env[2] = NULL;
+#endif
+
+ prog = it->toks[0];
+ if (*prog == '-' && *(prog+1))
+ prog++;
+ execve(prog, it->toks, env);
+ strcpy(buf, it->toks[0]);
+ strcat(buf, " exec failed\n");
+ err(buf);
+ _exit(1);
+ }
+}
+
+static void init_itab(struct initline *p) {
+ bzero(p, sizeof(struct initline));
+ p->pid = -1;
+ p->nextrun = time(NULL);
+}
+
+static void clear_itab(struct initline *p) {
+ if (p->line)
+ free(p->line);
+ if (p->fullline)
+ free(p->fullline);
+ if (p->toks)
+ free(p->toks);
+ init_itab(p);
+}
+
+void read_inittab(void)
+{
+ int i;
+
+ /*
+ * free any old data and start again
+ */
+ for (i = 0; i < numcmd; i++)
+ clear_itab(&inittab[i]);
+ numcmd = 0;
+
+ /* Fake an inittab entry if boot console defined */
+#ifdef CONFIG_USER_INIT_CONSOLE_SH
+#if LINUX_VERSION_CODE < 0x020100
+ if (console_device && strcmp(console_device, "/dev/null"))
+#else
+ if (have_console)
+#endif
+ {
+ struct initline *p;
+ p = inittab + numcmd++;
+ init_itab(p);
+ p->fullline = strdup("console");
+ strcpy(p->tty, "console");
+ strcpy(p->termcap, "linux");
+ add_tok(p, "-/bin/sh");
+ }
+#endif
+
+ i = 0;
+ if (read_initfile(_PATH_INITTAB) == 0)
+ i++;
+
+#ifdef CONFIG_USER_FLATFSD_FLATFSD
+ if (read_initfile(_PATH_CONFIGTAB) == 0)
+ i++;
+#endif
+
+ if (i == 0) {
+ err("Failed to open " _PATH_INITTAB
+#ifdef CONFIG_USER_FLATFSD_FLATFSD
+ " or " _PATH_CONFIGTAB
+#endif
+ "."
+ );
+ }
+
+#ifdef CONFIG_USER_INIT_CONF
+ load_init_conf();
+#endif
+
+ /* if needed, shrink the array using realloc -
+ * must be done here so that we include the results of all init files
+ * when calculating number of commands */
+ if ((numcmd + 2) < (inittab_size - NUMCMD)) {
+ /* round up from numcmd to the nearest multiple of NUMCMD */
+ inittab_size = ((numcmd + 2) / NUMCMD + 1) * NUMCMD;
+ inittab = realloc(inittab, inittab_size * sizeof(struct initline));
+ if (!inittab) {
+ /* failure case - what do you do if init fails? */
+ err("malloc failed");
+ _exit(1);
+ }
+ }
+
+ if (numcmd == 0)
+ _exit(1);
+}
+
+static int
+read_initfile(const char *initfile)
+{
+ struct initline *p;
+ FILE *f;
+ char *buf = NULL;
+ size_t buf_len = 0;
+ int i,j,k;
+ char *ptr, *getty;
+#ifdef SPECIAL_CONSOLE_TERM
+ char tty[50];
+ struct stat stb;
+ char *termenv;
+
+ termenv = getenv("TERM"); /* set by kernel */
+#endif
+
+ i = numcmd;
+
+ if (!(f = fopen(initfile, "r")))
+ return 1;
+
+ while(!feof(f)) {
+ if (i+2 == inittab_size) {
+ /* need to realloc inittab */
+ inittab_size += NUMCMD;
+ inittab = realloc(inittab, inittab_size * sizeof(struct initline));
+ if (!inittab) {
+ /* failure case - what do you do if init fails? */
+ err("malloc failed");
+ _exit(1);
+ }
+ }
+ if (getline(&buf, &buf_len, f) == -1) break;
+
+ for(k = 0; k < buf_len && buf[k]; k++) {
+ if(buf[k] == '#') {
+ buf[k] = '\0'; break;
+ }
+ }
+
+ if(buf[0] == '\0' || buf[0] == '\n') continue;
+
+ p = inittab + i;
+ init_itab(p);
+ p->line = strdup(buf);
+ p->fullline = strdup(buf);
+ if (!p->line || !p->fullline) {
+ err("Not memory to allocate inittab entry");
+ clear_itab(p);
+ continue;
+ }
+ ptr = strtok(p->line, ":");
+ if (!ptr) {
+ err("Missing TTY/ID field in inittab");
+ clear_itab(p);
+ continue;
+ }
+ strncpy(p->tty, ptr, 9);
+ //p->tty[9] = '\0';
+ ptr = strtok(NULL, ":");
+ if (!ptr) {
+ err("Missing TERMTYPE field in inittab");
+ clear_itab(p);
+ continue;
+ }
+ strncpy(p->termcap, ptr, 29);
+ //p->termcap[29] = '\0';
+
+ getty = strtok(NULL, " \t\n");
+ if (!getty) {
+ err("Missing PROCESS field in inittab");
+ clear_itab(p);
+ continue;
+ }
+ add_tok(p, getty);
+ j = 1;
+ while((ptr = strtok(NULL, " \t\n")))
+ add_tok(p, ptr);
+
+#ifdef SPECIAL_CONSOLE_TERM
+ /* special-case termcap for the console ttys */
+ strcpy(tty, "/dev/");
+ strcat(tty, p->tty);
+ if(!termenv || stat(tty, &stb) < 0) {
+ err("no TERM or cannot stat tty\n");
+ } else {
+ /* is it a console tty? */
+ if(major(stb.st_rdev) == 4 && minor(stb.st_rdev) < 64) {
+ strncpy(p->termcap, termenv, 30);
+ p->termcap[29] = 0;
+ }
+ }
+#endif
+
+ i++;
+ }
+
+ if (buf)
+ free(buf);
+
+ fclose(f);
+
+ numcmd = i;
+ return 0;
+}
+
+void hup_handler()
+{
+ reload = 1;
+}
+
+void reload_inittab()
+{
+ int i;
+ int oldnum;
+ char ** saveline = (char **) malloc(inittab_size * sizeof(char *));
+ pid_t * savepid = (pid_t*) malloc(inittab_size * sizeof(pid_t));
+
+ if (!saveline || !savepid) {
+ /* another failure case - what DO you do if init fails */
+ err("malloc failed");
+ _exit(1);
+ }
+
+ for (i=0; i<numcmd; i++) {
+ savepid[i] = inittab[i].pid;
+ saveline[i] = strdup(inittab[i].fullline);
+ if (!saveline[i]) {
+ err("malloc failed");
+ _exit(1);
+ }
+ }
+
+ oldnum = numcmd;
+ read_inittab();
+
+ /* See which ones still exist */
+ for(i = 0; i < numcmd; i++) {
+ int j;
+ for(j = 0; j < oldnum; j++) {
+ if(strcmp(saveline[j], inittab[i].fullline) == 0) {
+ inittab[i].pid = savepid[j];
+ savepid[j] = -1;
+ break;
+ }
+ }
+ }
+
+ /* Kill off processes no longer needed and free memory */
+ for(i = 0; i < oldnum; i++) {
+ if (savepid[i] > 1)
+ kill(savepid[i], SIGTERM);
+ free(saveline[i]);
+ }
+
+ free(saveline);
+ free(savepid);
+}
+
+void tstp_handler()
+{
+ stopped++;
+}
+
+void cont_handler()
+{
+ stopped = 0;
+}
+
+void int_handler()
+{
+ run_sigint_processing = 1;
+}
+
+void sigint_processing()
+{
+ /*
+ * After Linux 0.96b PL1, we get a SIGINT when
+ * the user presses Ctrl-Alt-Del...
+ */
+
+ int pid;
+
+ sync();
+ sync();
+ if((pid = vfork()) == 0) {
+ char *av[2];
+ extern char **environ;
+ /* reboot properly... */
+ av[0] = _PATH_REBOOT;
+ av[1] = NULL;
+
+ execve(_PATH_REBOOT, av, environ);
+#if __GNU_LIBRARY__ > 5
+ reboot(0x1234567);
+#else
+ reboot(0xfee1dead, 672274793, 0x1234567);
+#endif
+ _exit(2);
+ } else if(pid < 0) {
+ /* fork failed, try the hard way... */
+#if __GNU_LIBRARY__ > 5
+ reboot(0x1234567);
+#else
+ reboot(0xfee1dead, 672274793, 0x1234567);
+#endif
+ }
+}
+
+#ifdef INCLUDE_TIMEZONE
+void set_tz(void)
+{
+ FILE *f;
+ int len;
+
+ if((f = fopen("/etc/config/TZ", "r")) == NULL &&
+ (f = fopen("/etc/TZ", "r")) == NULL)
+ return;
+ fgets(tzone, BUF_SIZ-2, f);
+ fclose(f);
+ if((len=strlen(tzone)) < 2)
+ return;
+ tzone[len-1] = 0; /* get rid of the '\n' */
+ setenv("TZ", tzone, 0);
+}
+#endif
+
+#ifdef CONFIG_USER_INIT_CONF
+void load_init_conf(void)
+{
+ char line[BUF_SIZ];
+ FILE *f;
+
+ if ((f = fopen("/etc/config/init.conf", "r")) == NULL &&
+ (f = fopen("/etc/init.conf", "r")) == NULL)
+ return;
+ while (fgets(line, sizeof(line) - 2, f)) {
+ if (strncasecmp(line, "delaytime=", 10) == 0)
+ delaytime = atoi(line + 10);
+ if (strncasecmp(line, "maxdelay=", 9) == 0)
+ maxdelay = atoi(line + 9);
+ if (strncasecmp(line, "maxspawn=", 9) == 0)
+ maxspawn = atoi(line + 9);
+ if (strncasecmp(line, "testtime=", 9) == 0)
+ testtime = atoi(line + 9);
+ }
+ fclose(f);
+}
+#endif
+
+void write_wtmp(void)
+{
+#if 0
+ int fd;
+ struct utmp ut;
+
+ bzero((char *)&ut, sizeof(ut));
+ strcpy(ut.ut_line, "~");
+ bzero(ut.ut_name, sizeof(ut.ut_name));
+ time(&ut.ut_time);
+ ut.ut_type = BOOT_TIME;
+
+ if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND)) >= 0) {
+ flock(fd, LOCK_EX|LOCK_NB); /* make sure init won't hang */
+ write(fd, (char *)&ut, sizeof(ut));
+ flock(fd, LOCK_UN|LOCK_NB);
+ close(fd);
+ }
+#endif
+}
+
+void make_ascii_tty(void)
+{
+ struct termios tty;
+ const char *pt;
+
+ if (tcgetattr(0, &tty) < 0)
+ return;
+
+ tty.c_iflag &= ~(INLCR|IGNCR|IUCLC);
+ tty.c_iflag |= ICRNL;
+ tty.c_oflag &= ~(OCRNL|OLCUC|ONOCR|ONLRET|OFILL);
+ tty.c_oflag |= OPOST|ONLCR;
+ tty.c_cflag |= CLOCAL;
+ tty.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE;
+#ifdef IEXTEN
+ tty.c_lflag |= IEXTEN;
+#endif
+
+#if LINUX_VERSION_CODE < 0x020100
+ if (console_baud != -1)
+ cfsetospeed(&tty, console_baud);
+#endif
+
+ tty.c_cc[VINTR] = CTRL('C');
+ tty.c_cc[VQUIT] = CTRL('\\');
+ tty.c_cc[VERASE] = CTRL('H'); /*127*/
+ tty.c_cc[VKILL] = CTRL('U'); /*Changed from non-standard ^X*/
+ tty.c_cc[VEOF] = CTRL('D');
+ tty.c_cc[VTIME] = 0;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VSTART] = CTRL('Q');
+ tty.c_cc[VSTOP] = CTRL('S');
+ tty.c_cc[VSUSP] = CTRL('Z');
+#ifdef VWERASE
+ tty.c_cc[VWERASE] = CTRL('W');
+#endif
+ /* Pick up simple environment setting of VERASE.
+ * Useful for setting on kernel command line.
+ * e.g. TTYERASE=^?
+ */
+ pt = getenv("TTYERASE");
+ if (pt && pt[0] == '^' && pt[1]) {
+ tty.c_cc[VERASE] = (pt[1] == '?') ? 127 : CTRL(pt[1]);
+ }
+
+ tcsetattr(0, TCSANOW, &tty);
+}
+
+void make_console(const char *tty)
+{
+ char devname[32];
+
+ close(0); close(1); close(2);
+
+ if (tty && *tty) {
+#if LINUX_VERSION_CODE < 0x020100
+ /*
+ * until we get proper console support under 2.0
+ */
+ if (strcmp(tty, "console") == 0) {
+ strcpy(devname, console_device);
+ }
+ else
+#endif
+ {
+ strcpy(devname, "/dev/");
+ strcat(devname, tty);
+ }
+
+ /* Try to open the specified console */
+ if (open(devname, O_RDWR|O_NONBLOCK) >= 0) {
+ fcntl(0, F_SETFL, 0);
+ dup(0);
+ dup(0);
+ make_ascii_tty();
+ ioctl(0, TIOCSCTTY, (char*)0);
+ return;
+ }
+ }
+
+ /* No go, so send to /dev/null */
+ open("/dev/null", O_RDWR|O_NONBLOCK);
+ dup(0);
+ dup(0);
+}