File indexing completed on 2024-04-28 15:22:04

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