shell 在 c 中的实现问题

Problems with shell implementation in c

几天来一直致力于简单的 shell 实施。但我有两个问题:

1.When 你 运行 程序并键入命令,如“/bin/ls -l /usr/include”,然后按回车键,它将执行命令,但如果你随后输入几行程序仍将进入 execvp() 并输出“权限被拒绝”,因为它进入了 execvp 的错误处理,这是不应该发生的。 (我尝试了一些不同的方法来阻止它进入 main 中的 if() 但它们没有用。)

2.If你敲回车然后输入命令命令不会执行。 (我尝试释放 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] = '[=11=]';
        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] = '[=11=]';
}
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] = '[=12=]';
            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] = '[=12=]';
        }

你的 parse_cmdline() 函数应该测试空行,只包含 whote space 的行和以 # 和 return NULL 开头的注释行是这些案例。

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

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