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"