SValue For::Evaluate(const sptr<BShell>& parent, const sptr<ICommand>& shell, bool* outExit) { SVector<SValue> args; for (size_t i = 0 ; i < m_words.CountItems(); i++) { bool insert_args = false; //bout << "WORDS [" << i << "] " << m_words[i] << endl; SValue expanded = Expand(shell, m_words.ItemAt(i), &insert_args); if (insert_args) { collect_arguments(expanded.AsString(), &args); } else { //bout << "adding expanded " << expanded << endl; args.AddItem(expanded); } } *outExit = false; SValue returned = SValue::Status(B_OK); for (size_t i = 0 ; i < args.CountItems() && !*outExit; i++) { //bout << "setting m_condition to be " << args.ItemAt(i) << endl; shell->SetProperty(SValue::String(m_condition), args.ItemAt(i)); returned = m_dolist->Evaluate(parent, shell, outExit); } return returned; }
SValue SimpleCommand::Evaluate(const sptr<BShell>& parent, const sptr<ICommand>& shell, bool* outExit) { // bout << "SimpleCommand::Evaluate: " << m_command << endl; sptr<ICommand> command = NULL; bool doExit = false; *outExit = false; if (m_command != "" && m_command != "exit" && m_command != "return" && m_command != "cd" && m_command != "." && m_command != "source") { SValue cmdName = Expand(shell, m_command); // If the command is actually an ICommand object, // run it in-place. // XXX This isn't quite right -- we really want // to spawn a copy, in which we can set our own // environment. command = ICommand::AsInterface(cmdName); // Not an object, try to execute by name. if (command == NULL) { command = shell->Spawn(cmdName.AsString()); } if (command == NULL) { parent->TextError() << "bsh: " << m_command << ": command not found" << endl; return SValue::Status(B_NAME_NOT_FOUND); } } else command = shell; SValue result; if (m_prefix != NULL) result = m_prefix->Evaluate(parent, command, &doExit); if (m_suffix != NULL) m_suffix->Evaluate(parent, command, &doExit); SVector<SString> words; if (m_suffix != NULL) words = m_suffix->GetWords(); // set redirects // build argument list ICommand::ArgList args; args.AddItem(SValue::String(m_command)); for (size_t index = 0 ; index < words.CountItems(); index++) { bool expand = false; //bout << "WORDS [" << index << "] " << words[index] << endl; SValue expanded = Expand(shell, words.ItemAt(index), &expand); //bout << "WORDS [" << index << "] expaned to " << expanded << endl; if (expand) { collect_arguments(expanded.AsString(), &args); } else { args.AddItem(expanded); } } // only run this if we are a newly spawned command! if (command != shell) { result = command->Run(args); // This command may be a function, that could call "exit". *outExit = parent->ExitRequested(); } else if (m_command == "exit" || m_command == "return") { result = args.CountItems() > 1 ? args[1] : SValue::Status(B_OK); *outExit = true; if (m_command == "exit") { parent->RequestExit(); } } else if (m_command == "cd") { SString path; if (args.CountItems() > 1) { path = args[1].AsString(); } if (path != "") { SString cd=shell->GetProperty(SValue::String("PWD")).AsString(); cd.PathAppend(path, true); SNode node(parent->Context().Root()); SValue dir(node.Walk(cd, (uint32_t)0)); if (interface_cast<INode>(dir) != NULL) { shell->SetProperty(SValue::String("PWD"), SValue::String(cd)); result = SValue::Status(B_OK); } else { parent->TextError() << "cd: '" << path << "' is not a directory." << endl; result = SValue::Status(B_BAD_VALUE); } } else { parent->TextError() << "cd: no directory specified." << endl; result = SValue::Status(B_BAD_VALUE); } } else if (m_command == "." || m_command == "source") { if (args.CountItems() > 1) { sptr<ITextInput> input; SString path; find_some_input(args[1], parent, &input, &path); if (input != NULL) { SValue oldFile = parent->GetProperty(kBSH_SCRIPT_FILE); SValue oldDir = parent->GetProperty(kBSH_SCRIPT_DIR); args.RemoveItemsAt(0, 2); args.AddItemAt(SValue::String(path), 0); parent->SetLastResult(SValue::String(path)); parent->SetProperty(kBSH_SCRIPT_FILE, SValue::String(path)); SString parentDir; path.PathGetParent(&parentDir); parent->SetProperty(kBSH_SCRIPT_DIR, SValue::String(parentDir)); FunctionCommand::ArgumentHandler argHandler; argHandler.ApplyArgs(parent, args, true); sptr<Lexer> lexer = new Lexer(parent, input, parent->TextOutput(), false); SValue result; if (lexer != NULL) { Parser parser(parent); SValue result = parser.Parse(lexer); } else { parent->TextError() << m_command << ": out of memory." << endl; result = SValue::Status(B_NO_MEMORY); } argHandler.RestoreArgs(parent); parent->SetProperty(kBSH_SCRIPT_FILE, oldFile); parent->SetProperty(kBSH_SCRIPT_DIR, oldDir); return result; } else { parent->TextError() << m_command << ": '" << args[1] << "' is not a file." << endl; result = SValue::Status(B_BAD_VALUE); } } else { parent->TextError() << m_command << ": no file specified." << endl; result = SValue::Status(B_BAD_VALUE); } *outExit = parent->ExitRequested(); } return result; }