Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
emulab-devel
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
143
Issues
143
List
Boards
Labels
Service Desk
Milestones
Merge Requests
6
Merge Requests
6
Operations
Operations
Incidents
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
emulab
emulab-devel
Commits
cea4fdf5
Commit
cea4fdf5
authored
Oct 20, 2017
by
Mike Hibler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Old: hacks for FreeBSD 10.4 support.
parent
68887069
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
2459 additions
and
1 deletion
+2459
-1
clientside/configure
clientside/configure
+1
-0
clientside/configure.ac
clientside/configure.ac
+1
-0
clientside/tmcc/freebsd/init/10.4/GNUmakefile.in
clientside/tmcc/freebsd/init/10.4/GNUmakefile.in
+30
-0
clientside/tmcc/freebsd/init/10.4/getmntopts.c
clientside/tmcc/freebsd/init/10.4/getmntopts.c
+197
-0
clientside/tmcc/freebsd/init/10.4/init.c
clientside/tmcc/freebsd/init/10.4/init.c
+2078
-0
clientside/tmcc/freebsd/init/10.4/mntopts.h
clientside/tmcc/freebsd/init/10.4/mntopts.h
+102
-0
clientside/tmcc/freebsd/init/10.4/pathnames.h
clientside/tmcc/freebsd/init/10.4/pathnames.h
+43
-0
clientside/tmcc/freebsd/init/GNUmakefile.in
clientside/tmcc/freebsd/init/GNUmakefile.in
+5
-1
configure
configure
+1
-0
configure.ac
configure.ac
+1
-0
No files found.
clientside/configure
View file @
cea4fdf5
...
...
@@ -4558,6 +4558,7 @@ outfiles="Makeconf GNUmakefile setversion \
tmcc/freebsd/init/9/GNUmakefile
\
tmcc/freebsd/init/10/GNUmakefile
\
tmcc/freebsd/init/10.3/GNUmakefile
\
tmcc/freebsd/init/10.4/GNUmakefile
\
tmcc/freebsd/init/11/GNUmakefile
\
tmcc/freebsd/init/12/GNUmakefile
\
tmcc/freebsd/supfile tmcc/freebsd/sethostname
\
...
...
clientside/configure.ac
View file @
cea4fdf5
...
...
@@ -285,6 +285,7 @@ outfiles="Makeconf GNUmakefile setversion \
tmcc/freebsd/init/9/GNUmakefile \
tmcc/freebsd/init/10/GNUmakefile \
tmcc/freebsd/init/10.3/GNUmakefile \
tmcc/freebsd/init/10.4/GNUmakefile \
tmcc/freebsd/init/11/GNUmakefile \
tmcc/freebsd/init/12/GNUmakefile \
tmcc/freebsd/supfile tmcc/freebsd/sethostname \
...
...
clientside/tmcc/freebsd/init/10.4/GNUmakefile.in
0 → 100644
View file @
cea4fdf5
#
# Insert Copyright Here.
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = @top_builddir@
SUBDIR = $(subst $(TESTBED_SRCDIR)/,,$(SRCDIR))
include $(OBJDIR)/Makeconf
all:
client: init
include $(TESTBED_SRCDIR)/GNUmakerules
CFLAGS += -DDEBUGSHELL -DSECURE -DLOGIN_CAP -DCOMPAT_SYSV_INIT -DTESTBED
init.c: pathnames.h mntopts.h
getmntopts.c: mntopts.h
init: init.c getmntopts.c
$(CC) $(CFLAGS) -static -o init $^ -lutil -lcrypt
install:
client-install: client
install -s -o root -g wheel -m 555 -b -B.bak -fschg -S init $(DESTDIR)/sbin/init
clean:
rm -f *.o core init
clientside/tmcc/freebsd/init/10.4/getmntopts.c
0 → 100644
View file @
cea4fdf5
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 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.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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
* SUCH DAMAGE.
*/
#if 0
#ifndef lint
static char sccsid[] = "@(#)getmntopts.c 8.3 (Berkeley) 3/29/95";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID
(
"$FreeBSD: releng/10.4/sbin/mount/getmntopts.c 310378 2016-12-21 23:16:58Z brooks $"
);
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <err.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mntopts.h"
int
getmnt_silent
=
0
;
void
getmntopts
(
const
char
*
options
,
const
struct
mntopt
*
m0
,
int
*
flagp
,
int
*
altflagp
)
{
const
struct
mntopt
*
m
;
int
negative
,
len
;
char
*
opt
,
*
optbuf
,
*
p
;
int
*
thisflagp
;
/* Copy option string, since it is about to be torn asunder... */
if
((
optbuf
=
strdup
(
options
))
==
NULL
)
err
(
1
,
NULL
);
for
(
opt
=
optbuf
;
(
opt
=
strtok
(
opt
,
","
))
!=
NULL
;
opt
=
NULL
)
{
/* Check for "no" prefix. */
if
(
opt
[
0
]
==
'n'
&&
opt
[
1
]
==
'o'
)
{
negative
=
1
;
opt
+=
2
;
}
else
negative
=
0
;
/*
* for options with assignments in them (ie. quotas)
* ignore the assignment as it's handled elsewhere
*/
p
=
strchr
(
opt
,
'='
);
if
(
p
!=
NULL
)
*++
p
=
'\0'
;
/* Scan option table. */
for
(
m
=
m0
;
m
->
m_option
!=
NULL
;
++
m
)
{
len
=
strlen
(
m
->
m_option
);
if
(
strncasecmp
(
opt
,
m
->
m_option
,
len
)
==
0
)
if
(
opt
[
len
]
==
'\0'
||
opt
[
len
]
==
'='
)
break
;
}
/* Save flag, or fail if option is not recognized. */
if
(
m
->
m_option
)
{
thisflagp
=
m
->
m_altloc
?
altflagp
:
flagp
;
if
(
negative
==
m
->
m_inverse
)
*
thisflagp
|=
m
->
m_flag
;
else
*
thisflagp
&=
~
m
->
m_flag
;
}
else
if
(
!
getmnt_silent
)
{
errx
(
1
,
"-o %s: option not supported"
,
opt
);
}
}
free
(
optbuf
);
}
void
rmslashes
(
char
*
rrpin
,
char
*
rrpout
)
{
char
*
rrpoutstart
;
*
rrpout
=
*
rrpin
;
for
(
rrpoutstart
=
rrpout
;
*
rrpin
!=
'\0'
;
*
rrpout
++
=
*
rrpin
++
)
{
/* skip all double slashes */
while
(
*
rrpin
==
'/'
&&
*
(
rrpin
+
1
)
==
'/'
)
rrpin
++
;
}
/* remove trailing slash if necessary */
if
(
rrpout
-
rrpoutstart
>
1
&&
*
(
rrpout
-
1
)
==
'/'
)
*
(
rrpout
-
1
)
=
'\0'
;
else
*
rrpout
=
'\0'
;
}
int
checkpath
(
const
char
*
path
,
char
*
resolved
)
{
struct
stat
sb
;
if
(
realpath
(
path
,
resolved
)
==
NULL
||
stat
(
resolved
,
&
sb
)
!=
0
)
return
(
1
);
if
(
!
S_ISDIR
(
sb
.
st_mode
))
{
errno
=
ENOTDIR
;
return
(
1
);
}
return
(
0
);
}
void
build_iovec
(
struct
iovec
**
iov
,
int
*
iovlen
,
const
char
*
name
,
void
*
val
,
size_t
len
)
{
int
i
;
if
(
*
iovlen
<
0
)
return
;
i
=
*
iovlen
;
*
iov
=
realloc
(
*
iov
,
sizeof
**
iov
*
(
i
+
2
));
if
(
*
iov
==
NULL
)
{
*
iovlen
=
-
1
;
return
;
}
(
*
iov
)[
i
].
iov_base
=
strdup
(
name
);
(
*
iov
)[
i
].
iov_len
=
strlen
(
name
)
+
1
;
i
++
;
(
*
iov
)[
i
].
iov_base
=
val
;
if
(
len
==
(
size_t
)
-
1
)
{
if
(
val
!=
NULL
)
len
=
strlen
(
val
)
+
1
;
else
len
=
0
;
}
(
*
iov
)[
i
].
iov_len
=
(
int
)
len
;
*
iovlen
=
++
i
;
}
/*
* This function is needed for compatibility with parameters
* which used to use the mount_argf() command for the old mount() syscall.
*/
void
build_iovec_argf
(
struct
iovec
**
iov
,
int
*
iovlen
,
const
char
*
name
,
const
char
*
fmt
,
...)
{
va_list
ap
;
char
val
[
255
]
=
{
0
};
va_start
(
ap
,
fmt
);
vsnprintf
(
val
,
sizeof
(
val
),
fmt
,
ap
);
va_end
(
ap
);
build_iovec
(
iov
,
iovlen
,
name
,
strdup
(
val
),
(
size_t
)
-
1
);
}
/*
* Free the iovec and reset to NULL with zero length. Useful for calling
* nmount in a loop.
*/
void
free_iovec
(
struct
iovec
**
iov
,
int
*
iovlen
)
{
int
i
;
for
(
i
=
0
;
i
<
*
iovlen
;
i
++
)
free
((
*
iov
)[
i
].
iov_base
);
free
(
*
iov
);
}
clientside/tmcc/freebsd/init/10.4/init.c
0 → 100644
View file @
cea4fdf5
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Donn Seeley at Berkeley Software Design, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 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.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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
* SUCH DAMAGE.
*/
#ifndef lint
static
const
char
copyright
[]
=
"@(#) Copyright (c) 1991, 1993
\n
\
The Regents of the University of California. All rights reserved.
\n
"
;
#endif
/* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)init.c 8.1 (Berkeley) 7/15/93";
#endif
static
const
char
rcsid
[]
=
"$FreeBSD: releng/10.4/sbin/init/init.c 321907 2017-08-02 05:47:26Z delphij $"
;
#endif
/* not lint */
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/sysctl.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <db.h>
#include <errno.h>
#include <fcntl.h>
#include <kenv.h>
#include <libutil.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <ttyent.h>
#include <unistd.h>
#include <sys/reboot.h>
#include <err.h>
#include <stdarg.h>
#ifdef SECURE
#include <pwd.h>
#endif
#ifdef LOGIN_CAP
#include <login_cap.h>
#endif
#include "mntopts.h"
#include "pathnames.h"
/*
* Sleep times; used to prevent thrashing.
*/
#define GETTY_SPACING 5
/* N secs minimum getty spacing */
#define GETTY_SLEEP 30
/* sleep N secs after spacing problem */
#define GETTY_NSPACE 3
/* max. spacing count to bring reaction */
#define WINDOW_WAIT 3
/* wait N secs after starting window */
#define STALL_TIMEOUT 30
/* wait N secs after warning */
#define DEATH_WATCH 10
/* wait N secs for procs to die */
#define DEATH_SCRIPT 120
/* wait for 2min for /etc/rc.shutdown */
#define RESOURCE_RC "daemon"
#define RESOURCE_WINDOW "default"
#define RESOURCE_GETTY "default"
static
void
handle
(
sig_t
,
...);
static
void
delset
(
sigset_t
*
,
...);
static
void
stall
(
const
char
*
,
...)
__printflike
(
1
,
2
);
static
void
warning
(
const
char
*
,
...)
__printflike
(
1
,
2
);
static
void
emergency
(
const
char
*
,
...)
__printflike
(
1
,
2
);
static
void
disaster
(
int
);
static
void
badsys
(
int
);
static
void
revoke_ttys
(
void
);
static
int
runshutdown
(
void
);
static
char
*
strk
(
char
*
);
/*
* We really need a recursive typedef...
* The following at least guarantees that the return type of (*state_t)()
* is sufficiently wide to hold a function pointer.
*/
typedef
long
(
*
state_func_t
)(
void
);
typedef
state_func_t
(
*
state_t
)(
void
);
static
state_func_t
single_user
(
void
);
static
state_func_t
runcom
(
void
);
static
state_func_t
read_ttys
(
void
);
static
state_func_t
multi_user
(
void
);
static
state_func_t
clean_ttys
(
void
);
static
state_func_t
catatonia
(
void
);
static
state_func_t
death
(
void
);
static
state_func_t
death_single
(
void
);
static
state_func_t
reroot
(
void
);
static
state_func_t
reroot_phase_two
(
void
);
static
state_func_t
run_script
(
const
char
*
);
static
enum
{
AUTOBOOT
,
FASTBOOT
}
runcom_mode
=
AUTOBOOT
;
#define FALSE 0
#define TRUE 1
static
int
Reboot
=
FALSE
;
static
int
howto
=
RB_AUTOBOOT
;
static
int
devfs
;
static
void
transition
(
state_t
);
static
state_t
requested_transition
;
static
state_t
current_state
=
death_single
;
static
void
open_console
(
void
);
static
const
char
*
get_shell
(
void
);
static
void
write_stderr
(
const
char
*
message
);
typedef
struct
init_session
{
int
se_index
;
/* index of entry in ttys file */
pid_t
se_process
;
/* controlling process */
time_t
se_started
;
/* used to avoid thrashing */
int
se_flags
;
/* status of session */
#define SE_SHUTDOWN 0x1
/* session won't be restarted */
#define SE_PRESENT 0x2
/* session is in /etc/ttys */
int
se_nspace
;
/* spacing count */
char
*
se_device
;
/* filename of port */
char
*
se_getty
;
/* what to run on that port */
char
*
se_getty_argv_space
;
/* pre-parsed argument array space */
char
**
se_getty_argv
;
/* pre-parsed argument array */
char
*
se_window
;
/* window system (started only once) */
char
*
se_window_argv_space
;
/* pre-parsed argument array space */
char
**
se_window_argv
;
/* pre-parsed argument array */
char
*
se_type
;
/* default terminal type */
struct
init_session
*
se_prev
;
struct
init_session
*
se_next
;
}
session_t
;
static
void
free_session
(
session_t
*
);
static
session_t
*
new_session
(
session_t
*
,
int
,
struct
ttyent
*
);
static
session_t
*
sessions
;
static
char
**
construct_argv
(
char
*
);
static
void
start_window_system
(
session_t
*
);
static
void
collect_child
(
pid_t
);
static
pid_t
start_getty
(
session_t
*
);
static
void
transition_handler
(
int
);
static
void
alrm_handler
(
int
);
static
void
setsecuritylevel
(
int
);
static
int
getsecuritylevel
(
void
);
static
int
setupargv
(
session_t
*
,
struct
ttyent
*
);
#ifdef LOGIN_CAP
static
void
setprocresources
(
const
char
*
);
#endif
static
int
clang
;
static
int
start_session_db
(
void
);
static
void
add_session
(
session_t
*
);
static
void
del_session
(
session_t
*
);
static
session_t
*
find_session
(
pid_t
);
static
DB
*
session_db
;
/*
* The mother of all processes.
*/
int
main
(
int
argc
,
char
*
argv
[])
{
state_t
initial_transition
=
runcom
;
char
kenv_value
[
PATH_MAX
];
int
c
,
error
;
struct
sigaction
sa
;
sigset_t
mask
;
/* Dispose of random users. */
if
(
getuid
()
!=
0
)
errx
(
1
,
"%s"
,
strerror
(
EPERM
));
/* System V users like to reexec init. */
if
(
getpid
()
!=
1
)
{
#ifdef COMPAT_SYSV_INIT
/* So give them what they want */
if
(
argc
>
1
)
{
if
(
strlen
(
argv
[
1
])
==
1
)
{
char
runlevel
=
*
argv
[
1
];
int
sig
;
switch
(
runlevel
)
{
case
'0'
:
/* halt + poweroff */
sig
=
SIGUSR2
;
break
;
case
'1'
:
/* single-user */
sig
=
SIGTERM
;
break
;
case
'6'
:
/* reboot */
sig
=
SIGINT
;
break
;
case
'c'
:
/* block further logins */
sig
=
SIGTSTP
;
break
;
case
'q'
:
/* rescan /etc/ttys */
sig
=
SIGHUP
;
break
;
case
'r'
:
/* remount root */
sig
=
SIGEMT
;
break
;
default:
goto
invalid
;
}
kill
(
1
,
sig
);
_exit
(
0
);
}
else
invalid:
errx
(
1
,
"invalid run-level ``%s''"
,
argv
[
1
]);
}
else
#endif
errx
(
1
,
"already running"
);
}
/*
* Note that this does NOT open a file...
* Does 'init' deserve its own facility number?
*/
openlog
(
"init"
,
LOG_CONS
|
LOG_ODELAY
,
LOG_AUTH
);
/*
* Create an initial session.
*/
if
(
setsid
()
<
0
&&
(
errno
!=
EPERM
||
getsid
(
0
)
!=
1
))
warning
(
"initial setsid() failed: %m"
);
/*
* Establish an initial user so that programs running
* single user do not freak out and die (like passwd).
*/
if
(
setlogin
(
"root"
)
<
0
)
warning
(
"setlogin() failed: %m"
);
/*
* This code assumes that we always get arguments through flags,
* never through bits set in some random machine register.
*/
while
((
c
=
getopt
(
argc
,
argv
,
"dsfr"
))
!=
-
1
)
switch
(
c
)
{
case
'd'
:
devfs
=
1
;
break
;
case
's'
:
initial_transition
=
single_user
;
break
;
case
'f'
:
runcom_mode
=
FASTBOOT
;
break
;
case
'r'
:
initial_transition
=
reroot_phase_two
;
break
;
default:
warning
(
"unrecognized flag '-%c'"
,
c
);
break
;
}
if
(
optind
!=
argc
)
warning
(
"ignoring excess arguments"
);
/*
* We catch or block signals rather than ignore them,
* so that they get reset on exec.
*/
handle
(
badsys
,
SIGSYS
,
0
);
handle
(
disaster
,
SIGABRT
,
SIGFPE
,
SIGILL
,
SIGSEGV
,
SIGBUS
,
SIGXCPU
,
SIGXFSZ
,
0
);
handle
(
transition_handler
,
SIGHUP
,
SIGINT
,
SIGEMT
,
SIGTERM
,
SIGTSTP
,
SIGUSR1
,
SIGUSR2
,
0
);
handle
(
alrm_handler
,
SIGALRM
,
0
);
sigfillset
(
&
mask
);
delset
(
&
mask
,
SIGABRT
,
SIGFPE
,
SIGILL
,
SIGSEGV
,
SIGBUS
,
SIGSYS
,
SIGXCPU
,
SIGXFSZ
,
SIGHUP
,
SIGINT
,
SIGEMT
,
SIGTERM
,
SIGTSTP
,
SIGALRM
,
SIGUSR1
,
SIGUSR2
,
0
);
sigprocmask
(
SIG_SETMASK
,
&
mask
,
(
sigset_t
*
)
0
);
sigemptyset
(
&
sa
.
sa_mask
);
sa
.
sa_flags
=
0
;
sa
.
sa_handler
=
SIG_IGN
;
sigaction
(
SIGTTIN
,
&
sa
,
(
struct
sigaction
*
)
0
);
sigaction
(
SIGTTOU
,
&
sa
,
(
struct
sigaction
*
)
0
);
/*
* Paranoia.
*/
close
(
0
);
close
(
1
);
close
(
2
);
if
(
kenv
(
KENV_GET
,
"init_script"
,
kenv_value
,
sizeof
(
kenv_value
))
>
0
)
{
state_func_t
next_transition
;
if
((
next_transition
=
run_script
(
kenv_value
))
!=
0
)
initial_transition
=
(
state_t
)
next_transition
;
}
if
(
kenv
(
KENV_GET
,
"init_chroot"
,
kenv_value
,
sizeof
(
kenv_value
))
>
0
)
{
if
(
chdir
(
kenv_value
)
!=
0
||
chroot
(
"."
)
!=
0
)
warning
(
"Can't chroot to %s: %m"
,
kenv_value
);
}
/*
* Additional check if devfs needs to be mounted:
* If "/" and "/dev" have the same device number,
* then it hasn't been mounted yet.
*/
if
(
!
devfs
)
{
struct
stat
stst
;
dev_t
root_devno
;
stat
(
"/"
,
&
stst
);
root_devno
=
stst
.
st_dev
;
if
(
stat
(
"/dev"
,
&
stst
)
!=
0
)
warning
(
"Can't stat /dev: %m"
);
else
if
(
stst
.
st_dev
==
root_devno
)
devfs
++
;
}
if
(
devfs
)
{
struct
iovec
iov
[
4
];
char
*
s
;
int
i
;
char
_fstype
[]
=
"fstype"
;
char
_devfs
[]
=
"devfs"
;
char
_fspath
[]
=
"fspath"
;
char
_path_dev
[]
=
_PATH_DEV
;
iov
[
0
].
iov_base
=
_fstype
;
iov
[
0
].
iov_len
=
sizeof
(
_fstype
);
iov
[
1
].
iov_base
=
_devfs
;
iov
[
1
].
iov_len
=
sizeof
(
_devfs
);
iov
[
2
].
iov_base
=
_fspath
;
iov
[
2
].
iov_len
=
sizeof
(
_fspath
);
/*
* Try to avoid the trailing slash in _PATH_DEV.
* Be *very* defensive.
*/
s
=
strdup
(
_PATH_DEV
);
if
(
s
!=
NULL
)
{
i
=
strlen
(
s
);
if
(
i
>
0
&&
s
[
i
-
1
]
==
'/'
)
s
[
i
-
1
]
=
'\0'
;
iov
[
3
].
iov_base
=
s
;
iov
[
3
].
iov_len
=
strlen
(
s
)
+
1
;
}
else
{
iov
[
3
].
iov_base
=
_path_dev
;
iov
[
3
].
iov_len
=
sizeof
(
_path_dev
);
}
nmount
(
iov
,
4
,
0
);
if
(
s
!=
NULL
)
free
(
s
);
}