/* +----------------------------------------------------------------------+ | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2017 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Venkat Raghavan S | | Anantha Kesari H Y | +----------------------------------------------------------------------+ */ /* $Id$ */ #include #include #include #include "TSRM.h" #ifdef NETWARE #ifdef USE_MKFIFO #include #elif !defined(USE_PIPE_OPEN) /* NXFifoOpen */ #include #endif #include #include #include #include "mktemp.h" /* strtok() call in LibC is abending when used in a different address space * -- hence using PHP's version itself for now */ #include "tsrm_strtok_r.h" #define tsrm_strtok_r(a,b,c) strtok((a),(b)) #define WHITESPACE " \t" #define MAX_ARGS 10 TSRM_API FILE* popen(const char *commandline, const char *type) { char *command = NULL, *argv[MAX_ARGS] = {'\0'}, **env = NULL; char *tempName = "sys:/php/temp/phpXXXXXX.tmp"; char *filePath = NULL; char *ptr = NULL; int ptrLen = 0, argc = 0, i = 0, envCount = 0, err = 0; FILE *stream = NULL; #if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO) int pipe_handle; int mode = O_RDONLY; #else NXHandle_t pipe_handle; NXMode_t mode = NX_O_RDONLY; #endif NXExecEnvSpec_t envSpec; NXNameSpec_t nameSpec; NXVmId_t newVM = 0; /* Check for validity of input parameters */ if (!commandline || !type) return NULL; /* Get temporary file name */ filePath = mktemp(tempName); if (!filePath) return NULL; /* Set pipe mode according to type -- for now allow only "r" or "w" */ if (strcmp(type, "r") == 0) #if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO) mode = O_RDONLY; #else mode = NX_O_RDONLY; #endif else if (strcmp(type, "w") == 0) #if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO) mode = O_WRONLY; #else mode = NX_O_WRONLY; #endif else return NULL; #ifdef USE_PIPE_OPEN pipe_handle = pipe_open(filePath, mode); if (pipe_handle == -1) return NULL; #elif defined(USE_MKFIFO) pipe_handle = mkfifo(filePath, mode); if (pipe_handle == -1) return NULL; #else /* - NetWare doesn't require first parameter * - Allowing LibC to choose the buffer size for now */ err = NXFifoOpen(0, filePath, mode, 0, &pipe_handle); if (err) return NULL; #endif /* Copy the environment variables in preparation for the spawn call */ envCount = NXGetEnvCount() + 1; /* add one for NULL */ env = (char **) NXMemAlloc(sizeof(char *) * envCount, 0); if (!env) return NULL; err = NXCopyEnv(env, envCount); if (err) { NXMemFree (env); return NULL; } /* Separate commandline string into words */ ptr = tsrm_strtok_r((char*)commandline, WHITESPACE, NULL); ptrLen = strlen(ptr); command = (char*)malloc(ptrLen + 1); if (!command) { NXMemFree (env); return NULL; } strcpy (command, ptr); ptr = tsrm_strtok_r(NULL, WHITESPACE, NULL); while (ptr && (argc < MAX_ARGS)) { ptrLen = strlen(ptr); argv[argc] = (char*)malloc(ptrLen + 1); if (!argv[argc]) { NXMemFree (env); if (command) free (command); for (i = 0; i < argc; i++) { if (argv[i]) free (argv[i]); } return NULL; } strcpy (argv[argc], ptr); argc++; ptr = tsrm_strtok_r(NULL, WHITESPACE, NULL); } /* Setup the execution environment and spawn new process */ envSpec.esFlags = 0; /* Not used */ envSpec.esArgc = argc; envSpec.esArgv = (void **) argv; envSpec.esEnv = (void **) env; /* envSpec.esStdin.ssType = */ envSpec.esStdout.ssType = NX_OBJ_FIFO; envSpec.esStderr.ssType = NX_OBJ_FILE; /* 'ssHandle' is not a struct/union/class member */ /* envSpec.esStdin.ssHandle = envSpec.esStdout.ssHandle = envSpec.esStderr.ssHandle = -1; */ envSpec.esStdin.ssPathCtx = NULL; envSpec.esStdout.ssPathCtx = NULL; envSpec.esStderr.ssPathCtx = NULL; #if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO) if (mode == O_RDONLY) { #else if (mode == NX_O_RDONLY) { #endif envSpec.esStdin.ssPath = filePath; envSpec.esStdout.ssPath = stdout; } else { /* Write Only */ envSpec.esStdin.ssPath = stdin; envSpec.esStdout.ssPath = filePath; } envSpec.esStderr.ssPath = stdout; nameSpec.ssType = NX_OBJ_FIFO; /* nameSpec.ssHandle = 0; */ /* 'ssHandle' is not a struct/union/class member */ nameSpec.ssPathCtx = NULL; /* Not used */ nameSpec.ssPath = argv[0]; err = NXVmSpawn(&nameSpec, &envSpec, 0, &newVM); if (!err) /* Get file pointer corresponding to the pipe (file) opened */ stream = fdopen(pipe_handle, type); /* Clean-up */ if (env) NXMemFree (env); if (pipe_handle) #if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO) close(pipe_handle); #else NXClose(pipe_handle); #endif if (command) free (command); for (i = 0; i < argc; i++) { if (argv[i]) free (argv[i]); } return stream; } TSRM_API int pclose(FILE* stream) { int err = 0; NXHandle_t fd = 0; /* Get the process associated with this pipe (file) handle and terminate it */ fd = fileno(stream); NXClose (fd); err = fclose(stream); return err; } #endif /* NETWARE */