4 Interface for perl process functions
14 #define EXECF_SPAWN_NOWAIT 3
16 class CPerlProc : public IPerlProc
22 w32_perlshell_tokens = NULL;
23 w32_perlshell_items = -1;
29 virtual void Abort(void);
30 virtual void Exit(int status);
31 virtual void _Exit(int status);
32 virtual int Execl(const char *cmdname, const char *arg0, const char *arg1, const char *arg2, const char *arg3);
33 virtual int Execv(const char *cmdname, const char *const *argv);
34 virtual int Execvp(const char *cmdname, const char *const *argv);
35 virtual uid_t Getuid(void);
36 virtual uid_t Geteuid(void);
37 virtual gid_t Getgid(void);
38 virtual gid_t Getegid(void);
39 virtual char *Getlogin(void);
40 virtual int Kill(int pid, int sig);
41 virtual int Killpg(int pid, int sig);
42 virtual int PauseProc(void);
43 virtual PerlIO* Popen(const char *command, const char *mode);
44 virtual int Pclose(PerlIO *stream);
45 virtual int Pipe(int *phandles);
46 virtual int Setuid(uid_t u);
47 virtual int Setgid(gid_t g);
48 virtual int Sleep(unsigned int);
49 virtual int Times(struct tms *timebuf);
50 virtual int Wait(int *status);
51 virtual Sighandler_t Signal(int sig, Sighandler_t subcode);
52 virtual void GetSysMsg(char*& msg, DWORD& dwLen, DWORD dwErr);
53 virtual void FreeBuf(char* msg);
54 virtual BOOL DoCmd(char *cmd);
55 virtual int Spawn(char*cmds);
56 virtual int Spawnvp(int mode, const char *cmdname, const char *const *argv);
57 virtual int ASpawn(void *vreally, void **vmark, void **vsp);
59 inline void SetPerlObj(CPerlObj *p) { pPerl = p; };
61 int Spawn(char *cmd, int exectype);
63 long Tokenize(char *str, char **dest, char ***destv);
65 inline int IsWin95(void)
67 return (os_id() == VER_PLATFORM_WIN32_WINDOWS);
69 inline int IsWinNT(void)
71 return (os_id() == VER_PLATFORM_WIN32_NT);
74 inline long filetime_to_clock(PFILETIME ft)
76 __int64 qw = ft->dwHighDateTime;
78 qw |= ft->dwLowDateTime;
79 qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */
85 if((-1) == w32_platform)
89 memset(&osver, 0, sizeof(OSVERSIONINFO));
90 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
92 w32_platform = osver.dwPlatformId;
94 return (w32_platform);
98 char szLoginNameStr[128];
99 char *w32_perlshell_tokens;
100 long w32_perlshell_items;
101 char **w32_perlshell_vec;
103 long w32_num_children;
104 HANDLE w32_child_pids[MAXIMUM_WAIT_OBJECTS];
111 has_redirection(char *ptr)
117 * Scan string looking for redirection (< or >) or pipe
118 * characters (|) that are not in a quoted string
148 /* Tokenize a string. Words are null-separated, and the list
149 * ends with a doubled null. Any character (except null and
150 * including backslash) may be escaped by preceding it with a
151 * backslash (the backslash will be stripped).
152 * Returns number of words in result buffer.
155 CPerlProc::Tokenize(char *str, char **dest, char ***destv)
157 char *retstart = Nullch;
158 char **retvstart = 0;
161 int slen = strlen(str);
163 register char **retv;
164 New(1307, ret, slen+2, char);
165 New(1308, retv, (slen+3)/2, char*);
173 if (*ret == '\\' && *str)
175 else if (*ret == ' ') {
191 retvstart[items] = Nullch;
202 CPerlProc::GetShell(void)
204 if (!w32_perlshell_tokens) {
205 /* we don't use COMSPEC here for two reasons:
206 * 1. the same reason perl on UNIX doesn't use SHELL--rampant and
207 * uncontrolled unportability of the ensuing scripts.
208 * 2. PERL5SHELL could be set to a shell that may not be fit for
209 * interactive use (which is what most programs look in COMSPEC
212 char* defaultshell = (IsWinNT() ? "cmd.exe /x/c" : "command.com /c");
213 char* usershell = getenv("PERL5SHELL");
214 w32_perlshell_items = Tokenize(usershell ? usershell : defaultshell,
215 &w32_perlshell_tokens,
221 CPerlProc::ASpawn(void *vreally, void **vmark, void **vsp)
223 SV *really = (SV*)vreally;
224 SV **mark = (SV**)vmark;
236 New(1306, argv, (sp - mark) + w32_perlshell_items + 2, char*);
238 if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
243 while(++mark <= sp) {
244 if (*mark && (str = SvPV(*mark, na)))
251 status = Spawnvp(flag,
252 (really ? SvPV(really,na) : argv[0]),
253 (const char* const*)argv);
255 if (status < 0 && errno == ENOEXEC) {
256 /* possible shell-builtin, invoke with shell */
258 sh_items = w32_perlshell_items;
260 argv[index+sh_items] = argv[index];
261 while (--sh_items >= 0)
262 argv[sh_items] = w32_perlshell_vec[sh_items];
264 status = Spawnvp(flag,
265 (really ? SvPV(really,na) : argv[0]),
266 (const char* const*)argv);
270 if (pPerl->Perl_dowarn)
271 warn("Can't spawn \"%s\": %s", argv[0], strerror(errno));
274 else if (flag != P_NOWAIT)
277 return (pPerl->Perl_statusvalue = status);
282 CPerlProc::Spawn(char *cmd, int exectype)
288 BOOL needToTry = TRUE;
291 /* Save an extra exec if possible. See if there are shell
292 * metacharacters in it */
293 if(!has_redirection(cmd)) {
294 New(1301,argv, strlen(cmd) / 2 + 2, char*);
295 New(1302,cmd2, strlen(cmd) + 1, char);
298 for (s = cmd2; *s;) {
299 while (*s && isspace(*s))
303 while(*s && !isspace(*s))
312 status = Spawnvp(P_WAIT, argv[0],
313 (const char* const*)argv);
315 case EXECF_SPAWN_NOWAIT:
316 status = Spawnvp(P_NOWAIT, argv[0],
317 (const char* const*)argv);
320 status = Execvp(argv[0], (const char* const*)argv);
323 if (status != -1 || errno == 0)
333 New(1306, argv, w32_perlshell_items + 2, char*);
334 while (++i < w32_perlshell_items)
335 argv[i] = w32_perlshell_vec[i];
340 status = Spawnvp(P_WAIT, argv[0],
341 (const char* const*)argv);
343 case EXECF_SPAWN_NOWAIT:
344 status = Spawnvp(P_NOWAIT, argv[0],
345 (const char* const*)argv);
348 status = Execvp(argv[0], (const char* const*)argv);
355 if (pPerl->Perl_dowarn)
356 warn("Can't %s \"%s\": %s",
357 (exectype == EXECF_EXEC ? "exec" : "spawn"),
358 cmd, strerror(errno));
361 else if (exectype != EXECF_SPAWN_NOWAIT)
363 return (pPerl->Perl_statusvalue = status);
367 void CPerlProc::Abort(void)
372 void CPerlProc::Exit(int status)
377 void CPerlProc::_Exit(int status)
382 int CPerlProc::Execl(const char *cmdname, const char *arg0, const char *arg1, const char *arg2, const char *arg3)
384 return execl(cmdname, arg0, arg1, arg2, arg3);
387 int CPerlProc::Execv(const char *cmdname, const char *const *argv)
389 return execv(cmdname, argv);
392 int CPerlProc::Execvp(const char *cmdname, const char *const *argv)
394 return execvp(cmdname, argv);
397 #define ROOT_UID ((uid_t)0)
398 #define ROOT_GID ((gid_t)0)
400 uid_t CPerlProc::Getuid(void)
405 uid_t CPerlProc::Geteuid(void)
410 gid_t CPerlProc::Getgid(void)
415 gid_t CPerlProc::Getegid(void)
421 char *CPerlProc::Getlogin(void)
423 char unknown[] = "<Unknown>";
426 len = sizeof(szLoginNameStr);
427 if(!GetUserName(szLoginNameStr, &len))
429 strcpy(szLoginNameStr, unknown);
431 return szLoginNameStr;
434 int CPerlProc::Kill(int pid, int sig)
438 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
440 croak("kill process failed!\n");
442 if(TerminateProcess(hProcess, 0) == FALSE)
443 croak("kill process failed!\n");
445 CloseHandle(hProcess);
449 int CPerlProc::Killpg(int pid, int sig)
451 croak("killpg not implemented!\n");
455 int CPerlProc::PauseProc(void)
457 Sleep((unsigned int)((32767L << 16) + 32767));
461 PerlIO* CPerlProc::Popen(const char *command, const char *mode)
463 return (PerlIO*)_popen(command, mode);
466 int CPerlProc::Pclose(PerlIO *pf)
468 return _pclose((FILE*)pf);
471 int CPerlProc::Pipe(int *phandles)
473 return _pipe(phandles, 512, O_BINARY);
476 int CPerlProc::Sleep(unsigned int s)
482 int CPerlProc::Times(struct tms *timebuf)
487 if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
489 timebuf->tms_utime = filetime_to_clock(&user);
490 timebuf->tms_stime = filetime_to_clock(&kernel);
491 timebuf->tms_cutime = 0;
492 timebuf->tms_cstime = 0;
495 /* That failed - e.g. Win95 fallback to clock() */
497 timebuf->tms_utime = t;
498 timebuf->tms_stime = 0;
499 timebuf->tms_cutime = 0;
500 timebuf->tms_cstime = 0;
505 int CPerlProc::Wait(int *status)
510 /* XXX this wait emulation only knows about processes
511 * spawned via win32_spawnvp(P_NOWAIT, ...).
514 DWORD exitcode, waitcode;
516 if (!w32_num_children) {
521 /* if a child exists, wait for it to die */
522 waitcode = WaitForMultipleObjects(w32_num_children,
526 if (waitcode != WAIT_FAILED) {
527 if (waitcode >= WAIT_ABANDONED_0
528 && waitcode < WAIT_ABANDONED_0 + w32_num_children)
529 i = waitcode - WAIT_ABANDONED_0;
531 i = waitcode - WAIT_OBJECT_0;
532 if (GetExitCodeProcess(w32_child_pids[i], &exitcode) ) {
533 CloseHandle(w32_child_pids[i]);
534 *status = (int)((exitcode & 0xff) << 8);
535 retval = (int)w32_child_pids[i];
536 Copy(&w32_child_pids[i+1], &w32_child_pids[i],
537 (w32_num_children-i-1), HANDLE);
544 errno = GetLastError();
550 int CPerlProc::Setuid(uid_t u)
552 return (u == ROOT_UID ? 0 : -1);
555 int CPerlProc::Setgid(gid_t g)
557 return (g == ROOT_GID ? 0 : -1);
560 Sighandler_t CPerlProc::Signal(int sig, Sighandler_t subcode)
565 void CPerlProc::GetSysMsg(char*& sMsg, DWORD& dwLen, DWORD dwErr)
567 dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
568 |FORMAT_MESSAGE_IGNORE_INSERTS
569 |FORMAT_MESSAGE_FROM_SYSTEM, NULL,
570 dwErr, 0, (char *)&sMsg, 1, NULL);
572 while (0 < dwLen && isspace(sMsg[--dwLen]))
574 if ('.' != sMsg[dwLen])
579 sMsg = (char*)LocalAlloc(0, 64/**sizeof(TCHAR)*/);
580 dwLen = sprintf(sMsg,
581 "Unknown error #0x%lX (lookup 0x%lX)",
582 dwErr, GetLastError());
586 void CPerlProc::FreeBuf(char* sMsg)
591 BOOL CPerlProc::DoCmd(char *cmd)
593 Spawn(cmd, EXECF_EXEC);
597 int CPerlProc::Spawn(char* cmd)
599 return Spawn(cmd, EXECF_SPAWN);
602 int CPerlProc::Spawnvp(int mode, const char *cmdname, const char *const *argv)
606 status = spawnvp(mode, cmdname, (char * const *)argv);
608 /* XXX For the P_NOWAIT case, Borland RTL returns pinfo.dwProcessId
609 * while VC RTL returns pinfo.hProcess. For purposes of the custom
610 * implementation of win32_wait(), we assume the latter.
612 if (mode == P_NOWAIT && status >= 0)
613 w32_child_pids[w32_num_children++] = (HANDLE)status;