]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - login-utils/simpleinit.c
1 /* simpleinit.c - poe@daimi.aau.dk */
16 #include <sys/sysmacros.h>
22 #include "pathnames.h"
24 #define CMDSIZ 150 /* max size of a line in inittab */
25 #define NUMCMD 30 /* max number of lines in inittab */
26 #define NUMTOK 20 /* max number of tokens in inittab command */
29 #define TZFILE "/etc/TZ"
31 /* #define DEBUGGING */
33 /* Define this if you want init to ignore the termcap field in inittab for
35 /* #define SPECIAL_CONSOLE_TERM */
47 struct initline inittab
[NUMCMD
];
49 int stopped
= 0; /* are we stopped */
52 void spawn(), hup_handler(), read_inittab();
53 void tstp_handler(), int_handler(), set_tz(), write_wtmp();
60 if((fd
= open("/dev/console", O_WRONLY
)) < 0) return;
62 write(fd
, "init: ", 6);
63 write(fd
, s
, strlen(s
));
73 err("Booting to single user mode.\n");
74 if((pid
= fork()) == 0) {
76 execl(_PATH_BSHELL
, _PATH_BSHELL
, NULL
);
77 err("exec of single user shell failed\n");
79 while(wait(&i
) != pid
) /* nothing */;
81 err("fork of single user shell failed\n");
86 int main(int argc
, char *argv
[])
94 signal(SIGTSTP
, tstp_handler
);
95 signal(SIGINT
, int_handler
);
98 * start up in single user mode if /etc/singleboot exists or if
99 * argv[1] is "single".
101 if(boot_single(0, argc
, argv
)) enter_single();
104 /*If we get a SIGTSTP before multi-user mode, do nothing*/
107 if(do_rc() != 0 && boot_single(1, argc
, argv
) && !stopped
)
109 while(stopped
) /*Also if /etc/rc fails & we get SIGTSTP*/
113 write_wtmp(); /* write boottime record */
115 for(i
= 0; i
< NUMCMD
; i
++)
121 for(i
= 0; i
< numcmd
; i
++) {
124 printf("toks= %s %s %s %s\n",p
[0], p
[1], p
[2], p
[3]);
125 printf("tty= %s\n", inittab
[i
].tty
);
126 printf("termcap= %s\n", inittab
[i
].termcap
);
130 signal(SIGHUP
, hup_handler
);
132 for(i
= 0; i
< getdtablesize(); i
++) close(i
);
134 for(i
= 0; i
< numcmd
; i
++)
140 /* clear utmp entry, and append to wtmp if possible */
145 utmpname(_PATH_UTMP
);
147 while(ut
= getutent()) {
148 if(ut
->ut_pid
== pid
) {
150 memset(&ut
->ut_user
, 0, UT_NAMESIZE
);
151 memset(&ut
->ut_host
, 0, sizeof(ut
->ut_host
));
152 ut
->ut_type
= DEAD_PROCESS
;
157 if((ut_fd
= open(_PATH_WTMP
, O_APPEND
|O_WRONLY
)) >= 0) {
158 flock(ut_fd
, LOCK_EX
|LOCK_NB
);
159 write(ut_fd
, ut
, sizeof(struct utmp
));
160 flock(ut_fd
, LOCK_UN
|LOCK_NB
);
169 for(i
= 0; i
< numcmd
; i
++) {
170 if(pid
== inittab
[i
].pid
|| inittab
[i
].pid
< 0) {
171 if(stopped
) inittab
[i
].pid
= -1;
179 #define MAXTRIES 3 /* number of tries allowed when giving the password */
182 * return true if we should boot up in singleuser mode. If argv[i] is
183 * "single" or the file /etc/singleboot exists, then singleuser mode should
184 * be entered. If /etc/securesingle exists ask for root password first.
186 int boot_single(int singlearg
, int argc
, char *argv
[])
188 char *pass
, *rootpass
= NULL
;
192 for(i
= 1; i
< argc
; i
++) {
193 if(argv
[i
] && !strcmp(argv
[i
], "single")) singlearg
= 1;
196 if(access(_PATH_SINGLE
, 04) == 0 || singlearg
) {
197 if(access(_PATH_SECURE
, 04) == 0) {
198 if((pwd
= getpwnam("root")) || (pwd
= getpwuid(0)))
199 rootpass
= pwd
->pw_passwd
;
201 return 1; /* a bad /etc/passwd should not lock out */
203 for(i
= 0; i
< MAXTRIES
; i
++) {
204 pass
= getpass("Password: ");
205 if(pass
== NULL
) continue;
207 if(!strcmp(crypt(pass
, rootpass
), rootpass
)) {
211 puts("\nWrong password.\n");
219 * run /etc/rc. The environment is passed to the script, so the RC environment
220 * variable can be used to decide what to do. RC may be set from LILO.
227 if((pid
= fork()) == 0) {
231 argv
[0] = _PATH_BSHELL
;
235 if(open(_PATH_RC
, O_RDONLY
, 0) == 0) {
236 execv(_PATH_BSHELL
, argv
);
237 err("exec rc failed\n");
240 err("open of rc file failed\n");
243 /* parent, wait till rc process dies before spawning */
244 while(wait(&stat
) != pid
) /* nothing */;
246 err("fork of rc shell failed\n");
248 return WEXITSTATUS(stat
);
256 if((pid
= fork()) < 0) {
258 err("fork failed\n");
262 /* this is the parent */
263 inittab
[i
].pid
= pid
;
266 /* this is the child */
272 for(j
= 0; j
< getdtablesize(); j
++)
275 (void) sprintf(term
, "TERM=%s", inittab
[i
].termcap
);
279 (void) sprintf(tz
, "TZ=%s", tzone
);
284 execve(inittab
[i
].toks
[0], inittab
[i
].toks
, env
);
285 err("exec failed\n");
299 char *termenv
, *getenv();
301 termenv
= getenv("TERM"); /* set by kernel */
302 /* termenv = "vt100"; */
304 if(!(f
= fopen(_PATH_INITTAB
, "r"))) {
305 err("cannot open inittab\n");
310 while(!feof(f
) && i
< NUMCMD
- 2) {
311 if(fgets(buf
, CMDSIZ
- 1, f
) == 0) break;
314 for(k
= 0; k
< CMDSIZ
&& buf
[k
]; k
++) {
320 if(buf
[0] == 0 || buf
[0] == '\n') continue;
322 (void) strcpy(inittab
[i
].line
, buf
);
324 (void) strtok(inittab
[i
].line
, ":");
325 (void) strncpy(inittab
[i
].tty
, inittab
[i
].line
, 10);
326 inittab
[i
].tty
[9] = 0;
327 (void) strncpy(inittab
[i
].termcap
,
328 strtok((char *)0, ":"), 30);
329 inittab
[i
].termcap
[29] = 0;
331 getty
= strtok((char *)0, ":");
332 (void) strtok(getty
, " \t\n");
333 inittab
[i
].toks
[0] = getty
;
335 while(ptr
= strtok((char *)0, " \t\n"))
336 inittab
[i
].toks
[j
++] = ptr
;
337 inittab
[i
].toks
[j
] = (char *)0;
339 #ifdef SPECIAL_CONSOLE_TERM
340 /* special-case termcap for the console ttys */
341 (void) sprintf(tty
, "/dev/%s", inittab
[i
].tty
);
342 if(!termenv
|| stat(tty
, &stb
) < 0) {
343 err("no TERM or cannot stat tty\n");
345 /* is it a console tty? */
346 if(major(stb
.st_rdev
) == 4 && minor(stb
.st_rdev
) < 64) {
347 strncpy(inittab
[i
].termcap
, termenv
, 30);
348 inittab
[i
].termcap
[29] = 0;
363 struct initline savetab
[NUMCMD
];
366 (void) signal(SIGHUP
, SIG_IGN
);
368 memcpy(savetab
, inittab
, NUMCMD
* sizeof(struct initline
));
372 for(i
= 0; i
< numcmd
; i
++) {
374 for(j
= 0; j
< oldnum
; j
++) {
375 if(!strcmp(savetab
[j
].tty
, inittab
[i
].tty
)) {
377 if((inittab
[i
].pid
= savetab
[j
].pid
) < 0)
381 if(!had_already
) spawn(i
);
384 (void) signal(SIGHUP
, hup_handler
);
390 if(!stopped
) hup_handler();
392 signal(SIGTSTP
, tstp_handler
);
398 * After Linux 0.96b PL1, we get a SIGINT when
399 * the user presses Ctrl-Alt-Del...
406 if((pid
= fork()) == 0) {
407 /* reboot properly... */
408 execl(_PATH_REBOOT
, _PATH_REBOOT
, (char *)0);
409 reboot(0xfee1dead, 672274793, 0x1234567);
411 /* fork failed, try the hard way... */
412 reboot(0xfee1dead, 672274793, 0x1234567);
420 if((f
=fopen(TZFILE
, "r")) == (FILE *)NULL
) return;
421 fgets(tzone
, CMDSIZ
-2, f
);
423 if((len
=strlen(tzone
)) < 2) return;
424 tzone
[len
-1] = 0; /* get rid of the '\n' */
425 setenv("TZ", tzone
, 0);
433 memset((char *)&ut
, 0, sizeof(ut
));
434 strcpy(ut
.ut_line
, "~");
435 memset(ut
.ut_name
, 0, sizeof(ut
.ut_name
));
437 ut
.ut_type
= BOOT_TIME
;
439 if((fd
= open(_PATH_WTMP
, O_WRONLY
|O_APPEND
)) >= 0) {
440 flock(fd
, LOCK_EX
|LOCK_NB
); /* make sure init won't hang */
441 write(fd
, (char *)&ut
, sizeof(ut
));
442 flock(fd
, LOCK_UN
|LOCK_NB
);