From 8e2707b81b0c90295c9fdf92a576925442d22147 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Wed, 20 Aug 2014 21:11:13 +0200 Subject: add sash, simpleinit and a uclibc config for nonmmu case --- package/simpleinit/src/pathnames.h | 37 ++ package/simpleinit/src/simpleinit.c | 1046 +++++++++++++++++++++++++++++++++++ 2 files changed, 1083 insertions(+) create mode 100644 package/simpleinit/src/pathnames.h create mode 100644 package/simpleinit/src/simpleinit.c (limited to 'package/simpleinit/src') 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 + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SHADOW_PWD +#include +#endif + +#if __GNU_LIBRARY__ > 5 +#include +#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 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); +} -- cgit v1.2.3