+/* -------- sh.c -------- */
+/*
+ * shell
+ */
+
+int msh_main(int argc, char **argv);
+int msh_main(int argc, char **argv)
+{
+ int f;
+ char *s;
+ int cflag;
+ char *name, **ap;
+ int (*iof) (struct ioarg *);
+
+ PTR_TO_GLOBALS = xzalloc(sizeof(G));
+ sharedbuf.id = AFID_NOBUF;
+ mainbuf.id = AFID_NOBUF;
+ e.linep = line;
+ elinep = line + sizeof(line) - 5;
+
+#if ENABLE_FEATURE_EDITING
+ line_input_state = new_line_input_t(FOR_SHELL);
+#endif
+
+ DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
+
+ initarea();
+ ap = environ;
+ if (ap != NULL) {
+ while (*ap)
+ assign(*ap++, !COPYV);
+ for (ap = environ; *ap;)
+ export(lookup(*ap++));
+ }
+ closeall();
+ areanum = 1;
+
+ shell = lookup("SHELL");
+ if (shell->value == null)
+ setval(shell, (char *)DEFAULT_SHELL);
+ export(shell);
+
+ homedir = lookup("HOME");
+ if (homedir->value == null)
+ setval(homedir, "/");
+ export(homedir);
+
+ setval(lookup("$"), putn(getpid()));
+
+ path = lookup("PATH");
+ if (path->value == null) {
+ /* Can be merged with same string elsewhere in bbox */
+ if (geteuid() == 0)
+ setval(path, "/sbin:/usr/sbin:/bin:/usr/bin");
+ else
+ setval(path, "/sbin:/usr/sbin:/bin:/usr/bin" + sizeof("/sbin:/usr/sbin"));
+ }
+ export(path);
+
+ ifs = lookup("IFS");
+ if (ifs->value == null)
+ setval(ifs, " \t\n");
+
+#ifdef MSHDEBUG
+ mshdbg_var = lookup("MSHDEBUG");
+ if (mshdbg_var->value == null)
+ setval(mshdbg_var, "0");
+#endif
+
+ prompt = lookup("PS1");
+#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
+ if (prompt->value == null)
+#endif
+ setval(prompt, DEFAULT_USER_PROMPT);
+ if (geteuid() == 0) {
+ setval(prompt, DEFAULT_ROOT_PROMPT);
+ prompt->status &= ~EXPORT;
+ }
+ cprompt = lookup("PS2");
+#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
+ if (cprompt->value == null)
+#endif
+ setval(cprompt, "> ");
+
+ iof = filechar;
+ cflag = 0;
+ name = *argv++;
+ if (--argc >= 1) {
+ if (argv[0][0] == '-' && argv[0][1] != '\0') {
+ for (s = argv[0] + 1; *s; s++)
+ switch (*s) {
+ case 'c':
+ prompt->status &= ~EXPORT;
+ cprompt->status &= ~EXPORT;
+ setval(prompt, "");
+ setval(cprompt, "");
+ cflag = 1;
+ if (--argc > 0)
+ PUSHIO(aword, *++argv, iof = nlchar);
+ break;
+
+ case 'q':
+ qflag = SIG_DFL;
+ break;
+
+ case 's':
+ /* standard input */
+ break;
+
+ case 't':
+ prompt->status &= ~EXPORT;
+ setval(prompt, "");
+ iof = linechar;
+ break;
+
+ case 'i':
+ interactive++;
+ default:
+ if (*s >= 'a' && *s <= 'z')
+ FLAG[(int) *s]++;
+ }
+ } else {
+ argv--;
+ argc++;
+ }
+
+ if (iof == filechar && --argc > 0) {
+ setval(prompt, "");
+ setval(cprompt, "");
+ prompt->status &= ~EXPORT;
+ cprompt->status &= ~EXPORT;
+
+/* Shell is non-interactive, activate printf-based debug */
+#ifdef MSHDEBUG
+ mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0');
+ if (mshdbg < 0)
+ mshdbg = 0;
+#endif
+ DBGPRINTF(("MSH_MAIN: calling newfile()\n"));
+
+ name = *++argv;
+ if (newfile(name))
+ exit(1); /* Exit on error */
+ }
+ }
+
+ setdash();
+
+ /* This won't be true if PUSHIO has been called, say from newfile() above */
+ if (e.iop < iostack) {
+ PUSHIO(afile, 0, iof);
+ if (isatty(0) && isatty(1) && !cflag) {
+ interactive++;
+#if !ENABLE_FEATURE_SH_EXTRA_QUIET
+#ifdef MSHDEBUG
+ printf("\n\n%s Built-in shell (msh with debug)\n", BB_BANNER);
+#else
+ printf("\n\n%s Built-in shell (msh)\n", BB_BANNER);
+#endif
+ printf("Enter 'help' for a list of built-in commands.\n\n");
+#endif
+ }
+ }
+
+ signal(SIGQUIT, qflag);
+ if (name && name[0] == '-') {
+ interactive++;
+ f = open(".profile", O_RDONLY);
+ if (f >= 0)
+ next(remap(f));
+ f = open("/etc/profile", O_RDONLY);
+ if (f >= 0)
+ next(remap(f));
+ }
+ if (interactive)
+ signal(SIGTERM, sig);
+
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, onintr);
+ dolv = argv;
+ dolc = argc;
+ dolv[0] = name;
+ if (dolc > 1) {
+ for (ap = ++argv; --argc > 0;) {
+ *ap = *argv++;
+ if (assign(*ap, !COPYV)) {
+ dolc--; /* keyword */
+ } else {
+ ap++;
+ }
+ }
+ }
+ setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
+
+ DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack));
+
+ for (;;) {
+ if (interactive && e.iop <= iostack) {
+#if ENABLE_FEATURE_EDITING
+ current_prompt = prompt->value;
+#else
+ prs(prompt->value);
+#endif
+ }
+ onecommand();
+ /* Ensure that getenv("PATH") stays current */
+ setenv("PATH", path->value, 1);
+ }
+
+ DBGPRINTF(("MSH_MAIN: returning.\n"));
+}
+