提取 exec 函数的参数

Extracting arguments for an exec function

我正在尝试为学校设计一个项目,而且我已经非常接近了。目标是使用终端进行模拟,本质上是使用管道输入一系列命令并让它们正确执行。

下面列出了我当前的代码和输出,但主要要点是到目前为止我已经能够将命令和参数分开,但是当尝试在第 83 行使用 strcat 时,我感觉出现了分段错误。

我尝试添加的行是:

    strcat (allargs, print);
}
printf("\n %s -- ALLARGS\n ", allargs);

提取所有参数的字符串的最佳方法是什么?由于我正在寻找使用 execvp 或 execlp,有没有更好的方法来解决这个问题?

谢谢!

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <wait.h>
    #include <sys/types.h>
    #include <unistd.h>
    
    // count number of "|" in string
    int count_cmds(char *str)
    {
        int count = 1; // always will be 1 cmd
        for (int i = 0; i < strlen(str); i++)
        {
            if (str[i] == '|')
            {
                count++;
            }
        }
        return count;
    }
    
    char *get_token_at(char *command, size_t n, char *delimiter)
    {
        size_t position = 0;
        char *copy = strdup(command);
        char *token = strtok(copy, delimiter);
        char *output = NULL;
        while (token && position < n)
        {
            token = strtok(NULL, delimiter);
            position++;
        }
        if (token && position == n)
            output = strdup(token);
        free(copy);
        return output;
    }
    
    // trim whitespace
    char *trimwhitespace(char *str)
    {
        char *end;
        while (isspace(*str))
            str++;
        if (*str == 0)
            return str;
        end = str + strlen(str) - 1;
        while (end > str && isspace(*end))
            end--;
        // new end of string
        *(end + 1) = 0;
        return str;
    }
    // count spaces in a string
    int count_spaces(char *str)
    {
        int count = 0;
        for (int i = 0; i < strlen(str); i++)
        {
            if (str[i] == ' ')
            {
                count++;
            }
        }
        return count;
    }
    
    int fd[2];
    int x;
    int execc(char *command, int i)
    {
    
        printf("--- NEW CALL TO EXECC ---------------- COMMAND PASSED: %s \t\t\t\t\t\t ---- NUMBER PASSED: %d\n", command, i);
    
        char *text = trimwhitespace((get_token_at(command, i - 1, "|")));
        char *textargs = text;
        char *allargs = " ";
        for (int k = 0; k < count_spaces(textargs); k++)
        {
            char *print = trimwhitespace((get_token_at(textargs, k + 1, " ")));
            printf("\n %s -- TEXTARG\n ", print);
        }
        char *cmd_only = get_token_at(text, 0, " ");
        printf("\n %s -- cmd only\n ", cmd_only);
    
        int x = fork();
    
        if (x < 0)
        {
            perror("fork error");
            exit(1);
        }
        // parent
        if (x > 0)
        {
            printf("IN PARTENT -- wait for child\n");
            wait(&x);
            return x;
        }
        // child
        if (x == 0)
        {
            printf("NEW CHILD -- exec or call next \n");
            dup2(fd[0], STDIN_FILENO);
            if (i == 1)
            {
                dup2(fd[1], STDOUT_FILENO);
            }
    
            close(fd[0]);
            close(fd[1]);
            if (i == 1)
            {
                char *z1 = trimwhitespace((get_token_at(command, i - 1, "|")));
                printf(" i=1 ---------------- \n%s\n %s \n %s ", z1, z1, trimwhitespace((get_token_at(command, i - 1, " "), NULL)));
                // execlp(z1,z1, (trimwhitespace(get_token_at(command, i, " ")), NULL)); // if last command, exec
            }
            else
            {
                execc(command, --i); // if not last command, recurse
                char *z2 = trimwhitespace(get_token_at(command, i - 1, "|"));
                printf("i!=1 --------------------\n%s\n %s \n %s ", z2, z2, trimwhitespace((get_token_at(command, i - 1, " "), NULL)));
                // execlp(z2,z2, trimwhitespace((get_token_at(command, i, " "), NULL)));
            }
            // char* z3 = trimwhitespace(get_token_at(command, i-1, "|"));
            // printf("%s\n %s \n %s \n",z3,z3, trimwhitespace((get_token_at(command, i-1, " "), NULL)));
            // execlp(z3,z3, trimwhitespace((get_token_at(command, i, " "), NULL)));
        }
    }
    int main(int argc, char *argv[])
    {
        printf(" Enter Command>");
        char cmd[50];
        fgets(cmd, 50, stdin);
        int num_cmds = count_cmds(cmd);
        printf("\n");
        printf("Command count: %d\n", num_cmds);
        execc(cmd, num_cmds);
    
        pipe(fd);
        if (pipe(fd) == -1)
        {
            printf("Error pipe\n");
            exit(1);
        }
    }

./current Enter Command>ls -l | sort -r | grep -h

Command count: 3 --- NEW CALL TO EXECC ---------------- COMMAND PASSED: ls -l | sort -r | grep -h ---- NUMBER PASSED: 3

-h -- TEXTARG

grep -- cmd only IN PARTENT NEW CHILD --- NEW CALL TO EXECC ---------------- COMMAND PASSED: ls -l | sort -r | grep -h ---- NUMBER PASSED: 2

-r -- TEXTARG

sort -- cmd only IN PARTENT NEW CHILD --- NEW CALL TO EXECC ---------------- COMMAND PASSED: ls -l | sort -r | grep -h ---- NUMBER PASSED: 1

-l -- TEXTARG

ls -- cmd only IN PARTENT NEW CHILD

应该将allargs定义为字符数组,而不是指针,

像这样:

char allargs[64] = {0};