khostname.cpp
00001 /* This file is part of the KDE libraries 00002 * Copyright (C) 2001 Waldo Bastian <bastian@kde.org> 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Library General Public 00006 * License version 2 as published by the Free Software Foundation; 00007 * 00008 * This library is distributed in the hope that it will be useful, 00009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 * Library General Public License for more details. 00012 * 00013 * You should have received a copy of the GNU Library General Public License 00014 * along with this library; see the file COPYING.LIB. If not, write to 00015 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00016 * Boston, MA 02110-1301, USA. 00017 **/ 00018 00019 #include <sys/types.h> 00020 #include <sys/stat.h> 00021 #include <unistd.h> 00022 #include <stdlib.h> 00023 #include <stdio.h> 00024 00025 #include <qfile.h> 00026 #include <qtextstream.h> 00027 #include <qregexp.h> 00028 00029 #include <dcopclient.h> 00030 00031 #include <kcmdlineargs.h> 00032 #include <kapplication.h> 00033 #include <klocale.h> 00034 #include <kaboutdata.h> 00035 #include <kglobal.h> 00036 #include <kstandarddirs.h> 00037 #include <kprocess.h> 00038 #include <kde_file.h> 00039 00040 static KCmdLineOptions options[] = { 00041 { "+old", I18N_NOOP("Old hostname"), 0 }, 00042 { "+new", I18N_NOOP("New hostname"), 0 }, 00043 KCmdLineLastOption 00044 }; 00045 00046 static const char appName[] = "kdontchangethehostname"; 00047 static const char appVersion[] = "1.1"; 00048 00049 class KHostName 00050 { 00051 public: 00052 KHostName(); 00053 00054 void changeX(); 00055 void changeDcop(); 00056 void changeStdDirs(const QCString &type); 00057 void changeSessionManager(); 00058 00059 protected: 00060 QCString oldName; 00061 QCString newName; 00062 QCString display; 00063 QCString home; 00064 }; 00065 00066 KHostName::KHostName() 00067 { 00068 KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); 00069 if (args->count() != 2) 00070 args->usage(); 00071 oldName = args->arg(0); 00072 newName = args->arg(1); 00073 if (oldName == newName) 00074 exit(0); 00075 00076 home = ::getenv("HOME"); 00077 if (home.isEmpty()) 00078 { 00079 fprintf(stderr, "%s", i18n("Error: HOME environment variable not set.\n").local8Bit().data()); 00080 exit(1); 00081 } 00082 00083 display = ::getenv("DISPLAY"); 00084 // strip the screen number from the display 00085 display.replace(QRegExp("\\.[0-9]+$"), ""); 00086 if (display.isEmpty()) 00087 { 00088 fprintf(stderr, "%s", i18n("Error: DISPLAY environment variable not set.\n").local8Bit().data()); 00089 exit(1); 00090 } 00091 } 00092 00093 static QCStringList split(const QCString &str) 00094 { 00095 const char *s = str.data(); 00096 QCStringList result; 00097 while (*s) 00098 { 00099 const char *i = strchr(s, ' '); 00100 if (!i) 00101 { 00102 result.append(QCString(s)); 00103 return result; 00104 } 00105 result.append(QCString(s, i-s+1)); 00106 s = i; 00107 while (*s == ' ') s++; 00108 } 00109 return result; 00110 } 00111 00112 void KHostName::changeX() 00113 { 00114 QString cmd = "xauth list"; 00115 FILE *xFile = popen(QFile::encodeName(cmd), "r"); 00116 if (!xFile) 00117 { 00118 fprintf(stderr, "Warning: Can't run xauth.\n"); 00119 return; 00120 } 00121 QCStringList lines; 00122 { 00123 char buf[1024+1]; 00124 while (!feof(xFile)) 00125 { 00126 QCString line = fgets(buf, 1024, xFile); 00127 if (line.length()) 00128 line.truncate(line.length()-1); // Strip LF. 00129 if (!line.isEmpty()) 00130 lines.append(line); 00131 } 00132 } 00133 pclose(xFile); 00134 00135 for(QCStringList::ConstIterator it = lines.begin(); 00136 it != lines.end(); ++it) 00137 { 00138 QCStringList entries = split(*it); 00139 if (entries.count() != 3) 00140 continue; 00141 00142 QCString netId = entries[0]; 00143 QCString authName = entries[1]; 00144 QCString authKey = entries[2]; 00145 00146 int i = netId.findRev(':'); 00147 if (i == -1) 00148 continue; 00149 QCString netDisplay = netId.mid(i); 00150 if (netDisplay != display) 00151 continue; 00152 00153 i = netId.find('/'); 00154 if (i == -1) 00155 continue; 00156 00157 QCString newNetId = newName+netId.mid(i); 00158 QCString oldNetId = netId.left(i); 00159 00160 if(oldNetId != oldName) 00161 continue; 00162 00163 cmd = "xauth remove "+KProcess::quote(netId); 00164 system(QFile::encodeName(cmd)); 00165 cmd = "xauth add "; 00166 cmd += KProcess::quote(newNetId); 00167 cmd += " "; 00168 cmd += KProcess::quote(authName); 00169 cmd += " "; 00170 cmd += KProcess::quote(authKey); 00171 system(QFile::encodeName(cmd)); 00172 } 00173 } 00174 00175 void KHostName::changeDcop() 00176 { 00177 QCString origFNameOld = DCOPClient::dcopServerFileOld(oldName); 00178 QCString fname = DCOPClient::dcopServerFile(oldName); 00179 QCString origFName = fname; 00180 FILE *dcopFile = fopen(fname.data(), "r"); 00181 if (!dcopFile) 00182 { 00183 fprintf(stderr, "Warning: Can't open '%s' for reading.\n", fname.data()); 00184 return; 00185 } 00186 00187 QCString line1, line2; 00188 { 00189 char buf[1024+1]; 00190 line1 = fgets(buf, 1024, dcopFile); 00191 if (line1.length()) 00192 line1.truncate(line1.length()-1); // Strip LF. 00193 00194 line2 = fgets(buf, 1024, dcopFile); 00195 if (line2.length()) 00196 line2.truncate(line2.length()-1); // Strip LF. 00197 } 00198 fclose(dcopFile); 00199 00200 QCString oldNetId = line1; 00201 00202 if (!newName.isEmpty()) 00203 { 00204 int i = line1.findRev(':'); 00205 if (i == -1) 00206 { 00207 fprintf(stderr, "Warning: File '%s' has unexpected format.\n", fname.data()); 00208 return; 00209 } 00210 line1 = "local/"+newName+line1.mid(i); 00211 QCString newNetId = line1; 00212 fname = DCOPClient::dcopServerFile(newName); 00213 unlink(fname.data()); 00214 dcopFile = fopen(fname.data(), "w"); 00215 if (!dcopFile) 00216 { 00217 fprintf(stderr, "Warning: Can't open '%s' for writing.\n", fname.data()); 00218 return; 00219 } 00220 00221 fputs(line1.data(), dcopFile); 00222 fputc('\n', dcopFile); 00223 fputs(line2.data(), dcopFile); 00224 fputc('\n', dcopFile); 00225 00226 fclose(dcopFile); 00227 00228 QCString compatLink = DCOPClient::dcopServerFileOld(newName); 00229 ::symlink(fname.data(), compatLink.data()); // Compatibility link 00230 00231 // Update .ICEauthority 00232 QString cmd = "iceauth list "+KProcess::quote("netid="+oldNetId); 00233 FILE *iceFile = popen(QFile::encodeName(cmd), "r"); 00234 if (!iceFile) 00235 { 00236 fprintf(stderr, "Warning: Can't run iceauth.\n"); 00237 return; 00238 } 00239 QCStringList lines; 00240 { 00241 char buf[1024+1]; 00242 while (!feof(iceFile)) 00243 { 00244 QCString line = fgets(buf, 1024, iceFile); 00245 if (line.length()) 00246 line.truncate(line.length()-1); // Strip LF. 00247 if (!line.isEmpty()) 00248 lines.append(line); 00249 } 00250 } 00251 pclose(iceFile); 00252 00253 for(QCStringList::ConstIterator it = lines.begin(); 00254 it != lines.end(); ++it) 00255 { 00256 QCStringList entries = split(*it); 00257 if (entries.count() != 5) 00258 continue; 00259 00260 QCString protName = entries[0]; 00261 QCString netId = entries[2]; 00262 QCString authName = entries[3]; 00263 QCString authKey = entries[4]; 00264 if (netId != oldNetId) 00265 continue; 00266 00267 cmd = "iceauth add "; 00268 cmd += KProcess::quote(protName); 00269 cmd += " '' "; 00270 cmd += KProcess::quote(newNetId); 00271 cmd += " "; 00272 cmd += KProcess::quote(authName); 00273 cmd += " "; 00274 cmd += KProcess::quote(authKey); 00275 system(QFile::encodeName(cmd)); 00276 } 00277 } 00278 00279 // Remove old entries 00280 { 00281 QString cmd = "iceauth remove "+KProcess::quote("netid="+oldNetId); 00282 system(QFile::encodeName(cmd)); 00283 unlink(origFName.data()); 00284 origFName = DCOPClient::dcopServerFileOld(oldName); // Compatibility link 00285 unlink(origFName.data()); 00286 } 00287 } 00288 00289 void KHostName::changeStdDirs(const QCString &type) 00290 { 00291 // We make links to the old dirs cause we can't delete the old dirs. 00292 QCString oldDir = QFile::encodeName(QString("%1%2-%3").arg(KGlobal::dirs()->localkdedir()).arg(type).arg(oldName)); 00293 QCString newDir = QFile::encodeName(QString("%1%2-%3").arg(KGlobal::dirs()->localkdedir()).arg(type).arg(newName)); 00294 00295 KDE_struct_stat st_buf; 00296 00297 int result = KDE_lstat(oldDir.data(), &st_buf); 00298 if (result == 0) 00299 { 00300 if (S_ISLNK(st_buf.st_mode)) 00301 { 00302 char buf[4096+1]; 00303 result = readlink(oldDir.data(), buf, 4096); 00304 if (result >= 0) 00305 { 00306 buf[result] = 0; 00307 result = symlink(buf, newDir.data()); 00308 } 00309 } 00310 else if (S_ISDIR(st_buf.st_mode)) 00311 { 00312 result = symlink(oldDir.data(), newDir.data()); 00313 } 00314 else 00315 { 00316 result = -1; 00317 } 00318 } 00319 if (result != 0) 00320 { 00321 system(("lnusertemp "+type).data()); 00322 } 00323 } 00324 00325 void KHostName::changeSessionManager() 00326 { 00327 QCString sm = ::getenv("SESSION_MANAGER"); 00328 if (sm.isEmpty()) 00329 { 00330 fprintf(stderr, "Warning: No session management specified.\n"); 00331 return; 00332 } 00333 int i = sm.findRev(':'); 00334 if ((i == -1) || (sm.left(6) != "local/")) 00335 { 00336 fprintf(stderr, "Warning: Session Management socket '%s' has unexpected format.\n", sm.data()); 00337 return; 00338 } 00339 sm = "local/"+newName+sm.mid(i); 00340 QCString name = "SESSION_MANAGER"; 00341 QByteArray params; 00342 QDataStream stream(params, IO_WriteOnly); 00343 stream << name << sm; 00344 DCOPClient *client = new DCOPClient(); 00345 if (!client->attach()) 00346 { 00347 fprintf(stderr, "Warning: DCOP communication problem, can't fix Session Management.\n"); 00348 delete client; 00349 return; 00350 } 00351 QCString launcher = KApplication::launcher(); 00352 client->send(launcher, launcher, "setLaunchEnv(QCString,QCString)", params); 00353 delete client; 00354 } 00355 00356 int main(int argc, char **argv) 00357 { 00358 KLocale::setMainCatalogue("kdelibs"); 00359 KAboutData d(appName, I18N_NOOP("KDontChangeTheHostName"), appVersion, 00360 I18N_NOOP("Informs KDE about a change in hostname"), 00361 KAboutData::License_GPL, "(c) 2001 Waldo Bastian"); 00362 d.addAuthor("Waldo Bastian", I18N_NOOP("Author"), "bastian@kde.org"); 00363 00364 KCmdLineArgs::init(argc, argv, &d); 00365 KCmdLineArgs::addCmdLineOptions(options); 00366 00367 KInstance k(&d); 00368 00369 KHostName hn; 00370 00371 if(!getenv("XAUTHLOCALHOSTNAME")) 00372 hn.changeX(); 00373 00374 hn.changeDcop(); 00375 hn.changeStdDirs("socket"); 00376 hn.changeStdDirs("tmp"); 00377 hn.changeSessionManager(); 00378 } 00379