1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2013 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