/*
** main.c
**
** Handles initialization of rc and command line options.
*/

#include <locale.h>

#include "rc.h"

bool dashdee = FALSE, dashee = FALSE, dashvee = FALSE, dashex = FALSE, dashell = FALSE, dasheye = FALSE, dashen = FALSE, dashpee = FALSE, dashess = FALSE, interactive = FALSE;
int rc_pid;

bool wasdashell;

static bool dashoh;

static void assigndefault(char *,...);
static void checkfd(int, enum redirtype);

extern void main(int argc, char *argv[], char *envp[]) {
	char *dashsee[2], *dollarzero, *null[1];
	int c;

	/* enh 1996/03/01 - See what kind of an alien the user is. */
	setlocale ( LC_ALL, "" );

	initprint();
	dashsee[0] = dashsee[1] = NULL;
	dollarzero = argv[0];
	rc_pid = getpid();
	dashell = (*argv[0] == '-'); /* Unix tradition */

	while ((c = rc_getopt(argc, argv, "nolpeivdxsc:")) != -1) {
		switch (c) {
		case 'l':
			dashell = TRUE;
			break;
		case 'e':
			dashee = TRUE;
			break;
		case 'i':
			dasheye = interactive = TRUE;
			break;
		case 'v':
			dashvee = TRUE;
			break;
		case 'x':
			dashex = TRUE;
			break;
		case 'd':
			dashdee = TRUE;
			break;
		case 'c':
			/* original
			dashsee[0] = rc_optarg;
			goto quitopts;
			*/
			if (argv [rc_optind - 1] == rc_optarg) {
				/* if -c command */
				dashsee [0] = argv [rc_optind - 1];
			} else {
				/* if -ce command */
				dashsee [0] = argv [rc_optind];
			}
			if (*(dashsee [0]) == '(') {
				char *s;
				int optind = rc_optind;
				while (argv [optind] && *(argv [optind - 1] + strlen (argv [optind - 1]) - 1) != ')') {
					dashsee [0] = nprint ("%s %s", dashsee [0], argv [optind]);
					optind ++;
				}
				s = dashsee [0] + strlen (dashsee [0]) - 1;
				if (*s == ')') {
					*s = '\0';
					dashsee [0] ++;
				}
			}
			break;
		case 'n':
			dashen = TRUE;
			break;
		case 'p':
			dashpee = TRUE;
			break;
		case 'o':
			dashoh = TRUE;
			break;
		case 's':
			/* added for compatibility with sh */
			/* input from stdin, subsequent arguments placed in $* */
			dashess = dasheye = interactive = TRUE;
			break;
		case '?':
			(void)fprint (1, "rc -- shell\n");
			(void)fprint (1, "Usage: rc [-?eixvldnpos] [-c command] [arguments]\n");
			(void)fprint (1, "Where:\n");
			(void)fprint (1, "        -?=displays this usage information\n");
			(void)fprint (1, "        -e=exit on non-zero exit status\n");
			(void)fprint (1, "        -i=force interactive\n");
			(void)fprint (1, "        -x=print commands before execution\n");
			(void)fprint (1, "        -v=echo input to standard error\n");
			(void)fprint (1, "        -l=login shell (. ~/.rcrc)\n");
			(void)fprint (1, "        -d=debug (dump core if sent SIGQUIT)\n");
			(void)fprint (1, "        -n=read and parse input without executing\n");
			(void)fprint (1, "        -p=protected from functions in the environment\n");
			(void)fprint (1, "        -o=do not open /dev/null if inherit closed stdio\n");
			(void)fprint (1, "        -s=read commands from input, command tail in $*\n");
			(void)fprint (1, "        -c=execute given command, command tail in $*\n");
			exit (EXIT_FAILURE);
		case 0:
			exit (EXIT_FAILURE);
		}
		if (dashsee [0] && dashsee [0] != argv [rc_optind]) break;
		if (dashess) break;
	}
	wasdashell = dashell;
	argv += rc_optind;
	/* use isatty() iff -i is not set, and iff the input is not from a script or -c or -s flags */
	if (!dasheye && !dashess && dashsee[0] == NULL && *argv == NULL)
		interactive = isatty(0);
	if (!dashoh) {
		checkfd(0, rFrom);
		checkfd(1, rCreate);
		checkfd(2, rCreate);
	}
	initsignal();
	inithash();
	initparse();
	assigndefault("prompt", "; ", "", (void *)0);
#ifdef DEFAULTPATH
	assigndefault("path", DEFAULTPATH, (void *)0);
#endif
	assigndefault("ifs", " ", "\t", "\n", (void *)0);
	assigndefault("pid", nprint("%d", rc_pid), (void *)0);
	initenv(envp);
	grab_control ();
	initinput();
	null[0] = NULL;
	starassign(dollarzero, null, FALSE); /* assign $0 to $* */
	inithandler();
	if (dashsee[0] != NULL || dashess) {    /* input from  -c or -s? */
		if (*argv != NULL)
			starassign(dollarzero, argv, FALSE);
		if (dashess)
			pushfd(0);
		else
			pushstring(dashsee, TRUE);
	} else if (*argv != NULL) {     /* else from a file? */
		b_dot(--argv);
		rc_exit(getstatus());
	} else {                        /* else stdin */
		pushfd(0);
	}
	dasheye = FALSE;
	doit(TRUE);
	rc_exit(getstatus());
}

static void assigndefault(char *name,...) {
	va_list ap;
	List *l;
	char *v;
	va_start(ap, name);
	for (l = NULL; (v = va_arg(ap, char *)) != NULL;)
		l = append(l, word(v, NULL));
	varassign(name, l, FALSE);
	if (streq(name, "path"))
		alias(name, l, FALSE);
	va_end(ap);
}

/* open an fd on /dev/null if it is inherited closed */

static void checkfd(int fd, enum redirtype r) {
	int new = rc_open("/dev/null", r);
	if (new != fd && new != -1)
		close(new);
}
