def SourceStartupFile(fd_state, rc_path, lang, parse_ctx, cmd_ev): # type: (process.FdState, str, str, parse_lib.ParseContext, cmd_eval.CommandEvaluator) -> None # Right now this is called when the shell is interactive. (Maybe it should # be called on login_shel too.) # # Terms: # - interactive shell: Roughly speaking, no args or -c, and isatty() is true # for stdin and stdout. # - login shell: Started from the top level, e.g. from init or ssh. # # We're not going to copy everything bash does because it's too complex, but # for reference: # https://www.gnu.org/software/bash/manual/bash.html#Bash-Startup-Files # Bash also has --login. try: f = fd_state.Open(rc_path) except OSError as e: # TODO: Could warn about nonexistent explicit --rcfile? if e.errno != errno.ENOENT: raise # Goes to top level. Handle this better? return arena = parse_ctx.arena rc_line_reader = reader.FileLineReader(f, arena) rc_c_parser = parse_ctx.MakeOshParser(rc_line_reader) with alloc.ctx_Location(arena, source.SourcedFile(rc_path)): # TODO: handle status, e.g. 2 for ParseError status = main_loop.Batch(cmd_ev, rc_c_parser, arena) f.close()
def SourceStartupFile(rc_path, lang, parse_ctx, ex): # Right now this is called when the shell is interactive. (Maybe it should # be called on login_shel too.) # # Terms: # - interactive shell: Roughly speaking, no args or -c, and isatty() is true # for stdin and stdout. # - login shell: Started from the top level, e.g. from init or ssh. # # We're not going to copy everything bash does because it's too complex, but # for reference: # https://www.gnu.org/software/bash/manual/bash.html#Bash-Startup-Files # Bash also has --login. try: arena = parse_ctx.arena with open(rc_path) as f: rc_line_reader = reader.FileLineReader(f, arena) if lang == 'osh': rc_c_parser = parse_ctx.MakeOshParser(rc_line_reader) else: rc_c_parser = parse_ctx.MakeOilParser(rc_line_reader) arena.PushSource(source.SourcedFile(rc_path)) try: # TODO: don't ignore status, e.g. status == 2 when there's a parse error. status = main_loop.Batch(ex, rc_c_parser, arena) finally: arena.PopSource() except IOError as e: if e.errno != errno.ENOENT: raise
def Run(self, cmd_val): # type: (cmd_value__Argv) -> int call_spid = cmd_val.arg_spids[0] _, arg_r = flag_spec.ParseCmdVal('source', cmd_val) path = arg_r.Peek() if path is None: e_usage('missing required argument') arg_r.Next() resolved = self.search_path.Lookup(path, exec_required=False) if resolved is None: resolved = path try: f = self.fd_state.Open(resolved) # Shell can't use descriptors 3-9 except OSError as e: self.errfmt.Print_('source %r failed: %s' % (path, pyutil.strerror(e)), span_id=cmd_val.arg_spids[1]) return 1 try: line_reader = reader.FileLineReader(f, self.arena) c_parser = self.parse_ctx.MakeOshParser(line_reader) # A sourced module CAN have a new arguments array, but it always shares # the same variable scope as the caller. The caller could be at either a # global or a local scope. source_argv = arg_r.Rest() self.mem.PushSource(path, source_argv) src = source.SourcedFile(path, call_spid) try: with alloc.ctx_Location(self.arena, src): status = main_loop.Batch(self.cmd_ev, c_parser, self.arena, cmd_flags=cmd_eval.IsEvalSource) finally: self.mem.PopSource(source_argv) return status except _ControlFlow as e: if e.IsReturn(): return e.StatusCode() else: raise finally: f.close()
def Run(self, cmd_val): # type: (cmd_value__Argv) -> int argv = cmd_val.argv call_spid = cmd_val.arg_spids[0] try: path = argv[1] except IndexError: raise error.Usage('missing required argument') resolved = self.search_path.Lookup(path, exec_required=False) if resolved is None: resolved = path try: f = self.fd_state.Open(resolved) # Shell can't use descriptors 3-9 except OSError as e: self.errfmt.Print('source %r failed: %s', path, pyutil.strerror_OS(e), span_id=cmd_val.arg_spids[1]) return 1 try: line_reader = reader.FileLineReader(f, self.arena) c_parser = self.parse_ctx.MakeOshParser(line_reader) # A sourced module CAN have a new arguments array, but it always shares # the same variable scope as the caller. The caller could be at either a # global or a local scope. source_argv = argv[2:] self.mem.PushSource(path, source_argv) src = source.SourcedFile(path, call_spid) self.arena.PushSource(src) try: status = main_loop.Batch(self.cmd_ev, c_parser, self.arena) finally: self.arena.PopSource() self.mem.PopSource(source_argv) return status except _ControlFlow as e: if e.IsReturn(): return e.StatusCode() else: raise finally: f.close()
def _Source(self, arg_vec): argv = arg_vec.strs call_spid = arg_vec.spids[0] try: path = argv[1] except IndexError: raise args.UsageError('missing required argument') resolved = self.search_path.Lookup(path, exec_required=False) if resolved is None: resolved = path try: f = self.fd_state.Open(resolved) # Shell can't use descriptors 3-9 except OSError as e: self.errfmt.Print('source %r failed: %s', path, posix.strerror(e.errno), span_id=arg_vec.spids[1]) return 1 try: line_reader = reader.FileLineReader(f, self.arena) c_parser = self.parse_ctx.MakeOshParser(line_reader) # A sourced module CAN have a new arguments array, but it always shares # the same variable scope as the caller. The caller could be at either a # global or a local scope. source_argv = argv[2:] self.mem.PushSource(path, source_argv) try: status = self._EvalHelper(c_parser, source.SourcedFile(path, call_spid)) finally: self.mem.PopSource(source_argv) return status except _ControlFlow as e: if e.IsReturn(): return e.StatusCode() else: raise finally: f.close()