0% encontró este documento útil (0 votos)
169 vistas

Mini Shell

El documento describe un programa en C que implementa un shell mínimo con 7 comandos. El programa establece variables y estructuras de datos para almacenar comandos, parámetros y descriptores de ficheros/tuberías. Usa procesos hijos y tuberías para ejecutar comandos en paralelo y redirigir su entrada/salida. Los comandos incluyen mostrar información del sistema, filtrar datos de ficheros y comunicar procesos a través de tuberías.

Cargado por

sarii93
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como TXT, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
169 vistas

Mini Shell

El documento describe un programa en C que implementa un shell mínimo con 7 comandos. El programa establece variables y estructuras de datos para almacenar comandos, parámetros y descriptores de ficheros/tuberías. Usa procesos hijos y tuberías para ejecutar comandos en paralelo y redirigir su entrada/salida. Los comandos incluyen mostrar información del sistema, filtrar datos de ficheros y comunicar procesos a través de tuberías.

Cargado por

sarii93
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como TXT, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 11

#include <stdio.

h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
//atributo donde se almacenar el comando introducido por teclado
char cadena [155];
//funcioque se ejecuta al detectar CTRL+Z
void func(){
printf("\nExecuting command: %s\n",cadena);
}
//programa principal
int main(int argc,char *argv[]){
//variable para mantener el bucle infinito
int a=2;
/*variables que almacenaran otros parametros necesarios para ciertos comandos
en general constituyen el nombre de archivos de texto*/
char aux [155];
char aux2 [155];
pid_t pid;
/*array que almacenara los distintos parametros de cada comando para poder ejecu
tar
el comando execvp*/
char *cad[3];
//tuberias
int tuberia1[2];
int tuberia2[2];
int status;
//variables para abrir archivos de texto en determinados comandos
int fd;
int fd2;
//seal a la espera de recibir la combinacion CTRL+Z
signal(SIGTSTP, func);
while(a==2){
//para cada iteracion del bucle imprimimos el mensaje de minishell y cap
turamos el comando introducido a continuacion
printf("minishell>");
scanf("%s", cadena);

//comando 1
if(strcmp(cadena,"command1")==0){
//creamos el hijo
pid=fork();
switch(pid){
case 0:
//en el hijo se establecen los valores del array cad, el cual
//contenia los parametros usados para la ejecucion del comando
signal(SIGTSTP, SIG_IGN);
cad[0]="uptime";
cad[1]=NULL;
execvp("uptime",cad);
//si hay algun error en la ejecucion se imprimira el siguiente m
ensaje
perror("ERROR DEL EXECVP");
return -1;
case -1:
//si ha habido algun error en torno a la ejecucion del comando f
ork
perror("ERROR DEL FORK");
return -1;
default:
//el padre esperara a que el hijo acabe su ejecucion
while(pid != wait(&status));
}
}
//comando 2
if(strcmp(cadena,"command2")==0){
//creamos el hijo
pid=fork();
switch(pid){
case 0:
signal(SIGTSTP, SIG_IGN);
//se establecen los parametros del comando en el array cad
cad[0]="uname";
cad[1]="-a";
cad[2]=NULL;
//se ejecuta el comando comprobando errores si los hay
execvp("uname",cad);
perror("ERROR DEL EXECVP");
return -1;
case -1:
perror("ERROR DEL FORK");
return -1;
default:
while(pid != wait(&status));
}
}
//comando que provoca que se salga del bucle terminando la ejecucion del
programa

if(strcmp(cadena,"exit")==0){
a=0;
}
//comando 3
if(strcmp(cadena,"command3")==0){
//guardamos el valor del fichero en el cual escribiremos
//la salida del comando, en concreto, la informacion de la CPU
scanf("%s", aux);
pid=fork();
switch(pid){
case 0:
signal(SIGTSTP, SIG_IGN);
cad[0]="cat";
cad[1]="/proc/cpuinfo";
cad[2]=NULL;
//abrimos el fichero
fd=open(aux ,O_CREAT | O_WRONLY, 0777);
if(fd==-1){
perror("error al abrir el fichero\n");
return -1;
}
/*cerramos la salida estandar y a continuacion duplicamos
el descriptor del fichero en la entrada estandar,
para que asi, al ejecutar el comando, la informacion de
la tuberia se escriba directamente en el fichero*/
close(0);
dup2(fd,1);
//cerramos el fichero
close(fd);
//ejecutamos el comando
execvp("cat", cad);
perror("ERROR DEL EXECVP");
return -1;
case -1:
perror("ERROR DEL FORK");
return -1;
default:
while(pid != wait(&status));
}
}
//comando 4
if(strcmp(cadena,"command4")==0){
//guardamos el nombre del fichero del cual filtraremos los
//datos para sacar concretamente el modelo de procesador
scanf("%s", aux);
pid=fork();
switch(pid){
case 0:
signal(SIGTSTP, SIG_IGN);
//establecemos los parametros
cad[0]="grep";
cad[1]="model name";

cad[2]=NULL;
fd=open(aux, O_RDONLY);
if(fd==-1){
perror("error al abrir el fichero\n");
return -1;
}
//redirigimos el fichero a la variable estandar de salida
dup2(fd,0);
close(fd);
//ejecutamos el comando grep
execvp("grep", cad);
perror("ERROR DEL EXECVP");
return -1;
case -1:
perror("ERROR DEL FORK");
return -1;
default:
while(pid != wait(&status));
}
}
//comando 5
if(strcmp(cadena,"command5")==0){
//creacion de la tuberia
pipe(tuberia1);
//creacion de proceso hijo
pid=fork();
switch(pid){
case 0:
//proceso hijo ignora la seal ctrl+Z
signal(SIGTSTP, SIG_IGN);
//asignacion de parametros a la variable cad en este comando
cad[0]="cat";
cad[1]="/proc/cpuinfo";
cad[2]=NULL;
//redireccion de la salida a una tuberia
close(STDOUT_FILENO);
dup(tuberia1[1]);
close(tuberia1[1]);
close(tuberia1[0]);
//Cambio de la imagen del programa
execvp("cat", cad);
perror("ERROR DEL EXECVP");
return -1;
case -1:
// caso que controla que no se de un error en la ejecucion del
fork, en
//tal caso mostrara por pantalla el siguiente mensaje
perror("ERROR DEL FORK");
return -1;
default:
//el padre crea un segundo hijo que reciba la informacion de l
a tuberia
pid= fork();
switch(pid){

case 0:
//proceso hijo ignora la seal ctrl+Z
signal(SIGTSTP, SIG_IGN);
//asignacion de parametros a la variable cad en este comando
cad[0]="grep";
cad[1]="model name";
cad[2]=NULL;
close(STDIN_FILENO);
//redireccion de la entrada estandar a una tuberia
dup(tuberia1[0]);
close(tuberia1[0]);
close(tuberia1[1]);
//sustitucion de la imagen del programa
execvp("grep", cad);
perror("ERROR DEL EXECVP");
return -1;
case -1:
//caso que controla error en la ejecucion del fork()
perror("ERROR DEL FORK");
return -1;
default:
//el proceso padre cierra la tuberia y espera a la te
rminacion de los procesos
//hijos evitando que se queden huerfanos
close(tuberia1[0]);
close(tuberia1[1]);
while(pid!= wait(&status));
}
}
}
//comando6
if(strcmp(cadena,"command6")==0){
//se recibe por teclado el nombre del archivo
scanf("%s", aux);
//creacion de la tuberia
pipe(tuberia1);
//creacion del proceso hijo
pid=fork();
switch(pid){
case 0:
//proceso hijo ignora la seal ctrl+Z
signal(SIGTSTP, SIG_IGN);
//asignacion de parametros a la variable cad en este comando
cad[0]="du";
cad[1]="-ha";
cad[2]=NULL;
//redireccion de la salida a la tuberia
close(STDOUT_FILENO);
dup(tuberia1[1]);
close(tuberia1[1]);
close(tuberia1[0]);
//sustitucion de la imagen del programa
execvp("du", cad);
perror("ERROR DEL EXECVP");
return -1;

case -1:
//caso que controla el error en el fork()
perror("ERROR DEL FORK");
return -1;
default:
//proceso padre crea un segundo hijo
pid= fork();
switch(pid){
case 0:
//proceso hijo ignora la seal ctrl+Z
signal(SIGTSTP, SIG_IGN);
//asignacion de parametros a la variable cad en este comando
cad[0]="grep";
cad[1]="4,0K";
cad[2]=NULL;
//apertura o creacion de fichero segun sea pertinente
fd=open(aux ,O_CREAT | O_WRONLY, 0777);
if(fd==-1){
perror("error al abrir el fichero\n");
return -1;
}
//redireccion de la salida a la tuberia
close(STDIN_FILENO);
dup(tuberia1[0]);
close(tuberia1[0]);
close(tuberia1[1]);
//redireccion de la salida a un fichero
close(STDOUT_FILENO);
dup(fd);
close(fd);
//sustitucion de la imagen del programa
execvp("grep", cad);
perror("ERROR DEL EXECVP");
return -1;
case -1:
//caso que controla el error de ejecucion del fork()
perror("ERROR DEL FORK");
return -1;
default:
//proceso padre se encarga de cerrar la tuberia y esperar l
a terminacion de la ejecucion de los hijos
close(tuberia1[0]);
close(tuberia1[1]);
while(pid != wait(&status));
}
}
}
//comando 7
if(strcmp(cadena,"command7")==0){
//se recibe por teclado los nombres de dos documentos
scanf("%s", aux);
scanf("%s", aux2);
//se crean dos tuberias
pipe(tuberia1);
pipe(tuberia2);

//creacion de un proceso hijo


pid=fork();
switch(pid){
case 0:
//proceso hijo ignora la seal ctrl+Z
signal(SIGTSTP, SIG_IGN);
//apertura o creacion de fichero segun sea pertinente
fd2= open(aux2, O_WRONLY | O_CREAT, 0777);
if(fd2==-1){
perror("error al abrir el fichero\n");
return -1;
}
//asignacion de parametros a la variable cad en este comando
cad[0]="du";
cad[1]="-ha";
cad[2]=NULL;
//redireccion de la salida a la tuberia
close(STDOUT_FILENO);
dup(tuberia1[1]);
//redireccion de la salida al fichero de salida de errores
close(STDERR_FILENO);
dup(fd2);
close(fd2);
close(tuberia1[1]);
close(tuberia1[0]);
close(tuberia2[1]);
close(tuberia2[0]);
//sustitucion de la imagen del programa
execvp("du", cad);
perror("ERROR DEL EXECVP");
return -1;
case -1:
//caso que controla el error del fork()
perror("ERROR DEL FORK");
return -1;
default:
//el proceso padre crea un segundo hijo
pid= fork();
switch(pid){
case 0:
//proceso hijo ignora la seal ctrl+Z
signal(SIGTSTP, SIG_IGN);
//apertura o creacion de fichero segun sea pertinente
fd2= open(aux2, O_WRONLY | O_CREAT, 0777);
if(fd2==-1){
perror("error al abrir el fichero\n");
return -1;
}
//asignacion de parametros a la variable cad en
este comando
cad[0]="grep";
cad[1]="4,0K";
cad[2]=NULL;
//redireccion de la entrada a una tuberia

close(STDIN_FILENO);
dup(tuberia1[0]);
close(tuberia1[0]);
close(tuberia1[1]);
//redireccion de la salida al fichero de errores
close(STDERR_FILENO);
dup(fd2);
close(fd2);
//redireccion de la salida a un fichero
close(STDOUT_FILENO);
dup(tuberia2[1]);
close(tuberia2[1]);
close(tuberia2[0]);
//sustitucion de la imagen del programa por el c
omando grep de unix
execvp("grep", cad);
perror("ERROR DEL EXECVP");
return -1;
case -1:
perror("ERROR DEL FORK");
return -1;
default:
//el proceso padre crea un tercer hijo que recibira la i
nformacion del segundo mediante una tuberia
pid= fork();
switch(pid){
case 0:
//proceso hijo ignora la seal ctrl+Z
signal(SIGTSTP, SIG_IGN);
//apertura o creacion de fichero segun s
ea pertinente
fd2= open(aux2, O_WRONLY | O_CREAT, 0777);
if(fd2==-1){
perror("error al abrir el fichero\n");
return -1;
}
//redireccion de la salida al fichero de errores
close(STDERR_FILENO);
dup(fd2);
close(fd2);
//apertura o creacion de fichero segun sea
pertinente
fd= open(aux, O_WRONLY | O_CREAT, 0777);
if(fd==-1){
perror("error al abrir el fichero\n");
return -1;
}

//asignacion de parametros a la variable cad en


este comando

cad[0]="cut";
cad[1]="-f2";
cad[2]=NULL;
//redireccion de la entrada a una tuberia
close(STDIN_FILENO);
dup(tuberia2[0]);
close(STDOUT_FILENO);
dup(fd);
close(fd);
close(tuberia2[0]);
close(tuberia2[1]);
close(tuberia1[1]);
close(tuberia1[0]);
//sustitucion de la imagen del programa por el
comando cut y los parametros almacenados en cad
execvp("cut", cad);
perror("ERROR DEL EXECVP");
return -1;
case -1:
perror("ERROR DEL FORK");
return -1;
default:
//el padre cierra las tuberias 1 y 2 y espera a
la finalizacion de los procesos hijos
close(tuberia1[1]);
close(tuberia1[0]);
close(tuberia2[1]);
close(tuberia2[0]);
while(pid!=wait(&status));
}
}
}
}
if(strcmp(cadena,"command8")==0){
//se recibe por teclado el nombres del documento
scanf("%s", aux);
//se crea una tuberia que comunicara los dos pro
cesos
pipe(tuberia1);
//el proceso padre crea un hijo
pid=fork();
switch(pid){
case 0:
//el proceso hijo ignora la seal
signal(SIGTSTP, SIG_IGN);
//asignacion de los parametros
cad[0]="du";
cad[1]="-ha";
cad[2]=NULL;
//redireccion de la salida a la

tuberia
close(STDOUT_FILENO);
dup(tuberia1[1]);
close(tuberia1[1]);
close(tuberia1[0]);
//sustitucion de la imagen del prog
rama
execvp("du", cad);
perror("ERROR DEL EXECVP");
return -1;
case -1:
perror("ERROR DEL FORK");
return -1;
default:
pid= fork();
switch(pid){
case 0:
//el proceso hijo trata la seal c
trl+Z recibida por teclado ignorandola
signal(SIGTSTP, SIG_IGN);
//asignacion de los paramet
ros
cad[0]="grep";
cad[1]="4,0K";
cad[2]=NULL;
//apertura o creacion de
l fichero segun sea pertinente
fd=open(aux ,O_WRONLY | O_CR
EAT, 0777);
if(fd==-1){
perror("error al abrir e
l fichero\n");
return -1;
}
//redireccion de la entrada
estandar a la tuberia (recibe de la tuberia)
close(STDIN_FILENO);
dup(tuberia1[0]);
close(tuberia1[0]);
close(tuberia1[1]);
//redireccion de la salida
a la tuberia
close(STDOUT_FILENO);
dup(fd);
close(fd);
//sustitucion de la imagen del p
rograma
execvp("grep", cad);
perror("ERROR DEL EXECVP");
return -1;
case -1:
//caso que trata el error en la
ejecucion del fork
perror("ERROR DEL FORK");
return -1;
default:

//imprime el pid del proceso pad


re
printf("[%d]\n", pid);
//cierra la tuberia
close(tuberia1[0]);
close(tuberia1[1]);
//al quitar el wait ya no esper
a y por lo tanto llama directamente a la minishell
}
}
}
}//fin while
return 0;
}

También podría gustarte