@@ -18,6 +18,7 @@ use crate::{fmt, io};
1818#[ derive( Debug ) ]
1919pub struct Command {
2020 prog : OsString ,
21+ args : Vec < OsString > ,
2122 stdout : Option < Stdio > ,
2223 stderr : Option < Stdio > ,
2324}
@@ -39,12 +40,11 @@ pub enum Stdio {
3940
4041impl Command {
4142 pub fn new ( program : & OsStr ) -> Command {
42- Command { prog : program. to_os_string ( ) , stdout : None , stderr : None }
43+ Command { prog : program. to_os_string ( ) , args : Vec :: new ( ) , stdout : None , stderr : None }
4344 }
4445
45- // FIXME: Implement arguments as reverse of parsing algorithm
46- pub fn arg ( & mut self , _arg : & OsStr ) {
47- panic ! ( "unsupported" )
46+ pub fn arg ( & mut self , arg : & OsStr ) {
47+ self . args . push ( arg. to_os_string ( ) ) ;
4848 }
4949
5050 pub fn env_mut ( & mut self ) -> & mut CommandEnv {
@@ -72,7 +72,7 @@ impl Command {
7272 }
7373
7474 pub fn get_args ( & self ) -> CommandArgs < ' _ > {
75- panic ! ( "unsupported" )
75+ CommandArgs { iter : self . args . iter ( ) }
7676 }
7777
7878 pub fn get_envs ( & self ) -> CommandEnvs < ' _ > {
@@ -116,6 +116,9 @@ impl Command {
116116 pub fn output ( & mut self ) -> io:: Result < ( ExitStatus , Vec < u8 > , Vec < u8 > ) > {
117117 let mut cmd = uefi_command_internal:: Image :: load_image ( & self . prog ) ?;
118118
119+ let args = uefi_command_internal:: create_args ( & self . prog , & self . args ) ;
120+ cmd. set_args ( args) ;
121+
119122 // Setup Stdout
120123 let stdout = self . stdout . unwrap_or ( Stdio :: MakePipe ) ;
121124 let stdout = Self :: create_pipe ( stdout) ?;
@@ -315,7 +318,7 @@ mod uefi_command_internal {
315318 stdout : Option < helpers:: OwnedProtocol < PipeProtocol > > ,
316319 stderr : Option < helpers:: OwnedProtocol < PipeProtocol > > ,
317320 st : OwnedTable < r_efi:: efi:: SystemTable > ,
318- args : Option < Vec < u16 > > ,
321+ args : Option < ( * mut u16 , usize ) > ,
319322 }
320323
321324 impl Image {
@@ -449,20 +452,22 @@ mod uefi_command_internal {
449452 }
450453 }
451454
452- pub fn set_args ( & mut self , args : & OsStr ) {
455+ pub fn set_args ( & mut self , mut args : Box < [ u16 ] > ) {
453456 let loaded_image: NonNull < loaded_image:: Protocol > =
454457 helpers:: open_protocol ( self . handle , loaded_image:: PROTOCOL_GUID ) . unwrap ( ) ;
455458
456- let mut args = args. encode_wide ( ) . collect :: < Vec < u16 > > ( ) ;
457- let args_size = ( crate :: mem:: size_of :: < u16 > ( ) * args. len ( ) ) as u32 ;
459+ let len = args. len ( ) ;
460+ let ptr = args. as_mut_ptr ( ) ;
461+ crate :: mem:: forget ( args) ;
462+
463+ let args_size = ( crate :: mem:: size_of :: < u16 > ( ) * len) as u32 ;
458464
459465 unsafe {
460- ( * loaded_image. as_ptr ( ) ) . load_options =
461- args. as_mut_ptr ( ) as * mut crate :: ffi:: c_void ;
466+ ( * loaded_image. as_ptr ( ) ) . load_options = ptr as * mut crate :: ffi:: c_void ;
462467 ( * loaded_image. as_ptr ( ) ) . load_options_size = args_size;
463468 }
464469
465- self . args = Some ( args ) ;
470+ self . args = Some ( ( ptr , len ) ) ;
466471 }
467472
468473 fn update_st_crc32 ( & mut self ) -> io:: Result < ( ) > {
@@ -502,6 +507,10 @@ mod uefi_command_internal {
502507 ( ( * bt. as_ptr ( ) ) . unload_image ) ( self . handle . as_ptr ( ) ) ;
503508 }
504509 }
510+
511+ if let Some ( ( ptr, len) ) = self . args {
512+ let _ = unsafe { Box :: from_raw ( crate :: slice:: from_raw_parts_mut ( ptr, len) ) } ;
513+ }
505514 }
506515 }
507516
@@ -681,4 +690,36 @@ mod uefi_command_internal {
681690 }
682691 }
683692 }
693+
694+ pub fn create_args ( prog : & OsStr , args : & [ OsString ] ) -> Box < [ u16 ] > {
695+ const QUOTE : u16 = 0x0022 ;
696+ const SPACE : u16 = 0x0020 ;
697+ const CARET : u16 = 0x005e ;
698+ const NULL : u16 = 0 ;
699+
700+ let mut res = Vec :: new ( ) ;
701+
702+ // Wrap program name in quotes to avoid any problems
703+ res. push ( QUOTE ) ;
704+ res. extend ( prog. encode_wide ( ) ) ;
705+ res. push ( QUOTE ) ;
706+ res. push ( SPACE ) ;
707+
708+ for arg in args {
709+ // Wrap the argument in quotes to be treat as single arg
710+ res. push ( QUOTE ) ;
711+ for c in arg. encode_wide ( ) {
712+ // CARET in quotes is used to escape CARET or QUOTE
713+ if c == QUOTE || c == CARET {
714+ res. push ( CARET ) ;
715+ }
716+ res. push ( c) ;
717+ }
718+ res. push ( QUOTE ) ;
719+
720+ res. push ( SPACE ) ;
721+ }
722+
723+ res. into_boxed_slice ( )
724+ }
684725}
0 commit comments