Discussion:
Sobre hacer un shell en c
(demasiado antiguo para responder)
|||RIP|||
2007-05-14 12:46:04 UTC
Permalink
Hola!

Acabo de hacer un shell en c muy basico y no tengo ni idea de como hacer
que "entienda" los comando en segundo plano, '&'.

Hay alguna web en donde haya algun ejemplo o sabeis algo?

Saludos y gracias!
J.A. Gutierrez
2007-05-14 14:49:55 UTC
Permalink
|||RIP||| <***@gmail.com> wrote:
: Hola!

: Acabo de hacer un shell en c muy basico y no tengo ni idea de como hacer
: que "entienda" los comando en segundo plano, '&'.

De hecho, eso es lo mas facil; que los haga en segundo plano
(por lo menos si te desentiendes de ellos).
Es mas bien al reves, hay que complicarse la vida para que
sean en "foreground".

: Hay alguna web en donde haya algun ejemplo o sabeis algo?

http://giga.cps.unizar.es/~spd/src/system/she/
--
PGP and other useless info at \
http://webdiis.unizar.es/~spd/ \
finger://daphne.cps.unizar.es/spd \ Timeo Danaos et dona ferentes
ftp://ivo.cps.unizar.es/pub/ \ (Virgilio)
Eduardo Villanueva Che
2007-05-14 14:56:52 UTC
Permalink
Post by |||RIP|||
Hola!
Hola,
Post by |||RIP|||
Acabo de hacer un shell en c muy basico y no tengo ni idea de como hacer
que "entienda" los comando en segundo plano, '&'.
Hay alguna web en donde haya algun ejemplo o sabeis algo?
No se como estarás haciendo la shell, pero para hacer una shell simple te
debería bastar con esto:

man 3 execvp (o cualquiera de sus hermanos)
man 3 fork
man 3 wait

Ejecutar algo en segundo plano es fácil, el padre no espera al hijo y ya
está.
Post by |||RIP|||
Saludos y gracias!
Saludos, y de nada ;)
|||RIP|||
2007-05-14 21:43:30 UTC
Permalink
==========================================================================

hijo=fork();
switch (hijo) {
case -1:
perror("ERROR!");
exit(-1);
case 0:
execvp(resultado2[0], &resultado2[0]);
perror("ERROR!");
exit(e);
default:
if (ampersand != 1) {
WEXITSTATUS(e);
hijoMuerto=wait(&e);
printf("\nHOlaaaa\n");
// exit(0);
}

}
==========================================================================


La variable resultado2 la he teatado antes con strtok.
Para el comando que introduzco en mi prompt tengo una funcion que si
detecta un & lo elimina y pone a 1 la variable ampersand.

Los comando en mi shell funcionan pero cuando pongo uno en segundo plano
todos los que vayan detrás se ejecutarán en segundo plano también.
Para evitar esto al principio del bucle inicializo la variable ampersand
a 0 pero no me va.

Alguna idea?

Muchas gracias de antemano!
|||RIP|||
2007-05-15 13:13:08 UTC
Permalink
Buenas de nuevo grupo.

Os adjunto el codigo de mi shell. Lo he probado en el ordenador dnd debe
funcionar que es un IRIX y la funcion strtok no la soporta me da
warnings al compilar y al ejecutar introduzco cualquier palabra y me
pone Segmentation fault.

Podeis echarme un mano?

Saludos

===========================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define BLANCO " "
#define FIN "FIN"

int hayAmpersand(char cadena[]);

int main (int argc, char *argv[]) {
char comando[]="";
char ruta[5]="/bin/"; // No se puede cambiar de sitio
char resultado[]="";
char *resultado2[25];
int e, i, ampersand;
pid_t hijo, hijoMuerto;

while(1) {

// Vacio las cadenas al inicio de cada bucle
comando[0] = '\0';
resultado[0] = '\0';
resultado[1] = '\0';
resultado2[0] = '\0';
ampersand = 0;

printf("#@> ");
scanf("\n%[^\n]", comando);

if (strcmp(comando, FIN) == 0) return(0); // Si son iguales sale del
programa

if (hayAmpersand(comando) == 1) ampersand = 1;

// Convertimos una ruta relativa en absoluta
if (strncmp(comando, ruta, 5) == 0) {
strcat(resultado, comando);
} else {
strcat(resultado, ruta);
strcat(resultado, comando);
}

// printf("\nCCC %s.\n", comando);

//== Cadenas ==========================================================
// Sacamos la primera palabra de la cadena
resultado2[0] = strtok(resultado, BLANCO);

// Sacamos la otras palabras de la cadena
i=1;
while((resultado2[i] = strtok(NULL, BLANCO)) != NULL) i++;
//== Fin Cadenas ======================================================

hijo=fork();
switch (hijo) {
case -1:
perror("ERROR!");
exit(-1);
case 0:
execvp(resultado2[0], &resultado2[0]);
perror("ERROR!");
exit(e);
default:
if (ampersand != 1) {
WEXITSTATUS(e);
hijoMuerto=wait(&e);
printf("\nHOlaaaa\n");
// exit(0);
}

}
}
return (0);
}

int hayAmpersand(char cadena[]) {
int j=0;
int hay=0;

for (j=0; j<=strlen(cadena); j++) {
if (cadena[j] == '&') {
cadena[j] = cadena[j+1];
hay=1;
return(hay);
}
}
return(hay);
}
===========================================================
Oscar Garcia
2007-05-15 13:22:05 UTC
Permalink
Post by |||RIP|||
char comando[]="";
Eso puede crearte problemas.

Es equivalente a:
char comando[1] = "";

¿Realmente sólo vas a usar un carácter? (el nulo para finalizar la
cadena, ni siquiera da para nada más).

Mejor hacer algo como:
char comando[2048] = "";

Un saludo.
--
Óscar Javier García Baudet
LinaresDigital
Oscar Garcia
2007-05-15 13:32:30 UTC
Permalink
Post by |||RIP|||
int hayAmpersand(char cadena[]) {
int j=0;
int hay=0;
for (j=0; j<=strlen(cadena); j++) {
if (cadena[j] == '&') {
cadena[j] = cadena[j+1];
hay=1;
return(hay);
Directamente: "return 1;"
Post by |||RIP|||
}
}
return(hay);
Directamente "return 0;"
Post by |||RIP|||
}
Creo que sería mejor algo como:

int hayAmpersand (char *cadena) {
return strchr (cadena, '&')?1:0;
}

o "return (strchr (cadena, '&') != NULL)?1:0;".
o 'return (strstr (cadena, "&") != NULL)?1:0;'.
o memchr (cadena, '&', strlen (cadena))
etc...

Voy a compilarlo haciendo unos arreglos para ver qué puede estar
fallándote (a parte de esas cadenas extrañas).

Saludos.
--
Óscar Javier García Baudet
LinaresDigital
|||RIP|||
2007-05-15 13:46:37 UTC
Permalink
Post by Oscar Garcia
Voy a compilarlo haciendo unos arreglos para ver qué puede estar
fallándote (a parte de esas cadenas extrañas).
Muchisimas gracias!
Oscar Garcia
2007-05-15 13:46:57 UTC
Permalink
Post by |||RIP|||
Buenas de nuevo grupo.
Os adjunto el codigo de mi shell. Lo he probado en el ordenador dnd debe
funcionar que es un IRIX y la funcion strtok no la soporta me da
warnings al compilar y al ejecutar introduzco cualquier palabra y me
pone Segmentation fault.
Podeis echarme un mano?
Te ayudaremos mejor si nos pegas el warning exacto. Lo he compilado con
-Wall y no me ha dado ningún warning con gcc (gcc version 4.0.3).
Post by |||RIP|||
// Vacio las cadenas al inicio de cada bucle
comando[0] = '\0';
resultado[0] = '\0';
resultado[1] = '\0';
resultado2[0] = '\0';
ampersand = 0;
También:
*comando = *resultado = ampersand = 0;

Por cierto... ¡¡ojo!!

¡¡No puedes hacer resultado2[0] = '\0'!!

¡¡resultado2 es un arreglo (array) de punteros que inicialmente no están
inicializados a ninguna zona de memoria!!

Si haces eso posiblemente estés escribiendo en un posición de memoria al
azar y posiblemente incorrecta (posiblemente te provoque el volcado de
memoria).

Otro saludo. Disculpa que te lo haya dividido en tres comentarios.
--
Óscar Javier García Baudet
LinaresDigital
|||RIP|||
2007-05-15 14:02:16 UTC
Permalink
Con lo de las cadenas ya he solucionado algunos problemillas que tenia.
Pense que al meter variable[]="" tenia tamaño ilimitado.

Los warnings que apunte esta mañana son:
- hijoMuerto y ampersand dice que no estan usadas
- WEXITSTATUS(e); dice que no tiene efecto

Al ejecutarlo cuando meto algun comando correcto o no correcto me dice
que Segmentation fault y me saca del programa.

Pero si las lineas que contienen la funcion strtok las pongo entre
comentarios entonces no me da ningun fallo al compilar pero claro como
no he "partido" en palabra la frase que metro en mi prompt todo lo que
mete no vale para nada.

La version del IRIX es la ultima que hay.

Saludos y muchas gracias
Oscar Garcia
2007-05-15 14:03:38 UTC
Permalink
Post by |||RIP|||
Con lo de las cadenas ya he solucionado algunos problemillas que tenia.
Pense que al meter variable[]="" tenia tamaño ilimitado.
- hijoMuerto y ampersand dice que no estan usadas
- WEXITSTATUS(e); dice que no tiene efecto
Lo mejor es que nos vuelques directamente los mensajes.
Post by |||RIP|||
Al ejecutarlo cuando meto algun comando correcto o no correcto me dice
que Segmentation fault y me saca del programa.
Tiene pinta de ser por los strtok... se puede implementar con strchr..
si quieres ahora te implemento un posible solución.
Post by |||RIP|||
Pero si las lineas que contienen la funcion strtok las pongo entre
comentarios entonces no me da ningun fallo al compilar pero claro como
no he "partido" en palabra la frase que metro en mi prompt todo lo que
mete no vale para nada.
La version del IRIX es la ultima que hay.
Prueba a compilar con -Wall para que salgan todos los warnings.
Post by |||RIP|||
Saludos y muchas gracias
De nada.
--
Óscar Javier García Baudet
LinaresDigital
|||RIP|||
2007-05-15 14:19:53 UTC
Permalink
Post by Oscar Garcia
Lo mejor es que nos vuelques directamente los mensajes.
El jueves que me toca laboratorio los escribo tal cual me salen
Post by Oscar Garcia
Tiene pinta de ser por los strtok... se puede implementar con strchr..
si quieres ahora te implemento un posible solución.
Te estaria muy agradecido
Post by Oscar Garcia
Prueba a compilar con -Wall para que salgan todos los warnings.
El jueves lo hago.

Saludos y muchas gracias
Oscar Garcia
2007-05-15 14:20:47 UTC
Permalink
Post by Oscar Garcia
Tiene pinta de ser por los strtok... se puede implementar con strchr..
si quieres ahora te implemento un posible solución.
Así con las prisas:

#include <stdio.h>
#include <string.h>

int main () {
char cadena[] = "Esta es una prueba de busqueda", *t, *token[12];
int i = 0, n;

for (t = token[0] = cadena; (t = strchr (t, ' ')) != NULL;) {
*t = 0;
token[++i] = ++t;
printf ("%s\n", t);
}
for (n = 0; n <= i; n++) {
printf ("%s\n", token[n]);
}
return 0;
}

Saludos.
--
Óscar Javier García Baudet
LinaresDigital
|||RIP|||
2007-05-15 14:32:08 UTC
Permalink
Como para hacerlo yo...

Muchas gracias de nuevo!
J.A. Gutierrez
2007-05-16 14:26:26 UTC
Permalink
|||RIP||| <***@gmail.com> wrote:

: La version del IRIX es la ultima que hay.

???
La ultima depende del hardware, del nivel de revision y
si se utiliza la rama _f o _m, asi que eso no es decir
mucho.
Tampoco estaria de mas indicar la version y opciones del
compilador; aunque en este caso no creo que ninguno de
estos factores influya...
--
PGP and other useless info at \
http://webdiis.unizar.es/~spd/ \
finger://daphne.cps.unizar.es/spd \ Timeo Danaos et dona ferentes
ftp://ivo.cps.unizar.es/pub/ \ (Virgilio)
J.A. Gutierrez
2007-05-16 14:25:08 UTC
Permalink
|||RIP||| <***@gmail.com> wrote:
: Buenas de nuevo grupo.

: Os adjunto el codigo de mi shell. Lo he probado en el ordenador dnd debe
: funcionar que es un IRIX y la funcion strtok no la soporta me da

strtok es totalmente estandar y funciona perfectamente en IRIX

: warnings al compilar y al ejecutar introduzco cualquier palabra y me

Pues tendras que hacerle caso al compilador y corregir lo
que te dicen los warnings

Un consejo: prescinde de la costumbre de utilizar comentarios
de C++ si pretendes que tu codigo sea portable.

: pone Segmentation fault.

: Podeis echarme un mano?

: Saludos

: ===========================================================
: #include <stdio.h>
: #include <stdlib.h>
: #include <string.h>
: #include <unistd.h>
: #include <sys/types.h>
: #include <sys/wait.h>

: #define BLANCO " "
: #define FIN "FIN"

: int hayAmpersand(char cadena[]);


: char resultado[]="";

: // Convertimos una ruta relativa en absoluta
: if (strncmp(comando, ruta, 5) == 0) {
: strcat(resultado, comando);
: } else {
: strcat(resultado, ruta);
: strcat(resultado, comando);
: }

strcat sobre una cadena que no tiene espacio reservado?
--
PGP and other useless info at \
http://webdiis.unizar.es/~spd/ \
finger://daphne.cps.unizar.es/spd \ Timeo Danaos et dona ferentes
ftp://ivo.cps.unizar.es/pub/ \ (Virgilio)
|||RIP|||
2007-05-16 14:58:32 UTC
Permalink
Post by J.A. Gutierrez
Un consejo: prescinde de la costumbre de utilizar comentarios
de C++ si pretendes que tu codigo sea portable.
Me la apunto.
Post by J.A. Gutierrez
strcat sobre una cadena que no tiene espacio reservado?
Ya puse todas las cadenas con espacio reservado.

Muchas gracias!!!
your name
2007-05-20 17:40:47 UTC
Permalink
Post by |||RIP|||
Hola!
Acabo de hacer un shell en c muy basico y no tengo ni idea de como hacer
que "entienda" los comando en segundo plano, '&'.
Hay alguna web en donde haya algun ejemplo o sabeis algo?
Saludos y gracias!
yo tengo que haccer un shell en c y debe autocompletar cuando presione
el tabulador sabes como hacer esto
Oscar Garcia
2007-05-20 20:47:05 UTC
Permalink
Post by your name
Post by |||RIP|||
Acabo de hacer un shell en c muy basico y no tengo ni idea de como
hacer
Post by |||RIP|||
que "entienda" los comando en segundo plano, '&'.
yo tengo que haccer un shell en c y debe autocompletar cuando presione
el tabulador sabes como hacer esto
1.- Bucle mientras tengas directorios en el PATH si no es una ruta
absoluta lo que estamos buscando.
2.- Por cada PATH comprobar cada uno de los archivos de dicho directorio
que tengan permisos de ejecución.
3.- Por cada uno de los archivos ejecutables de cada directorio
compruebas con un strncmp compruebas la coincidencia de la cadena
introducida con cada archivo.

Puede ser que estemos haciendo referencia a una ruta absoluta, en ese
caso hacemos lo mismo pero sólo con esa ruta, y no las del PATH.

4.- En caso de ser un directorio lo que hemos encontrado añadimos lo que
falte de directorio y un carácter '/' al final de la cadena.

Puede haber más casos.. si los planteas te podemos ayudar a solucionarlo.

Espero que eso te ayude.

Un saludo.
--
Óscar Javier García Baudet
LinaresDigital
Pascal Bourguignon
2007-05-20 21:18:30 UTC
Permalink
Post by your name
Post by |||RIP|||
Hola!
Acabo de hacer un shell en c muy basico y no tengo ni idea de como
hacer
Post by |||RIP|||
que "entienda" los comando en segundo plano, '&'.
Hay alguna web en donde haya algun ejemplo o sabeis algo?
Saludos y gracias!
yo tengo que haccer un shell en c y debe autocompletar cuando presione
el tabulador sabes como hacer esto
Pues, si no debes al mismo tiempo buscar algo de arena y fundir tu
proprio procesador, esto se suele hacer usando una biblioteca como
readline. http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html
--
__Pascal Bourguignon__ http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.
|||RIP|||
2007-05-21 07:28:10 UTC
Permalink
Post by your name
yo tengo que haccer un shell en c y debe autocompletar cuando presione
el tabulador sabes como hacer esto
Ufff, que va! Lo máximo que hice al final fue lo de los procesos en
segundo plano. Lo que pides se me va de madre.

Cuando haga la presentación en clase pegaré aquí el código de la shell
por si le puede valer a alguien, que no creo... Quizás tú también
podrías pegarlo, me gustaría saber como has coseguido lo del TAB.

Saludos
|||RIP|||
2007-07-11 14:13:08 UTC
Permalink
Hola!

Lo prometido es deuda.

Aquí cuelgo el código de mi humilde shell que no hubiera podido hacer
sin vuestra ayuda. Os lo agradezco.

Al final aprobe la asignatura de Sistemas Operativos.

De nuevo, gracias!

==============================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAXIMO 2048
#define BLANCO " "
#define FIN "FIN"
#define MSG_ERROR "ERROR!"
#define PROMPT "\n#@> "

int hayAmpersand(char cadena[]);

int main (int argc, char *argv[]) {
char comando[MAXIMO]="";
char *palabras[MAXIMO];
int e, i, ampersand;
pid_t hijo, hijoMuerto;

while(1) {

// Vacio las cadenas al inicio de cada bucle
comando[0] = '\0';
ampersand = 0;

printf(PROMPT);
scanf("\n%[^\n]", comando); // Leemos la cadena entera

if (strcmp(comando, FIN) == 0) return(0); // Si son iguales
sale del programa

if (hayAmpersand(comando) == 1)
ampersand = 1;

//== Cadenas
==========================================================
// Sacamos la primera palabra de la cadena
palabras[0] = strtok(comando, BLANCO);

// Sacamos la otras palabras de la cadena
i=1;
while((palabras[i] = strtok(NULL, BLANCO)) != NULL) i++;
//== Fin Cadenas
======================================================

hijo = fork();

switch (hijo) {
case -1:
perror(MSG_ERROR);
exit(-1);
case 0:
execvp(palabras[0], &palabras[0]);
perror(MSG_ERROR);
exit(e);
default:
if (ampersand != 1) {
hijoMuerto = 0;
while ((hijo != hijoMuerto) && (hijoMuerto != -1))
hijoMuerto = wait(&e);
}
}
}
return (0);
}

int hayAmpersand(char cadena[]) {
int j = 0;

for (j = 0; j <= strlen(cadena); j++) {
if (cadena[j] == '&') {
cadena[j] = cadena[j+1];
return(1);
}
}
return(0);
}

Loading...