Search code examples
clinuxreallocstrtok

C - Trying to build a simple shell in linux and having trouble with strtok, realloc in a loop


Trying to build a shell implementation in linux for an assignment and am having trouble. I get the following error after running 3/4 times into the loop

* Error in `./1': realloc(): invalid next size: 0x000000000132c150 * Aborted (core dumped)

I have left parts of the code out as it's long and I know there's no issues with them. If there's other parts you need I can add them too. Thanks in advance :)

Note: argc and argv are global variables

int argc = 0;
char **argv = NULL; 

int main(void)
{   
    while(1)
    {
        catch_signal();
        printDate();
        readCommand();

        if(strcmp(argv[0], "cd") == 0)
        {
            changeDirectory();
        }
        else
        {
            executeCommand();
        }
        //free(argv);
    }   
}

void readCommand()
{
    char *buffer = NULL;
    char *token = " ";
    char *p;

    size_t len = 0;
    int i = 0;

    getline(&buffer, &len, stdin);
    p = strtok(buffer, "\n");
    p = strtok(buffer, token);

    while(p)
    {
        argv = realloc(argv, sizeof(char *) * ++i);

        argv[i - 1] = p;
        p = strtok(NULL, token);
    }
    argc = i;
    argv[argc] = NULL;
    free(p);
}

void executeCommand()
{
    int status;
    pid_t pid;

    if((pid = fork()) < 0)
    {
        printf("Error: forking child process failed.");
    }
    else if(pid == 0)
    {
       if(execvp(argv[0], argv) < 0)
       {
           printf("error");
           exit(1);
       }
    }
    else
    {
       while(wait(&status) != pid);
    }
}

Solution

  • You are reallocating the argv array 1 pointer too short. There is not enough space for the final NULL pointer. Consider replacing the while(p) loop with this code:

    if (!p) {
        /* deal with empty command line */
    }
    
    while (p) {
        argv = realloc(argv, sizeof(char *) * (i + 2));
        argv[i++] = p;
        p = strtok(NULL, token);
    }
    

    p should start as NULL if the user entered an actual command. But what if buffer contains an empty string or just a blank one? strtok will return NULL directly in these cases. You should ignore such command lines.