Este proyecto es una implementación simple del comando de shell pipex
, que es similar a la redirección de tuberías en Unix (|
).
Queria empezar a construir y adquirir conocimientos haciendo unas pequeñas llamadas simples a ver si entendi lo que se explicaba en el manual
- crea una bifurcacion es decir una copia exacta(hijo) del programa(padre) y nos devuelve el id que podemos guardar en una variable entera en caso de error en la creacion del hijo nos devolvera -1
-
Espera a que el proceso hijo que le pasemos por argumento acabe
-
Si le pasamos el argumento
NULL
a wait espera a que cualquier hijo acabe -
Para demostrar esto tenemos un pequeño main
si quitas el wait y no esperas que el/los procesos hijos terminen y el padre acaba antes puede haber problemas en este caso:
-En este caso
int main()
{
int id =fork();
fork();
}
Se creara una bifurcacion para el proceso hijo y otra para el padre de locos y si lo llamamos otra vez ? todos tendran un nuevo proceso haciendo un efecto escalera bien chulo Volver al índice
- Es complicado y esta duro pero antes de ponerse a nada queria entender bien el funcionamiento de la funcion original primero veamos el comportamiento sin fork
int main()
{
#include <unistd.h>
#include <stdio.h>
#include "lib/get_next_line/get_next_line.h"
#include "lib/libft/libft.h"
int main()
{
char *line;
int fd[2];
char *str;
pipe(fd);
ft_putstr_fd("hola mundo\n", fd[1]);
if (get_next_line(fd[0], &str) == EXIT_SUCCESS)
printf("success\n");
else
printf("error\n");
printf("%s", str);
}
}
nakama@DESKTOP-FIDJ5EI:~/pipex$ ./a.out
hola mundo
- Pipe siempre va a necesitar 2 fd , para crear entrada y salida de datos 0 es entadas lo que hace es duplicar fd1 en fd0
- Pipe enlaza dos fd como entrada y salada
- Escribimos en el fd de entrada
- leemos del fd de salida
- imprimimos
-Ahora bien si hacemos un fork para tener dos procesos
-
tendremos los fd por duplicado y tanto para el padre como para el hijo tendremos los fd[0] y fd[1]
-
En este caso le digo al programa si esta en el proceso hijo cierra el fd[0] ya que no vamos a leer nada , despues de escribir cierro el fd de salida
-
si es el caso de estar en el proceso padre cierra el fd de salida , lee lo que hay en el fd de entrada que para el es el [0] imprime lo que conseguimos y cerramos el fd de entrada.
-
la funcion execve ejecuta un programa
int execve(const char *pathname, char *const _Nullable argv[],char *const _Nullable envp[])
-
El primer parametro necesita la ruta en el sistema del programa;
-
En este momento que estoy aun en plena investigación(02/01/2024 05:08 am) se me ocurrido una pequeña funcion para esto que no sera la difinitiva pero para testear
char *create_path(char *arg) { char *path = "/bin/"; char *tmp; tmp = ft_strjoin(path, arg); return (tmp); }
-
nakama@DESKTOP-FIDJ5EI:~/pipex$ ./a.out ls -l wc -l
./a.out
ls
-l
wc
-l
Ruta del programa 1 : /bin/ls
Ruta del programa 2 : /bin/wc
-
como lo que estoy probando esta todo dentro de bin es facil sacar la ruta
-
el segundo parametro de execve es el comando y los parametros, siempre debe acabar en null
-
el 3 es la variable de entorno
-
dup2(int oldfd, int newfd)
Hace que newfd sea la copia de oldfd en nuestro caso nos sirve para redirigir la salida del programa por la pipe usandoSTDOUT_FILENO
ySTDIN_FILENO
para la entrada o la salida
int main(int argc, char **argv, char **envp )
{
check_numargc(argc, argv);
char *path;
char *path2;
path=create_path(argv[1]);
path2=create_path(argv[3]);
//esto es para concatenar el path con el nombre del ejecutable
printf("Ruta del programa 1 : %s\n", path);
printf("Ruta del programa 2 : %s\n", path2);
int pid;
int fd[2];
pipe(fd);
pid = fork();
char *cmd1[] = {argv[1], argv[2], NULL};
char *cmd2[] = {argv[3], argv[4], NULL};
wait(NULL);
if (pid == 0)
{
close(fd[0]);
dup2(fd[1], STDOUT_FILENO);
close(fd[1]);
execve(path,cmd1, NULL);
}
else
{
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
execve(path2, cmd2, NULL);
}
return 0;
}
nakama@DESKTOP-FIDJ5EI:~/pipex$ ./a.out ls -l wc -l
./a.out
ls
-l
wc
-l
Ruta del programa 1 : /bin/ls
Ruta del programa 2 : /bin/wc
9
-
Pertenece a
<unistd.h>
-
Toma dos argumentos la ruta del archivo y el tipo de acceso que se quiere comprobar
-
el tipo de acceso puede ser una combinacion de las siguientes const
-
F_OK
: si existe el archivo -R_OK
: permiso de lectura -W_OK
: Permiso de escritura -X_OK
: Permiso de ejecucion
-
-
Devuelve 0 si el proceso tiene el acceso solicitado al archivo y -1 si no lo tiene o ocurrre algun error
int main()
{
char *path = "/bin/lss";
if (access(path, X_OK) == 0)
printf("existe\n");
else
printf("no existe\n");
if (access("/etc/passwd", R_OK) == 0) {
printf("El archivo se puede leer.\n");
} else {
printf("El archivo no se puede leer.\n");
}
if (access("/etc/passwd", W_OK) == 0)
printf("El archivo se puede escribir.\n");
else
printf("El archivo no se puede escribir.\n");
return (0);
}
sin sudo
nakama@DESKTOP-FIDJ5EI:~/pipex$ ./a.out
no existe
El archivo se puede leer.
El archivo no se puede escribir.
con sudo
nakama@DESKTOP-FIDJ5EI:~/pipex$ sudo ./a.out
no existe
El archivo se puede leer.
El archivo se puede escribir.