705 lines
16 KiB
C
705 lines
16 KiB
C
|
|
/*
|
|
* Copyright © 2001 Novell, Inc. All Rights Reserved.
|
|
*
|
|
* You may distribute under the terms of either the GNU General Public
|
|
* License or the Artistic License, as specified in the README file.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* FILENAME : NWPipe.c
|
|
* DESCRIPTION : Functions to implement pipes on NetWare.
|
|
* Author : HYAK
|
|
* Date : January 2001.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
#include <nwadv.h>
|
|
#include <nwdsdefs.h>
|
|
|
|
#include "win32ish.h"
|
|
#include "nwpipe.h"
|
|
#include "nwplglob.h"
|
|
|
|
|
|
// This was added since the compile failed saying "undefined P_WAIT"
|
|
// when USE_ITHREADS was commented in the makefile
|
|
#ifndef P_WAIT
|
|
#define P_WAIT 0
|
|
#endif
|
|
|
|
#ifndef P_NOWAIT
|
|
#define P_NOWAIT 1
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*============================================================================================
|
|
|
|
Function : fnPipeFileMakeArgv
|
|
|
|
Description : This function makes the argument array.
|
|
|
|
Parameters : ptpf (IN) - Input structure.
|
|
|
|
Returns : Boolean.
|
|
|
|
==============================================================================================*/
|
|
|
|
BOOL fnPipeFileMakeArgv(PTEMPPIPEFILE ptpf)
|
|
{
|
|
int i=0, j=0;
|
|
int dindex = 0;
|
|
int sindex = 0;
|
|
|
|
ptpf->m_argv_len = 0;
|
|
|
|
|
|
// Below 2 is added for the following reason:
|
|
// - The first one is for an additional value that will be added through ptpf->m_redirect.
|
|
// - The second one is for a NULL termination of the array.
|
|
// This is required for spawnvp API that takes a NULL-terminated array as its 3rd parameter.
|
|
// If the array is NOT NULL-terminated, then the server abends at the spawnvp call !!
|
|
ptpf->m_argv = (char **) malloc((ptpf->m_pipeCommand->m_argc + 2) * sizeof(char*));
|
|
if (ptpf->m_argv == NULL)
|
|
return FALSE;
|
|
|
|
// For memory allocation it is just +1 since the last one is only for NULL-termination
|
|
// and no memory is required to be allocated.
|
|
for(i=0; i<(ptpf->m_pipeCommand->m_argc + 1); i++)
|
|
{
|
|
ptpf->m_argv[i] = (char *) malloc(MAX_DN_BYTES * sizeof(char));
|
|
if (ptpf->m_argv[i] == NULL)
|
|
{
|
|
for(j=0; j<i; j++)
|
|
{
|
|
if(ptpf->m_argv[j])
|
|
{
|
|
free(ptpf->m_argv[j]);
|
|
ptpf->m_argv[j] = NULL;
|
|
}
|
|
}
|
|
free(ptpf->m_argv);
|
|
ptpf->m_argv = NULL;
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// Copy over parsed items, removing "load" keyword if necessary.
|
|
sindex = ((stricmp(ptpf->m_pipeCommand->m_argv[0], LOAD_COMMAND) == 0) ? 1 : 0);
|
|
while (sindex < ptpf->m_pipeCommand->m_argc)
|
|
{
|
|
strcpy(ptpf->m_argv[dindex], ptpf->m_pipeCommand->m_argv[sindex]);
|
|
dindex++;
|
|
sindex++;
|
|
}
|
|
|
|
if (stricmp(ptpf->m_argv[0], PERL_COMMAND_NAME) == 0) // If Perl is the first command.
|
|
{
|
|
ptpf->m_launchPerl = TRUE;
|
|
|
|
#ifdef MPK_ON
|
|
ptpf->m_perlSynchSemaphore = kSemaphoreAlloc((BYTE *)"pipeSemaphore", 0);
|
|
#else
|
|
ptpf->m_perlSynchSemaphore = OpenLocalSemaphore(0);
|
|
#endif //MPK_ON
|
|
}
|
|
else if (stricmp(ptpf->m_argv[0], (char *)"perlglob") == 0)
|
|
ptpf->m_doPerlGlob = TRUE;
|
|
|
|
|
|
// Create last argument, which will redirect to or from the temp file
|
|
if (!ptpf->m_doPerlGlob || ptpf->m_mode)
|
|
{
|
|
if (!ptpf->m_mode) // If read mode?
|
|
{
|
|
if (ptpf->m_launchPerl)
|
|
strcpy(ptpf->m_redirect, (char *)">");
|
|
else
|
|
strcpy(ptpf->m_redirect, (char *)"(CLIB_OPT)/>");
|
|
}
|
|
else
|
|
{
|
|
if (ptpf->m_launchPerl)
|
|
strcpy(ptpf->m_redirect, (char *)"<");
|
|
else
|
|
strcpy(ptpf->m_redirect, (char *)"(CLIB_OPT)/<");
|
|
}
|
|
strcat(ptpf->m_redirect, ptpf->m_fileName);
|
|
|
|
if (ptpf->m_launchPerl)
|
|
{
|
|
char tbuf[15] = {'\0'};
|
|
sprintf(tbuf, (char *)" -{%x", ptpf->m_perlSynchSemaphore);
|
|
strcat(ptpf->m_redirect, tbuf);
|
|
}
|
|
|
|
strcpy(ptpf->m_argv[dindex], (char*) ptpf->m_redirect);
|
|
dindex++;
|
|
}
|
|
|
|
if (dindex < (ptpf->m_pipeCommand->m_argc + 1))
|
|
{
|
|
if(ptpf->m_argv[dindex])
|
|
{
|
|
free(ptpf->m_argv[dindex]);
|
|
ptpf->m_argv[dindex] = NULL; // NULL termination - required for spawnvp call.
|
|
}
|
|
}
|
|
|
|
ptpf->m_argv_len = dindex; // Length of the argv array OR number of argv string values.
|
|
ptpf->m_argv[ptpf->m_argv_len] = NULL; // NULL termination - required for spawnvp call.
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*============================================================================================
|
|
|
|
Function : fnPipeFileOpen
|
|
|
|
Description : This function opens the pipe file.
|
|
|
|
Parameters : ptpf (IN) - Input structure.
|
|
command (IN) - Input command string.
|
|
mode (IN) - Mode of opening.
|
|
|
|
Returns : File pointer.
|
|
|
|
==============================================================================================*/
|
|
|
|
FILE* fnPipeFileOpen(PTEMPPIPEFILE ptpf, char* command, char* mode)
|
|
{
|
|
int i=0, j=0;
|
|
|
|
char tempName[_MAX_PATH] = {'\0'};
|
|
|
|
|
|
ptpf->m_fileName = (char *) malloc(_MAX_PATH * sizeof(char));
|
|
if(ptpf->m_fileName == NULL)
|
|
return NULL;
|
|
|
|
// The char array is emptied so that there is no junk characters.
|
|
strncpy(ptpf->m_fileName, "", (_MAX_PATH * sizeof(char)));
|
|
|
|
|
|
// Save off stuff
|
|
//
|
|
if(strchr(mode,'r') != 0)
|
|
ptpf->m_mode = FALSE; // Read mode
|
|
else if(strchr(mode,'w') != 0)
|
|
ptpf->m_mode = TRUE; // Write mode
|
|
else
|
|
{
|
|
if(ptpf->m_fileName != NULL)
|
|
{
|
|
// if (strlen(ptpf->m_fileName))
|
|
if (ptpf->m_fileName)
|
|
unlink(ptpf->m_fileName);
|
|
|
|
free(ptpf->m_fileName);
|
|
ptpf->m_fileName = NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
ptpf->m_pipeCommand = (PCOMMANDLINEPARSER) malloc(sizeof(COMMANDLINEPARSER));
|
|
if (!ptpf->m_pipeCommand)
|
|
{
|
|
// if (strlen(ptpf->m_fileName))
|
|
if (ptpf->m_fileName)
|
|
unlink(ptpf->m_fileName);
|
|
|
|
free(ptpf->m_fileName);
|
|
ptpf->m_fileName = NULL;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// Initialise the variables
|
|
ptpf->m_pipeCommand->m_isValid = TRUE;
|
|
|
|
/****
|
|
// Commented since these are not being used. Still retained here.
|
|
// To be removed once things are proved to be working fine to a good confident level,
|
|
|
|
ptpf->m_pipeCommand->m_redirInName = NULL;
|
|
ptpf->m_pipeCommand->m_redirOutName = NULL;
|
|
ptpf->m_pipeCommand->m_redirErrName = NULL;
|
|
ptpf->m_pipeCommand->m_redirBothName = NULL;
|
|
ptpf->m_pipeCommand->nextarg = NULL;
|
|
****/
|
|
|
|
ptpf->m_pipeCommand->sSkippedToken = NULL;
|
|
ptpf->m_pipeCommand->m_argv = NULL;
|
|
ptpf->m_pipeCommand->new_argv = NULL;
|
|
|
|
#ifdef MPK_ON
|
|
ptpf->m_pipeCommand->m_qSemaphore = NULL;
|
|
#else
|
|
ptpf->m_pipeCommand->m_qSemaphore = 0L;
|
|
#endif //MPK_ON
|
|
|
|
ptpf->m_pipeCommand->m_noScreen = 0;
|
|
ptpf->m_pipeCommand->m_AutoDestroy = 0;
|
|
ptpf->m_pipeCommand->m_argc = 0;
|
|
ptpf->m_pipeCommand->m_argv_len = 1;
|
|
|
|
|
|
ptpf->m_pipeCommand->m_argv = (char **) malloc(ptpf->m_pipeCommand->m_argv_len * sizeof(char *));
|
|
if (ptpf->m_pipeCommand->m_argv == NULL)
|
|
{
|
|
free(ptpf->m_pipeCommand);
|
|
ptpf->m_pipeCommand = NULL;
|
|
|
|
// if (strlen(ptpf->m_fileName))
|
|
if (ptpf->m_fileName)
|
|
unlink(ptpf->m_fileName);
|
|
|
|
free(ptpf->m_fileName);
|
|
ptpf->m_fileName = NULL;
|
|
|
|
return NULL;
|
|
}
|
|
ptpf->m_pipeCommand->m_argv[0] = (char *) malloc(MAX_DN_BYTES * sizeof(char));
|
|
if (ptpf->m_pipeCommand->m_argv[0] == NULL)
|
|
{
|
|
for(j=0; j<i; j++)
|
|
{
|
|
if(ptpf->m_pipeCommand->m_argv[j])
|
|
{
|
|
free(ptpf->m_pipeCommand->m_argv[j]);
|
|
ptpf->m_pipeCommand->m_argv[j]=NULL;
|
|
}
|
|
}
|
|
free(ptpf->m_pipeCommand->m_argv);
|
|
ptpf->m_pipeCommand->m_argv=NULL;
|
|
|
|
free(ptpf->m_pipeCommand);
|
|
ptpf->m_pipeCommand = NULL;
|
|
|
|
// if (strlen(ptpf->m_fileName))
|
|
if (ptpf->m_fileName)
|
|
unlink(ptpf->m_fileName);
|
|
|
|
free(ptpf->m_fileName);
|
|
ptpf->m_fileName = NULL;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
ptpf->m_redirect = (char *) malloc(MAX_DN_BYTES * sizeof(char));
|
|
if (ptpf->m_redirect == NULL)
|
|
{
|
|
for(i=0; i<ptpf->m_pipeCommand->m_argv_len; i++)
|
|
{
|
|
if(ptpf->m_pipeCommand->m_argv[i] != NULL)
|
|
{
|
|
free(ptpf->m_pipeCommand->m_argv[i]);
|
|
ptpf->m_pipeCommand->m_argv[i] = NULL;
|
|
}
|
|
}
|
|
|
|
free(ptpf->m_pipeCommand->m_argv);
|
|
ptpf->m_pipeCommand->m_argv = NULL;
|
|
|
|
free(ptpf->m_pipeCommand);
|
|
ptpf->m_pipeCommand = NULL;
|
|
|
|
|
|
// if (strlen(ptpf->m_fileName))
|
|
if (ptpf->m_fileName)
|
|
unlink(ptpf->m_fileName);
|
|
|
|
free(ptpf->m_fileName);
|
|
ptpf->m_fileName = NULL;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// The char array is emptied.
|
|
// If it is not done so, then it could contain some junk values and the string length in that case
|
|
// will not be zero. This causes erroneous results in fnPipeFileMakeArgv() function
|
|
// where strlen(ptpf->m_redirect) is used as a check for incrementing the parameter count and
|
|
// it will wrongly get incremented in such cases.
|
|
strncpy(ptpf->m_redirect, "", (MAX_DN_BYTES * sizeof(char)));
|
|
|
|
// Parse the parameters.
|
|
fnCommandLineParser(ptpf->m_pipeCommand, (char *)command, TRUE);
|
|
if (!ptpf->m_pipeCommand->m_isValid)
|
|
{
|
|
fnTempPipeFileReleaseMemory(ptpf);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// Create a temporary file name
|
|
//
|
|
strncpy ( tempName, fnNwGetEnvironmentStr((char *)"TEMP", NWDEFPERLTEMP), (_MAX_PATH - 20) );
|
|
tempName[_MAX_PATH-20] = '\0';
|
|
strcat(tempName, (char *)"\\plXXXXXX.tmp");
|
|
if (!fnMy_MkTemp(tempName))
|
|
{
|
|
fnTempPipeFileReleaseMemory(ptpf);
|
|
return NULL;
|
|
}
|
|
|
|
// create a temporary place-holder file
|
|
fclose(fopen(tempName, (char *)"w"));
|
|
strcpy(ptpf->m_fileName, tempName);
|
|
|
|
|
|
// Make the argument array
|
|
if(!fnPipeFileMakeArgv(ptpf))
|
|
{
|
|
fnTempPipeFileReleaseMemory(ptpf);
|
|
|
|
// Release additional memory
|
|
if(ptpf->m_argv != NULL)
|
|
{
|
|
for(i=0; i<ptpf->m_argv_len; i++)
|
|
{
|
|
if(ptpf->m_argv[i] != NULL)
|
|
{
|
|
free(ptpf->m_argv[i]);
|
|
ptpf->m_argv[i] = NULL;
|
|
}
|
|
}
|
|
|
|
free(ptpf->m_argv);
|
|
ptpf->m_argv = NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// Open the temp file in the appropriate way...
|
|
//
|
|
if (!ptpf->m_mode) // If Read mode?
|
|
{
|
|
// we wish to spawn a command, intercept its output,
|
|
// and then get that output
|
|
//
|
|
if (!ptpf->m_argv[0])
|
|
{
|
|
fnTempPipeFileReleaseMemory(ptpf);
|
|
|
|
// Release additional memory
|
|
if(ptpf->m_argv != NULL)
|
|
{
|
|
for(i=0; i<ptpf->m_argv_len; i++)
|
|
{
|
|
if(ptpf->m_argv[i] != NULL)
|
|
{
|
|
free(ptpf->m_argv[i]);
|
|
ptpf->m_argv[i] = NULL;
|
|
}
|
|
}
|
|
|
|
free(ptpf->m_argv);
|
|
ptpf->m_argv = NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
if (ptpf->m_launchPerl)
|
|
fnPipeFileDoPerlLaunch(ptpf);
|
|
else
|
|
if (ptpf->m_doPerlGlob)
|
|
fnDoPerlGlob(ptpf->m_argv, ptpf->m_fileName); // hack to do perl globbing
|
|
else
|
|
spawnvp(P_WAIT, ptpf->m_argv[0], ptpf->m_argv);
|
|
|
|
ptpf->m_file = fopen (ptpf->m_fileName, (char *)"r"); // Get the Pipe file handle
|
|
}
|
|
else if (ptpf->m_mode) // If Write mode?
|
|
{
|
|
// we wish to open the file for writing now and
|
|
// do the command later
|
|
//
|
|
ptpf->m_file = fopen(ptpf->m_fileName, (char *)"w");
|
|
}
|
|
|
|
fnTempPipeFileReleaseMemory(ptpf);
|
|
|
|
// Release additional memory
|
|
if(ptpf->m_argv != NULL)
|
|
{
|
|
for(i=0; i<(ptpf->m_argv_len); i++)
|
|
{
|
|
if(ptpf->m_argv[i] != NULL)
|
|
{
|
|
free(ptpf->m_argv[i]);
|
|
ptpf->m_argv[i] = NULL;
|
|
}
|
|
}
|
|
|
|
free(ptpf->m_argv);
|
|
ptpf->m_argv = NULL;
|
|
}
|
|
|
|
|
|
return ptpf->m_file; // Return the Pipe file handle.
|
|
}
|
|
|
|
|
|
/*============================================================================================
|
|
|
|
Function : fnPipeFileClose
|
|
|
|
Description : This function closes the pipe file.
|
|
|
|
Parameters : ptpf (IN) - Input structure.
|
|
|
|
Returns : Nothing.
|
|
|
|
==============================================================================================*/
|
|
|
|
void fnPipeFileClose(PTEMPPIPEFILE ptpf)
|
|
{
|
|
int i = 0;
|
|
|
|
if (ptpf->m_mode) // If Write mode?
|
|
{
|
|
// we wish to spawn a command using our temp file for
|
|
// its input
|
|
//
|
|
if(ptpf->m_file != NULL)
|
|
{
|
|
fclose (ptpf->m_file);
|
|
ptpf->m_file = NULL;
|
|
}
|
|
|
|
if (ptpf->m_launchPerl)
|
|
fnPipeFileDoPerlLaunch(ptpf);
|
|
else if (ptpf->m_argv)
|
|
spawnvp(P_WAIT, ptpf->m_argv[0], ptpf->m_argv);
|
|
}
|
|
|
|
|
|
// Close the temporary Pipe File, if opened
|
|
if (ptpf->m_file)
|
|
{
|
|
fclose(ptpf->m_file);
|
|
ptpf->m_file = NULL;
|
|
}
|
|
// Delete the temporary Pipe Filename if still valid and free the memory associated with the file name.
|
|
if(ptpf->m_fileName != NULL)
|
|
{
|
|
// if (strlen(ptpf->m_fileName))
|
|
if (ptpf->m_fileName)
|
|
unlink(ptpf->m_fileName);
|
|
|
|
free(ptpf->m_fileName);
|
|
ptpf->m_fileName = NULL;
|
|
}
|
|
|
|
/**
|
|
if(ptpf->m_argv != NULL)
|
|
{
|
|
for(i=0; i<(ptpf->m_argv_len); i++)
|
|
{
|
|
if(ptpf->m_argv[i] != NULL)
|
|
{
|
|
free(ptpf->m_argv[i]);
|
|
ptpf->m_argv[i] = NULL;
|
|
}
|
|
}
|
|
|
|
free(ptpf->m_argv);
|
|
ptpf->m_argv = NULL;
|
|
}
|
|
**/
|
|
|
|
if (ptpf->m_perlSynchSemaphore)
|
|
{
|
|
#ifdef MPK_ON
|
|
kSemaphoreFree(ptpf->m_perlSynchSemaphore);
|
|
#else
|
|
CloseLocalSemaphore(ptpf->m_perlSynchSemaphore);
|
|
#endif //MPK_ON
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*============================================================================================
|
|
|
|
Function : fnPipeFileDoPerlLaunch
|
|
|
|
Description : This function launches Perl.
|
|
|
|
Parameters : ptpf (IN) - Input structure.
|
|
|
|
Returns : Nothing.
|
|
|
|
==============================================================================================*/
|
|
|
|
void fnPipeFileDoPerlLaunch(PTEMPPIPEFILE ptpf)
|
|
{
|
|
char curdir[_MAX_PATH] = {'\0'};
|
|
char* pcwd = NULL;
|
|
|
|
int i=0;
|
|
|
|
|
|
// save off the current working directory to restore later
|
|
// this is just a hack! these problems of synchronization and
|
|
// restoring calling context need a much better solution!
|
|
pcwd = (char *)getcwd(curdir, sizeof(curdir)-1);
|
|
fnSystemCommand(ptpf->m_argv, ptpf->m_argv_len);
|
|
if (ptpf->m_perlSynchSemaphore)
|
|
{
|
|
#ifdef MPK_ON
|
|
kSemaphoreWait(ptpf->m_perlSynchSemaphore);
|
|
#else
|
|
WaitOnLocalSemaphore(ptpf->m_perlSynchSemaphore);
|
|
#endif //MPK_ON
|
|
}
|
|
|
|
if (pcwd)
|
|
chdir(pcwd);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*============================================================================================
|
|
|
|
Function : fnTempPipeFile
|
|
|
|
Description : This function initialises the variables of the structure passed in.
|
|
|
|
Parameters : ptpf (IN) - Input structure.
|
|
|
|
Returns : Nothing.
|
|
|
|
==============================================================================================*/
|
|
|
|
void fnTempPipeFile(PTEMPPIPEFILE ptpf)
|
|
{
|
|
ptpf->m_fileName = NULL;
|
|
|
|
ptpf->m_mode = FALSE; // Default mode = Read mode.
|
|
ptpf->m_file = NULL;
|
|
ptpf->m_pipeCommand = NULL;
|
|
ptpf->m_argv = NULL;
|
|
|
|
ptpf->m_redirect = NULL;
|
|
|
|
ptpf->m_launchPerl = FALSE;
|
|
ptpf->m_doPerlGlob = FALSE;
|
|
|
|
#ifdef MPK_ON
|
|
ptpf->m_perlSynchSemaphore = NULL;
|
|
#else
|
|
ptpf->m_perlSynchSemaphore = 0L;
|
|
#endif
|
|
|
|
ptpf->m_argv_len = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*============================================================================================
|
|
|
|
Function : fnTempPipeFileReleaseMemory
|
|
|
|
Description : This function frees the memory allocated to various buffers.
|
|
|
|
Parameters : ptpf (IN) - Input structure.
|
|
|
|
Returns : Nothing.
|
|
|
|
==============================================================================================*/
|
|
|
|
void fnTempPipeFileReleaseMemory(PTEMPPIPEFILE ptpf)
|
|
{
|
|
int i=0;
|
|
|
|
|
|
if (ptpf->m_pipeCommand)
|
|
{
|
|
if(ptpf->m_pipeCommand->m_argv != NULL)
|
|
{
|
|
for(i=0; i<ptpf->m_pipeCommand->m_argv_len; i++)
|
|
{
|
|
if(ptpf->m_pipeCommand->m_argv[i] != NULL)
|
|
{
|
|
free(ptpf->m_pipeCommand->m_argv[i]);
|
|
ptpf->m_pipeCommand->m_argv[i] = NULL;
|
|
}
|
|
}
|
|
|
|
free(ptpf->m_pipeCommand->m_argv);
|
|
ptpf->m_pipeCommand->m_argv = NULL;
|
|
}
|
|
|
|
if(ptpf->m_pipeCommand->sSkippedToken != NULL)
|
|
{
|
|
free(ptpf->m_pipeCommand->sSkippedToken);
|
|
ptpf->m_pipeCommand->sSkippedToken = NULL;
|
|
}
|
|
/****
|
|
// Commented since these are not being used. Still retained here.
|
|
// To be removed once things are proved to be working fine to a good confident level,
|
|
|
|
if(ptpf->m_pipeCommand->nextarg)
|
|
{
|
|
free(ptpf->m_pipeCommand->nextarg);
|
|
ptpf->m_pipeCommand->nextarg = NULL;
|
|
}
|
|
|
|
if(ptpf->m_pipeCommand->m_redirInName)
|
|
{
|
|
free(ptpf->m_pipeCommand->m_redirInName);
|
|
ptpf->m_pipeCommand->m_redirInName = NULL;
|
|
}
|
|
if(ptpf->m_pipeCommand->m_redirOutName)
|
|
{
|
|
free(ptpf->m_pipeCommand->m_redirOutName);
|
|
ptpf->m_pipeCommand->m_redirOutName = NULL;
|
|
}
|
|
if(ptpf->m_pipeCommand->m_redirErrName)
|
|
{
|
|
free(ptpf->m_pipeCommand->m_redirErrName);
|
|
ptpf->m_pipeCommand->m_redirErrName = NULL;
|
|
}
|
|
if(ptpf->m_pipeCommand->m_redirBothName)
|
|
{
|
|
free(ptpf->m_pipeCommand->m_redirBothName);
|
|
ptpf->m_pipeCommand->m_redirBothName = NULL;
|
|
}
|
|
****/
|
|
|
|
if(ptpf->m_pipeCommand != NULL)
|
|
{
|
|
free(ptpf->m_pipeCommand);
|
|
ptpf->m_pipeCommand = NULL;
|
|
}
|
|
}
|
|
|
|
if(ptpf->m_redirect != NULL)
|
|
{
|
|
free(ptpf->m_redirect);
|
|
ptpf->m_redirect = NULL;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|