• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kinit
 

kinit

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

kinit

Skip menu "kinit"
  • Main Page
  • File List
  • Related Pages

kinit

Skip menu "kinit"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kinit by doxygen 1.8.3.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |