Permalink
Browse files

Add command string parser to break up commands for direct execution.

This adds a parser for the UNIX version of MythSystem, to break commands
apart at white space characters, obeying quoting and escaping where
appropriate, to allow commands passed as a single string to be executed
directly by execv, rather than be passed through the Bourne shell.
Note, this does not include support for any form of piping, redirects,
or backgrounding.  This includes an ABI bump.

Refs #10860
  • Loading branch information...
wagnerrp committed May 2, 2012
1 parent 4ba7c3d commit c877947a5065846c6c4174ea36804f810c49168f
@@ -144,6 +144,9 @@ class MBASE_PUBLIC MythSystemPrivate : public QObject
virtual void Signal(int sig) = 0;
virtual void JumpAbort(void) = 0;
+ virtual bool ParseShell(const QString cmd, QString &abscmd,
+ QStringList &args) = 0;
+
protected:
MythSystem *m_parent;
@@ -12,7 +12,7 @@
/// Update this whenever the plug-in API changes.
/// Including changes in the libmythbase, libmyth, libmythtv, libmythav* and
/// libmythui class methods used by plug-ins.
-#define MYTH_BINARY_VERSION "0.26.20120417-1"
+#define MYTH_BINARY_VERSION "0.26.20120502-1"
/** \brief Increment this whenever the MythTV network protocol changes.
*
@@ -582,6 +582,131 @@ MythSystemUnix::~MythSystemUnix(void)
{
}
+bool MythSystemUnix::ParseShell(const QString cmd, QString &abscmd,
+ QStringList &args)
+{
+ QList<QChar> whitespace; whitespace << ' ' << '\t' << '\n' << '\r';
+ QList<QChar> whitechr; whitechr << 't' << 'n' << 'r';
+ QChar quote = '"',
+ hardquote = '\'',
+ escape = '\\';
+ bool quoted = false,
+ hardquoted = false,
+ escaped = false;
+
+ QString tmp;
+ QString::const_iterator i = cmd.begin();
+ while (i != cmd.end())
+ {
+ if (quoted || hardquoted)
+ {
+ if (escaped)
+ {
+ if ((quote == *i) || (escape == *i) ||
+ whitespace.contains(*i))
+ // pass through escape (\), quote ("), and any whitespace
+ tmp += *i;
+ else if (whitechr.contains(*i))
+ // process whitespace escape code, and pass character
+ tmp += whitespace[whitechr.indexOf(*i)+1];
+ else
+ // unhandled escape code, abort
+ return false;
+
+ escaped = false;
+ }
+
+ else if (*i == escape)
+ {
+ if (hardquoted)
+ // hard quotes (') pass everything
+ tmp += *i;
+ else
+ // otherwise, mark escaped to handle next character
+ escaped = true;
+ }
+
+ else if ((quoted & (*i == quote)) ||
+ (hardquoted && (*i == hardquote)))
+ // end of quoted sequence
+ quoted = hardquoted = false;
+
+ else
+ // pass through character
+ tmp += *i;
+ }
+
+ else if (escaped)
+ {
+ if ((*i == quote) || (*i == hardquote) || (*i == escape) ||
+ whitespace.contains(*i))
+ // pass through special characters
+ tmp += *i;
+ else if (whitechr.contains(*i))
+ // process whitespace escape code, and pass character
+ tmp += whitespace[whitechr.indexOf(*i)+1];
+ else
+ // unhandled escape code, abort
+ return false;
+
+ escaped = false;
+ }
+
+ // handle quotes and escape characters
+ else if (quote == *i)
+ quoted = true;
+ else if (hardquote == *i)
+ hardquoted = true;
+ else if (escape == *i)
+ escaped = true;
+
+ // handle whitespace characters
+ else if (whitespace.contains(*i) && !tmp.isEmpty())
+ {
+ args << tmp;
+ tmp.clear();
+ }
+
+ else
+ // pass everything else
+ tmp += *i;
+
+ // step forward to next character
+ ++i;
+ }
+
+ if (quoted || hardquoted || escaped)
+ // command not terminated cleanly
+ return false;
+
+ if (!tmp.isEmpty())
+ // collect last argument
+ args << tmp;
+
+ if (args.isEmpty())
+ // this shouldnt happen
+ return false;
+
+ // grab the first argument to use as the command
+ abscmd = args.takeFirst();
+ if (!abscmd.startsWith('/'))
+ {
+ // search for absolute path
+ QStringList path = QString(getenv("PATH")).split(':');
+ QStringList::const_iterator i = path.begin();
+ for (; i != path.end(); ++i)
+ {
+ QFile file(QString("%1/%2").arg(*i).arg(abscmd));
+ if (file.exists())
+ {
+ abscmd = file.fileName();
+ break;
+ }
+ }
+ }
+
+ return true;
+}
void MythSystemUnix::Term(bool force)
{
@@ -5,6 +5,8 @@
#include <signal.h>
#include <QObject>
+#include <QString>
+#include <QStringList>
#include <QMap>
#include <QList>
#include <QBuffer>
@@ -89,6 +91,9 @@ class MBASE_PUBLIC MythSystemUnix : public MythSystemPrivate
virtual void Signal(int sig);
virtual void JumpAbort(void);
+ virtual bool ParseShell(const QString cmd, QString &abscmd,
+ QStringList &args);
+
friend class MythSystemManager;
friend class MythSystemSignalManager;
friend class MythSystemIOHandler;
@@ -532,6 +532,12 @@ MythSystemWindows::~MythSystemWindows(void)
{
}
+bool MythSystemWindows::ParseShell(const QString cmd, QString &abscmd,
+ QStringList &args)
+{
+ return false;
+}
+
void MythSystemWindows::Term(bool force)
{
if( (GetStatus() != GENERIC_EXIT_RUNNING) || (!m_child) )
@@ -90,6 +90,9 @@ class MBASE_PUBLIC MythSystemWindows : public MythSystemPrivate
virtual void Signal(int sig);
virtual void JumpAbort(void);
+ virtual bool ParseShell(const QString cmd, QString &abscmd,
+ QStringList &args);
+
friend class MythSystemManager;
friend class MythSystemSignalManager;
friend class MythSystemIOHandler;

0 comments on commit c877947

Please sign in to comment.