Home > other >  Extracting arguments for an exec function
Extracting arguments for an exec function

Time:04-02

I'm trying to figure out a project for school and I'm pretty close. The goal is to emulate using a terminal, essentially inputting a series of commands with pipes and having them execute correctly.

My current code and output is listed below but the main gist is that I have been able to separate commands and arguments thus far, but when attempting to use an strcat on line 83, I feel to get a segmentation fault.

The lines I attempted to add were:

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

What would be the best way to extract a string of all the arguments? As I'm looking to use either execvp or execlp, would there be a better way to go about this?

Thanks!

    #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

CodePudding user response:

should define allargs as a char array, not a pointer,

Like this:

char allargs[64] = {0};
  • Related