#ifdef __i386__
-# if (__GLIBC__ >= 2)
+# ifdef __GLIBC__
/* GNU libc 2.x */
# define STACK_DEBUG 1
# if (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
/* Only glibc 2.0 needs this */
# include <sigcontext.h>
+# elif ( __GLIBC__ > 2) && ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))
+# include <bits/sigcontext.h>
# endif
# endif
#endif
* This only works correctly because the linux select updates
* the elapsed time in the struct timeval passed to select!
*/
+static
void do_sleep(int sec)
{
struct timeval tv;
/*
* Non-failing allocation routines (init cannot fail).
*/
+static
void *imalloc(size_t size)
{
void *m;
return m;
}
-
+static
char *istrdup(char *s)
{
char *m;
* Send the state info of the previous running init to
* the new one, in a version-independant way.
*/
+static
void send_state(int fd)
{
FILE *fp;
* Read the complete state info from the state pipe.
* Returns 0 on success
*/
+static
int receive_state(int fd)
{
FILE *f;
/*
* Set console_dev to a working console.
*/
+static
void console_init(void)
{
int fd;
/*
* Open the console with retries.
*/
+static
int console_open(int mode)
{
int f, fd = -1;
/*
* We got a signal (HUP PWR WINCH ALRM INT)
*/
+static
void signal_handler(int sig)
{
ADDSET(got_signals, sig);
/*
* SIGCHLD: one of our children has died.
*/
-void chld_handler()
+static
+# ifdef __GNUC__
+void chld_handler(int sig __attribute__((unused)))
+# else
+void chld_handler(int sig)
+# endif
{
CHILD *ch;
int pid, st;
*
* The SIGCONT handler
*/
-void cont_handler()
+static
+# ifdef __GNUC__
+void cont_handler(int sig __attribute__((unused)))
+# else
+void cont_handler(int sig)
+# endif
{
got_cont = 1;
}
/*
* Fork and dump core in /.
*/
+static
void coredump(void)
{
static int dumped = 0;
* If we have the info, print where it occured.
* Then sleep 30 seconds and try to continue.
*/
+static
#if defined(STACK_DEBUG) && defined(__linux__)
+# ifdef __GNUC__
+void segv_handler(int sig __attribute__((unused)), struct sigcontext ctx)
+# else
void segv_handler(int sig, struct sigcontext ctx)
+# endif
{
char *p = "";
int saved_errno = errno;
errno = saved_errno;
}
#else
-void segv_handler()
+# ifdef __GNUC__
+void segv_handler(int sig __attribute__((unused)))
+# else
+void segv_handler(int sig)
+# endif
{
int saved_errno = errno;
/*
* The SIGSTOP & SIGTSTP handler
*/
-void stop_handler()
+static
+# ifdef __GNUC__
+void stop_handler(int sig __attribute__((unused)))
+# else
+void stop_handler(int sig)
+# endif
{
int saved_errno = errno;
/*
* Set terminal settings to reasonable defaults
*/
+static
void console_stty(void)
{
struct termios tty;
tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
tty.c_cflag |= HUPCL|CLOCAL|CREAD;
- tty.c_cc[VINTR] = 3; /* ctrl('c') */
- tty.c_cc[VQUIT] = 28; /* ctrl('\\') */
- tty.c_cc[VERASE] = 127;
- tty.c_cc[VKILL] = 24; /* ctrl('x') */
- tty.c_cc[VEOF] = 4; /* ctrl('d') */
- tty.c_cc[VTIME] = 0;
- tty.c_cc[VMIN] = 1;
- tty.c_cc[VSTART] = 17; /* ctrl('q') */
- tty.c_cc[VSTOP] = 19; /* ctrl('s') */
- tty.c_cc[VSUSP] = 26; /* ctrl('z') */
+ tty.c_cc[VINTR] = CINTR;
+ tty.c_cc[VQUIT] = CQUIT;
+ tty.c_cc[VERASE] = CERASE; /* ASCII DEL (0177) */
+ tty.c_cc[VKILL] = CKILL;
+ tty.c_cc[VEOF] = CEOF;
+ tty.c_cc[VTIME] = 0;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VSWTC] = _POSIX_VDISABLE;
+ tty.c_cc[VSTART] = CSTART;
+ tty.c_cc[VSTOP] = CSTOP;
+ tty.c_cc[VSUSP] = CSUSP;
+ tty.c_cc[VEOL] = _POSIX_VDISABLE;
+ tty.c_cc[VREPRINT] = CREPRINT;
+ tty.c_cc[VDISCARD] = CDISCARD;
+ tty.c_cc[VWERASE] = CWERASE;
+ tty.c_cc[VLNEXT] = CLNEXT;
+ tty.c_cc[VEOL2] = _POSIX_VDISABLE;
/*
* Set pre and post processing
*/
- tty.c_iflag = IGNPAR|ICRNL|IXON|IXANY
+ tty.c_iflag = IGNPAR|ICRNL|IXON|IXANY;
#ifdef IUTF8 /* Not defined on FreeBSD */
- | (tty.c_iflag & IUTF8)
+ tty.c_iflag |= IUTF8;
#endif /* IUTF8 */
- ;
tty.c_oflag = OPOST|ONLCR;
tty.c_lflag = ISIG|ICANON|ECHO|ECHOCTL|ECHOPRT|ECHOKE;
+#if defined(SANE_TIO) && (SANE_TIO == 1)
+ /*
+ * Disable flow control (-ixon), ignore break (ignbrk),
+ * and make nl/cr more usable (sane).
+ */
+ tty.c_iflag |= IGNBRK;
+ tty.c_iflag &= ~(BRKINT|INLCR|IGNCR|IXON);
+ tty.c_oflag &= ~(OCRNL|ONLRET);
+#endif
/*
* Now set the terminal line.
* We don't care about non-transmitted output data
char i_lvl[] = "RUNLEVEL=x";
char i_prev[] = "PREVLEVEL=x";
char i_cons[32];
+ char i_shell[] = "SHELL=" SHELL;
char **e;
int n, i;
snprintf(i_cons, sizeof(i_cons), "CONSOLE=%s", console_dev);
i_lvl[9] = thislevel;
i_prev[10] = prevlevel;
+ e[n++] = istrdup(i_shell);
e[n++] = istrdup(i_lvl);
e[n++] = istrdup(i_prev);
e[n++] = istrdup(i_cons);
* This function is too long and indents too deep.
*
*/
+static
int spawn(CHILD *ch, int *res)
{
char *args[16]; /* Argv array */
/*
* Start a child running!
*/
+static
void startup(CHILD *ch)
{
/*
/*
* Read the inittab file.
*/
+static
void read_inittab(void)
{
FILE *fp; /* The INITTAB file */
* The entries that do not belong here at all are removed
* from the list.
*/
+static
void start_if_needed(void)
{
CHILD *ch; /* Pointer to child */
/*
* Ask the user on the console for a runlevel
*/
+static
int ask_runlevel(void)
{
const char prompt[] = "\nEnter runlevel: ";
* Search the INITTAB file for the 'initdefault' field, with the default
* runlevel. If this fails, ask the user to supply a runlevel.
*/
+static
int get_init_default(void)
{
CHILD *ch;
* the "old" INITLVL and arg == 0, try to read the new
* runlevel from that file first.
*/
+static
int read_level(int arg)
{
CHILD *ch; /* Walk through list */
initlog(L_VB, "Switching to runlevel: %c", foo);
}
- if (foo == 'Q') return runlevel;
+ if (foo == 'Q') {
+#if defined(SIGINT_ONLYONCE) && (SIGINT_ONLYONCE == 1)
+ /* Re-enable signal from keyboard */
+ struct sigaction sa;
+ SETSIG(sa, SIGINT, signal_handler, 0);
+#endif
+ return runlevel;
+ }
/* Check if this is a runlevel a, b or c */
if (strchr("ABC", foo)) {
* longer than 5 minutes, or inittab was read again due
* to user interaction.
*/
+static
void fail_check(void)
{
CHILD *ch; /* Pointer to child structure */
}
/* Set all 'Fail' timers to 0 */
+static
void fail_cancel(void)
{
CHILD *ch;
/*
* Start up powerfail entries.
*/
+static
void do_power_fail(int pwrstat)
{
CHILD *ch;
/*
* Check for state-pipe presence
*/
+static
int check_pipe(int fd)
{
struct timeval t;
/*
* Make a state-pipe.
*/
+static
int make_pipe(int fd)
{
int fds[2];
/*
* Attempt to re-exec.
*/
+static
void re_exec(void)
{
CHILD *ch;
* We got a change runlevel request through the
* init.fifo. Process it.
*/
+static
void fifo_new_level(int level)
{
#if CHANGE_WAIT
if (runlevel > '1' && runlevel < '6') redo_utmp_wtmp();
read_inittab();
fail_cancel();
- setproctitle("init [%c]", runlevel);
+ setproctitle("init [%c]", (int)runlevel);
}
}
}
* encoded as KEY=VAL\0KEY=VAL\0\0. With "=VAL" it means
* setenv, without it means unsetenv.
*/
+static
void initcmd_setenv(char *data, int size)
{
char *env, *p, *e, *eq;
* the 2.2 kernel credential stuff to see who we're talking to.
*
*/
+static
void check_init_fifo(void)
{
struct init_request request;
* This function is used in the transition
* sysinit (-> single user) boot -> multi-user.
*/
+static
void boot_transitions()
{
CHILD *ch;
write_utmp_wtmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~");
thislevel = runlevel;
prevlevel = oldlevel;
- setproctitle("init [%c]", runlevel);
+ setproctitle("init [%c]", (int)runlevel);
}
}
}
* Init got hit by a signal. See which signal it is,
* and act accordingly.
*/
+static
void process_signals()
{
CHILD *ch;
}
if (ISMEMBER(got_signals, SIGINT)) {
+#if defined(SIGINT_ONLYONCE) && (SIGINT_ONLYONCE == 1)
+ /* Ignore any further signal from keyboard */
+ struct sigaction sa;
+ SETSIG(sa, SIGINT, SIG_IGN, SA_RESTART);
+#endif
INITDBG(L_VB, "got SIGINT");
/* Tell ctrlaltdel entry to start up */
for(ch = family; ch; ch = ch->next)
runlevel == '1') console_stty();
read_inittab();
fail_cancel();
- setproctitle("init [%c]", runlevel);
+ setproctitle("init [%c]", (int)runlevel);
DELSET(got_signals, SIGHUP);
}
}
/*
* The main loop
*/
-int init_main()
+static
+void init_main(void)
{
CHILD *ch;
struct sigaction sa;
/*
* Tell the user about the syntax we expect.
*/
+static
void usage(char *s)
{
fprintf(stderr, "Usage: %s {-e VAR[=VAL] | [-t SECONDS] {0|1|2|3|4|5|6|S|s|Q|q|A|a|B|b|C|c|U|u}}\n", s);
exit(1);
}
+static
int telinit(char *progname, int argc, char **argv)
{
#ifdef TELINIT_USES_INITLVL
request.sleeptime = sltime;
}
+ /* Change to the root directory. */
+ chdir("/");
+
/* Open the fifo and write a command. */
/* Make sure we don't hang on opening /dev/initctl */
SETSIG(sa, SIGALRM, signal_handler, 0);
alarm(3);
- if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0 &&
- write(fd, &request, sizeof(request)) == sizeof(request)) {
+ if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0) {
+ ssize_t p = 0;
+ size_t s = sizeof(request);
+ void *ptr = &request;
+
+ while (s > 0) {
+ p = write(fd, ptr, s);
+ if (p < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ break;
+ }
+ ptr += p;
+ s -= p;
+ }
close(fd);
alarm(0);
return 0;
p++;
else
p = argv[0];
+
+ /* Common umask */
umask(022);
/* Quick check */
for (f = 0; f < argc; f++)
maxproclen += strlen(argv[f]) + 1;
reload = 1;
- setproctitle("init [%c]",runlevel);
+ setproctitle("init [%c]", (int)runlevel);
init_main();
}
argv0 = argv[0];
argv[1] = NULL;
setproctitle("init boot");
- init_main(dfl_level);
+ init_main();
/*NOTREACHED*/
return 0;