简单的shell用fork和exec

时间:2017-10-22 18:20:56

标签: c shell fork exec implementation

我正在尝试创建一个简单的shell运行来自PATH的任何命令,让我们说ls或pwd du gedit等。我遇到exec.I要求如果我输入空间没有任何反应,如果我输入退出它终止。任何帮助表示赞赏

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

#define BUFFER 1024

int main() {
    char line[BUFFER];
    char* args[100];
    char* path = "";
    char program[20];


while(1){
    printf("$ ");
         if(!fgets(line, BUFFER, stdin))
          break;
          size_t length = strlen(line);
         if (line[length - 1] == '\n')
         line[length - 1] = '\0';
     if(strcmp(line, "exit")==0)  break;
         strcpy(program,path);           
         strcat(program,line);
    int pid= fork();              //fork child

        if(pid==0){               //Child
        execlp(program,line,(char *)NULL);    
    }else{                    //Parent
        wait(NULL);
}
}
}   

2 个答案:

答案 0 :(得分:1)

嗨,请参阅下面的更正并查看我的评论。

int main() {
char line[BUFFER];
char* args[100];
char* path = "/bin/";
char program[20];
char command[50];

while(1){
    printf("$ ");
    if(!fgets(line, BUFFER, stdin))
        break;
    memset(command,0,sizeof(command));
    if(strncmp(line, "exit", (strlen(line)-1))==0)  break;
    strncpy(command,line,(strlen(line)-1));
    strcpy(program, path);
    strcat(program,command);
    int pid= fork();              //fork child
    if(pid==0){               //Child
        execl(program,command,NULL);
        exit(0);// you must exit from the child because now you are inside while loop of child. Otherwise you have to type exit twice to exit from the application. Because your while loop also became the part of every child and from the child again it will call fork and create a child again
    }else{
        wait(NULL);
    }
 }
}

另外,为了支持所有命令执行,请参阅函数execl如何传递参数。因此,您需要拆分命令并为execl正确创建参数列表。

答案 1 :(得分:0)

  1. 您有2次fgets()来电。删除第一个fgets(line, BUFFER, stdin);

  2. 如果缓冲区中有空格,
  3. fgets()将在换行符中读取。您需要删除它,因为当您输入exit时,您实际上输入exit\n并且没有/bin/exit\n的命令。

  4. 以下代码演示了删除换行符:

        if(!fgets(line, BUFFER, stdin))
            break;
        char *p = strchr(line, '\n');
        if (p) *p = 0;
    
    1. 您的用法是错误的。查看execl的手册。您需要传递参数:execl(program, line, (char *)NULL); 注意NULL的最后一个参数的演员表。如果NULL被定义为0,那么强制转换是必要的,因为execl是一个可变函数。
    2. 使用execvp的修改示例:

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      #include <sys/wait.h>
      #include <sys/types.h>
      #include <string.h>
      
      #define BUFFER 1024
      
      int main(void) {
          char line[BUFFER];
      
          while(1) {
              printf("$ ");
              if(!fgets(line, BUFFER, stdin)) break;
              char *p = strchr(line, '\n');
              if (p) *p = 0;
              if(strcmp(line, "exit")==0) break;
              char *args[] = {line, (char*)0};
              int pid= fork();              //fork child
              if(pid==0) {               //Child
                  execvp(line, args);
                  perror("exec");
                  exit(1);
              } else {                    //Parent
                  wait(NULL);
              }
          }
      
          return 0;
      }