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.

kinit.cpp 52KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913
  1. /*
  2. * This file is part of the KDE libraries
  3. * Copyright (c) 1999-2000 Waldo Bastian <bastian@kde.org>
  4. * (c) 1999 Mario Weilguni <mweilguni@sime.com>
  5. * (c) 2001 Lubos Lunak <l.lunak@kde.org>
  6. *
  7. * $Id$
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Library General Public
  11. * License version 2 as published by the Free Software Foundation.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Library General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Library General Public License
  19. * along with this library; see the file COPYING.LIB. If not, write to
  20. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  21. * Boston, MA 02110-1301, USA.
  22. */
  23. #include "config.h"
  24. #include <config.h>
  25. #include <sys/types.h>
  26. #include <sys/time.h>
  27. #include <sys/stat.h>
  28. #include <sys/socket.h>
  29. #include <sys/un.h>
  30. #include <sys/wait.h>
  31. #ifdef HAVE_SYS_SELECT_H
  32. #include <sys/select.h> // Needed on some systems.
  33. #endif
  34. #include <errno.h>
  35. #include <fcntl.h>
  36. #include <setproctitle.h>
  37. #include <signal.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <ctype.h>
  42. #include <unistd.h>
  43. #include <locale.h>
  44. #include <tqstring.h>
  45. #include <tqfile.h>
  46. #include <tqdatetime.h>
  47. #include <tqfileinfo.h>
  48. #include <tqtextstream.h>
  49. #include <tqregexp.h>
  50. #include <tqfont.h>
  51. #include <kinstance.h>
  52. #include <kstandarddirs.h>
  53. #include <tdeglobal.h>
  54. #include <tdeconfig.h>
  55. #include <klibloader.h>
  56. #include <tdeapplication.h>
  57. #include <tdelocale.h>
  58. #ifdef HAVE_SYS_PRCTL_H
  59. #include <sys/prctl.h>
  60. #ifndef PR_SET_NAME
  61. #define PR_SET_NAME 15
  62. #endif
  63. #endif
  64. #if defined Q_WS_X11 && ! defined K_WS_QTONLY
  65. #include <tdestartupinfo.h> // schroder
  66. #endif
  67. #include <tdeversion.h>
  68. #include "ltdl.h"
  69. #include "tdelauncher_cmds.h"
  70. //#if defined Q_WS_X11 && ! defined K_WS_QTONLY
  71. #ifdef Q_WS_X11
  72. //#undef K_WS_QTONLY
  73. #include <X11/Xlib.h>
  74. #include <X11/Xatom.h>
  75. #endif
  76. #ifdef HAVE_DLFCN_H
  77. # include <dlfcn.h>
  78. #endif
  79. #ifdef RTLD_GLOBAL
  80. # define LTDL_GLOBAL RTLD_GLOBAL
  81. #else
  82. # ifdef DL_GLOBAL
  83. # define LTDL_GLOBAL DL_GLOBAL
  84. # else
  85. # define LTDL_GLOBAL 0
  86. # endif
  87. #endif
  88. #if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
  89. #include <X11/Xft/Xft.h>
  90. extern "C" FcBool XftInitFtLibrary (void);
  91. #include <fontconfig/fontconfig.h>
  92. #endif
  93. extern char **environ;
  94. extern int lt_dlopen_flag;
  95. //#if defined Q_WS_X11 && ! defined K_WS_QTONLY
  96. #ifdef Q_WS_X11
  97. static int X11fd = -1;
  98. static Display *X11display = 0;
  99. static int X11_startup_notify_fd = -1;
  100. static Display *X11_startup_notify_display = 0;
  101. #endif
  102. static const TDEInstance *s_instance = 0;
  103. #define MAX_SOCK_FILE 255
  104. static char sock_file[MAX_SOCK_FILE];
  105. static char sock_file_old[MAX_SOCK_FILE];
  106. //#if defined Q_WS_X11 && ! defined K_WS_QTONLY
  107. #ifdef Q_WS_X11
  108. #define DISPLAY "DISPLAY"
  109. #elif defined(Q_WS_QWS)
  110. #define DISPLAY "QWS_DISPLAY"
  111. #elif defined(Q_WS_MACX)
  112. #define DISPLAY "MAC_DISPLAY"
  113. #elif defined(K_WS_QTONLY)
  114. #define DISPLAY "QT_DISPLAY"
  115. #else
  116. #error Use QT/X11 or QT/Embedded
  117. #endif
  118. /* Group data */
  119. static struct {
  120. int maxname;
  121. int fd[2];
  122. int launcher[2]; /* socket pair for launcher communication */
  123. int deadpipe[2]; /* pipe used to detect dead children */
  124. int initpipe[2];
  125. int wrapper; /* socket for wrapper communication */
  126. int wrapper_old; /* old socket for wrapper communication */
  127. char result;
  128. int exit_status;
  129. pid_t fork;
  130. pid_t launcher_pid;
  131. pid_t my_pid;
  132. int n;
  133. lt_dlhandle handle;
  134. lt_ptr sym;
  135. char **argv;
  136. int (*func)(int, char *[]);
  137. int (*launcher_func)(int);
  138. bool debug_wait;
  139. int lt_dlopen_flag;
  140. TQCString errorMsg;
  141. bool launcher_ok;
  142. bool suicide;
  143. } d;
  144. //#if defined Q_WS_X11 && ! defined K_WS_QTONLY
  145. #ifdef Q_WS_X11
  146. extern "C" {
  147. int tdeinit_xio_errhandler( Display * );
  148. int tdeinit_x_errhandler( Display *, XErrorEvent *err );
  149. }
  150. #endif
  151. /* These are to link libtdeparts even if 'smart' linker is used */
  152. #include <tdeparts/plugin.h>
  153. extern "C" KParts::Plugin* _kinit_init_tdeparts() { return new KParts::Plugin(); }
  154. /* These are to link libtdeio even if 'smart' linker is used */
  155. #include <tdeio/authinfo.h>
  156. extern "C" TDEIO::AuthInfo* _tdeioslave_init_kio() { return new TDEIO::AuthInfo(); }
  157. /*
  158. * Close fd's which are only useful for the parent process.
  159. * Restore default signal handlers.
  160. */
  161. static void close_fds()
  162. {
  163. if (d.deadpipe[0] != -1)
  164. {
  165. close(d.deadpipe[0]);
  166. d.deadpipe[0] = -1;
  167. }
  168. if (d.deadpipe[1] != -1)
  169. {
  170. close(d.deadpipe[1]);
  171. d.deadpipe[1] = -1;
  172. }
  173. if (d.initpipe[0] != -1)
  174. {
  175. close(d.initpipe[0]);
  176. d.initpipe[0] = -1;
  177. }
  178. if (d.initpipe[1] != -1)
  179. {
  180. close(d.initpipe[1]);
  181. d.initpipe[1] = -1;
  182. }
  183. if (d.launcher_pid)
  184. {
  185. close(d.launcher[0]);
  186. d.launcher_pid = 0;
  187. }
  188. if (d.wrapper)
  189. {
  190. close(d.wrapper);
  191. d.wrapper = 0;
  192. }
  193. if (d.wrapper_old)
  194. {
  195. close(d.wrapper_old);
  196. d.wrapper_old = 0;
  197. }
  198. #if defined Q_WS_X11 && ! defined K_WS_QTONLY
  199. //#ifdef Q_WS_X11
  200. if (X11fd >= 0)
  201. {
  202. close(X11fd);
  203. X11fd = -1;
  204. }
  205. if (X11_startup_notify_fd >= 0 && X11_startup_notify_fd != X11fd )
  206. {
  207. close(X11_startup_notify_fd);
  208. X11_startup_notify_fd = -1;
  209. }
  210. #endif
  211. signal(SIGCHLD, SIG_DFL);
  212. signal(SIGPIPE, SIG_DFL);
  213. }
  214. static void exitWithErrorMsg(const TQString &errorMsg)
  215. {
  216. fprintf( stderr, "[tdeinit] %s\n", errorMsg.local8Bit().data() );
  217. TQCString utf8ErrorMsg = errorMsg.utf8();
  218. d.result = 3; // Error with msg
  219. write(d.fd[1], &d.result, 1);
  220. int l = utf8ErrorMsg.length();
  221. write(d.fd[1], &l, sizeof(int));
  222. write(d.fd[1], utf8ErrorMsg.data(), l);
  223. close(d.fd[1]);
  224. exit(255);
  225. }
  226. static void setup_tty( const char* tty )
  227. {
  228. if( tty == NULL || *tty == '\0' )
  229. return;
  230. int fd = open( tty, O_WRONLY );
  231. if( fd < 0 )
  232. {
  233. fprintf(stderr, "[tdeinit] couldn't open() %s: %s\n", tty, strerror (errno) );
  234. return;
  235. }
  236. if( dup2( fd, STDOUT_FILENO ) < 0 )
  237. {
  238. fprintf(stderr, "[tdeinit] couldn't dup2() %s: %s\n", tty, strerror (errno) );
  239. close( fd );
  240. return;
  241. }
  242. if( dup2( fd, STDERR_FILENO ) < 0 )
  243. {
  244. fprintf(stderr, "[tdeinit] couldn't dup2() %s: %s\n", tty, strerror (errno) );
  245. close( fd );
  246. return;
  247. }
  248. close( fd );
  249. }
  250. // from tdecore/netwm.cpp
  251. static int get_current_desktop( Display* disp )
  252. {
  253. int desktop = 0; // no desktop by default
  254. #if defined Q_WS_X11 && ! defined K_WS_QTONLY
  255. //#ifdef Q_WS_X11 // Only X11 supports multiple desktops
  256. Atom net_current_desktop = XInternAtom( disp, "_NET_CURRENT_DESKTOP", False );
  257. Atom type_ret;
  258. int format_ret;
  259. unsigned char *data_ret;
  260. unsigned long nitems_ret, unused;
  261. if( XGetWindowProperty( disp, DefaultRootWindow( disp ), net_current_desktop,
  262. 0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret )
  263. == Success)
  264. {
  265. if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1)
  266. desktop = *((long *) data_ret) + 1;
  267. if (data_ret)
  268. XFree ((char*) data_ret);
  269. }
  270. #endif
  271. return desktop;
  272. }
  273. // var has to be e.g. "DISPLAY=", i.e. with =
  274. const char* get_env_var( const char* var, int envc, const char* envs )
  275. {
  276. if( envc > 0 )
  277. { // get the var from envs
  278. const char* env_l = envs;
  279. int ln = strlen( var );
  280. for (int i = 0; i < envc; i++)
  281. {
  282. if( strncmp( env_l, var, ln ) == 0 )
  283. return env_l + ln;
  284. while(*env_l != 0) env_l++;
  285. env_l++;
  286. }
  287. }
  288. return NULL;
  289. }
  290. #if defined Q_WS_X11 && ! defined K_WS_QTONLY
  291. //#ifdef Q_WS_X11 // FIXME(E): Implement for Qt/Embedded
  292. static void init_startup_info( TDEStartupInfoId& id, const char* bin,
  293. int envc, const char* envs )
  294. {
  295. const char* dpy = get_env_var( DISPLAY"=", envc, envs );
  296. // this may be called in a child, so it can't use display open using X11display
  297. // also needed for multihead
  298. X11_startup_notify_display = XOpenDisplay( dpy );
  299. if( X11_startup_notify_display == NULL )
  300. return;
  301. X11_startup_notify_fd = XConnectionNumber( X11_startup_notify_display );
  302. TDEStartupInfoData data;
  303. int desktop = get_current_desktop( X11_startup_notify_display );
  304. data.setDesktop( desktop );
  305. data.setBin( bin );
  306. TDEStartupInfo::sendChangeX( X11_startup_notify_display, id, data );
  307. XFlush( X11_startup_notify_display );
  308. }
  309. static void complete_startup_info( TDEStartupInfoId& id, pid_t pid )
  310. {
  311. if( X11_startup_notify_display == NULL )
  312. return;
  313. if( pid == 0 ) // failure
  314. TDEStartupInfo::sendFinishX( X11_startup_notify_display, id );
  315. else
  316. {
  317. TDEStartupInfoData data;
  318. data.addPid( pid );
  319. data.setHostname();
  320. TDEStartupInfo::sendChangeX( X11_startup_notify_display, id, data );
  321. }
  322. XCloseDisplay( X11_startup_notify_display );
  323. X11_startup_notify_display = NULL;
  324. X11_startup_notify_fd = -1;
  325. }
  326. #endif
  327. TQCString execpath_avoid_loops( const TQCString& exec, int envc, const char* envs, bool avoid_loops )
  328. {
  329. TQStringList paths;
  330. if( envc > 0 ) /* use the passed environment */
  331. {
  332. const char* path = get_env_var( "PATH=", envc, envs );
  333. if( path != NULL )
  334. paths = TQStringList::split( TQRegExp( "[:\b]" ), path, true );
  335. }
  336. else
  337. paths = TQStringList::split( TQRegExp( "[:\b]" ), getenv( "PATH" ), true );
  338. TQCString execpath = TQFile::encodeName(
  339. s_instance->dirs()->findExe( exec, paths.join( TQString( ":" ))));
  340. if( avoid_loops && !execpath.isEmpty())
  341. {
  342. int pos = execpath.findRev( '/' );
  343. TQString bin_path = execpath.left( pos );
  344. for( TQStringList::Iterator it = paths.begin();
  345. it != paths.end();
  346. ++it )
  347. if( ( *it ) == bin_path || ( *it ) == bin_path + '/' )
  348. {
  349. paths.remove( it );
  350. break; // -->
  351. }
  352. execpath = TQFile::encodeName(
  353. s_instance->dirs()->findExe( exec, paths.join( TQString( ":" ))));
  354. }
  355. return execpath;
  356. }
  357. #ifdef TDEINIT_OOM_PROTECT
  358. static int oom_pipe = -1;
  359. static void oom_protect_sighandler( int ) {
  360. }
  361. static void reset_oom_protect() {
  362. if( oom_pipe <= 0 )
  363. return;
  364. struct sigaction act, oldact;
  365. act.sa_handler = oom_protect_sighandler;
  366. act.sa_flags = 0;
  367. sigemptyset( &act.sa_mask );
  368. sigaction( SIGUSR1, &act, &oldact );
  369. sigset_t sigs, oldsigs;
  370. sigemptyset( &sigs );
  371. sigaddset( &sigs, SIGUSR1 );
  372. sigprocmask( SIG_BLOCK, &sigs, &oldsigs );
  373. pid_t pid = getpid();
  374. if( write( oom_pipe, &pid, sizeof( pid_t )) > 0 ) {
  375. sigsuspend( &oldsigs ); // wait for the signal to come
  376. }
  377. sigprocmask( SIG_SETMASK, &oldsigs, NULL );
  378. sigaction( SIGUSR1, &oldact, NULL );
  379. close( oom_pipe );
  380. oom_pipe = -1;
  381. }
  382. #else
  383. static void reset_oom_protect() {
  384. }
  385. #endif
  386. static pid_t launch(int argc, const char *_name, const char *args,
  387. const char *cwd=0, int envc=0, const char *envs=0,
  388. bool reset_env = false,
  389. const char *tty=0, bool avoid_loops = false,
  390. const char* startup_id_str = "0" )
  391. {
  392. int launcher = 0;
  393. TQCString lib;
  394. TQCString name;
  395. TQCString exec;
  396. if (strcmp(_name, "tdelauncher") == 0) {
  397. /* tdelauncher is launched in a special way:
  398. * It has a communication socket on LAUNCHER_FD
  399. */
  400. if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, d.launcher))
  401. {
  402. perror("[tdeinit] socketpair() failed!\n");
  403. exit(255);
  404. }
  405. launcher = 1;
  406. }
  407. TQCString libpath;
  408. TQCString execpath;
  409. if (_name[0] != '/')
  410. {
  411. /* Relative name without '.la' */
  412. name = _name;
  413. lib = name + ".la";
  414. exec = name;
  415. libpath = TQFile::encodeName(KLibLoader::findLibrary( lib, s_instance ));
  416. execpath = execpath_avoid_loops( exec, envc, envs, avoid_loops );
  417. }
  418. else
  419. {
  420. lib = _name;
  421. name = _name;
  422. name = name.mid( name.findRev('/') + 1);
  423. exec = _name;
  424. if (lib.right(3) == ".la")
  425. libpath = lib;
  426. else
  427. execpath = exec;
  428. }
  429. if (!args)
  430. {
  431. argc = 1;
  432. }
  433. if (0 > pipe(d.fd))
  434. {
  435. perror("[tdeinit] pipe() failed!\n");
  436. d.result = 3;
  437. d.errorMsg = i18n("Unable to start new process.\n"
  438. "The system may have reached the maximum number of open files possible or the maximum number of open files that you are allowed to use has been reached.").utf8();
  439. close(d.fd[0]);
  440. close(d.fd[1]);
  441. d.fork = 0;
  442. return d.fork;
  443. }
  444. #if defined Q_WS_X11 && ! defined K_WS_QTONLY
  445. //#ifdef Q_WS_X11
  446. TDEStartupInfoId startup_id;
  447. startup_id.initId( startup_id_str );
  448. if( !startup_id.none())
  449. init_startup_info( startup_id, name, envc, envs );
  450. #endif
  451. d.errorMsg = 0;
  452. d.fork = fork();
  453. switch(d.fork) {
  454. case -1:
  455. perror("[tdeinit] fork() failed!\n");
  456. d.result = 3;
  457. d.errorMsg = i18n("Unable to create new process.\n"
  458. "The system may have reached the maximum number of processes possible or the maximum number of processes that you are allowed to use has been reached.").utf8();
  459. close(d.fd[0]);
  460. close(d.fd[1]);
  461. d.fork = 0;
  462. break;
  463. case 0:
  464. /** Child **/
  465. close(d.fd[0]);
  466. close_fds();
  467. if (launcher)
  468. {
  469. if (d.fd[1] == LAUNCHER_FD)
  470. {
  471. d.fd[1] = dup(d.fd[1]); // Evacuate from LAUNCHER_FD
  472. }
  473. if (d.launcher[1] != LAUNCHER_FD)
  474. {
  475. dup2( d.launcher[1], LAUNCHER_FD); // Make sure the socket has fd LAUNCHER_FD
  476. close( d.launcher[1] );
  477. }
  478. close( d.launcher[0] );
  479. }
  480. reset_oom_protect();
  481. if (cwd && *cwd)
  482. chdir(cwd);
  483. if( reset_env ) // KWRAPPER/SHELL
  484. {
  485. TQStrList unset_envs;
  486. for( int tmp_env_count = 0;
  487. environ[tmp_env_count];
  488. tmp_env_count++)
  489. unset_envs.append( environ[ tmp_env_count ] );
  490. for( TQStrListIterator it( unset_envs );
  491. it.current() != NULL ;
  492. ++it )
  493. {
  494. TQCString tmp( it.current());
  495. int pos = tmp.find( '=' );
  496. if( pos >= 0 )
  497. unsetenv( tmp.left( pos ));
  498. }
  499. }
  500. for (int i = 0; i < envc; i++)
  501. {
  502. putenv((char *)envs);
  503. while(*envs != 0) envs++;
  504. envs++;
  505. }
  506. #if defined Q_WS_X11 && ! defined K_WS_QTONLY
  507. //#ifdef Q_WS_X11
  508. if( startup_id.none())
  509. TDEStartupInfo::resetStartupEnv();
  510. else
  511. startup_id.setupStartupEnv();
  512. #endif
  513. {
  514. int r;
  515. TQCString procTitle;
  516. d.argv = (char **) malloc(sizeof(char *) * (argc+1));
  517. d.argv[0] = (char *) _name;
  518. for (int i = 1; i < argc; i++)
  519. {
  520. d.argv[i] = (char *) args;
  521. procTitle += " ";
  522. procTitle += (char *) args;
  523. while(*args != 0) args++;
  524. args++;
  525. }
  526. d.argv[argc] = 0;
  527. /** Give the process a new name **/
  528. #ifdef HAVE_SYS_PRCTL_H
  529. /* set the process name, so that killall works like intended */
  530. r = prctl(PR_SET_NAME, (unsigned long) name.data(), 0, 0, 0);
  531. if ( r == 0 )
  532. tdeinit_setproctitle( "%s [tdeinit]%s", name.data(), procTitle.data() ? procTitle.data() : "" );
  533. else
  534. tdeinit_setproctitle( "[tdeinit] %s%s", name.data(), procTitle.data() ? procTitle.data() : "" );
  535. #else
  536. tdeinit_setproctitle( "[tdeinit] %s%s", name.data(), procTitle.data() ? procTitle.data() : "" );
  537. #endif
  538. }
  539. d.handle = 0;
  540. if (libpath.isEmpty() && execpath.isEmpty())
  541. {
  542. TQString errorMsg = i18n("Could not find '%1' executable.").arg(TQFile::decodeName(_name));
  543. exitWithErrorMsg(errorMsg);
  544. }
  545. if ( getenv("TDE_IS_PRELINKED") && !execpath.isEmpty() && !launcher)
  546. libpath.truncate(0);
  547. if ( !libpath.isEmpty() )
  548. {
  549. d.handle = lt_dlopen( TQFile::encodeName(libpath) );
  550. if (!d.handle )
  551. {
  552. const char * ltdlError = lt_dlerror();
  553. if (execpath.isEmpty())
  554. {
  555. // Error
  556. TQString errorMsg = i18n("Could not open library '%1'.\n%2").arg(TQFile::decodeName(libpath))
  557. .arg(ltdlError ? TQFile::decodeName(ltdlError) : i18n("Unknown error"));
  558. exitWithErrorMsg(errorMsg);
  559. }
  560. else
  561. {
  562. // Print warning
  563. fprintf(stderr, "Could not open library %s: %s\n", lib.data(), ltdlError != 0 ? ltdlError : "(null)" );
  564. }
  565. }
  566. }
  567. lt_dlopen_flag = d.lt_dlopen_flag;
  568. if (!d.handle )
  569. {
  570. d.result = 2; // Try execing
  571. write(d.fd[1], &d.result, 1);
  572. // We set the close on exec flag.
  573. // Closing of d.fd[1] indicates that the execvp succeeded!
  574. fcntl(d.fd[1], F_SETFD, FD_CLOEXEC);
  575. setup_tty( tty );
  576. execvp(execpath.data(), d.argv);
  577. d.result = 1; // Error
  578. write(d.fd[1], &d.result, 1);
  579. close(d.fd[1]);
  580. exit(255);
  581. }
  582. d.sym = lt_dlsym( d.handle, "tdeinitmain");
  583. if (!d.sym )
  584. {
  585. d.sym = lt_dlsym( d.handle, "kdemain" );
  586. if ( !d.sym )
  587. {
  588. #if ! KDE_IS_VERSION( 3, 90, 0 )
  589. d.sym = lt_dlsym( d.handle, "main");
  590. #endif
  591. if (!d.sym )
  592. {
  593. const char * ltdlError = lt_dlerror();
  594. fprintf(stderr, "Could not find kdemain: %s\n", ltdlError != 0 ? ltdlError : "(null)" );
  595. TQString errorMsg = i18n("Could not find 'kdemain' in '%1'.\n%2").arg(TQString(libpath))
  596. .arg(ltdlError ? TQFile::decodeName(ltdlError) : i18n("Unknown error"));
  597. exitWithErrorMsg(errorMsg);
  598. }
  599. }
  600. }
  601. d.result = 0; // Success
  602. write(d.fd[1], &d.result, 1);
  603. close(d.fd[1]);
  604. d.func = (int (*)(int, char *[])) d.sym;
  605. if (d.debug_wait)
  606. {
  607. fprintf(stderr, "[tdeinit] Suspending process\n"
  608. "[tdeinit] 'gdb tdeinit %d' to debug\n"
  609. "[tdeinit] 'kill -SIGCONT %d' to continue\n",
  610. getpid(), getpid());
  611. kill(getpid(), SIGSTOP);
  612. }
  613. else
  614. {
  615. setup_tty( tty );
  616. }
  617. exit( d.func(argc, d.argv)); /* Launch! */
  618. break;
  619. default:
  620. /** Parent **/
  621. close(d.fd[1]);
  622. if (launcher)
  623. {
  624. close(d.launcher[1]);
  625. d.launcher_pid = d.fork;
  626. }
  627. bool exec = false;
  628. for(;;)
  629. {
  630. d.n = read(d.fd[0], &d.result, 1);
  631. if (d.n == 1)
  632. {
  633. if (d.result == 2)
  634. {
  635. #ifndef NDEBUG
  636. fprintf(stderr, "[tdeinit] %s is executable and not a library. Launching with exec.\n", _name );
  637. #endif
  638. exec = true;
  639. continue;
  640. }
  641. if (d.result == 3)
  642. {
  643. int l = 0;
  644. d.n = read(d.fd[0], &l, sizeof(int));
  645. if (d.n == sizeof(int))
  646. {
  647. TQCString tmp;
  648. tmp.resize(l+1);
  649. d.n = read(d.fd[0], tmp.data(), l);
  650. tmp[l] = 0;
  651. if (d.n == l)
  652. d.errorMsg = tmp;
  653. }
  654. }
  655. // Finished
  656. break;
  657. }
  658. if (d.n == -1)
  659. {
  660. if (errno == ECHILD) { // a child died.
  661. continue;
  662. }
  663. if (errno == EINTR || errno == EAGAIN) { // interrupted or more to read
  664. continue;
  665. }
  666. }
  667. if (exec)
  668. {
  669. d.result = 0;
  670. break;
  671. }
  672. if (d.n == 0)
  673. {
  674. perror("[tdeinit] Pipe closed unexpectedly");
  675. d.result = 1; // Error
  676. break;
  677. }
  678. perror("[tdeinit] Error reading from pipe");
  679. d.result = 1; // Error
  680. break;
  681. }
  682. close(d.fd[0]);
  683. if (launcher && (d.result == 0))
  684. {
  685. // Trader launched successful
  686. d.launcher_pid = d.fork;
  687. }
  688. }
  689. #if defined Q_WS_X11 && ! defined K_WS_QTONLY
  690. //#ifdef Q_WS_X11
  691. if( !startup_id.none())
  692. {
  693. if( d.fork && d.result == 0 ) // launched successfully
  694. complete_startup_info( startup_id, d.fork );
  695. else // failure, cancel ASN
  696. complete_startup_info( startup_id, 0 );
  697. }
  698. #endif
  699. return d.fork;
  700. }
  701. static void sig_child_handler(int)
  702. {
  703. /*
  704. * Write into the pipe of death.
  705. * This way we are sure that we return from the select()
  706. *
  707. * A signal itself causes select to return as well, but
  708. * this creates a race-condition in case the signal arrives
  709. * just before we enter the select.
  710. */
  711. char c = 0;
  712. write(d.deadpipe[1], &c, 1);
  713. }
  714. static void init_signals()
  715. {
  716. struct sigaction act;
  717. long options;
  718. if (pipe(d.deadpipe) != 0)
  719. {
  720. perror("[tdeinit] Aborting. Can't create pipe: ");
  721. exit(255);
  722. }
  723. options = fcntl(d.deadpipe[0], F_GETFL);
  724. if (options == -1)
  725. {
  726. perror("[tdeinit] Aborting. Can't make pipe non-blocking: ");
  727. exit(255);
  728. }
  729. if (fcntl(d.deadpipe[0], F_SETFL, options | O_NONBLOCK) == -1)
  730. {
  731. perror("[tdeinit] Aborting. Can't make pipe non-blocking: ");
  732. exit(255);
  733. }
  734. /*
  735. * A SIGCHLD handler is installed which sends a byte into the
  736. * pipe of death. This is to ensure that a dying child causes
  737. * an exit from select().
  738. */
  739. act.sa_handler=sig_child_handler;
  740. sigemptyset(&(act.sa_mask));
  741. sigaddset(&(act.sa_mask), SIGCHLD);
  742. sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
  743. act.sa_flags = SA_NOCLDSTOP;
  744. // CC: take care of SunOS which automatically restarts interrupted system
  745. // calls (and thus does not have SA_RESTART)
  746. #ifdef SA_RESTART
  747. act.sa_flags |= SA_RESTART;
  748. #endif
  749. sigaction( SIGCHLD, &act, 0L);
  750. act.sa_handler=SIG_IGN;
  751. sigemptyset(&(act.sa_mask));
  752. sigaddset(&(act.sa_mask), SIGPIPE);
  753. sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
  754. act.sa_flags = 0;
  755. sigaction( SIGPIPE, &act, 0L);
  756. }
  757. static void init_tdeinit_socket()
  758. {
  759. struct sockaddr_un sa;
  760. struct sockaddr_un sa_old;
  761. kde_socklen_t socklen;
  762. long options;
  763. const char *home_dir = getenv("HOME");
  764. int max_tries = 10;
  765. if (!home_dir || !home_dir[0])
  766. {
  767. fprintf(stderr, "[tdeinit] Aborting. $HOME not set!");
  768. exit(255);
  769. }
  770. chdir(home_dir);
  771. {
  772. TQCString path = home_dir;
  773. TQCString readOnly = getenv("TDE_HOME_READONLY");
  774. if (access(path.data(), R_OK|W_OK))
  775. {
  776. if (errno == ENOENT)
  777. {
  778. fprintf(stderr, "[tdeinit] Aborting. $HOME directory (%s) does not exist.\n", path.data());
  779. exit(255);
  780. }
  781. else if (readOnly.isEmpty())
  782. {
  783. fprintf(stderr, "[tdeinit] Aborting. No write access to $HOME directory (%s).\n", path.data());
  784. exit(255);
  785. }
  786. }
  787. path = getenv("ICEAUTHORITY");
  788. if (path.isEmpty())
  789. {
  790. path = home_dir;
  791. path += "/.ICEauthority";
  792. }
  793. if (access(path.data(), R_OK|W_OK) && (errno != ENOENT))
  794. {
  795. fprintf(stderr, "[tdeinit] Aborting. No write access to '%s'.\n", path.data());
  796. exit(255);
  797. }
  798. }
  799. /** Test if socket file is already present
  800. * note that access() resolves symlinks, and so we check the actual
  801. * socket file if it exists
  802. */
  803. if (access(sock_file, W_OK) == 0)
  804. {
  805. int s;
  806. struct sockaddr_un server;
  807. // fprintf(stderr, "[tdeinit] Warning, socket_file already exists!\n");
  808. /*
  809. * create the socket stream
  810. */
  811. s = socket(PF_UNIX, SOCK_STREAM, 0);
  812. if (s < 0)
  813. {
  814. perror("socket() failed: ");
  815. exit(255);
  816. }
  817. server.sun_family = AF_UNIX;
  818. strcpy(server.sun_path, sock_file);
  819. socklen = sizeof(server);
  820. if(connect(s, (struct sockaddr *)&server, socklen) == 0)
  821. {
  822. fprintf(stderr, "[tdeinit] Shutting down running client.\n");
  823. tdelauncher_header request_header;
  824. request_header.cmd = LAUNCHER_TERMINATE_TDEINIT;
  825. request_header.arg_length = 0;
  826. write(s, &request_header, sizeof(request_header));
  827. sleep(1); // Give it some time
  828. }
  829. close(s);
  830. }
  831. /** Delete any stale socket file (and symlink) **/
  832. unlink(sock_file);
  833. unlink(sock_file_old);
  834. /** create socket **/
  835. d.wrapper = socket(PF_UNIX, SOCK_STREAM, 0);
  836. if (d.wrapper < 0)
  837. {
  838. perror("[tdeinit] Aborting. socket() failed: ");
  839. exit(255);
  840. }
  841. options = fcntl(d.wrapper, F_GETFL);
  842. if (options == -1)
  843. {
  844. perror("[tdeinit] Aborting. Can't make socket non-blocking: ");
  845. close(d.wrapper);
  846. exit(255);
  847. }
  848. if (fcntl(d.wrapper, F_SETFL, options | O_NONBLOCK) == -1)
  849. {
  850. perror("[tdeinit] Aborting. Can't make socket non-blocking: ");
  851. close(d.wrapper);
  852. exit(255);
  853. }
  854. while (1) {
  855. /** bind it **/
  856. socklen = sizeof(sa);
  857. memset(&sa, 0, socklen);
  858. sa.sun_family = AF_UNIX;
  859. strcpy(sa.sun_path, sock_file);
  860. if(bind(d.wrapper, (struct sockaddr *)&sa, socklen) != 0)
  861. {
  862. if (max_tries == 0) {
  863. perror("[tdeinit] Aborting. bind() failed: ");
  864. fprintf(stderr, "Could not bind to socket '%s'\n", sock_file);
  865. close(d.wrapper);
  866. exit(255);
  867. }
  868. max_tries--;
  869. } else
  870. break;
  871. }
  872. /** set permissions **/
  873. if (chmod(sock_file, 0600) != 0)
  874. {
  875. perror("[tdeinit] Aborting. Can't set permissions on socket: ");
  876. fprintf(stderr, "Wrong permissions of socket '%s'\n", sock_file);
  877. unlink(sock_file);
  878. close(d.wrapper);
  879. exit(255);
  880. }
  881. if(listen(d.wrapper, SOMAXCONN) < 0)
  882. {
  883. perror("[tdeinit] Aborting. listen() failed: ");
  884. unlink(sock_file);
  885. close(d.wrapper);
  886. exit(255);
  887. }
  888. /** create compatibility socket **/
  889. d.wrapper_old = socket(PF_UNIX, SOCK_STREAM, 0);
  890. if (d.wrapper_old < 0)
  891. {
  892. // perror("[tdeinit] Aborting. socket() failed: ");
  893. return;
  894. }
  895. options = fcntl(d.wrapper_old, F_GETFL);
  896. if (options == -1)
  897. {
  898. // perror("[tdeinit] Aborting. Can't make socket non-blocking: ");
  899. close(d.wrapper_old);
  900. d.wrapper_old = 0;
  901. return;
  902. }
  903. if (fcntl(d.wrapper_old, F_SETFL, options | O_NONBLOCK) == -1)
  904. {
  905. // perror("[tdeinit] Aborting. Can't make socket non-blocking: ");
  906. close(d.wrapper_old);
  907. d.wrapper_old = 0;
  908. return;
  909. }
  910. max_tries = 10;
  911. while (1) {
  912. /** bind it **/
  913. socklen = sizeof(sa_old);
  914. memset(&sa_old, 0, socklen);
  915. sa_old.sun_family = AF_UNIX;
  916. strcpy(sa_old.sun_path, sock_file_old);
  917. if(bind(d.wrapper_old, (struct sockaddr *)&sa_old, socklen) != 0)
  918. {
  919. if (max_tries == 0) {
  920. // perror("[tdeinit] Aborting. bind() failed: ");
  921. fprintf(stderr, "Could not bind to socket '%s'\n", sock_file_old);
  922. close(d.wrapper_old);
  923. d.wrapper_old = 0;
  924. return;
  925. }
  926. max_tries--;
  927. } else
  928. break;
  929. }
  930. /** set permissions **/
  931. if (chmod(sock_file_old, 0600) != 0)
  932. {
  933. fprintf(stderr, "Wrong permissions of socket '%s'\n", sock_file);
  934. unlink(sock_file_old);
  935. close(d.wrapper_old);
  936. d.wrapper_old = 0;
  937. return;
  938. }
  939. if(listen(d.wrapper_old, SOMAXCONN) < 0)
  940. {
  941. // perror("[tdeinit] Aborting. listen() failed: ");
  942. unlink(sock_file_old);
  943. close(d.wrapper_old);
  944. d.wrapper_old = 0;
  945. }
  946. }
  947. /*
  948. * Read 'len' bytes from 'sock' into buffer.
  949. * returns 0 on success, -1 on failure.
  950. */
  951. static int read_socket(int sock, char *buffer, int len)
  952. {
  953. ssize_t result;
  954. int bytes_left = len;
  955. while ( bytes_left > 0)
  956. {
  957. result = read(sock, buffer, bytes_left);
  958. if (result > 0)
  959. {
  960. buffer += result;
  961. bytes_left -= result;
  962. }
  963. else if (result == 0)
  964. return -1;
  965. else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
  966. return -1;
  967. }
  968. return 0;
  969. }
  970. static void WaitPid( pid_t waitForPid)
  971. {
  972. int result;
  973. while(1)
  974. {
  975. result = waitpid(waitForPid, &d.exit_status, 0);
  976. if ((result == -1) && (errno == ECHILD))
  977. return;
  978. }
  979. }
  980. static void launcher_died()
  981. {
  982. if (!d.launcher_ok)
  983. {
  984. /* This is bad. */
  985. fprintf(stderr, "[tdeinit] Communication error with launcher. Exiting!\n");
  986. ::exit(255);
  987. return;
  988. }
  989. // TDELauncher died... restart
  990. #ifndef NDEBUG
  991. fprintf(stderr, "[tdeinit] TDELauncher died unexpectedly.\n");
  992. #endif
  993. // Make sure it's really dead.
  994. if (d.launcher_pid)
  995. {
  996. kill(d.launcher_pid, SIGKILL);
  997. sleep(1); // Give it some time
  998. }
  999. d.launcher_ok = false;
  1000. d.launcher_pid = 0;
  1001. close(d.launcher[0]);
  1002. d.launcher[0] = -1;
  1003. pid_t pid = launch( 1, "tdelauncher", 0 );
  1004. #ifndef NDEBUG
  1005. fprintf(stderr, "[tdeinit] Relaunching TDELauncher, pid = %ld result = %d\n", (long) pid, d.result);
  1006. #endif
  1007. }
  1008. static void handle_launcher_request(int sock = -1)
  1009. {
  1010. bool launcher = false;
  1011. if (sock < 0)
  1012. {
  1013. sock = d.launcher[0];
  1014. launcher = true;
  1015. }
  1016. tdelauncher_header request_header;
  1017. char *request_data = 0L;
  1018. int result = read_socket(sock, (char *) &request_header, sizeof(request_header));
  1019. if (result != 0)
  1020. {
  1021. if (launcher)
  1022. launcher_died();
  1023. return;
  1024. }
  1025. if ( request_header.arg_length != 0 )
  1026. {
  1027. request_data = (char *) malloc(request_header.arg_length);
  1028. result = read_socket(sock, request_data, request_header.arg_length);
  1029. if (result != 0)
  1030. {
  1031. if (launcher)
  1032. launcher_died();
  1033. free(request_data);
  1034. return;
  1035. }
  1036. }
  1037. if (request_header.cmd == LAUNCHER_OK)
  1038. {
  1039. d.launcher_ok = true;
  1040. }
  1041. else if (request_header.arg_length &&
  1042. ((request_header.cmd == LAUNCHER_EXEC) ||
  1043. (request_header.cmd == LAUNCHER_EXT_EXEC) ||
  1044. (request_header.cmd == LAUNCHER_SHELL ) ||
  1045. (request_header.cmd == LAUNCHER_KWRAPPER) ||
  1046. (request_header.cmd == LAUNCHER_EXEC_NEW)))
  1047. {
  1048. pid_t pid;
  1049. tdelauncher_header response_header;
  1050. long response_data;
  1051. long l;
  1052. memcpy( &l, request_data, sizeof( long ));
  1053. int argc = l;
  1054. const char *name = request_data + sizeof(long);
  1055. const char *args = name + strlen(name) + 1;
  1056. const char *cwd = 0;
  1057. int envc = 0;
  1058. const char *envs = 0;
  1059. const char *tty = 0;
  1060. int avoid_loops = 0;
  1061. const char *startup_id_str = "0";
  1062. #ifndef NDEBUG
  1063. fprintf(stderr, "[tdeinit] Got %s '%s' from %s.\n",
  1064. (request_header.cmd == LAUNCHER_EXEC ? "EXEC" :
  1065. (request_header.cmd == LAUNCHER_EXT_EXEC ? "EXT_EXEC" :
  1066. (request_header.cmd == LAUNCHER_EXEC_NEW ? "EXEC_NEW" :
  1067. (request_header.cmd == LAUNCHER_SHELL ? "SHELL" : "KWRAPPER" )))),
  1068. name, launcher ? "launcher" : "socket" );
  1069. #endif
  1070. const char *arg_n = args;
  1071. for(int i = 1; i < argc; i++)
  1072. {
  1073. arg_n = arg_n + strlen(arg_n) + 1;
  1074. }
  1075. if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER )
  1076. {
  1077. // Shell or kwrapper
  1078. cwd = arg_n; arg_n += strlen(cwd) + 1;
  1079. }
  1080. if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
  1081. || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
  1082. {
  1083. memcpy( &l, arg_n, sizeof( long ));
  1084. envc = l;
  1085. arg_n += sizeof(long);
  1086. envs = arg_n;
  1087. for(int i = 0; i < envc; i++)
  1088. {
  1089. arg_n = arg_n + strlen(arg_n) + 1;
  1090. }
  1091. if( request_header.cmd == LAUNCHER_KWRAPPER )
  1092. {
  1093. tty = arg_n;
  1094. arg_n += strlen( tty ) + 1;
  1095. }
  1096. }
  1097. if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
  1098. || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
  1099. {
  1100. memcpy( &l, arg_n, sizeof( long ));
  1101. avoid_loops = l;
  1102. arg_n += sizeof( long );
  1103. }
  1104. if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
  1105. || request_header.cmd == LAUNCHER_EXT_EXEC )
  1106. {
  1107. startup_id_str = arg_n;
  1108. arg_n += strlen( startup_id_str ) + 1;
  1109. }
  1110. if ((request_header.arg_length > (arg_n - request_data)) &&
  1111. (request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW ))
  1112. {
  1113. // Optional cwd
  1114. cwd = arg_n; arg_n += strlen(cwd) + 1;
  1115. }
  1116. if ((arg_n - request_data) != request_header.arg_length)
  1117. {
  1118. #ifndef NDEBUG
  1119. fprintf(stderr, "[tdeinit] EXEC request has invalid format.\n");
  1120. #endif
  1121. free(request_data);
  1122. d.debug_wait = false;
  1123. return;
  1124. }
  1125. // support for the old a bit broken way of setting DISPLAY for multihead
  1126. TQCString olddisplay = getenv(DISPLAY);
  1127. TQCString kdedisplay = getenv("TDE_DISPLAY");
  1128. bool reset_display = (! olddisplay.isEmpty() &&
  1129. ! kdedisplay.isEmpty() &&
  1130. olddisplay != kdedisplay);
  1131. if (reset_display)
  1132. setenv(DISPLAY, kdedisplay, true);
  1133. pid = launch( argc, name, args, cwd, envc, envs,
  1134. request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER,
  1135. tty, avoid_loops, startup_id_str );
  1136. if (reset_display) {
  1137. unsetenv("TDE_DISPLAY");
  1138. setenv(DISPLAY, olddisplay, true);
  1139. }
  1140. if (pid && (d.result == 0))
  1141. {
  1142. response_header.cmd = LAUNCHER_OK;
  1143. response_header.arg_length = sizeof(response_data);
  1144. response_data = pid;
  1145. write(sock, &response_header, sizeof(response_header));
  1146. write(sock, &response_data, response_header.arg_length);
  1147. }
  1148. else
  1149. {
  1150. int l = d.errorMsg.length();
  1151. if (l) l++; // Include trailing null.
  1152. response_header.cmd = LAUNCHER_ERROR;
  1153. response_header.arg_length = l;
  1154. write(sock, &response_header, sizeof(response_header));
  1155. if (l)
  1156. write(sock, d.errorMsg.data(), l);
  1157. }
  1158. d.debug_wait = false;
  1159. }
  1160. else if (request_header.arg_length && request_header.cmd == LAUNCHER_SETENV)
  1161. {
  1162. const char *env_name;
  1163. const char *env_value;
  1164. env_name = request_data;
  1165. env_value = env_name + strlen(env_name) + 1;
  1166. #ifndef NDEBUG
  1167. if (launcher)
  1168. fprintf(stderr, "[tdeinit] Got SETENV '%s=%s' from tdelauncher.\n", env_name, env_value);
  1169. else
  1170. fprintf(stderr, "[tdeinit] Got SETENV '%s=%s' from socket.\n", env_name, env_value);
  1171. #endif
  1172. if ( request_header.arg_length !=
  1173. (int) (strlen(env_name) + strlen(env_value) + 2))
  1174. {
  1175. #ifndef NDEBUG
  1176. fprintf(stderr, "[tdeinit] SETENV request has invalid format.\n");
  1177. #endif
  1178. free(request_data);
  1179. return;
  1180. }
  1181. setenv( env_name, env_value, 1);
  1182. }
  1183. else if (request_header.cmd == LAUNCHER_TERMINATE_KDE)
  1184. {
  1185. #ifndef NDEBUG
  1186. fprintf(stderr,"[tdeinit] Terminating Trinity.\n");
  1187. #endif
  1188. #ifdef Q_WS_X11
  1189. tdeinit_xio_errhandler( 0L );
  1190. #endif
  1191. }
  1192. else if (request_header.cmd == LAUNCHER_TERMINATE_TDEINIT)
  1193. {
  1194. #ifndef NDEBUG
  1195. fprintf(stderr,"[tdeinit] Killing tdeinit/tdelauncher.\n");
  1196. #endif
  1197. if (d.launcher_pid)
  1198. kill(d.launcher_pid, SIGTERM);
  1199. if (d.my_pid)
  1200. kill(d.my_pid, SIGTERM);
  1201. }
  1202. else if (request_header.cmd == LAUNCHER_DEBUG_WAIT)
  1203. {
  1204. #ifndef NDEBUG
  1205. fprintf(stderr,"[tdeinit] Debug wait activated.\n");
  1206. #endif
  1207. d.debug_wait = true;
  1208. }
  1209. if (request_data)
  1210. free(request_data);
  1211. }
  1212. static void handle_requests(pid_t waitForPid)
  1213. {
  1214. int max_sock = d.wrapper;
  1215. if (d.wrapper_old > max_sock)
  1216. max_sock = d.wrapper_old;
  1217. if (d.launcher_pid && (d.launcher[0] > max_sock))
  1218. max_sock = d.launcher[0];
  1219. #if defined Q_WS_X11 && ! defined K_WS_QTONLY
  1220. //#ifdef _WS_X11
  1221. if (X11fd > max_sock)
  1222. max_sock = X11fd;
  1223. #endif
  1224. max_sock++;
  1225. while(1)
  1226. {
  1227. fd_set rd_set;
  1228. fd_set wr_set;
  1229. fd_set e_set;
  1230. int result;
  1231. pid_t exit_pid;
  1232. char c;
  1233. /* Flush the pipe of death */
  1234. while( read(d.deadpipe[0], &c, 1) == 1);
  1235. /* Handle dying children */
  1236. do {
  1237. exit_pid = waitpid(-1, 0, WNOHANG);
  1238. if (exit_pid > 0)
  1239. {
  1240. #ifndef NDEBUG
  1241. fprintf(stderr, "[tdeinit] PID %ld terminated.\n", (long) exit_pid);
  1242. #endif
  1243. if (waitForPid && (exit_pid == waitForPid))
  1244. return;
  1245. if (d.launcher_pid)
  1246. {
  1247. // TODO send process died message
  1248. tdelauncher_header request_header;
  1249. long request_data[2];
  1250. request_header.cmd = LAUNCHER_DIED;
  1251. request_header.arg_length = sizeof(long) * 2;
  1252. request_data[0] = exit_pid;
  1253. request_data[1] = 0; /* not implemented yet */
  1254. write(d.launcher[0], &request_header, sizeof(request_header));
  1255. write(d.launcher[0], request_data, request_header.arg_length);
  1256. }
  1257. }
  1258. }
  1259. while( exit_pid > 0);
  1260. FD_ZERO(&rd_set);
  1261. FD_ZERO(&wr_set);
  1262. FD_ZERO(&e_set);
  1263. if (d.launcher_pid)
  1264. {
  1265. FD_SET(d.launcher[0], &rd_set);
  1266. }
  1267. FD_SET(d.wrapper, &rd_set);
  1268. if (d.wrapper_old)
  1269. {
  1270. FD_SET(d.wrapper_old, &rd_set);
  1271. }
  1272. FD_SET(d.deadpipe[0], &rd_set);
  1273. #if defined Q_WS_X11 && ! defined K_WS_QTONLY
  1274. //#ifdef Q_WS_X11
  1275. if(X11fd >= 0) FD_SET(X11fd, &rd_set);
  1276. #endif
  1277. result = select(max_sock, &rd_set, &wr_set, &e_set, 0);
  1278. /* Handle wrapper request */
  1279. if ((result > 0) && (FD_ISSET(d.wrapper, &rd_set)))
  1280. {
  1281. struct sockaddr_un client;
  1282. kde_socklen_t sClient = sizeof(client);
  1283. int sock = accept(d.wrapper, (struct sockaddr *)&client, &sClient);
  1284. if (sock >= 0)
  1285. {
  1286. #if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
  1287. if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
  1288. FcInitReinitialize();
  1289. #endif
  1290. if (fork() == 0)
  1291. {
  1292. close_fds();
  1293. reset_oom_protect();
  1294. handle_launcher_request(sock);
  1295. exit(255); /* Terminate process. */
  1296. }
  1297. close(sock);
  1298. }
  1299. }
  1300. if ((result > 0) && (FD_ISSET(d.wrapper_old, &rd_set)))
  1301. {
  1302. struct sockaddr_un client;
  1303. kde_socklen_t sClient = sizeof(client);
  1304. int sock = accept(d.wrapper_old, (struct sockaddr *)&client, &sClient);
  1305. if (sock >= 0)
  1306. {
  1307. #if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
  1308. if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
  1309. FcInitReinitialize();
  1310. #endif
  1311. if (fork() == 0)
  1312. {
  1313. close_fds();
  1314. reset_oom_protect();
  1315. handle_launcher_request(sock);
  1316. exit(255); /* Terminate process. */
  1317. }
  1318. close(sock);
  1319. }
  1320. }
  1321. /* Handle launcher request */
  1322. if ((result > 0) && (d.launcher_pid) && (FD_ISSET(d.launcher[0], &rd_set)))
  1323. {
  1324. handle_launcher_request();
  1325. if (waitForPid == d.launcher_pid)
  1326. return;
  1327. }
  1328. //#if defined Q_WS_X11 && ! defined K_WS_QTONLY
  1329. #ifdef Q_WS_X11
  1330. /* Look for incoming X11 events */
  1331. if((result > 0) && (X11fd >= 0))
  1332. {
  1333. if(FD_ISSET(X11fd,&rd_set))
  1334. {
  1335. if (X11display != 0) {
  1336. XEvent event_return;
  1337. while (XPending(X11display))
  1338. XNextEvent(X11display, &event_return);
  1339. }
  1340. }
  1341. }
  1342. #endif
  1343. }
  1344. }
  1345. static void tdeinit_library_path()
  1346. {
  1347. TQStringList ltdl_library_path =
  1348. TQStringList::split(':', TQFile::decodeName(getenv("LTDL_LIBRARY_PATH")));
  1349. TQStringList ld_library_path =
  1350. TQStringList::split(':', TQFile::decodeName(getenv("LD_LIBRARY_PATH")));
  1351. TQCString extra_path;
  1352. TQStringList candidates = s_instance->dirs()->resourceDirs("lib");
  1353. for (TQStringList::ConstIterator it = candidates.begin();
  1354. it != candidates.end();
  1355. it++)
  1356. {
  1357. TQString d = *it;
  1358. if (ltdl_library_path.contains(d))
  1359. continue;
  1360. if (ld_library_path.contains(d))
  1361. continue;
  1362. if (d[d.length()-1] == '/')
  1363. {
  1364. d.truncate(d.length()-1);
  1365. if (ltdl_library_path.contains(d))
  1366. continue;
  1367. if (ld_library_path.contains(d))
  1368. continue;
  1369. }
  1370. if ((d == "/lib") || (d == "/usr/lib"))
  1371. continue;
  1372. TQCString dir = TQFile::encodeName(d);
  1373. if (access(dir, R_OK))
  1374. continue;
  1375. if ( !extra_path.isEmpty())
  1376. extra_path += ":";
  1377. extra_path += dir;
  1378. }
  1379. if (lt_dlinit())
  1380. {
  1381. const char * ltdlError = lt_dlerror();
  1382. fprintf(stderr, "can't initialize dynamic loading: %s\n", ltdlError != 0 ? ltdlError : "(null)" );
  1383. }
  1384. if (!extra_path.isEmpty())
  1385. lt_dlsetsearchpath(extra_path.data());
  1386. TQCString display = getenv(DISPLAY);
  1387. if (display.isEmpty())
  1388. {
  1389. fprintf(stderr, "[tdeinit] Aborting. $"DISPLAY" is not set.\n");
  1390. exit(255);
  1391. }
  1392. int i;
  1393. if((i = display.findRev('.')) > display.findRev(':') && i >= 0)
  1394. display.truncate(i);
  1395. TQCString socketName = TQFile::encodeName(locateLocal("socket", TQString("tdeinit-%1").arg(TQString(display)), s_instance));
  1396. if (socketName.length() >= MAX_SOCK_FILE)
  1397. {
  1398. fprintf(stderr, "[tdeinit] Aborting. Socket name will be too long:\n");
  1399. fprintf(stderr, " '%s'\n", socketName.data());
  1400. exit(255);
  1401. }
  1402. strcpy(sock_file_old, socketName.data());
  1403. display.replace(":","_");
  1404. socketName = TQFile::encodeName(locateLocal("socket", TQString("tdeinit_%1").arg(TQString(display)), s_instance));
  1405. if (socketName.length() >= MAX_SOCK_FILE)
  1406. {
  1407. fprintf(stderr, "[tdeinit] Aborting. Socket name will be too long:\n");
  1408. fprintf(stderr, " '%s'\n", socketName.data());
  1409. exit(255);
  1410. }
  1411. strcpy(sock_file, socketName.data());
  1412. }
  1413. int tdeinit_xio_errhandler( Display *disp )
  1414. {
  1415. // disp is 0L when KDE shuts down. We don't want those warnings then.
  1416. if ( disp )
  1417. tqWarning( "[tdeinit] Fatal IO error: client killed" );
  1418. if (sock_file[0])
  1419. {
  1420. /** Delete any stale socket file **/
  1421. unlink(sock_file);
  1422. }
  1423. if (sock_file_old[0])
  1424. {
  1425. /** Delete any stale socket file **/
  1426. unlink(sock_file_old);
  1427. }
  1428. // Don't kill our children in suicide mode, they may still be in use
  1429. if (d.suicide)
  1430. {
  1431. if (d.launcher_pid)
  1432. kill(d.launcher_pid, SIGTERM);
  1433. exit( 0 );
  1434. }
  1435. if ( disp )
  1436. tqWarning( "[tdeinit] sending SIGHUP to children." );
  1437. /* this should remove all children we started */
  1438. signal(SIGHUP, SIG_IGN);
  1439. kill(0, SIGHUP);
  1440. sleep(2);
  1441. if ( disp )
  1442. tqWarning( "[tdeinit] sending SIGTERM to children." );
  1443. /* and if they don't listen to us, this should work */
  1444. signal(SIGTERM, SIG_IGN);
  1445. kill(0, SIGTERM);
  1446. if ( disp )
  1447. tqWarning( "[tdeinit] Exit." );
  1448. exit( 0 );
  1449. return 0;
  1450. }
  1451. #ifdef Q_WS_X11
  1452. int tdeinit_x_errhandler( Display *dpy, XErrorEvent *err )
  1453. {
  1454. #ifndef NDEBUG
  1455. char errstr[256];
  1456. // tdeinit almost doesn't use X, and therefore there shouldn't be any X error
  1457. XGetErrorText( dpy, err->error_code, errstr, 256 );
  1458. fprintf(stderr, "[tdeinit] TDE detected X Error: %s %d\n"
  1459. " Major opcode: %d\n"
  1460. " Minor opcode: %d\n"
  1461. " Resource id: 0x%lx\n",
  1462. errstr, err->error_code, err->request_code, err->minor_code, err->resourceid );
  1463. #else
  1464. Q_UNUSED(dpy);
  1465. Q_UNUSED(err);
  1466. #endif
  1467. return 0;
  1468. }
  1469. #endif
  1470. //#if defined Q_WS_X11 && ! defined K_WS_QTONLY
  1471. #ifdef Q_WS_X11
  1472. // needs to be done sooner than initXconnection() because of also opening
  1473. // another X connection for startup notification purposes
  1474. static void setupX()
  1475. {
  1476. XInitThreads();
  1477. XSetIOErrorHandler(tdeinit_xio_errhandler);
  1478. XSetErrorHandler(tdeinit_x_errhandler);
  1479. }
  1480. // Borrowed from tdebase/kaudio/kaudioserver.cpp
  1481. static int initXconnection()
  1482. {
  1483. X11display = XOpenDisplay(NULL);
  1484. if ( X11display != 0 ) {
  1485. XCreateSimpleWindow(X11display, DefaultRootWindow(X11display), 0,0,1,1, \
  1486. 0,
  1487. BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)),
  1488. BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)) );
  1489. #ifndef NDEBUG
  1490. fprintf(stderr, "[tdeinit] opened connection to %s\n", DisplayString(X11display));
  1491. #endif
  1492. int fd = XConnectionNumber( X11display );
  1493. int on = 1;
  1494. (void) setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, (int) sizeof(on));
  1495. return fd;
  1496. } else
  1497. fprintf(stderr, "[tdeinit] Can't connect to the X Server.\n" \
  1498. "[tdeinit] Might not terminate at end of session.\n");
  1499. return -1;
  1500. }
  1501. #endif
  1502. #ifdef __KCC
  1503. /* One of my horrible hacks. KCC includes in each "main" function a call
  1504. to _main(), which is provided by the C++ runtime system. It is
  1505. responsible for calling constructors for some static objects. That must
  1506. be done only once, so _main() is guarded against multiple calls.
  1507. For unknown reasons the designers of KAI's libKCC decided it would be
  1508. a good idea to actually abort() when it's called multiple times, instead
  1509. of ignoring further calls. This breaks our mechanism of KLM's, because
  1510. most KLM's have a main() function which is called from us.
  1511. The "solution" is to simply define our own _main(), which ignores multiple
  1512. calls, which is easy, and which does the same work as KAI'c _main(),
  1513. which is difficult. Currently (KAI 4.0f) it only calls __call_ctors(void)
  1514. (a C++ function), but if that changes we need to change our's too.
  1515. (matz) */
  1516. /*
  1517. Those 'unknown reasons' are C++ standard forbidding recursive calls to main()
  1518. or any means that would possibly allow that (e.g. taking address of main()).
  1519. The correct solution is not using main() as entry point for tdeinit modules,
  1520. but only kdemain().
  1521. */
  1522. extern "C" void _main(void);
  1523. extern "C" void __call_ctors__Fv(void);
  1524. static int main_called = 0;
  1525. void _main(void)
  1526. {
  1527. if (main_called)
  1528. return;
  1529. main_called = 1;
  1530. __call_ctors__Fv ();
  1531. }
  1532. #endif
  1533. static void secondary_child_handler(int)
  1534. {
  1535. waitpid(-1, 0, WNOHANG);
  1536. }
  1537. int main(int argc, char **argv, char **envp)
  1538. {
  1539. int i;
  1540. pid_t pid;
  1541. int launch_dcop = 1;
  1542. int launch_tdelauncher = 1;
  1543. int launch_kded = 1;
  1544. int keep_running = 1;
  1545. int new_startup = 0;
  1546. d.suicide = false;
  1547. /** Save arguments first... **/
  1548. char **safe_argv = (char **) malloc( sizeof(char *) * argc);
  1549. for(i = 0; i < argc; i++)
  1550. {
  1551. safe_argv[i] = strcpy((char*)malloc(strlen(argv[i])+1), argv[i]);
  1552. if (strcmp(safe_argv[i], "--no-dcop") == 0)
  1553. launch_dcop = 0;
  1554. if (strcmp(safe_argv[i], "--no-tdelauncher") == 0)
  1555. launch_tdelauncher = 0;
  1556. if (strcmp(safe_argv[i], "--no-kded") == 0)
  1557. launch_kded = 0;
  1558. if (strcmp(safe_argv[i], "--suicide") == 0)
  1559. d.suicide = true;
  1560. if (strcmp(safe_argv[i], "--exit") == 0)
  1561. keep_running = 0;
  1562. if (strcmp(safe_argv[i], "--new-startup") == 0)
  1563. new_startup = 1;
  1564. #ifdef TDEINIT_OOM_PROTECT
  1565. if (strcmp(safe_argv[i], "--oom-pipe") == 0 && i+1<argc)
  1566. oom_pipe = atol(argv[i+1]);
  1567. #endif
  1568. if (strcmp(safe_argv[i], "--help") == 0)
  1569. {
  1570. printf("Usage: tdeinit [options]\n");
  1571. // printf(" --no-dcop Do not start dcopserver\n");
  1572. // printf(" --no-tdelauncher Do not start tdelauncher\n");
  1573. printf(" --no-kded Do not start kded\n");
  1574. printf(" --suicide Terminate when no TDE applications are left running\n");
  1575. // printf(" --exit Terminate when kded has run\n");
  1576. exit(0);
  1577. }
  1578. }
  1579. pipe(d.initpipe);
  1580. // Fork here and let parent process exit.
  1581. // Parent process may only exit after all required services have been
  1582. // launched. (dcopserver/tdelauncher and services which start with '+')
  1583. signal( SIGCHLD, secondary_child_handler);
  1584. if (fork() > 0) // Go into background
  1585. {
  1586. close(d.initpipe[1]);
  1587. d.initpipe[1] = -1;
  1588. // wait till init is complete
  1589. char c;
  1590. while( read(d.initpipe[0], &c, 1) < 0);
  1591. // then exit;
  1592. close(d.initpipe[0]);
  1593. d.initpipe[0] = -1;
  1594. return 0;
  1595. }
  1596. close(d.initpipe[0]);
  1597. d.initpipe[0] = -1;
  1598. d.my_pid = getpid();
  1599. /** Make process group leader (for shutting down children later) **/
  1600. if(keep_running)
  1601. setsid();
  1602. /** Create our instance **/
  1603. s_instance = new TDEInstance("tdeinit");
  1604. /** Prepare to change process name **/
  1605. tdeinit_initsetproctitle(argc, argv, envp);
  1606. tdeinit_library_path();
  1607. // Don't make our instance the global instance
  1608. // (do it only after tdeinit_library_path, that one indirectly uses TDEConfig,
  1609. // which seems to be buggy and always use TDEGlobal instead of the maching TDEInstance)
  1610. TDEGlobal::_instance = 0L;
  1611. // don't change envvars before tdeinit_initsetproctitle()
  1612. unsetenv("LD_BIND_NOW");
  1613. unsetenv("DYLD_BIND_AT_LAUNCH");
  1614. TDEApplication::loadedByKdeinit = true;
  1615. d.maxname = strlen(argv[0]);
  1616. d.launcher_pid = 0;
  1617. d.wrapper = 0;
  1618. d.wrapper_old = 0;
  1619. d.debug_wait = false;
  1620. d.launcher_ok = false;
  1621. d.lt_dlopen_flag = lt_dlopen_flag;
  1622. lt_dlopen_flag |= LTDL_GLOBAL;
  1623. init_signals();
  1624. #ifdef Q_WS_X11
  1625. setupX();
  1626. #endif
  1627. if (keep_running)
  1628. {
  1629. /*
  1630. * Create ~/.trinity/tmp-<hostname>/tdeinit-<display> socket for incoming wrapper
  1631. * requests.
  1632. */
  1633. init_tdeinit_socket();
  1634. }
  1635. if (launch_dcop)
  1636. {
  1637. if (d.suicide)
  1638. pid = launch( 3, "dcopserver", "--nosid\0--suicide" );
  1639. else
  1640. pid = launch( 2, "dcopserver", "--nosid" );
  1641. #ifndef NDEBUG
  1642. fprintf(stderr, "[tdeinit] Launched DCOPServer, pid = %ld result = %d\n", (long) pid, d.result);
  1643. #endif
  1644. WaitPid(pid);
  1645. if (!WIFEXITED(d.exit_status) || (WEXITSTATUS(d.exit_status) != 0))
  1646. {
  1647. fprintf(stderr, "[tdeinit] DCOPServer could not be started, aborting.\n");
  1648. exit(1);
  1649. }
  1650. }
  1651. #ifndef __CYGWIN__
  1652. if (!d.suicide && !getenv("TDE_IS_PRELINKED"))
  1653. {
  1654. TQString konq = locate("lib", "libkonq.la", s_instance);
  1655. if (!konq.isEmpty())
  1656. (void) lt_dlopen(TQFile::encodeName(konq).data());
  1657. }
  1658. #endif
  1659. if (launch_tdelauncher)
  1660. {
  1661. if( new_startup )
  1662. pid = launch( 2, "tdelauncher", "--new-startup" );
  1663. else
  1664. pid = launch( 1, "tdelauncher", 0 );
  1665. #ifndef NDEBUG
  1666. fprintf(stderr, "[tdeinit] Launched TDELauncher, pid = %ld result = %d\n", (long) pid, d.result);
  1667. #endif
  1668. handle_requests(pid); // Wait for tdelauncher to be ready
  1669. }
  1670. #if defined Q_WS_X11 && ! defined K_WS_QTONLY
  1671. //#ifdef Q_WS_X11
  1672. X11fd = initXconnection();
  1673. #endif
  1674. {
  1675. #if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
  1676. if( FcGetVersion() < 20390 )
  1677. {
  1678. XftInit(0);
  1679. XftInitFtLibrary();
  1680. }
  1681. #endif
  1682. TQFont::initialize();
  1683. setlocale (LC_ALL, "");
  1684. setlocale (LC_NUMERIC, "C");
  1685. #ifdef Q_WS_X11
  1686. if (XSupportsLocale ())
  1687. {
  1688. // Similar to TQApplication::create_xim()
  1689. // but we need to use our own display
  1690. XOpenIM (X11display, 0, 0, 0);
  1691. }
  1692. #endif
  1693. }
  1694. if (launch_kded)
  1695. {
  1696. if( new_startup )
  1697. pid = launch( 2, "kded", "--new-startup" );
  1698. else
  1699. pid = launch( 1, "kded", 0 );
  1700. #ifndef NDEBUG
  1701. fprintf(stderr, "[tdeinit] Launched KDED, pid = %ld result = %d\n", (long) pid, d.result);
  1702. #endif
  1703. handle_requests(pid);
  1704. }
  1705. for(i = 1; i < argc; i++)
  1706. {
  1707. if (safe_argv[i][0] == '+')
  1708. {
  1709. pid = launch( 1, safe_argv[i]+1, 0);
  1710. #ifndef NDEBUG
  1711. fprintf(stderr, "[tdeinit] Launched '%s', pid = %ld result = %d\n", safe_argv[i]+1, (long) pid, d.result);
  1712. #endif
  1713. handle_requests(pid);
  1714. }
  1715. else if (safe_argv[i][0] == '-'
  1716. #ifdef TDEINIT_OOM_PROTECT
  1717. || isdigit(safe_argv[i][0])
  1718. #endif
  1719. )
  1720. {
  1721. // Ignore
  1722. }
  1723. else
  1724. {
  1725. pid = launch( 1, safe_argv[i], 0 );
  1726. #ifndef NDEBUG
  1727. fprintf(stderr, "[tdeinit] Launched '%s', pid = %ld result = %d\n", safe_argv[i], (long) pid, d.result);
  1728. #endif
  1729. }
  1730. }
  1731. /** Free arguments **/
  1732. for(i = 0; i < argc; i++)
  1733. {
  1734. free(safe_argv[i]);
  1735. }
  1736. free (safe_argv);
  1737. tdeinit_setproctitle("tdeinit Running...");
  1738. if (!keep_running)
  1739. return 0;
  1740. char c = 0;
  1741. write(d.initpipe[1], &c, 1); // Kdeinit is started.
  1742. close(d.initpipe[1]);
  1743. d.initpipe[1] = -1;
  1744. handle_requests(0);
  1745. return 0;
  1746. }