1 //===-- ProcessLaunchInfo.h -------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_HOST_PROCESSLAUNCHINFO_H
10 #define LLDB_HOST_PROCESSLAUNCHINFO_H
11 
12 // C++ Headers
13 #include <string>
14 
15 // LLDB Headers
16 #include "lldb/Utility/Flags.h"
17 
18 #include "lldb/Host/FileAction.h"
19 #include "lldb/Host/Host.h"
20 #include "lldb/Host/PseudoTerminal.h"
21 #include "lldb/Utility/FileSpec.h"
22 #include "lldb/Utility/ProcessInfo.h"
23 #include "lldb/Utility/StructuredData.h"
24 
25 namespace lldb_private {
26 
27 // ProcessLaunchInfo
28 //
29 // Describes any information that is required to launch a process.
30 
31 class ProcessLaunchInfo : public ProcessInfo {
32 public:
33   ProcessLaunchInfo();
34 
35   ProcessLaunchInfo(const FileSpec &stdin_file_spec,
36                     const FileSpec &stdout_file_spec,
37                     const FileSpec &stderr_file_spec,
38                     const FileSpec &working_dir, uint32_t launch_flags);
39 
AppendFileAction(const FileAction & info)40   void AppendFileAction(const FileAction &info) {
41     m_file_actions.push_back(info);
42   }
43 
44   bool AppendCloseFileAction(int fd);
45 
46   bool AppendDuplicateFileAction(int fd, int dup_fd);
47 
48   bool AppendOpenFileAction(int fd, const FileSpec &file_spec, bool read,
49                             bool write);
50 
51   bool AppendSuppressFileAction(int fd, bool read, bool write);
52 
53   // Redirect stdin/stdout/stderr to a pty, if no action for the respective file
54   // descriptor is specified. (So if stdin and stdout already have file actions,
55   // but stderr doesn't, then only stderr will be redirected to a pty.)
56   llvm::Error SetUpPtyRedirection();
57 
GetNumFileActions()58   size_t GetNumFileActions() const { return m_file_actions.size(); }
59 
60   const FileAction *GetFileActionAtIndex(size_t idx) const;
61 
62   const FileAction *GetFileActionForFD(int fd) const;
63 
GetFlags()64   Flags &GetFlags() { return m_flags; }
65 
GetFlags()66   const Flags &GetFlags() const { return m_flags; }
67 
68   const FileSpec &GetWorkingDirectory() const;
69 
70   void SetWorkingDirectory(const FileSpec &working_dir);
71 
72   const char *GetProcessPluginName() const;
73 
74   void SetProcessPluginName(llvm::StringRef plugin);
75 
76   const FileSpec &GetShell() const;
77 
78   void SetShell(const FileSpec &shell);
79 
GetResumeCount()80   uint32_t GetResumeCount() const { return m_resume_count; }
81 
SetResumeCount(uint32_t c)82   void SetResumeCount(uint32_t c) { m_resume_count = c; }
83 
GetLaunchInSeparateProcessGroup()84   bool GetLaunchInSeparateProcessGroup() const {
85     return m_flags.Test(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
86   }
87 
88   void SetLaunchInSeparateProcessGroup(bool separate);
89 
GetShellExpandArguments()90   bool GetShellExpandArguments() const {
91     return m_flags.Test(lldb::eLaunchFlagShellExpandArguments);
92   }
93 
94   void SetShellExpandArguments(bool expand);
95 
96   void Clear();
97 
98   bool ConvertArgumentsForLaunchingInShell(Status &error, bool will_debug,
99                                            bool first_arg_is_full_shell_command,
100                                            uint32_t num_resumes);
101 
SetMonitorProcessCallback(Host::MonitorChildProcessCallback callback)102   void SetMonitorProcessCallback(Host::MonitorChildProcessCallback callback) {
103     m_monitor_callback = std::move(callback);
104   }
105 
GetMonitorProcessCallback()106   const Host::MonitorChildProcessCallback &GetMonitorProcessCallback() const {
107     return m_monitor_callback;
108   }
109 
110   /// A Monitor callback which does not take any action on process events. Use
111   /// this if you don't need to take any particular action when the process
112   /// terminates, but you still need to reap it.
113   static void NoOpMonitorCallback(lldb::pid_t pid, int signal, int status);
114 
115   // If the LaunchInfo has a monitor callback, then arrange to monitor the
116   // process. Return true if the LaunchInfo has taken care of monitoring the
117   // process, and false if the caller might want to monitor the process
118   // themselves.
119 
120   bool MonitorProcess() const;
121 
GetPTY()122   PseudoTerminal &GetPTY() { return *m_pty; }
123 
124   // Get and set the actual listener that will be used for the process events
GetListener()125   lldb::ListenerSP GetListener() const { return m_listener_sp; }
126 
SetListener(const lldb::ListenerSP & listener_sp)127   void SetListener(const lldb::ListenerSP &listener_sp) {
128     m_listener_sp = listener_sp;
129   }
130 
GetHijackListener()131   lldb::ListenerSP GetHijackListener() const { return m_hijack_listener_sp; }
132 
SetHijackListener(const lldb::ListenerSP & listener_sp)133   void SetHijackListener(const lldb::ListenerSP &listener_sp) {
134     m_hijack_listener_sp = listener_sp;
135   }
136 
SetLaunchEventData(const char * data)137   void SetLaunchEventData(const char *data) { m_event_data.assign(data); }
138 
GetLaunchEventData()139   const char *GetLaunchEventData() const { return m_event_data.c_str(); }
140 
141   void SetDetachOnError(bool enable);
142 
GetDetachOnError()143   bool GetDetachOnError() const {
144     return m_flags.Test(lldb::eLaunchFlagDetachOnError);
145   }
146 
IsScriptedProcess()147   bool IsScriptedProcess() const {
148     return !m_scripted_process_class_name.empty();
149   }
150 
GetScriptedProcessClassName()151   std::string GetScriptedProcessClassName() const {
152     return m_scripted_process_class_name;
153   }
154 
SetScriptedProcessClassName(std::string name)155   void SetScriptedProcessClassName(std::string name) {
156     m_scripted_process_class_name = name;
157   }
158 
159   lldb_private::StructuredData::DictionarySP
GetScriptedProcessDictionarySP()160   GetScriptedProcessDictionarySP() const {
161     return m_scripted_process_dictionary_sp;
162   }
163 
SetScriptedProcessDictionarySP(lldb_private::StructuredData::DictionarySP dictionary_sp)164   void SetScriptedProcessDictionarySP(
165       lldb_private::StructuredData::DictionarySP dictionary_sp) {
166     m_scripted_process_dictionary_sp = dictionary_sp;
167   }
168 
169 protected:
170   FileSpec m_working_dir;
171   std::string m_plugin_name;
172   FileSpec m_shell;
173   Flags m_flags; // Bitwise OR of bits from lldb::LaunchFlags
174   std::vector<FileAction> m_file_actions; // File actions for any other files
175   std::shared_ptr<PseudoTerminal> m_pty;
176   uint32_t m_resume_count = 0; // How many times do we resume after launching
177   Host::MonitorChildProcessCallback m_monitor_callback;
178   std::string m_event_data; // A string passed to the plugin launch, having no
179                             // meaning to the upper levels of lldb.
180   lldb::ListenerSP m_listener_sp;
181   lldb::ListenerSP m_hijack_listener_sp;
182   std::string m_scripted_process_class_name; // The name of the class that will
183                                              // manage a scripted process.
184   StructuredData::DictionarySP
185       m_scripted_process_dictionary_sp; // A dictionary that holds key/value
186                                         // pairs passed to the scripted process.
187 };
188 }
189 
190 #endif // LLDB_HOST_PROCESSLAUNCHINFO_H
191