首页 > 解决方案 > 自制外壳问题

问题描述

我在 C 中的 linux 中制作了一个自定义终端,我正在尝试实现末尾的 '&' 应该在后台执行进程的功能,我制作了一个函数来剪切行末尾的 '&'工作,例如,如果我输入:

root@ivo-Surface-Pro-6:/home/ivo/Documents/SO1/Unix-Shell$echo hola &

回报是:

你好

但是,如果我尝试执行如下命令: 'ls -lt &​​' 它会返回:

root@ivo-Surface-Pro-6:/home/ivo/Documents/SO1/Unix-Shell$ls -lt &

ls: 无法访问 '': 没有这样的文件或目录

我的代码如下:

void parseAmp(char *str, char garbage) //Function to see if & is in there and delete it, only if it is last{

char *src, *dst;
int is = 0;
for (src = dst = str; *src != '\0'; src++)
{
    *dst = *src;
    if (*dst != garbage)
        dst++;
}
*dst = '\0';
//dst[strlen(dst) - 1] = '\0'; -> I thought of doing this, but doesnt work either}

int main(){ /* shell loop */

char command[COMMAND_BUFFER_SIZE];
char *tokens[TOKEN_BUFFER_SIZE], *tmp;
char *aux;

int token_Size = 0;

int pid;
int child_pid;
int status;
int result;

int flag;
int check;

int isPipe;
int output;
int input;

int isAmper;
int blk;

signal(SIGINT, handlerC);
signal(SIGTSTP, handlerZ);
signal(SIGQUIT, handlerBS);
signal(SIGCHLD, handlerZomb);

while (1)
{

    using_history();
    do
    {
        customPrompt();
        fgets(command, COMMAND_BUFFER_SIZE, stdin);
    } while (strlen(command) < 2);

    token_Size = 0;

    token_Size = parse(command, tokens, token_Size);

    if (ownCmdHandler(tokens))
    {
        continue;
    }

    if ((child_pid = fork()) == -1)
    {
        perror("Fork:");
        exit(1);
    }

    if (child_pid == 0)
    {
        isAmper = needs_amper(tokens, token_Size);
        output = needs_out_redir(tokens, token_Size);
        input = needs_in_redir(tokens, token_Size);
        isPipe = needs_pipe(tokens, token_Size);

        if (strcmp(tokens[0], "echo") == 0)
        {
            int i = 1;
            for (i; tokens[i]; i++)
            {
                printf("%s ", tokens[i]);
            }
        }

        flag = 0;

        if (output != -1)
        {
            redirect_output(tokens, output);
            tokens[output] = NULL;
            flag = 1;
        }

        if (input != -1)
        {
            redirect_input(tokens, input);
            tokens[input] = NULL;
            flag = 1;
        }

        if (isPipe != -1)
        {
            create_pipe(tokens, output, input, isPipe);
        }

        if (isAmper != -1)
        {
            parseAmp(tokens[isAmper], '&')l
            blk = 1;
        }

        if (flag || isPipe == -1)
        {
            for (int i = 0; tokens[i]; i++)
            {
                //printf("Toy: %s ", tokens[i]);
            }
            execvp(tokens[0], tokens);
            perror("Unkown Command:");
            exit(1);
        }
    }
    else
    {
        if (blk == 1)
        {
            printf("Waiting for child, pid = %d\n", pid);

            //result = waitpid(child_id, &status, 0);
        }
        else
        {
            pid = wait(&status);
        }
    }
}

return 0;}

我不明白为什么程序会在正确删除“&”时向我抛出该错误,我是否遗漏了什么?我能做些什么来纠正这个问题?

编辑:如果您想知道 need_amper 的作用,它会返回 & 的位置

static int needs_amper(char *tokens[], int size){
int position;
int i;

position = -1;
if (strcmp(tokens[size], "&") == 0)
{
    position = size;
}

return position;}

标签: clinuxterminal

解决方案


我设法解决了这个问题,这行得通:因为 isAmper 返回我的位置 '&' 是,我只是这样做:

tokens[isAmper] = NULL;

由于 execvp 在最后一行读取了一个空字符,因此它没有识别它,因此它需要 NULL 在字符末尾


推荐阅读