fix tricky regression noticed by Vyacheslav Tokarev on Google Reader.
[kdelibs.git] / kinit / kwrapper_win.cpp
blob6065749ce0322d8a0a0bcfa4f512a16b6d0010ae
1 /*
2 This file is part of the KDE libraries
3 Copyright (c) 2007 Ralf Habacker <ralf.habacker@freenet.de>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
21 kde application starter
22 - allows starting kde application without any additional path settings [1]
23 - supports multiple root installation which is often used by packagers
24 (adds bin/lib directories from KDEDIRS environment to PATH environment)
25 - designed to start kde application from windows start menu entries
26 - support for reading KDEDIRS setting from flat file
27 (located in <path-of-kwrapper.exe>/../../kdedirs.cache)
28 - planned: automatic KDEDIRS detection support
30 [1] recent kde cmake buildsystem on win32 installs shared libraries
31 into lib instead of bin. This requires to have the lib directory
32 in the PATH environment variable too (required for all pathes in KDEDIRS)
34 TODO: There is an prelimary concept of setting KDEDIRS environment variable
35 from a cache file located on a well known path relative from the requested
36 application.
37 The recent implementation expects a file name 'kdedirs.cache' two level
38 above this executable which will be <ProgramFiles> in case kwrapper4 lives
39 in <Programfiles>/kde4/bin.
40 This works not in any case especially when running application inside the
41 build directory.
45 #include <stdio.h>
46 #include <assert.h>
47 #include <stdlib.h>
48 #include <process.h>
49 #include <windows.h>
51 #include <QString>
52 #include <QProcess>
53 #include <QtDebug>
54 #include <QFileInfo>
55 #include <QCoreApplication>
56 #include <QList>
58 bool verbose = 0;
60 int main(int argc, char **argv)
62 QCoreApplication app(argc,argv);
64 QStringList envPath; /// pathes for using in environment of started process
65 QStringList searchPath; /// pathes for using to find executable
66 QString exeToStart;
67 QString myAppName = "kwrapper4:";
68 QStringList exeParams;
69 int firstParam = 1;
71 if (QCoreApplication::arguments().size() == 1)
73 qDebug() << myAppName << "no application given";
74 return 1;
77 if (QCoreApplication::arguments().at(1) == "--verbose")
79 verbose = 1;
80 firstParam = 2;
83 exeToStart = QCoreApplication::arguments().at(firstParam);
85 for(int i=firstParam+1; i < QCoreApplication::arguments().size(); i++)
86 exeParams << QCoreApplication::arguments().at(i);
88 QString path = QString::fromLocal8Bit(qgetenv("PATH")).toLower().replace('\\','/');
90 /** add pathes from PATH environment
91 - all to client path environment
92 - pathes not ending with lib to application search path
94 foreach(const QString &a, path.split(';'))
96 if (!envPath.contains(a))
97 envPath << a;
98 if (!a.endsWith("/lib") && !a.endsWith("/lib/") && !searchPath.contains(a))
99 searchPath << a;
102 // add current install path
103 path = QCoreApplication::applicationDirPath().toLower().replace('\\','/');
104 if (!envPath.contains(path))
105 envPath << path;
107 // detect directory where kdedirs.cache lives
108 // this is not complete, KDEDIRS path should be used as base too
109 QFileInfo fi(path + "/../..");
110 QString rootPath = fi.canonicalPath();
112 if (verbose)
113 qDebug() << "try to find kdedirs.cache in" << rootPath;
115 // add current lib path to client path environment
116 path = path.replace("bin","lib");
117 if (!envPath.contains(path))
118 envPath << path;
121 add bin and lib pathes from KDEDIRS
122 - bin/lib to client path environment
123 - bin to application search path
125 path = QString::fromLocal8Bit(qgetenv("KDEDIRS")).toLower().replace('\\','/');
126 QStringList kdedirs;
128 if (path.size() > 0)
129 kdedirs = path.split(';');
131 bool changedKDEDIRS = 0;
132 // setup kdedirs if not present
133 if (kdedirs.size() == 0)
135 QStringList kdedirsCacheList;
136 #ifdef Q_CC_MSVC
137 kdedirsCacheList << rootPath + "/kdedirs.cache.msvc";
138 #endif
139 kdedirsCacheList << rootPath + "/kdedirs.cache";
141 bool found = false;
142 foreach(const QString &kdedirsCachePath,kdedirsCacheList)
144 QFile f(kdedirsCachePath);
145 if (f.exists())
147 f.open(QIODevice::ReadOnly);
148 QByteArray data = f.readAll();
149 f.close();
150 kdedirs = QString(data).split(';');
151 if (verbose)
152 qDebug() << "load kdedirs cache from " << kdedirsCachePath << "values=" << kdedirs;
153 found = true;
154 break;
157 if (!found)
160 f.open(QIODevice::WriteOnly);
161 // search all pathes one level above for a directory share/apps
162 // write entries into a cache
163 f.write(kdedirs.join(";").toAscii());
164 f.close();
167 changedKDEDIRS = 1;
169 if (verbose)
170 qDebug() << "found KDEDIRS\n\t" << kdedirs.join("\n\t");
172 foreach(const QString &a, kdedirs)
174 if (!envPath.contains(a+"/bin"))
175 envPath << a + "/bin";
176 if (!envPath.contains(a+"/lib"))
177 envPath << a + "/lib";
178 if (!searchPath.contains(a+"/bin"))
179 searchPath << a + "/bin";
182 // find executable
183 WCHAR _appName[MAX_PATH+1];
185 if (verbose)
186 qDebug() << "search " << exeToStart << "in";
188 bool found = false;
189 foreach(const QString &a, searchPath)
191 if (verbose)
192 qDebug() << "\t" << a;
193 if (SearchPathW((LPCWSTR)a.utf16(),(LPCWSTR)exeToStart.utf16(),
194 L".exe",MAX_PATH+1,(LPWSTR)_appName,NULL))
196 found = true;
197 break;
200 QString appName = QString::fromUtf16((unsigned short*)_appName);
202 if (!found)
204 qWarning() << myAppName << "application not found";
205 return 3;
208 if (verbose)
209 qDebug() << "run" << exeToStart << "with params" << exeParams << "and PATH environment\n\t" << envPath.join("\n\t");
211 // setup client process envirionment
212 QStringList env = QProcess::systemEnvironment();
213 env.replaceInStrings(QRegExp("^PATH=(.*)", Qt::CaseInsensitive), QLatin1String("PATH=") + envPath.join(";"));
214 if (changedKDEDIRS)
215 env << QLatin1String("KDEDIRS=") + kdedirs.join(";");
217 QProcess *process = new QProcess;
218 process->setEnvironment(env);
219 process->start(appName,exeParams);
220 if (process->state() == QProcess::NotRunning)
222 qWarning() << myAppName << "process not running";
223 return 4;
225 process->waitForStarted();
227 return 0;