/* 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
 *	rpipe(cmd, in)	- run a shell command with stdin/stdout piped
 *	rpclose(fd)	- close a pipe that was created via rpipe()
 *	gethome(argv0)	- return name of home directory
 *
 * 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"
#ifndef XDOS
extern char **environ;
#endif

#if TURBOC
#define switchar() '/'
#endif

#if MSDOS
#include <process.h>
#ifndef XDOS
extern unsigned char _osmajor;
#endif
#endif
#if TOS
#include <osbind.h>
#endif


#if MSDOS || TOS
#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
	char *cmdswitch="/c";
	if (_osmajor<4)
		cmdswitch[0]=switchar();
	return spawnle(P_WAIT, o_shell, o_shell, cmdswitch, cmd, (char *)0, environ);
#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];

int rpipe(cmd, in)
	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 (in)
	{
		dup2(in, 0);
		close(in);
	}
	dup2(fd, 1);

	/* call command */
	cmdstate=system(cmd);

	/* restore old std... */
	dup2(old0, 0); close(old0);
	dup2(old1, 1); close(old1);

	/* rewind command output */
	lseek(fd, 0L, 0);
	return fd;
}

/* This function closes the pipe opened by rpipe(), and returns 0 for success */
int rpclose(fd)
	int	fd;
{
	int	status;

	close(fd);
	unlink(output);
	return cmdstate;
}

/* This function returns the name of the home directory.  If there is an
 * environment variable named "HOME", then its value is used; otherwise,
 * argv[0] is expected to contain the full pathname of the ELVIS.EXE, and
 * its directory will be used as the home directory.  The first time this
 * function is called, you must pass it the value of argv[0] but after that
 * you can pass it a NULL pointer.
 *
 * NOTE: This may alter the argv[0] string.
 */
char *gethome(exe)
	char	*exe;	/* full pathname of the ELVIS.EXE file */
{
	static char	*home;

	/* if this is the first time this func has been called, find home */
	if (!home)
	{
		home = getenv("HOME");
		if (!home)
		{
			home = exe;
			exe = strrchr(exe, SLASH);
			if (exe)
			{
				/* Yes, it was a full pathname.  Strip off the
				 * "ELVIS.EXE" part of the name, and use the
				 * rest as the name of the home directory.
				 */
				*exe = '\0';
			}
			else
			{
				/* Not a full pathname.  Use the current
				 * directory as the home directory.
				 */
				home = ".";
			}
		}
	}

	/* return home */
	return home;
}

#endif
