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 <tqfile.h> 00026 #include <tqtextstream.h> 00027 #include <tqregexp.h> 00028 00029 #include <dcopclient.h> 00030 00031 #include <tdecmdlineargs.h> 00032 #include <tdeapplication.h> 00033 #include <tdelocale.h> 00034 #include <tdeaboutdata.h> 00035 #include <tdeglobal.h> 00036 #include <kstandarddirs.h> 00037 #include <kprocess.h> 00038 #include <kde_file.h> 00039 00040 static TDECmdLineOptions options[] = { 00041 { "+old", I18N_NOOP("Old hostname"), 0 }, 00042 { "+new", I18N_NOOP("New hostname"), 0 }, 00043 TDECmdLineLastOption 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 TQCString &type); 00057 void changeSessionManager(); 00058 00059 protected: 00060 TQCString oldName; 00061 TQCString newName; 00062 TQCString display; 00063 TQCString home; 00064 }; 00065 00066 KHostName::KHostName() 00067 { 00068 TDECmdLineArgs *args = TDECmdLineArgs::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(TQRegExp("\\.[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 TQCString &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(TQCString(s)); 00103 return result; 00104 } 00105 result.append(TQCString(s, i-s+1)); 00106 s = i; 00107 while (*s == ' ') s++; 00108 } 00109 return result; 00110 } 00111 00112 void KHostName::changeX() 00113 { 00114 const char* xauthlocalhostname = getenv("XAUTHLOCALHOSTNAME"); 00115 TQString cmd = "xauth -n list"; 00116 FILE *xFile = popen(TQFile::encodeName(cmd), "r"); 00117 if (!xFile) 00118 { 00119 fprintf(stderr, "Warning: Can't run xauth.\n"); 00120 return; 00121 } 00122 QCStringList lines; 00123 { 00124 char buf[1024+1]; 00125 while (!feof(xFile)) 00126 { 00127 buf[1024]='\0'; 00128 TQCString line = fgets(buf, 1024, xFile); 00129 if (line.length()) 00130 line.truncate(line.length()-1); // Strip LF. 00131 if (!line.isEmpty()) 00132 lines.append(line); 00133 } 00134 } 00135 pclose(xFile); 00136 00137 for(QCStringList::ConstIterator it = lines.begin(); 00138 it != lines.end(); ++it) 00139 { 00140 QCStringList entries = split(*it); 00141 if (entries.count() != 3) 00142 continue; 00143 00144 TQCString netId = entries[0]; 00145 TQCString authName = entries[1]; 00146 TQCString authKey = entries[2]; 00147 00148 int i = netId.findRev(':'); 00149 if (i == -1) 00150 continue; 00151 TQCString netDisplay = netId.mid(i); 00152 if (netDisplay != display) 00153 continue; 00154 00155 i = netId.find('/'); 00156 if (i == -1) 00157 continue; 00158 00159 TQCString newNetId = newName+netId.mid(i); 00160 TQCString oldNetId = netId.left(i); 00161 00162 if(oldNetId != oldName 00163 && (!xauthlocalhostname || strcmp(xauthlocalhostname, oldNetId.data()) != 0)) 00164 continue; 00165 00166 // don't nuke the xauth when XAUTHLOCALHOSTNAME points to it 00167 if (!xauthlocalhostname || oldNetId != xauthlocalhostname) 00168 { 00169 cmd = "xauth -n remove "+TDEProcess::quote(netId); 00170 system(TQFile::encodeName(cmd)); 00171 } 00172 cmd = "xauth -n add "; 00173 cmd += TDEProcess::quote(newNetId); 00174 cmd += " "; 00175 cmd += TDEProcess::quote(authName); 00176 cmd += " "; 00177 cmd += TDEProcess::quote(authKey); 00178 system(TQFile::encodeName(cmd)); 00179 } 00180 } 00181 00182 void KHostName::changeDcop() 00183 { 00184 TQCString origFNameOld = DCOPClient::dcopServerFileOld(oldName); 00185 TQCString fname = DCOPClient::dcopServerFile(oldName); 00186 TQCString origFName = fname; 00187 FILE *dcopFile = fopen(fname.data(), "r"); 00188 if (!dcopFile) 00189 { 00190 fprintf(stderr, "Warning: Can't open '%s' for reading.\n", fname.data()); 00191 return; 00192 } 00193 00194 TQCString line1, line2; 00195 { 00196 char buf[1024+1]; 00197 line1 = fgets(buf, 1024, dcopFile); 00198 if (line1.length()) 00199 line1.truncate(line1.length()-1); // Strip LF. 00200 00201 line2 = fgets(buf, 1024, dcopFile); 00202 if (line2.length()) 00203 line2.truncate(line2.length()-1); // Strip LF. 00204 } 00205 fclose(dcopFile); 00206 00207 TQCString oldNetId = line1; 00208 00209 if (!newName.isEmpty()) 00210 { 00211 int i = line1.findRev(':'); 00212 if (i == -1) 00213 { 00214 fprintf(stderr, "Warning: File '%s' has unexpected format.\n", fname.data()); 00215 return; 00216 } 00217 line1 = "local/"+newName+line1.mid(i); 00218 TQCString newNetId = line1; 00219 fname = DCOPClient::dcopServerFile(newName); 00220 unlink(fname.data()); 00221 dcopFile = fopen(fname.data(), "w"); 00222 if (!dcopFile) 00223 { 00224 fprintf(stderr, "Warning: Can't open '%s' for writing.\n", fname.data()); 00225 return; 00226 } 00227 00228 fputs(line1.data(), dcopFile); 00229 fputc('\n', dcopFile); 00230 fputs(line2.data(), dcopFile); 00231 fputc('\n', dcopFile); 00232 00233 fclose(dcopFile); 00234 00235 TQCString compatLink = DCOPClient::dcopServerFileOld(newName); 00236 ::symlink(fname.data(), compatLink.data()); // Compatibility link 00237 00238 // Update .ICEauthority 00239 TQString cmd = "iceauth list "+TDEProcess::quote("netid="+oldNetId); 00240 FILE *iceFile = popen(TQFile::encodeName(cmd), "r"); 00241 if (!iceFile) 00242 { 00243 fprintf(stderr, "Warning: Can't run iceauth.\n"); 00244 return; 00245 } 00246 QCStringList lines; 00247 { 00248 char buf[1024+1]; 00249 while (!feof(iceFile)) 00250 { 00251 TQCString line = fgets(buf, 1024, iceFile); 00252 if (line.length()) 00253 line.truncate(line.length()-1); // Strip LF. 00254 if (!line.isEmpty()) 00255 lines.append(line); 00256 } 00257 } 00258 pclose(iceFile); 00259 00260 for(QCStringList::ConstIterator it = lines.begin(); 00261 it != lines.end(); ++it) 00262 { 00263 QCStringList entries = split(*it); 00264 if (entries.count() != 5) 00265 continue; 00266 00267 TQCString protName = entries[0]; 00268 TQCString netId = entries[2]; 00269 TQCString authName = entries[3]; 00270 TQCString authKey = entries[4]; 00271 if (netId != oldNetId) 00272 continue; 00273 00274 cmd = "iceauth add "; 00275 cmd += TDEProcess::quote(protName); 00276 cmd += " '' "; 00277 cmd += TDEProcess::quote(newNetId); 00278 cmd += " "; 00279 cmd += TDEProcess::quote(authName); 00280 cmd += " "; 00281 cmd += TDEProcess::quote(authKey); 00282 system(TQFile::encodeName(cmd)); 00283 } 00284 } 00285 00286 // Remove old entries, but only if XAUTHLOCALHOSTNAME doesn't point 00287 // to it 00288 char* xauthlocalhostname = getenv("XAUTHLOCALHOSTNAME"); 00289 if (!xauthlocalhostname || !oldNetId.contains(xauthlocalhostname)) 00290 { 00291 TQString cmd = "iceauth remove "+TDEProcess::quote("netid="+oldNetId); 00292 system(TQFile::encodeName(cmd)); 00293 unlink(origFName.data()); 00294 origFName = DCOPClient::dcopServerFileOld(oldName); // Compatibility link 00295 unlink(origFName.data()); 00296 } 00297 } 00298 00299 void KHostName::changeStdDirs(const TQCString &type) 00300 { 00301 // We make links to the old dirs cause we can't delete the old dirs. 00302 TQCString oldDir = TQFile::encodeName(TQString("%1%2-%3").arg(TDEGlobal::dirs()->localtdedir()).arg(type.data()).arg(oldName.data())); 00303 TQCString newDir = TQFile::encodeName(TQString("%1%2-%3").arg(TDEGlobal::dirs()->localtdedir()).arg(type.data()).arg(newName.data())); 00304 00305 KDE_struct_stat st_buf; 00306 00307 int result = KDE_lstat(oldDir.data(), &st_buf); 00308 if (result == 0) 00309 { 00310 if (S_ISLNK(st_buf.st_mode)) 00311 { 00312 char buf[4096+1]; 00313 result = readlink(oldDir.data(), buf, 4096); 00314 if (result >= 0) 00315 { 00316 buf[result] = 0; 00317 result = symlink(buf, newDir.data()); 00318 } 00319 } 00320 else if (S_ISDIR(st_buf.st_mode)) 00321 { 00322 result = symlink(oldDir.data(), newDir.data()); 00323 } 00324 else 00325 { 00326 result = -1; 00327 } 00328 } 00329 if (result != 0) 00330 { 00331 system(("lnusertemp "+type).data()); 00332 } 00333 } 00334 00335 void KHostName::changeSessionManager() 00336 { 00337 TQCString sm = ::getenv("SESSION_MANAGER"); 00338 if (sm.isEmpty()) 00339 { 00340 fprintf(stderr, "Warning: No session management specified.\n"); 00341 return; 00342 } 00343 int i = sm.findRev(':'); 00344 if ((i == -1) || (sm.left(6) != "local/")) 00345 { 00346 fprintf(stderr, "Warning: Session Management socket '%s' has unexpected format.\n", sm.data()); 00347 return; 00348 } 00349 sm = "local/"+newName+sm.mid(i); 00350 TQCString name = "SESSION_MANAGER"; 00351 TQByteArray params; 00352 TQDataStream stream(params, IO_WriteOnly); 00353 stream << name << sm; 00354 DCOPClient *client = new DCOPClient(); 00355 if (!client->attach()) 00356 { 00357 fprintf(stderr, "Warning: DCOP communication problem, can't fix Session Management.\n"); 00358 delete client; 00359 return; 00360 } 00361 TQCString launcher = TDEApplication::launcher(); 00362 client->send(launcher, launcher, "setLaunchEnv(TQCString,TQCString)", params); 00363 delete client; 00364 } 00365 00366 int main(int argc, char **argv) 00367 { 00368 TDELocale::setMainCatalogue("tdelibs"); 00369 TDEAboutData d(appName, I18N_NOOP("KDontChangeTheHostName"), appVersion, 00370 I18N_NOOP("Informs TDE about a change in hostname"), 00371 TDEAboutData::License_GPL, "(c) 2001 Waldo Bastian"); 00372 d.addAuthor("Waldo Bastian", I18N_NOOP("Author"), "bastian@kde.org"); 00373 00374 TDECmdLineArgs::init(argc, argv, &d); 00375 TDECmdLineArgs::addCmdLineOptions(options); 00376 00377 TDEInstance k(&d); 00378 00379 KHostName hn; 00380 00381 hn.changeX(); 00382 hn.changeDcop(); 00383 hn.changeStdDirs("socket"); 00384 hn.changeStdDirs("tmp"); 00385 hn.changeSessionManager(); 00386 } 00387