Search code examples
clinuxforkwaitexecvp

Fork() and Wait() with execvp() in C


I'm am trying to use the fork method to call a different program and wait until it completes, I tried to check what is the problem and it seems that the wait function doesn't wait to the childReturns and it makes doesn't print the answer. (the assignment was to loop compare method until ctrl+c )

the program I call is a comparator that compares 2 strings.

the problem is that the wait func doesn't wait for the child the compile is GCC

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/wait.h>

#define LINELEN (80)

char *mygets(char *buf, int len);
char *progName(char *prog);
int main(int argc, char *argv[])
{
    char *args[3];
    char str1[LINELEN + 1];
    char str2[LINELEN + 1];
    int childReturns;
    if (argc != 2)
        return -1;

    char *prog = progName(argv[1]);
    if (prog == NULL)
        return -1;
    args[0] = prog;
    while (1)
    {
        printf("Enter string:");
        if (mygets(str1, LINELEN) == NULL)
            break;
        printf("Enter  string:");
        if (mygets(str2, LINELEN) == NULL)
            break;
        args[1] = str1;
        args[2] = str2;
        int processId = fork();
        if (processId == 0)
            execvp(prog, args);
        else
        {
            wait(&childReturns); // Wait for the child
            printf("Child  code is %d\n", WEXITSTATUS(childReturns));
        }
    }
    free(prog);
    return 0;
}
char *progName(char *prog)
{
    char *filePath = (char *)malloc(strlen(prog) + 3);
    if (!filePath)
        return NULL;
    strcpy(filePath, "./");
    strcat(filePath, prog);
    return filePath;
}

char *mygets(char *buf, int len)
{
    char *retval;

    retval = fgets(buf, len, stdin);
    buf[len] = '\0';
    if (buf[strlen(buf) - 1] == 10) /* trim \r */
        buf[strlen(buf) - 1] = '\0';
    else if (retval)
        while (getchar() != '\n')
            ; /* get to eol */

    return retval;
} ```

Solution

  • As Jonathan Leffler said the problem was with the args, execvp() needs that the array off args has in the end NULL.

    and that fixed the problem.

    the Right code :

        char str1[LINELEN + 1];
        char str2[LINELEN + 1];
        int childReturns = 1;
        if (argc != 2)
            return -1;
    
        char *prog = progName(argv[1]);
        if (prog == NULL)
            return -1;
        char *args[4];
        args[3] = NULL;
        args[0] = prog;
        while (1)
        {
            printf("Enter string:");
            if (mygets(str1, LINELEN) == NULL)
                break;
            printf("Enter  string:");
            if (mygets(str2, LINELEN) == NULL)
                break;
            args[1] = str1;
            args[2] = str2;
            int processId = fork();
            if (processId == 0)
            {
                execvp(prog, args);
            }
            else
            {
                wait(&childReturns); // Wait for the child
                printf("Child  code is %d\n", WEXITSTATUS(childReturns));
            }
        }
        free(prog);
        return 0;```