【问题标题】:Problems with shell implementation in cc语言中shell实现的问题
【发布时间】:2021-12-28 07:52:02
【问题描述】:

几天来一直在研究一个简单的 shell 实现。但我有两个问题:

1.当你运行程序并输入一个类似“/bin/ls -l /usr/include”的命令然后按回车它会执行命令但是如果你再输入几行新的程序仍然会运行进入 execvp() 并输出“Permission denied”,因为它进入了 execvp 的错误处理,这不应该发生。 (我尝试了一些不同的方法来阻止它进入 main 中的 if(),但它们不起作用。)

2.如果你输入回车然后输入一个命令,该命令将不会被执行。 (我尝试释放 buff 并再次分配内存,但这会导致更多问题。)

所以基本上它会进入“if(buff[offset] == '\n')”,即使该行不应该是空的,并且它不会执行命令,除非它是第一个启动程序后输入。

代码:

int fd = 0;
const size_t read_size = 1;
size_t size = read_size;
char *buff = malloc(size+1);
size_t offset = 0;
size_t res = 0;

write(STDOUT_FILENO, "$ ", strlen("$ "));
while((res = read(fd, buff + offset, read_size)) > 0) 
{
    if(buff[offset] == '\n')
    {
        buff[offset] = '\0';
        char **result = parse_cmdline(buff); // turn string into array for execvp()

        int exec;
        int status;
        pid_t pid = fork();
        if(pid == -1) {/*error handling*/}
        else if(pid == 0)
        {
            if((exec = execvp(result[0], result)) == -1) {/*error handling*/}
        }
        else
        {
            waitpid(pid, &status, 0);
        }

        offset = 0;
        free(result[0]);
        free(result);
        result = NULL;
        write(STDOUT_FILENO, "$ ", strlen("$ "));
    }
    offset += res;
    if (offset + read_size > size)
    {
        size *= 2;
        buff = realloc(buff, size+1);
    }
    buff[offset] = '\0';
}
free(buff);
return 0;

更新:适用于在第一行之后输入的命令,但在每种情况下都会出错:

"a.out: malloc.c:2379: sysmalloc: 断言`(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' 失败。 中止(核心转储)”

更新代码:

if(buff[offset] == '\n')
        {
            buff[offset] = '\0';
            char **result = parse_cmdline(buff);
            if(result[0] != NULL)
            {
            int exec;
            int status;
            pid_t pid = fork(); // create the child process
            if(pid == -1) // check for fork() errors (no memory, etc.)
            {
                fork_error();
            }
            else if(pid == 0) // Handle child process
            {
                if((exec = execvp(result[0], result)) == -1) // run the command itself and check if an error will occur (invalid command, etc.)
                {
                    file_error(result[0]);
                }
            }
            else // Handle parent process
            {
                waitpid(pid, &status, 0);
            }

            offset = 0;
            free(buff);
            size = read_size;
            free(result[0]);
            free(result);
            result = NULL;
            }
            write(STDOUT_FILENO, "$ ", strlen("$ "));
            
        }
        else
        {
            offset += res;
            if (offset + read_size > size)
            {
                size *= 2;
                buff = realloc(buff, size+1);
            }
            buff[offset] = '\0';
        }

【问题讨论】:

  • “所以基本上它会进入“if(buff[offset] == '\n')”,即使该行是空的” - 该行不为空.当您按 Enter 时,它会发送 \n 并且由于 offset 初始化为 0,您会得到 buff[0] == '\n'
  • 是的,但我不明白为什么如果输入是:“命令,输入,输入”,输入进入 execvp,它会崩溃,如果输入是“输入,输入,命令”,则没有错误,但命令未执行。此外,我对代码进行了一些更改,似乎让它变得更好了——如果有作为非第一个输入的命令输入但每次都有错误,它现在可以工作。

标签: c shell input process


【解决方案1】:

您的parse_cmdline() 函数应测试空行、仅包含空白行的行和以# 开头的注释行,并在这些情况下返回NULL

然后调用代码应测试result 是否忽略这些行。

调用代码还应将result[0]与内部命令的名称进行比较,例如cdchdir,并在本地处理它们,而不是调用forkexec

【讨论】:

    猜你喜欢
    • 2013-11-25
    • 1970-01-01
    • 2020-07-25
    • 2012-06-07
    • 2011-05-09
    • 2014-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多