File indexing completed on 2025-02-16 13:03:26
0001 /* 0002 This file is part of the KDE project, module kdesu. 0003 SPDX-FileCopyrightText: 1999, 2000 Geert Jansen <jansen@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-only 0006 */ 0007 0008 #ifndef KDESUPTYPROCESS_H 0009 #define KDESUPTYPROCESS_H 0010 0011 #include <memory> 0012 #include <sys/types.h> 0013 0014 #include <QByteArray> 0015 #include <QList> 0016 #include <QString> 0017 #include <QStringList> 0018 0019 #include <kdesu/kdesu_export.h> 0020 0021 #include <KPty> 0022 0023 namespace KDESu 0024 { 0025 class PtyProcessPrivate; 0026 0027 /** \class PtyProcess ptyprocess.h KDESu/PtyProcess 0028 * Synchronous communication with tty programs. 0029 * 0030 * PtyProcess provides synchronous communication with tty based programs. 0031 * The communications channel used is a pseudo tty (as opposed to a pipe) 0032 * This means that programs which require a terminal will work. 0033 */ 0034 0035 class KDESU_EXPORT PtyProcess 0036 { 0037 public: 0038 /** Error return values for checkPidExited() */ 0039 enum checkPidStatus { 0040 Error = -1, /**< No child */ 0041 NotExited = -2, /**< Child hasn't exited */ 0042 Killed = -3, /**< Child terminated by signal */ 0043 }; 0044 0045 PtyProcess(); 0046 virtual ~PtyProcess(); 0047 0048 /** 0049 * Forks off and execute a command. The command's standard in and output 0050 * are connected to the pseudo tty. They are accessible with readLine 0051 * and writeLine. 0052 * @param command The command to execute. 0053 * @param args The arguments to the command. 0054 * @return 0 on success, -1 on error. errno might give more information then. 0055 */ 0056 int exec(const QByteArray &command, const QList<QByteArray> &args); 0057 0058 /** 0059 * Reads a line from the program's standard out. Depending on the @em block 0060 * parameter, this call blocks until something was read. 0061 * Note that in some situations this function will return less than a full 0062 * line of output, but never more. Newline characters are stripped. 0063 * @param block Block until a full line is read? 0064 * @return The output string. 0065 */ 0066 QByteArray readLine(bool block = true); 0067 0068 /** 0069 * Read all available output from the program's standard out. 0070 * @param block If no output is in the buffer, should the function block 0071 * (else it will return an empty QByteArray)? 0072 * @return The output. 0073 */ 0074 QByteArray readAll(bool block = true); 0075 0076 /** 0077 * Writes a line of text to the program's standard in. 0078 * @param line The text to write. 0079 * @param addNewline Adds a '\n' to the line. 0080 */ 0081 void writeLine(const QByteArray &line, bool addNewline = true); 0082 0083 /** 0084 * Puts back a line of input. 0085 * @param line The line to put back. 0086 * @param addNewline Adds a '\n' to the line. 0087 */ 0088 void unreadLine(const QByteArray &line, bool addNewline = true); 0089 0090 /** 0091 * Sets the exit string. If a line of program output matches this, 0092 * waitForChild() will terminate the program and return. 0093 */ 0094 void setExitString(const QByteArray &exit); 0095 0096 /** 0097 * Waits for the child to exit. See also setExitString. 0098 */ 0099 int waitForChild(); 0100 0101 /** 0102 * Waits until the pty has cleared the ECHO flag. This is useful 0103 * when programs write a password prompt before they disable ECHO. 0104 * Disabling it might flush any input that was written. 0105 */ 0106 int waitSlave(); 0107 0108 #if KDESU_ENABLE_DEPRECATED_SINCE(5, 0) 0109 /** 0110 * @deprecated since 5.0, use waitSlave() 0111 */ 0112 KDESU_DEPRECATED_VERSION(5, 0, "Use PtyProcess::waitSlave()") 0113 int WaitSlave() 0114 { 0115 return waitSlave(); 0116 } 0117 #endif 0118 0119 /** 0120 * Enables/disables local echo on the pseudo tty. 0121 */ 0122 int enableLocalEcho(bool enable = true); 0123 0124 /** 0125 * Enables/disables terminal output. Relevant only to some subclasses. 0126 */ 0127 void setTerminal(bool terminal); 0128 0129 /** 0130 * Overwrites the password as soon as it is used. Relevant only to 0131 * some subclasses. 0132 */ 0133 void setErase(bool erase); 0134 0135 /** 0136 * Set additinal environment variables. 0137 */ 0138 void setEnvironment(const QList<QByteArray> &env); 0139 0140 /** 0141 * Returns the filedescriptor of the process. 0142 */ 0143 int fd() const; 0144 0145 /** 0146 * Returns the pid of the process. 0147 */ 0148 int pid() const; 0149 0150 /* 0151 ** This is a collection of static functions that can be 0152 ** used for process control inside kdesu. I'd suggest 0153 ** against using this publicly. There are probably 0154 ** nicer Qt based ways to do what you want. 0155 */ 0156 0157 /** 0158 ** Wait @p ms milliseconds (ie. 1/10th of a second is 100ms), 0159 ** using @p fd as a filedescriptor to wait on. Returns 0160 ** select(2)'s result, which is -1 on error, 0 on timeout, 0161 ** or positive if there is data on one of the selected fd's. 0162 ** 0163 ** @p ms must be in the range 0..999 (i.e. the maximum wait 0164 ** duration is 999ms, almost one second). 0165 */ 0166 static int waitMS(int fd, int ms); 0167 0168 /** 0169 ** Basic check for the existence of @p pid. 0170 ** Returns true iff @p pid is an extant process, 0171 ** (one you could kill - see man kill(2) for signal 0). 0172 */ 0173 static bool checkPid(pid_t pid); 0174 0175 /** 0176 ** Check process exit status for process @p pid. 0177 ** If child @p pid has exited, return its exit status, 0178 ** (which may be zero). 0179 ** On error (no child, no exit), return -1. 0180 ** If child @p has not exited, return -2. 0181 */ 0182 static int checkPidExited(pid_t pid); 0183 0184 protected: 0185 KDESU_NO_EXPORT explicit PtyProcess(PtyProcessPrivate &dd); 0186 0187 /** Standard hack to add virtual methods in a BC way. Unused. */ 0188 virtual void virtual_hook(int id, void *data); 0189 QList<QByteArray> environment() const; 0190 0191 // KF6 TODO: move to PtyProcessPrivate 0192 bool m_erase; /**< @see setErase() */ 0193 bool m_terminal; /**< Indicates running in a terminal, causes additional 0194 newlines to be printed after output. Set to @c false 0195 in constructor. @see setTerminal() */ 0196 int m_pid; /**< PID of child process */ 0197 QByteArray m_command; /**< Unused */ 0198 QByteArray m_exitString; /**< String to scan for in output that indicates child has exited. */ 0199 0200 private: 0201 KDESU_NO_EXPORT int init(); 0202 KDESU_NO_EXPORT int setupTTY(); 0203 0204 private: 0205 friend class StubProcess; 0206 friend class SshProcess; 0207 friend class SuProcess; 0208 std::unique_ptr<PtyProcessPrivate> const d; 0209 // KF6 TODO: change private d to protected d_ptr, use normal Q_DECLARE_PRIVATE, remove friend 0210 }; 0211 0212 } 0213 0214 #endif // KDESUPTYPROCESS_H