* Copyright (c) 1986, 1987, 1992 Daniel D. Lanciani.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by
* 4. The name of the author may not
* be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY Daniel D. Lanciani ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Daniel D. Lanciani BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 5 00076
* -------------------- ----- ----------------------
* 15 Aug 92 David Dawes SIGTERM + 10 seconds before SIGKILL
* 24 Jul 92 Nate Williams Fixed utmp removal, wtmp info
* 31 Jul 92 Christoph Robitschko Fixed run level change code
* 04 Sep 92 Paul Kranenburg Fixed kill -1 and kill -15 for
* daemons started from /etc/rc.
* 26 Jan 93 Nate Williams Fixed patchkit error
#define NTTY 32 /* max ttys */
#define NARG 16 /* max args to login/getty */
/* non-standard tty_logout: rerun login/getty with -o switch to clean line */
#define TTY_LOGOUT 0x1000
/* non-standard tty_open: open device for login/getty */
#define isspace(c) ((c) == ' ' || (c) == '\t')
} ttytab
[NTTY
], *ttytabend
= ttytab
;
char arg
[128], nam
[64], term
[64], *env
[] = { term
, 0 };
char *Reboot
= "autoboot";
char *newstring(), *malloc();
/* signal state of child process */
#define SIGNALSFORCHILD \
signal(SIGHUP, SIG_DFL); signal(SIGINT, SIG_DFL); \
signal(SIGTERM, SIG_DFL); signal(SIGALRM, SIG_DFL); \
signal(SIGTSTP, SIG_DFL); signal(SIGCHLD, SIG_DFL); \
signal(SIGTTIN, SIG_DFL); signal(SIGTTOU, SIG_DFL); \
sigsetmask( 0); /* 04 Sep 92*/
/* SIGHUP: reread /etc/ttys */
/* SIGALRM: abort wait and go single user */
signal(SIGALRM
, SIG_DFL
);
/* SIGTERM: go single user */
register struct ttytab
*tt
;
for(tt
= ttytab
; tt
< ttytabend
; tt
++) {
/* give processes time to exit cleanly */ /* 15 Aug 92*/
while(wait((int *)0) > 0);
signal(SIGALRM
, SIG_DFL
);
/* SIGTSTP: drain system */
register struct ttytab
*tt
;
long mask
= sigblock(sigmask(SIGHUP
) | sigmask(SIGTERM
));
/* did some idiot try to run us? */
writes(2,"init: sorry, system daemon, runnable only by system\n");
/* allocate a session for init */
/* protect against signals, listen for outside requests */
signal (SIGTTIN
, SIG_IGN
);
signal (SIGTTOU
, SIG_IGN
);
signal (SIGCHLD
, SIG_IGN
);
signal (SIGINT
, SIG_IGN
);
/* handle arguments, if any */
if(!strcmp(argv
[1], "-s"))
else if(!strcmp(argv
[1], "-f"))
/* otherwise, execute /etc/rc */
if (access("/etc/rc", F_OK
) == 0) {
signal(SIGTERM
, SIG_IGN
); /* XXX */
/* signals, to default state */
login_tty(open("/dev/console", 2));
execl("/bin/sh", "sh", "/etc/rc", Reboot
, (char *)0);
Reboot
= 0; /* 31 Jul 92*/
while(wait(&status
) != pid
);
/* if we are about to be rebooted, then wait for it */
if (WIFSIGNALED(status
) && WTERMSIG(status
) == SIGKILL
)
logwtmp("~", "reboot", "");
} else { status
= 1; sflag
= 1; goto top
; }
/* do single user shell on console */
if (setjmp(single
) || status
) {
/* signals, to default state */
/* do open and configuration of console */
login_tty(open("/dev/console", 2));
execl("/bin/sh", "-", (char *)0);
while(wait(&status
) != pid
);
while(drain
) /* 31 Jul 92*/
/* multiuser mode, traipse through table */
for(tt
= ttytab
; (ty
= getttyent()) && tt
< &ttytab
[NTTY
]; tt
++) {
tt
->tt_name
= newstring(ty
->ty_name
);
tt
->tt_getty
= newstring(ty
->ty_getty
);
tt
->tt_type
= newstring(ty
->ty_type
);
tt
->tt_status
= ty
->ty_status
;
for(tt
= ttytab
; tt
< ttytabend
; getty(tt
++));
/* if we receive a request to reread the table, come here */
/* first pass. find and clean the entries that have changed */
while(ty
= getttyent()) {
for(tt
= ttytab
; tt
< ttytabend
; tt
++)
if(!strcmp(tt
->tt_name
, ty
->ty_name
)) {
/* if a process present, mark */
if((tt
->tt_status
& ~TTY_LOGIN
) !=ty
->ty_status
)
tt
->tt_status
= ty
->ty_status
|TTY_DIFF
;
if(strcmp(tt
->tt_getty
, ty
->ty_getty
)) {
tt
->tt_getty
= newstring(ty
->ty_getty
);
tt
->tt_status
|= TTY_DIFF
;
if(strcmp(tt
->tt_type
, ty
->ty_type
)) {
tt
->tt_type
= newstring(ty
->ty_type
);
tt
->tt_status
|= TTY_DIFF
;
if(((tt
->tt_status
|= TTY_SEEN
) & TTY_DIFF
)
if(tt
== ttytabend
&& tt
< &ttytab
[NTTY
]) {
tt
->tt_name
= newstring(ty
->ty_name
);
tt
->tt_getty
= newstring(ty
->ty_getty
);
tt
->tt_type
= newstring(ty
->ty_type
);
tt
->tt_status
= ty
->ty_status
|
/* second pass. offer gettys on previously cleaned entries,
and garbage collect "dead" entries */
for(tt
= ttytab
; tt
< ttytabend
; tt
++)
if(tt
->tt_status
& TTY_SEEN
) {
tt
->tt_status
&= ~TTY_SEEN
;
if(tt
->tt_status
& TTY_DIFF
) {
tt
->tt_status
&= ~TTY_DIFF
;
for(tt
++; tt
< ttytabend
; tt
++)
/* listen for terminating gettys and sessions, and process them */
sigblock(sigmask(SIGHUP
) | sigmask(SIGTERM
));
for(tt
= ttytab
; tt
< ttytabend
; tt
++)
/* 24 Jul 92*/ if (logout(tt
->tt_name
)) logwtmp(tt
->tt_name
,"","");
if(drain
&& !(tt
->tt_status
& TTY_LOGIN
)) {
for(tt
++; tt
< ttytabend
; tt
++)
/* process a getty for a "line". N.B. by having getty do open, init
is not limited by filedescriptors for number of possible users */
register char *p
= arg
, **sp
= sargv
;
if(!(tt
->tt_status
& TTY_ON
)) {
if((tt
->tt_pid
= fork()) < 0)
if(tt
->tt_status
& TTY_LOGOUT
)
tt
->tt_status
^= TTY_LOGIN
;
signal(SIGTERM
, SIG_DFL
);
signal(SIGTSTP
, SIG_DFL
);
while(sp
< &sargv
[NARG
- 2]) {
while(!isspace(*p
) && *p
)
strcpy(nam
, tt
->tt_name
);
strcat(term
, tt
->tt_type
);
if(!(n
= malloc(strlen(s
) + 1)))
fd
= open("/dev/console", 2);
writes(fd
, "init WARNING: ");
login_tty(open("/dev/console", 2));
writes(2, "init FATAL error: ");