#define INCL_DOS
#define INCL_NOPM
+#define INCL_DOSFILEMGR
+#ifndef NO_SYS_ALLOC
+# define INCL_DOSMEMMGR
+# define INCL_DOSERRORS
+#endif /* ! defined NO_SYS_ALLOC */
#include <os2.h>
/*
Signal_t (*ihand)(); /* place to save signal during system() */
Signal_t (*qhand)(); /* place to save signal during system() */
- if (pid < 0 || flag != 0)
+ if (pid < 0 || flag != 0)
return pid;
ihand = signal(SIGINT, SIG_IGN);
qhand = signal(SIGQUIT, SIG_IGN);
- r = waitpid(pid, &status, 0);
+ do {
+ r = wait4pid(pid, &status, 0);
+ } while (r == -1 && errno == EINTR);
signal(SIGINT, ihand);
signal(SIGQUIT, qhand);
if (flag == P_WAIT)
flag = P_NOWAIT;
+ if (*Argv[0] != '/' && *Argv[0] != '\\') /* will swawnvp use PATH? */
+ TAINT_ENV(); /* testing IFS here is overkill, probably */
if (really && *(tmps = SvPV(really, na)))
rc = result(trueflag, spawnvp(flag,tmps,Argv));
else
if (rc < 0 && dowarn)
warn("Can't spawn \"%s\": %s", Argv[0], Strerror(errno));
+ if (rc < 0) rc = 255 << 8; /* Emulate the fork(). */
} else
rc = -1;
do_execfree();
char *shell, *copt;
int rc;
- if ((shell = getenv("SHELL")) != NULL)
+#ifdef TRYSHELL
+ if ((shell = getenv("EMXSHELL")) != NULL)
+ copt = "-c";
+ else if ((shell = getenv("SHELL")) != NULL)
copt = "-c";
else if ((shell = getenv("COMSPEC")) != NULL)
copt = "/C";
else
shell = "cmd.exe";
+#else
+ /* Consensus on perl5-porters is that it is _very_ important to
+ have a shell which will not change between computers with the
+ same architecture, to avoid "action on a distance".
+ And to have simple build, this shell should be sh. */
+ shell = "sh.exe";
+ copt = "-c";
+#endif
+
+ while (*cmd && isSPACE(*cmd))
+ cmd++;
/* save an extra exec if possible */
/* see if there are shell metacharacters in it */
- /*SUPPRESS 530*/
- if (*cmd == '@') {
- ++cmd;
- goto shell_cmd;
- }
+ if (*cmd == '.' && isSPACE(cmd[1]))
+ goto doshell;
+
+ if (strnEQ(cmd,"exec",4) && isSPACE(cmd[4]))
+ goto doshell;
+
+ for (s = cmd; *s && isALPHA(*s); s++) ; /* catch VAR=val gizmo */
+ if (*s == '=')
+ goto doshell;
+
for (s = cmd; *s; s++) {
- if (*s != ' ' && !isALPHA(*s) && strchr("%&|<>\n",*s)) {
+ if (*s != ' ' && !isALPHA(*s) && strchr("$&*(){}[]'\";\\|?<>~`\n",*s)) {
if (*s == '\n' && !s[1]) {
*s = '\0';
break;
}
-shell_cmd: return result(P_WAIT, spawnl(P_NOWAIT,shell,shell,copt,cmd,(char*)0));
+ doshell:
+ rc = result(P_WAIT,
+ spawnl(P_NOWAIT,shell,shell,copt,cmd,(char*)0));
+ if (rc < 0 && dowarn)
+ warn("Can't spawn \"%s\": %s", shell, Strerror(errno));
+ if (rc < 0) rc = 255 << 8; /* Emulate the fork(). */
+ return rc;
}
}
+
New(402,Argv, (s - cmd) / 2 + 2, char*);
Cmd = savepvn(cmd, s-cmd);
a = Argv;
rc = result(P_WAIT, spawnvp(P_NOWAIT,Argv[0],Argv));
if (rc < 0 && dowarn)
warn("Can't spawn \"%s\": %s", Argv[0], Strerror(errno));
+ if (rc < 0) rc = 255 << 8; /* Emulate the fork(). */
} else
rc = -1;
do_execfree();
return rc;
}
+FILE *
+my_popen(cmd,mode)
+char *cmd;
+char *mode;
+{
+ char *shell = getenv("EMXSHELL");
+ FILE *res;
+
+ my_setenv("EMXSHELL", "sh.exe");
+ res = popen(cmd, mode);
+ my_setenv("EMXSHELL", shell);
+ return res;
+}
+
/*****************************************************************************/
#ifndef HAS_FORK
/* not implemented in EMX 0.9a */
void * ctermid(x) { return 0; }
+
+#ifdef MYTTYNAME /* was not in emx0.9a */
void * ttyname(x) { return 0; }
+#endif
void * gethostent() { return 0; }
void * getnetent() { return 0; }
}
#endif
+
+#ifndef NO_SYS_ALLOC
+
+static char *oldchunk;
+static long oldsize;
+
+#define _32_K (1<<15)
+#define _64_K (1<<16)
+
+/* The real problem is that DosAllocMem will grant memory on 64K-chunks
+ * boundaries only. Note that addressable space for application memory
+ * is around 240M, thus we will run out of addressable space if we
+ * allocate around 14M worth of 4K segments.
+ * Thus we allocate memory in 64K chunks, and abandon the rest of the old
+ * chunk if the new is bigger than that rest. Also, we just allocate
+ * whatever is requested if the size is bigger that 32K. With this strategy
+ * we cannot lose more than 1/2 of addressable space. */
+
+void *
+sbrk(int size)
+{
+ char *got;
+ APIRET rc;
+ int small, reqsize;
+
+ if (!size) return 0;
+ else if (size <= oldsize) {
+ got = oldchunk;
+ oldchunk += size;
+ oldsize -= size;
+ return (void *)got;
+ } else if (size >= _32_K) {
+ small = 0;
+ } else {
+ reqsize = size;
+ size = _64_K;
+ small = 1;
+ }
+ rc = DosAllocMem((void **)&got, size, PAG_COMMIT | PAG_WRITE);
+ if (rc == ERROR_NOT_ENOUGH_MEMORY) {
+ return (void *) -1;
+ } else if ( rc ) die("Got an error from DosAllocMem: %li", (long)rc);
+ if (small) {
+ /* Chunk is small, register the rest for future allocs. */
+ oldchunk = got + reqsize;
+ oldsize = size - reqsize;
+ }
+ return (void *)got;
+}
+#endif /* ! defined NO_SYS_ALLOC */
+
+/* tmp path */
+
+char *tmppath = TMPPATH1;
+
+void
+settmppath()
+{
+ char *p = getenv("TMP"), *tpath;
+ int len;
+
+ if (!p) p = getenv("TEMP");
+ if (!p) return;
+ len = strlen(p);
+ tpath = (char *)malloc(len + strlen(TMPPATH1) + 2);
+ strcpy(tpath, p);
+ tpath[len] = '/';
+ strcpy(tpath + len + 1, TMPPATH1);
+ tmppath = tpath;
+}
+
+#include "XSUB.h"
+
+XS(XS_File__Copy_syscopy)
+{
+ dXSARGS;
+ if (items < 2 || items > 3)
+ croak("Usage: File::Copy::syscopy(src,dst,flag=0)");
+ {
+ char * src = (char *)SvPV(ST(0),na);
+ char * dst = (char *)SvPV(ST(1),na);
+ U32 flag;
+ int RETVAL, rc;
+
+ if (items < 3)
+ flag = 0;
+ else {
+ flag = (unsigned long)SvIV(ST(2));
+ }
+
+ errno = DosCopy(src, dst, flag);
+ RETVAL = !errno;
+ ST(0) = sv_newmortal();
+ sv_setiv(ST(0), (IV)RETVAL);
+ }
+ XSRETURN(1);
+}
+
+OS2_Perl_data_t OS2_Perl_data;
+
+int
+Xs_OS2_init()
+{
+ char *file = __FILE__;
+ {
+ newXS("File::Copy::syscopy", XS_File__Copy_syscopy, file);
+ }
+}
+
+void
+Perl_OS2_init()
+{
+ settmppath();
+ OS2_Perl_data.xs_init = &Xs_OS2_init;
+}