2016-02-20 27 views
0

我發現了同樣的問題,但沒有答案。Unix shell的輸入重定向不起作用

在構建我自己的unix shell中,我的輸出重定向工作正常,但是當我嘗試輸入時,它不會執行任何操作。如果你能幫我弄清楚這個問題會很好。 這是我的執行函數代碼:

void execute (char **args) 
{ 
    int pid, status; 
    pid = fork(); 

    if (pid < 0) 
    { 
     perror ("Error forking!"); 
     return; 
    } 


    else if (pid > 0) 
    { 
     fflush(0); 
     while (wait (&status) != pid) 
     continue; 
    } 


    else if (pid == 0) 
    { 

     int i,in=0,out=0; 
     char input[BUF_SIZE],output[BUF_SIZE]; 

     for(i=0;args[i]!=NULL;i++) 
     { 
     if(strcmp(args[i],"<")==0) 
     {   
      args[i]=NULL; 
      strcpy(input,args[i+1]); 
      in=2;   
     }    

     if(strcmp(args[i],">")==0) 
     {  
      args[i]=NULL; 
      strcpy(output,args[i+1]); 
      out=2; 
     }   
     } 


     if(in) 
     { 
     int fd0; 
     if ((fd0 = open(input, O_RDONLY, 0)) < 0) 
     { 
      perror("Couldn't open input file"); 
      exit(0); 
     }   

     dup2(fd0, 0); 

     close(fd0); 
     } 


     if (out) 
     { 
     int fd1; 
     if ((fd1 = creat(output , 0644)) < 0) 
     { 
      perror("Couldn't open the output file"); 
      exit(0); 
     }   

     dup2(fd1, 1); 
     close(fd1); 
     } 

     execvp (*args, args); 
     perror("execvp"); 
     _exit(1); 
    } 

這裏是我的全部代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <signal.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <sys/stat.h> 
#include <fcntl.h> 

#define ARGSIZE 20 
#define BUF_SIZE 1024 

void execute (char **args); 
void cd (char *directory); 
int killpid (char *pitstr, int sig); 

int main (void) 
{ 
    char line[BUF_SIZE] = {0}; 
    char *args[ARGSIZE] = {NULL}; 
    char *token; 
    int i, argIndex = 0; 

    while (1) 
    { 

     argIndex = 0; 

     for (i = 0; i < ARGSIZE; i++) 
      args[i] = NULL; 

     printf ("shell> "); 

     if (fgets (line, BUF_SIZE, stdin) == NULL) 
     { 
      printf ("EOF received\n"); 
      return 0; 
     } 

     if (*line == '\n') 
     continue; 

     token = strtok (line, " \n"); 

     while (token != NULL) 
     { 
      args[argIndex] = token; 
      token = strtok (NULL, " \n"); 
      argIndex++; 
     } 

     if (!argIndex) 
      continue; 

     if (strcmp (args[0], "quit") == 0 || strcmp (args[0], "exit") == 0) 
      break; 

     if ((strcmp (args[0], "cd") == 0)) 
      cd (args[1]); 
     else if ((strcmp (args[0], "kill") == 0)) 
     { 
      if (args[1]) 
       killpid (args[1], SIGTERM); 
     } 


     else 
      execute (args); 

    } 
    return 0; 
} 

void execute (char **args) 
{ 
    int pid, status; 
    pid = fork(); 

    if (pid < 0) 
    { 
     perror ("Error forking!"); 
     return; 
    } 


    else if (pid > 0) 
    { 
     fflush(0); 
     while (wait (&status) != pid) 
      continue; 
    } 


    else if (pid == 0) 
    { 

     int i,in=0,out=0; 
     char input[BUF_SIZE],output[BUF_SIZE]; 

     for(i=0;args[i]!=NULL;i++) 
     { 
      if(strcmp(args[i],"<")==0) 
      {   
       args[i]=NULL; 
       strcpy(input,args[i+1]); 
       in=2;   
      }    

      if(strcmp(args[i],">")==0) 
      {  
       args[i]=NULL; 
       strcpy(output,args[i+1]); 
       out=2; 
      }   
     } 


     if(in) 
     { 
      int fd0; 
      if ((fd0 = open(input, O_RDONLY, 0)) < 0) 
      { 
       perror("Couldn't open input file"); 
       exit(0); 
      }   

      dup2(fd0, 0); 
      close(fd0); 
     } 


     if (out) 
     { 
      int fd1; 
      if ((fd1 = creat(output , 0644)) < 0) 
      { 
       perror("Couldn't open the output file"); 
       exit(0); 
      }   

      dup2(fd1, 1); 
      close(fd1); 
     } 

     execvp (*args, args); 
     perror("execvp"); 
     _exit(1); 
     } 

} 

void cd (char *directory) 
{ 
    char dir[BUF_SIZE] = {0}; 

    if (!directory) 
    { 
     directory = getenv ("HOME"); 

     if (chdir (directory)) 
      fprintf (stderr, "Failed to enter directory: %s\n", directory); 
     else 
      printf ("%s\n", directory); 

     return; 
    } 

    if (*directory == '~') 
    { 
     strcpy (dir, getenv ("HOME")); 
     strcat (dir, "/"); 
     strcat (dir, directory + 2); 

     if (chdir (dir)) 
      fprintf (stderr, "Failed to enter directory: %s\n", dir); 
     else 
      printf ("%s\n", dir); 

     return; 
    } 

    if (chdir (directory)) 
     fprintf (stderr, "Failed to enter directory: %s\n", directory); 
    else 
     printf ("%s\n", directory); 
} 

int killpid (char *pidstr, int sig) 
{ 
    pid_t pid = (pid_t)atoi (pidstr); 

    if (pid < 1) 
    { 
     fprintf (stderr, "warning: requested pid < 1, ignoring\n"); 
     return (int)pid; 
    } 

    printf (" killing pid '%d' with signal '%d'\n", (int)pid, sig); 
    return 0; 
} 
+0

這是C或C++或其他什麼東西? –

+0

將'execvp(...)'替換爲int c; while((c = getchar())!= EOF)putchar(c);'並用結果編輯你的問題。 – msw

+0

這是C,我很抱歉msw我的大學服務器正在關閉atm所以我不能運行它,但如何工作?它會打印文件的內容,但不會執行命令..但我的輸出不起作用。我必須能夠執行「ls -al> out.txt」,但「sort Shallan

回答

1

當你args數組中看到<這裏

if(strcmp(args[i],"<")==0) 

設置ARGS [我]到NULL

args[i]=NULL; 

但是,你把它傳遞給strcmp()

if(strcmp(args[i],">")==0) 

和您的孩子的過程會很樂意段錯誤。使用if-else -construct這裏:

if(strcmp(args[i],"<")==0) {   
    args[i]=NULL; 
    strcpy(input,args[i+1]); 
    in=2;   
} else if(strcmp(args[i],">")==0) {  
    args[i]=NULL; 
    strcpy(output,args[i+1]); 
    out=2; 
} 

這應該修復錯誤。

此外,這可能會派上用場,以檢測這種情況:

... 
while (wait (&status) != pid) 
    continue; 
if (WIFSIGNALED(status)) 
    printf("Killed by signal %d%s\n", 
      WTERMSIG(status), WCOREDUMP(status)?" (Core dumped)":""); 
+0

你遇到了問題(不一定是唯一的問題),但'set參數爲null'表示shell命令將忽略任何後續參數。在POSIX shell中,您可以在輸入行中的任意點寫入「'< input >輸出命令名稱arg1 arg2'」(所以「'> output command-name 2>/dev/null arg1

+0

@JonathanLeffler由於循環沒有終止,它將_will_找到後續的輸出重定向,據我所知。好的,你的意思是重定向後的常規參數被忽略。這是真的,但我會說,這種行爲是在外殼設計師的處置。 – Ctx

+0

是的,shell會找到它,但'execvp()'將停止處理第一個空指針處的命令行;那之後它不會再尋找額外的參數。所以,如果你有'command-name