【问题标题】:creating a shell like program in C在 C 中创建类似 shell 的程序
【发布时间】:2017-07-06 02:00:07
【问题描述】:

我正在尝试创建一个简单的 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);
    
    }
    

谁能告诉我我做错了什么或指导我如何纠正这个问题。

【问题讨论】:

    标签: c shell operating-system


    【解决方案1】:

    这个输入读数

    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() 了解失败的原因。

    【讨论】:

    • 谢谢。这真的很有帮助。我从 scanf 更改为 gets 并修改了 execl() 命令并且它起作用了。它也适用于 execv() 。但是哪一个更好呢?我更喜欢 execl() 只是因为 execv() 更简单
    • execl 和 execv 之间没有“更好”的地方——它们只是论点不同。因此,请使用对您的用例方便的任何一种。
    猜你喜欢
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    相关资源
    最近更新 更多