#ifndef lint
static const char RCSid[] = "$Id: popen.c,v 2.5 2003/02/22 02:07:22 greg Exp $";
#endif
/*
* popen() and pclose() calls for systems without pipe facilities
*/
/* ====================================================================
* The Radiance Software License, Version 1.0
*
* Copyright (c) 1990 - 2002 The Regents of the University of California,
* through Lawrence Berkeley National Laboratory. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes Radiance software
* (http://radsite.lbl.gov/)
* developed by the Lawrence Berkeley National Laboratory
* (http://www.lbl.gov/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
* and "The Regents of the University of California" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact radiance@radsite.lbl.gov.
*
* 5. Products derived from this software may not be called "Radiance",
* nor may "Radiance" appear in their name, without prior written
* permission of Lawrence Berkeley National Laboratory.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of Lawrence Berkeley National Laboratory. For more
* information on Lawrence Berkeley National Laboratory, please see
* .
*/
#include
#include
#include
#include
#include "paths.h"
#ifndef NFILE
#define NFILE 32
#endif
static struct {
char *f; /* file name, NULL if inactive */
char *c; /* command if writing */
} pips[NFILE];
FILE *
popen(cmd, mode) /* open command for reading or writing */
register char *cmd;
char *mode;
{
FILE *fp;
char *newcmd, *fname;
register char *cp, *cp2 = NULL;
int quote = '\0', paren = 0;
while (isspace(*cmd))
cmd++;
if (!*cmd)
return(NULL);
fname = (char *)malloc(TEMPLEN+1);
newcmd = (char *)malloc(TEMPLEN+6+strlen(cmd));
if (fname == NULL | newcmd == NULL)
return(NULL);
mktemp(strcpy(fname,TEMPLATE));
/* build our command */
for (cp = newcmd; ; cmd++) {
switch (*cmd) {
case '\'':
case '"':
if (!quote)
quote = *cmd;
else if (quote == *cmd)
quote = '\0';
#ifdef MSDOS
else
break;
*cp++ = '"'; /* double quotes only */
continue;
case '\\':
if (!quote && cmd[1] == '\n') {
*cp++ = ' ';
cmd++;
continue;
}
cmd++;
break;
#else
break;
case '\\':
*cp++ = *cmd++;
break;
case '(':
if (!quote)
paren++;
break;
case ')':
if (!quote && paren)
paren--;
break;
case ';':
#endif
case '|':
if (!quote && !paren && cp2 == NULL)
cp2 = fname;
break;
case ' ':
case '\t':
if (!quote)
while (isspace(cmd[1]))
cmd++;
break;
case '\n':
case '\0':
if (cp2 == NULL)
cp2 = fname;
break;
}
if (cp2 == fname && *mode == 'w') { /* add input file */
*cp++ = ' '; *cp++ = '<';
while (*cp2)
*cp++ = *cp2++;
*cp++ = ' ';
}
if (!(*cp = *cmd))
break;
cp++;
}
if (*mode == 'r') { /* add output file */
while (isspace(cp[-1]) || cp[-1] == ';')
cp--;
*cp++ = ' '; *cp++ = '>';
while (*cp2)
*cp++ = *cp2++;
*cp = '\0';
system(newcmd); /* execute command first */
}
if ((fp = fopen(fname, mode)) == NULL) { /* open file */
free(fname);
free(newcmd);
return(NULL);
}
if (fileno(fp) >= NFILE) {
eputs("popen: too many open files\n");
quit(1);
}
pips[fileno(fp)].f = fname;
if (*mode == 'r') {
free(newcmd);
pips[fileno(fp)].c = NULL;
} else
pips[fileno(fp)].c = newcmd;
return(fp);
}
pclose(fp) /* close pipe and cleanup */
FILE *fp;
{
register int pn = fileno(fp);
if (pn >= NFILE || pips[pn].f == NULL || fclose(fp) == -1)
return(-1);
if (pips[pn].c != NULL) {
system(pips[pn].c); /* execute command last */
free(pips[pn].c);
}
unlink(pips[pn].f); /* remove temp file */
free(pips[pn].f);
pips[pn].f = NULL;
return(0);
}