1 | /* |
2 | This file is part of the KDE project, module kdesu. |
3 | SPDX-FileCopyrightText: 1999, 2000 Geert Jansen <jansen@kde.org> |
4 | |
5 | SPDX-License-Identifier: GPL-2.0-only |
6 | */ |
7 | |
8 | #ifndef KDESUPTYPROCESS_H |
9 | #define KDESUPTYPROCESS_H |
10 | |
11 | #include <memory> |
12 | #include <sys/types.h> |
13 | |
14 | #include <QByteArray> |
15 | #include <QList> |
16 | #include <QString> |
17 | #include <QStringList> |
18 | |
19 | #include <kdesu/kdesu_export.h> |
20 | |
21 | #include <KPty> |
22 | |
23 | namespace KDESu |
24 | { |
25 | class PtyProcessPrivate; |
26 | |
27 | /** \class PtyProcess ptyprocess.h KDESu/PtyProcess |
28 | * Synchronous communication with tty programs. |
29 | * |
30 | * PtyProcess provides synchronous communication with tty based programs. |
31 | * The communications channel used is a pseudo tty (as opposed to a pipe) |
32 | * This means that programs which require a terminal will work. |
33 | */ |
34 | |
35 | class KDESU_EXPORT PtyProcess |
36 | { |
37 | public: |
38 | /** Error return values for checkPidExited() */ |
39 | enum checkPidStatus { |
40 | Error = -1, /**< No child */ |
41 | NotExited = -2, /**< Child hasn't exited */ |
42 | Killed = -3, /**< Child terminated by signal */ |
43 | }; |
44 | |
45 | PtyProcess(); |
46 | virtual ~PtyProcess(); |
47 | |
48 | /** |
49 | * Forks off and execute a command. The command's standard in and output |
50 | * are connected to the pseudo tty. They are accessible with readLine |
51 | * and writeLine. |
52 | * @param command The command to execute. |
53 | * @param args The arguments to the command. |
54 | * @return 0 on success, -1 on error. errno might give more information then. |
55 | */ |
56 | int exec(const QByteArray &command, const QList<QByteArray> &args); |
57 | |
58 | /** |
59 | * Reads a line from the program's standard out. Depending on the @em block |
60 | * parameter, this call blocks until something was read. |
61 | * Note that in some situations this function will return less than a full |
62 | * line of output, but never more. Newline characters are stripped. |
63 | * @param block Block until a full line is read? |
64 | * @return The output string. |
65 | */ |
66 | QByteArray readLine(bool block = true); |
67 | |
68 | /** |
69 | * Read all available output from the program's standard out. |
70 | * @param block If no output is in the buffer, should the function block |
71 | * (else it will return an empty QByteArray)? |
72 | * @return The output. |
73 | */ |
74 | QByteArray readAll(bool block = true); |
75 | |
76 | /** |
77 | * Writes a line of text to the program's standard in. |
78 | * @param line The text to write. |
79 | * @param addNewline Adds a '\n' to the line. |
80 | */ |
81 | void writeLine(const QByteArray &line, bool addNewline = true); |
82 | |
83 | /** |
84 | * Puts back a line of input. |
85 | * @param line The line to put back. |
86 | * @param addNewline Adds a '\n' to the line. |
87 | */ |
88 | void unreadLine(const QByteArray &line, bool addNewline = true); |
89 | |
90 | /** |
91 | * Sets the exit string. If a line of program output matches this, |
92 | * waitForChild() will terminate the program and return. |
93 | */ |
94 | void setExitString(const QByteArray &exit); |
95 | |
96 | /** |
97 | * Waits for the child to exit. See also setExitString. |
98 | */ |
99 | int waitForChild(); |
100 | |
101 | /** |
102 | * Waits until the pty has cleared the ECHO flag. This is useful |
103 | * when programs write a password prompt before they disable ECHO. |
104 | * Disabling it might flush any input that was written. |
105 | */ |
106 | int waitSlave(); |
107 | |
108 | /** |
109 | * Enables/disables local echo on the pseudo tty. |
110 | */ |
111 | int enableLocalEcho(bool enable = true); |
112 | |
113 | /** |
114 | * Enables/disables terminal output. Relevant only to some subclasses. |
115 | */ |
116 | void setTerminal(bool terminal); |
117 | |
118 | /** |
119 | * Overwrites the password as soon as it is used. Relevant only to |
120 | * some subclasses. |
121 | */ |
122 | void setErase(bool erase); |
123 | |
124 | /** |
125 | * Set additinal environment variables. |
126 | */ |
127 | void setEnvironment(const QList<QByteArray> &env); |
128 | |
129 | /** |
130 | * Returns the filedescriptor of the process. |
131 | */ |
132 | int fd() const; |
133 | |
134 | /** |
135 | * Returns the pid of the process. |
136 | */ |
137 | int pid() const; |
138 | |
139 | /* |
140 | ** This is a collection of static functions that can be |
141 | ** used for process control inside kdesu. I'd suggest |
142 | ** against using this publicly. There are probably |
143 | ** nicer Qt based ways to do what you want. |
144 | */ |
145 | |
146 | /** |
147 | ** Wait @p ms milliseconds (ie. 1/10th of a second is 100ms), |
148 | ** using @p fd as a filedescriptor to wait on. Returns |
149 | ** select(2)'s result, which is -1 on error, 0 on timeout, |
150 | ** or positive if there is data on one of the selected fd's. |
151 | ** |
152 | ** @p ms must be in the range 0..999 (i.e. the maximum wait |
153 | ** duration is 999ms, almost one second). |
154 | */ |
155 | static int waitMS(int fd, int ms); |
156 | |
157 | /** |
158 | ** Basic check for the existence of @p pid. |
159 | ** Returns true iff @p pid is an extant process, |
160 | ** (one you could kill - see man kill(2) for signal 0). |
161 | */ |
162 | static bool checkPid(pid_t pid); |
163 | |
164 | /** |
165 | ** Check process exit status for process @p pid. |
166 | ** If child @p pid has exited, return its exit status, |
167 | ** (which may be zero). |
168 | ** On error (no child, no exit), return -1. |
169 | ** If child @p has not exited, return -2. |
170 | */ |
171 | static int checkPidExited(pid_t pid); |
172 | |
173 | protected: |
174 | KDESU_NO_EXPORT explicit PtyProcess(PtyProcessPrivate &dd); |
175 | |
176 | /** Standard hack to add virtual methods in a BC way. Unused. */ |
177 | virtual void virtual_hook(int id, void *data); |
178 | QList<QByteArray> environment() const; |
179 | |
180 | // KF6 TODO: move to PtyProcessPrivate |
181 | bool m_erase; /**< @see setErase() */ |
182 | bool m_terminal; /**< Indicates running in a terminal, causes additional |
183 | newlines to be printed after output. Set to @c false |
184 | in constructor. @see setTerminal() */ |
185 | int m_pid; /**< PID of child process */ |
186 | QByteArray m_command; /**< Unused */ |
187 | QByteArray m_exitString; /**< String to scan for in output that indicates child has exited. */ |
188 | |
189 | private: |
190 | KDESU_NO_EXPORT int init(); |
191 | KDESU_NO_EXPORT int setupTTY(); |
192 | |
193 | protected: |
194 | std::unique_ptr<PtyProcessPrivate> const d_ptr; |
195 | |
196 | private: |
197 | Q_DECLARE_PRIVATE(PtyProcess) |
198 | }; |
199 | |
200 | } |
201 | |
202 | #endif // KDESUPTYPROCESS_H |
203 | |