1/* This file is part of the KDE libraries
2 * Copyright (C) 2001 Waldo Bastian <bastian@kde.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License version 2 as published by the Free Software Foundation;
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Library General Public License for more details.
12 *
13 * You should have received a copy of the GNU Library General Public License
14 * along with this library; see the file COPYING.LIB. If not, write to
15 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301, USA.
17 **/
18
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <unistd.h>
22#include <stdlib.h>
23#include <stdio.h>
24
25#include <QtCore/QFile>
26#include <QtCore/QRegExp>
27#include <QtCore/Q_PID>
28
29#include <kcmdlineargs.h>
30#include <kapplication.h>
31#include <klocale.h>
32#include <kaboutdata.h>
33#include <kglobal.h>
34#include <kstandarddirs.h>
35#include <ktoolinvocation.h>
36#include <klauncher_iface.h>
37#include <kde_file.h>
38#include <QtDBus/QtDBus>
39
40static const char appName[] = "kdontchangethehostname";
41static const char appVersion[] = "1.1";
42
43class KHostName
44{
45public:
46 KHostName();
47
48 void changeX();
49 void changeStdDirs(const QByteArray &type);
50 void changeSessionManager();
51
52protected:
53 QString oldName;
54 QString newName;
55 QString display;
56 QByteArray home;
57};
58
59KHostName::KHostName()
60{
61 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
62 if (args->count() != 2)
63 args->usage();
64 oldName = args->arg(0);
65 newName = args->arg(1);
66 if (oldName == newName)
67 exit(0);
68
69 home = qgetenv("HOME");
70 if (home.isEmpty())
71 {
72 fprintf(stderr, "%s", i18n("Error: HOME environment variable not set.\n").toLocal8Bit().data());
73 exit(1);
74 }
75
76 display = QString::fromLocal8Bit(qgetenv("DISPLAY"));
77 // strip the screen number from the display
78 display.remove(QRegExp("\\.[0-9]+$"));
79#if defined(Q_WS_X11) || defined(Q_WS_QWS)
80 if (display.isEmpty())
81 {
82 fprintf(stderr, "%s", i18n("Error: DISPLAY environment variable not set.\n").toLocal8Bit().data());
83 exit(1);
84 }
85#endif
86}
87
88static QList<QByteArray> split(const QByteArray &str)
89{
90 const char *s = str.data();
91 QList<QByteArray> result;
92 while (*s)
93 {
94 const char *i = strchr(s, ' ');
95 if (!i)
96 {
97 result.append(QByteArray(s));
98 return result;
99 }
100 result.append(QByteArray(s, i-s+1));
101 s = i;
102 while (*s == ' ') s++;
103 }
104 return result;
105}
106
107void KHostName::changeX()
108{
109 QProcess proc;
110 proc.start("xauth", QStringList() << "-n" << "list");
111 if (!proc.waitForFinished())
112 {
113 fprintf(stderr, "Warning: Can not run xauth.\n");
114 return;
115 }
116 QList<QByteArray> lines;
117 {
118 while (!proc.atEnd())
119 {
120 QByteArray line = proc.readLine();
121 if (line.length())
122 line.truncate(line.length()-1); // Strip LF.
123 if (!line.isEmpty())
124 lines.append(line);
125 }
126 }
127
128 foreach ( const QByteArray &it, lines )
129 {
130 QList<QByteArray> entries = split(it);
131 if (entries.count() != 3)
132 continue;
133
134 QByteArray netId = entries[0];
135 QByteArray authName = entries[1];
136 QByteArray authKey = entries[2];
137
138 int i = netId.lastIndexOf(':');
139 if (i == -1)
140 continue;
141 QByteArray netDisplay = netId.mid(i);
142 if (netDisplay != display)
143 continue;
144
145 i = netId.indexOf('/');
146 if (i == -1)
147 continue;
148
149 QString newNetId = newName+netId.mid(i);
150 QString oldNetId = netId.left(i);
151
152 if (oldNetId != oldName)
153 continue;
154
155 QProcess::execute("xauth", QStringList() << "-n" << "remove" << netId);
156 QProcess::execute("xauth", QStringList() << "-n" << "add" << newNetId << authName << authKey);
157 }
158}
159
160void KHostName::changeStdDirs(const QByteArray &type)
161{
162 // We make links to the old dirs cause we can't delete the old dirs.
163 QByteArray oldDir = QFile::encodeName(QString("%1%2-%3").arg(KGlobal::dirs()->localkdedir()).arg(QString( type )).arg(QString( oldName )));
164 QByteArray newDir = QFile::encodeName(QString("%1%2-%3").arg(KGlobal::dirs()->localkdedir()).arg(QString( type )).arg(QString( newName )));
165
166 KDE_struct_stat st_buf;
167
168 int result = KDE_lstat(oldDir.data(), &st_buf);
169 if (result == 0)
170 {
171 if (S_ISLNK(st_buf.st_mode))
172 {
173 char buf[4096+1];
174 result = readlink(oldDir.data(), buf, 4096);
175 if (result >= 0)
176 {
177 buf[result] = 0;
178 result = symlink(buf, newDir.data());
179 }
180 }
181 else if (S_ISDIR(st_buf.st_mode))
182 {
183 result = symlink(oldDir.data(), newDir.data());
184 }
185 else
186 {
187 result = -1;
188 }
189 }
190 if (result != 0)
191 {
192 const QString lnusertemp = KGlobal::dirs()->findExe( "lnusertemp" );
193 QProcess::execute( lnusertemp, QStringList() << type );
194 }
195}
196
197void KHostName::changeSessionManager()
198{
199 QString sm = QString::fromLocal8Bit(qgetenv("SESSION_MANAGER"));
200 if (sm.isEmpty())
201 {
202 fprintf(stderr, "Warning: No session management specified.\n");
203 return;
204 }
205 int i = sm.lastIndexOf(':');
206 if ((i == -1) || (sm.left(6) != "local/"))
207 {
208 fprintf(stderr, "Warning: Session Management socket '%s' has unexpected format.\n", sm.toLocal8Bit().constData());
209 return;
210 }
211 sm = "local/"+newName+sm.mid(i);
212 KToolInvocation::klauncher()->call(QDBus::NoBlock, "setLaunchEnv", QByteArray("SESSION_MANAGER"), sm);
213}
214
215int main(int argc, char **argv)
216{
217 KAboutData d(appName, "kdelibs4", ki18n("KDontChangeTheHostName"), appVersion,
218 ki18n("Informs KDE about a change in hostname"),
219 KAboutData::License_GPL, ki18n("(c) 2001 Waldo Bastian"));
220 d.addAuthor(ki18n("Waldo Bastian"), ki18n("Author"), "bastian@kde.org");
221
222 KCmdLineOptions options;
223 options.add("+old", ki18n("Old hostname"));
224 options.add("+new", ki18n("New hostname"));
225
226 KCmdLineArgs::init(argc, argv, &d);
227 KCmdLineArgs::addCmdLineOptions(options);
228
229 KComponentData k(&d);
230
231 KHostName hn;
232
233 hn.changeX();
234 hn.changeStdDirs("socket");
235 hn.changeStdDirs("tmp");
236 hn.changeSessionManager();
237}
238
239