mirror of
https://github.com/php/php-src.git
synced 2024-12-12 19:33:31 +08:00
241 lines
5.9 KiB
C
241 lines
5.9 KiB
C
/*
|
|
+----------------------------------------------------------------------+
|
|
| PHP Version 7 |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 1997-2014 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 <rvenkat@novell.com> |
|
|
| Anantha Kesari H Y <hyanantha@novell.com> |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
/* $Id$ */
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "TSRM.h"
|
|
|
|
#ifdef NETWARE
|
|
|
|
#ifdef USE_MKFIFO
|
|
#include <sys/stat.h>
|
|
#elif !defined(USE_PIPE_OPEN) /* NXFifoOpen */
|
|
#include <nks/fsio.h>
|
|
#endif
|
|
|
|
#include <nks/vm.h>
|
|
#include <nks/memory.h>
|
|
|
|
#include <string.h>
|
|
|
|
#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 */
|