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/** \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
35class KDESU_EXPORT PtyProcess
36{
37public:
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
173protected:
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
189private:
190 KDESU_NO_EXPORT int init();
191 KDESU_NO_EXPORT int setupTTY();
192
193protected:
194 std::unique_ptr<PtyProcessPrivate> const d_ptr;
195
196private:
197 Q_DECLARE_PRIVATE(PtyProcess)
198};
199
200}
201
202#endif // KDESUPTYPROCESS_H
203

source code of kdesu/src/ptyprocess.h