@@ -29,7 +29,7 @@ use crate::output::Output;
2929use crate :: qga:: QgaWrapper ;
3030use crate :: { Mount , Target , VMConfig } ;
3131
32- const INIT_SCRIPT : & str = include_str ! ( "init/init.sh" ) ;
32+ const INIT_TEMPLATE : & str = include_str ! ( "init/init.sh.template " ) ;
3333const COMMAND_TEMPLATE : & str = include_str ! ( "init/command.template" ) ;
3434// Needs to be `/dev/root` for kernel to "find" the 9pfs as rootfs
3535const ROOTFS_9P_FS_MOUNT_TAG : & str = "/dev/root" ;
@@ -87,8 +87,32 @@ struct CommandContext {
8787 command_output_port_name : String ,
8888}
8989
90+ /// Used by templating engine to render init.sh
91+ #[ derive( Serialize ) ]
92+ struct InitContext {
93+ /// $PATH the guest should use
94+ path : String ,
95+ }
96+
9097const QEMU_DEFAULT_ARGS : & [ & str ] = & [ "-nodefaults" , "-display" , "none" ] ;
9198
99+ /// Gets instance of template engine
100+ ///
101+ /// Unfortunately cannot be done as a lazy_static or OnceCell b/c TinyTemplate
102+ /// internally uses some !Sync stuff.
103+ fn get_templates ( ) -> TinyTemplate < ' static > {
104+ // Disable HTML escaping (b/c we're not dealing with HTML)
105+ let mut tt = TinyTemplate :: new ( ) ;
106+ tt. set_default_formatter ( & format_unescaped) ;
107+
108+ // We are ok panicing here b/c there should never be a runtime
109+ // error compiling the template. Any errors are trivial bugs.
110+ tt. add_template ( "cmd" , COMMAND_TEMPLATE ) . unwrap ( ) ;
111+ tt. add_template ( "init" , INIT_TEMPLATE ) . unwrap ( ) ;
112+
113+ tt
114+ }
115+
92116/// Whether or not the host supports KVM
93117fn host_supports_kvm ( arch : & str ) -> bool {
94118 arch == ARCH && Path :: new ( "/dev/kvm" ) . exists ( )
@@ -134,6 +158,18 @@ fn guest_init_path(guest_temp_dir: PathBuf, host_init_path: PathBuf) -> Result<P
134158 Ok ( guest_init_path)
135159}
136160
161+ /// Generates init.sh that guest will use as pid 1
162+ fn init_script ( ) -> String {
163+ let path = match env:: var ( "PATH" ) {
164+ Ok ( p) => p,
165+ Err ( _) => "/bin:/sbin:/usr/bin:/usr/sbin" . to_string ( ) ,
166+ } ;
167+
168+ // Ignore errors cuz only trivial bugs are possible
169+ let context = InitContext { path } ;
170+ get_templates ( ) . render ( "init" , & context) . unwrap ( )
171+ }
172+
137173// Given a rootfs, generate a tempfile with the init script inside.
138174// Returns the tempfile and the path to the init script inside the guest.
139175// When rootfs is /, both the tempfile filename and guest init path are equal.
@@ -152,7 +188,7 @@ fn gen_init(rootfs: &Path) -> Result<(NamedTempFile, PathBuf)> {
152188 . context ( "Failed to create tempfile" ) ?;
153189
154190 host_init
155- . write_all ( INIT_SCRIPT . as_bytes ( ) )
191+ . write_all ( init_script ( ) . as_bytes ( ) )
156192 . context ( "Failed to write init to tmpfs" ) ?;
157193
158194 // Set write bits on script
@@ -743,14 +779,6 @@ impl Qemu {
743779
744780 /// Generates a bash script that runs `self.command`
745781 fn command_script ( & self ) -> String {
746- // Disable HTML escaping (b/c we're not dealing with HTML)
747- let mut tt = TinyTemplate :: new ( ) ;
748- tt. set_default_formatter ( & format_unescaped) ;
749-
750- // We are ok panicing here b/c there should never be a runtime
751- // error compiling the template. Any errors are trivial bugs.
752- tt. add_template ( "cmd" , COMMAND_TEMPLATE ) . unwrap ( ) ;
753-
754782 let context = CommandContext {
755783 // Only `cd` for kernel targets that share userspace with host
756784 should_cd : !self . image && self . rootfs == Target :: default_rootfs ( ) ,
@@ -759,8 +787,8 @@ impl Qemu {
759787 command_output_port_name : COMMAND_OUTPUT_PORT_NAME . into ( ) ,
760788 } ;
761789
762- // Same as above, ignore errors cuz only trivial bugs are possible
763- tt . render ( "cmd" , & context) . unwrap ( )
790+ // Ignore errors cuz only trivial bugs are possible
791+ get_templates ( ) . render ( "cmd" , & context) . unwrap ( )
764792 }
765793
766794 /// Run this target's command inside the VM
0 commit comments