Vidalia 0.3.1
procutil.cpp
Go to the documentation of this file.
1/*
2** This file is part of Vidalia, and is subject to the license terms in the
3** LICENSE file, found in the top level directory of this distribution. If you
4** did not receive the LICENSE file with this file, you may obtain it from the
5** Vidalia source package distributed by the Vidalia Project at
6** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7** including this file, may be copied, modified, propagated, or distributed
8** except according to the terms described in the LICENSE file.
9*/
10
11/*
12** \file procutil.cpp
13** \brief Process information and pidfile functions
14*/
15
16#include "procutil.h"
17#include "stringutil.h"
18
19#include <QDir>
20#include <QFile>
21#include <QFileInfo>
22#include <QTextStream>
23#include <QApplication>
24#include <QProcess>
25
26#if !defined(Q_OS_WIN)
27#include <signal.h>
28#endif
29
30
31/** Returns the PID of the current process. */
32qint64
34{
35#if defined(Q_OS_WIN)
36 return (qint64)GetCurrentProcessId();
37#else
38 return (qint64)getpid();
39#endif
40}
41
42/** Returns true if a process with the given PID is running. */
43bool
45{
46#if defined(Q_OS_WIN)
47 QHash<qint64, QString> procList = win32_process_list();
48 if (procList.contains(pid)) {
49 /* A process with this ID exists. Check if it's the same as this process. */
50 QString exeFile = procList.value(pid);
51 QString thisExe = QFileInfo(QApplication::applicationFilePath()).fileName();
52 return (exeFile.toLower() == thisExe.toLower());
53 }
54 return false;
55#else
56 /* Send the "null" signal to check if a process exists */
57 if (kill((pid_t)pid, 0) < 0) {
58 return (errno != ESRCH);
59 }
60 return true;
61#endif
62}
63
64/** Writes the given file to disk containing the current process's PID. */
65bool
66write_pidfile(const QString &pidFileName, QString *errmsg)
67{
68 /* Make sure the directory exists */
69 QDir pidFileDir = QFileInfo(pidFileName).absoluteDir();
70 if (!pidFileDir.exists()) {
71 pidFileDir.mkpath(QDir::convertSeparators(pidFileDir.absolutePath()));
72 }
73
74 /* Try to open (and create if it doesn't exist) the pidfile */
75 QFile pidfile(pidFileName);
76 if (!pidfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
77 return err(errmsg, pidfile.errorString());
78 }
79
80 /* Write our current PID to it */
81 QTextStream pidstream(&pidfile);
82 pidstream << get_pid();
83 return true;
84}
85
86/** Reads the given pidfile and returns the value contained in it. If the file
87 * does not exist 0 is returned. Returns -1 if an error occurs. */
88qint64
89read_pidfile(const QString &pidFileName, QString *errmsg)
90{
91 qint64 pid;
92
93 /* Open the pidfile, if it exists */
94 QFile pidfile(pidFileName);
95 if (!pidfile.exists()) {
96 return 0;
97 }
98 if (!pidfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
99 if (errmsg) {
100 *errmsg = pidfile.errorString();
101 }
102 return -1;
103 }
104
105 /* Read the PID in from the file */
106 QTextStream pidstream(&pidfile);
107 pidstream >> pid;
108 return pid;
109}
110
111QHash<qint64, QString>
112process_list(quint16 port)
113{
114 return universal_process_list(port);
115}
116
117bool
118process_kill(qint64 pid)
119{
120#if defined(Q_OS_WIN32)
121 HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE,
122 static_cast<DWORD>(pid));
123 if (hProcess == NULL)
124 return false;
125
126 BOOL ret = TerminateProcess(hProcess, 0);
127 CloseHandle(hProcess);
128
129 return (ret != FALSE);
130#else
131 if(!kill(pid, 15))
132 return true;
133 return false;
134#endif
135}
136
137QHash<qint64, QString>
139{
140 QHash<qint64, QString> pl;
141
142 QProcess ps;
143 QStringList args;
144#if defined(Q_OS_LINUX)
145 args << "-npl";
146#else
147 args << "-no";
148#endif
149
150 ps.start("netstat", args, QIODevice::ReadOnly);
151 while(!ps.waitForFinished());
152
153 QString flt = QString("127.0.0.1:%1").arg(port);
154 QStringList lines = QString(ps.readAllStandardOutput()).split("\n");
155 QStringList filtered = lines.filter(flt);
156
157#if defined(Q_OS_WIN)
158 filtered = filtered.filter("LISTENING");
159#endif
160
161 if(filtered.length() == 0)
162 return QHash<qint64, QString>();
163
164 qint64 pid = 0;
165 QString proc = "";
166#if defined(Q_OS_LINUX)
167 foreach(QString line, lines) {
168 QStringList items = line.trimmed().split(" ");
169 if(items.length() < 1)
170 continue;
171 items = items.last().trimmed().split("/");
172 if(items.length() < 2)
173 continue;
174
175 pid = items[0].toLong();
176 proc = items[1];
177
178 pl.insert(pid, proc);
179 }
180#else
181 pid = filtered[0].split(" ").last().trimmed().toLong();
182 proc = "tor";
183 pl.insert(pid, proc);
184#endif
185
186 return pl;
187}
QHash< qint64, QString > process_list(quint16 port)
Definition: procutil.cpp:112
qint64 read_pidfile(const QString &pidFileName, QString *errmsg)
Definition: procutil.cpp:89
bool write_pidfile(const QString &pidFileName, QString *errmsg)
Definition: procutil.cpp:66
QHash< qint64, QString > universal_process_list(quint16 port)
Definition: procutil.cpp:138
qint64 get_pid()
Definition: procutil.cpp:33
bool process_kill(qint64 pid)
Definition: procutil.cpp:118
bool is_process_running(qint64 pid)
Definition: procutil.cpp:44
bool err(QString *str, const QString &errmsg)
Definition: stringutil.cpp:37
QHash< qint64, QString > win32_process_list()
Definition: win32.cpp:228