void cmdloop(int top) { union node *n; struct stackmark smark; int inter; int numeof = 0; enum skipstate skip; TRACE(("cmdloop(%d) called\n", top)); setstackmark(&smark); for (;;) { if (pendingsigs) dotrap(); inter = 0; if (iflag == 1 && top) { inter = 1; showjobs(out2, SHOW_CHANGED); chkmail(0); flushout(&errout); nflag = 0; } n = parsecmd(inter); TRACE(("cmdloop: "); showtree(n)); /* showtree(n); DEBUG */ if (n == NEOF) { if (!top || numeof >= 50) break; if (nflag) break; if (!stoppedjobs()) { if (!iflag || !Iflag) break; out2str("\nUse \"exit\" to leave shell.\n"); } numeof++; } else if (n != NULL && nflag == 0) { job_warning = (job_warning == 2) ? 1 : 0; numeof = 0; evaltree(n, EV_MORE); } popstackmark(&smark); setstackmark(&smark); /* * Any SKIP* can occur here! SKIP(FUNC|BREAK|CONT) occur when * a dotcmd is in a loop or a function body and appropriate * built-ins occurs in file scope in the sourced file. Values * other than SKIPFILE are reset by the appropriate eval*() * that contained the dotcmd() call. */ skip = current_skipstate(); if (skip != SKIPNONE) { if (skip == SKIPFILE) stop_skipping(); break; } } popstackmark(&smark); }
void dotrap(void) { int i; char *tr; int savestatus; struct skipsave saveskip; in_dotrap++; CTRACE(DBG_TRAP, ("dotrap[%d]: %d pending, traps %sinvalid\n", in_dotrap, pendingsigs, traps_invalid ? "" : "not ")); for (;;) { pendingsigs = 0; for (i = 1 ; ; i++) { if (i >= NSIG) return; if (gotsig[i]) break; } gotsig[i] = 0; if (traps_invalid) continue; tr = trap[i]; CTRACE(DBG_TRAP|DBG_SIG, ("dotrap %d: %s%s%s\n", i, tr ? "\"" : "", tr ? tr : "NULL", tr ? "\"" : "")); if (tr != NULL) { last_trapsig = i; save_skipstate(&saveskip); savestatus = exitstatus; tr = savestr(tr); /* trap code may free trap[i] */ evalstring(tr, 0); ckfree(tr); if (current_skipstate() == SKIPNONE || saveskip.state != SKIPNONE) { restore_skipstate(&saveskip); exitstatus = savestatus; } } } in_dotrap--; }