Home > Mobile >  What is the cause of my segmentation fault?
What is the cause of my segmentation fault?

Time:09-14

I have a school project which consists of reproducing the pipe operator between two commands that my corrector will choose as it pleases.

I managed to reproduce the pipe between two commands that I choose manually, with this code:

int main(void)
{
    pid_t   pid1;
    pid_t   pid2;
    int     fd[2];
    char    *argv1[] = {"/bin/cat", "algo.txt", NULL};
    char    *argv2[] = {"/bin/wc", "-l", NULL};

    if (pipe(fd) == -1)
        return (1);

    pid1 = fork();

    if (pid1 == -1)
        return (1);
    
    if (pid1 == 0)
    {
        dup2(fd[1], STDOUT_FILENO);
        close(fd[0]);
        close(fd[1]);
        execve(argv1[0], argv1, NULL);
    }
    
    pid2 = fork();
    
    if (pid2 == -1)
        return (1);
    
    if (pid2 == 0)
    {
        dup2(fd[0], STDIN_FILENO);
        close(fd[0]);
        close(fd[1]);
        execve(argv2[0], argv2, NULL);
    }
    
    close(fd[0]);
    close(fd[1]);

    waitpid(pid1, NULL, 0);
    waitpid(pid2, NULL, 0);

    return (0);
}

To execute two commands that we do not know in advance, I understood that I have to retrieve the binary files of the commands that I want to execute, and that they are in the PATH environment variable of the envp.

So here is my way of doing it:

  • Extract the PATH string from the envp with strnstr
  • Store what comes after “PATH=” in another string (the different paths of the binary files)
  • Store paths delimited by “:” in an **array with split
  • Add a “/” to each path to be able to check if they are accessible and executable with access() function later

My way of coding it:

int main(int argc, char *argv[], char **envp)
{
    (void)argc;
    (void)argv;
    
    char    *path;
    char    *tempo;
    char    **array_of_paths;
    int     i;
    int     j;

    path = NULL;
    tempo = NULL;
    array_of_paths = NULL;
    i = 0;

    while (envp[i] != NULL && envp[i][0] != '\0')
    {
        path = ft_strnstr(envp[i], "PATH=", 5);
        // path = "PATH=/mnt/nfs/homes/user/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"

        if (path)
        {
            path = ft_substr(path, 5, ft_strlen(path));
            break ;
        }
        i  ;
    }
    
    array_of_paths = ft_split(path, ':');
    
    while (array_of_paths[i])
    {
        tempo = array_of_paths[i];
        array_of_paths[i] = ft_strjoin(tempo, "/");
        free(tempo);
        i  ;        
    }

    i = 0;
    j = 0;

    while (array_of_paths[i])
    {
        while (array_of_paths[i][j])
        {
            printf("%d", array_of_paths[i][j]);
            j  ;
        }
        i  ;
    }

    return (0);
}

My split function :

char    *ft_strncpy(char *dest, const char *src, unsigned int n)
{
    unsigned int    i;

    i = 0;
    while (i < n && src[i])
    {
        dest[i] = src[i];
        i  ;
    }
    while (i < n)
    {
        dest[i] = '\0';
        i  ;
    }
    return (dest);
}

int ft_cntwrd(char const *s, char c)
{
    unsigned int    i;
    int             cntr;

    i = 0;
    cntr = 0;
    while (s[i])
    {
        while (s[i] == c)
            i  ;
        if (s[i] != '\0')
            cntr  ;
        while (s[i] && (s[i] != c))
            i  ;
    }
    return (cntr);
}

char    *ft_strndup(const char *s, size_t n)
{
    char    *str;

    str = (char *)malloc(sizeof(char) * n   1);
    if (!str)
        return (NULL);
    str = ft_strncpy(str, s, n);
    str[n] = '\0';
    return (str);
}

char    **ft_split(char const *s, char c)
{
    int     i;
    int     j;
    int     k;
    char    **tab;

    i = 0;
    k = 0;
    tab = (char **)malloc(sizeof(char *) * (ft_cntwrd(s, c))   1);
    if (!tab)
        return (NULL);
    while (s[i])
    {
        while (s[i] == c)
            i  ;
        j = i;
        while (s[i] && s[i] != c)
            i  ;
        if (i > j)
        {
            tab[k] = ft_strndup(s   j, i - j);
            k  ;
        }
    }
    tab[k] = NULL;
    return (tab);
}

Others :

size_t  ft_strlen(const char *s)
{
    int i;

    i = 0;
    while (s[i])
        i  ;
    return (i);
}

char    *ft_strcpy(char *dest, char *src)
{
    int i;

    i = 0;
    while (src[i])
    {
        dest[i] = src[i];
        i  ;
    }
    dest[i] = '\0';
    return (dest);
}

size_t  ft_strlcpy(char *dest, const char *src, size_t size)
{
    size_t  src_len;
    size_t  i;

    src_len = 0;
    while (src[src_len] != '\0')
        src_len  ;
    if (size == 0)
        return (src_len);
    i = 0;
    while (src[i] != '\0' && i < (size - 1))
    {
        dest[i] = src[i];
        i  ;
    }
    dest[i] = '\0';
    return (src_len);
}

char    *ft_strnstr(const char *big, const char *needle, size_t len)
{
    size_t  h;
    size_t  n;

    h = 0;
    if (needle[0] == '\0')
        return ((char *)big);
    while (big[h] != '\0')
    {
        n = 0;
        while (big[h   n] == needle[n] && (h   n) < len)
        {
            if (big[h   n] == '\0' && needle[n] == '\0')
                return ((char *)&big[h]);
            n  ;
        }
        if (needle[n] == '\0')
            return ((char *)big   h);
        h  ;
    }
    return (0);
}

char    *ft_strdup(const char *s)
{
    char    *dst;

    dst = (char *)malloc(ft_strlen(s)   1);
    if (!dst)
        return (NULL);
    return (ft_strcpy(dst, (char *)s));
}

char    *ft_strjoin(char const *s1, char const *s2)
{
    int     i;
    int     j;
    char    *str;

    i = 0;
    j = 0;
    str = (char *)malloc(sizeof(char) * (ft_strlen(s1)   ft_strlen(s2)   1));
    if (!str)
        return (NULL);
    while (s1[i])
    {
        str[i] = s1[i];
        i  ;
    }
    while (s2[j])
    {
        str[i   j] = s2[j];
        j  ;
    }
    str[i   j] = '\0';
    return (str);
}

char    *ft_substr(char const *s, unsigned int start, size_t len)
{
    char    *res;
    char    *src;
    size_t  reslen;

    if (!s)
        return (NULL);
    if (ft_strlen(s) < (size_t)start)
        return (ft_strdup(""));
    src = (char *)s   start;
    if (ft_strlen(src) < len)
        reslen = ft_strlen(src)   1;
    else
        reslen = len   1;
    res = malloc(reslen * sizeof(char));
    if (!res)
        return (NULL);
    ft_strlcpy(res, src, reslen);
    return (res);
}

I try to display my array to see if everything is fine but I have a segmentation fault and I don't understand where it comes from.

Do you have an idea ?

Small precision: I had to recode some functions of the GNU C Library in a previous project.

CodePudding user response:

I suggest you try to run the code in a debugger. gdb shows you were the problem is.

enter image description here

  • Related