* Copyright (c) 1980,1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)init.c 5.9 (Berkeley) %G%";
#define LINSIZ sizeof(wtmp.ut_line)
#define CMDSIZ 200 /* max string length for getty or window command*/
#define ALL p = itab; p ; p = p->next
#define SCPYN(a, b) strncpy(a, b, sizeof(a))
#define SCMPN(a, b) strncmp(a, b, sizeof(a))
char shell
[] = "/bin/sh";
char utmpf
[] = "/etc/utmp";
char wtmpf
[] = "/usr/adm/wtmp";
char ctty
[] = "/dev/console";
int wpid
; /* window system pid for SIGHUP */
char wcmd
[CMDSIZ
]; /* command to start window system process */
char *strcpy(), *strcat();
struct sigvec rvec
= { reset
, sigmask(SIGHUP
), 0 };
#if defined(vax) || defined(tahoe)
register int r12
; /* make sure r11 gets bootflags */
register int r11
; /* passed thru from boot */
#if defined(vax) || defined(tahoe)
if (argc
> 1 && argv
[1][0] == '-') {
while (*cp
) switch (*cp
++) {
openlog("init", LOG_CONS
|LOG_ODELAY
, LOG_AUTH
);
sigvec(SIGTERM
, &rvec
, (struct sigvec
*)0);
signal(SIGSTOP
, SIG_IGN
);
signal(SIGTTIN
, SIG_IGN
);
signal(SIGTTOU
, SIG_IGN
);
if (setjmp(shutpass
) == 0)
if (oldhowto
& RB_SINGLE
)
if (runcom(oldhowto
) == 0)
register struct tab
*p
, *p1
;
close(creat(utmpf
, 0644));
signal(SIGALRM
, shutreset
);
(void) kill(-1, SIGTERM
); /* one chance to catch it */
while (wait((int *)0) != -1)
char shutfailm
[] = "WARNING: Something is hung (won't die); ps axl advised\n";
write(ct
, shutfailm
, sizeof (shutfailm
));
signal(SIGALRM
, SIG_DFL
);
f
= open(wtmpf
, O_WRONLY
|O_APPEND
);
SCPYN(wtmp
.ut_line
, "~");
SCPYN(wtmp
.ut_name
, "shutdown");
write(f
, (char *)&wtmp
, sizeof(wtmp
));
signal(SIGTERM
, SIG_DFL
);
signal(SIGALRM
, SIG_DFL
);
signal(SIGTSTP
, SIG_IGN
);
(void) open(ctty
, O_RDWR
);
execl(shell
, minus
, (char *)0);
while ((xpid
= wait((int *)0)) != pid
)
if (xpid
== -1 && errno
== ECHILD
)
(void) open("/", O_RDONLY
);
if (oldhowto
& RB_SINGLE
)
execl(shell
, shell
, runc
, (char *)0);
execl(shell
, shell
, runc
, "autoboot", (char *)0);
while (wait(&status
) != pid
)
f
= open(wtmpf
, O_WRONLY
|O_APPEND
);
SCPYN(wtmp
.ut_line
, "~");
SCPYN(wtmp
.ut_name
, "reboot");
write(f
, (char *)&wtmp
, sizeof(wtmp
));
struct sigvec mvec
= { merge
, sigmask(SIGTERM
), 0 };
* Multi-user. Listen for users leaving, SIGHUP's
* which indicate ttys has changed, and SIGTERM's which
* are used to shutdown the system.
sigvec(SIGHUP
, &mvec
, (struct sigvec
*)0);
omask
= sigblock(sigmask(SIGHUP
));
/* must restart window system BEFORE emulator */
if (p
->wpid
== pid
|| p
->wpid
== -1)
if (p
->pid
== pid
|| p
->pid
== -1) {
/* disown the window system */
* Merge current contents of ttys file
* into in-core table of configured tty lines.
* Entered as signal handler for SIGHUP.
register struct ttyent
*t
;
while (t
= getttyent()) {
if ((t
->ty_status
& TTY_ON
) == 0)
if (SCMPN(p
->line
, t
->ty_name
))
if (SCMPN(p
->comn
, t
->ty_getty
)) {
SCPYN(p
->comn
, t
->ty_getty
);
if (SCMPN(p
->wcmd
, t
->ty_window
? t
->ty_window
: "")) {
p
->xflag
|= WCHANGE
|CHANGE
;
SCPYN(p
->wcmd
, t
->ty_window
);
* Make space for a new one
p1
= (struct tab
*)calloc(1, sizeof(*p1
));
syslog(LOG_ERR
, "no space for '%s' !?!", t
->ty_name
);
* Put new terminal at the end of the linked list.
for (p
= itab
; p
->next
; p
= p
->next
)
SCPYN(p
->line
, t
->ty_name
);
p
->xflag
|= FOUND
|CHANGE
;
SCPYN(p
->comn
, t
->ty_getty
);
if (t
->ty_window
&& strcmp(t
->ty_window
, "") != 0) {
SCPYN(p
->wcmd
, t
->ty_window
);
if ((p
->xflag
&FOUND
) == 0) {
/* window system should be started first */
/* send SIGHUP to get rid of connections */
if ((t
- p
->gettytime
) >= 60) {
} else if (p
->gettycnt
>= 5) {
signal(SIGTERM
, SIG_DFL
);
sigsetmask(0); /* since can be called from masked code */
syslog(LOG_ERR
, "'%s %s' failing, sleeping", p
->comn
, p
->line
);
execit(p
->comn
, p
->line
);
static unsigned utmpsize
;
static struct utmp
*utmp
;
if (utmpsize
< statbf
.st_size
) {
utmpsize
= statbf
.st_size
+ 10 * sizeof(struct utmp
);
utmp
= (struct utmp
*)realloc(utmp
, utmpsize
);
utmp
= (struct utmp
*)malloc(utmpsize
);
syslog(LOG_ERR
, "utmp malloc failed");
if (statbf
.st_size
&& utmp
) {
nutmp
= read(f
, utmp
, statbf
.st_size
);
nutmp
/= sizeof(struct utmp
);
for (u
= utmp
; u
< &utmp
[nutmp
] ; u
++) {
if (u
->ut_name
[0] == 0 ||
SCMPN(u
->ut_line
, p
->line
))
lseek(f
, ((long)u
)-((long)utmp
), L_SET
);
write(f
, (char *)u
, sizeof(*u
));
f
= open(wtmpf
, O_WRONLY
|O_APPEND
);
SCPYN(wtmp
.ut_line
, p
->line
);
write(f
, (char *)&wtmp
, sizeof(wtmp
));
* After a proper login force reset
* of error detection code in dfork.
/* if window system dies, mark it for restart */
if ((t
- p
->windtime
) >= 60) {
} else if (p
->windcnt
>= 5) {
signal(SIGTERM
, SIG_DFL
);
sigsetmask(0); /* since can be called from masked code */
syslog(LOG_ERR
, "'%s %s' failing, sleeping", p
->wcmd
, p
->line
);
execit(p
->wcmd
, p
->line
);
#define NARGS 20 /* must be at least 4 */
#define ARGLEN 512 /* total size for all the argument strings */
char *arg
; /* last argument on line */
char *argv
[NARGS
], args
[ARGLEN
], *envp
[1];
register char *ap
= args
;
* First we have to set up the argument vector.
* "prog arg1 arg2" maps to exec("prog", "-", "arg1", "arg2").
for (i
= 1; i
< NARGS
- 2; i
++) {
if ((c
= *sp
++) == '\0' || ap
>= &args
[ARGLEN
-1]) {
execve(argv
[0], &argv
[1], envp
);
/* report failure of exec */
syslog(LOG_ERR
, "%s: %m", argv
[0]);
sleep(10); /* prevent failures from eating machine */