Article View: comp.sys.amiga.tech
Article #13143Re: Using PIP:
From: Rick Schaeffer 99
Date: Sun, 17 Dec 1989 18:35
Date: Sun, 17 Dec 1989 18:35
216 lines
6433 bytes
6433 bytes
I've been following the discussion on using pipes with interest. Recently
I hacked this small routine which uses the ARP 1.3 AsyncRun() function and
AmigaDos 1.3 pipes to provide a Unix-like popen() function. It seems to
work fine on anything I've tried (including standard AmigaDos programs like
type and list that were written in BCPL). It probably has some bugs but,
since it's short and *does* seem to work I thought I'd post it. Comments,
improvements, and whatnot welcome. It was compiled with Lattice 5.04 but
shouldn't be too tough to make with Aztec.
/*
** popen.c
** Written by Rick Schaeffer (ricks@isc-br.isc-br.com)
NAME
popen, pclose - initiate I/O to/from a process
SYNOPSIS
#include <stdio.h>
FILE *popen(command, type)
char *command, *type;
pclose(stream)
FILE *stream;
DESCRIPTION
The arguments to popen are pointers to null-terminated
strings containing respectively a command line and an
I/O mode, either "r" for reading or "w" for writing. It
creates a pipe between the calling process and the command
to be executed. The value returned is a stream pointer that
can be used (as appropriate) to write to the standard input
of the command or read from its standard output.
A stream opened by popen **MUST** be closed by pclose, which
waits for the associated process to terminate and returns
the exit status of the command.
Because stdio files are shared, a type "r" command may be
used as an input filter, and a type "w" as an output filter.
DIAGNOSTICS
Popen returns a null pointer if files or processes cannot be
created.
Pclose returns -1 if stream is not associated with a
`popened' command.
*/
#include <stdio.h>
#include <string.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <arp/arpbase.h>
#include <ios1.h>
struct ArpBase *ArpBase;
static struct Process *thistask;
static struct ProcessControlBlock pcb;
struct pstruct {
FILE *fptr;
struct ZombieMsg exitmsg;
};
struct pstruct poarray[6];
FILE *popen(cmd,mode)
char *cmd;
char *mode;
{
char *parms;
static char tempname[] = "pipe:pXXX.XXX";
char *pname,redir[20],*mktemp();
short i;
int pmode;
struct pstruct *poptr;
BPTR pfd;
if (thistask == NULL)
thistask = (struct Process *) FindTask(NULL);
if (ArpBase == NULL)
ArpBase = (struct ArpBase *) OpenLibrary(ArpName,ArpVersion);
if (ArpBase == NULL) {
fprintf(stderr,"Arp Open Failed\n");
return(NULL);
}
poptr = NULL;
for (i=0; i<6; i++) {
if (poarray[i].fptr == NULL) {
poptr = &poarray[i];
break;
}
}
if (poptr == NULL) {
fprintf(stderr,"popen: Unable to find an open pipe\n");
return(NULL);
}
if (strcmp(mode,"r") == 0)
pmode = MODE_NEWFILE;
else if (strcmp(mode,"w") == 0)
pmode = MODE_OLDFILE;
else {
fprintf(stderr,"popen: Mode must be 'r' or 'w'\n");
return(NULL);
}
tempname[5] = 'a' + i;
strcpy(redir,tempname);
pname = mktemp(redir); /* set up a pipe: file name */
setmem(&pcb, sizeof(struct ProcessControlBlock), 0);
/* Now get the child's stack and priority set up */
if (thistask->pr_CLI) {
struct CommandLineInterface *cli;
cli = (struct CommandLineInterface *) BADDR(thistask->pr_CLI);
pcb.pcb_StackSize = cli->cli_DefaultStack << 2;
}
else
pcb.pcb_StackSize = thistask->pr_StackSize;
pcb.pcb_Pri = thistask->pr_Task.tc_Node.ln_Pri;
/* Open the side of the pipe for the child */
pfd = Open(pname,pmode);
if (pfd == 0) {
fprintf(stderr,"popen: Unable to open pipe file\n");
return(NULL);
}
if (pmode == MODE_NEWFILE)
pcb.pcb_Output = pfd;
else
pcb.pcb_Input = pfd;
/* Locate the break between command and parameters */
parms = strpbrk(cmd," \t");
if (parms) {
*parms++ = 0;
parms = stpblk(parms);
if (parms && *parms == 0)
parms = NULL;
}
/* Create a port for the child's exit message */
poptr->exitmsg.zm_ExecMessage.mn_ReplyPort = CreatePort(NULL,0);
if (poptr->exitmsg.zm_ExecMessage.mn_ReplyPort == 0) {
fprintf(stderr,"popen: Couldn't create message port\n");
return(NULL);
}
pcb.pcb_LastGasp = &poptr->exitmsg;
if (ASyncRun(cmd,parms,&pcb) < 0) {
fprintf(stderr,"popen: AsyncRun failed\n");
DeletePort(poptr->exitmsg.zm_ExecMessage.mn_ReplyPort);
return(NULL);
}
/* Now open our side of the pipe */
poptr->fptr = fopen(pname,mode);
if (poptr->fptr == NULL) {
fprintf(stderr,"popen: Unable to open pipe file %s\n",pname);
DeletePort(poptr->exitmsg.zm_ExecMessage.mn_ReplyPort);
return(NULL);
}
return(poptr->fptr);
}
pclose(fptr)
FILE *fptr;
{
short i;
for (i=0; i<6; i++)
if (poarray[i].fptr == fptr)
break;
if (i > 5) {
fprintf(stderr,"popen: DISASTER...couldn't find file pointer in pclose\n");
exit(1);
}
fclose(fptr);
WaitPort(poarray[i].exitmsg.zm_ExecMessage.mn_ReplyPort);
poarray[i].fptr = NULL;
DeletePort(poarray[i].exitmsg.zm_ExecMessage.mn_ReplyPort);
return(poarray[i].exitmsg.zm_ReturnCode);
}
char *mktemp(template)
char *template;
{
register char *cp;
register unsigned long val;
cp = template;
cp += strlen(cp);
for (val = (unsigned long) FindTask(0L) ; ; )
if (*--cp == 'X') {
*cp = val%10 + '0';
val /= 10;
} else if (*cp != '.')
break;
if (*++cp != 0) {
*cp = 'A';
while (access(template, 0) == 0) {
if (*cp == 'Z') {
*template = 0;
break;
}
++*cp;
}
} else {
if (access(template, 0) == 0)
*template = 0;
}
return template;
}
--
Rick Schaeffer UUCP: uunet!isc-br.isc-br.com!ricks
ISC-Bunker Ramo ricks@isc-br.isc-br.com
Box TAF-C8 Phone: (509)927-5114
Spokane, WA 99220
Technical Details
Message-ID:
<2676@isc-br.ISCS.COM>Path:
arc1-ca.pugleaf.net!utzoo!attcan!utgpu!jarvis.csri.toronto.edu!rutgers!cs.utexas.edu!uunet!isc-br!eagle!ricksReferences:
<4689@sugar.hackercorp.com> <1610.AA1610@julie> <1718.AA1718@julie> <4778@sugar.hackercorp.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!utgpu!jarvis.csri.toronto.edu!rutgers!cs.utexas.edu!uunet!isc-br!eagle!ricks From: ricks@eagle.iscs.com (Rick Schaeffer 99) Newsgroups: comp.sys.amiga.tech Subject: Re: Using PIP: Keywords: dupping closing pipes popen Message-ID: <2676@isc-br.ISCS.COM> Date: 17 Dec 89 18:35:11 GMT References: <4689@sugar.hackercorp.com> <1610.AA1610@julie> <1718.AA1718@julie> <4778@sugar.hackercorp.com> Sender: news@isc-br.ISCS.COM Reply-To: ricks@eagle.UUCP (Rick Schaeffer 99) Organization: ISC Systems Corporation, Spokane WA Lines: 216