11#[ allow( unused_imports) ]
22use std:: io:: { self , Write } ;
33use std:: path:: PathBuf ;
4+ use std:: os:: unix:: process:: CommandExt ;
45
56const BUILT_IN_COMMANDS : [ & str ; 3 ] = [ "echo" , "exit" , "type" ] ;
67
@@ -49,32 +50,55 @@ enum Command{
4950 ExitCommand ,
5051 EchoCommand { display_string : String } ,
5152 TypeCommand { command_name : String } ,
53+ ExternalCommand { program : String , args : Vec < String > } ,
5254 CommandNotFound ,
5355}
5456
5557impl Command {
5658 fn from_input ( input : & str ) -> Self {
5759 let input=input. trim ( ) ;
58- if input == "exit" || input == "exit 0" {
59- return Self :: ExitCommand ;
60- } ;
61- if let Some ( pos ) = input . find ( "echo" ) {
62- if pos == 0 {
63- return Self :: EchoCommand {
64- display_string : input [ "echo" . len ( ) .. ] . trim ( ) . to_string ( ) ,
65- } ;
66- }
60+
61+ // splitting tokens so that i can have the command and arguments
62+ let tokens : Vec < String > = input
63+ . split_whitespace ( )
64+ . map ( |s| s . to_string ( ) )
65+ . collect ( ) ;
66+
67+ if tokens . is_empty ( ) {
68+ return Command :: CommandNotFound ;
6769 }
68- if let Some ( pos) = input. find ( "type" ) {
69- if pos==0 {
70- return Self :: TypeCommand {
71- command_name : input[ "type" . len ( ) ..] . trim ( ) . to_string ( ) ,
72- } ;
70+ let program = tokens[ 0 ] . clone ( ) ;
71+ let args = & tokens[ 1 ..] ;
72+ let cmd = match program. as_str ( ) {
73+ "exit" => Command :: ExitCommand ,
74+ "echo" => Command :: EchoCommand {
75+ display_string : args. join ( " " )
76+ } ,
77+ "type" => {
78+ if args. is_empty ( ) {
79+ Command :: CommandNotFound
80+ } else {
81+ Command :: TypeCommand {
82+ command_name : args[ 0 ] . clone ( )
83+ }
84+ }
7385 }
74- }
75- Self :: CommandNotFound // we are returning this value
86+ _ => {
87+ let loc = CommandLocation :: resolve ( & program) ;
88+ match loc {
89+ CommandLocation :: Executable ( _) => {
90+ Command :: ExternalCommand { program, args : args. to_vec ( ) }
91+ }
92+ CommandLocation :: NotFound => Command :: CommandNotFound ,
93+ CommandLocation :: Builtin => unreachable ! ( ) , // handled above
94+ }
95+ }
96+ } ;
97+
98+ cmd
7699 }
77100
101+
78102}
79103
80104fn main ( ) {
@@ -84,18 +108,7 @@ fn main() {
84108
85109 let mut input = String :: new ( ) ;
86110 io:: stdin ( ) . read_line ( & mut input) . unwrap ( ) ;
87- if input. is_empty ( ) {
88- continue ;
89- }
90-
91- // splitting tokens so that i can have the command and arguments
92- let tokens: Vec < String > = input
93- . split_whitespace ( )
94- . map ( |s| s. to_string ( ) )
95- . collect ( ) ;
96111
97- let cmd_name = tokens[ 0 ] . clone ( ) ;
98- let args = & tokens[ 1 ..] ;
99112 //implementing internal built_in_commands
100113 let command = Command :: from_input ( & input) ;
101114 match command{
@@ -105,22 +118,29 @@ fn main() {
105118 let location = CommandLocation :: resolve ( & command_name) ;
106119 println ! ( "{}" , location. describe( & command_name) ) ;
107120 } ,
108- Command :: CommandNotFound =>{
109- match CommandLocation :: resolve ( & cmd_name) {
110- CommandLocation :: Executable ( path) => {
111- let status = std:: process:: Command :: new ( path)
112- . args ( args)
113- . spawn ( )
114- . and_then ( |mut child| child. wait ( ) ) ;
115- if status. is_err ( ) {
116- println ! ( "{}: failed to execute" , cmd_name) ;
121+ Command :: ExternalCommand { program, args} => {
122+ match CommandLocation :: resolve ( & program) {
123+ CommandLocation :: Executable ( path) =>{
124+ let child =std:: process:: Command :: new ( & path)
125+ . arg0 ( & program)
126+ . args ( & args)
127+ . spawn ( ) ;
128+ match child {
129+ Ok ( mut c) =>{
130+ let _ = c. wait ( ) ;
131+ }
132+ Err ( _) =>{
133+ println ! ( "{}: failed to execute" , program) ;
134+ }
117135 }
118136 }
119- CommandLocation :: Builtin => unreachable ! ( ) ,
120- CommandLocation :: NotFound => println ! ( "{}: command not found" , input. trim( ) ) ,
121- }
137+ _ => println ! ( "{}: command not found" , program) ,
122138
123- } ,
139+ }
140+ }
141+ Command :: CommandNotFound =>{
142+ println ! ( "{}: command not found" , input. trim( ) ) ;
143+ }
124144 }
125145 }
126146}
0 commit comments