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.