2016-04-22 9 views
0
#include <stdio.h> 
#include <string.h> 
#include <cstring> 
#include <stdlib.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <sys/wait.h> 

char input[100]; 
#define DELIMITERS " \t\n" 
char * tokens[100]; 
int numTokens = 0; 
int i = 0; 
int n = 0; 
char * cmd; 

// function prototype 
void nonBuiltin(char * inputs[]); 
void handlePipe(char * cmds[]); 

// this breaks the input into tokens and returns them 
char * tokenize(char input[100]) 
{ 
    n = 0; 
    // grabs input and separates by delimiters until the char is null 
    for(cmd = strtok(input, DELIMITERS); cmd; cmd = strtok(NULL, DELIMITERS)) 
    { 
     if(n >= 100) 
     { 
     break; 
     } 
     tokens[n++] = cmd; 
     numTokens++; 
    } 

    for(size_t i = 0; i != n; i++) 
     { 
     printf("Tokens %zu is %s\n", i, tokens[i]); 
     } 
    return * tokens; 
} 

// handles the commands you enter 
// checks if builtin or non builtin command 
// if builtin, execute command 
// else, send command to nonbuiltin function 
void handleCommands(char * inputs) 
{ 
    // changes directory 
    if(strcmp(tokens[0], "cd") == 0) 
    { 
     int change = chdir(tokens[1]); 
     if(change == 0) 
     { 
      chdir(tokens[1]); 
     } 
     else 
     { 
      perror("Cannot find path specified...\n"); 
     } 
    } 
    // prints working directory 
    else if(strcmp(tokens[0], "pwd") == 0) 
    { 
     printf("Your current working directory is: %s\n", getenv("PWD")); 
    } 
    // implements set command 
    else if(strcmp(tokens[0], "set") == 0) 
    { 
     // do this 
    } 
    // exits program 
    else if(strcmp(tokens[0], "exit") == 0) 
    { 
     printf("Now exiting...\n"); 
     exit(3); 
    } 
    // input contains a nonbuiltin command 
    // sends input to nonbuiltin function 
    else 
    { 
     printf("Your command is a nonbuilt-in command\n"); 
     nonBuiltin(tokens); 
    } 
} 

void nonBuiltin(char * inputs[]) 
{ 
    int fp; 
    int status; 

    // create a new process 
    pid_t pid; 
    pid = fork(); 
    // process creation was unsuccessful 
    if(pid < 0) 
    { 
     perror("Fork unsuccessful...\n"); 
     exit(-1); 
    } 
    // child process 
    else if(pid == 0) 
    { 
     // printf("Fork successful...\n"); 
     if(numTokens >= 3) 
    { 
     for(int i = 0; i < numTokens; i++) 
     { 
      if(strcmp(tokens[i], "<") == 0) 
      { 
      tokens[i] = tokens[i+1]; 
      fp = open(tokens[i], O_RDONLY, 0); 
      dup2(fp, 0); 
      execvp(tokens[0], tokens); 
      } 
      else if(strcmp(tokens[i], ">") == 0) 
      { 
      tokens[i] = tokens[i+1]; 
      fp = open(tokens[i], O_WRONLY | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP); 
      dup2(fp, 1); 
      close(fp); 
      tokens[i]= NULL; 
      execvp(tokens[0], tokens); 

      } 
      else if(strcmp(tokens[i], "|") == 0) 
      { 
       tokens[i] = tokens[i+1]; 
       handlePipe(tokens); 
      } 
     } 
    } 

     else 
     { 
     // printf("Nothing special as far as commands go\n"); 
     execvp(tokens[0], tokens); 


     } 
    } 
    // wait for child process to end 
    else 
    { 
     waitpid(-1, &status, WUNTRACED); 
     printf("the child process has now terminated\n"); 
    // exit(0); 
    } 

} 


void handlePipe(char * cmds[]) 
{ 
    printf("Initiate piping\n"); 
    // file descriptors 
    int fd[2]; 
    // fd[0] is the read end of pipe 
    // fd[1] is the write end of pipe 
    pipe(fd); 

    if(!fork()) 
     { 
     // first close the write end 
     close(1); 
     // fd[1] can now take stdout 
     dup(fd[1]); 
     close(fd[0]); 
     execvp(cmds[0], cmds); 

     } 
    else 
     { 
     // close read end 
     close(0); 
     // fd[1] can now take stdin 
     dup(fd[0]); 
     close(fd[1]); 
     execvp(cmds[1], cmds); 
     } 


} 

// starts the program and asks the user to enter input 
// loops until the user enters 'exit' 
int main() 
{ 
    while(1) 
    { 
     printf("Enter a command...\n"); 
     fgets(input, 100, stdin); 
     handleCommands(tokenize(input)); 
    } 
} 

Wenn ich meine Shell-Programm auszuführen, geben Sie ich in einem Befehl wie ls oder eine Katze, und der Befehl korrekt ausgeführt. Wenn ich einen weiteren Befehl nach dem One ausführe, wird der Befehl überhaupt nicht ausgeführt. Es könnte sogar der gleiche Befehl als der erste sein, den ich eingegeben habe, und es wird immer noch nicht für das zweite Mal laufen. Es werden keine Fehlermeldungen ausgegeben. Es gibt nur nicht aus, was der Befehl ruft, um es auszugeben. Ich benutze zur Zeit execvp, und ich glaube, dass ich die Argumente derzeit übergebe, also bin ich mir nicht sicher, wohin ich von hier aus gehen soll. Könnte mir jemand eine Eingabe zu geben, warum das passiert?Warum funktioniert execvp nur für den ersten Befehl in meiner Shell?

+0

Bitte teilen Sie, was Sie getestet haben (falls vorhanden) und was Sie herausgefunden haben. Haben Sie beispielsweise Ihr Programm in einem Debugger ausgeführt und/oder weitere Debug-Print-Anweisungen hinzugefügt, um die Ausführung Ihres Programms nachzuverfolgen? – kaylum

Antwort

0

Überall dort, wo Sie das Gefühl, angemessen ist (es für mich in der Hauptschleife gearbeitet, obwohl ich das Design bei Ihnen hinterlassen werden):

numTokens = 0; 

Sie die Anzahl der Token nicht Zurücksetzen der Sie erhöhen die Tokenize-Funktion. Die Verwendung einer globalen Variablen macht es leicht, kleine Dinge wie diese zu übersehen.

+0

Whoa, vielen Dank! Daran hätte ich leider nie gedacht. – Sherbs

+0

Ich hätte es auch nicht so schnell eingefangen, deshalb sind Valgrind und GdB deine Freunde. Valgrind hat mir sofort gesagt, dass Sie versuchen, nach einem Befehl und der Codezeile, in der das geschieht, einen ungültigen Lesevorgang auszuführen, also habe ich Ihre Tokenize-Funktion näher betrachtet. –

+0

Danke, ich werde definitiv in diese Debugger schauen – Sherbs