/*
	tinymain.c - small _main
*/


#include	"stdio.h"
#include	"stdlib.h"
#include	"stdarg.h"
#include	"string.h"
#include	"ctype.h"

/***#pragma nonrec***/


typedef	char	bool;
#define	YES	1
#define	NO	0

#define	MAXFUNC	32

extern	void	_exit(int);
extern	void	_puterrmes(char *);

#ifndef	CPM
extern	char	*_argv0;
#endif

static	char	ERR_MEMORY[] = "out of memory";
#ifdef	CPM
static	char	ERR_OPEN[]   = "can't open: ";
#endif


extern	void	(*_func[MAXFUNC])();

#define	MAXARGS		64
#define	MAXENVVARS	1000


#ifdef	CPM
void	_puterrmes(char *p)
{
	write(2, p, strlen(p));
}
#endif


void	exit(int rc)
{
	FILE	*fp;
	int	i;

	for (i = MAXFUNC; --i >= 0; )
		if (_func[i] != (void (*)())NULL)
			(*_func[i])();
	for (fp = _iob; fp < _iob + _SYS_STREAMS; fp++)
		if (fp->mode)
			fflush(fp);
	for (; fp < _iob + SYS_OPEN; fp++)
		if (fp->mode)
			fclose(fp);
	_exit(rc);
}


#ifndef	CPM

extern	char	*_environ;
char	**environ;

static	void	_setenviron()
{
	int	n;
auto	char	*envp[MAXENVVARS];
	char	**ep;
	char	*p;

	ep = envp;
	n = 0;
	for (p = _environ; *p; p += strlen(p) + 1) {
		if (++n >= MAXENVVARS)
			_puterrmes(ERR_MEMORY), exit(1);
		*ep++ = p;
	}
	*ep = NULL;
	if ((environ = malloc(sizeof(char *) * (n + 1))) == NULL)
		_puterrmes(ERR_MEMORY), exit(1);
	memcpy(environ, envp, sizeof(char *) * (n + 1));
}

#endif


void	_main(char *s)
{
#ifdef	CPM
	int	main(int, char *[]);
	char	*stdifn, *stdofn;
	char	*wmode = "w";
#else
	int	main(int, char *[], char *[]);
#endif
	auto	char	*arv[MAXARGS];
	int	arc;
	char	c, b, *p;

#ifdef	CPM
	stdifn = stdofn = "con:";
	arv[0] = "";
#else
	if (_argv0 == NULL)
		arv[0] = "";
	else
		arv[0] = _argv0;
#endif
	arc = 1;
	b = '\0';
	do {
		while ((c = *s++) == ' ' || c == '\t')
			;
		if (c == '\0')
			break;
#ifdef	CPM
		if (c == '<') {
			b = c;
			continue;
		} else if (c == '>') {
			if (*s == '>') {
				s++;
				wmode = "a";
			} else
				wmode = "w";
			b = c;
			continue;
		}
#endif
		p = --s;
		while ((c = *s) && c != ' ' && c != '\t')
			s++;
		*s++ = '\0';
#ifdef	CPM
		if (b == '<')
			stdifn = p;
		else if (b == '>')
			stdofn = p;
		else
			arv[arc++] = p;
		b = '\0';
#else
		arv[arc++] = p;
#endif
	} while (c != '\0');
	arv[arc] = NULL;
#ifdef	CPM
	if (freopen(stdifn, "r", stdin) == NULL) {
		_puterrmes(ERR_OPEN);
		_puterrmes(stdifn);
		exit(1);
	}
	if (freopen(stdofn, wmode, stdout) == NULL) {
		_puterrmes(ERR_OPEN);
		_puterrmes(stdifn);
		exit(1);
	}
	if (freopen("con:", "w", stderr) == NULL) {
		_puterrmes(ERR_OPEN);
		_puterrmes("con:");
		exit(1);
	}
#else
	fdreopen(0, "r", stdin);
	fdreopen(1, "w", stdout);
	fdreopen(2, "w", stderr);
	fdreopen(3, "w+b", stdaux);
	fdreopen(4, "wb", stdprn);
#endif
	setvbuf(stdin, NULL, _IOFBF, BUFSIZ);
#ifdef	CPM
	exit(main(arc, arv));
#else
	_setenviron();
	exit(main(arc, arv, environ));
#endif
}
