diff options
Diffstat (limited to 'NetWare/Nwpipe.c')
-rw-r--r-- | NetWare/Nwpipe.c | 704 |
1 files changed, 704 insertions, 0 deletions
diff --git a/NetWare/Nwpipe.c b/NetWare/Nwpipe.c new file mode 100644 index 0000000000..2da2b065c3 --- /dev/null +++ b/NetWare/Nwpipe.c @@ -0,0 +1,704 @@ + +/* + * 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", DEFTEMP), (_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; +} + |