* by default once people are aware of its existance
* by default once people are aware of its existence
main(argc, argv)	int argc;	register char **argv;{	register int i;	int argi;	Source *s;	struct block *l;	int restricted, errexit;	char **wp;	struct env env;	pid_t ppid;#ifdef MEM_DEBUG	chmem_set_defaults("ct", 1);	/* chmem_push("+c", 1); */#endif /* MEM_DEBUG */#ifdef OS2	setmode (0, O_BINARY);	setmode (1, O_TEXT);#endif	/* make sure argv[] is sane */	if (!*argv) {		static const char	*empty_argv[] = {					    "pdksh", (char *) 0					};		argv = (char **) empty_argv;		argc = 1;	}	kshname = *argv;	ainit(&aperm);		/* initialize permanent Area */	/* set up base environment */	memset(&env, 0, sizeof(env));	env.type = E_NONE;	ainit(&env.area);	e = &env;	newblock();		/* set up global l->vars and l->funs */	/* Do this first so output routines (eg, errorf, shellf) can work */	initio();	initvar();	initctypes();	inittraps();#ifdef KSH	coproc_init();#endif /* KSH */	/* set up variable and command dictionaries */	tinit(&taliases, APERM, 0);	tinit(&aliases, APERM, 0);	tinit(&homedirs, APERM, 0);	/* define shell keywords */	initkeywords();	/* define built-in commands */	tinit(&builtins, APERM, 64); /* must be 2^n (currently 40 builtins) */	for (i = 0; shbuiltins[i].name != NULL; i++)		builtin(shbuiltins[i].name, shbuiltins[i].func);	for (i = 0; kshbuiltins[i].name != NULL; i++)		builtin(kshbuiltins[i].name, kshbuiltins[i].func);	init_histvec();	def_path = DEFAULT__PATH;#if defined(HAVE_CONFSTR) && defined(_CS_PATH)	{		size_t len = confstr(_CS_PATH, (char *) 0, 0);		char *new;		if (len > 0) {			confstr(_CS_PATH, new = alloc(len + 1, APERM), len + 1);			def_path = new;		}	}#endif /* HAVE_CONFSTR && _CS_PATH */	/* Set PATH to def_path (will set the path global variable).	 * (import of environment below will probably change this setting).	 */	{		struct tbl *vp = global("PATH");		/* setstr can't fail here */		setstr(vp, def_path, KSH_RETURN_ERROR);	}	/* Turn on nohup by default for how - will change to off	 * by default once people are aware of its existance	 * (at&t ksh does not have a nohup option - it always sends	 * the hup).	 */	Flag(FNOHUP) = 1;	/* Turn on brace expansion by default.  At&t ksh's that have	 * alternation always have it on.  BUT, posix doesn't have	 * brace expansion, so set this before setting up FPOSIX	 * (change_flag() clears FBRACEEXPAND when FPOSIX is set).	 */#ifdef BRACE_EXPAND	Flag(FBRACEEXPAND) = 1;#endif /* BRACE_EXPAND */	/* set posix flag just before environment so that it will have	 * exactly the same effect as the POSIXLY_CORRECT environment	 * variable.  If this needs to be done sooner to ensure correct posix	 * operation, an initial scan of the environment will also have	 * done sooner.	 */#ifdef POSIXLY_CORRECT	change_flag(FPOSIX, OF_SPECIAL, 1);#endif /* POSIXLY_CORRECT */	/* Check to see if we're /bin/sh. */	if (!strcmp(&kshname[strlen(kshname) - 3], "/sh")	    || !strcmp(kshname, "sh") || !strcmp(kshname, "-sh"))		Flag(FSH) = 1;	/* Set edit mode to emacs by default, may be overridden	 * by the environment or the user.  Also, we want tab completion	 * on in vi by default. */#if defined(EDIT) && defined(EMACS)	change_flag(FEMACS, OF_SPECIAL, 1);#endif /* EDIT && EMACS */#if defined(EDIT) && defined(VI)	Flag(FVITABCOMPLETE) = 1;#endif /* EDIT && VI */	/* import environment */	if (environ != NULL)		for (wp = environ; *wp != NULL; wp++)			typeset(*wp, IMPORT|EXPORT, 0, 0, 0);	kshpid = procpid = getpid();	typeset(initifs, 0, 0, 0, 0);	/* for security */	/* assign default shell variable values */	substitute(initsubs, 0);	/* Figure out the current working directory and set $PWD */	{		struct stat s_pwd, s_dot;		struct tbl *pwd_v = global("PWD");		char *pwd = str_val(pwd_v);		char *pwdx = pwd;		/* Try to use existing $PWD if it is valid */		if (!ISABSPATH(pwd)		    || stat(pwd, &s_pwd) < 0 || stat(".", &s_dot) < 0		    || s_pwd.st_dev != s_dot.st_dev		    || s_pwd.st_ino != s_dot.st_ino)			pwdx = (char *) 0;		set_current_wd(pwdx);		if (current_wd[0])			simplify_path(current_wd);		/* Only set pwd if we know where we are or if it had a		 * bogus value		 */		if (current_wd[0] || pwd != null)			/* setstr can't fail here */			setstr(pwd_v, current_wd, KSH_RETURN_ERROR);	}	ppid = getppid();	setint(global("PPID"), (long) ppid);#ifdef KSH	setint(global("RANDOM"), (long) (time((time_t *)0) * kshpid * ppid));#endif /* KSH */	/* setstr can't fail here */	setstr(global(version_param), ksh_version, KSH_RETURN_ERROR);	/* execute initialization statements */	for (wp = (char**) initcoms; *wp != NULL; wp++) {		shcomexec(wp);		for (; *wp != NULL; wp++)			;	}	ksheuid = geteuid();	safe_prompt = ksheuid ? "$ " : "# ";	{		struct tbl *vp = global("PS1");		/* Set PS1 if it isn't set, or we are root and prompt doesn't		 * contain a #.		 */		if (!(vp->flag & ISSET)		    || (!ksheuid && !strchr(str_val(vp), '#')))			/* setstr can't fail here */			setstr(vp, safe_prompt, KSH_RETURN_ERROR);	}	/* Set this before parsing arguments */	Flag(FPRIVILEGED) = getuid() != ksheuid || getgid() != getegid();	/* this to note if monitor is set on command line (see below) */	Flag(FMONITOR) = 127;	argi = parse_args(argv, OF_CMDLINE, (int *) 0);	if (argi < 0)		exit(1);	if (Flag(FCOMMAND)) {		s = pushs(SSTRING, ATEMP);		if (!(s->start = s->str = argv[argi++]))			errorf("-c requires an argument");		if (argv[argi])			kshname = argv[argi++];	} else if (argi < argc && !Flag(FSTDIN)) {		s = pushs(SFILE, ATEMP);#ifdef OS2		/* a bug in os2 extproc shell processing doesn't		 * pass full pathnames so we have to search for it.		 * This changes the behavior of 'ksh arg' to search		 * the users search path but it can't be helped.		 */		s->file = search(argv[argi++], path, R_OK, (int *) 0);		if (!s->file || !*s->file)		        s->file = argv[argi - 1];#else		s->file = argv[argi++];#endif /* OS2 */		s->u.shf = shf_open(s->file, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC);		if (s->u.shf == NULL) {			exstat = 127; /* POSIX */			errorf("%s: %s", s->file, strerror(errno));		}		kshname = s->file;	} else {		Flag(FSTDIN) = 1;		s = pushs(SSTDIN, ATEMP);		s->file = "<stdin>";		s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0),				      (struct shf *) 0);		if (isatty(0) && isatty(2)) {			Flag(FTALKING) = Flag(FTALKING_I) = 1;			/* The following only if isatty(0) */			s->flags |= SF_TTY;			s->u.shf->flags |= SHF_INTERRUPT;			s->file = (char *) 0;		}	}	/* This bizarreness is mandated by POSIX */	{		struct stat s_stdin;		if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode) &&		    Flag(FTALKING))			reset_nonblock(0);	}	/* initialize job control */	i = Flag(FMONITOR) != 127;	Flag(FMONITOR) = 0;	j_init(i);#ifdef EDIT	/* Do this after j_init(), as tty_fd is not initialized 'til then */	if (Flag(FTALKING))		x_init();#endif	l = e->loc;	l->argv = &argv[argi - 1];	l->argc = argc - argi;	l->argv[0] = (char *) kshname;	getopts_reset(1);	/* Disable during .profile/ENV reading */	restricted = Flag(FRESTRICTED);	Flag(FRESTRICTED) = 0;	errexit = Flag(FERREXIT);	Flag(FERREXIT) = 0;	/* Do this before profile/$ENV so that if it causes problems in them,	 * user will know why things broke.	 */	if (!current_wd[0] && Flag(FTALKING))		warningf(FALSE, "Cannot determine current working directory");	if (Flag(FLOGIN)) {#ifdef OS2		char *profile;		/* Try to find a profile - first see if $INIT has a value,		 * then try /etc/profile.ksh, then c:/usr/etc/profile.ksh.		 */		if (!Flag(FPRIVILEGED)		    && strcmp(profile = substitute("$INIT/profile.ksh", 0),			      "/profile.ksh"))			include(profile, 0, (char **) 0, 1);		else if (include("/etc/profile.ksh", 0, (char **) 0, 1) < 0)			include("c:/usr/etc/profile.ksh", 0, (char **) 0, 1);		if (!Flag(FPRIVILEGED))			include(substitute("$HOME/profile.ksh", 0), 0,				(char **) 0, 1);#else /* OS2 */		include(KSH_SYSTEM_PROFILE, 0, (char **) 0, 1);		if (!Flag(FPRIVILEGED))			include(substitute("$HOME/.profile", 0), 0,				(char **) 0, 1);#endif /* OS2 */	}	if (Flag(FPRIVILEGED))		include("/etc/suid_profile", 0, (char **) 0, 1);	else {		char *env_file;#ifndef KSH		if (!Flag(FPOSIX))			env_file = null;		else#endif /* !KSH */			/* include $ENV */			env_file = str_val(global("ENV"));#ifdef DEFAULT_ENV		/* If env isn't set, include default environment */		if (env_file == null)			env_file = DEFAULT_ENV;#endif /* DEFAULT_ENV */		env_file = substitute(env_file, DOTILDE);		if (*env_file != '\0')			include(env_file, 0, (char **) 0, 1);#ifdef OS2		else if (Flag(FTALKING))			include(substitute("$HOME/kshrc.ksh", 0), 0,				(char **) 0, 1);#endif /* OS2 */	}	if (is_restricted(argv[0]) || is_restricted(str_val(global("SHELL"))))		restricted = 1;	if (restricted) {		static const char *const restr_com[] = {						"typeset", "-r", "PATH",						    "ENV", "SHELL",						(char *) 0					    };		shcomexec((char **) restr_com);		/* After typeset command... */		Flag(FRESTRICTED) = 1;	}	if (errexit)		Flag(FERREXIT) = 1;	if (Flag(FTALKING)) {		hist_init(s);#ifdef KSH		alarm_init();#endif /* KSH */	} else		Flag(FTRACKALL) = 1;	/* set after ENV */	shell(s, TRUE);	/* doesn't return */	return 0;}