/* 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
