From: mcuddy@fensende.Rational.COM (Mike Cuddy)
Newsgroups: comp.sys.amiga.programmer
Subject: Re: Emulating UNIX pipes on Amiga (GCC?)
Date: 19 Aug 92 20:25:17 GMT

kentd@FtCollins.NCR.com (Kent Dalton) writes:

>Does anybody know how Amiga GCC 2.1/ixemlib implements pipes? I am
>porting a program which extensively uses pipes and the file handles
>provided by the GCC popen function are behaving like they are pointed at
>/dev/null. Does it even work at all?

I don't know about GCC pipes, but here's some code that works for me using
amigados 2 and the pipe: device...

(there are a couple of routines missing... StringNew() and StringDelete()
you can use malloc() and free())

-----pipe.h-----
/*
** pipe.h -- functions for dealing with named pipes 
*/
#ifndef _H_PIPE
#define _H_PIPE

typedef struct pipe_f {
    struct FileHandle *p_write;
    struct FileHandle *p_read;
} Pipe;

#define PIPE_NOREAD (1<<1)
/* open a pair of file descriptors on the same file in PIPE: */
int OpenPipe(Pipe *pipe,char *name, char **filename, int flags);

#define PIPE_SUBS (1<<0)	/* replace '%' with pipe filename */
/* open a pipe to write data to another program */
struct FileHandle *PipeTo(char *progname, long flags, struct FileHandle *output);

/* open a pipe to read data from another program */
struct FileHandle *PipeFrom(char *progname, long flags, struct FileHandle *input);

#endif

-----pipe.c-----
/*
** pipe.c: handle pipes..
*/

#include <dos/dos.h>
#include <dos/dostags.h>
#include <stdio.h>
#include <clib/dos_protos.h>
#include <pragmas/dos_lib.h> 
#include <string.h>
#include "strstuff.h"
#include "pipe.h"

/* 
** fill in (Pipe *)pipe with a read file descriptor and a write file
** descriptor.  if flags & PIPE_NOREAD, don't open a read pipe 
*/
int OpenPipe(Pipe *pipe,char *name,char **filename, int flags)
{
    char buf[32];
    static int counter = 0;

    Forbid(); counter++; Permit();	/* keep it pure.. ;-) */
    sprintf(buf,"PIPE:%X.%d",FindTask(0),counter);
    if (name) strncat(buf,name,sizeof(buf) - strlen(buf));
    if (filename) {
        *filename = StringSave(buf);
	if (*filename == NULL) return(NULL);
    }
    
    /* make a temp file name in PIPE:  and returns 2 file descriptors */
    pipe->p_write = (struct FileHandle *)Open(buf,MODE_NEWFILE);
    if (pipe->p_write == NULL) {
#ifdef TEST_PIPE
	printf("can't open write pipe %s\n",buf);
#endif
        return(-1);
    }
    if (!(flags & PIPE_NOREAD)) {
	pipe->p_read = (struct FileHandle *)Open(buf,MODE_OLDFILE);
	if (pipe->p_read == NULL) { 
#ifdef TEST_PIPE
	    printf("can't open write pipe %s\n",buf);
#endif
	    Close((BPTR)(pipe->p_write)); return(-1); 
	}
    } else pipe->p_read = NULL;
    return(0);
}

void ClosePipe(Pipe *pipe)
{
#ifdef TEST_PIPE
    printf("closing pipe");
#endif
    if (pipe->p_read) Close((BPTR)pipe->p_read); 
    pipe->p_read = NULL;
    if (pipe->p_write) Close((BPTR)pipe->p_write);
    pipe->p_write = NULL;
}

struct FileHandle *PipeTo(char *progname, long flags, struct FileHandle *output)
{
    Pipe pipe;
    long err;
    char *pipefn = NULL;
    char *substname = NULL;
    /* 
    ** runs another program asynchronously, returns a file descriptor
    ** to write to 
    */
    if (output == NULL) {
        output = (struct FileHandle *)Open("CONSOLE:",MODE_NEWFILE);
	if (output == NULL) {
#ifdef TEST_PIPE
	    printf("can't open CONSOLE: for output\n");
#endif
	    return(NULL);	/* couldn't open console */
	}
    }
    if (OpenPipe(&pipe,NULL,flags & PIPE_SUBS ? &pipefn : NULL,flags & PIPE_SUBS ? PIPE_NOREAD : 0)==-1) 
        return(NULL); 

    if (flags & PIPE_SUBS) {
	int count = 0;
	char *p;

        if (pipefn == NULL) return(NULL);
	p = progname;
	while (*p) if (*p++ == '%') count++;
	if (count != 0) {
	    char *out;
	    substname = StringNew(strlen(progname)+count*strlen(pipefn));
	    if (substname == NULL) {
	        StringDelete(pipefn);
		ClosePipe(&pipe);
		return(NULL);
	    }
	    out = substname;
	    p = progname;
	    while(*p) {
	        if (*p == '%') {
		    char *q = pipefn;
		    while (*q) *out++ = *q++;	/* copy file name */
		    p++;
		} else {
		    *out++ = *p++;
		}
	    }
	    *out = 0;	/* Null terminate substituted command line */
	    progname = substname;
	    StringDelete(pipefn);
	}
    }

#ifdef TEST_PIPE
    printf("calling SystemTags(%s)\n",progname);
#endif
    err = SystemTags(progname, SYS_Input, pipe.p_read,
		    SYS_Asynch, 1, 
		    SYS_Output, output,
		    SYS_UserShell, 1,
		    TAG_DONE);

    if (substname) StringDelete(substname);

    if (err) {
#ifdef TEST_PIPE
        printf("couldn't SystemTags.\n");
#endif
        ClosePipe(&pipe);
	Close((BPTR)output);
	return(NULL);
    }
    return(pipe.p_write);
}

struct FileHandle *PipeFrom(char *progname, long flags, struct FileHandle *input)
{
    Pipe pipe;
    long err;
    char *pipefn = NULL;
    char *substname = NULL;
    /* 
    ** runs another program asynchronously, returns a file descriptor
    ** to write to 
    */
    if (input == NULL) {
        input = (struct FileHandle *)Open("CONSOLE:",MODE_OLDFILE);
	if (input == NULL) {
#ifdef TEST_PIPE
	    printf("can't open CONSOLE: for input\n");
#endif
	    return(NULL);	/* couldn't open console */
	}
    }
    if (OpenPipe(&pipe,NULL,flags & PIPE_SUBS ? &pipefn : NULL, flags)==-1) 
        return(NULL); 

    if (flags & PIPE_SUBS) {
	int count = 0;
	char *p;

        if (pipefn == NULL) return(NULL);
	p = progname;
	while (*p) if (*p++ == '%') count++;
	if (count != 0) {
	    char *out;
	    substname = StringNew(strlen(progname)+count*strlen(pipefn));
	    if (substname == NULL) {
	        StringDelete(pipefn);
		ClosePipe(&pipe);
		return(NULL);
	    }
	    out = substname;
	    p = progname;
	    while(*p) {
	        if (*p == '%') {
		    char *q = pipefn;
		    while (*q) *out++ = *q++;	/* copy file name */
		    p++;
		} else {
		    *out++ = *p++;
		}
	    }
	    *out = 0;	/* Null terminate substituted command line */
	    progname = substname;
	    StringDelete(pipefn);
	}
    }

    err = SystemTags(progname, SYS_Input, input,
		    SYS_Asynch, 1, 
		    SYS_Output, pipe.p_write,
		    SYS_UserShell, 1,
		    TAG_DONE);
#ifdef TEST_PIPE
    printf("calling SystemTags(%s)\n",progname);
#endif

    if (substname) StringDelete(substname);

    if (err) {
#ifdef TEST_PIPE
        printf("couldn't SystemTags.\n");
#endif
        ClosePipe(&pipe);
	Close((BPTR)input);
	return(NULL);
    }
    return(pipe.p_read);
}

#ifdef TEST_PIPE
char buf[1024];

main(int argc,char **argv)
{
    struct FileHandle *r, *w;
    char *str;
    int bytes;

    /* test pipe functions.. */

    /* open a read pipe to 'type' */
    r = PipeFrom("ls -al", PIPE_SUBS, NULL);

    /* open a write pipe to 'type' */
    /* we set PIPE_NOREAD because we let more use redirection and
    ** if we open the read side of the pipe, more will not be able to.
     */
    w = PipeTo(argv[1] ? argv[1] : "more <%",PIPE_SUBS|PIPE_NOREAD,(struct FileHandle *)Output());

    while ((bytes = Read((BPTR)r,buf,sizeof(buf))) > 0) {
        Write((BPTR)w,buf,bytes);
    }
    str = "That's all folks!\n\n*** END OF FILE***\n";
    Write((BPTR)w,str,strlen(str));
    Close((BPTR)r);
    Close((BPTR)w);
    return(0);
}
#endif
Newsgroups: comp.sys.amiga.programmer