better variant of change#4644 (from Andy Dougherty)
[p5sagit/p5-mst-13.2.git] / vmesa / vmesa.c
CommitLineData
092bebab 1/************************************************************/
2/* */
3/* Module ID - vmesa.c */
4/* */
5/* Function - Provide operating system dependent process- */
6/* ing for perl under VM/ESA. */
7/* */
8/* Parameters - See individual entry points. */
9/* */
10/* Called By - N/A - see individual entry points. */
11/* */
12/* Calling To - N/A - see individual entry points. */
13/* */
14/* Notes - (1) ....................................... */
15/* */
16/* (2) ....................................... */
17/* */
18/* Name - Neale Ferguson. */
19/* */
20/* Date - August, 1998. */
21/* */
22/* */
23/* Associated - (1) Refer To ........................... */
24/* Documentation */
25/* (2) Refer To ........................... */
26/* */
27/************************************************************/
28/************************************************************/
29/* */
30/* MODULE MAINTENANCE HISTORY */
31/* -------------------------- */
32/* */
33static char REQ_REL_WHO [13] =
34/*-------------- -------------------------------------*/
35 "9999_99 NAF "; /* Original module */
36/* */
37/*============ End of Module Maintenance History ===========*/
38
39/************************************************************/
40/* */
41/* DEFINES */
42/* ------- */
43/* */
44/************************************************************/
45
46#define FAIL 65280
47
48/*=============== END OF DEFINES ===========================*/
49
50/************************************************************/
51/* */
52/* INCLUDE STATEMENTS */
53/* ------------------ */
54/* */
55/************************************************************/
56
57#include <stdio.h>
58#include <stdlib.h>
59#include <spawn.h>
60#include <fcntl.h>
61#include <unistd.h>
62#include <pthread.h>
63#include <dll.h>
64#include "EXTERN.h"
65#include "perl.h"
66#pragma map(truncate, "@@TRUNC")
67
68/*================== End of Include Statements =============*/
69
70/************************************************************/
71/* */
72/* Global Variables */
73/* ---------------- */
74/* */
75/************************************************************/
76
77static int Perl_stdin_fd = STDIN_FILENO,
78 Perl_stdout_fd = STDOUT_FILENO;
79
80static long dl_retcode = 0;
81
82/*================== End of Global Variables ===============*/
83
84/************************************************************/
85/* */
86/* FUNCTION PROTOTYPES */
87/* ------------------- */
88/* */
89/************************************************************/
90
91int do_aspawn(SV *, SV **, SV **);
92int do_spawn(char *, int);
93static int spawnit(char *);
94static pid_t spawn_cmd(char *, int, int);
95struct perl_thread * getTHR(void);
96
97/*================== End of Prototypes =====================*/
98
99/************************************************************/
100/* */
101/* D O _ A S P A W N */
102/* ----------------- */
103/* */
104/************************************************************/
105
106int
107do_aspawn(SV* really, SV **mark, SV **sp)
108{
109 char **a,
110 *tmps;
111 struct inheritance inherit;
112 pid_t pid;
113 int status,
114 fd,
115 nFd,
116 fdMap[3];
117 SV *sv,
118 **p_sv;
2d8e6c8d 119 STRLEN n_a;
092bebab 120
121 status = FAIL;
122 if (sp > mark)
123 {
124 dTHR;
125 New(401,PL_Argv, sp - mark + 1, char*);
126 a = PL_Argv;
127 while (++mark <= sp)
128 {
129 if (*mark)
2d8e6c8d 130 *a++ = SvPVx(*mark, n_a);
092bebab 131 else
132 *a++ = "";
133 }
134 inherit.flags = SPAWN_SETGROUP;
135 inherit.pgroup = SPAWN_NEWPGROUP;
136 fdMap[STDIN_FILENO] = Perl_stdin_fd;
137 fdMap[STDOUT_FILENO] = Perl_stdout_fd;
138 fdMap[STDERR_FILENO] = STDERR_FILENO;
139 nFd = 3;
140 *a = Nullch;
141 /*-----------------------------------------------------*/
142 /* Will execvp() use PATH? */
143 /*-----------------------------------------------------*/
144 if (*PL_Argv[0] != '/')
145 TAINT_ENV();
2d8e6c8d 146 if (really && *(tmps = SvPV(really, n_a)))
092bebab 147 pid = spawnp(tmps, nFd, fdMap, &inherit,
148 (const char **) PL_Argv,
149 (const char **) environ);
150 else
151 pid = spawnp(PL_Argv[0], nFd, fdMap, &inherit,
152 (const char **) PL_Argv,
153 (const char **) environ);
154 if (pid < 0)
155 {
156 status = FAIL;
157 if (ckWARN(WARN_EXEC))
158 warner(WARN_EXEC,"Can't exec \"%s\": %s",
159 PL_Argv[0],
160 Strerror(errno));
161 }
162 else
163 {
164 /*------------------------------------------------*/
165 /* If the file descriptors have been remapped then*/
166 /* we've been called following a my_popen request */
167 /* therefore we don't want to wait for spawnned */
168 /* program to complete. We need to set the fdpid */
169 /* value to the value of the spawnned process' pid*/
170 /*------------------------------------------------*/
171 fd = 0;
172 if (Perl_stdin_fd != STDIN_FILENO)
173 fd = Perl_stdin_fd;
174 else
175 if (Perl_stdout_fd != STDOUT_FILENO)
176 fd = Perl_stdout_fd;
177 if (fd != 0)
178 {
179 /*---------------------------------------------*/
180 /* Get the fd of the other end of the pipe, */
181 /* use this to reference the fdpid which will */
182 /* be used by my_pclose */
183 /*---------------------------------------------*/
184 close(fd);
185 p_sv = av_fetch(PL_fdpid,fd,TRUE);
186 fd = (int) SvIVX(*p_sv);
187 SvREFCNT_dec(*p_sv);
188 *p_sv = &PL_sv_undef;
189 sv = *av_fetch(PL_fdpid,fd,TRUE);
190 (void) SvUPGRADE(sv, SVt_IV);
191 SvIVX(sv) = pid;
192 status = 0;
193 }
194 else
195 wait4pid(pid, &status, 0);
196 }
197 do_execfree();
198 }
199 return (status);
200}
201
202/*===================== End of do_aspawn ===================*/
203
204/************************************************************/
205/* */
206/* D O _ S P A W N */
207/* --------------- */
208/* */
209/************************************************************/
210
211int
212do_spawn(char *cmd, int execf)
213{
214 char **a,
215 *s,
216 flags[10];
217 int status,
218 nFd,
219 fdMap[3];
220 struct inheritance inherit;
221 pid_t pid;
222
223 while (*cmd && isSPACE(*cmd))
224 cmd++;
225
226 /*------------------------------------------------------*/
227 /* See if there are shell metacharacters in it */
228 /*------------------------------------------------------*/
229
230 if (*cmd == '.' && isSPACE(cmd[1]))
231 return (spawnit(cmd));
232 else
233 {
234 if (strnEQ(cmd,"exec",4) && isSPACE(cmd[4]))
235 return (spawnit(cmd));
236 else
237 {
238 /*------------------------------------------------*/
239 /* Catch VAR=val gizmo */
240 /*------------------------------------------------*/
241 for (s = cmd; *s && isALPHA(*s); s++);
242 if (*s != '=')
243 {
244 for (s = cmd; *s; s++)
245 {
246 if (*s != ' ' &&
247 !isALPHA(*s) &&
248 strchr("$&*(){}[]'\";\\|?<>~`\n",*s))
249 {
250 if (*s == '\n' && !s[1])
251 {
252 *s = '\0';
253 break;
254 }
255 return(spawnit(cmd));
256 }
257 }
258 }
259 }
260 }
261
262 New(402,PL_Argv, (s - cmd) / 2 + 2, char*);
263 PL_Cmd = savepvn(cmd, s-cmd);
264 a = PL_Argv;
265 for (s = PL_Cmd; *s;)
266 {
267 while (*s && isSPACE(*s)) s++;
268 if (*s)
269 *(a++) = s;
270 while (*s && !isSPACE(*s)) s++;
271 if (*s)
272 *s++ = '\0';
273 }
274 *a = Nullch;
275 fdMap[STDIN_FILENO] = Perl_stdin_fd;
276 fdMap[STDOUT_FILENO] = Perl_stdout_fd;
277 fdMap[STDERR_FILENO] = STDERR_FILENO;
278 nFd = 3;
279 inherit.flags = 0;
280 if (PL_Argv[0])
281 {
282 pid = spawnp(PL_Argv[0], nFd, fdMap, &inherit,
283 (const char **) PL_Argv,
284 (const char **) environ);
285 if (pid < 0)
286 {
287 dTHR;
288 status = FAIL;
289 if (ckWARN(WARN_EXEC))
290 warner(WARN_EXEC,"Can't exec \"%s\": %s",
291 PL_Argv[0],
292 Strerror(errno));
293 }
294 else
295 wait4pid(pid, &status, 0);
296 }
297 do_execfree();
298 return (status);
299}
300
301/*===================== End of do_spawn ====================*/
302
303/************************************************************/
304/* */
305/* Name - spawnit. */
306/* */
307/* Function - Spawn command and return status. */
308/* */
309/* On Entry - cmd - command to be spawned. */
310/* */
311/* On Exit - status returned. */
312/* */
313/************************************************************/
314
315int
316spawnit(char *cmd)
317{
318 pid_t pid;
319 int status;
320
321 pid = spawn_cmd(cmd, STDIN_FILENO, STDOUT_FILENO);
322 if (pid < 0)
323 status = FAIL;
324 else
325 wait4pid(pid, &status, 0);
326
327 return (status);
328}
329
330/*===================== End of spawnit =====================*/
331
332/************************************************************/
333/* */
334/* Name - spawn_cmd. */
335/* */
336/* Function - Spawn command and return pid. */
337/* */
338/* On Entry - cmd - command to be spawned. */
339/* */
340/* On Exit - pid returned. */
341/* */
342/************************************************************/
343
344pid_t
345spawn_cmd(char *cmd, int inFd, int outFd)
346{
347 struct inheritance inherit;
348 pid_t pid;
349 const char *argV[4] = {"/bin/sh","-c",NULL,NULL};
350 int nFd,
351 fdMap[3];
352
353 argV[2] = cmd;
354 fdMap[STDIN_FILENO] = inFd;
355 fdMap[STDOUT_FILENO] = outFd;
356 fdMap[STDERR_FILENO] = STDERR_FILENO;
357 nFd = 3;
358 inherit.flags = SPAWN_SETGROUP;
359 inherit.pgroup = SPAWN_NEWPGROUP;
360 pid = spawn(argV[0], nFd, fdMap, &inherit,
361 argV, (const char **) environ);
362 return (pid);
363}
364
365/*===================== End of spawnit =====================*/
366
367/************************************************************/
368/* */
369/* Name - my_popen. */
370/* */
371/* Function - Use popen to execute a command return a */
372/* file descriptor. */
373/* */
374/* On Entry - cmd - command to be executed. */
375/* */
376/* On Exit - FILE * returned. */
377/* */
378/************************************************************/
379
380#include <ctest.h>
381PerlIO *
382my_popen(char *cmd, char *mode)
383{
384 FILE *fd;
385 int pFd[2],
386 this,
387 that,
388 pid;
389 SV *sv;
390
391 if (PerlProc_pipe(pFd) >= 0)
392 {
393 this = (*mode == 'w');
394 that = !this;
395 /*-------------------------------------------------*/
396 /* If this is a read mode pipe */
397 /* - map the write end of the pipe to STDOUT */
398 /* - return the *FILE for the read end of the pipe */
399 /*-------------------------------------------------*/
400 if (!this)
401 Perl_stdout_fd = pFd[that];
402 /*-------------------------------------------------*/
403 /* Else */
404 /* - map the read end of the pipe to STDIN */
405 /* - return the *FILE for the write end of the pipe*/
406 /*-------------------------------------------------*/
407 else
408 Perl_stdin_fd = pFd[that];
409 if (strNE(cmd,"-"))
410 {
45bc9206 411 PERL_FLUSHALL_FOR_CHILD;
092bebab 412 pid = spawn_cmd(cmd, Perl_stdin_fd, Perl_stdout_fd);
413 if (pid >= 0)
414 {
415 sv = *av_fetch(PL_fdpid,pFd[this],TRUE);
416 (void) SvUPGRADE(sv, SVt_IV);
417 SvIVX(sv) = pid;
418 fd = PerlIO_fdopen(pFd[this], mode);
419 close(pFd[that]);
420 }
421 else
422 fd = Nullfp;
423 }
424 else
425 {
426 sv = *av_fetch(PL_fdpid,pFd[that],TRUE);
427 (void) SvUPGRADE(sv, SVt_IV);
428 SvIVX(sv) = pFd[this];
429 fd = PerlIO_fdopen(pFd[this], mode);
430 }
431 }
432 else
433 fd = Nullfp;
434 return (fd);
435}
436
437/*===================== End of my_popen ====================*/
438
439/************************************************************/
440/* */
441/* Name - my_pclose. */
442/* */
443/* Function - Use pclose to terminate a piped command */
444/* file stream. */
445/* */
446/* On Entry - fd - FILE pointer. */
447/* */
448/* On Exit - Status returned. */
449/* */
450/************************************************************/
451
452long
453my_pclose(FILE *fp)
454{
455 int pid,
456 saveErrno,
457 status;
458 long rc,
459 wRc;
460 SV **sv;
461 FILE *other;
462
463 sv = av_fetch(PL_fdpid,PerlIO_fileno(fp),TRUE);
464 pid = (int) SvIVX(*sv);
465 SvREFCNT_dec(*sv);
466 *sv = &PL_sv_undef;
467 rc = PerlIO_close(fp);
468 saveErrno = errno;
469 do
470 {
471 wRc = waitpid(pid, &status, 0);
472 } while ((wRc == -1) && (errno == EINTR));
473 Perl_stdin_fd = STDIN_FILENO;
474 Perl_stdout_fd = STDOUT_FILENO;
475 errno = saveErrno;
476 if (rc != 0)
477 SETERRNO(errno, garbage);
478 return (rc);
479
480}
481
092bebab 482/************************************************************/
483/* */
484/* Name - dlopen. */
485/* */
486/* Function - Load a DLL. */
487/* */
488/* On Exit - */
489/* */
490/************************************************************/
491
492void *
493dlopen(const char *path)
494{
495 dllhandle *handle;
496
497fprintf(stderr,"Loading %s\n",path);
498 handle = dllload(path);
499 dl_retcode = errno;
500fprintf(stderr,"Handle %08X %s\n",handle,strerror(errno));
501 return ((void *) handle);
502}
503
504/*===================== End of dlopen ======================*/
505
506/************************************************************/
507/* */
508/* Name - dlsym. */
509/* */
510/* Function - Locate a DLL symbol. */
511/* */
512/* On Exit - */
513/* */
514/************************************************************/
515
516void *
517dlsym(void *handle, const char *symbol)
518{
519 void *symLoc;
520
521fprintf(stderr,"Finding %s\n",symbol);
522 symLoc = dllqueryvar((dllhandle *) handle, (char *) symbol);
523 if (symLoc == NULL)
524 symLoc = (void *) dllqueryfn((dllhandle *) handle,
525 (char *) symbol);
526 dl_retcode = errno;
527 return(symLoc);
528}
529
530/*===================== End of dlsym =======================*/
531
532/************************************************************/
533/* */
534/* Name - dlerror. */
535/* */
536/* Function - Return the last errno pertaining to a DLL */
537/* operation. */
538/* */
539/* On Exit - */
540/* */
541/************************************************************/
542
543void *
544dlerror(void)
545{
546 char * dlEmsg;
547
548 dlEmsg = strerror(dl_retcode);
549 dl_retcode = 0;
550 return(dlEmsg);
551}
552
553/*===================== End of dlerror =====================*/
554
555/************************************************************/
556/* */
557/* Name - TRUNCATE. */
558/* */
559/* Function - Truncate a file identified by 'path' to */
560/* a given length. */
561/* */
562/* On Entry - path - Path of file to be truncated. */
563/* length - length of truncated file. */
564/* */
565/* On Exit - retC - return code. */
566/* */
567/************************************************************/
568
569int
570truncate(const unsigned char *path, off_t length)
571{
572 int fd,
573 retC;
574
575 fd = open((const char *) path, O_RDWR);
576 if (fd > 0)
577 {
578 retC = ftruncate(fd, length);
579 close(fd);
580 }
581 else
582 retC = fd;
583 return(retC);
584}
585
586/*===================== End of trunc =======================*/