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

source code of kdesu/src/ptyprocess.h