File indexing completed on 2024-03-24 05:01:00
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2000 Alexander Neundorf <neundorf@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 #include "kshellcmdexecutor.h" 0007 0008 #include <sys/time.h> 0009 #include <sys/types.h> 0010 #include <unistd.h> 0011 #include <signal.h> 0012 #include <stdlib.h> 0013 0014 #include <QSocketNotifier> 0015 #include <QInputDialog> 0016 #include <QFontDatabase> 0017 0018 #include <KDESu/PtyProcess> 0019 #include <KLocalizedString> 0020 0021 0022 KShellCommandExecutor::KShellCommandExecutor(const QString &command, QWidget *parent) 0023 : QTextEdit(parent) 0024 , m_shellProcess(nullptr) 0025 , m_command(command) 0026 , m_readNotifier(nullptr) 0027 , m_writeNotifier(nullptr) 0028 { 0029 setAcceptRichText(false); 0030 setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); 0031 setReadOnly(true); 0032 } 0033 0034 KShellCommandExecutor::~KShellCommandExecutor() 0035 { 0036 if (m_shellProcess != nullptr) { 0037 ::kill(m_shellProcess->pid() + 1, SIGTERM); 0038 delete m_shellProcess; 0039 }; 0040 } 0041 0042 int KShellCommandExecutor::exec() 0043 { 0044 //qCDebug(KONQUEROR_LOG)<<"---------- KShellCommandExecutor::exec()"; 0045 setText(QLatin1String("")); 0046 if (m_shellProcess != nullptr) { 0047 ::kill(m_shellProcess->pid(), SIGTERM); 0048 delete m_shellProcess; 0049 }; 0050 delete m_readNotifier; 0051 delete m_writeNotifier; 0052 0053 m_shellProcess = new KDESu::PtyProcess(); 0054 m_shellProcess->setTerminal(true); 0055 0056 QList<QByteArray> args; 0057 args += "-c"; 0058 args += m_command.toLocal8Bit(); 0059 //qCDebug(KONQUEROR_LOG)<<"------- executing: "<<m_command.toLocal8Bit(); 0060 0061 QByteArray shell(getenv("SHELL")); 0062 if (shell.isEmpty()) { 0063 shell = "sh"; 0064 } 0065 0066 int ret = m_shellProcess->exec(shell, args); 0067 if (ret < 0) { 0068 //qCDebug(KONQUEROR_LOG)<<"could not execute"; 0069 delete m_shellProcess; 0070 m_shellProcess = nullptr; 0071 return 0; 0072 } 0073 0074 m_readNotifier = new QSocketNotifier(m_shellProcess->fd(), QSocketNotifier::Read, this); 0075 m_writeNotifier = new QSocketNotifier(m_shellProcess->fd(), QSocketNotifier::Write, this); 0076 m_writeNotifier->setEnabled(false); 0077 connect(m_readNotifier, &QSocketNotifier::activated, this, &KShellCommandExecutor::readDataFromShell); 0078 connect(m_writeNotifier, &QSocketNotifier::activated, this, &KShellCommandExecutor::writeDataToShell); 0079 0080 return 1; 0081 } 0082 0083 void KShellCommandExecutor::readDataFromShell() 0084 { 0085 //qCDebug(KONQUEROR_LOG)<<"--------- reading ------------"; 0086 char buffer[16 * 1024]; 0087 int bytesRead =::read(m_shellProcess->fd(), buffer, 16 * 1024 - 1); 0088 //0-terminate the buffer 0089 //process exited 0090 if (bytesRead <= 0) { 0091 slotFinished(); 0092 } else if (bytesRead > 0) { 0093 //qCDebug(KONQUEROR_LOG)<<"***********************\n"<<buffer<<"###################\n"; 0094 buffer[bytesRead] = '\0'; 0095 this->append(QString::fromLocal8Bit(buffer)); 0096 setAcceptRichText(false); 0097 }; 0098 } 0099 0100 void KShellCommandExecutor::writeDataToShell() 0101 { 0102 //qCDebug(KONQUEROR_LOG)<<"--------- writing ------------"; 0103 bool ok; 0104 QString str = QInputDialog::getText(this, 0105 QString(), 0106 i18n("Input Required:"), 0107 QLineEdit::Normal, 0108 QString(), 0109 &ok); 0110 if (ok) { 0111 QByteArray input = str.toLocal8Bit(); 0112 ::write(m_shellProcess->fd(), input.constData(), input.length()); 0113 ::write(m_shellProcess->fd(), "\n", 1); 0114 } else { 0115 slotFinished(); 0116 } 0117 0118 if (m_writeNotifier) { 0119 m_writeNotifier->setEnabled(false); 0120 } 0121 } 0122 0123 void KShellCommandExecutor::slotFinished() 0124 { 0125 setAcceptRichText(false); 0126 if (m_shellProcess != nullptr) { 0127 delete m_readNotifier; 0128 m_readNotifier = nullptr; 0129 delete m_writeNotifier; 0130 m_writeNotifier = nullptr; 0131 0132 //qCDebug(KONQUEROR_LOG)<<"slotFinished: pid: "<<m_shellProcess->pid(); 0133 ::kill(m_shellProcess->pid() + 1, SIGTERM); 0134 ::kill(m_shellProcess->pid(), SIGTERM); 0135 }; 0136 delete m_shellProcess; 0137 m_shellProcess = nullptr; 0138 emit finished(); 0139 } 0140