00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <QString>
00029 #include <vidalia.h>
00030 #include <util/string.h>
00031
00032
00033 #if defined (Q_OS_WIN32)
00034 #include <windows.h>
00035 #endif
00036
00037 #include "torprocess.h"
00038
00039
00040
00041 TorProcess::TorProcess()
00042 {
00043 openStdout();
00044 connect(this, SIGNAL(readyReadStandardOutput()),
00045 this, SLOT(onReadyRead()));
00046 connect(this, SIGNAL(error(QProcess::ProcessError)),
00047 this, SLOT(onError(QProcess::ProcessError)));
00048 }
00049
00050
00051 QString
00052 TorProcess::formatArguments(const QStringList args)
00053 {
00054 QStringList out;
00055 foreach (QString arg, args) {
00056 out << (arg.contains(" ") || arg.isEmpty() ? string_escape(arg) : arg);
00057 }
00058 return out.join(" ");
00059 }
00060
00061
00062
00063
00064
00065 void
00066 TorProcess::start(QString app, QStringList args)
00067 {
00068 #if defined(Q_OS_WIN32)
00069
00070
00071 app = "\"" + app + "\"";
00072 #endif
00073
00074
00075 QStringList env = QProcess::systemEnvironment();
00076 #if !defined(Q_OS_WIN32)
00077
00078
00079
00080 for (int i = 0; i < env.size(); i++) {
00081 QString envVar = env.at(i);
00082 if (envVar.startsWith("PATH="))
00083 env.replace(i, envVar += ":/usr/sbin");
00084 }
00085 #endif
00086 setEnvironment(env);
00087
00088 vNotice("Starting Tor using '%1 %2'").arg(app).arg(formatArguments(args));
00089 QProcess::start(app, args, QIODevice::ReadOnly | QIODevice::Text);
00090 }
00091
00092
00093 bool
00094 TorProcess::stop(QString *errmsg)
00095 {
00096
00097
00098 if (state() == QProcess::NotRunning) {
00099 return true;
00100 }
00101
00102 vNotice("Stopping the Tor process.");
00103
00104 #if defined(Q_OS_WIN32)
00105
00106
00107 kill();
00108 #else
00109 terminate();
00110
00111
00112 if (!waitForFinished(5000)) {
00113 vWarn("Tor failed to stop: %1").arg(errorString());
00114 if (errmsg) {
00115 *errmsg =
00116 tr("Process %1 failed to stop. [%2]").arg(pid()).arg(errorString());
00117 }
00118 return false;
00119 }
00120 #endif
00121 return true;
00122 }
00123
00124
00125 quint64
00126 TorProcess::pid()
00127 {
00128 #if defined(Q_OS_WIN32)
00129 return (quint64)((QProcess::pid())->dwProcessId);
00130 #else
00131 return QProcess::pid();
00132 #endif
00133 }
00134
00135
00136
00137 void
00138 TorProcess::openStdout()
00139 {
00140 setReadChannelMode(QProcess::MergedChannels);
00141 setReadChannel(QProcess::StandardOutput);
00142 }
00143
00144
00145
00146 void
00147 TorProcess::closeStdout()
00148 {
00149
00150 closeReadChannel(QProcess::StandardOutput);
00151
00152 onReadyRead();
00153 }
00154
00155
00156 void
00157 TorProcess::onReadyRead()
00158 {
00159 int i, j;
00160 QString line;
00161
00162 while (canReadLine()) {
00163 line = readLine();
00164 if (!line.isEmpty()) {
00165
00166 i = line.indexOf("[");
00167 j = line.indexOf("]");
00168 if (i > 0 && j > i && line.length() >= j+2) {
00169 emit log(line.mid(i+1, j-i-1), line.mid(j+2));
00170 }
00171 }
00172 }
00173 }
00174
00175
00176
00177
00178 void
00179 TorProcess::onError(QProcess::ProcessError error)
00180 {
00181 if (error == QProcess::FailedToStart) {
00182 vWarn("The Tor process failed to start: %1").arg(errorString());
00183
00184 emit startFailed(errorString());
00185 } else {
00186 vWarn("Tor process error: %1").arg(errorString());
00187 }
00188 }
00189