🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: es.comp.os.linux.programacion
Article #12191

Re: fork(), pipes,... no mentero

#12191
From: Gonzalo Paniagua Javier
Date: Wed, 22 Aug 2001 21:54
164 lines
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-mail
References: <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