Article View: es.comp.os.linux.programacion
Article #12191Re: fork(), pipes,... no mentero
From: Gonzalo Paniagua Javier
Date: Wed, 22 Aug 2001 21:54
Date: Wed, 22 Aug 2001 21:54
164 lines
7705 bytes
7705 bytes
Toni Martir <toni@no_spampala.com> escribi�:
No me ha llegado a�n el post original pero ...
Este mensaje es un poco largo. Que me perdone quien
no quiera perdonarme ;-).
>> Resulta que quiero hacer que mi programa controle a otro de
>> forma interactiva. Asi puedo ejecutar el wish y usar tcl/tk
>> desde C. Para eso quiero poder escribir al stdin del wish
>> y poder leer su stdout y stderr.
>> He leido en la documentacion de glibc que eso se puede hacer
>> con las funciones fork, pipe y dup, pero no consigo que funcionen.
>> Fork crea un proceso, pero no se como se controla ni como se hace
>> para crear las pipes.
>> A ver si alguien me explica mas o menos como funciona y puede
>> enviarme algun codigo fuente de ejemplo.
>>
Bueno, pues te mando aqu� c�digo comentado. Creo que hace alg�n
tiempo ya lo poste�, pero aqu� va de nuevo.
Juega con el c�digo para ir descubriendo c�mo funciona.
Lee el manual:
-pipe
-dup2 (f�jate en las diferencias con dup+close)
-fork
Tambi�n podr�a ser de ayuda mirar los fuentes de la libc, funci�n
popen() (es de m�s alto nivel que las anteriores).
Los include que hay que poner para el ejemplo (igual me sobra
o falta alguno):
-unistd.h
-signal.h
-stdio.h
-stdlib.h
-fcntl.h
Bien, en primer lugar, como el uso de pipes puede provocar
el lanzamiento de la se�al SIGPIPE que, por defecto, nos
saca el "Broken pipe" y termina el programa, la ignoramos:
signal(SIGPIPE, SIG_IGN);
Y aqu� el c�digo de la funci�n:
/* Esto recibe dos cadenas con los comando a ejecutar y deja la
salida de una tuber�a entre ambos en 'archivo'
NOTA: la funci�n CadenaError() es equivalente a strerror()
*/
#define SHELL "/bin/sh"
#define ARGS1 "-c", comando1
#define ARGS2 "-c", comando2
/* Descriptores de ficheros estandar para por si no est�n */
#define STDERR 2
#define STDOUT 1
#define STDIN 0
int OverWrite=0;
static void tuberia(char *comando1, char *comando2, char *archivo)
{
int fd1[2]; /* Para la tuberia */
int output; /* descriptor para el archivo de salida */
pid_t childpid; /* PID del proceso hijo */
struct stat File; /* Datos sobre el archivo de salida */
(void) pipe(fd1); /* comando1 envia su salida aqui */
childpid = fork();
if (childpid == 0){ /* Estamos en el hijo */
/* Cierra la parte de la tuberia que no nos interesa */
(void) close(fd1[0]);
/* Duplica la parte de la tuberia donde se escribe con STDOUT
* y STDERR */
(void) dup2(fd1[1], STDOUT);
(void) dup2(fd1[1], STDERR);
/* Ejecuto el primer comando */
if (execlp(SHELL,SHELL,ARGS1,NULL) == -1){
(void) fprintf(stderr,"%s %s\n",comando1,
CadenaError(errno));
(void) kill(getppid(),SIGTERM);
exit(EXIT_FAILURE);
}
(void) close(fd1[1]);
exit(EXIT_SUCCESS);
} /* hijo */
else { /* Esto es del padre */
/* Comprueba que no hay error en fork () */
if (childpid == -1) {
(void) fprintf(stderr,"pipe: error creando "
"proceso hijo\n");
exit(EXIT_FAILURE);
}
/* Cierra la parte de la primera tuberia que no nos
* interesa */
(void) close(fd1[1]);
/* Comprobaciones sobre el archivo de salida */
if (lstat(archivo,&File)){
/* No existe el fichero */
output = open(archivo,O_WRONLY | O_CREAT,
0600);
if (output == -1){
(void) fprintf(stderr,"No puedo"
" crear el archivo %s.\n",archivo);
exit(EXIT_FAILURE);
}
}
else {
/* El fichero existe */
if (OverWrite == TRUE){
output = open(archivo,O_WRONLY |
O_CREAT | O_TRUNC, 0600);
if (output == -1){
(void) fprintf(stderr," No"
" puedo acceder al archivo %s.\n",archivo);
exit(EXIT_FAILURE);
}
}
else { /* no OverWrite */
output = open(archivo,
O_WRONLY | O_APPEND);
if (output == -1){
(void) fprintf(stderr,
"No puedo abrir el archivo %s.\n",archivo);
exit(EXIT_FAILURE);
}
}
}
/* Cambio la salida estandar y la de error por el
* fichero de salida */
(void) dup2(output, STDOUT);
(void) dup2(output, STDERR);
/* Tomo la entrada de la salida de la tuberia */
(void) dup2(fd1[0], STDIN);
/* Ejecuto el segundo comando */
if (execlp(SHELL,SHELL,ARGS2,NULL) == -1){
(void) fprintf(stderr,"%s %s\n",comando2,
CadenaError(errno));
(void) kill(childpid,SIGTERM);
(void) close(output);
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
} /* padre */
} /* tuberia() */
--
"Emacs is a good OS but it lacks a good text editor.
That's why I'm using Vim"
Anonymous
Technical Details
Message-ID:
<g491m9.1o.ln@127.0.0.1>Path:
arc1-ca.pugleaf.net!archiver1.google.com!newsfeed.google.com!newsfeed.stanford.edu!newsfeeds.belnet.be!news.belnet.be!cleanfeed.casema.net!leda.casema.net!newsfeed2.news.nl.uu.net!sun4nl!ams.uu.net!newsf01.!newsr02..POSTED!not-for-mailReferences:
<6nvg7.24112$322.414183@telenews.teleline.es> <7exg7.25762$322.469626@telenews.teleline.es>Show Full Headers
Complete Article Headers
X-Google-Language: SPANISH,ASCII
X-Google-Thread: f86c8,6b0d03b6e42024c5
X-Google-Attributes: gidf86c8,public
X-Google-ArrivalTime: 2001-08-22 14:53:40 PST
Path: arc1-ca.pugleaf.net!archiver1.google.com!newsfeed.google.com!newsfeed.stanford.edu!newsfeeds.belnet.be!news.belnet.be!cleanfeed.casema.net!leda.casema.net!newsfeed2.news.nl.uu.net!sun4nl!ams.uu.net!newsf01.!newsr02..POSTED!not-for-mail
From: Gonzalo Paniagua Javier <gpanjav@jazzfree.com>
Subject: Re: fork(), pipes,... no mentero
Newsgroups: es.comp.os.linux.programacion
References: <6nvg7.24112$322.414183@telenews.teleline.es> <7exg7.25762$322.469626@telenews.teleline.es>
User-Agent: tin/1.5.8-20010221 ("Blue Water") (UNIX) (Linux/2.4.8 (i586))
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
Message-ID: <g491m9.1o.ln@127.0.0.1>
Lines: 165
Date: Wed, 22 Aug 2001 21:54:01 GMT
NNTP-Posting-Host: 62.42.14.67
X-Trace: newsr02. 998517241 62.42.14.67 (Wed, 22 Aug 2001 23:54:01 MET DST)
NNTP-Posting-Date: Wed, 22 Aug 2001 23:54:01 MET DST