# include  <stdio.h> # include  <stdlib.h> # include  <string.h> # include  <errno.h> # include  <unistd.h> # include  <sys/types.h> # include  <sys/wait.h> # include  <ctype.h> # include  <sys/stat.h> # include  <fcntl.h> # define  ZERO  '\0' # define  SIZE  512 # define  SEP  " " # define  NUM  32 # define  Skiopath ( p)  do {  p +=  strlen ( p- 1 ) ; while ( * p!= '/' ) p-- ; } while ( 0 ) # define  SkipSpace ( cmd, pos)  do { while ( 1 ) { if ( isspace ( cmd[ pos] ) ) pos++ ; else  break ; } } while ( 0 ) # define  None_Redir  0 # define  In_Redir  1 # define  Out_Redir  2 # define  App_Redir  3 int  redir_type =  None_Redir; 
char *  filename = NULL ; char  * gArgv[ NUM] ; 
char  cwd[ SIZE* 2 ] ; 
int  lastcode = 0 ; void  Die ( ) 
{ exit ( 1 ) ; 
} 
const  char  * Gethome ( ) 
{ const  char  * home = getenv ( "HOME" ) ; if ( home== NULL ) return  "/" ; return  home; 
} 
const  char  * GetuserName ( ) 
{ const  char  * name=  getenv ( "USER" ) ; if ( name== NULL ) return  "None" ; return  name; 
} 
const  char  * GethostName ( ) 
{ const  char  * hostname =  getenv ( "HOSTNAME" ) ; if ( hostname== NULL ) return  "None" ; return  hostname; 
} 
const  char  * GetCwd ( ) 
{ const  char  * cwd= getenv ( "PWD" ) ; if ( cwd== NULL ) return  "None" ; return  cwd; 
} 
void  Makecommandline_print ( ) 
{ char  line[ SIZE] ; const  char  * username =  GetuserName ( ) ; const  char  * hostname =  GethostName ( ) ; const  char  * cwd =  GetCwd ( ) ; Skiopath ( cwd) ; snprintf ( line, SIZE, "[%s@%s %s]> " , username, hostname, strlen ( cwd) == 1 ? "/" : cwd+ 1 ) ; printf ( "%s" , line) ; fflush ( stdout ) ; 
} 
int  Getusercommand ( char  command[ ] , size_t  n) 
{ char  * s =  fgets ( command, n, stdin ) ; if ( s== NULL ) return  1 ; command[ strlen ( command) - 1 ] = ZERO; return  strlen ( command) ; 
} void  Splitcommand ( char  command[ ] , size_t  n) 
{ gArgv[ 0 ]  =  strtok ( command, SEP) ; int  index = 1 ; while ( ( gArgv[ index++ ] = strtok ( NULL , SEP) ) ) ; } void  Executecommand ( ) 
{ pid_t  id = fork ( ) ; if ( id< 0 )  Die ( ) ; else  if ( id== 0 ) { if ( filename !=  NULL ) { if ( redir_type ==  In_Redir) { int  fd = open ( filename, O_RDONLY) ; dup2 ( fd, 0 ) ; } else  if ( redir_type ==  Out_Redir) { int  fd = open ( filename, O_WRONLY |  O_CREAT |  O_TRUNC, 0666 ) ; dup2 ( fd, 1 ) ; } else  if ( redir_type ==  App_Redir) { int  fd = open ( filename, O_WRONLY |  O_CREAT |  O_APPEND, 0666 ) ; dup2 ( fd, 1 ) ; } else { } } execvp ( gArgv[ 0 ] , gArgv) ; exit ( errno) ; } else { int  status = 0 ; pid_t  rid =  waitpid ( id, & status, 0 ) ; if ( rid> 0 ) { lastcode =  WEXITSTATUS ( status) ; if ( lastcode!= 0 ) printf ( "%s:%s:%d\n" , gArgv[ 0 ] , strerror ( lastcode) , lastcode) ; } } } 
void  Cd ( ) 
{ const  char  * path =  gArgv[ 1 ] ; if ( path== NULL ) path= Gethome ( ) ; chdir ( path) ; char  temp[ SIZE* 2 ] ; getcwd ( temp, sizeof ( temp) ) ; snprintf ( cwd, sizeof ( cwd) , "PWD=%s" , temp) ; putenv ( cwd) ; 
} 
int  Checkbuilding ( ) 
{ int  yes = 0 ; const  char  * enter_cmd =  gArgv[ 0 ] ; if ( strcmp ( enter_cmd, "cd" ) == 0 ) { yes = 1 ; Cd ( ) ; } else  if ( strcmp ( enter_cmd, "echo" ) == 0 && strcmp ( gArgv[ 1 ] , "$?" ) == 0 ) { yes= 1 ; printf ( "%d\n" , lastcode) ; lastcode= 0 ; } return  yes; 
} 
void  CheckRedir ( char  cmd[ ] ) 
{ int  pos = 0 ; int  end= strlen ( cmd) ; while ( pos <  end) { if ( cmd[ pos]  ==  '>' ) { if ( cmd[ pos+ 1 ]  ==  '>' ) { cmd[ pos++ ]  =  0 ; pos++ ; redir_type =  App_Redir; SkipSpace ( cmd, pos) ; filename =  cmd + pos; } else { cmd[ pos++ ]  =  0 ; redir_type =  Out_Redir; SkipSpace ( cmd, pos) ; filename =  cmd + pos; } } else  if ( cmd[ pos]  ==  '<' ) { cmd[ pos++ ] = 0 ; redir_type =  In_Redir; SkipSpace ( cmd, pos) ; filename =  cmd+ pos; } else  { pos++ ; } } 
} 
int  main ( ) 
{ int  quit = 0  ; while ( ! quit) { redir_type =  None_Redir; filename = NULL ; Makecommandline_print ( ) ; char  usercommand[ SIZE] ; int  n =  Getusercommand ( usercommand, sizeof ( usercommand) ) ; CheckRedir ( usercommand) ; Splitcommand ( usercommand, sizeof ( usercommand) ) ; n= Checkbuilding ( ) ; if ( n) continue ; Executecommand ( ) ; } return  0 ; 
}