home *** CD-ROM | disk | FTP | other *** search
- /*
- * popen.c - imitate UNIX pipes
- *
- * $Header: c:/src/RCS/popen.c 1.2 1993/05/17 17:51:07 few Exp $
- *
- * Author: Frank Whaley (few@autodesk.com)
- *
- * Copyright (c) 1993 Frank Whaley. All rights reserved.
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appears in all copies. The
- * name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <process.h>
- #include <io.h>
- #include <errno.h>
-
- #define NPIPES 10 /* max number of pipes */
-
- typedef struct
- {
- char *command; /* program name */
- FILE *fp; /* pipe tempfile */
- char *file; /* pipe filename */
- char *mode; /* pipe mode */
- int status; /* status to return */
- } PIPE;
-
- static PIPE pipes[NPIPES];
- static int init = 0;
-
- /* forward declarations */
- static PIPE *findPipe(FILE *fp);
- static int killPipe(PIPE *pp, int mode);
- static PIPE *newPipe(char *command, char *mode);
-
-
- /*
- -* popen - open a (pseudo) pipe
- */
- FILE *
- popen(char *command, char *type)
- {
- int old_stdout;
- PIPE *pp;
-
- /* init PIPE table */
- if ( !init )
- {
- for ( pp = pipes; pp < &pipes[NPIPES]; pp++ )
- pp->fp = (FILE *)NULL;
- init++;
- }
-
- /* which flavor pipe ?? */
- switch ( *type )
- {
- case 'w':
- /* pclose() execs command for write pipes */
- if ( (pp = newPipe(command, type)) == (PIPE *)NULL )
- return ( (FILE *)NULL );
- return ( pp->fp );
-
- case 'r':
- /* exec command now for read pipes */
- if ( (pp = newPipe(command, type)) == (PIPE *)NULL )
- return ( (FILE *)NULL );
-
- if ( ((old_stdout = dup(fileno(stdout))) < 0) ||
- (dup2(fileno(pp->fp), fileno(stdout)) < 0) ||
- ((pp->status = system(command)) < 0) ||
- (fclose(pp->fp) < 0) ||
- (dup2(old_stdout, fileno(stdout)) < 0) ||
- ((pp->fp = fopen(pp->file, pp->mode)) == (FILE *)NULL) )
- {
- killPipe(pp, 1);
- return ( (FILE *)NULL );
- }
-
- return ( pp->fp );
-
- default:
- errno = EINVAL;
- return ( (FILE *)NULL );
- }
- }
-
- /*
- -* pclose - close a (pseudo) pipe
- */
- int
- pclose(FILE *fp)
- {
- PIPE *pp;
- int old_stdin;
-
- if ( (pp = findPipe(fp)) == (PIPE *)NULL )
- {
- errno = EBADF;
- return ( -1 );
- }
-
- if ( fclose(pp->fp) < 0 )
- return ( killPipe(pp, 1) );
-
- if ( (*pp->mode == 'w') &&
- (((pp->fp = fopen(pp->file, "r")) == (FILE *)NULL) ||
- ((old_stdin = dup(fileno(stdin))) < 0) ||
- (dup2(fileno(pp->fp), fileno(stdin)) < 0) ||
- ((pp->status = system(pp->command)) < 0) ||
- (fclose(pp->fp) < 0) ||
- (dup2(old_stdin, fileno(stdin)) < 0)) )
- {
- return ( killPipe(pp, 1) );
- }
-
- return ( killPipe(pp, 0) );
- }
-
- /*
- * find a PIPE entry
- */
- static PIPE *
- findPipe(FILE *fp)
- {
- PIPE *pp;
-
- for ( pp = pipes; pp < &pipes[NPIPES]; pp++ )
- if ( pp->fp == fp )
- return ( pp );
-
- return ( (PIPE *)NULL );
- }
-
- /*
- * cancel a pipe
- */
- static int
- killPipe(PIPE *pp, int mode)
- {
- int result = (!mode) ? 0 : -1;
- int serrno = errno;
-
- fclose(pp->fp);
-
- if ( pp->file != NULL )
- {
- result = unlink(pp->file);
-
- if ( !mode )
- serrno = errno;
- else
- result = -1;
- free(pp->file);
- }
-
- if ( pp->command != NULL )
- free(pp->command);
-
- pp->fp = (FILE *)NULL;
-
- errno = serrno;
- return ( result );
- }
-
- /*
- * init PIPE structure
- */
- static PIPE *
- newPipe(char *command, char *mode)
- {
- FILE *fp;
- PIPE *pp;
- char tmpfile[256];
- static char *tmpdir = NULL;
-
- /* one-time search for tmp directory */
- if ( (tmpdir == NULL) &&
- ((tmpdir = getenv("TMPDIR")) == NULL) &&
- ((tmpdir = getenv("TMP")) == NULL) &&
- ((tmpdir = getenv("TEMP")) == NULL) )
- tmpdir = ".";
-
- /* make temp file */
- strcat(strcpy(tmpfile, tmpdir), "/ppXXXXXX");
- mktemp(tmpfile);
- if ( (fp = fopen(tmpfile, "w")) == (FILE *)NULL )
- return ( (PIPE *)NULL );
-
- /* make PIPE entry */
- if ( (pp = findPipe((FILE *)NULL)) == (PIPE *)NULL )
- {
- fclose(fp);
- unlink(tmpfile);
- errno = EMFILE;
- return ( (PIPE *)NULL );
- }
-
- pp->fp = fp;
- pp->mode = strdup(mode);
- pp->command = strdup(command);
- pp->file = strdup(tmpfile);
-
- /* errors ?? */
- if ( (pp->command == NULL) || (pp->file == NULL) )
- {
- killPipe(pp, 1);
- errno = ENOMEM;
- return ( (PIPE *)NULL );
- }
-
- return ( pp );
- }
-
- /* END of popen.c */
-