/* Nick Urbanik (very) simple shell. */ #include #include #include #include #include #include #include void print_prompt( const char *prog ) { printf( "%s-> ", prog ); } /* Read the command into a buffer line[]. Then set an array of pointers, one to the start of each word. A word starts at the first non-whitespace character after either the beginning of the line, or whitespace. Terminate the array of pointers to arguements with a NULL pointer, as required for execv*(). We also null-terminate each argument, as required. Handle specially the case where the command is exit. Exit if get end of file. */ #define MAX_ARGS 64 #define MAX_LINE_LEN 1024 char *args[ MAX_ARGS + 1 ]; void built_in_commands( void ) { if ( strcmp( args[ 0 ], "exit" ) == 0 ) exit( 0 ); } void read_command( void ) { static char line[ MAX_LINE_LEN ]; int i = 0, j = 0, inspace = 1; if ( fgets( line, MAX_LINE_LEN, stdin ) == NULL ) exit( 1 ); while ( line[ i ] != '\0' && j < MAX_ARGS ) { if ( isspace( line[ i ] ) ) { if ( ! inspace ) line[ i ] = '\0'; ++i; inspace = 1; continue; } if ( inspace ) { args[ j++ ] = &line[ i ]; inspace = 0; } else ++i; } args[ j ] = NULL; built_in_commands(); } int main( int argc, char **argv ) { char *prog_name = basename( *argv ); print_prompt( prog_name ); read_command(); for ( ;; ) { int pid = fork(); if ( pid < 0 ) { perror( prog_name ); exit( 2 ); } if ( pid == 0 ) { int rv = execvp( args[ 0 ], args ); if ( rv == -1 ) perror( prog_name ); exit( 1 ); } wait( NULL ); print_prompt( prog_name ); read_command(); } }