standardserverconsole.cpp
1 //------------------------------------------------------------------------------
2 // standardserverconsole.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301, USA.
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2009 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "standardserverconsole.h"
24 
25 #include <QMessageBox>
26 
27 #ifndef Q_OS_WIN32
28 #include <QTextStream>
29 #include <signal.h>
30 #endif
31 
32 StandardServerConsole::StandardServerConsole(const QIcon &icon, const QString &program, const QStringList &arguments)
33 {
34  // Have the console delete itself
35  setAttribute(Qt::WA_DeleteOnClose);
36 
37  // Set up the window.
38  setWindowTitle("Server Console");
39  setWindowIcon(icon);
40  resize(640, 400);
41 
42  // Add our console widget
43  console = new ServerConsole();
44  setCentralWidget(console);
45 
46  // Start the process
47  process = new QProcess();
48  process->start(program, arguments);
49  if(process->waitForStarted())
50  {
51  show();
52  connect(console, SIGNAL(messageSent(const QString &)), this, SLOT(writeToStandardInput(const QString &)));
53  connect(process, SIGNAL(readyReadStandardError()), this, SLOT(errorDataReady()));
54  connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(outputDataReady()));
55  connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finish(int, QProcess::ExitStatus)));
56  }
57  else // Didn't start get rid of this console.
58  close();
59 }
60 
61 StandardServerConsole::~StandardServerConsole()
62 {
63 #ifndef Q_OS_WIN32
64  if(process->pid() != 0)
65  {
66  // On non-Windows systems try to find child processes and kill them.
67  // Unfrotunately it doesn't look like Qt can help us here (which kind of
68  // makes sense considering it seems like there no real API to do it).
69  // Ideally only one process started and we don't have to do this.
70  QProcess *ps = new QProcess();
71  ps->start(QString("ps h --ppid %1 -o pid").arg(process->pid()));
72  ps->waitForFinished();
73  QByteArray psOutput = ps->readAllStandardOutput();
74  QTextStream stream(&psOutput);
75  stream.skipWhiteSpace();
76  while(!stream.atEnd())
77  {
78  unsigned int cpid;
79  stream >> cpid;
80  stream.skipWhiteSpace();
81  kill(cpid, SIGTERM);
82  }
83  delete ps;
84  }
85 #endif
86 
87  process->close();
88  process->waitForFinished();
89  delete process;
90 }
91 
92 void StandardServerConsole::errorDataReady()
93 {
94  console->appendMessage(QString(process->readAllStandardError()));
95 }
96 
97 void StandardServerConsole::finish(int exitCode, QProcess::ExitStatus exitStatus)
98 {
99  if(exitStatus == QProcess::CrashExit && exitCode != 0)
100  QMessageBox::critical(this, "Server crash", QString("The server terminated unexpectedly with exit code: %1").arg(exitCode));
101 
102  close();
103 }
104 
105 void StandardServerConsole::outputDataReady()
106 {
107  console->appendMessage(QString(process->readAllStandardOutput()));
108 }
109 
110 void StandardServerConsole::writeToStandardInput(const QString &message)
111 {
112  process->write((message+"\n").toAscii());
113 }