TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

khostname.cpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  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. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <unistd.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <tqfile.h>
  24. #include <tqtextstream.h>
  25. #include <tqregexp.h>
  26. #include <dcopclient.h>
  27. #include <kcmdlineargs.h>
  28. #include <kapplication.h>
  29. #include <klocale.h>
  30. #include <kaboutdata.h>
  31. #include <kglobal.h>
  32. #include <kstandarddirs.h>
  33. #include <kprocess.h>
  34. #include <kde_file.h>
  35. static KCmdLineOptions options[] = {
  36. { "+old", I18N_NOOP("Old hostname"), 0 },
  37. { "+new", I18N_NOOP("New hostname"), 0 },
  38. KCmdLineLastOption
  39. };
  40. static const char appName[] = "kdontchangethehostname";
  41. static const char appVersion[] = "1.1";
  42. class KHostName
  43. {
  44. public:
  45. KHostName();
  46. void changeX();
  47. void changeDcop();
  48. void changeStdDirs(const TQCString &type);
  49. void changeSessionManager();
  50. protected:
  51. TQCString oldName;
  52. TQCString newName;
  53. TQCString display;
  54. TQCString home;
  55. };
  56. KHostName::KHostName()
  57. {
  58. KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
  59. if (args->count() != 2)
  60. args->usage();
  61. oldName = args->arg(0);
  62. newName = args->arg(1);
  63. if (oldName == newName)
  64. exit(0);
  65. home = ::getenv("HOME");
  66. if (home.isEmpty())
  67. {
  68. fprintf(stderr, "%s", i18n("Error: HOME environment variable not set.\n").local8Bit().data());
  69. exit(1);
  70. }
  71. display = ::getenv("DISPLAY");
  72. // strip the screen number from the display
  73. display.replace(TQRegExp("\\.[0-9]+$"), "");
  74. if (display.isEmpty())
  75. {
  76. fprintf(stderr, "%s", i18n("Error: DISPLAY environment variable not set.\n").local8Bit().data());
  77. exit(1);
  78. }
  79. }
  80. static QCStringList split(const TQCString &str)
  81. {
  82. const char *s = str.data();
  83. QCStringList result;
  84. while (*s)
  85. {
  86. const char *i = strchr(s, ' ');
  87. if (!i)
  88. {
  89. result.append(TQCString(s));
  90. return result;
  91. }
  92. result.append(TQCString(s, i-s+1));
  93. s = i;
  94. while (*s == ' ') s++;
  95. }
  96. return result;
  97. }
  98. void KHostName::changeX()
  99. {
  100. const char* xauthlocalhostname = getenv("XAUTHLOCALHOSTNAME");
  101. TQString cmd = "xauth -n list";
  102. FILE *xFile = popen(TQFile::encodeName(cmd), "r");
  103. if (!xFile)
  104. {
  105. fprintf(stderr, "Warning: Can't run xauth.\n");
  106. return;
  107. }
  108. QCStringList lines;
  109. {
  110. char buf[1024+1];
  111. while (!feof(xFile))
  112. {
  113. buf[1024]='\0';
  114. TQCString line = fgets(buf, 1024, xFile);
  115. if (line.length())
  116. line.truncate(line.length()-1); // Strip LF.
  117. if (!line.isEmpty())
  118. lines.append(line);
  119. }
  120. }
  121. pclose(xFile);
  122. for(QCStringList::ConstIterator it = lines.begin();
  123. it != lines.end(); ++it)
  124. {
  125. QCStringList entries = split(*it);
  126. if (entries.count() != 3)
  127. continue;
  128. TQCString netId = entries[0];
  129. TQCString authName = entries[1];
  130. TQCString authKey = entries[2];
  131. int i = netId.findRev(':');
  132. if (i == -1)
  133. continue;
  134. TQCString netDisplay = netId.mid(i);
  135. if (netDisplay != display)
  136. continue;
  137. i = netId.find('/');
  138. if (i == -1)
  139. continue;
  140. TQCString newNetId = newName+netId.mid(i);
  141. TQCString oldNetId = netId.left(i);
  142. if(oldNetId != oldName
  143. && (!xauthlocalhostname || strcmp(xauthlocalhostname, oldNetId.data()) != 0))
  144. continue;
  145. // don't nuke the xauth when XAUTHLOCALHOSTNAME points to it
  146. if (!xauthlocalhostname || oldNetId != xauthlocalhostname)
  147. {
  148. cmd = "xauth -n remove "+KProcess::quote(netId);
  149. system(TQFile::encodeName(cmd));
  150. }
  151. cmd = "xauth -n add ";
  152. cmd += KProcess::quote(newNetId);
  153. cmd += " ";
  154. cmd += KProcess::quote(authName);
  155. cmd += " ";
  156. cmd += KProcess::quote(authKey);
  157. system(TQFile::encodeName(cmd));
  158. }
  159. }
  160. void KHostName::changeDcop()
  161. {
  162. TQCString origFNameOld = DCOPClient::dcopServerFileOld(oldName);
  163. TQCString fname = DCOPClient::dcopServerFile(oldName);
  164. TQCString origFName = fname;
  165. FILE *dcopFile = fopen(fname.data(), "r");
  166. if (!dcopFile)
  167. {
  168. fprintf(stderr, "Warning: Can't open '%s' for reading.\n", fname.data());
  169. return;
  170. }
  171. TQCString line1, line2;
  172. {
  173. char buf[1024+1];
  174. line1 = fgets(buf, 1024, dcopFile);
  175. if (line1.length())
  176. line1.truncate(line1.length()-1); // Strip LF.
  177. line2 = fgets(buf, 1024, dcopFile);
  178. if (line2.length())
  179. line2.truncate(line2.length()-1); // Strip LF.
  180. }
  181. fclose(dcopFile);
  182. TQCString oldNetId = line1;
  183. if (!newName.isEmpty())
  184. {
  185. int i = line1.findRev(':');
  186. if (i == -1)
  187. {
  188. fprintf(stderr, "Warning: File '%s' has unexpected format.\n", fname.data());
  189. return;
  190. }
  191. line1 = "local/"+newName+line1.mid(i);
  192. TQCString newNetId = line1;
  193. fname = DCOPClient::dcopServerFile(newName);
  194. unlink(fname.data());
  195. dcopFile = fopen(fname.data(), "w");
  196. if (!dcopFile)
  197. {
  198. fprintf(stderr, "Warning: Can't open '%s' for writing.\n", fname.data());
  199. return;
  200. }
  201. fputs(line1.data(), dcopFile);
  202. fputc('\n', dcopFile);
  203. fputs(line2.data(), dcopFile);
  204. fputc('\n', dcopFile);
  205. fclose(dcopFile);
  206. TQCString compatLink = DCOPClient::dcopServerFileOld(newName);
  207. ::symlink(fname.data(), compatLink.data()); // Compatibility link
  208. // Update .ICEauthority
  209. TQString cmd = "iceauth list "+KProcess::quote("netid="+oldNetId);
  210. FILE *iceFile = popen(TQFile::encodeName(cmd), "r");
  211. if (!iceFile)
  212. {
  213. fprintf(stderr, "Warning: Can't run iceauth.\n");
  214. return;
  215. }
  216. QCStringList lines;
  217. {
  218. char buf[1024+1];
  219. while (!feof(iceFile))
  220. {
  221. TQCString line = fgets(buf, 1024, iceFile);
  222. if (line.length())
  223. line.truncate(line.length()-1); // Strip LF.
  224. if (!line.isEmpty())
  225. lines.append(line);
  226. }
  227. }
  228. pclose(iceFile);
  229. for(QCStringList::ConstIterator it = lines.begin();
  230. it != lines.end(); ++it)
  231. {
  232. QCStringList entries = split(*it);
  233. if (entries.count() != 5)
  234. continue;
  235. TQCString protName = entries[0];
  236. TQCString netId = entries[2];
  237. TQCString authName = entries[3];
  238. TQCString authKey = entries[4];
  239. if (netId != oldNetId)
  240. continue;
  241. cmd = "iceauth add ";
  242. cmd += KProcess::quote(protName);
  243. cmd += " '' ";
  244. cmd += KProcess::quote(newNetId);
  245. cmd += " ";
  246. cmd += KProcess::quote(authName);
  247. cmd += " ";
  248. cmd += KProcess::quote(authKey);
  249. system(TQFile::encodeName(cmd));
  250. }
  251. }
  252. // Remove old entries, but only if XAUTHLOCALHOSTNAME doesn't point
  253. // to it
  254. char* xauthlocalhostname = getenv("XAUTHLOCALHOSTNAME");
  255. if (!xauthlocalhostname || !oldNetId.contains(xauthlocalhostname))
  256. {
  257. TQString cmd = "iceauth remove "+KProcess::quote("netid="+oldNetId);
  258. system(TQFile::encodeName(cmd));
  259. unlink(origFName.data());
  260. origFName = DCOPClient::dcopServerFileOld(oldName); // Compatibility link
  261. unlink(origFName.data());
  262. }
  263. }
  264. void KHostName::changeStdDirs(const TQCString &type)
  265. {
  266. // We make links to the old dirs cause we can't delete the old dirs.
  267. TQCString oldDir = TQFile::encodeName(TQString("%1%2-%3").arg(KGlobal::dirs()->localkdedir()).arg(type).arg(oldName));
  268. TQCString newDir = TQFile::encodeName(TQString("%1%2-%3").arg(KGlobal::dirs()->localkdedir()).arg(type).arg(newName));
  269. KDE_struct_stat st_buf;
  270. int result = KDE_lstat(oldDir.data(), &st_buf);
  271. if (result == 0)
  272. {
  273. if (S_ISLNK(st_buf.st_mode))
  274. {
  275. char buf[4096+1];
  276. result = readlink(oldDir.data(), buf, 4096);
  277. if (result >= 0)
  278. {
  279. buf[result] = 0;
  280. result = symlink(buf, newDir.data());
  281. }
  282. }
  283. else if (S_ISDIR(st_buf.st_mode))
  284. {
  285. result = symlink(oldDir.data(), newDir.data());
  286. }
  287. else
  288. {
  289. result = -1;
  290. }
  291. }
  292. if (result != 0)
  293. {
  294. system(("lnusertemp "+type).data());
  295. }
  296. }
  297. void KHostName::changeSessionManager()
  298. {
  299. TQCString sm = ::getenv("SESSION_MANAGER");
  300. if (sm.isEmpty())
  301. {
  302. fprintf(stderr, "Warning: No session management specified.\n");
  303. return;
  304. }
  305. int i = sm.findRev(':');
  306. if ((i == -1) || (sm.left(6) != "local/"))
  307. {
  308. fprintf(stderr, "Warning: Session Management socket '%s' has unexpected format.\n", sm.data());
  309. return;
  310. }
  311. sm = "local/"+newName+sm.mid(i);
  312. TQCString name = "SESSION_MANAGER";
  313. TQByteArray params;
  314. TQDataStream stream(params, IO_WriteOnly);
  315. stream << name << sm;
  316. DCOPClient *client = new DCOPClient();
  317. if (!client->attach())
  318. {
  319. fprintf(stderr, "Warning: DCOP communication problem, can't fix Session Management.\n");
  320. delete client;
  321. return;
  322. }
  323. TQCString launcher = KApplication::launcher();
  324. client->send(launcher, launcher, "setLaunchEnv(TQCString,TQCString)", params);
  325. delete client;
  326. }
  327. int main(int argc, char **argv)
  328. {
  329. KLocale::setMainCatalogue("kdelibs");
  330. KAboutData d(appName, I18N_NOOP("KDontChangeTheHostName"), appVersion,
  331. I18N_NOOP("Informs KDE about a change in hostname"),
  332. KAboutData::License_GPL, "(c) 2001 Waldo Bastian");
  333. d.addAuthor("Waldo Bastian", I18N_NOOP("Author"), "bastian@kde.org");
  334. KCmdLineArgs::init(argc, argv, &d);
  335. KCmdLineArgs::addCmdLineOptions(options);
  336. KInstance k(&d);
  337. KHostName hn;
  338. hn.changeX();
  339. hn.changeDcop();
  340. hn.changeStdDirs("socket");
  341. hn.changeStdDirs("tmp");
  342. hn.changeSessionManager();
  343. }