2016-04-22 6 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)); 
    } 
} 

私は私のシェルプログラムを実行すると、私はLSや猫のように、コマンドで入力し、 コマンドが正常に実行されます。その の後に別のコマンドを実行すると、コマンドはまったく実行されません。最初に入力したものと同じ コマンドであっても、それはまだ 2度目には実行されません。エラーメッセージは表示されません。これは、出力するコマンドを で呼び出すだけでは出力されません。私は現在execvpを使用していますが、私は現在議論を通過していると考えていますので、ここからどこに行くのかは分かりません。誰かが私に の入力をしてもらえますか?なぜexecvpはシェルで最初に入力されたコマンドに対してのみ機能しますか?

+0

あなたが行ったデバッグ(もしあれば)とあなたが見つけたものを教えてください。たとえば、プログラムをデバッガで実行したり、デバッグプリントステートメントを追加してプログラムの実行をトレースしたりしますか? – kaylum

答えて

0

あなたは(私はあなた次第なデザインを残しておきますが、それは、メインループの中で私のために働いていた)が適切であると感じどこ:

numTokens = 0; 

あなたはどのトークンの数をリセットしていませんあなたはtokenize関数をインクリメントします。グローバル変数を使用すると、このような小さな事を見逃しやすくなります。

+0

おはよう、ありがとう!私は残念ながらそれを考えなかったでしょう。 – Sherbs

+0

私はそれを素早く見つけられませんでした。これがvalgrindとgdbがあなたの友人である理由です。 Valgrindはすぐにあなたが1つのコマンドの後に無効な読み取りをしようとしていると言いました、そして、これが起こっていたコード行について、あなたのtokenize関数を詳しく見ました。 –

+0

ありがとう、私は間違いなくそれらのデバッガを調べます – Sherbs

関連する問題