File indexing completed on 2024-04-21 03:56:41

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2007 Oswald Buddenhagen <ossi@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "kptyprocess.h"
0009 
0010 #include <kptydevice.h>
0011 #include <kuser.h>
0012 
0013 #include <stdlib.h>
0014 #include <unistd.h>
0015 
0016 //////////////////
0017 // private data //
0018 //////////////////
0019 
0020 class KPtyProcessPrivate
0021 {
0022 public:
0023     KPtyProcessPrivate()
0024     {
0025     }
0026 
0027     std::unique_ptr<KPtyDevice> pty;
0028     KPtyProcess::PtyChannels ptyChannels = KPtyProcess::NoChannels;
0029     bool addUtmp = false;
0030 };
0031 
0032 KPtyProcess::KPtyProcess(QObject *parent)
0033     : KPtyProcess(-1, parent)
0034 {
0035 }
0036 
0037 KPtyProcess::KPtyProcess(int ptyMasterFd, QObject *parent)
0038     : KProcess(parent)
0039     , d_ptr(new KPtyProcessPrivate)
0040 {
0041     Q_D(KPtyProcess);
0042 
0043     auto parentChildProcModifier = KProcess::childProcessModifier();
0044     setChildProcessModifier([d, parentChildProcModifier]() {
0045         d->pty->setCTty();
0046         if (d->addUtmp) {
0047             d->pty->login(KUser(KUser::UseRealUserID).loginName().toLocal8Bit().constData(), qgetenv("DISPLAY").constData());
0048         }
0049         if (d->ptyChannels & StdinChannel) {
0050             dup2(d->pty->slaveFd(), 0);
0051         }
0052         if (d->ptyChannels & StdoutChannel) {
0053             dup2(d->pty->slaveFd(), 1);
0054         }
0055         if (d->ptyChannels & StderrChannel) {
0056             dup2(d->pty->slaveFd(), 2);
0057         }
0058 
0059         if (parentChildProcModifier) {
0060             parentChildProcModifier();
0061         }
0062     });
0063 
0064     d->pty = std::make_unique<KPtyDevice>(this);
0065 
0066     if (ptyMasterFd == -1) {
0067         d->pty->open();
0068     } else {
0069         d->pty->open(ptyMasterFd);
0070     }
0071 
0072     connect(this, &QProcess::stateChanged, this, [this](QProcess::ProcessState state) {
0073         if (state == QProcess::NotRunning && d_ptr->addUtmp) {
0074             d_ptr->pty->logout();
0075         }
0076     });
0077 }
0078 
0079 KPtyProcess::~KPtyProcess()
0080 {
0081     Q_D(KPtyProcess);
0082 
0083     if (state() != QProcess::NotRunning && d->addUtmp) {
0084         d->pty->logout();
0085         disconnect(this, &QProcess::stateChanged, this, nullptr);
0086     }
0087 }
0088 
0089 void KPtyProcess::setPtyChannels(PtyChannels channels)
0090 {
0091     Q_D(KPtyProcess);
0092 
0093     d->ptyChannels = channels;
0094 }
0095 
0096 KPtyProcess::PtyChannels KPtyProcess::ptyChannels() const
0097 {
0098     Q_D(const KPtyProcess);
0099 
0100     return d->ptyChannels;
0101 }
0102 
0103 void KPtyProcess::setUseUtmp(bool value)
0104 {
0105     Q_D(KPtyProcess);
0106 
0107     d->addUtmp = value;
0108 }
0109 
0110 bool KPtyProcess::isUseUtmp() const
0111 {
0112     Q_D(const KPtyProcess);
0113 
0114     return d->addUtmp;
0115 }
0116 
0117 KPtyDevice *KPtyProcess::pty() const
0118 {
0119     Q_D(const KPtyProcess);
0120 
0121     return d->pty.get();
0122 }
0123 
0124 #include "moc_kptyprocess.cpp"