def NoneAreRunning(self): # type: () -> bool """Test if all jobs are done. Used by 'wait' builtin.""" for _, job in iteritems(self.jobs): # mycpp rewite: from itervalues() if job.State() == job_state_e.Running: return False return True
def _PrintShValue(val, buf): # type: (value_t, mylib.BufWriter) -> None """Using maybe_shell_encode() for legacy xtrace_details.""" # NOTE: This is a bit like _PrintVariables for declare -p result = '?' UP_val = val with tagswitch(val) as case: if case(value_e.Str): val = cast(value__Str, UP_val) result = qsn.maybe_shell_encode(val.s) elif case(value_e.MaybeStrArray): val = cast(value__MaybeStrArray, UP_val) parts = ['('] for s in val.strs: parts.append(qsn.maybe_shell_encode(s)) parts.append(')') result = ' '.join(parts) elif case(value_e.AssocArray): val = cast(value__AssocArray, UP_val) parts = ['('] for k, v in iteritems(val.d): parts.append( '[%s]=%s' % (qsn.maybe_shell_encode(k), qsn.maybe_shell_encode(v))) parts.append(')') result = ' '.join(parts) buf.write(result)
def List(self): # type: () -> None """Used by the 'jobs' builtin. https://pubs.opengroup.org/onlinepubs/9699919799/utilities/jobs.html "By default, the jobs utility shall display the status of all stopped jobs, running background jobs and all jobs whose status has changed and have not been reported by the shell." """ # NOTE: A job is a background process or pipeline. # # echo hi | wc -l -- this starts two processes. Wait for TWO # echo hi | wc -l & -- this starts a process which starts two processes # Wait for ONE. # # bash GROUPS the PIDs by job. And it has their state and code. # $ jobs -l # [1]+ 24414 Stopped sleep 5 # 24415 | sleep 5 # [2] 24502 Running sleep 6 # 24503 | sleep 6 # 24504 | sleep 5 & # [3]- 24508 Running sleep 6 # 24509 | sleep 6 # 24510 | sleep 5 & # # zsh has VERY similar UI. # NOTE: Jobs don't need to show state? Because pipelines are never stopped # -- only the jobs within them are. if mylib.PYTHON: # TODO: don't use __repr__ and so forth print('Jobs:') for pid, job in iteritems(self.jobs): # Use the %1 syntax print('%%%d %s %s' % (pid, job.State(), job)) print('') print('Processes:') for pid, proc in iteritems(self.child_procs): print('%d %s %s' % (pid, proc.state, proc.thunk.DisplayLine()))
def __init__(self, defaults): # type: (Dict[str, value_t]) -> None # New style self.attrs = {} # type: Dict[str, value_t] self.opt_changes = [] # type: List[OptChange] # -o errexit +o nounset self.shopt_changes = [ ] # type: List[OptChange] # -O nullglob +O nullglob self.show_options = False # 'set -o' without an argument self.actions = [] # type: List[str] # for compgen -A self.saw_double_dash = False # for set -- for name, v in iteritems(defaults): self.Set(name, v)
def Run(self, cmd_val): # type: (cmd_value__Argv) -> int attrs, arg_r = flag_spec.ParseCmdVal('trap', cmd_val) arg = arg_types.trap(attrs.attrs) if arg.p: # Print registered handlers for name, value in iteritems(self.traps): # The unit tests rely on this being one line. # bash prints a line that can be re-parsed. print('%s %s' % (name, value.__class__.__name__)) return 0 if arg.l: # List valid signals and hooks for name in _HOOK_NAMES: print(' %s' % name) for name, int_val in signal_def.AllNames(): print('%2d %s' % (int_val, name)) return 0 code_str = arg_r.ReadRequired('requires a code string') sig_spec, sig_spid = arg_r.ReadRequired2( 'requires a signal or hook name') # sig_key is NORMALIZED sig_spec: a signal number string or string hook # name. sig_key = None # type: Optional[str] sig_num = None if sig_spec in _HOOK_NAMES: sig_key = sig_spec elif sig_spec == '0': # Special case sig_key = 'EXIT' else: sig_num = _GetSignalNumber(sig_spec) if sig_num is not None: sig_key = str(sig_num) if sig_key is None: self.errfmt.Print_("Invalid signal or hook %r" % sig_spec, span_id=cmd_val.arg_spids[2]) return 1 # NOTE: sig_spec isn't validated when removing handlers. if code_str == '-': if sig_key in _HOOK_NAMES: try: del self.traps[sig_key] except KeyError: pass return 0 if sig_num is not None: try: del self.traps[sig_key] except KeyError: pass self.sig_state.RemoveUserTrap(sig_num) return 0 raise AssertionError('Signal or trap') # Try parsing the code first. node = self._ParseTrapCode(code_str) if node is None: return 1 # ParseTrapCode() prints an error for us. # Register a hook. if sig_key in _HOOK_NAMES: if sig_key in ('ERR', 'RETURN', 'DEBUG'): stderr_line("osh warning: The %r hook isn't implemented", sig_spec) self.traps[sig_key] = _TrapHandler(node, self.nodes_to_run) return 0 # Register a signal. if sig_num is not None: handler = _TrapHandler(node, self.nodes_to_run) # For signal handlers, the traps dictionary is used only for debugging. self.traps[sig_key] = handler if sig_num in (signal.SIGKILL, signal.SIGSTOP): self.errfmt.Print_("Signal %r can't be handled" % sig_spec, span_id=sig_spid) # Other shells return 0, but this seems like an obvious error return 1 self.sig_state.AddUserTrap(sig_num, handler) return 0 raise AssertionError('Signal or trap')