1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 2007 Oswald Buddenhagen <ossi@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #include "kptyprocess.h" |
9 | |
10 | #include <kptydevice.h> |
11 | #include <kuser.h> |
12 | |
13 | #include <stdlib.h> |
14 | #include <unistd.h> |
15 | |
16 | ////////////////// |
17 | // private data // |
18 | ////////////////// |
19 | |
20 | class KPtyProcessPrivate |
21 | { |
22 | public: |
23 | KPtyProcessPrivate() |
24 | { |
25 | } |
26 | |
27 | std::unique_ptr<KPtyDevice> pty; |
28 | KPtyProcess::PtyChannels ptyChannels = KPtyProcess::NoChannels; |
29 | bool addUtmp = false; |
30 | }; |
31 | |
32 | KPtyProcess::KPtyProcess(QObject *parent) |
33 | : KPtyProcess(-1, parent) |
34 | { |
35 | } |
36 | |
37 | KPtyProcess::KPtyProcess(int ptyMasterFd, QObject *parent) |
38 | : KProcess(parent) |
39 | , d_ptr(new KPtyProcessPrivate) |
40 | { |
41 | Q_D(KPtyProcess); |
42 | |
43 | auto parentChildProcModifier = KProcess::childProcessModifier(); |
44 | setChildProcessModifier([d, parentChildProcModifier]() { |
45 | d->pty->setCTty(); |
46 | if (d->addUtmp) { |
47 | d->pty->login(user: KUser(KUser::UseRealUserID).loginName().toLocal8Bit().constData(), remotehost: qgetenv(varName: "DISPLAY" ).constData()); |
48 | } |
49 | if (d->ptyChannels & StdinChannel) { |
50 | dup2(fd: d->pty->slaveFd(), fd2: 0); |
51 | } |
52 | if (d->ptyChannels & StdoutChannel) { |
53 | dup2(fd: d->pty->slaveFd(), fd2: 1); |
54 | } |
55 | if (d->ptyChannels & StderrChannel) { |
56 | dup2(fd: d->pty->slaveFd(), fd2: 2); |
57 | } |
58 | |
59 | if (parentChildProcModifier) { |
60 | parentChildProcModifier(); |
61 | } |
62 | }); |
63 | |
64 | d->pty = std::make_unique<KPtyDevice>(args: this); |
65 | |
66 | if (ptyMasterFd == -1) { |
67 | d->pty->open(); |
68 | } else { |
69 | d->pty->open(fd: ptyMasterFd); |
70 | } |
71 | |
72 | connect(sender: this, signal: &QProcess::stateChanged, context: this, slot: [this](QProcess::ProcessState state) { |
73 | if (state == QProcess::NotRunning && d_ptr->addUtmp) { |
74 | d_ptr->pty->logout(); |
75 | } |
76 | }); |
77 | } |
78 | |
79 | KPtyProcess::~KPtyProcess() |
80 | { |
81 | Q_D(KPtyProcess); |
82 | |
83 | if (state() != QProcess::NotRunning && d->addUtmp) { |
84 | d->pty->logout(); |
85 | disconnect(sender: this, signal: &QProcess::stateChanged, receiver: this, zero: nullptr); |
86 | } |
87 | } |
88 | |
89 | void KPtyProcess::setPtyChannels(PtyChannels channels) |
90 | { |
91 | Q_D(KPtyProcess); |
92 | |
93 | d->ptyChannels = channels; |
94 | } |
95 | |
96 | KPtyProcess::PtyChannels KPtyProcess::ptyChannels() const |
97 | { |
98 | Q_D(const KPtyProcess); |
99 | |
100 | return d->ptyChannels; |
101 | } |
102 | |
103 | void KPtyProcess::setUseUtmp(bool value) |
104 | { |
105 | Q_D(KPtyProcess); |
106 | |
107 | d->addUtmp = value; |
108 | } |
109 | |
110 | bool KPtyProcess::isUseUtmp() const |
111 | { |
112 | Q_D(const KPtyProcess); |
113 | |
114 | return d->addUtmp; |
115 | } |
116 | |
117 | KPtyDevice *KPtyProcess::pty() const |
118 | { |
119 | Q_D(const KPtyProcess); |
120 | |
121 | return d->pty.get(); |
122 | } |
123 | |
124 | #include "moc_kptyprocess.cpp" |
125 | |