File indexing completed on 2024-04-28 09:46:50

0001 /*
0002     SPDX-FileCopyrightText: 2007-2008 Robert Knight <robertknight@gmail.com>
0003     SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #ifndef PTY_H
0009 #define PTY_H
0010 
0011 // Qt
0012 #include <QProcess>
0013 #include <QSize>
0014 
0015 // Konsole
0016 #include "konsoleprivate_export.h"
0017 
0018 #ifndef Q_OS_WIN
0019 // KDE
0020 #include <KPtyProcess>
0021 #else
0022 #include <QObject>
0023 
0024 #include "ptyqt/iptyprocess.h"
0025 #endif
0026 
0027 namespace Konsole
0028 {
0029 /**
0030  * The Pty class is used to start the terminal process,
0031  * send data to it, receive data from it and manipulate
0032  * various properties of the pseudo-teletype interface
0033  * used to communicate with the process.
0034  *
0035  * To use this class, construct an instance and connect
0036  * to the sendData slot and receivedData signal to
0037  * send data to or receive data from the process.
0038  *
0039  * To start the terminal process, call the start() method
0040  * with the program name and appropriate arguments.
0041  */
0042 #ifdef Q_OS_WIN
0043 #define ParentClass QObject
0044 #else
0045 #define ParentClass KPtyProcess
0046 #endif
0047 
0048 class KONSOLEPRIVATE_EXPORT Pty : public ParentClass
0049 {
0050     Q_OBJECT
0051 
0052 public:
0053     /**
0054      * Constructs a new Pty.
0055      *
0056      * Connect to the sendData() slot and receivedData() signal to prepare
0057      * for sending and receiving data from the terminal process.
0058      *
0059      * To start the terminal process, call the run() method with the
0060      * name of the program to start and appropriate arguments.
0061      */
0062     explicit Pty(QObject *parent = nullptr);
0063 
0064     /**
0065      * Construct a process using an open pty master.
0066      * See KPtyProcess::KPtyProcess()
0067      */
0068     explicit Pty(int ptyMasterFd, QObject *parent = nullptr);
0069 
0070     ~Pty() override;
0071 
0072 #ifndef Q_OS_WIN
0073     /**
0074      * Starts the terminal process.
0075      *
0076      * Returns 0 if the process was started successfully or non-zero
0077      * otherwise.
0078      *
0079      * @param program Path to the program to start
0080      * @param arguments Arguments to pass to the program being started
0081      * @param environment A list of key=value pairs which will be added
0082      * to the environment for the new process.  At the very least this
0083      * should include an assignment for the TERM environment variable.
0084      */
0085     int start(const QString &program, const QStringList &arguments, const QStringList &environment);
0086 #else
0087     /**
0088      * Starts the terminal process.
0089      *
0090      * Returns 0 if the process was started successfully or non-zero
0091      * otherwise.
0092      *
0093      * @param program Path to the program to start
0094      * @param arguments Arguments to pass to the program being started
0095      * @param workingDir initial working directory
0096      * @param environment A list of key=value pairs which will be added
0097      * to the environment for the new process.  At the very least this
0098      * should include an assignment for the TERM environment variable.
0099      */
0100     int start(const QString &program, const QStringList &arguments, const QString &workingDir, const QStringList &environment, int cols, int lines);
0101 #endif
0102 
0103     /** Control whether the pty device is writeable by group members. */
0104     void setWriteable(bool writeable);
0105 
0106     /**
0107      * Enables or disables Xon/Xoff flow control.  The flow control setting
0108      * may be changed later by a terminal application, so flowControlEnabled()
0109      * may not equal the value of @p on in the previous call to setFlowControlEnabled()
0110      */
0111     void setFlowControlEnabled(bool on);
0112 
0113     /** Queries the terminal state and returns true if Xon/Xoff flow control is enabled. */
0114     bool flowControlEnabled() const;
0115 
0116     /**
0117      * Sets the size of the window (in columns and lines of characters,
0118      * and width and height in pixels) used by this teletype.
0119      */
0120     void setWindowSize(int columns, int lines, int width, int height);
0121 
0122     /** Returns the size of the window used by this teletype in characters.  See setWindowSize() */
0123     QSize windowSize() const;
0124 
0125     /** Returns the size of the window used by this teletype in pixels.  See setWindowSize() */
0126     QSize pixelSize() const;
0127 
0128     /**
0129      * Sets the special character for erasing previous not-yet-erased character.
0130      * See termios(3) for detailed description.
0131      */
0132     void setEraseChar(char eraseChar);
0133 
0134     /** */
0135     char eraseChar() const;
0136 
0137     /**
0138      * Sets the initial working directory.
0139      */
0140     void setInitialWorkingDirectory(const QString &dir);
0141 
0142     /**
0143      * Returns the process id of the teletype's current foreground
0144      * process.  This is the process which is currently reading
0145      * input sent to the terminal via. sendData()
0146      *
0147      * If there is a problem reading the foreground process group,
0148      * 0 will be returned.
0149      */
0150     int foregroundProcessGroup() const;
0151 
0152     /**
0153      * Close the underlying pty master/slave pair.
0154      */
0155     void closePty();
0156 
0157 #ifdef Q_OS_WIN
0158     int processId() const
0159     {
0160         if (m_proc && m_proc->isAvailable()) {
0161             return m_proc->pid();
0162         }
0163         return 0;
0164     }
0165 
0166     bool isRunning() const
0167     {
0168         return processId() > 0;
0169     }
0170 
0171     QString errorString() const
0172     {
0173         if (m_proc) {
0174             return m_proc->lastError();
0175         }
0176         return QStringLiteral("Conhost failed to start");
0177     }
0178 
0179     bool kill()
0180     {
0181         if (m_proc) {
0182             return m_proc->kill();
0183         }
0184         return false;
0185     }
0186 
0187     int exitCode() const
0188     {
0189         if (m_proc) {
0190             return m_proc->exitCode();
0191         }
0192         return -1;
0193     }
0194 
0195     Q_SIGNAL void finished(int exitCode, QProcess::ExitStatus);
0196 #endif
0197 
0198 public Q_SLOTS:
0199     /**
0200      * Put the pty into UTF-8 mode on systems which support it.
0201      */
0202     void setUtf8Mode(bool on);
0203 
0204     /**
0205      * Sends data to the process currently controlling the
0206      * teletype ( whose id is returned by foregroundProcessGroup() )
0207      *
0208      * @param data the data to send.
0209      */
0210     void sendData(const QByteArray &data);
0211 
0212 Q_SIGNALS:
0213     /**
0214      * Emitted when a new block of data is received from
0215      * the teletype.
0216      *
0217      * @param buffer Pointer to the data received.
0218      * @param length Length of @p buffer
0219      */
0220     void receivedData(const char *buffer, int length);
0221 
0222 private Q_SLOTS:
0223     // called when data is received from the terminal process
0224     void dataReceived();
0225 
0226 private:
0227     void init();
0228 
0229     // takes a list of key=value pairs and adds them
0230     // to the environment for the process
0231     void addEnvironmentVariables(const QStringList &environment);
0232 
0233     int _windowColumns;
0234     int _windowLines;
0235     int _windowWidth;
0236     int _windowHeight;
0237     char _eraseChar;
0238     bool _xonXoff;
0239     bool _utf8;
0240 #ifdef Q_OS_WIN
0241     std::unique_ptr<IPtyProcess> m_proc;
0242 #endif
0243 };
0244 }
0245 
0246 #undef ParentClass
0247 
0248 #endif // PTY_H