home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
317b.lha
/
RCS_Sources
/
rsbx.lib
/
popen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-05
|
6KB
|
305 lines
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
#include <ios1.h>
#include <fcntl.h>
#include <libraries/dosextens.h>
#include <exec/lists.h>
#include <exec/nodes.h>
#include <rsbx/ChildTasking.h>
struct pstruct {
struct MinNode node;
FILE *fptr1;
struct ChildNode *child;
};
static struct MinList PList = { 0 };
FILE *popenl(char *args, ...);
FILE *popenv(char **args, char *mode);
int pclose(FILE *fptr);
static char *mktemp(char *template);
/****** rsbx.lib/popenl() ****************************************************
*
* NAME
* popenl -- Initiate I/O to or from a command.
*
* SYNOPSIS
* pipe = popenl(arg0, ..., argn, NULL, mode)
*
* FILE *popenl(char *, char *, ...);
*
* FUNCTION
* Creates a stream between the calling process and the stdin or stdout
* streams of the command it executes. Mode should be "r" to read
* the stdout stream of the command, or "w" to write to the stdin
* stream of the command.
*
* INPUTS
* arg0 - Name of file to execute.
* ... - Other command line arguments needed by the file to be
* executed.
* NULL - Zero.
* mode _ I/O mode string.
*
* RESULT
* pipe - File pointer to use to read or write to the command
* with.
*
* NOTES
* A stream opened by popenl() should be closed by pclose().
*
* SEE ALSO
* popenv(), pclose().
*
* BUGS
* This function does not create a complete CLI enviroment for the child
* process. Use of this function with a command that expects a BCPL
* environment will crash the system. The Unix function 'popen' takes
* as arguments a command string which it passes to the shell, and a
* mode string.
*
******************************************************************************
*
*/
FILE *popenl(char *args, ...)
{
char **nullarg;
for(nullarg = (char **)(&args); *nullarg != 0; nullarg++);
return(popenv(&args, *(nullarg+1)));
}
/****** rsbx.lib/popenv() ****************************************************
*
* NAME
* popenv -- Initiate I/O to or from a command.
*
* SYNOPSIS
* pipe = popenv(argv, mode)
*
* FILE *popenv(char **, char *);
*
* FUNCTION
* Creates a stream between the calling process and the stdin or stdout
* streams of the command it executes. Mode should be "r" to read
* the stdout stream of the command, or "w" to write to the stdin
* stream of the command.
*
* INPUTS
* argv - An array of pointer to the argument strings for the
* command. The last pointer must be followed by a 0
* pointer. The first pointer, argv[0], is the name of
* file to execute.
* mode _ I/O mode string.
*
* RESULT
* pipe - File pointer to use to read or write to the command
* with.
*
* NOTES
* A stream opened by popenv() should be closed by pclose().
*
* SEE ALSO
* popenl(), pclose().
*
* BUGS
* This function does not create a complete CLI enviroment for the child
* process. Use of this function with a command that expects a BCPL
* environment will crash the system. The Unix function 'popen' takes
* as arguments a command string which it passes to the shell, and a
* mode string.
*
******************************************************************************
*
*/
FILE *popenv(char **args, char *mode)
{
struct LAUNCHENV env = { 0,0,0,0,0,0,0 };
static char tempname[] = "pipe:popen.XXXX.XXXXXXXX";
char *pname;
char redir[64];
struct pstruct *poptr;
char *mode1;
int mode2;
int f2;
if (!PList.mlh_Head)
{
NewList(&PList);
}
if ((strcmp(mode,"r") != 0) && (strcmp(mode,"w") != 0))
{
fprintf(stderr,"popen: bad mode!\n");
return(NULL);
}
if (*mode == 'r')
{
mode1 = "r";
mode2 = MODE_NEWFILE;
}
else
{
mode1 = "w";
mode2 = MODE_OLDFILE;
}
strcpy(redir,tempname);
if (!(poptr = (struct pstruct *)malloc(sizeof(struct pstruct))))
{
fprintf(stderr,"popen: Out of memory!\n");
return(NULL);
}
if (!(pname = mktemp(redir)))
{
fprintf(stderr,"popen: Unable to find an available pipe.\n");
free(poptr);
return(NULL);
}
if (!(poptr->fptr1 = fopen(pname, mode1)))
{
fprintf(stderr,"popen: Unable to open pipe end 1 file %s mode %s\n", pname, m
de);
free(poptr);
return(NULL);
}
if (!(f2 = Open(pname, mode2)))
{
fprintf(stderr,"popen: Unable to open pipe end 2 file %s mode %s\n", pname, m
de);
fclose(poptr->fptr1);
free(poptr);
return(NULL);
}
env.priority = ((struct Task *)FindTask(NULL))->tc_Node.ln_Pri;
if (*mode == 'r')
{
env.std_out = f2;
}
else
{
env.std_in = f2;
}
env.le_fh1 = f2;
if (!(poptr->child = LaunchChildv(&env, *args, args)))
{
fprintf(stderr,"popen: Fork failed\n");
Close(f2);
fclose(poptr->fptr1);
free(poptr);
return(NULL);
}
AddTail(&PList, poptr);
return(poptr->fptr1);
}
/****** rsbx.lib/pclose() ****************************************************
*
* NAME
* pclose -- Closes pipe opened by popenl() or by popenv().
*
* SYNOPSIS
* status = pclose(pipe)
*
* int pclose(FILE *);
*
* FUNCTION
* Waits for the command associated with the pipe to exit, closes the
* stream, and returns the return code from the command.
*
* INPUTS
* pipe - Stream pointer returned by a call to popenl() or to
* popenv().
*
* RESULT
* status - The return code from the command executed, or -1 if
* pipe wasn't opened by popenl() or by popenv().
*
* NOTES
*
* SEE ALSO
* popenl(), popenv().
*
* BUGS
* None known.
*
******************************************************************************
*
*/
int pclose(FILE *fptr)
{
long status;
struct pstruct *poptr;
for (poptr = (struct pstruct *)PList.mlh_Head;
poptr->node.mln_Succ;
poptr = (struct pstruct *)poptr->node.mln_Succ)
{
if (poptr->fptr1 == fptr)
{
Remove(poptr);
fclose(poptr->fptr1);
if (!WaitChild(poptr->child, &status))
{
status = -1;
}
free(poptr);
return(status);
}
}
return -1;
}
static unsigned short Generation = 0;
static char *hex = "0123456789abcdef";
static char *mktemp(char *template)
{
char *cp;
unsigned long val;
cp = template;
cp += strlen(template);
val = (unsigned long) FindTask(0L);
while (*--cp == 'X')
{
*cp = hex[val%16];
val /= 16;
}
val = Generation++;
while (*--cp == 'X')
{
*cp = hex[val%16];
val /= 16;
}
return template;
}