Init
This commit is contained in:
838
etc/init.c
Normal file
838
etc/init.c
Normal file
@@ -0,0 +1,838 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)init.c 1.1 94/10/31 SMI"; /* from UCB 5.6 5/26/86 */
|
||||
#endif not lint
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <utmp.h>
|
||||
#include <setjmp.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <errno.h>
|
||||
#include <sys/file.h>
|
||||
#include <ttyent.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/label.h>
|
||||
#include <sys/audit.h>
|
||||
#include <pwdadj.h>
|
||||
|
||||
#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 EVER ;;
|
||||
#define SCPYN(a, b) strncpy(a, b, sizeof(a))
|
||||
#define SCMPN(a, b) strncmp(a, b, sizeof(a))
|
||||
|
||||
char shell[] = "/sbin/sh";
|
||||
char singleshell[] = "/single/sh";
|
||||
char oldshell[] = "/bin/sh";
|
||||
char minus[] = "-";
|
||||
char bootc[] = "/etc/rc.boot";
|
||||
char runc[] = "/etc/rc";
|
||||
char utmpf[] = "/etc/utmp";
|
||||
char wtmpf[] = "/var/adm/wtmp";
|
||||
char ctty[] = "/dev/console";
|
||||
char ttys[] = "/etc/ttys";
|
||||
char ttytab[] = "/etc/ttytab";
|
||||
char pwdf[] = "/etc/passwd";
|
||||
char pwaf[] = "/etc/security/passwd.adjunct";
|
||||
|
||||
struct utmp wtmp;
|
||||
struct tab
|
||||
{
|
||||
char line[LINSIZ];
|
||||
char comn[CMDSIZ];
|
||||
char xflag;
|
||||
int pid;
|
||||
int wpid; /* window system pid for SIGHUP */
|
||||
char wcmd[CMDSIZ]; /* command to start window system process */
|
||||
time_t gettytime;
|
||||
int gettycnt;
|
||||
time_t windtime;
|
||||
int windcnt;
|
||||
struct tab *next;
|
||||
} *itab;
|
||||
|
||||
jmp_buf sjbuf, shutpass;
|
||||
time_t time0;
|
||||
|
||||
void runrc();
|
||||
void merge();
|
||||
void reset();
|
||||
void idlehup();
|
||||
void idle();
|
||||
char *strcpy(), *strcat();
|
||||
long lseek();
|
||||
|
||||
struct sigvec rvec = { reset, sigmask(SIGHUP), 0 };
|
||||
|
||||
|
||||
#ifdef vax
|
||||
main()
|
||||
{
|
||||
register int r11; /* passed thru from boot */
|
||||
#else
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
#endif
|
||||
int howto, oldhowto;
|
||||
|
||||
if (getpid() != 1) {
|
||||
fprintf(stderr, "init already running\n");
|
||||
exit(-1);
|
||||
}
|
||||
time0 = time(0);
|
||||
#ifdef vax
|
||||
howto = r11;
|
||||
#else
|
||||
if (argc > 1 && argv[1][0] == '-') {
|
||||
char *cp;
|
||||
|
||||
howto = 0;
|
||||
cp = &argv[1][1];
|
||||
while (*cp) switch (*cp++) {
|
||||
case 'a':
|
||||
howto |= RB_ASKNAME;
|
||||
break;
|
||||
case 's':
|
||||
howto |= RB_SINGLE;
|
||||
break;
|
||||
case 'b':
|
||||
howto |= RB_NOBOOTRC;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
howto = RB_SINGLE;
|
||||
}
|
||||
#endif
|
||||
openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH);
|
||||
sigvec(SIGTERM, &rvec, (struct sigvec *)0);
|
||||
signal(SIGTSTP, idle);
|
||||
signal(SIGSTOP, SIG_IGN);
|
||||
signal(SIGTTIN, SIG_IGN);
|
||||
signal(SIGTTOU, SIG_IGN);
|
||||
(void) setjmp(sjbuf);
|
||||
if ((howto&RB_NOBOOTRC) == 0 && access(bootc, 4) == 0) {
|
||||
howto |= RB_NOBOOTRC;
|
||||
if (bootrc(howto) == 0)
|
||||
/* if rc.boot exits abnormally, stay single-user */
|
||||
howto = RB_SINGLE|RB_NOBOOTRC;
|
||||
}
|
||||
for (EVER) {
|
||||
oldhowto = howto;
|
||||
howto = RB_SINGLE|RB_NOBOOTRC;
|
||||
if (setjmp(shutpass) == 0)
|
||||
shutdown();
|
||||
if (oldhowto & RB_SINGLE)
|
||||
single();
|
||||
if (runcom(oldhowto) == 0)
|
||||
continue;
|
||||
merge();
|
||||
multiple();
|
||||
}
|
||||
}
|
||||
|
||||
void shutreset();
|
||||
|
||||
shutdown()
|
||||
{
|
||||
register i;
|
||||
register struct tab *p, *p1;
|
||||
|
||||
close(creat(utmpf, 0644));
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
for (p = itab; p ; ) {
|
||||
term(p);
|
||||
p1 = p->next;
|
||||
free(p);
|
||||
p = p1;
|
||||
}
|
||||
itab = (struct tab *)0;
|
||||
signal(SIGALRM, shutreset);
|
||||
(void) kill(-1, SIGTERM); /* one chance to catch it */
|
||||
sleep(5);
|
||||
alarm(30);
|
||||
for (i = 0; i < 5; i++)
|
||||
kill(-1, SIGKILL);
|
||||
while (wait((int *)0) != -1)
|
||||
;
|
||||
alarm(0);
|
||||
shutend();
|
||||
}
|
||||
|
||||
char shutfailm[] = "WARNING: Something is hung (won't die); ps axl advised\n";
|
||||
|
||||
void
|
||||
shutreset()
|
||||
{
|
||||
if (fork() == 0) {
|
||||
int ct = open(ctty, 1);
|
||||
write(ct, shutfailm, sizeof (shutfailm));
|
||||
sleep(5);
|
||||
exit(1);
|
||||
}
|
||||
sleep(5);
|
||||
shutend();
|
||||
longjmp(shutpass, 1);
|
||||
}
|
||||
|
||||
shutend()
|
||||
{
|
||||
register i, f;
|
||||
|
||||
acct(0);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
for (i = 0; i < 10; i++)
|
||||
close(i);
|
||||
f = open(wtmpf, O_WRONLY|O_APPEND);
|
||||
if (f >= 0) {
|
||||
SCPYN(wtmp.ut_line, "~");
|
||||
SCPYN(wtmp.ut_name, "shutdown");
|
||||
SCPYN(wtmp.ut_host, "");
|
||||
time(&wtmp.ut_time);
|
||||
write(f, (char *)&wtmp, sizeof(wtmp));
|
||||
close(f);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
bootrc(howto)
|
||||
int howto;
|
||||
{
|
||||
register int pid;
|
||||
int status;
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
getcons(1);
|
||||
if (howto & RB_SINGLE)
|
||||
runrc(bootc, "singleuser");
|
||||
else
|
||||
runrc(bootc, (char *)0);
|
||||
exit(1);
|
||||
}
|
||||
while (wait(&status) != pid)
|
||||
;
|
||||
if (status)
|
||||
return (0);
|
||||
else
|
||||
return (1);
|
||||
}
|
||||
|
||||
single()
|
||||
{
|
||||
register pid;
|
||||
register xpid;
|
||||
extern errno;
|
||||
|
||||
do {
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGHUP, SIG_DFL);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
signal(SIGTTIN, SIG_IGN);
|
||||
signal(SIGTTOU, SIG_IGN);
|
||||
getcons(0);
|
||||
if (checkpass() == 0) {
|
||||
execl(shell, minus, (char *)0);
|
||||
execl(singleshell, minus, (char *)0);
|
||||
execl(oldshell, minus, (char *)0);
|
||||
perror(oldshell);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
while ((xpid = wait((int *)0)) != pid)
|
||||
if (xpid == -1 && errno == ECHILD)
|
||||
break;
|
||||
} while (xpid == -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify user knows root password
|
||||
*/
|
||||
checkpass()
|
||||
{
|
||||
char *pass;
|
||||
char *epass;
|
||||
extern char *rootpass();
|
||||
extern char *getpass();
|
||||
int not_ok = 1;
|
||||
|
||||
if (!isc2secure() && cons_secure())
|
||||
return (0);
|
||||
|
||||
/* Get the root password */
|
||||
epass = rootpass();
|
||||
if (epass == NULL)
|
||||
/* Go ahead if no password */
|
||||
return (0);
|
||||
while (not_ok) {
|
||||
pass = getpass("Password:");
|
||||
if (*pass == '\0')
|
||||
return (1);
|
||||
not_ok = strcmp(_crypt(pass, epass), epass);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
runcom(oldhowto)
|
||||
int oldhowto;
|
||||
{
|
||||
register pid, f;
|
||||
int status;
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
getcons(1);
|
||||
if (oldhowto & RB_SINGLE)
|
||||
runrc(runc, (char *)0);
|
||||
else
|
||||
runrc(runc, "autoboot");
|
||||
exit(1);
|
||||
}
|
||||
while (wait(&status) != pid)
|
||||
;
|
||||
if (status)
|
||||
return (0);
|
||||
f = open(wtmpf, O_WRONLY|O_APPEND);
|
||||
if (f >= 0) {
|
||||
SCPYN(wtmp.ut_line, "~");
|
||||
SCPYN(wtmp.ut_name, "reboot");
|
||||
SCPYN(wtmp.ut_host, "");
|
||||
if (time0) {
|
||||
wtmp.ut_time = time0;
|
||||
time0 = 0;
|
||||
} else
|
||||
time(&wtmp.ut_time);
|
||||
write(f, (char *)&wtmp, sizeof(wtmp));
|
||||
close(f);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
runrc(rcname, arg)
|
||||
char *rcname;
|
||||
char *arg;
|
||||
{
|
||||
kbd_disable();
|
||||
execl(shell, shell, rcname, arg, (char *)0);
|
||||
execl(singleshell, singleshell, rcname, arg, (char *)0);
|
||||
execl(oldshell, oldshell, rcname, arg, (char *)0);
|
||||
}
|
||||
|
||||
struct sigvec mvec = { merge, sigmask(SIGTERM), 0 };
|
||||
/*
|
||||
* Multi-user. Listen for users leaving, SIGHUP's
|
||||
* which indicate ttytab has changed, and SIGTERM's which
|
||||
* are used to shutdown the system.
|
||||
*/
|
||||
multiple()
|
||||
{
|
||||
register struct tab *p;
|
||||
register pid;
|
||||
int omask;
|
||||
|
||||
sigvec(SIGHUP, &mvec, (struct sigvec *)0);
|
||||
for (EVER) {
|
||||
pid = wait((int *)0);
|
||||
if (pid == -1)
|
||||
return;
|
||||
omask = sigblock(SIGHUP);
|
||||
for (ALL) {
|
||||
/* must restart window system BEFORE emulator */
|
||||
if (p->wpid == pid || p->wpid == -1)
|
||||
wstart(p);
|
||||
if (p->pid == pid || p->pid == -1) {
|
||||
/* disown the window system */
|
||||
if (p->wpid)
|
||||
kill(p->wpid, SIGHUP);
|
||||
rmut(p);
|
||||
dfork(p);
|
||||
}
|
||||
}
|
||||
sigsetmask(omask);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Merge current contents of ttytab file
|
||||
* into in-core table of configured tty lines.
|
||||
* Entered as signal handler for SIGHUP.
|
||||
*/
|
||||
#define FOUND 1
|
||||
#define CHANGE 2
|
||||
#define WCHANGE 4
|
||||
|
||||
void
|
||||
merge()
|
||||
{
|
||||
register struct tab *p;
|
||||
register struct ttyent *t;
|
||||
register struct tab *p1;
|
||||
int ttysfd;
|
||||
register FILE *ttysf = NULL;
|
||||
struct stat ttys_stat, ttytab_stat;
|
||||
|
||||
for (ALL)
|
||||
p->xflag = 0;
|
||||
setttyent();
|
||||
if (stat(ttytab, &ttytab_stat) < 0)
|
||||
syslog(LOG_ERR, "%s: %m", ttytab);
|
||||
else {
|
||||
/*
|
||||
* If "/etc/ttys" doesn't exist, or if it is not the same
|
||||
* file as "/etc/ttytab", create it if necessary and put
|
||||
* an old-style "ttys" file into it.
|
||||
*/
|
||||
if (stat(ttys, &ttys_stat) < 0
|
||||
|| ttys_stat.st_dev != ttytab_stat.st_dev
|
||||
|| ttys_stat.st_ino != ttytab_stat.st_ino) {
|
||||
if ((ttysfd = open(ttys, O_WRONLY|O_CREAT|O_TRUNC, 0444)) < 0)
|
||||
syslog(LOG_WARNING, "Can't create %s: %m",
|
||||
ttys);
|
||||
else
|
||||
ttysf = fdopen(ttysfd, "w");
|
||||
}
|
||||
}
|
||||
while (t = getttyent()) {
|
||||
if (ttysf != NULL)
|
||||
(void) fprintf(ttysf, "%c2%s\n",
|
||||
(t->ty_status & TTY_ON) ? '1' : '0', t->ty_name);
|
||||
if ((t->ty_status & TTY_ON) == 0)
|
||||
continue;
|
||||
for (ALL) {
|
||||
if (SCMPN(p->line, t->ty_name))
|
||||
continue;
|
||||
p->xflag |= FOUND;
|
||||
if (SCMPN(p->comn, t->ty_getty)) {
|
||||
p->xflag |= CHANGE;
|
||||
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);
|
||||
}
|
||||
goto contin1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make space for a new one
|
||||
*/
|
||||
p1 = (struct tab *)calloc(1, sizeof(*p1));
|
||||
if (!p1) {
|
||||
syslog(LOG_ERR, "no space for '%s' !?!", t->ty_name);
|
||||
goto contin1;
|
||||
}
|
||||
/*
|
||||
* Put new terminal at the end of the linked list.
|
||||
*/
|
||||
if (itab) {
|
||||
for (p = itab; p->next ; p = p->next)
|
||||
;
|
||||
p->next = p1;
|
||||
} else
|
||||
itab = p1;
|
||||
|
||||
p = p1;
|
||||
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) {
|
||||
p->xflag |= WCHANGE;
|
||||
SCPYN(p->wcmd, t->ty_window);
|
||||
}
|
||||
contin1:
|
||||
;
|
||||
}
|
||||
endttyent();
|
||||
if (ttysf != NULL)
|
||||
(void) fclose(ttysf);
|
||||
p1 = (struct tab *)0;
|
||||
for (ALL) {
|
||||
if ((p->xflag&FOUND) == 0) {
|
||||
term(p);
|
||||
wterm(p);
|
||||
if (p1)
|
||||
p1->next = p->next;
|
||||
else
|
||||
itab = p->next;
|
||||
free(p);
|
||||
p = p1 ? p1 : itab;
|
||||
} else {
|
||||
/* window system should be started first */
|
||||
if (p->xflag&WCHANGE) {
|
||||
wterm(p);
|
||||
wstart(p);
|
||||
}
|
||||
if (p->xflag&CHANGE) {
|
||||
term(p);
|
||||
dfork(p);
|
||||
}
|
||||
}
|
||||
p1 = p;
|
||||
}
|
||||
}
|
||||
|
||||
term(p)
|
||||
register struct tab *p;
|
||||
{
|
||||
|
||||
if (p->pid != 0) {
|
||||
rmut(p);
|
||||
kill(p->pid, SIGKILL);
|
||||
}
|
||||
p->pid = 0;
|
||||
/* send SIGHUP to get rid of connections */
|
||||
if (p->wpid > 0)
|
||||
kill(p->wpid, SIGHUP);
|
||||
}
|
||||
|
||||
dfork(p)
|
||||
struct tab *p;
|
||||
{
|
||||
register pid;
|
||||
time_t t;
|
||||
int dowait = 0;
|
||||
|
||||
time(&t);
|
||||
p->gettycnt++;
|
||||
if ((t - p->gettytime) >= 60) {
|
||||
p->gettytime = t;
|
||||
p->gettycnt = 1;
|
||||
} else if (p->gettycnt >= 5) {
|
||||
dowait = 1;
|
||||
p->gettytime = t;
|
||||
p->gettycnt = 1;
|
||||
}
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
sigsetmask(0); /* since can be called from masked code */
|
||||
if (dowait) {
|
||||
syslog(LOG_ERR, "'%s %s' failing, sleeping", p->comn, p->line);
|
||||
closelog();
|
||||
sleep(30);
|
||||
}
|
||||
execit(p->comn, p->line);
|
||||
exit(0);
|
||||
}
|
||||
p->pid = pid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove utmp entry.
|
||||
*/
|
||||
rmut(p)
|
||||
register struct tab *p;
|
||||
{
|
||||
register f;
|
||||
int found = 0;
|
||||
static unsigned utmpsize;
|
||||
static struct utmp *utmp;
|
||||
register struct utmp *u;
|
||||
int nutmp;
|
||||
struct stat statbf;
|
||||
|
||||
f = open(utmpf, O_RDWR);
|
||||
if (f >= 0) {
|
||||
fstat(f, &statbf);
|
||||
if (utmpsize < statbf.st_size) {
|
||||
utmpsize = statbf.st_size + 10 * sizeof(struct utmp);
|
||||
if (utmp)
|
||||
utmp = (struct utmp *)realloc(utmp, utmpsize);
|
||||
else
|
||||
utmp = (struct utmp *)malloc(utmpsize);
|
||||
if (!utmp)
|
||||
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 (SCMPN(u->ut_line, p->line) ||
|
||||
u->ut_name[0]==0)
|
||||
continue;
|
||||
lseek(f, ((long)u)-((long)utmp), L_SET);
|
||||
SCPYN(u->ut_name, "");
|
||||
SCPYN(u->ut_host, "");
|
||||
time(&u->ut_time);
|
||||
write(f, (char *)u, sizeof(*u));
|
||||
found++;
|
||||
}
|
||||
}
|
||||
close(f);
|
||||
}
|
||||
if (found) {
|
||||
f = open(wtmpf, O_WRONLY|O_APPEND);
|
||||
if (f >= 0) {
|
||||
SCPYN(wtmp.ut_line, p->line);
|
||||
SCPYN(wtmp.ut_name, "");
|
||||
SCPYN(wtmp.ut_host, "");
|
||||
time(&wtmp.ut_time);
|
||||
write(f, (char *)&wtmp, sizeof(wtmp));
|
||||
close(f);
|
||||
}
|
||||
/*
|
||||
* After a proper login force reset
|
||||
* of error detection code in dfork.
|
||||
*/
|
||||
p->gettytime = 0;
|
||||
p->windtime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
reset()
|
||||
{
|
||||
|
||||
longjmp(sjbuf, 1);
|
||||
}
|
||||
|
||||
jmp_buf idlebuf;
|
||||
|
||||
void
|
||||
idlehup()
|
||||
{
|
||||
|
||||
longjmp(idlebuf, 1);
|
||||
}
|
||||
|
||||
void
|
||||
idle()
|
||||
{
|
||||
register struct tab *p;
|
||||
register pid;
|
||||
|
||||
signal(SIGHUP, idlehup);
|
||||
for (EVER) {
|
||||
if (setjmp(idlebuf))
|
||||
return;
|
||||
pid = wait((int *) 0);
|
||||
if (pid == -1) {
|
||||
sigpause(0);
|
||||
continue;
|
||||
}
|
||||
for (ALL) {
|
||||
/* if window system dies, mark it for restart */
|
||||
if (p->wpid == pid)
|
||||
p->wpid = -1;
|
||||
if (p->pid == pid) {
|
||||
rmut(p);
|
||||
p->pid = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wterm(p)
|
||||
register struct tab *p;
|
||||
{
|
||||
if (p->wpid != 0) {
|
||||
kill(p->wpid, SIGKILL);
|
||||
}
|
||||
p->wpid = 0;
|
||||
}
|
||||
|
||||
wstart(p)
|
||||
register struct tab *p;
|
||||
{
|
||||
register pid;
|
||||
time_t t;
|
||||
int dowait = 0;
|
||||
|
||||
time(&t);
|
||||
p->windcnt++;
|
||||
if ((t - p->windtime) >= 60) {
|
||||
p->windtime = t;
|
||||
p->windcnt = 1;
|
||||
} else if (p->windcnt >= 5) {
|
||||
dowait = 1;
|
||||
p->windtime = t;
|
||||
p->windcnt = 1;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid == 0) {
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
sigsetmask(0); /* since can be called from masked code */
|
||||
if (dowait) {
|
||||
syslog(LOG_ERR, "'%s %s' failing, sleeping", p->wcmd, p->line);
|
||||
closelog();
|
||||
sleep(30);
|
||||
}
|
||||
execit(p->wcmd, p->line);
|
||||
exit(0);
|
||||
}
|
||||
p->wpid = pid;
|
||||
}
|
||||
|
||||
#define NARGS 20 /* must be at least 4 */
|
||||
#define ARGLEN 512 /* total size for all the argument strings */
|
||||
|
||||
execit(s, arg)
|
||||
char *s;
|
||||
char *arg; /* last argument on line */
|
||||
{
|
||||
char *argv[NARGS], args[ARGLEN], *envp[1];
|
||||
register char *sp = s;
|
||||
register char *ap = args;
|
||||
register char c;
|
||||
register int i;
|
||||
|
||||
/*
|
||||
* 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++) {
|
||||
argv[i] = ap;
|
||||
for (EVER) {
|
||||
if ((c = *sp++) == '\0' || ap >= &args[ARGLEN-1]) {
|
||||
*ap = '\0';
|
||||
goto done;
|
||||
}
|
||||
if (c == ' ') {
|
||||
*ap++ = '\0';
|
||||
while (*sp == ' ')
|
||||
sp++;
|
||||
if (*sp == '\0')
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
*ap++ = c;
|
||||
}
|
||||
}
|
||||
done:
|
||||
setpgrp(0,0);
|
||||
argv[0] = argv[1];
|
||||
argv[1] = "-";
|
||||
argv[i+1] = arg;
|
||||
argv[i+2] = 0;
|
||||
envp[0] = 0;
|
||||
execve(argv[0], &argv[1], envp);
|
||||
/* report failure of exec */
|
||||
syslog(LOG_ERR, "%s: %m", argv[0]);
|
||||
closelog();
|
||||
sleep(10); /* prevent failures from eating machine */
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable keyboard interrupts
|
||||
*/
|
||||
kbd_disable()
|
||||
{
|
||||
if (isc2secure() || !cons_secure()) {
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
}
|
||||
}
|
||||
|
||||
int securestate = -1;
|
||||
|
||||
/*
|
||||
* Is this a C2 secure system ?
|
||||
*/
|
||||
isc2secure()
|
||||
{
|
||||
|
||||
if (securestate == -1)
|
||||
securestate = (access(pwaf, F_OK) == 0);
|
||||
return (securestate);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the password for user ID == 0
|
||||
*/
|
||||
char *
|
||||
rootpass()
|
||||
{
|
||||
register FILE *f;
|
||||
register struct passwd *pwd;
|
||||
register struct passwd_adjunct *pwa;
|
||||
extern struct passwd *fgetpwent();
|
||||
extern struct passwd_adjunct *fgetpwaent();
|
||||
|
||||
if ((f = fopen(pwdf, "r")) == NULL)
|
||||
return (NULL);
|
||||
while ((pwd = fgetpwent(f)) != NULL) {
|
||||
if (pwd->pw_uid == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
if (pwd == NULL)
|
||||
return (NULL);
|
||||
if ((f = fopen(pwaf, "r")) == NULL)
|
||||
return (pwd->pw_passwd);
|
||||
while ((pwa = fgetpwaent(f)) != NULL) {
|
||||
if (strcmp(pwa->pwa_name, pwd->pw_name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
if (pwa == NULL)
|
||||
return (NULL);
|
||||
|
||||
return (pwa->pwa_passwd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the console secure?
|
||||
*/
|
||||
cons_secure()
|
||||
{
|
||||
register struct ttyent *t;
|
||||
register char *s;
|
||||
extern char *rindex();
|
||||
|
||||
s = rindex(ctty, '/');
|
||||
if (s != NULL)
|
||||
s++;
|
||||
if ((t = getttynam(s)) != NULL)
|
||||
return (t->ty_status & TTY_SECURE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#include <sys/termios.h>
|
||||
/*
|
||||
* close std{in,out,err}
|
||||
* make this process a session leader
|
||||
* get the console as this process' ctty
|
||||
* if (protect) leave the tty in a non signaling state
|
||||
*/
|
||||
getcons(protect)
|
||||
{
|
||||
|
||||
(void) close(0); (void) close(1); (void) close(2);
|
||||
(void) setpgrp(0, 0);
|
||||
(void) open(ctty, O_RDWR);
|
||||
(void) dup2(0, 1); (void) dup2(0, 2);
|
||||
if (!protect)
|
||||
return;
|
||||
/*
|
||||
* the child grabs the tty, protecting the parent and the
|
||||
* parent's descendants.
|
||||
*/
|
||||
if (fork() == 0) {
|
||||
int pgrp = getpid();
|
||||
|
||||
(void) setpgrp(pgrp, pgrp);
|
||||
(void) ioctl(0, TIOCSPGRP, &pgrp);
|
||||
exit(0);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user