python3: update to 3.11.10
[openadk.git] / package / simpleinit / src / simpleinit.c
blob291f88f479cf9ad4e24d727bc09120d0e6739ac3
1 /* simpleinit.c - poe@daimi.aau.dk */
2 /* Version 1.21 */
4 /* gerg@snapgear.com -- modified for direct console support DEC/1999 */
5 /* davidm@snapgear.com -- modified for init.conf SEP/2004 */
6 /* toby@snapgear.com -- allow the array of commands to grow as needed OCT/2004 */
7 /* davidm@snapgear.com -- use dynamically allocated tables APR/2005 */
9 #define _GNU_SOURCE /* For crypt() and termios defines */
11 #include <sys/types.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <limits.h>
15 #include <stdio.h>
16 #include <fcntl.h>
17 #include <string.h>
18 #include <signal.h>
19 #include <pwd.h>
20 #include <sys/file.h>
21 #include <sys/wait.h>
22 #include <sys/stat.h>
23 #include <sys/termios.h>
24 #include <sys/ioctl.h>
25 #include <sys/uio.h>
26 #include <linux/version.h>
27 #include <utmp.h>
28 #include <errno.h>
29 #include <time.h>
30 #include <termios.h>
31 #ifdef SHADOW_PWD
32 #include <shadow.h>
33 #endif
35 #if __GNU_LIBRARY__ > 5
36 #include <sys/reboot.h>
37 #endif
39 #include "pathnames.h"
41 #define BUF_SIZ 100 /* max size of a line in inittab */
42 #define NUMCMD 30 /* step size when realloc more space for the commands */
43 #define NUMTOK 20 /* max number of tokens in inittab command */
45 /* Threshold time for detecting "fast" spawning processes */
46 static int testtime = 90;
47 /* Number of rapid respawns that counts as too fast */
48 static int maxspawn = 5;
49 /* Maximum delay between runs */
50 static int maxdelay = 595;
51 /* Time between successive runs of a process */
52 static int delaytime = 5;
54 #define MAXTRIES 3 /* number of tries allowed when giving the password */
56 #define RUN_RC /* Use a console if possible */
58 #ifndef CTRL
59 #define CTRL(X) ((X)&037)
60 #endif
62 #ifdef INCLUDE_TIMEZONE
63 char tzone[BUF_SIZ];
64 #endif
65 /* #define DEBUGGING */
67 /* Define this if you want init to ignore the termcap field in inittab for
68 console ttys. */
69 /* #define SPECIAL_CONSOLE_TERM */
71 struct initline {
72 pid_t pid;
73 time_t lastrun;
74 time_t nextrun;
75 char **toks;
76 short delay;
77 char tty[10];
78 char termcap[30];
79 char *line;
80 char *fullline;
81 unsigned char xcnt;
84 struct initline *inittab;
85 /* How many struct initline's will fit in the memory pointed to by inittab */
86 int inittab_size = 0;
87 int numcmd;
88 int stopped = 0; /* are we stopped */
89 int reload = 0; /* are we stopped */
90 int run_sigint_processing = 0;
92 extern void spawn(int);
93 extern void hup_handler();
94 extern void reload_inittab();
95 extern void read_inittab(void);
96 static int read_initfile(const char *);
97 extern void tstp_handler();
98 extern void int_handler();
99 extern void sigint_processing();
100 extern void cont_handler();
101 extern void set_tz(void);
102 extern void write_wtmp(void);
103 extern void make_ascii_tty(void);
104 extern void make_console(const char *);
105 extern int boot_single(int singlearg, int argc, char *argv[]);
106 #ifdef CONFIG_USER_INIT_CONF
107 extern void load_init_conf(void);
108 #endif
110 /* Keep track of console device, if any... */
111 #if LINUX_VERSION_CODE < 0x020100
112 char *console_device = NULL;
113 int console_baud = -1;
114 #else
115 int have_console = 0;
116 #endif
119 static void err(const char *s)
121 struct iovec output[2];
122 #if LINUX_VERSION_CODE < 0x020100
123 int fd;
124 #endif
125 output[0].iov_base = "init: ";
126 output[0].iov_len = 6;
127 output[1].iov_base = (void *)s;
128 output[1].iov_len = strlen(s);
129 #if LINUX_VERSION_CODE < 0x020100
130 if (console_device == NULL) return;
131 if((fd = open(console_device, O_WRONLY)) < 0) return;
132 writev(fd, output, 2);
133 close(fd);
134 #else
135 if (have_console)
136 writev(1, output, 2);
137 #endif
140 void
141 add_tok(struct initline *p, char *tok)
143 int i;
144 for (i = 0; p->toks && p->toks[i]; i++)
147 /* allocate space for new entry and terminating NULL */
148 p->toks = (char **) realloc(p->toks, (i + 2) * sizeof(char *));
149 if (!p->toks) {
150 err("malloc failed\n");
151 _exit(1);
153 p->toks[i++] = tok;
154 p->toks[i] = NULL;
157 static void enter_single(void)
159 pid_t pid;
160 char *av[2];
162 err("Booting to single user mode\n");
163 av[0] = _PATH_BSHELL;
164 av[1] = NULL;
165 if((pid = vfork()) == 0) {
166 extern char **environ;
167 /* the child */
168 execve(_PATH_BSHELL, av, environ);
169 err("exec of single user shell failed\n");
170 _exit(0);
171 } else if(pid > 0) {
172 int i;
173 while(wait(&i) != pid) /* nothing */;
174 } else if(pid < 0) {
175 err("fork of single user shell failed\n");
177 unlink(_PATH_SINGLE);
181 #if LINUX_VERSION_CODE < 0x020100
182 static void
183 set_console_baud(int baud)
185 switch (baud) {
186 case 50: console_baud = B50; break;
187 case 75: console_baud = B75; break;
188 case 110: console_baud = B110; break;
189 case 134: console_baud = B134; break;
190 case 150: console_baud = B150; break;
191 case 200: console_baud = B200; break;
192 case 300: console_baud = B300; break;
193 case 600: console_baud = B600; break;
194 case 1200: console_baud = B1200; break;
195 case 1800: console_baud = B1800; break;
196 case 2400: console_baud = B2400; break;
197 case 4800: console_baud = B4800; break;
198 default:
199 case 9600: console_baud = B9600; break;
200 case 19200: console_baud = B19200; break;
201 case 38400: console_baud = B38400; break;
202 case 57600: console_baud = B57600; break;
203 case 115200: console_baud = B115200; break;
204 case 230400: console_baud = B230400; break;
205 case 460800: console_baud = B460800; break;
208 #endif
210 static int do_command(const char *path, const char *filename, int dowait)
212 pid_t pid, wpid;
213 int stat, st;
215 if((pid = vfork()) == 0) {
216 /* the child */
217 char *argv[3];
218 #ifdef INCLUDE_TIMEZONE
219 char tz[BUF_SIZ];
220 #endif
221 char *env[3];
223 /* Use /dev/null for stdin */
224 close(0);
225 open("/dev/null", O_RDONLY);
227 argv[0] = (char *)path;
228 argv[1] = (char *)filename;
229 argv[2] = NULL;
231 env[0] = "PATH=/bin:/usr/bin:/etc:/sbin:/usr/sbin";
232 #ifdef INCLUDE_TIMEZONE
233 strcpy(tz, "TZ=");
234 strcat(tz, tzone);
235 env[1] = tz;
236 env[2] = NULL;
237 #else
238 env[1] = NULL;
239 #endif
241 execve(path, argv, env);
243 err("exec rc failed\n");
244 _exit(2);
245 } else if(pid > 0) {
246 if (!dowait)
247 stat = 0;
248 else {
249 /* parent, wait till rc process dies before spawning */
250 while ((wpid = wait(&stat)) != pid)
251 if (wpid == -1 && errno == ECHILD) { /* see wait(2) manpage */
252 stat = 0;
253 break;
256 } else if(pid < 0) {
257 err("fork of rc shell failed\n");
258 stat = -1;
260 st = WEXITSTATUS(stat);
261 return st;
265 * run /etc/rc. The environment is passed to the script, so the RC environment
266 * variable can be used to decide what to do. RC may be set from LILO.
268 static int do_rc(void)
270 int rc;
272 rc = do_command(_PATH_BSHELL, _PATH_RC, 1);
273 if (rc)
274 return(rc);
275 #ifdef CONFIG_USER_INIT_RUN_FIREWALL
276 rc = do_command(_PATH_FIREWALL, "-i", 1);
277 if (rc)
278 err(_PATH_FIREWALL " failed!");
279 #endif
280 #ifdef CONFIG_USER_FLATFSD_FLATFSD
281 rc = do_command(_PATH_BSHELL, _PATH_CONFIGRC, 1);
282 if (rc)
283 err(_PATH_CONFIGRC " failed!");
284 #endif
285 #ifdef CONFIG_USER_INIT_RUN_FIREWALL
286 rc = do_command(_PATH_FIREWALL, NULL, 0);
287 if (rc)
288 err(_PATH_FIREWALL " failed!");
289 #endif
290 #ifdef INCLUDE_TIMEZONE
291 /* We read the timezone file here, because the flat file system
292 * has probably been created by now.
294 set_tz();
295 #endif
296 return(0);
299 void respawn_children(int signo) {
300 int i, delta = -1;
301 time_t now;
302 alarm(0);
303 if ((now = time(NULL)) == 0) now = 1;
304 for(i = 0; i < numcmd; i++) {
305 if(inittab[i].pid < 0) { /* Start jobs */
306 if(stopped)
307 inittab[i].pid = -1;
309 ** Do not spawn child from signal handler !
310 ** SIGALRM would be blocked for the child
312 else if (signo == 0)
313 spawn(i);
315 /* Check for naughty jobs */
316 if (inittab[i].nextrun > now) {
317 int d;
318 d = inittab[i].nextrun - now;
319 if (delta < 0 || d < delta)
320 delta = d;
323 if (delta > 0) {
324 alarm(delta);
328 int main(int argc, char *argv[])
330 int i;
331 struct sigaction sa;
334 * setup all the signal handlers here
337 memset(&sa, 0, sizeof(sa));
338 /* sa.sa_flags = SA_RESETHAND we want to keep the handlers armed */
340 sa.sa_handler = tstp_handler;
341 sigaction(SIGTSTP, &sa, NULL);
343 sa.sa_handler = cont_handler;
344 sigaction(SIGCONT, &sa, NULL);
346 sa.sa_handler = int_handler;
347 sigaction(SIGINT, &sa, NULL);
349 sa.sa_handler = respawn_children;
350 sigaction(SIGALRM, &sa, NULL);
352 sa.sa_handler = hup_handler;
353 sigaction(SIGHUP, &sa, NULL);
355 #if defined(CONSOLE_BAUD_RATE) && LINUX_VERSION_CODE < 0x020100
356 set_console_baud(CONSOLE_BAUD_RATE);
357 #endif
360 * start up in single user mode if /etc/singleboot exists or if
361 * argv[1] is "single".
363 if(boot_single(0, argc, argv)) enter_single();
365 #ifdef RUN_RC
366 /* Register console if defined by boot */
367 #if LINUX_VERSION_CODE < 0x020100
368 if ((console_device = getenv("CONSOLE"))) {
369 char *sp;
370 unsetenv("CONSOLE");
371 if ((sp = strchr(console_device, ','))) {
372 *sp++ = 0;
373 set_console_baud(atoi(sp));
377 make_ascii_tty();
378 #else
380 struct stat st;
382 if (isatty(1)) {
383 have_console = 1;
384 make_ascii_tty();
385 } else if (fstat(1, &st) == -1 && errno == EBADF) {
386 /* No stdout, so send everything to /dev/null */
387 close(0); close(1); close(2);
388 open("/dev/null", O_RDWR);
389 dup(0);
390 dup(0);
393 #endif
395 /*If we get a SIGTSTP before multi-user mode, do nothing*/
396 while(stopped)
397 pause();
398 if(do_rc() != 0 && boot_single(1, argc, argv) && !stopped)
399 enter_single();
400 while(stopped) /*Also if /etc/rc fails & we get SIGTSTP*/
401 pause();
402 #endif
404 /* initialize the array of commands */
405 inittab = (struct initline *)malloc(NUMCMD * sizeof(struct initline));
406 inittab_size = NUMCMD;
408 if (!inittab) {
409 /* failure case - what do you do if init fails? */
410 err("malloc failed");
411 _exit(1);
414 write_wtmp(); /* write boottime record */
415 read_inittab();
417 #ifdef DEBUGGING
418 for(i = 0; i < numcmd; i++) {
419 char **p = inittab[i].toks;
420 printf("toks= %s %s %s %s\n",p[0], p[1], p[2], p[3]);
421 printf("tty= %s\n", inittab[i].tty);
422 printf("termcap= %s\n", inittab[i].termcap);
424 /*exit(0);*/
425 #endif
427 #if LINUX_VERSION_CODE < 0x020100
428 for(i = 0; i < getdtablesize(); i++) close(i);
429 #else
430 /* Always leave 0, 1, and 2 connected (to /dev/null) for the child process */
431 for(i = 3; i < getdtablesize(); i++) close(i);
432 #endif
434 for (;;) {
435 pid_t pid;
436 int vec;
438 if (run_sigint_processing) {
439 run_sigint_processing = 0;
440 sigint_processing();
443 respawn_children(0);
445 if (reload) {
446 reload = 0;
447 reload_inittab();
448 continue; /* process all reloads before waiting */
451 pid = wait(&vec);
452 alarm(0);
454 /* clear utmp entry, and append to wtmp if possible */
455 #if 0 /* DAVIDM */
457 struct utmp *ut;
458 int ut_fd;
460 utmpname(_PATH_UTMP);
461 setutent();
462 while((ut = getutent())) {
463 if(ut->ut_pid == pid) {
464 time(&ut->ut_time);
465 bzero(&ut->ut_user, UT_NAMESIZE);
466 bzero(&ut->ut_host, sizeof(ut->ut_host));
467 ut->ut_type = DEAD_PROCESS;
468 ut->ut_pid = 0;
469 ut->ut_addr = 0;
470 endutent();
471 pututline(ut);
472 if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
473 flock(ut_fd, LOCK_EX|LOCK_NB);
474 write(ut_fd, (const void *)ut, sizeof(struct utmp));
475 flock(ut_fd, LOCK_UN|LOCK_NB);
476 close(ut_fd);
478 break;
481 endutent();
483 #endif
485 for(i = 0; i < numcmd; i++) {
486 if(pid == inittab[i].pid) {
487 inittab[i].pid = -1;
495 * return true if we should boot up in singleuser mode. If argv[i] is
496 * "single" or the file /etc/singleboot exists, then singleuser mode should
497 * be entered. If /etc/securesingle exists ask for root password first.
499 int boot_single(int singlearg, int argc, char *argv[])
501 char *pass, *rootpass = NULL;
502 struct passwd *pwd;
503 int i;
505 for(i = 1; i < argc; i++) {
506 if(argv[i] && !strcmp(argv[i], "single")) singlearg = 1;
508 return 0;
511 void spawn(int i)
513 pid_t pid;
514 int j;
515 time_t t;
516 struct initline *it;
517 char buf[150];
519 it = inittab + i;
521 t = time(NULL);
522 /* Check for held process */
523 if ((unsigned long)(it->nextrun - t - 1) < maxdelay)
524 return;
525 if (it->lastrun + testtime > t) { /* Respawning quickly */
526 if (it->xcnt < 0xff)
527 it->xcnt++;
528 } else { /* Normal respawning */
529 it->xcnt = 0;
530 it->lastrun = t;
531 it->delay = delaytime;
533 if (it->xcnt >= maxspawn) { /* Too many too quickly */
534 strcpy(buf, it->toks[0]);
535 strcat(buf, " respawning too fast\n");
536 err(buf);
537 it->pid = -1;
538 if (it->delay >= maxdelay)
539 it->delay = maxdelay;
540 else if (it->delay < delaytime)
541 it->delay = delaytime;
542 else if((it->delay *= 2) > maxdelay)
543 it->delay = maxdelay;
544 it->nextrun = t + it->delay;
545 /* Fiddle with the tracking vars to ensure that only
546 * one attempt is made to run this next time around.
548 it->lastrun = it->nextrun;
549 it->xcnt -= 2;
550 return;
552 it->nextrun = t + delaytime;
554 if((pid = vfork()) < 0) {
555 it->pid = -1;
556 err("fork failed\n");
557 return;
559 if(pid) {
560 /* this is the parent */
561 it->pid = pid;
562 return;
563 } else {
564 /* this is the child */
565 char term[40];
566 char *prog;
567 #ifdef INCLUDE_TIMEZONE
568 char tz[BUF_SIZ];
569 #endif
570 char *env[4];
572 setsid();
574 /* Close everything other than 0, 1 and 2 */
575 for(j = 3; j < getdtablesize(); j++) {
576 close(j);
578 /* Now set up 0, 1 and 2 */
579 make_console(it->tty);
581 strcpy(term, "TERM=");
582 strcat(term, it->termcap);
583 env[0] = term;
584 env[1] = "PATH=/bin:/usr/bin:/etc:/sbin:/usr/sbin";
585 #ifdef INCLUDE_TIMEZONE
586 strcpy(tz, "TZ=");
587 strcat(tz, tzone);
588 env[2] = tz;
589 env[3] = NULL;
590 #else
591 env[2] = NULL;
592 #endif
594 prog = it->toks[0];
595 if (*prog == '-' && *(prog+1))
596 prog++;
597 execve(prog, it->toks, env);
598 strcpy(buf, it->toks[0]);
599 strcat(buf, " exec failed\n");
600 err(buf);
601 _exit(1);
605 static void init_itab(struct initline *p) {
606 bzero(p, sizeof(struct initline));
607 p->pid = -1;
608 p->nextrun = time(NULL);
611 static void clear_itab(struct initline *p) {
612 if (p->line)
613 free(p->line);
614 if (p->fullline)
615 free(p->fullline);
616 if (p->toks)
617 free(p->toks);
618 init_itab(p);
621 void read_inittab(void)
623 int i;
626 * free any old data and start again
628 for (i = 0; i < numcmd; i++)
629 clear_itab(&inittab[i]);
630 numcmd = 0;
632 /* Fake an inittab entry if boot console defined */
633 #ifdef CONFIG_USER_INIT_CONSOLE_SH
634 #if LINUX_VERSION_CODE < 0x020100
635 if (console_device && strcmp(console_device, "/dev/null"))
636 #else
637 if (have_console)
638 #endif
640 struct initline *p;
641 p = inittab + numcmd++;
642 init_itab(p);
643 p->fullline = strdup("console");
644 strcpy(p->tty, "console");
645 strcpy(p->termcap, "linux");
646 add_tok(p, "-/bin/sh");
648 #endif
650 i = 0;
651 if (read_initfile(_PATH_INITTAB) == 0)
652 i++;
654 #ifdef CONFIG_USER_FLATFSD_FLATFSD
655 if (read_initfile(_PATH_CONFIGTAB) == 0)
656 i++;
657 #endif
659 if (i == 0) {
660 err("Failed to open " _PATH_INITTAB
661 #ifdef CONFIG_USER_FLATFSD_FLATFSD
662 " or " _PATH_CONFIGTAB
663 #endif
668 #ifdef CONFIG_USER_INIT_CONF
669 load_init_conf();
670 #endif
672 /* if needed, shrink the array using realloc -
673 * must be done here so that we include the results of all init files
674 * when calculating number of commands */
675 if ((numcmd + 2) < (inittab_size - NUMCMD)) {
676 /* round up from numcmd to the nearest multiple of NUMCMD */
677 inittab_size = ((numcmd + 2) / NUMCMD + 1) * NUMCMD;
678 inittab = realloc(inittab, inittab_size * sizeof(struct initline));
679 if (!inittab) {
680 /* failure case - what do you do if init fails? */
681 err("malloc failed");
682 _exit(1);
686 if (numcmd == 0)
687 _exit(1);
690 static int
691 read_initfile(const char *initfile)
693 struct initline *p;
694 FILE *f;
695 char *buf = NULL;
696 size_t buf_len = 0;
697 int i,j,k;
698 char *ptr, *getty;
699 #ifdef SPECIAL_CONSOLE_TERM
700 char tty[50];
701 struct stat stb;
702 char *termenv;
704 termenv = getenv("TERM"); /* set by kernel */
705 #endif
707 i = numcmd;
709 if (!(f = fopen(initfile, "r")))
710 return 1;
712 while(!feof(f)) {
713 if (i+2 == inittab_size) {
714 /* need to realloc inittab */
715 inittab_size += NUMCMD;
716 inittab = realloc(inittab, inittab_size * sizeof(struct initline));
717 if (!inittab) {
718 /* failure case - what do you do if init fails? */
719 err("malloc failed");
720 _exit(1);
723 if (getline(&buf, &buf_len, f) == -1) break;
725 for(k = 0; k < buf_len && buf[k]; k++) {
726 if(buf[k] == '#') {
727 buf[k] = '\0'; break;
731 if(buf[0] == '\0' || buf[0] == '\n') continue;
733 p = inittab + i;
734 init_itab(p);
735 p->line = strdup(buf);
736 p->fullline = strdup(buf);
737 if (!p->line || !p->fullline) {
738 err("Not memory to allocate inittab entry");
739 clear_itab(p);
740 continue;
742 ptr = strtok(p->line, ":");
743 if (!ptr) {
744 err("Missing TTY/ID field in inittab");
745 clear_itab(p);
746 continue;
748 strncpy(p->tty, ptr, 9);
749 //p->tty[9] = '\0';
750 ptr = strtok(NULL, ":");
751 if (!ptr) {
752 err("Missing TERMTYPE field in inittab");
753 clear_itab(p);
754 continue;
756 strncpy(p->termcap, ptr, 29);
757 //p->termcap[29] = '\0';
759 getty = strtok(NULL, " \t\n");
760 if (!getty) {
761 err("Missing PROCESS field in inittab");
762 clear_itab(p);
763 continue;
765 add_tok(p, getty);
766 j = 1;
767 while((ptr = strtok(NULL, " \t\n")))
768 add_tok(p, ptr);
770 #ifdef SPECIAL_CONSOLE_TERM
771 /* special-case termcap for the console ttys */
772 strcpy(tty, "/dev/");
773 strcat(tty, p->tty);
774 if(!termenv || stat(tty, &stb) < 0) {
775 err("no TERM or cannot stat tty\n");
776 } else {
777 /* is it a console tty? */
778 if(major(stb.st_rdev) == 4 && minor(stb.st_rdev) < 64) {
779 strncpy(p->termcap, termenv, 30);
780 p->termcap[29] = 0;
783 #endif
785 i++;
788 if (buf)
789 free(buf);
791 fclose(f);
793 numcmd = i;
794 return 0;
797 void hup_handler()
799 reload = 1;
802 void reload_inittab()
804 int i;
805 int oldnum;
806 char ** saveline = (char **) malloc(inittab_size * sizeof(char *));
807 pid_t * savepid = (pid_t*) malloc(inittab_size * sizeof(pid_t));
809 if (!saveline || !savepid) {
810 /* another failure case - what DO you do if init fails */
811 err("malloc failed");
812 _exit(1);
815 for (i=0; i<numcmd; i++) {
816 savepid[i] = inittab[i].pid;
817 saveline[i] = strdup(inittab[i].fullline);
818 if (!saveline[i]) {
819 err("malloc failed");
820 _exit(1);
824 oldnum = numcmd;
825 read_inittab();
827 /* See which ones still exist */
828 for(i = 0; i < numcmd; i++) {
829 int j;
830 for(j = 0; j < oldnum; j++) {
831 if(strcmp(saveline[j], inittab[i].fullline) == 0) {
832 inittab[i].pid = savepid[j];
833 savepid[j] = -1;
834 break;
839 /* Kill off processes no longer needed and free memory */
840 for(i = 0; i < oldnum; i++) {
841 if (savepid[i] > 1)
842 kill(savepid[i], SIGTERM);
843 free(saveline[i]);
846 free(saveline);
847 free(savepid);
850 void tstp_handler()
852 stopped++;
855 void cont_handler()
857 stopped = 0;
860 void int_handler()
862 run_sigint_processing = 1;
865 void sigint_processing()
868 * After Linux 0.96b PL1, we get a SIGINT when
869 * the user presses Ctrl-Alt-Del...
872 int pid;
874 sync();
875 sync();
876 if((pid = vfork()) == 0) {
877 char *av[2];
878 extern char **environ;
879 /* reboot properly... */
880 av[0] = _PATH_REBOOT;
881 av[1] = NULL;
883 execve(_PATH_REBOOT, av, environ);
884 #if __GNU_LIBRARY__ > 5
885 reboot(0x1234567);
886 #else
887 reboot(0xfee1dead, 672274793, 0x1234567);
888 #endif
889 _exit(2);
890 } else if(pid < 0) {
891 /* fork failed, try the hard way... */
892 #if __GNU_LIBRARY__ > 5
893 reboot(0x1234567);
894 #else
895 reboot(0xfee1dead, 672274793, 0x1234567);
896 #endif
900 #ifdef INCLUDE_TIMEZONE
901 void set_tz(void)
903 FILE *f;
904 int len;
906 if((f = fopen("/etc/config/TZ", "r")) == NULL &&
907 (f = fopen("/etc/TZ", "r")) == NULL)
908 return;
909 fgets(tzone, BUF_SIZ-2, f);
910 fclose(f);
911 if((len=strlen(tzone)) < 2)
912 return;
913 tzone[len-1] = 0; /* get rid of the '\n' */
914 setenv("TZ", tzone, 0);
916 #endif
918 #ifdef CONFIG_USER_INIT_CONF
919 void load_init_conf(void)
921 char line[BUF_SIZ];
922 FILE *f;
924 if ((f = fopen("/etc/config/init.conf", "r")) == NULL &&
925 (f = fopen("/etc/init.conf", "r")) == NULL)
926 return;
927 while (fgets(line, sizeof(line) - 2, f)) {
928 if (strncasecmp(line, "delaytime=", 10) == 0)
929 delaytime = atoi(line + 10);
930 if (strncasecmp(line, "maxdelay=", 9) == 0)
931 maxdelay = atoi(line + 9);
932 if (strncasecmp(line, "maxspawn=", 9) == 0)
933 maxspawn = atoi(line + 9);
934 if (strncasecmp(line, "testtime=", 9) == 0)
935 testtime = atoi(line + 9);
937 fclose(f);
939 #endif
941 void write_wtmp(void)
943 #if 0
944 int fd;
945 struct utmp ut;
947 bzero((char *)&ut, sizeof(ut));
948 strcpy(ut.ut_line, "~");
949 bzero(ut.ut_name, sizeof(ut.ut_name));
950 time(&ut.ut_time);
951 ut.ut_type = BOOT_TIME;
953 if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND)) >= 0) {
954 flock(fd, LOCK_EX|LOCK_NB); /* make sure init won't hang */
955 write(fd, (char *)&ut, sizeof(ut));
956 flock(fd, LOCK_UN|LOCK_NB);
957 close(fd);
959 #endif
962 void make_ascii_tty(void)
964 struct termios tty;
965 const char *pt;
967 if (tcgetattr(0, &tty) < 0)
968 return;
970 tty.c_iflag &= ~(INLCR|IGNCR|IUCLC);
971 tty.c_iflag |= ICRNL;
972 tty.c_oflag &= ~(OCRNL|OLCUC|ONOCR|ONLRET|OFILL);
973 tty.c_oflag |= OPOST|ONLCR;
974 tty.c_cflag |= CLOCAL;
975 tty.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE;
976 #ifdef IEXTEN
977 tty.c_lflag |= IEXTEN;
978 #endif
980 #if LINUX_VERSION_CODE < 0x020100
981 if (console_baud != -1)
982 cfsetospeed(&tty, console_baud);
983 #endif
985 tty.c_cc[VINTR] = CTRL('C');
986 tty.c_cc[VQUIT] = CTRL('\\');
987 tty.c_cc[VERASE] = CTRL('H'); /*127*/
988 tty.c_cc[VKILL] = CTRL('U'); /*Changed from non-standard ^X*/
989 tty.c_cc[VEOF] = CTRL('D');
990 tty.c_cc[VTIME] = 0;
991 tty.c_cc[VMIN] = 1;
992 tty.c_cc[VSTART] = CTRL('Q');
993 tty.c_cc[VSTOP] = CTRL('S');
994 tty.c_cc[VSUSP] = CTRL('Z');
995 #ifdef VWERASE
996 tty.c_cc[VWERASE] = CTRL('W');
997 #endif
998 /* Pick up simple environment setting of VERASE.
999 * Useful for setting on kernel command line.
1000 * e.g. TTYERASE=^?
1002 pt = getenv("TTYERASE");
1003 if (pt && pt[0] == '^' && pt[1]) {
1004 tty.c_cc[VERASE] = (pt[1] == '?') ? 127 : CTRL(pt[1]);
1007 tcsetattr(0, TCSANOW, &tty);
1010 void make_console(const char *tty)
1012 char devname[32];
1014 close(0); close(1); close(2);
1016 if (tty && *tty) {
1017 #if LINUX_VERSION_CODE < 0x020100
1019 * until we get proper console support under 2.0
1021 if (strcmp(tty, "console") == 0) {
1022 strcpy(devname, console_device);
1024 else
1025 #endif
1027 strcpy(devname, "/dev/");
1028 strcat(devname, tty);
1031 /* Try to open the specified console */
1032 if (open(devname, O_RDWR|O_NONBLOCK) >= 0) {
1033 fcntl(0, F_SETFL, 0);
1034 dup(0);
1035 dup(0);
1036 make_ascii_tty();
1037 ioctl(0, TIOCSCTTY, (char*)0);
1038 return;
1042 /* No go, so send to /dev/null */
1043 open("/dev/null", O_RDWR|O_NONBLOCK);
1044 dup(0);
1045 dup(0);