another threads reliability fix: serialize writes to thr->threadsv
[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 {
411 pid = spawn_cmd(cmd, Perl_stdin_fd, Perl_stdout_fd);
412 if (pid >= 0)
413 {
414 sv = *av_fetch(PL_fdpid,pFd[this],TRUE);
415 (void) SvUPGRADE(sv, SVt_IV);
416 SvIVX(sv) = pid;
417 fd = PerlIO_fdopen(pFd[this], mode);
418 close(pFd[that]);
419 }
420 else
421 fd = Nullfp;
422 }
423 else
424 {
425 sv = *av_fetch(PL_fdpid,pFd[that],TRUE);
426 (void) SvUPGRADE(sv, SVt_IV);
427 SvIVX(sv) = pFd[this];
428 fd = PerlIO_fdopen(pFd[this], mode);
429 }
430 }
431 else
432 fd = Nullfp;
433 return (fd);
434}
435
436/*===================== End of my_popen ====================*/
437
438/************************************************************/
439/* */
440/* Name - my_pclose. */
441/* */
442/* Function - Use pclose to terminate a piped command */
443/* file stream. */
444/* */
445/* On Entry - fd - FILE pointer. */
446/* */
447/* On Exit - Status returned. */
448/* */
449/************************************************************/
450
451long
452my_pclose(FILE *fp)
453{
454 int pid,
455 saveErrno,
456 status;
457 long rc,
458 wRc;
459 SV **sv;
460 FILE *other;
461
462 sv = av_fetch(PL_fdpid,PerlIO_fileno(fp),TRUE);
463 pid = (int) SvIVX(*sv);
464 SvREFCNT_dec(*sv);
465 *sv = &PL_sv_undef;
466 rc = PerlIO_close(fp);
467 saveErrno = errno;
468 do
469 {
470 wRc = waitpid(pid, &status, 0);
471 } while ((wRc == -1) && (errno == EINTR));
472 Perl_stdin_fd = STDIN_FILENO;
473 Perl_stdout_fd = STDOUT_FILENO;
474 errno = saveErrno;
475 if (rc != 0)
476 SETERRNO(errno, garbage);
477 return (rc);
478
479}
480
092bebab 481/************************************************************/
482/* */
483/* Name - dlopen. */
484/* */
485/* Function - Load a DLL. */
486/* */
487/* On Exit - */
488/* */
489/************************************************************/
490
491void *
492dlopen(const char *path)
493{
494 dllhandle *handle;
495
496fprintf(stderr,"Loading %s\n",path);
497 handle = dllload(path);
498 dl_retcode = errno;
499fprintf(stderr,"Handle %08X %s\n",handle,strerror(errno));
500 return ((void *) handle);
501}
502
503/*===================== End of dlopen ======================*/
504
505/************************************************************/
506/* */
507/* Name - dlsym. */
508/* */
509/* Function - Locate a DLL symbol. */
510/* */
511/* On Exit - */
512/* */
513/************************************************************/
514
515void *
516dlsym(void *handle, const char *symbol)
517{
518 void *symLoc;
519
520fprintf(stderr,"Finding %s\n",symbol);
521 symLoc = dllqueryvar((dllhandle *) handle, (char *) symbol);
522 if (symLoc == NULL)
523 symLoc = (void *) dllqueryfn((dllhandle *) handle,
524 (char *) symbol);
525 dl_retcode = errno;
526 return(symLoc);
527}
528
529/*===================== End of dlsym =======================*/
530
531/************************************************************/
532/* */
533/* Name - dlerror. */
534/* */
535/* Function - Return the last errno pertaining to a DLL */
536/* operation. */
537/* */
538/* On Exit - */
539/* */
540/************************************************************/
541
542void *
543dlerror(void)
544{
545 char * dlEmsg;
546
547 dlEmsg = strerror(dl_retcode);
548 dl_retcode = 0;
549 return(dlEmsg);
550}
551
552/*===================== End of dlerror =====================*/
553
554/************************************************************/
555/* */
556/* Name - TRUNCATE. */
557/* */
558/* Function - Truncate a file identified by 'path' to */
559/* a given length. */
560/* */
561/* On Entry - path - Path of file to be truncated. */
562/* length - length of truncated file. */
563/* */
564/* On Exit - retC - return code. */
565/* */
566/************************************************************/
567
568int
569truncate(const unsigned char *path, off_t length)
570{
571 int fd,
572 retC;
573
574 fd = open((const char *) path, O_RDWR);
575 if (fd > 0)
576 {
577 retC = ftruncate(fd, length);
578 close(fd);
579 }
580 else
581 retC = fd;
582 return(retC);
583}
584
585/*===================== End of trunc =======================*/