15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/process_proxy/process_proxy.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/ioctl.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 15a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/posix/eintr_wrapper.h" 16a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/kill.h" 17a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/launch.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/process_proxy/process_output_watcher.h" 20a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "third_party/cros_system_api/switches/chrome_switches.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum PipeEnd { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PIPE_END_READ, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PIPE_END_WRITE 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum PseudoTerminalFd { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PT_MASTER_FD, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PT_SLAVE_FD 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInvalidFd = -1; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProcessProxy::ProcessProxy(): process_launched_(false), 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_set_(false), 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) watcher_started_(false) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set pipes to initial, invalid value so we can easily know if a pipe was 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // opened by us. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClearAllFdPairs(); 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProcessProxy::Open(const std::string& command, pid_t* pid) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (process_launched_) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreatePseudoTerminalPair(pt_pair_)) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) process_launched_ = LaunchProcess(command, pt_pair_[PT_SLAVE_FD], &pid_); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (process_launched_) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We won't need these anymore. These will be used by the launched process. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseFd(&pt_pair_[PT_SLAVE_FD]); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pid = pid_; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Process launched: " << pid_; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseFdPair(pt_pair_); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return process_launched_; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ProcessProxy::StartWatchingOnThread( 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Thread* watch_thread, 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ProcessOutputCallback& callback) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(process_launched_); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (watcher_started_) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pipe(shutdown_pipe_)) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We give ProcessOutputWatcher a copy of master to make life easier during 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tear down. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(tbarzic): improve fd managment. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int master_copy = HANDLE_EINTR(dup(pt_pair_[PT_MASTER_FD])); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (master_copy == -1) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_set_ = true; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_ = callback; 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_runner_ = base::MessageLoopProxy::current(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This object will delete itself once watching is stopped. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It also takes ownership of the passed fds. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessOutputWatcher* output_watcher = 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ProcessOutputWatcher(master_copy, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_pipe_[PIPE_END_READ], 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ProcessProxy::OnProcessOutput, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Output watcher took ownership of the read end of shutdown pipe. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_pipe_[PIPE_END_READ] = -1; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |watch| thread is blocked by |output_watcher| from now on. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) watch_thread->message_loop()->PostTask(FROM_HERE, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ProcessOutputWatcher::Start, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(output_watcher))); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) watcher_started_ = true; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProcessProxy::OnProcessOutput(ProcessOutputType type, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& output) { 1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!callback_runner_.get()) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_runner_->PostTask( 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ProcessProxy::CallOnProcessOutputCallback, 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, type, output)); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProcessProxy::CallOnProcessOutputCallback(ProcessOutputType type, 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& output) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We may receive some output even after Close was called (crosh process does 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not have to quit instantly, or there may be some trailing data left in 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // output stream fds). In that case owner of the callback may be gone so we 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't want to send it anything. |callback_set_| is reset when this gets 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // closed. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (callback_set_) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_.Run(type, output); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProcessProxy::StopWatching() { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!watcher_started_) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signal Watcher that we are done. We use self-pipe trick to unblock watcher. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Anything may be written to the pipe. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char message[] = "q"; 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return base::WriteFileDescriptor(shutdown_pipe_[PIPE_END_WRITE], 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) message, sizeof(message)); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProcessProxy::Close() { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!process_launched_) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) process_launched_ = false; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_set_ = false; 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_ = ProcessOutputCallback(); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_runner_ = NULL; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::KillProcess(pid_, 0, true /* wait */); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(tbarzic): What if this fails? 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopWatching(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAllFdPairs(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProcessProxy::Write(const std::string& text) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!process_launched_) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't want to write '\0' to the pipe. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t data_size = text.length() * sizeof(*text.c_str()); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_written = 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WriteFileDescriptor(pt_pair_[PT_MASTER_FD], 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) text.c_str(), data_size); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (bytes_written == static_cast<int>(data_size)); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProcessProxy::OnTerminalResize(int width, int height) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (width < 0 || height < 0) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winsize ws; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Number of rows. 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ws.ws_row = height; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Number of columns. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ws.ws_col = width; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (HANDLE_EINTR(ioctl(pt_pair_[PT_MASTER_FD], TIOCSWINSZ, &ws)) != -1); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProcessProxy::~ProcessProxy() { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In case watcher did not started, we may get deleted without calling Close. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In that case we have to clean up created pipes. If watcher had been 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // started, there will be a callback with our reference owned by 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process_output_watcher until Close is called, so we know Close has been 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called by now (and pipes have been cleaned). 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!watcher_started_) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAllFdPairs(); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProcessProxy::CreatePseudoTerminalPair(int *pt_pair) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClearFdPair(pt_pair); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open Master. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pt_pair[PT_MASTER_FD] = HANDLE_EINTR(posix_openpt(O_RDWR | O_NOCTTY)); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pt_pair[PT_MASTER_FD] == -1) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (grantpt(pt_pair_[PT_MASTER_FD]) != 0 || 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unlockpt(pt_pair_[PT_MASTER_FD]) != 0) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseFd(&pt_pair[PT_MASTER_FD]); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* slave_name = NULL; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Per man page, slave_name must not be freed. 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) slave_name = ptsname(pt_pair_[PT_MASTER_FD]); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (slave_name) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pt_pair_[PT_SLAVE_FD] = HANDLE_EINTR(open(slave_name, O_RDWR | O_NOCTTY)); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pt_pair_[PT_SLAVE_FD] == -1) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseFdPair(pt_pair); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProcessProxy::LaunchProcess(const std::string& command, int slave_fd, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t* pid) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Redirect crosh process' output and input so we can read it. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::FileHandleMappingVector fds_mapping; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fds_mapping.push_back(std::make_pair(slave_fd, STDIN_FILENO)); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fds_mapping.push_back(std::make_pair(slave_fd, STDOUT_FILENO)); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fds_mapping.push_back(std::make_pair(slave_fd, STDERR_FILENO)); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchOptions options; 227a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Do not set NO_NEW_PRIVS on processes if the system is in dev-mode. This 228a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // permits sudo in the crosh shell when in developer mode. 229a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch options.allow_new_privs = base::CommandLine::ForCurrentProcess()-> 230a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch HasSwitch(chromeos::switches::kSystemInDevMode); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.fds_to_remap = &fds_mapping; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.ctrl_terminal_fd = slave_fd; 23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) options.environ["TERM"] = "xterm"; 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Launch the process. 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::LaunchProcess(CommandLine(base::FilePath(command)), options, 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pid); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProcessProxy::CloseAllFdPairs() { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseFdPair(pt_pair_); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseFdPair(shutdown_pipe_); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProcessProxy::CloseFdPair(int* pipe) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseFd(&(pipe[PIPE_END_READ])); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseFd(&(pipe[PIPE_END_WRITE])); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProcessProxy::CloseFd(int* fd) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*fd != kInvalidFd) { 252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IGNORE_EINTR(close(*fd)) != 0) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DPLOG(WARNING) << "close fd failed."; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *fd = kInvalidFd; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProcessProxy::ClearAllFdPairs() { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClearFdPair(pt_pair_); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClearFdPair(shutdown_pipe_); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProcessProxy::ClearFdPair(int* pipe) { 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipe[PIPE_END_READ] = kInvalidFd; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipe[PIPE_END_WRITE] = kInvalidFd; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace chromeos 269