/* job cleanup before shell exit */ void j_exit(void) { /* kill stopped, and possibly running, jobs */ Job *j; int killed = 0; for (j = job_list; j != (Job *) 0; j = j->next) { if (j->ppid == procpid && (j->state == PSTOPPED || (j->state == PRUNNING && ((j->flags & JF_FG) || (Flag(FLOGIN) && !Flag(FNOHUP) && procpid == kshpid))))) { killed = 1; if (j->pgrp == 0) kill_job(j, SIGHUP); else killpg(j->pgrp, SIGHUP); #ifdef JOBS if (j->state == PSTOPPED) { if (j->pgrp == 0) kill_job(j, SIGCONT); else killpg(j->pgrp, SIGCONT); } #endif /* JOBS */ } } if (killed) sleep(1); j_notify(); #ifdef JOBS if (kshpid == procpid && restore_ttypgrp >= 0) { /* Need to restore the tty pgrp to what it was when the * shell started up, so that the process that started us * will be able to access the tty when we are done. * Also need to restore our process group in case we are * about to do an exec so that both our parent and the * process we are to become will be able to access the tty. */ tcsetpgrp(tty_fd, restore_ttypgrp); setpgid(0, restore_ttypgrp); } if (Flag(FMONITOR)) { Flag(FMONITOR) = 0; j_change(); } #endif /* JOBS */ }
/* job cleanup before shell exit */ void j_exit(void) { /* kill stopped, and possibly running, jobs */ Job *j; int killed = 0; for (j = job_list; j != (Job *) 0; j = j->next) { if (j->ppid == procpid && (j->state == PSTOPPED || (j->state == PRUNNING && (j->flags & JF_FG)))) { killed = 1; if (j->pgrp == 0) kill_job(j, SIGHUP); else killpg(j->pgrp, SIGHUP); } } if (killed) sleep(1); j_notify(); }
/* * run the commands from the input source, returning status. */ int shell(Source * volatile s, volatile int level) { struct op *t; volatile bool wastty = tobool(s->flags & SF_TTY); volatile uint8_t attempts = 13; volatile bool interactive = (level == 0) && Flag(FTALKING); volatile bool sfirst = true; Source *volatile old_source = source; int i; newenv(level == 2 ? E_EVAL : E_PARSE); if (interactive) really_exit = false; switch ((i = kshsetjmp(e->jbuf))) { case 0: break; case LBREAK: case LCONTIN: if (level != 2) { source = old_source; quitenv(NULL); internal_errorf(Tf_cant_s, Tshell, i == LBREAK ? Tbreak : Tcontinue); /* NOTREACHED */ } /* assert: interactive == false */ /* FALLTHROUGH */ case LINTR: /* we get here if SIGINT not caught or ignored */ case LERROR: case LSHELL: if (interactive) { if (i == LINTR) shellf("\n"); /* * Reset any eof that was read as part of a * multiline command. */ if (Flag(FIGNOREEOF) && s->type == SEOF && wastty) s->type = SSTDIN; /* * Used by exit command to get back to * top level shell. Kind of strange since * interactive is set if we are reading from * a tty, but to have stopped jobs, one only * needs FMONITOR set (not FTALKING/SF_TTY)... */ /* toss any input we have so far */ yyrecursive_pop(true); s->start = s->str = null; retrace_info = NULL; herep = heres; break; } /* FALLTHROUGH */ case LEXIT: case LLEAVE: case LRETURN: source = old_source; quitenv(NULL); /* keep on going */ unwind(i); /* NOTREACHED */ default: source = old_source; quitenv(NULL); internal_errorf(Tunexpected_type, Tunwind, Tshell, i); /* NOTREACHED */ } while (/* CONSTCOND */ 1) { if (trap) runtraps(0); if (s->next == NULL) { if (Flag(FVERBOSE)) s->flags |= SF_ECHO; else s->flags &= ~SF_ECHO; } if (interactive) { j_notify(); set_prompt(PS1, s); } t = compile(s, sfirst, true); if (interactive) histsave(&s->line, NULL, HIST_FLUSH, true); sfirst = false; if (!t) goto source_no_tree; if (t->type == TEOF) { if (wastty && Flag(FIGNOREEOF) && --attempts > 0) { shellf("Use 'exit' to leave mksh\n"); s->type = SSTDIN; } else if (wastty && !really_exit && j_stopped_running()) { really_exit = true; s->type = SSTDIN; } else { /* * this for POSIX which says EXIT traps * shall be taken in the environment * immediately after the last command * executed. */ if (level == 0) unwind(LEXIT); break; } } else if ((s->flags & SF_MAYEXEC) && t->type == TCOM) t->u.evalflags |= DOTCOMEXEC; if (!Flag(FNOEXEC) || (s->flags & SF_TTY)) exstat = execute(t, 0, NULL) & 0xFF; if (t->type != TEOF && interactive && really_exit) really_exit = false; source_no_tree: reclaim(); } quitenv(NULL); source = old_source; return (exstat & 0xFF); }