• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

kalarm/lib

  • sources
  • kde-4.12
  • kdepim
  • kalarm
  • lib
shellprocess.cpp
Go to the documentation of this file.
1 /*
2  * shellprocess.cpp - execute a shell process
3  * Program: kalarm
4  * Copyright © 2004,2005,2007,2008 by David Jarvie <djarvie@kde.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 #include <stdlib.h>
22 #include <qglobal.h>
23 #include <kde_file.h>
24 #include <kapplication.h>
25 #include <klocale.h>
26 #include <kdebug.h>
27 #include <kauthorized.h>
28 
29 #include "shellprocess.moc"
30 
31 
32 QByteArray ShellProcess::mShellName;
33 QByteArray ShellProcess::mShellPath;
34 bool ShellProcess::mInitialised = false;
35 bool ShellProcess::mAuthorised = false;
36 
37 
38 ShellProcess::ShellProcess(const QString& command)
39  : mCommand(command),
40  mStdinBytes(0),
41  mStatus(INACTIVE),
42  mStdinExit(false)
43 {
44 }
45 
46 /******************************************************************************
47 * Execute a command.
48 */
49 bool ShellProcess::start(OpenMode openMode)
50 {
51  if (!authorised())
52  {
53  mStatus = UNAUTHORISED;
54  return false;
55  }
56  connect(this, SIGNAL(bytesWritten(qint64)), SLOT(writtenStdin(qint64)));
57  connect(this, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(slotExited(int,QProcess::ExitStatus)));
58  connect(this, SIGNAL(readyReadStandardOutput()), SLOT(stdoutReady()));
59  connect(this, SIGNAL(readyReadStandardError()), SLOT(stderrReady()));
60  QStringList args;
61  args << QLatin1String("-c") << mCommand;
62  QProcess::start(QLatin1String(shellName()), args, openMode);
63  if (!waitForStarted())
64  {
65  mStatus = START_FAIL;
66  return false;
67  }
68  mStatus = RUNNING;
69  return true;
70 }
71 
72 /******************************************************************************
73 * Called when a shell process execution completes.
74 * Interprets the exit status according to which shell was called, and emits
75 * a shellExited() signal.
76 */
77 void ShellProcess::slotExited(int exitCode, QProcess::ExitStatus exitStatus)
78 {
79  kDebug() << exitCode << "," << exitStatus;
80  mStdinQueue.clear();
81  mStatus = SUCCESS;
82  mExitCode = exitCode;
83  if (exitStatus != NormalExit)
84  {
85  kWarning(5950) << mCommand << ":" << mShellName << ": crashed/killed";
86  mStatus = DIED;
87  }
88  else
89  {
90  // Some shells report if the command couldn't be found, or is not executable
91  if ((mShellName == "bash" && (exitCode == 126 || exitCode == 127))
92  || (mShellName == "ksh" && exitCode == 127))
93  {
94  kWarning(5950) << mCommand << ":" << mShellName << ": not found or not executable";
95  mStatus = NOT_FOUND;
96  }
97  }
98  emit shellExited(this);
99 }
100 
101 /******************************************************************************
102 * Write a string to STDIN.
103 */
104 void ShellProcess::writeStdin(const char* buffer, int bufflen)
105 {
106  QByteArray scopy(buffer, bufflen); // construct a deep copy
107  bool doWrite = mStdinQueue.isEmpty();
108  mStdinQueue.enqueue(scopy);
109  if (doWrite)
110  {
111  mStdinBytes = mStdinQueue.head().length();
112  write(mStdinQueue.head());
113  }
114 }
115 
116 /******************************************************************************
117 * Called when output to STDIN completes.
118 * Send the next queued output, if any.
119 * Note that buffers written to STDIN must not be freed until the bytesWritten()
120 * signal has been processed.
121 */
122 void ShellProcess::writtenStdin(qint64 bytes)
123 {
124  mStdinBytes -= bytes;
125  if (mStdinBytes > 0)
126  return; // buffer has only been partially written so far
127  if (!mStdinQueue.isEmpty())
128  mStdinQueue.dequeue(); // free the buffer which has now been written
129  if (!mStdinQueue.isEmpty())
130  {
131  mStdinBytes = mStdinQueue.head().length();
132  write(mStdinQueue.head());
133  }
134  else if (mStdinExit)
135  kill();
136 }
137 
138 /******************************************************************************
139 * Tell the process to exit once all STDIN strings have been written.
140 */
141 void ShellProcess::stdinExit()
142 {
143  if (mStdinQueue.isEmpty())
144  kill();
145  else
146  mStdinExit = true;
147 }
148 
149 /******************************************************************************
150 * Return the error message corresponding to the command exit status.
151 * Reply = null string if not yet exited, or if command successful.
152 */
153 QString ShellProcess::errorMessage() const
154 {
155  switch (mStatus)
156  {
157  case UNAUTHORISED:
158  return i18nc("@info", "Failed to execute command (shell access not authorized)");
159  case START_FAIL:
160  case NOT_FOUND:
161  return i18nc("@info", "Failed to execute command");
162  case DIED:
163  return i18nc("@info", "Command execution error");
164  case SUCCESS:
165  if (mExitCode)
166  return i18nc("@info", "Command exit code: %1", mExitCode);
167  // Fall through to INACTIVE
168  case INACTIVE:
169  case RUNNING:
170  default:
171  return QString();
172  }
173 }
174 
175 /******************************************************************************
176 * Determine which shell to use.
177 * Don't use the KProcess default shell, since we need to know which shell is
178 * used in order to decide what its exit code means.
179 */
180 const QByteArray& ShellProcess::shellPath()
181 {
182  if (mShellPath.isEmpty())
183  {
184  // Get the path to the shell
185  mShellPath = "/bin/sh";
186  QByteArray envshell = qgetenv("SHELL").trimmed();
187  if (!envshell.isEmpty())
188  {
189  KDE_struct_stat fileinfo;
190  if (KDE_stat(envshell.data(), &fileinfo) != -1 // ensure file exists
191  && !S_ISDIR(fileinfo.st_mode) // and it's not a directory
192  && !S_ISCHR(fileinfo.st_mode) // and it's not a character device
193  && !S_ISBLK(fileinfo.st_mode) // and it's not a block device
194 #ifdef S_ISSOCK
195  && !S_ISSOCK(fileinfo.st_mode) // and it's not a socket
196 #endif
197  && !S_ISFIFO(fileinfo.st_mode) // and it's not a fifo
198  && !access(envshell.data(), X_OK)) // and it's executable
199  mShellPath = envshell;
200  }
201 
202  // Get the shell filename with the path stripped off
203  int i = mShellPath.lastIndexOf('/');
204  if (i >= 0)
205  mShellName = mShellPath.mid(i + 1);
206  else
207  mShellName = mShellPath;
208  }
209  return mShellPath;
210 }
211 
212 /******************************************************************************
213 * Check whether shell commands are allowed at all.
214 */
215 bool ShellProcess::authorised()
216 {
217  if (!mInitialised)
218  {
219  mAuthorised = KAuthorized::authorizeKAction(QLatin1String("shell_access"));
220  mInitialised = true;
221  }
222  return mAuthorised;
223 }
224 
225 // vim: et sw=4:
ShellProcess::UNAUTHORISED
Definition: shellprocess.h:69
ShellProcess::exitCode
int exitCode() const
Returns the shell exit code.
Definition: shellprocess.h:85
ShellProcess::shellExited
void shellExited(ShellProcess *)
Signal emitted when the shell process execution completes.
ShellProcess::NOT_FOUND
Definition: shellprocess.h:71
ShellProcess::writeStdin
void writeStdin(const char *buffer, int bufflen)
Writes a string to the process's STDIN.
Definition: shellprocess.cpp:104
ShellProcess::SUCCESS
Definition: shellprocess.h:68
ShellProcess::RUNNING
Definition: shellprocess.h:67
ShellProcess::authorised
static bool authorised()
Returns whether the user is authorised to run shell commands.
Definition: shellprocess.cpp:215
ShellProcess::ShellProcess
ShellProcess(const QString &command)
Constructor.
Definition: shellprocess.cpp:38
ShellProcess::START_FAIL
Definition: shellprocess.h:72
ShellProcess::shellPath
static const QByteArray & shellPath()
Determines which shell to use.
Definition: shellprocess.cpp:180
ShellProcess::errorMessage
QString errorMessage() const
Returns the error message corresponding to the command exit status.
Definition: shellprocess.cpp:153
ShellProcess::stdinExit
void stdinExit()
Tell the process to exit once any outstanding STDIN strings have been written.
Definition: shellprocess.cpp:141
ShellProcess::INACTIVE
Definition: shellprocess.h:66
ShellProcess::shellName
static const QByteArray & shellName()
Determines which shell to use.
Definition: shellprocess.h:108
ShellProcess::DIED
Definition: shellprocess.h:70
ShellProcess::start
bool start(OpenMode=ReadWrite)
Executes the configured command.
Definition: shellprocess.cpp:49
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:59:20 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kalarm/lib

Skip menu "kalarm/lib"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal