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 
00159       cmd = "xauth remove "+KProcess::quote(netId);
00160       system(QFile::encodeName(cmd));
00161       cmd = "xauth add ";
00162       cmd += KProcess::quote(newNetId);
00163       cmd += " ";
00164       cmd += KProcess::quote(authName);
00165       cmd += " ";
00166       cmd += KProcess::quote(authKey);
00167       system(QFile::encodeName(cmd));
00168    }
00169 }
00170 
00171 void KHostName::changeDcop()
00172 {
00173    QCString origFNameOld = DCOPClient::dcopServerFileOld(oldName);
00174    QCString fname = DCOPClient::dcopServerFile(oldName);
00175    QCString origFName = fname;
00176    FILE *dcopFile = fopen(fname.data(), "r");
00177    if (!dcopFile)
00178    {
00179       fprintf(stderr, "Warning: Can't open '%s' for reading.\n", fname.data());
00180       return;
00181    }
00182 
00183    QCString line1, line2;
00184    {
00185      char buf[1024+1];
00186      line1 = fgets(buf, 1024, dcopFile);
00187      if (line1.length())
00188             line1.truncate(line1.length()-1); // Strip LF.
00189 
00190      line2 = fgets(buf, 1024, dcopFile);
00191      if (line2.length())
00192             line2.truncate(line2.length()-1); // Strip LF.
00193    }
00194    fclose(dcopFile);
00195 
00196    QCString oldNetId = line1;
00197 
00198    if (!newName.isEmpty())
00199    {
00200       int i = line1.findRev(':');
00201       if (i == -1)
00202       {
00203          fprintf(stderr, "Warning: File '%s' has unexpected format.\n", fname.data());
00204          return;
00205       }
00206       line1 = "local/"+newName+line1.mid(i);
00207       QCString newNetId = line1;
00208       fname = DCOPClient::dcopServerFile(newName);
00209       unlink(fname.data());
00210       dcopFile = fopen(fname.data(), "w");
00211       if (!dcopFile)
00212       {
00213          fprintf(stderr, "Warning: Can't open '%s' for writing.\n", fname.data());
00214          return;
00215       }
00216 
00217       fputs(line1.data(), dcopFile);
00218       fputc('\n', dcopFile);
00219       fputs(line2.data(), dcopFile);
00220       fputc('\n', dcopFile);
00221 
00222       fclose(dcopFile);
00223 
00224       QCString compatLink = DCOPClient::dcopServerFileOld(newName);
00225       ::symlink(fname.data(), compatLink.data()); // Compatibility link
00226 
00227       // Update .ICEauthority
00228       QString cmd = "iceauth list "+KProcess::quote("netid="+oldNetId);
00229       FILE *iceFile = popen(QFile::encodeName(cmd), "r");
00230       if (!iceFile)
00231       {
00232          fprintf(stderr, "Warning: Can't run iceauth.\n");
00233          return;   
00234       }
00235       QCStringList lines;
00236       {
00237          char buf[1024+1];
00238          while (!feof(iceFile))
00239          {
00240             QCString line = fgets(buf, 1024, iceFile);
00241             if (line.length())
00242                line.truncate(line.length()-1); // Strip LF.
00243             if (!line.isEmpty())
00244                lines.append(line);
00245          }
00246       }
00247       pclose(iceFile);
00248 
00249       for(QCStringList::ConstIterator it = lines.begin();
00250          it != lines.end(); ++it)
00251       {
00252          QCStringList entries = split(*it);
00253          if (entries.count() != 5)
00254             continue;
00255 
00256          QCString protName = entries[0];
00257          QCString netId = entries[2];
00258          QCString authName = entries[3];
00259          QCString authKey = entries[4];
00260          if (netId != oldNetId)
00261             continue;
00262 
00263          cmd = "iceauth add ";
00264          cmd += KProcess::quote(protName);
00265          cmd += " '' ";
00266          cmd += KProcess::quote(newNetId);
00267          cmd += " ";
00268          cmd += KProcess::quote(authName);
00269          cmd += " ";
00270          cmd += KProcess::quote(authKey);
00271          system(QFile::encodeName(cmd));
00272       }
00273    }
00274 
00275    // Remove old entries
00276    {
00277       QString cmd = "iceauth remove "+KProcess::quote("netid="+oldNetId);
00278       system(QFile::encodeName(cmd));
00279       unlink(origFName.data());
00280       origFName = DCOPClient::dcopServerFileOld(oldName); // Compatibility link
00281       unlink(origFName.data());
00282    }
00283 }
00284 
00285 void KHostName::changeStdDirs(const QCString &type)
00286 {
00287    // We make links to the old dirs cause we can't delete the old dirs.
00288    QCString oldDir = QFile::encodeName(QString("%1%2-%3").arg(KGlobal::dirs()->localkdedir()).arg(type).arg(oldName));
00289    QCString newDir = QFile::encodeName(QString("%1%2-%3").arg(KGlobal::dirs()->localkdedir()).arg(type).arg(newName));
00290 
00291    KDE_struct_stat st_buf;
00292 
00293    int result = KDE_lstat(oldDir.data(), &st_buf);
00294    if (result == 0)
00295    {
00296       if (S_ISLNK(st_buf.st_mode))
00297       {
00298          char buf[4096+1];
00299          result = readlink(oldDir.data(), buf, 4096);
00300          if (result >= 0)
00301          {
00302             buf[result] = 0;
00303             result = symlink(buf, newDir.data());
00304          }
00305       }
00306       else if (S_ISDIR(st_buf.st_mode))
00307       {
00308          result = symlink(oldDir.data(), newDir.data());
00309       }
00310       else
00311       {
00312          result = -1;
00313       }
00314    }
00315    if (result != 0)
00316    {
00317       system(("lnusertemp "+type).data());
00318    }
00319 }
00320 
00321 void KHostName::changeSessionManager()
00322 {
00323    QCString sm = ::getenv("SESSION_MANAGER");
00324    if (sm.isEmpty())
00325    {
00326       fprintf(stderr, "Warning: No session management specified.\n");
00327       return;
00328    }
00329    int i = sm.findRev(':');
00330    if ((i == -1) || (sm.left(6) != "local/"))
00331    {
00332       fprintf(stderr, "Warning: Session Management socket '%s' has unexpected format.\n", sm.data());
00333       return;
00334    }
00335    sm = "local/"+newName+sm.mid(i);
00336    QCString name = "SESSION_MANAGER";
00337    QByteArray params;
00338    QDataStream stream(params, IO_WriteOnly);
00339    stream << name << sm;
00340    DCOPClient *client = new DCOPClient();
00341    if (!client->attach())
00342    {
00343       fprintf(stderr, "Warning: DCOP communication problem, can't fix Session Management.\n");
00344       delete client;
00345       return;
00346    }
00347    QCString launcher = KApplication::launcher();
00348    client->send(launcher, launcher, "setLaunchEnv(QCString,QCString)", params);
00349    delete client;
00350 }
00351 
00352 int main(int argc, char **argv)
00353 {
00354    KLocale::setMainCatalogue("kdelibs");
00355    KAboutData d(appName, I18N_NOOP("KDontChangeTheHostName"), appVersion,
00356                 I18N_NOOP("Informs KDE about a change in hostname"),
00357                 KAboutData::License_GPL, "(c) 2001 Waldo Bastian");
00358    d.addAuthor("Waldo Bastian", I18N_NOOP("Author"), "bastian@kde.org");
00359 
00360    KCmdLineArgs::init(argc, argv, &d);
00361    KCmdLineArgs::addCmdLineOptions(options);
00362 
00363    KInstance k(&d);
00364 
00365    KHostName hn;
00366 
00367    if(!getenv("XAUTHLOCALHOSTNAME"))
00368        hn.changeX();
00369 
00370    hn.changeDcop();
00371    hn.changeStdDirs("socket");
00372    hn.changeStdDirs("tmp");
00373    hn.changeSessionManager();
00374 }
00375 
KDE Home | KDE Accessibility Home | Description of Access Keys