#include <utmp.h>
#include <ctype.h>
#include <stdarg.h>
+#include <sys/ttydefaults.h>
#include <sys/syslog.h>
#include <sys/time.h>
}
static
-char *istrdup(char *s)
+char *istrdup(const char *s)
{
char *m;
int l;
f = fdopen(fd, "r");
- if (get_cmd(f) != C_VER)
+ if (get_cmd(f) != C_VER) {
+ fclose(f);
return -1;
+ }
get_string(old_version, sizeof(old_version), f);
oops_error = 0;
for (pp = &family; (*pp = get_record(f)) != NULL; pp = &((*pp)->next))
rlim.rlim_cur = RLIM_INFINITY;
rlim.rlim_max = RLIM_INFINITY;
setrlimit(RLIMIT_CORE, &rlim);
- chdir("/");
+ if (0 != chdir("/"))
+ initlog(L_VB, "unable to chdir to /: %s",
+ strerror(errno));
signal(SIGSEGV, SIG_DFL);
raise(SIGSEGV);
}
}
+/*
+ * Add or replace specific environment value
+ */
+int addnewenv(const char *new, char **curr, int n)
+{
+ size_t nlen = strcspn(new, "=");
+ int i;
+ for (i = 0; i < n; i++) {
+ if (nlen != strcspn(curr[i], "="))
+ continue;
+ if (strncmp (new, curr[i], nlen) == 0)
+ break;
+ }
+ if (i >= n)
+ curr[n++] = istrdup(new);
+ else {
+ free(curr[i]);
+ curr[i] = istrdup(new);
+ }
+ return n;
+}
/*
* Build a new environment for execve().
{
char i_lvl[] = "RUNLEVEL=x";
char i_prev[] = "PREVLEVEL=x";
- char i_cons[32];
+ char i_cons[128];
char i_shell[] = "SHELL=" SHELL;
char **e;
int n, i;
for (n = 0; environ[n]; n++)
;
- n += NR_EXTRA_ENV;
+ n += NR_EXTRA_ENV + 1; /* Also room for last NULL */
if (child)
n += 8;
- e = calloc(n, sizeof(char *));
+
+ while ((e = (char**)calloc(n, sizeof(char *))) == NULL) {
+ initlog(L_VB, "out of memory");
+ do_sleep(5);
+ }
for (n = 0; environ[n]; n++)
e[n] = istrdup(environ[n]);
for (i = 0; i < NR_EXTRA_ENV; i++) {
- if (extra_env[i])
- e[n++] = istrdup(extra_env[i]);
+ if (extra_env[i] == NULL || *extra_env[i] == '\0')
+ continue;
+ n = addnewenv(extra_env[i], e, n);
}
if (child) {
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);
- e[n++] = istrdup(E_VERSION);
+ n = addnewenv(i_shell, e, n);
+ n = addnewenv(i_lvl, e, n);
+ n = addnewenv(i_prev, e, n);
+ n = addnewenv(i_cons, e, n);
+ n = addnewenv(E_VERSION, e, n);
}
e[n++] = NULL;
* to be its controlling tty.
*/
if (strchr("*#sS", runlevel) && ch->flags & WAITING) {
+ int ftty; /* Handler for tty controlling */
/*
* We fork once extra. This is so that we can
* wait and change the process group and session
* of the console after exit of the leader.
*/
setsid();
- if ((f = console_open(O_RDWR|O_NOCTTY)) >= 0) {
+ if ((ftty = console_open(O_RDWR|O_NOCTTY)) >= 0) {
/* Take over controlling tty by force */
- (void)ioctl(f, TIOCSCTTY, 1);
- dup(f);
- dup(f);
+ (void)ioctl(ftty, TIOCSCTTY, 1);
+
+ if(dup(ftty) < 0){
+ initlog(L_VB, "cannot duplicate console fd");
+ }
+
+ if(dup(ftty) < 0){
+ initlog(L_VB, "cannot duplicate console fd");
+ }
+
}
/*
* Small optimization. See if stealing
* controlling tty back is needed.
*/
- pgrp = tcgetpgrp(f);
+ pgrp = tcgetpgrp(ftty);
if (pgrp != getpid())
exit(0);
}
if (pid == 0) {
setsid();
- (void)ioctl(f, TIOCSCTTY, 1);
+ (void)ioctl(ftty, TIOCSCTTY, 1);
exit(0);
}
while((rc = waitpid(pid, &st, 0)) != pid)
/* Set ioctl settings to default ones */
console_stty();
- } else {
+ } else { /* parent */
+ int fd;
setsid();
- if ((f = console_open(O_RDWR|O_NOCTTY)) < 0) {
+ if ((fd = console_open(O_RDWR|O_NOCTTY)) < 0) {
initlog(L_VB, "open(%s): %s", console_dev,
strerror(errno));
- f = open("/dev/null", O_RDWR);
+ fd = open("/dev/null", O_RDWR);
+ }
+
+ if(dup(fd) < 0) {
+ initlog(L_VB, "cannot duplicate /dev/null fd");
+ }
+
+ if(dup(fd) < 0) {
+ initlog(L_VB, "cannot duplicate /dev/null fd");
}
- dup(f);
- dup(f);
+
}
/*
case POWEROKWAIT:
case CTRLALTDEL:
if (!(ch->flags & XECUTED)) ch->flags |= WAITING;
+ /* Fall through */
case KBREQUEST:
case BOOT:
case POWERFAIL:
#endif
/*
- * Open INITTAB and real line by line.
+ * Open INITTAB and read line by line.
*/
if ((fp = fopen(INITTAB, "r")) == NULL)
initlog(L_VB, "No inittab file found");
if (rlevel && strlen(rlevel) > 11)
strcpy(err, "rlevel field too long (max 11 characters)");
if (process && strlen(process) > 127)
- strcpy(err, "process field too long");
+ strcpy(err, "process field too long (max 127 characters)");
if (action && strlen(action) > 32)
strcpy(err, "action field too long");
if (err[0] != 0) {
case 0: /* Send TERM signal */
if (talk)
initlog(L_CO,
- "Sending processes the TERM signal");
+ "Sending processes configured via /etc/inittab the TERM signal");
kill(-(ch->pid), SIGTERM);
foundOne = 1;
break;
case 1: /* Send KILL signal and collect status */
if (talk)
initlog(L_CO,
- "Sending processes the KILL signal");
+ "Sending processes configured via /etc/inittab the KILL signal");
kill(-(ch->pid), SIGKILL);
break;
}
static
void initcmd_setenv(char *data, int size)
{
- char *env, *p, *e, *eq;
- int i, sz;
+ char *env, *p, *e;
+ size_t sz;
+ int i, eq;
e = data + size;
while (*data && data < e) {
- eq = NULL;
for (p = data; *p && p < e; p++)
- if (*p == '=') eq = p;
+ ;
if (*p) break;
env = data;
data = ++p;
- sz = eq ? (eq - env) : (p - env);
-
- /*initlog(L_SY, "init_setenv: %s, %s, %d", env, eq, sz);*/
-
/*
* We only allow INIT_* to be set.
*/
if (strncmp(env, "INIT_", 5) != 0)
continue;
+ sz = strcspn(env, "=");
+ eq = (env[sz] == '=');
+
+ /*initlog(L_SY, "init_setenv: %s, %d, %d", env, eq, sz);*/
+
/* Free existing vars. */
for (i = 0; i < NR_EXTRA_ENV; i++) {
- if (extra_env[i] == NULL) continue;
- if (!strncmp(extra_env[i], env, sz) &&
- extra_env[i][sz] == '=') {
+ if (extra_env[i] == NULL)
+ continue;
+ if (sz != strcspn(extra_env[i], "="))
+ continue;
+ if (strncmp(extra_env[i], env, sz) == 0) {
free(extra_env[i]);
extra_env[i] = NULL;
}
}
+ if (eq == 0)
+ continue;
+
/* Set new vars if needed. */
- if (eq == NULL) continue;
for (i = 0; i < NR_EXTRA_ENV; i++) {
if (extra_env[i] == NULL) {
extra_env[i] = istrdup(env);
if (!strchr("0123456789SsQqAaBbCcUu", argv[optind][0]))
usage(progname);
request.cmd = INIT_CMD_RUNLVL;
- request.runlevel = env ? 0 : argv[optind][0];
+ request.runlevel = argv[optind][0];
request.sleeptime = sltime;
}
/* Change to the root directory. */
- chdir("/");
+ if (0 != chdir("/"))
+ initlog(L_VB, "unable to chdir to /: %s",
+ strerror(errno));
/* Open the fifo and write a command. */
/* Make sure we don't hang on opening /dev/initctl */