2011-02-25 134 views
1

我试图执行UNIX cat“>”命令,从我的UNIX shell中执行file1.txt > foo.txtC Shell打开文件并返回到命令提示符

我想从用户输入中取得普通的UNIX命令,并通过execvp执行它们(我现在做得很好)。

我要添加“>”到我的壳流,但我有与写它,并给代表团重新就业,为连续用户输入的指令行后关闭文件问题。有人可以向我解释我在做什么愚蠢的事情吗?我知道,为了写入文件,我必须关闭标准,打开一个新的标准,写入文件,然后以某种方式关闭文件的标准输出并重新启用键盘的标准输出以便能够接受用户再命令..

我的主要功能,只是给你一个想法:

int main(int argc, char **argv) 
{   
    printf("[MYSHELL] $ "); 

    while (TRUE) { 
     user_input = getchar(); 
     switch (user_input) { 
      case EOF: 
       exit(-1); 

      case '\n': 
       printf("[MYSHELL] $ "); 
       break; 

      default: 
       // parse input into cmd_argv - store # commands in cmd_argc 
       handle_user_input(); 

       //determine input and execute foreground/background process 
       execute_command(); 
     } 
     background = 0; 
    } 
    printf("\n[MYSHELL] $ "); 
    return 0;  
} 

这是我的函数获取用户输入的基础。如果它找到一个“>”的cmd_argv阵列中,它设置输出标志= 1和从期望的可执行命令删除它:

// get command line input 
    while ((user_input != '\n') && (buffer_characters < 50)) { 
     buffer[buffer_characters++] = user_input; 
     user_input = getchar(); 
    } 

    // clear buffer 
    buffer[buffer_characters] = 0x00; 

    // populate cmd_argv - array of commands 
    char *buffer_pointer; 
    buffer_pointer = strtok(buffer, " "); 

    while (buffer_pointer != NULL) { 
     cmd_argv[cmd_argc] = buffer_pointer; 
     buffer_pointer = strtok(NULL, " "); 

     if(strcmp(cmd_argv[cmd_argc], ">") == 0){ 
      cmd_argv[cmd_argc] = strtok(NULL, " "); 
      output = 1; 
     } 

     cmd_argc++; 

     if(output){ 
      filename = buffer_pointer; //name of file that we're going to write to. 
      return; 
     }   
    } 

的代码从execute_command驱动输出功能注意的I GOT这里味精。这似乎是在那里的死亡

if (output == 1){ 
      close(1); 
      file = fopen(filename, "w"); 
      create_process(); 
      output = 0; 
      printf("IT GOT HERE!!!\n"); 
      fclose(file); 
      fopen("/dev/null", "r"); // open a new stdin that is always empty 
      return 1; 
     }else{ 
     create_process(); 
     return; 
    } 

而且create_process处理前台和后台进程

void create_process() 
{ 
    status = 0; 
    int pid = fork(); 
    background = 0; 

    if (pid == 0) { 
     // child process 
     if(background) { 
      printf("no background"); 
      fclose(stdin); // close child's stdin 
      fopen("/dev/null", "r"); // open a new stdin that is always empty 
      execvp(*cmd_argv,cmd_argv); 

      // If an error occurs, print error and exit 
      fprintf (stderr, "unknown command: %s\n", cmd_argv[0]); 
      exit(1); 

     }else if(output == 1){ 
      execvp(*cmd_argv,cmd_argv); 
     } 
     else { 
      execvp(*cmd_argv,cmd_argv); 
      // If an error occurs, print error and exit 
      fprintf (stderr, "unknown command: %s\n", cmd_argv[0]); 
      exit(1); 
     } 
    } else { 
     // parent process, waiting on child process 
     if (background) { 
      printf("starting background job %d\n", pid); 
      jobs_list[jobs_list_size] = pid; 
      jobs_list_size++; 

     } else { 
      waitpid(pid, &status, 0); 
     } 

     if (status != 0) 
      fprintf (stderr, "error: %s exited with status code %d\n", cmd_argv[0], status); 

     return; 
    } 
} 

回答

1

你接近它错了。你不想混淆父进程的文件描述符,所有,你不想使用C的stdio - 你应该使用基于低级文件描述符的调用这项工作。

fork()后,在子进程中,你应该执行:

int output_fd = open(filename, O_RDONLY); 
if (output_fd > -1) { 
    dup2(output_fd, STDOUT_FILENO); 
    close(output_fd); 
} else { 
    perror("open"); 
} 

没有必要在父任何的清理,因为家长的公开文件单独留在家中。

+0

感谢您的帮助! '不需要在父母中进行任何清理' - 你的意思是什么?我试过你的例子,并且认为它仍然需要用某种输出标志来包装,这取决于我的程序在调用create_process时的结构。思考? – user546459 2011-02-25 15:23:18

+0

@ user546459:我的意思是说,因为你不曾打开父文件中的输出文件,或者改变父文件的打开文件,你以后也不必“修复它们”。使用你的程序结构,你必须将文件名传递给'create_process()',以便它可以在'fork()'之后执行'open()',所以你可以只有'filename == NULL'没有输出文件。 – caf 2011-02-25 23:56:26

相关问题