home *** CD-ROM | disk | FTP | other *** search
- /* sysdos.c -- DOS version of system.c */
-
- /* Author:
- * Guntram Blohm
- * Buchenstrasse 19
- * 7904 Erbach, West Germany
- * Tel. ++49-7305-6997
- * sorry - no regular network connection
- */
-
-
- /* This file is derived from Steve Kirkendall's system.c.
- *
- * Entry points are:
- * system(cmd) - run a single shell command
- * wildcard(names) - expand wildcard characters in filanames
- *
- * This file is for use with DOS and TOS. For OS/2, slight modifications
- * might be sufficient. For UNIX, use system.c. For Amiga, completely
- * rewrite this stuff.
- *
- * Another system function, filter, is the same on DOS and UNIX and thus
- * can be found in the original system.c.
- */
-
- #include "config.h"
- #include "vi.h"
- extern char **environ;
-
- #if MSDOS || MINT
- #include <process.h>
- # if MSDOS
- extern unsigned char _osmajor;
- # endif
- #endif
- #if TOS || MINT
- #include <osbind.h>
- #endif
- #if MINT
- #include <stdio.h>
- #endif
-
- #if MSDOS || TOS || MINT
- #include <string.h>
-
- /*
- * Calling command is a bit nasty because of the undocumented yet sometimes
- * used feature to change the option char to something else than /.
- * Versions 2.x and 3.x support this, 4.x doesn't.
- *
- * For Atari, some shells define a shortcut entry which is faster than
- * shell -c. Also, Mark Williams uses a special ARGV environment variable
- * to pass more than 128 chars to a called command.
- * We try to support all of these features here.
- */
-
- int system(cmd)
- const char *cmd;
- {
- #if MSDOS || MINT
- # if MINT
- static char *extensions[] = { "ttp", "prg", "tos", NULL };
- extern char *findfile (char *, char *, char **);
- extern char *getenv();
-
- char **argv = 0, *cmdcopy = 0, **argp, *path, *p;
- int ret;
- size_t clen;
- static char cmdpath[FILENAME_MAX];
-
- long ssp;
- int (*shell)();
-
- if (cmd == o_shell)
- return spawnlp(P_WAIT, o_shell, o_shell, (char *)0);
-
- if (!getenv("NO_SHELLP")) {
- ssp = Super(0L);
- shell = *((int (**)())0x4F6);
- (void) Super(ssp);
- if (shell)
- return (*shell)(cmd);
- }
-
- /* see if cmd is simple enough so that we don't need a shell */
- if ((path = getenv("PATH")) && (clen = strlen(cmd)) &&
- !strpbrk(cmd, "'\"`><;$~[*?&|(){}") &&
- (argv = (char **) malloc((clen/2+2) * sizeof(char *))) &&
- (cmdcopy = strdup(cmd)) &&
- (p = findfile(strtok(cmdcopy, " \t"), path, extensions))) {
- argp = argv;
- *argp++ = strcpy(cmdpath, p);
- while (*argp++ = strtok((char *) NULL, " \t"))
- ;
- errno = 0;
- ret = spawnv(P_WAIT, p, argv);
- free(argv);
- free(cmdcopy);
- if (ret != -1 || errno != ENOEXEC)
- return ret;
- }
- if (argv)
- free(argv);
- if (cmdcopy)
- free(cmdcopy);
- return spawnlp(P_WAIT, o_shell, o_shell, "-c", cmd, (char *)0);
- # else
- char *cmdswitch="/c";
- if (_osmajor<4)
- cmdswitch[0]=switchar();
- return spawnle(P_WAIT, o_shell, o_shell, cmdswitch, cmd, (char *)0, environ);
- # endif
- #else
- long ssp;
- int (*shell)();
- char line[130];
- char env[4096], *ep=env;
- int i;
-
- /* does our shell have a shortcut, that we can use? */
-
- ssp = Super(0L);
- shell = *((int (**)())0x4F6);
- Super(ssp);
- if (shell)
- return (*shell)(cmd);
-
- /* else we'll have to call a shell ... */
-
- for (i=0; environ[i] && strncmp(environ[i], "ARGV=", 5); i++)
- { strcpy(ep, environ[i]);
- ep+=strlen(ep)+1;
- }
- if (environ[i])
- {
- strcpy(ep, environ[i]); ep+=strlen(ep)+1;
- strcpy(ep, o_shell); ep+=strlen(ep)+1;
- strcpy(ep, "-c"); ep+=3;
- strcpy(ep, cmd); ep+=strlen(ep)+1;
- }
- *ep='\0';
- strcpy(line+1, "-c ");
- strncat(line+1, cmd, 126);
- line[0]=strlen(line+1);
- return Pexec(0, o_shell, line, env);
- #endif
- }
-
- /* This private function opens a pipe from a filter. It is similar to the
- * system() function above, and to popen(cmd, "r").
- * sorry - i cant use cmdstate until rpclose, but get it from spawnle.
- */
-
- static int cmdstate;
- static char output[80];
-
- #if MINT
- /* MiNT uses real pipes if it can... (wich means unless running vanilla TOS.) */
- int trpipe(cmd, in)
- #else
- int rpipe(cmd, in)
- #endif
- char *cmd; /* the filter command to use */
- int in; /* the fd to use for stdin */
- {
- int fd, old0, old1, old2;
-
- /* create the file that will collect the filter's output */
- strcpy(output, o_directory);
- if ((fd=strlen(output)) && !strchr("/\\:", output[fd-1]))
- output[fd++]=SLASH;
- strcpy(output+fd, SCRATCHIN+3);
- mktemp(output);
- close(creat(output, 0666));
- if ((fd=open(output, O_RDWR))==-1)
- {
- unlink(output);
- return -1;
- }
-
- /* save and redirect stdin, stdout, and stderr */
- old0=dup(0);
- old1=dup(1);
- #if MINT
- /* ... and stderr :-) */
- old2=dup(2);
- #endif
- if (in)
- {
- dup2(in, 0);
- close(in);
- }
- dup2(fd, 1);
- #if MINT
- dup2(fd, 2);
- #endif
-
- /* call command */
- cmdstate=system(cmd);
-
- /* restore old std... */
- dup2(old0, 0); close(old0);
- dup2(old1, 1); close(old1);
- #if MINT
- dup2(old2, 2); close(old2);
- #endif
-
- /* rewind command output */
- #if TOS || MINT
- /* GEMDOS redirection bugs department... */
- close(fd);
- fd=open(output, O_RDWR);
- #else
- lseek(fd, 0L, 0);
- #endif
- return fd;
- }
-
- /* This function closes the pipe opened by rpipe(), and returns 0 for success */
- #if MINT
- int trpclose(fd)
- #else
- int rpclose(fd)
- #endif
- int fd;
- {
- close(fd);
- unlink(output);
- return cmdstate;
- }
-
- #endif
-