xref: /PHP-5.5/TSRM/tsrm_nw.c (revision 73c1be26)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2015 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Venkat Raghavan S <rvenkat@novell.com>                      |
16    |          Anantha Kesari H Y <hyanantha@novell.com>                   |
17    +----------------------------------------------------------------------+
18 */
19 
20 /* $Id$ */
21 
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <fcntl.h>
25 
26 #include "TSRM.h"
27 
28 #ifdef NETWARE
29 
30 #ifdef USE_MKFIFO
31 #include <sys/stat.h>
32 #elif !defined(USE_PIPE_OPEN)   /* NXFifoOpen */
33 #include <nks/fsio.h>
34 #endif
35 
36 #include <nks/vm.h>
37 #include <nks/memory.h>
38 
39 #include <string.h>
40 
41 #include "mktemp.h"
42 
43 /* strtok() call in LibC is abending when used in a different address space
44  * -- hence using PHP's version itself for now
45  */
46 #include "tsrm_strtok_r.h"
47 #define tsrm_strtok_r(a,b,c) strtok((a),(b))
48 
49 #define WHITESPACE  " \t"
50 #define MAX_ARGS    10
51 
52 
popen(const char * commandline,const char * type)53 TSRM_API FILE* popen(const char *commandline, const char *type)
54 {
55 	char *command = NULL, *argv[MAX_ARGS] = {'\0'}, **env = NULL;
56 	char *tempName = "sys:/php/temp/phpXXXXXX.tmp";
57 	char *filePath = NULL;
58 	char *ptr = NULL;
59 	int ptrLen = 0, argc = 0, i = 0, envCount = 0, err = 0;
60 	FILE *stream = NULL;
61 #if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
62 	int pipe_handle;
63 	int mode = O_RDONLY;
64 #else
65 	NXHandle_t pipe_handle;
66 	NXMode_t mode = NX_O_RDONLY;
67 #endif
68 	NXExecEnvSpec_t envSpec;
69 	NXNameSpec_t nameSpec;
70 	NXVmId_t newVM = 0;
71 
72 	/* Check for validity of input parameters */
73 	if (!commandline || !type)
74 		return NULL;
75 
76 	/* Get temporary file name */
77 	filePath = mktemp(tempName);
78 	if (!filePath)
79 		return NULL;
80 
81 	/* Set pipe mode according to type -- for now allow only "r" or "w" */
82 	if (strcmp(type, "r") == 0)
83 #if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
84 		mode = O_RDONLY;
85 #else
86 		mode = NX_O_RDONLY;
87 #endif
88 	else if (strcmp(type, "w") == 0)
89 #if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
90 		mode = O_WRONLY;
91 #else
92 		mode = NX_O_WRONLY;
93 #endif
94 	else
95 		return NULL;
96 
97 #ifdef USE_PIPE_OPEN
98 	pipe_handle = pipe_open(filePath, mode);
99 	if (pipe_handle == -1)
100 		return NULL;
101 #elif defined(USE_MKFIFO)
102 	pipe_handle = mkfifo(filePath, mode);
103 	if (pipe_handle == -1)
104 		return NULL;
105 #else
106 	/* - NetWare doesn't require first parameter
107 	 * - Allowing LibC to choose the buffer size for now
108 	 */
109 	err = NXFifoOpen(0, filePath, mode, 0, &pipe_handle);
110 	if (err)
111 		return NULL;
112 #endif
113 
114 	/* Copy the environment variables in preparation for the spawn call */
115 	envCount = NXGetEnvCount() + 1;  /* add one for NULL */
116 	env = (char **) NXMemAlloc(sizeof(char *) * envCount, 0);
117 	if (!env)
118 		return NULL;
119 
120 	err = NXCopyEnv(env, envCount);
121 	if (err) {
122 		NXMemFree (env);
123 		return NULL;
124 	}
125 
126 	/* Separate commandline string into words */
127 	ptr = tsrm_strtok_r((char*)commandline, WHITESPACE, NULL);
128 	ptrLen = strlen(ptr);
129 
130 	command = (char*)malloc(ptrLen + 1);
131 	if (!command) {
132 		NXMemFree (env);
133 		return NULL;
134 	}
135 
136 	strcpy (command, ptr);
137 
138 	ptr = tsrm_strtok_r(NULL, WHITESPACE, NULL);
139 	while (ptr && (argc < MAX_ARGS)) {
140 		ptrLen = strlen(ptr);
141 
142 		argv[argc] = (char*)malloc(ptrLen + 1);
143 		if (!argv[argc]) {
144 			NXMemFree (env);
145 			if (command)
146 				free (command);
147 
148 			for (i = 0; i < argc; i++) {
149 				if (argv[i])
150 					free (argv[i]);
151 			}
152 
153 			return NULL;
154 		}
155 
156 		strcpy (argv[argc], ptr);
157 		argc++;
158 		ptr = tsrm_strtok_r(NULL, WHITESPACE, NULL);
159 	}
160 
161 	/* Setup the execution environment and spawn new process */
162 	envSpec.esFlags = 0;    /* Not used */
163 	envSpec.esArgc = argc;
164 	envSpec.esArgv = (void **) argv;
165 	envSpec.esEnv = (void **) env;
166 
167 /*	envSpec.esStdin.ssType = */
168 	envSpec.esStdout.ssType = NX_OBJ_FIFO;
169 	envSpec.esStderr.ssType = NX_OBJ_FILE;
170 
171 	/* 'ssHandle' is not a struct/union/class member */
172 /*
173 	envSpec.esStdin.ssHandle =
174 	envSpec.esStdout.ssHandle =
175 	envSpec.esStderr.ssHandle = -1;
176 */
177 	envSpec.esStdin.ssPathCtx = NULL;
178 	envSpec.esStdout.ssPathCtx = NULL;
179 	envSpec.esStderr.ssPathCtx = NULL;
180 
181 #if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
182 	if (mode == O_RDONLY) {
183 #else
184 	if (mode == NX_O_RDONLY) {
185 #endif
186 		envSpec.esStdin.ssPath = filePath;
187 		envSpec.esStdout.ssPath = stdout;
188 	} else { /* Write Only */
189 		envSpec.esStdin.ssPath = stdin;
190 		envSpec.esStdout.ssPath = filePath;
191 	}
192 
193 	envSpec.esStderr.ssPath = stdout;
194 
195 	nameSpec.ssType = NX_OBJ_FIFO;
196 /*	nameSpec.ssHandle = 0; */	/* 'ssHandle' is not a struct/union/class member */
197 	nameSpec.ssPathCtx = NULL;  /* Not used */
198 	nameSpec.ssPath = argv[0];
199 	err = NXVmSpawn(&nameSpec, &envSpec, 0, &newVM);
200 	if (!err)
201 		/* Get file pointer corresponding to the pipe (file) opened */
202 		stream = fdopen(pipe_handle, type);
203 
204 	/* Clean-up */
205 	if (env)
206 		NXMemFree (env);
207 
208 	if (pipe_handle)
209 #if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
210 		close(pipe_handle);
211 #else
212 		NXClose(pipe_handle);
213 #endif
214 
215 	if (command)
216 		free (command);
217 
218 	for (i = 0; i < argc; i++) {
219 		if (argv[i])
220 			free (argv[i]);
221 	}
222 
223 	return stream;
224 }
225 
226 TSRM_API int pclose(FILE* stream)
227 {
228 	int err = 0;
229 	NXHandle_t fd = 0;
230 
231 	/* Get the process associated with this pipe (file) handle and terminate it */
232 	fd = fileno(stream);
233 	NXClose (fd);
234 
235 	err = fclose(stream);
236 
237 	return err;
238 }
239 
240 #endif	/* NETWARE */
241