cexecexecvp

Create an array of null-terminated strings from standard input


I'm trying to read in from standard input and use the input in execvp().

at the moment I am recieving many warnings such as

warning: assignment makes integer from pointer without a cast [-Wint-conversion] commands[i]=NULL;

warning: passing argument 1 of ‘execvp’ makes pointer from integer without a cast [-Wint-conversion] execvp(commands2[0],commands2);

# include <stdlib.h>
# include <stdio.h>
# include <unistd.h>
# include <string.h>
# include <sys/wait.h>
# define BUF_SIZE 256
    

int main()
{
    char buffer[BUF_SIZE];
    char *commands;
    char *commands2;


    fgets(buffer, BUF_SIZE, stdin);
    commands = strtok(buffer, " ");

    printf("%d",commands[0]);
    while( commands != NULL ) 
    {
      printf( "%s", commands );
    
      commands = strtok(NULL, " ");
    }
    commands = realloc(commands,1);

    int i = strlen(commands);
    printf("%d",i);
    commands[i]=NULL;

    fgets(buffer, BUF_SIZE, stdin);
    commands2 = strtok(buffer, " ");
    
    while( commands2 != NULL ) 
    {
        commands2 = strtok(NULL, " ");
    }
    commands2 = realloc(commands2,1);
    
    int z = strlen(commands2);
    printf("%d",z);
    commands2[z]=NULL;

    int my_pipe[2];

    if (pipe(my_pipe) == -1)
    {
        perror("cannot create pipe\n");
    }

    pid_t my_pid;

    my_pid = fork();

    if (my_pid < 0)
    {
        perror("Failed fork\n");
    }

    if (my_pid > 0)
    {
        close(my_pipe[1]);
        dup2(my_pipe[0], 0);
        close(my_pipe[0]);

        wait(NULL);
        execvp(commands2[0],commands2); 
    }
    else
    {
        close(my_pipe[0]);   
        dup2(my_pipe[1], 1);
        close(my_pipe[1]);

        execvp(commands[0],commands);
    }
}

Solution

  • There is first a confusion on using pointers. char *commands is a pointer (to a char). commands[i] is a char (not a pointer). NULL is a pointer (of type void *, and of value 0) So, you can't write commands[i]=NULL. But you can do commands[i]='\0' (the char of value 0).

    Then there is probably a confusion about the vector expected by execvp(). This vector (the v of execvp) is an array (of one dimension) of pointers. Each of those pointers is a char *, a string, a word. This vector of pointers ends with the pointer NULL.

    So, may I propose the following simple code (without fork() and pipe()):

        #include <stdlib.h>
        #include <stdio.h>
        #include <unistd.h>
        #include <string.h>
    
        #define BUF_SIZE 256
        #define MAX_ARGS 256
            
        int main() {
            char buffer[BUF_SIZE];
            char *argv[MAX_ARGS];
            int argc = 0;
    
            fgets(buffer, BUF_SIZE, stdin);
            
            for ( argv[argc] = strtok(buffer, " \t\n"); 
                  argv[argc] != NULL; 
                  argv[++argc] = strtok(NULL, " \t\n") ) {
              printf("argv[%d]=\"%s\"\n", argc, argv[argc]);
            }
            argv[argc] = NULL;
    
            execvp(argv[0], argv); 
            
            perror(argv[0]);
            exit(EXIT_FAILURE);
        }