在C中创建类似程序的shell

时间:2017-02-16 19:16:07

标签: c shell operating-system

我正在尝试创建一个简单的c程序,它接受用户输入,将其传递给底层shell并返回用户命令的输出。例如:pwd将提供当前的工作目录。

我想在无限循环中使用fork()和exec()执行此操作,但我遇到两个问题:

  1. 我的循环在首次运行后终止
  2. 只需要第一个参数。 ' ls -ltr'会给我输出' ls'而不是' ls -ltr'

    int runit(char*);
    
    void main() {
    
    int pid=0;                          
    char command[50];
    while(1)
    
    {
        int d=0;
        printf("Please enter your command!\n");
        scanf("%s", &command);
        switch (pid = fork()) 
        {
            case 0:                    // a fork returns 0 to the child 
                printf("Child process \n");
                d=runit(command);
                if(d==-1){
                printf("command not found \n");}
                break;
    
            default:
                wait(5);               // a fork returns a pid to the parent 
                printf("Parent process \n"); 
                break;
    
            case -1:                   //if something went wrong 
                perror("fork");
                exit(1);
    
        }
      }                
    }
    
    int runit(char* command) {                     //executing the command
    
        char path[50]="/bin/";
    
        int d = execl(strcat(path,command),command,NULL,NULL);     
    
        return(d);
    
    }
    
  3. 有人可以告诉我我做错了什么或指导我如何纠正这个问题。

1 个答案:

答案 0 :(得分:2)

此输入读数

scanf("%s", &command);

将停在第一个空格处(除非发生输入失败 - 在任何情况下都应检查scanf()的返回值)。因此,当您输入ls -ltr时,command将只有ls。您需要阅读。例如,使用fgets()读取输入(并确保处理尾随换行符):

fgets(command, sizeof command, stdin);
command[strcspn(command, "\n")] = 0; /* to remove \n if present */

接下来的问题是execl()需要多个参数。这意味着 这个用法:

int d = execl(strcat(path,command),command,NULL,NULL);     

坏了。您需要将输入命令拆分为多个字符串,并将每个参数传递给execl()。将单个字符串存储在数组中并使用execv()代替的更好选项。

您需要注意的另一件事是exec*()家庭功能成功返回。因此,返回代码检查不是很有用 - 相反,您可以使用perror()来了解失败时失败的原因。