home *** CD-ROM | disk | FTP | other *** search
- /*
- 89/03/02: ERS: added the "mode" argument for MS-DOS/Unix
- compatibility. Added prototypes for GNU C.
-
- fixed spawnve: the original didn't pass the command tail
- correctly, nor did it handle errno right. Also, this version
- passes args in the environment as well as the command line,
- using the ARGV= mechanism supported by crt0.s
-
- Written 89/01/10 by ERS. Original version Copyright (c) 1988 by
- Memorial University of Newfoundland. This version is based upon
- that original, but is substantially different. (In fact, there
- probably isn't a single line of the original left.)
-
- Adapted 90/06/25 by ERS to MiNT.
- */
-
- #include <stdarg.h>
- #include <process.h>
- #include <param.h>
- #include <errno.h>
- #include <osbind.h>
- #include <mintbind.h>
- #include <stdlib.h>
- #include <time.h>
- #include <string.h>
- #include "lib.h"
-
- #define TOS_ARGS 126
-
- extern char **environ;
- extern int __mint;
-
- static char cmd[TOS_ARGS+1];
-
- int
- _spawnve(mode, _path, argv, envp)
- int mode;
- char *_path;
- char **argv;
- char **envp;
- {
- extern void _exit();
- static char path[MAXPATHLEN];
- int cmlen = 0;
- int enlen = 0;
- char *p;
- char *s, *t;
- char *env;
- long rval;
-
- if (mode != P_WAIT && mode != P_OVERLAY && mode != P_NOWAIT) {
- errno = EINVAL;
- return -1;
- }
- (void)_unx2dos(_path, path); /* convert filename, if necessary */
- if (!envp)
- envp = environ;
-
- /* count up space needed for environment */
- for(cmlen = 0; argv[cmlen]; cmlen++)
- enlen += strlen(argv[cmlen]) + 1;
- for(cmlen = 0; envp[cmlen]; cmlen++)
- enlen += strlen(envp[cmlen]) + 1;
- enlen += 32; /* filler for stuff like ARGV= and zeros */
-
- if (!(env = (char *)Malloc((long)enlen))) {
- errno = ENOMEM;
- return -1;
- }
- s = env;
- while ((p = *envp) != 0) {
- /*
- * NOTE: in main.c, we converted the PATH environment variable into
- * POSIX form. Here, we convert back into gulam form. Note that the
- * new variable will be shorter than the old, so space is not a problem.
- */
- if (!strncmp(p, "PATH=", 5)) {
- strncpy(s, p, 5); s += 5; p += 5;
- while (*p) {
- if (!strncmp(p, "/dev/", 5) && p[5]) {
- *s++ = p[5];
- *s++ = ':';
- p += 6;
- } else if (*p == ':') {
- *s++ = ','; p++;
- } else if (*p == '/') {
- *s++ = '\\'; p++;
- } else {
- *s++ = *p++;
- }
- }
- } else {
- while(*p)
- *s++ = *p++;
- }
- *s++ = '\0';
- envp++;
- }
-
- strcpy(s, "ARGV=");
- s += 6; /* s+=sizeof("ARGV=") */
-
- /* copy argv[0] first (because it doesn't go into the command line */
- if (argv && *argv) {
- for (p = *argv; *p; )
- *s++ = *p++;
- *s++ = '\0';
- }
-
- bzero(t = cmd, sizeof(cmd));
-
- /* s points at the environment's copy of the args */
- /* t points at the command line copy to be put in the basepage */
-
- if (argv && *argv) {
- t++;
- while (*++argv) {
- p = *argv;
- while (*p) {
- if (cmlen <= TOS_ARGS) {
- *t++ = *p; cmlen++;
- }
- *s++ = *p++;
- }
- if (cmlen <= TOS_ARGS && *(argv+1)) {
- *t++ = ' '; cmlen++;
- }
- *s++ = '\0';
- }
- /* *cmd = (char) cmlen; NOT ANY MORE */
- }
-
- /* tie off environment */
- *s++ = '\0';
- *s = '\0';
-
- /* signal Extended Argument Passing */
- *cmd = 0x7f;
-
- /* MiNT and MicroRTX support background processes with Pexec(100,...) */
- /* MiNT supports overlays with Pexec(200,...) */
-
- if (mode == P_NOWAIT) cmlen = 100;
- else if (mode == P_OVERLAY && __mint) cmlen = 200;
- else cmlen = 0;
-
- rval = Pexec(cmlen, path, cmd, env);
-
- if (rval < 0)
- {
- errno = -rval;
- rval = -1;
- }
- else if (mode == P_OVERLAY)
- /* note that we get here only if MiNT is not active! */
- _exit((int)rval);
- (void)Mfree(env);
- return rval;
- }
-