00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include <config.h>
00026
00027 #include <sys/types.h>
00028 #include <sys/time.h>
00029 #include <sys/stat.h>
00030 #include <sys/socket.h>
00031 #include <sys/un.h>
00032 #include <sys/wait.h>
00033 #ifdef HAVE_SYS_SELECT_H
00034 #include <sys/select.h>
00035 #endif
00036
00037 #include <errno.h>
00038 #include <fcntl.h>
00039 #include <setproctitle.h>
00040 #include <signal.h>
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #include <string.h>
00044 #include <ctype.h>
00045 #include <unistd.h>
00046 #include <locale.h>
00047
00048 #include <qstring.h>
00049 #include <qfile.h>
00050 #include <qdatetime.h>
00051 #include <qfileinfo.h>
00052 #include <qtextstream.h>
00053 #include <qregexp.h>
00054 #include <qfont.h>
00055 #include <kinstance.h>
00056 #include <kstandarddirs.h>
00057 #include <kglobal.h>
00058 #include <kconfig.h>
00059 #include <klibloader.h>
00060 #include <kapplication.h>
00061 #include <klocale.h>
00062
00063 #ifdef Q_OS_LINUX
00064 #include <sys/prctl.h>
00065 #ifndef PR_SET_NAME
00066 #define PR_SET_NAME 15
00067 #endif
00068 #endif
00069
00070 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00071 #include <kstartupinfo.h>
00072 #endif
00073
00074 #include <kdeversion.h>
00075
00076 #include "ltdl.h"
00077 #include "klauncher_cmds.h"
00078
00079
00080 #ifdef Q_WS_X11
00081
00082 #include <X11/Xlib.h>
00083 #include <X11/Xatom.h>
00084 #endif
00085
00086 #ifdef HAVE_DLFCN_H
00087 # include <dlfcn.h>
00088 #endif
00089
00090 #ifdef RTLD_GLOBAL
00091 # define LTDL_GLOBAL RTLD_GLOBAL
00092 #else
00093 # ifdef DL_GLOBAL
00094 # define LTDL_GLOBAL DL_GLOBAL
00095 # else
00096 # define LTDL_GLOBAL 0
00097 # endif
00098 #endif
00099
00100 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
00101 #include <X11/Xft/Xft.h>
00102 extern "C" FcBool XftInitFtLibrary (void);
00103 #include <fontconfig/fontconfig.h>
00104 #endif
00105
00106 extern char **environ;
00107
00108 extern int lt_dlopen_flag;
00109
00110 #ifdef Q_WS_X11
00111 static int X11fd = -1;
00112 static Display *X11display = 0;
00113 static int X11_startup_notify_fd = -1;
00114 static Display *X11_startup_notify_display = 0;
00115 #endif
00116 static const KInstance *s_instance = 0;
00117 #define MAX_SOCK_FILE 255
00118 static char sock_file[MAX_SOCK_FILE];
00119 static char sock_file_old[MAX_SOCK_FILE];
00120
00121
00122 #ifdef Q_WS_X11
00123 #define DISPLAY "DISPLAY"
00124 #elif defined(Q_WS_QWS)
00125 #define DISPLAY "QWS_DISPLAY"
00126 #elif defined(Q_WS_MACX)
00127 #define DISPLAY "MAC_DISPLAY"
00128 #elif defined(K_WS_QTONLY)
00129 #define DISPLAY "QT_DISPLAY"
00130 #else
00131 #error Use QT/X11 or QT/Embedded
00132 #endif
00133
00134
00135 static struct {
00136 int maxname;
00137 int fd[2];
00138 int launcher[2];
00139 int deadpipe[2];
00140 int initpipe[2];
00141 int wrapper;
00142 int wrapper_old;
00143 char result;
00144 int exit_status;
00145 pid_t fork;
00146 pid_t launcher_pid;
00147 pid_t my_pid;
00148 int n;
00149 lt_dlhandle handle;
00150 lt_ptr sym;
00151 char **argv;
00152 int (*func)(int, char *[]);
00153 int (*launcher_func)(int);
00154 bool debug_wait;
00155 int lt_dlopen_flag;
00156 QCString errorMsg;
00157 bool launcher_ok;
00158 bool suicide;
00159 } d;
00160
00161
00162 #ifdef Q_WS_X11
00163 extern "C" {
00164 int kdeinit_xio_errhandler( Display * );
00165 int kdeinit_x_errhandler( Display *, XErrorEvent *err );
00166 }
00167 #endif
00168
00169
00170 #include <kparts/plugin.h>
00171 extern "C" KParts::Plugin* _kinit_init_kparts() { return new KParts::Plugin(); }
00172
00173 #include <kio/authinfo.h>
00174 extern "C" KIO::AuthInfo* _kioslave_init_kio() { return new KIO::AuthInfo(); }
00175
00176
00177
00178
00179
00180 static void close_fds()
00181 {
00182 if (d.deadpipe[0] != -1)
00183 {
00184 close(d.deadpipe[0]);
00185 d.deadpipe[0] = -1;
00186 }
00187
00188 if (d.deadpipe[1] != -1)
00189 {
00190 close(d.deadpipe[1]);
00191 d.deadpipe[1] = -1;
00192 }
00193
00194 if (d.initpipe[0] != -1)
00195 {
00196 close(d.initpipe[0]);
00197 d.initpipe[0] = -1;
00198 }
00199
00200 if (d.initpipe[1] != -1)
00201 {
00202 close(d.initpipe[1]);
00203 d.initpipe[1] = -1;
00204 }
00205
00206 if (d.launcher_pid)
00207 {
00208 close(d.launcher[0]);
00209 d.launcher_pid = 0;
00210 }
00211 if (d.wrapper)
00212 {
00213 close(d.wrapper);
00214 d.wrapper = 0;
00215 }
00216 if (d.wrapper_old)
00217 {
00218 close(d.wrapper_old);
00219 d.wrapper_old = 0;
00220 }
00221 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00222
00223 if (X11fd >= 0)
00224 {
00225 close(X11fd);
00226 X11fd = -1;
00227 }
00228 if (X11_startup_notify_fd >= 0 && X11_startup_notify_fd != X11fd )
00229 {
00230 close(X11_startup_notify_fd);
00231 X11_startup_notify_fd = -1;
00232 }
00233 #endif
00234
00235 signal(SIGCHLD, SIG_DFL);
00236 signal(SIGPIPE, SIG_DFL);
00237 }
00238
00239 static void exitWithErrorMsg(const QString &errorMsg)
00240 {
00241 fprintf( stderr, "%s\n", errorMsg.local8Bit().data() );
00242 QCString utf8ErrorMsg = errorMsg.utf8();
00243 d.result = 3;
00244 write(d.fd[1], &d.result, 1);
00245 int l = utf8ErrorMsg.length();
00246 write(d.fd[1], &l, sizeof(int));
00247 write(d.fd[1], utf8ErrorMsg.data(), l);
00248 close(d.fd[1]);
00249 exit(255);
00250 }
00251
00252 static void setup_tty( const char* tty )
00253 {
00254 if( tty == NULL || *tty == '\0' )
00255 return;
00256 int fd = open( tty, O_WRONLY );
00257 if( fd < 0 )
00258 {
00259 perror( "kdeinit: couldn't open() tty" );
00260 return;
00261 }
00262 if( dup2( fd, STDOUT_FILENO ) < 0 )
00263 {
00264 perror( "kdeinit: couldn't dup2() tty" );
00265 close( fd );
00266 return;
00267 }
00268 if( dup2( fd, STDERR_FILENO ) < 0 )
00269 {
00270 perror( "kdeinit: couldn't dup2() tty" );
00271 close( fd );
00272 return;
00273 }
00274 close( fd );
00275 }
00276
00277
00278 static int get_current_desktop( Display* disp )
00279 {
00280 int desktop = 0;
00281 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00282
00283 Atom net_current_desktop = XInternAtom( disp, "_NET_CURRENT_DESKTOP", False );
00284 Atom type_ret;
00285 int format_ret;
00286 unsigned char *data_ret;
00287 unsigned long nitems_ret, unused;
00288 if( XGetWindowProperty( disp, DefaultRootWindow( disp ), net_current_desktop,
00289 0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret )
00290 == Success)
00291 {
00292 if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1)
00293 desktop = *((long *) data_ret) + 1;
00294 if (data_ret)
00295 XFree ((char*) data_ret);
00296 }
00297 #endif
00298 return desktop;
00299 }
00300
00301
00302 const char* get_env_var( const char* var, int envc, const char* envs )
00303 {
00304 if( envc > 0 )
00305 {
00306 const char* env_l = envs;
00307 int ln = strlen( var );
00308 for (int i = 0; i < envc; i++)
00309 {
00310 if( strncmp( env_l, var, ln ) == 0 )
00311 return env_l + ln;
00312 while(*env_l != 0) env_l++;
00313 env_l++;
00314 }
00315 }
00316 return NULL;
00317 }
00318
00319 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00320
00321 static void init_startup_info( KStartupInfoId& id, const char* bin,
00322 int envc, const char* envs )
00323 {
00324 const char* dpy = get_env_var( DISPLAY"=", envc, envs );
00325
00326
00327 X11_startup_notify_display = XOpenDisplay( dpy );
00328 if( X11_startup_notify_display == NULL )
00329 return;
00330 X11_startup_notify_fd = XConnectionNumber( X11_startup_notify_display );
00331 KStartupInfoData data;
00332 int desktop = get_current_desktop( X11_startup_notify_display );
00333 data.setDesktop( desktop );
00334 data.setBin( bin );
00335 KStartupInfo::sendChangeX( X11_startup_notify_display, id, data );
00336 XFlush( X11_startup_notify_display );
00337 }
00338
00339 static void complete_startup_info( KStartupInfoId& id, pid_t pid )
00340 {
00341 if( X11_startup_notify_display == NULL )
00342 return;
00343 if( pid == 0 )
00344 KStartupInfo::sendFinishX( X11_startup_notify_display, id );
00345 else
00346 {
00347 KStartupInfoData data;
00348 data.addPid( pid );
00349 data.setHostname();
00350 KStartupInfo::sendChangeX( X11_startup_notify_display, id, data );
00351 }
00352 XCloseDisplay( X11_startup_notify_display );
00353 X11_startup_notify_display = NULL;
00354 X11_startup_notify_fd = -1;
00355 }
00356 #endif
00357
00358 QCString execpath_avoid_loops( const QCString& exec, int envc, const char* envs, bool avoid_loops )
00359 {
00360 QStringList paths;
00361 if( envc > 0 )
00362 {
00363 const char* path = get_env_var( "PATH=", envc, envs );
00364 if( path != NULL )
00365 paths = QStringList::split( QRegExp( "[:\b]" ), path, true );
00366 }
00367 else
00368 paths = QStringList::split( QRegExp( "[:\b]" ), getenv( "PATH" ), true );
00369 QCString execpath = QFile::encodeName(
00370 s_instance->dirs()->findExe( exec, paths.join( QString( ":" ))));
00371 if( avoid_loops && !execpath.isEmpty())
00372 {
00373 int pos = execpath.findRev( '/' );
00374 QString bin_path = execpath.left( pos );
00375 for( QStringList::Iterator it = paths.begin();
00376 it != paths.end();
00377 ++it )
00378 if( ( *it ) == bin_path || ( *it ) == bin_path + '/' )
00379 {
00380 paths.remove( it );
00381 break;
00382 }
00383 execpath = QFile::encodeName(
00384 s_instance->dirs()->findExe( exec, paths.join( QString( ":" ))));
00385 }
00386 return execpath;
00387 }
00388
00389 #ifdef KDEINIT_OOM_PROTECT
00390 static int oom_pipe = -1;
00391
00392 static void oom_protect_sighandler( int ) {
00393 }
00394
00395 static void reset_oom_protect() {
00396 if( oom_pipe <= 0 )
00397 return;
00398 struct sigaction act, oldact;
00399 act.sa_handler = oom_protect_sighandler;
00400 act.sa_flags = 0;
00401 sigemptyset( &act.sa_mask );
00402 sigaction( SIGUSR1, &act, &oldact );
00403 sigset_t sigs, oldsigs;
00404 sigemptyset( &sigs );
00405 sigaddset( &sigs, SIGUSR1 );
00406 sigprocmask( SIG_BLOCK, &sigs, &oldsigs );
00407 pid_t pid = getpid();
00408 if( write( oom_pipe, &pid, sizeof( pid_t )) > 0 ) {
00409 sigsuspend( &oldsigs );
00410 }
00411 sigprocmask( SIG_SETMASK, &oldsigs, NULL );
00412 sigaction( SIGUSR1, &oldact, NULL );
00413 close( oom_pipe );
00414 oom_pipe = -1;
00415 }
00416 #else
00417 static void reset_oom_protect() {
00418 }
00419 #endif
00420
00421 static pid_t launch(int argc, const char *_name, const char *args,
00422 const char *cwd=0, int envc=0, const char *envs=0,
00423 bool reset_env = false,
00424 const char *tty=0, bool avoid_loops = false,
00425 const char* startup_id_str = "0" )
00426 {
00427 int launcher = 0;
00428 QCString lib;
00429 QCString name;
00430 QCString exec;
00431
00432 if (strcmp(_name, "klauncher") == 0) {
00433
00434
00435
00436 if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, d.launcher))
00437 {
00438 perror("kdeinit: socketpair() failed!\n");
00439 exit(255);
00440 }
00441 launcher = 1;
00442 }
00443
00444 QCString libpath;
00445 QCString execpath;
00446 if (_name[0] != '/')
00447 {
00448
00449 name = _name;
00450 lib = name + ".la";
00451 exec = name;
00452 libpath = QFile::encodeName(KLibLoader::findLibrary( lib, s_instance ));
00453 execpath = execpath_avoid_loops( exec, envc, envs, avoid_loops );
00454 }
00455 else
00456 {
00457 lib = _name;
00458 name = _name;
00459 name = name.mid( name.findRev('/') + 1);
00460 exec = _name;
00461 if (lib.right(3) == ".la")
00462 libpath = lib;
00463 else
00464 execpath = exec;
00465 }
00466 if (!args)
00467 {
00468 argc = 1;
00469 }
00470
00471 if (0 > pipe(d.fd))
00472 {
00473 perror("kdeinit: pipe() failed!\n");
00474 d.result = 3;
00475 d.errorMsg = i18n("Unable to start new process.\n"
00476 "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();
00477 close(d.fd[0]);
00478 close(d.fd[1]);
00479 d.fork = 0;
00480 return d.fork;
00481 }
00482
00483 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00484
00485 KStartupInfoId startup_id;
00486 startup_id.initId( startup_id_str );
00487 if( !startup_id.none())
00488 init_startup_info( startup_id, name, envc, envs );
00489 #endif
00490
00491 d.errorMsg = 0;
00492 d.fork = fork();
00493 switch(d.fork) {
00494 case -1:
00495 perror("kdeinit: fork() failed!\n");
00496 d.result = 3;
00497 d.errorMsg = i18n("Unable to create new process.\n"
00498 "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();
00499 close(d.fd[0]);
00500 close(d.fd[1]);
00501 d.fork = 0;
00502 break;
00503 case 0:
00505 close(d.fd[0]);
00506 close_fds();
00507 if (launcher)
00508 {
00509 if (d.fd[1] == LAUNCHER_FD)
00510 {
00511 d.fd[1] = dup(d.fd[1]);
00512 }
00513 if (d.launcher[1] != LAUNCHER_FD)
00514 {
00515 dup2( d.launcher[1], LAUNCHER_FD);
00516 close( d.launcher[1] );
00517 }
00518 close( d.launcher[0] );
00519 }
00520 reset_oom_protect();
00521
00522 if (cwd && *cwd)
00523 chdir(cwd);
00524
00525 if( reset_env )
00526 {
00527
00528 QStrList unset_envs;
00529 for( int tmp_env_count = 0;
00530 environ[tmp_env_count];
00531 tmp_env_count++)
00532 unset_envs.append( environ[ tmp_env_count ] );
00533 for( QStrListIterator it( unset_envs );
00534 it.current() != NULL ;
00535 ++it )
00536 {
00537 QCString tmp( it.current());
00538 int pos = tmp.find( '=' );
00539 if( pos >= 0 )
00540 unsetenv( tmp.left( pos ));
00541 }
00542 }
00543
00544 for (int i = 0; i < envc; i++)
00545 {
00546 putenv((char *)envs);
00547 while(*envs != 0) envs++;
00548 envs++;
00549 }
00550
00551 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00552
00553 if( startup_id.none())
00554 KStartupInfo::resetStartupEnv();
00555 else
00556 startup_id.setupStartupEnv();
00557 #endif
00558 {
00559 int r;
00560 QCString procTitle;
00561 d.argv = (char **) malloc(sizeof(char *) * (argc+1));
00562 d.argv[0] = (char *) _name;
00563 for (int i = 1; i < argc; i++)
00564 {
00565 d.argv[i] = (char *) args;
00566 procTitle += " ";
00567 procTitle += (char *) args;
00568 while(*args != 0) args++;
00569 args++;
00570 }
00571 d.argv[argc] = 0;
00572
00574 #ifdef Q_OS_LINUX
00575
00576 r = prctl(PR_SET_NAME, (unsigned long) name.data(), 0, 0, 0);
00577 if ( r == 0 )
00578 kdeinit_setproctitle( "%s [kdeinit]%s", name.data(), procTitle.data() ? procTitle.data() : "" );
00579 else
00580 kdeinit_setproctitle( "kdeinit: %s%s", name.data(), procTitle.data() ? procTitle.data() : "" );
00581 #else
00582 kdeinit_setproctitle( "kdeinit: %s%s", name.data(), procTitle.data() ? procTitle.data() : "" );
00583 #endif
00584 }
00585
00586 d.handle = 0;
00587 if (libpath.isEmpty() && execpath.isEmpty())
00588 {
00589 QString errorMsg = i18n("Could not find '%1' executable.").arg(QFile::decodeName(_name));
00590 exitWithErrorMsg(errorMsg);
00591 }
00592
00593 if ( getenv("KDE_IS_PRELINKED") && !execpath.isEmpty() && !launcher)
00594 libpath.truncate(0);
00595
00596 if ( !libpath.isEmpty() )
00597 {
00598 d.handle = lt_dlopen( QFile::encodeName(libpath) );
00599 if (!d.handle )
00600 {
00601 const char * ltdlError = lt_dlerror();
00602 if (execpath.isEmpty())
00603 {
00604
00605 QString errorMsg = i18n("Could not open library '%1'.\n%2").arg(QFile::decodeName(libpath))
00606 .arg(ltdlError ? QFile::decodeName(ltdlError) : i18n("Unknown error"));
00607 exitWithErrorMsg(errorMsg);
00608 }
00609 else
00610 {
00611
00612 fprintf(stderr, "Could not open library %s: %s\n", lib.data(), ltdlError != 0 ? ltdlError : "(null)" );
00613 }
00614 }
00615 }
00616 lt_dlopen_flag = d.lt_dlopen_flag;
00617 if (!d.handle )
00618 {
00619 d.result = 2;
00620 write(d.fd[1], &d.result, 1);
00621
00622
00623
00624 fcntl(d.fd[1], F_SETFD, FD_CLOEXEC);
00625
00626 setup_tty( tty );
00627
00628 execvp(execpath.data(), d.argv);
00629 d.result = 1;
00630 write(d.fd[1], &d.result, 1);
00631 close(d.fd[1]);
00632 exit(255);
00633 }
00634
00635 d.sym = lt_dlsym( d.handle, "kdeinitmain");
00636 if (!d.sym )
00637 {
00638 d.sym = lt_dlsym( d.handle, "kdemain" );
00639 if ( !d.sym )
00640 {
00641 #if ! KDE_IS_VERSION( 3, 90, 0 )
00642 d.sym = lt_dlsym( d.handle, "main");
00643 #endif
00644 if (!d.sym )
00645 {
00646 const char * ltdlError = lt_dlerror();
00647 fprintf(stderr, "Could not find kdemain: %s\n", ltdlError != 0 ? ltdlError : "(null)" );
00648 QString errorMsg = i18n("Could not find 'kdemain' in '%1'.\n%2").arg(libpath)
00649 .arg(ltdlError ? QFile::decodeName(ltdlError) : i18n("Unknown error"));
00650 exitWithErrorMsg(errorMsg);
00651 }
00652 }
00653 }
00654
00655 d.result = 0;
00656 write(d.fd[1], &d.result, 1);
00657 close(d.fd[1]);
00658
00659 d.func = (int (*)(int, char *[])) d.sym;
00660 if (d.debug_wait)
00661 {
00662 fprintf(stderr, "kdeinit: Suspending process\n"
00663 "kdeinit: 'gdb kdeinit %d' to debug\n"
00664 "kdeinit: 'kill -SIGCONT %d' to continue\n",
00665 getpid(), getpid());
00666 kill(getpid(), SIGSTOP);
00667 }
00668 else
00669 {
00670 setup_tty( tty );
00671 }
00672
00673 exit( d.func(argc, d.argv));
00674
00675 break;
00676 default:
00678 close(d.fd[1]);
00679 if (launcher)
00680 {
00681 close(d.launcher[1]);
00682 d.launcher_pid = d.fork;
00683 }
00684 bool exec = false;
00685 for(;;)
00686 {
00687 d.n = read(d.fd[0], &d.result, 1);
00688 if (d.n == 1)
00689 {
00690 if (d.result == 2)
00691 {
00692 #ifndef NDEBUG
00693 fprintf(stderr, "Could not load library! Trying exec....\n");
00694 #endif
00695 exec = true;
00696 continue;
00697 }
00698 if (d.result == 3)
00699 {
00700 int l = 0;
00701 d.n = read(d.fd[0], &l, sizeof(int));
00702 if (d.n == sizeof(int))
00703 {
00704 QCString tmp;
00705 tmp.resize(l+1);
00706 d.n = read(d.fd[0], tmp.data(), l);
00707 tmp[l] = 0;
00708 if (d.n == l)
00709 d.errorMsg = tmp;
00710 }
00711 }
00712
00713 break;
00714 }
00715 if (d.n == -1)
00716 {
00717 if (errno == ECHILD) {
00718 continue;
00719 }
00720 if (errno == EINTR || errno == EAGAIN) {
00721 continue;
00722 }
00723 }
00724 if (exec)
00725 {
00726 d.result = 0;
00727 break;
00728 }
00729 if (d.n == 0)
00730 {
00731 perror("kdeinit: Pipe closed unexpectedly");
00732 d.result = 1;
00733 break;
00734 }
00735 perror("kdeinit: Error reading from pipe");
00736 d.result = 1;
00737 break;
00738 }
00739 close(d.fd[0]);
00740 if (launcher && (d.result == 0))
00741 {
00742
00743 d.launcher_pid = d.fork;
00744 }
00745 }
00746 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00747
00748 if( !startup_id.none())
00749 {
00750 if( d.fork && d.result == 0 )
00751 complete_startup_info( startup_id, d.fork );
00752 else
00753 complete_startup_info( startup_id, 0 );
00754 }
00755 #endif
00756 return d.fork;
00757 }
00758
00759 static void sig_child_handler(int)
00760 {
00761
00762
00763
00764
00765
00766
00767
00768
00769 char c = 0;
00770 write(d.deadpipe[1], &c, 1);
00771 }
00772
00773 static void init_signals()
00774 {
00775 struct sigaction act;
00776 long options;
00777
00778 if (pipe(d.deadpipe) != 0)
00779 {
00780 perror("kdeinit: Aborting. Can't create pipe: ");
00781 exit(255);
00782 }
00783
00784 options = fcntl(d.deadpipe[0], F_GETFL);
00785 if (options == -1)
00786 {
00787 perror("kdeinit: Aborting. Can't make pipe non-blocking: ");
00788 exit(255);
00789 }
00790
00791 if (fcntl(d.deadpipe[0], F_SETFL, options | O_NONBLOCK) == -1)
00792 {
00793 perror("kdeinit: Aborting. Can't make pipe non-blocking: ");
00794 exit(255);
00795 }
00796
00797
00798
00799
00800
00801
00802 act.sa_handler=sig_child_handler;
00803 sigemptyset(&(act.sa_mask));
00804 sigaddset(&(act.sa_mask), SIGCHLD);
00805 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
00806 act.sa_flags = SA_NOCLDSTOP;
00807
00808
00809
00810
00811 #ifdef SA_RESTART
00812 act.sa_flags |= SA_RESTART;
00813 #endif
00814 sigaction( SIGCHLD, &act, 0L);
00815
00816 act.sa_handler=SIG_IGN;
00817 sigemptyset(&(act.sa_mask));
00818 sigaddset(&(act.sa_mask), SIGPIPE);
00819 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
00820 act.sa_flags = 0;
00821 sigaction( SIGPIPE, &act, 0L);
00822 }
00823
00824 static void init_kdeinit_socket()
00825 {
00826 struct sockaddr_un sa;
00827 struct sockaddr_un sa_old;
00828 kde_socklen_t socklen;
00829 long options;
00830 const char *home_dir = getenv("HOME");
00831 int max_tries = 10;
00832 if (!home_dir || !home_dir[0])
00833 {
00834 fprintf(stderr, "kdeinit: Aborting. $HOME not set!");
00835 exit(255);
00836 }
00837 chdir(home_dir);
00838
00839 {
00840 QCString path = home_dir;
00841 QCString readOnly = getenv("KDE_HOME_READONLY");
00842 if (access(path.data(), R_OK|W_OK))
00843 {
00844 if (errno == ENOENT)
00845 {
00846 fprintf(stderr, "kdeinit: Aborting. $HOME directory (%s) does not exist.\n", path.data());
00847 exit(255);
00848 }
00849 else if (readOnly.isEmpty())
00850 {
00851 fprintf(stderr, "kdeinit: Aborting. No write access to $HOME directory (%s).\n", path.data());
00852 exit(255);
00853 }
00854 }
00855 path = getenv("ICEAUTHORITY");
00856 if (path.isEmpty())
00857 {
00858 path = home_dir;
00859 path += "/.ICEauthority";
00860 }
00861 if (access(path.data(), R_OK|W_OK) && (errno != ENOENT))
00862 {
00863 fprintf(stderr, "kdeinit: Aborting. No write access to '%s'.\n", path.data());
00864 exit(255);
00865 }
00866 }
00867
00872 if (access(sock_file, W_OK) == 0)
00873 {
00874 int s;
00875 struct sockaddr_un server;
00876
00877
00878
00879
00880
00881 s = socket(PF_UNIX, SOCK_STREAM, 0);
00882 if (s < 0)
00883 {
00884 perror("socket() failed: ");
00885 exit(255);
00886 }
00887 server.sun_family = AF_UNIX;
00888 strcpy(server.sun_path, sock_file);
00889 socklen = sizeof(server);
00890
00891 if(connect(s, (struct sockaddr *)&server, socklen) == 0)
00892 {
00893 fprintf(stderr, "kdeinit: Shutting down running client.\n");
00894 klauncher_header request_header;
00895 request_header.cmd = LAUNCHER_TERMINATE_KDEINIT;
00896 request_header.arg_length = 0;
00897 write(s, &request_header, sizeof(request_header));
00898 sleep(1);
00899 }
00900 close(s);
00901 }
00902
00904 unlink(sock_file);
00905 unlink(sock_file_old);
00906
00908 d.wrapper = socket(PF_UNIX, SOCK_STREAM, 0);
00909 if (d.wrapper < 0)
00910 {
00911 perror("kdeinit: Aborting. socket() failed: ");
00912 exit(255);
00913 }
00914
00915 options = fcntl(d.wrapper, F_GETFL);
00916 if (options == -1)
00917 {
00918 perror("kdeinit: Aborting. Can't make socket non-blocking: ");
00919 close(d.wrapper);
00920 exit(255);
00921 }
00922
00923 if (fcntl(d.wrapper, F_SETFL, options | O_NONBLOCK) == -1)
00924 {
00925 perror("kdeinit: Aborting. Can't make socket non-blocking: ");
00926 close(d.wrapper);
00927 exit(255);
00928 }
00929
00930 while (1) {
00932 socklen = sizeof(sa);
00933 memset(&sa, 0, socklen);
00934 sa.sun_family = AF_UNIX;
00935 strcpy(sa.sun_path, sock_file);
00936 if(bind(d.wrapper, (struct sockaddr *)&sa, socklen) != 0)
00937 {
00938 if (max_tries == 0) {
00939 perror("kdeinit: Aborting. bind() failed: ");
00940 fprintf(stderr, "Could not bind to socket '%s'\n", sock_file);
00941 close(d.wrapper);
00942 exit(255);
00943 }
00944 max_tries--;
00945 } else
00946 break;
00947 }
00948
00950 if (chmod(sock_file, 0600) != 0)
00951 {
00952 perror("kdeinit: Aborting. Can't set permissions on socket: ");
00953 fprintf(stderr, "Wrong permissions of socket '%s'\n", sock_file);
00954 unlink(sock_file);
00955 close(d.wrapper);
00956 exit(255);
00957 }
00958
00959 if(listen(d.wrapper, SOMAXCONN) < 0)
00960 {
00961 perror("kdeinit: Aborting. listen() failed: ");
00962 unlink(sock_file);
00963 close(d.wrapper);
00964 exit(255);
00965 }
00966
00968 d.wrapper_old = socket(PF_UNIX, SOCK_STREAM, 0);
00969 if (d.wrapper_old < 0)
00970 {
00971
00972 return;
00973 }
00974
00975 options = fcntl(d.wrapper_old, F_GETFL);
00976 if (options == -1)
00977 {
00978
00979 close(d.wrapper_old);
00980 d.wrapper_old = 0;
00981 return;
00982 }
00983
00984 if (fcntl(d.wrapper_old, F_SETFL, options | O_NONBLOCK) == -1)
00985 {
00986
00987 close(d.wrapper_old);
00988 d.wrapper_old = 0;
00989 return;
00990 }
00991
00992 max_tries = 10;
00993 while (1) {
00995 socklen = sizeof(sa_old);
00996 memset(&sa_old, 0, socklen);
00997 sa_old.sun_family = AF_UNIX;
00998 strcpy(sa_old.sun_path, sock_file_old);
00999 if(bind(d.wrapper_old, (struct sockaddr *)&sa_old, socklen) != 0)
01000 {
01001 if (max_tries == 0) {
01002
01003 fprintf(stderr, "Could not bind to socket '%s'\n", sock_file_old);
01004 close(d.wrapper_old);
01005 d.wrapper_old = 0;
01006 return;
01007 }
01008 max_tries--;
01009 } else
01010 break;
01011 }
01012
01014 if (chmod(sock_file_old, 0600) != 0)
01015 {
01016 fprintf(stderr, "Wrong permissions of socket '%s'\n", sock_file);
01017 unlink(sock_file_old);
01018 close(d.wrapper_old);
01019 d.wrapper_old = 0;
01020 return;
01021 }
01022
01023 if(listen(d.wrapper_old, SOMAXCONN) < 0)
01024 {
01025
01026 unlink(sock_file_old);
01027 close(d.wrapper_old);
01028 d.wrapper_old = 0;
01029 }
01030 }
01031
01032
01033
01034
01035
01036 static int read_socket(int sock, char *buffer, int len)
01037 {
01038 ssize_t result;
01039 int bytes_left = len;
01040 while ( bytes_left > 0)
01041 {
01042 result = read(sock, buffer, bytes_left);
01043 if (result > 0)
01044 {
01045 buffer += result;
01046 bytes_left -= result;
01047 }
01048 else if (result == 0)
01049 return -1;
01050 else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
01051 return -1;
01052 }
01053 return 0;
01054 }
01055
01056 static void WaitPid( pid_t waitForPid)
01057 {
01058 int result;
01059 while(1)
01060 {
01061 result = waitpid(waitForPid, &d.exit_status, 0);
01062 if ((result == -1) && (errno == ECHILD))
01063 return;
01064 }
01065 }
01066
01067 static void launcher_died()
01068 {
01069 if (!d.launcher_ok)
01070 {
01071
01072 fprintf(stderr, "kdeinit: Communication error with launcher. Exiting!\n");
01073 ::exit(255);
01074 return;
01075 }
01076
01077
01078 #ifndef NDEBUG
01079 fprintf(stderr, "kdeinit: KLauncher died unexpectedly.\n");
01080 #endif
01081
01082 if (d.launcher_pid)
01083 {
01084 kill(d.launcher_pid, SIGKILL);
01085 sleep(1);
01086 }
01087
01088 d.launcher_ok = false;
01089 d.launcher_pid = 0;
01090 close(d.launcher[0]);
01091 d.launcher[0] = -1;
01092
01093 pid_t pid = launch( 1, "klauncher", 0 );
01094 #ifndef NDEBUG
01095 fprintf(stderr, "kdeinit: Relaunching KLauncher, pid = %ld result = %d\n", (long) pid, d.result);
01096 #endif
01097 }
01098
01099 static void handle_launcher_request(int sock = -1)
01100 {
01101 bool launcher = false;
01102 if (sock < 0)
01103 {
01104 sock = d.launcher[0];
01105 launcher = true;
01106 }
01107
01108 klauncher_header request_header;
01109 char *request_data = 0L;
01110 int result = read_socket(sock, (char *) &request_header, sizeof(request_header));
01111 if (result != 0)
01112 {
01113 if (launcher)
01114 launcher_died();
01115 return;
01116 }
01117
01118 if ( request_header.arg_length != 0 )
01119 {
01120 request_data = (char *) malloc(request_header.arg_length);
01121
01122 result = read_socket(sock, request_data, request_header.arg_length);
01123 if (result != 0)
01124 {
01125 if (launcher)
01126 launcher_died();
01127 free(request_data);
01128 return;
01129 }
01130 }
01131
01132 if (request_header.cmd == LAUNCHER_OK)
01133 {
01134 d.launcher_ok = true;
01135 }
01136 else if (request_header.arg_length &&
01137 ((request_header.cmd == LAUNCHER_EXEC) ||
01138 (request_header.cmd == LAUNCHER_EXT_EXEC) ||
01139 (request_header.cmd == LAUNCHER_SHELL ) ||
01140 (request_header.cmd == LAUNCHER_KWRAPPER) ||
01141 (request_header.cmd == LAUNCHER_EXEC_NEW)))
01142 {
01143 pid_t pid;
01144 klauncher_header response_header;
01145 long response_data;
01146 long l;
01147 memcpy( &l, request_data, sizeof( long ));
01148 int argc = l;
01149 const char *name = request_data + sizeof(long);
01150 const char *args = name + strlen(name) + 1;
01151 const char *cwd = 0;
01152 int envc = 0;
01153 const char *envs = 0;
01154 const char *tty = 0;
01155 int avoid_loops = 0;
01156 const char *startup_id_str = "0";
01157
01158 #ifndef NDEBUG
01159 fprintf(stderr, "kdeinit: Got %s '%s' from %s.\n",
01160 (request_header.cmd == LAUNCHER_EXEC ? "EXEC" :
01161 (request_header.cmd == LAUNCHER_EXT_EXEC ? "EXT_EXEC" :
01162 (request_header.cmd == LAUNCHER_EXEC_NEW ? "EXEC_NEW" :
01163 (request_header.cmd == LAUNCHER_SHELL ? "SHELL" : "KWRAPPER" )))),
01164 name, launcher ? "launcher" : "socket" );
01165 #endif
01166
01167 const char *arg_n = args;
01168 for(int i = 1; i < argc; i++)
01169 {
01170 arg_n = arg_n + strlen(arg_n) + 1;
01171 }
01172
01173 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER )
01174 {
01175
01176 cwd = arg_n; arg_n += strlen(cwd) + 1;
01177 }
01178 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
01179 || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
01180 {
01181 memcpy( &l, arg_n, sizeof( long ));
01182 envc = l;
01183 arg_n += sizeof(long);
01184 envs = arg_n;
01185 for(int i = 0; i < envc; i++)
01186 {
01187 arg_n = arg_n + strlen(arg_n) + 1;
01188 }
01189 if( request_header.cmd == LAUNCHER_KWRAPPER )
01190 {
01191 tty = arg_n;
01192 arg_n += strlen( tty ) + 1;
01193 }
01194 }
01195
01196 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
01197 || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
01198 {
01199 memcpy( &l, arg_n, sizeof( long ));
01200 avoid_loops = l;
01201 arg_n += sizeof( long );
01202 }
01203
01204 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
01205 || request_header.cmd == LAUNCHER_EXT_EXEC )
01206 {
01207 startup_id_str = arg_n;
01208 arg_n += strlen( startup_id_str ) + 1;
01209 }
01210
01211 if ((request_header.arg_length > (arg_n - request_data)) &&
01212 (request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW ))
01213 {
01214
01215 cwd = arg_n; arg_n += strlen(cwd) + 1;
01216 }
01217
01218 if ((arg_n - request_data) != request_header.arg_length)
01219 {
01220 #ifndef NDEBUG
01221 fprintf(stderr, "kdeinit: EXEC request has invalid format.\n");
01222 #endif
01223 free(request_data);
01224 d.debug_wait = false;
01225 return;
01226 }
01227
01228
01229 QCString olddisplay = getenv(DISPLAY);
01230 QCString kdedisplay = getenv("KDE_DISPLAY");
01231 bool reset_display = (! olddisplay.isEmpty() &&
01232 ! kdedisplay.isEmpty() &&
01233 olddisplay != kdedisplay);
01234
01235 if (reset_display)
01236 setenv(DISPLAY, kdedisplay, true);
01237
01238 pid = launch( argc, name, args, cwd, envc, envs,
01239 request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER,
01240 tty, avoid_loops, startup_id_str );
01241
01242 if (reset_display) {
01243 unsetenv("KDE_DISPLAY");
01244 setenv(DISPLAY, olddisplay, true);
01245 }
01246
01247 if (pid && (d.result == 0))
01248 {
01249 response_header.cmd = LAUNCHER_OK;
01250 response_header.arg_length = sizeof(response_data);
01251 response_data = pid;
01252 write(sock, &response_header, sizeof(response_header));
01253 write(sock, &response_data, response_header.arg_length);
01254 }
01255 else
01256 {
01257 int l = d.errorMsg.length();
01258 if (l) l++;
01259 response_header.cmd = LAUNCHER_ERROR;
01260 response_header.arg_length = l;
01261 write(sock, &response_header, sizeof(response_header));
01262 if (l)
01263 write(sock, d.errorMsg.data(), l);
01264 }
01265 d.debug_wait = false;
01266 }
01267 else if (request_header.arg_length && request_header.cmd == LAUNCHER_SETENV)
01268 {
01269 const char *env_name;
01270 const char *env_value;
01271 env_name = request_data;
01272 env_value = env_name + strlen(env_name) + 1;
01273
01274 #ifndef NDEBUG
01275 if (launcher)
01276 fprintf(stderr, "kdeinit: Got SETENV '%s=%s' from klauncher.\n", env_name, env_value);
01277 else
01278 fprintf(stderr, "kdeinit: Got SETENV '%s=%s' from socket.\n", env_name, env_value);
01279 #endif
01280
01281 if ( request_header.arg_length !=
01282 (int) (strlen(env_name) + strlen(env_value) + 2))
01283 {
01284 #ifndef NDEBUG
01285 fprintf(stderr, "kdeinit: SETENV request has invalid format.\n");
01286 #endif
01287 free(request_data);
01288 return;
01289 }
01290 setenv( env_name, env_value, 1);
01291 }
01292 else if (request_header.cmd == LAUNCHER_TERMINATE_KDE)
01293 {
01294 #ifndef NDEBUG
01295 fprintf(stderr,"kdeinit: terminate KDE.\n");
01296 #endif
01297 #ifdef Q_WS_X11
01298 kdeinit_xio_errhandler( 0L );
01299 #endif
01300 }
01301 else if (request_header.cmd == LAUNCHER_TERMINATE_KDEINIT)
01302 {
01303 #ifndef NDEBUG
01304 fprintf(stderr,"kdeinit: Killing kdeinit/klauncher.\n");
01305 #endif
01306 if (d.launcher_pid)
01307 kill(d.launcher_pid, SIGTERM);
01308 if (d.my_pid)
01309 kill(d.my_pid, SIGTERM);
01310 }
01311 else if (request_header.cmd == LAUNCHER_DEBUG_WAIT)
01312 {
01313 #ifndef NDEBUG
01314 fprintf(stderr,"kdeinit: Debug wait activated.\n");
01315 #endif
01316 d.debug_wait = true;
01317 }
01318 if (request_data)
01319 free(request_data);
01320 }
01321
01322 static void handle_requests(pid_t waitForPid)
01323 {
01324 int max_sock = d.wrapper;
01325 if (d.wrapper_old > max_sock)
01326 max_sock = d.wrapper_old;
01327 if (d.launcher_pid && (d.launcher[0] > max_sock))
01328 max_sock = d.launcher[0];
01329 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01330
01331 if (X11fd > max_sock)
01332 max_sock = X11fd;
01333 #endif
01334 max_sock++;
01335
01336 while(1)
01337 {
01338 fd_set rd_set;
01339 fd_set wr_set;
01340 fd_set e_set;
01341 int result;
01342 pid_t exit_pid;
01343 char c;
01344
01345
01346 while( read(d.deadpipe[0], &c, 1) == 1);
01347
01348
01349 do {
01350 exit_pid = waitpid(-1, 0, WNOHANG);
01351 if (exit_pid > 0)
01352 {
01353 #ifndef NDEBUG
01354 fprintf(stderr, "kdeinit: PID %ld terminated.\n", (long) exit_pid);
01355 #endif
01356 if (waitForPid && (exit_pid == waitForPid))
01357 return;
01358
01359 if (d.launcher_pid)
01360 {
01361
01362 klauncher_header request_header;
01363 long request_data[2];
01364 request_header.cmd = LAUNCHER_DIED;
01365 request_header.arg_length = sizeof(long) * 2;
01366 request_data[0] = exit_pid;
01367 request_data[1] = 0;
01368 write(d.launcher[0], &request_header, sizeof(request_header));
01369 write(d.launcher[0], request_data, request_header.arg_length);
01370 }
01371 }
01372 }
01373 while( exit_pid > 0);
01374
01375 FD_ZERO(&rd_set);
01376 FD_ZERO(&wr_set);
01377 FD_ZERO(&e_set);
01378
01379 if (d.launcher_pid)
01380 {
01381 FD_SET(d.launcher[0], &rd_set);
01382 }
01383 FD_SET(d.wrapper, &rd_set);
01384 if (d.wrapper_old)
01385 {
01386 FD_SET(d.wrapper_old, &rd_set);
01387 }
01388 FD_SET(d.deadpipe[0], &rd_set);
01389 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01390
01391 if(X11fd >= 0) FD_SET(X11fd, &rd_set);
01392 #endif
01393
01394 result = select(max_sock, &rd_set, &wr_set, &e_set, 0);
01395
01396
01397 if ((result > 0) && (FD_ISSET(d.wrapper, &rd_set)))
01398 {
01399 struct sockaddr_un client;
01400 kde_socklen_t sClient = sizeof(client);
01401 int sock = accept(d.wrapper, (struct sockaddr *)&client, &sClient);
01402 if (sock >= 0)
01403 {
01404 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
01405 if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
01406 FcInitReinitialize();
01407 #endif
01408 if (fork() == 0)
01409 {
01410 close_fds();
01411 reset_oom_protect();
01412 handle_launcher_request(sock);
01413 exit(255);
01414 }
01415 close(sock);
01416 }
01417 }
01418 if ((result > 0) && (FD_ISSET(d.wrapper_old, &rd_set)))
01419 {
01420 struct sockaddr_un client;
01421 kde_socklen_t sClient = sizeof(client);
01422 int sock = accept(d.wrapper_old, (struct sockaddr *)&client, &sClient);
01423 if (sock >= 0)
01424 {
01425 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
01426 if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
01427 FcInitReinitialize();
01428 #endif
01429 if (fork() == 0)
01430 {
01431 close_fds();
01432 reset_oom_protect();
01433 handle_launcher_request(sock);
01434 exit(255);
01435 }
01436 close(sock);
01437 }
01438 }
01439
01440
01441 if ((result > 0) && (d.launcher_pid) && (FD_ISSET(d.launcher[0], &rd_set)))
01442 {
01443 handle_launcher_request();
01444 if (waitForPid == d.launcher_pid)
01445 return;
01446 }
01447
01448
01449 #ifdef Q_WS_X11
01450
01451 if((result > 0) && (X11fd >= 0))
01452 {
01453 if(FD_ISSET(X11fd,&rd_set))
01454 {
01455 if (X11display != 0) {
01456 XEvent event_return;
01457 while (XPending(X11display))
01458 XNextEvent(X11display, &event_return);
01459 }
01460 }
01461 }
01462 #endif
01463 }
01464 }
01465
01466 static void kdeinit_library_path()
01467 {
01468 QStringList ltdl_library_path =
01469 QStringList::split(':', QFile::decodeName(getenv("LTDL_LIBRARY_PATH")));
01470 QStringList ld_library_path =
01471 QStringList::split(':', QFile::decodeName(getenv("LD_LIBRARY_PATH")));
01472
01473 QCString extra_path;
01474 QStringList candidates = s_instance->dirs()->resourceDirs("lib");
01475 for (QStringList::ConstIterator it = candidates.begin();
01476 it != candidates.end();
01477 it++)
01478 {
01479 QString d = *it;
01480 if (ltdl_library_path.contains(d))
01481 continue;
01482 if (ld_library_path.contains(d))
01483 continue;
01484 if (d[d.length()-1] == '/')
01485 {
01486 d.truncate(d.length()-1);
01487 if (ltdl_library_path.contains(d))
01488 continue;
01489 if (ld_library_path.contains(d))
01490 continue;
01491 }
01492 if ((d == "/lib") || (d == "/usr/lib"))
01493 continue;
01494
01495 QCString dir = QFile::encodeName(d);
01496
01497 if (access(dir, R_OK))
01498 continue;
01499
01500 if ( !extra_path.isEmpty())
01501 extra_path += ":";
01502 extra_path += dir;
01503 }
01504
01505 if (lt_dlinit())
01506 {
01507 const char * ltdlError = lt_dlerror();
01508 fprintf(stderr, "can't initialize dynamic loading: %s\n", ltdlError != 0 ? ltdlError : "(null)" );
01509 }
01510 if (!extra_path.isEmpty())
01511 lt_dlsetsearchpath(extra_path.data());
01512
01513 QCString display = getenv(DISPLAY);
01514 if (display.isEmpty())
01515 {
01516 fprintf(stderr, "kdeinit: Aborting. $"DISPLAY" is not set.\n");
01517 exit(255);
01518 }
01519 int i;
01520 if((i = display.findRev('.')) > display.findRev(':') && i >= 0)
01521 display.truncate(i);
01522
01523 QCString socketName = QFile::encodeName(locateLocal("socket", QString("kdeinit-%1").arg(display), s_instance));
01524 if (socketName.length() >= MAX_SOCK_FILE)
01525 {
01526 fprintf(stderr, "kdeinit: Aborting. Socket name will be too long:\n");
01527 fprintf(stderr, " '%s'\n", socketName.data());
01528 exit(255);
01529 }
01530 strcpy(sock_file_old, socketName.data());
01531
01532 display.replace(":","_");
01533 socketName = QFile::encodeName(locateLocal("socket", QString("kdeinit_%1").arg(display), s_instance));
01534 if (socketName.length() >= MAX_SOCK_FILE)
01535 {
01536 fprintf(stderr, "kdeinit: Aborting. Socket name will be too long:\n");
01537 fprintf(stderr, " '%s'\n", socketName.data());
01538 exit(255);
01539 }
01540 strcpy(sock_file, socketName.data());
01541 }
01542
01543 int kdeinit_xio_errhandler( Display *disp )
01544 {
01545
01546
01547 if ( disp )
01548 qWarning( "kdeinit: Fatal IO error: client killed" );
01549
01550 if (sock_file[0])
01551 {
01553 unlink(sock_file);
01554 }
01555 if (sock_file_old[0])
01556 {
01558 unlink(sock_file_old);
01559 }
01560
01561
01562 if (d.suicide)
01563 {
01564 if (d.launcher_pid)
01565 kill(d.launcher_pid, SIGTERM);
01566 exit( 0 );
01567 }
01568
01569 if ( disp )
01570 qWarning( "kdeinit: sending SIGHUP to children." );
01571
01572
01573 signal(SIGHUP, SIG_IGN);
01574 kill(0, SIGHUP);
01575
01576 sleep(2);
01577
01578 if ( disp )
01579 qWarning( "kdeinit: sending SIGTERM to children." );
01580
01581
01582 signal(SIGTERM, SIG_IGN);
01583 kill(0, SIGTERM);
01584
01585 if ( disp )
01586 qWarning( "kdeinit: Exit." );
01587
01588 exit( 0 );
01589 return 0;
01590 }
01591
01592 #ifdef Q_WS_X11
01593 int kdeinit_x_errhandler( Display *dpy, XErrorEvent *err )
01594 {
01595 #ifndef NDEBUG
01596 char errstr[256];
01597
01598 XGetErrorText( dpy, err->error_code, errstr, 256 );
01599 fprintf(stderr, "kdeinit: KDE detected X Error: %s %d\n"
01600 " Major opcode: %d\n"
01601 " Minor opcode: %d\n"
01602 " Resource id: 0x%lx\n",
01603 errstr, err->error_code, err->request_code, err->minor_code, err->resourceid );
01604 #else
01605 Q_UNUSED(dpy);
01606 Q_UNUSED(err);
01607 #endif
01608 return 0;
01609 }
01610 #endif
01611
01612
01613 #ifdef Q_WS_X11
01614
01615
01616 static void setupX()
01617 {
01618 XSetIOErrorHandler(kdeinit_xio_errhandler);
01619 XSetErrorHandler(kdeinit_x_errhandler);
01620 }
01621
01622
01623 static int initXconnection()
01624 {
01625 X11display = XOpenDisplay(NULL);
01626 if ( X11display != 0 ) {
01627 XCreateSimpleWindow(X11display, DefaultRootWindow(X11display), 0,0,1,1, \
01628 0,
01629 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)),
01630 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)) );
01631 #ifndef NDEBUG
01632 fprintf(stderr, "kdeinit: opened connection to %s\n", DisplayString(X11display));
01633 #endif
01634 int fd = XConnectionNumber( X11display );
01635 int on = 1;
01636 (void) setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, (int) sizeof(on));
01637 return fd;
01638 } else
01639 fprintf(stderr, "kdeinit: Can't connect to the X Server.\n" \
01640 "kdeinit: Might not terminate at end of session.\n");
01641
01642 return -1;
01643 }
01644 #endif
01645
01646 #ifdef __KCC
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666 extern "C" void _main(void);
01667 extern "C" void __call_ctors__Fv(void);
01668 static int main_called = 0;
01669 void _main(void)
01670 {
01671 if (main_called)
01672 return;
01673 main_called = 1;
01674 __call_ctors__Fv ();
01675 }
01676 #endif
01677
01678 static void secondary_child_handler(int)
01679 {
01680 waitpid(-1, 0, WNOHANG);
01681 }
01682
01683 int main(int argc, char **argv, char **envp)
01684 {
01685 int i;
01686 pid_t pid;
01687 int launch_dcop = 1;
01688 int launch_klauncher = 1;
01689 int launch_kded = 1;
01690 int keep_running = 1;
01691 int new_startup = 0;
01692 d.suicide = false;
01693
01695 char **safe_argv = (char **) malloc( sizeof(char *) * argc);
01696 for(i = 0; i < argc; i++)
01697 {
01698 safe_argv[i] = strcpy((char*)malloc(strlen(argv[i])+1), argv[i]);
01699 if (strcmp(safe_argv[i], "--no-dcop") == 0)
01700 launch_dcop = 0;
01701 if (strcmp(safe_argv[i], "--no-klauncher") == 0)
01702 launch_klauncher = 0;
01703 if (strcmp(safe_argv[i], "--no-kded") == 0)
01704 launch_kded = 0;
01705 if (strcmp(safe_argv[i], "--suicide") == 0)
01706 d.suicide = true;
01707 if (strcmp(safe_argv[i], "--exit") == 0)
01708 keep_running = 0;
01709 if (strcmp(safe_argv[i], "--new-startup") == 0)
01710 new_startup = 1;
01711 #ifdef KDEINIT_OOM_PROTECT
01712 if (strcmp(safe_argv[i], "--oom-pipe") == 0 && i+1<argc)
01713 oom_pipe = atol(argv[i+1]);
01714 #endif
01715 if (strcmp(safe_argv[i], "--help") == 0)
01716 {
01717 printf("Usage: kdeinit [options]\n");
01718
01719
01720 printf(" --no-kded Do not start kded\n");
01721 printf(" --suicide Terminate when no KDE applications are left running\n");
01722
01723 exit(0);
01724 }
01725 }
01726
01727 pipe(d.initpipe);
01728
01729
01730
01731
01732 signal( SIGCHLD, secondary_child_handler);
01733 if (fork() > 0)
01734 {
01735 close(d.initpipe[1]);
01736 d.initpipe[1] = -1;
01737
01738 char c;
01739 while( read(d.initpipe[0], &c, 1) < 0);
01740
01741 close(d.initpipe[0]);
01742 d.initpipe[0] = -1;
01743 return 0;
01744 }
01745 close(d.initpipe[0]);
01746 d.initpipe[0] = -1;
01747 d.my_pid = getpid();
01748
01750 if(keep_running)
01751 setsid();
01752
01754 s_instance = new KInstance("kdeinit");
01755
01757 kdeinit_initsetproctitle(argc, argv, envp);
01758 kdeinit_library_path();
01759
01760
01761
01762 KGlobal::_instance = 0L;
01763
01764 unsetenv("LD_BIND_NOW");
01765 unsetenv("DYLD_BIND_AT_LAUNCH");
01766 KApplication::loadedByKdeinit = true;
01767
01768 d.maxname = strlen(argv[0]);
01769 d.launcher_pid = 0;
01770 d.wrapper = 0;
01771 d.wrapper_old = 0;
01772 d.debug_wait = false;
01773 d.launcher_ok = false;
01774 d.lt_dlopen_flag = lt_dlopen_flag;
01775 lt_dlopen_flag |= LTDL_GLOBAL;
01776 init_signals();
01777 #ifdef Q_WS_X11
01778 setupX();
01779 #endif
01780
01781 if (keep_running)
01782 {
01783
01784
01785
01786
01787 init_kdeinit_socket();
01788 }
01789
01790 if (launch_dcop)
01791 {
01792 if (d.suicide)
01793 pid = launch( 3, "dcopserver", "--nosid\0--suicide" );
01794 else
01795 pid = launch( 2, "dcopserver", "--nosid" );
01796 #ifndef NDEBUG
01797 fprintf(stderr, "kdeinit: Launched DCOPServer, pid = %ld result = %d\n", (long) pid, d.result);
01798 #endif
01799 WaitPid(pid);
01800 if (!WIFEXITED(d.exit_status) || (WEXITSTATUS(d.exit_status) != 0))
01801 {
01802 fprintf(stderr, "kdeinit: DCOPServer could not be started, aborting.\n");
01803 exit(1);
01804 }
01805 }
01806 #ifndef __CYGWIN__
01807 if (!d.suicide && !getenv("KDE_IS_PRELINKED"))
01808 {
01809 QString konq = locate("lib", "libkonq.la", s_instance);
01810 if (!konq.isEmpty())
01811 (void) lt_dlopen(QFile::encodeName(konq).data());
01812 }
01813 #endif
01814 if (launch_klauncher)
01815 {
01816 if( new_startup )
01817 pid = launch( 2, "klauncher", "--new-startup" );
01818 else
01819 pid = launch( 1, "klauncher", 0 );
01820 #ifndef NDEBUG
01821 fprintf(stderr, "kdeinit: Launched KLauncher, pid = %ld result = %d\n", (long) pid, d.result);
01822 #endif
01823 handle_requests(pid);
01824 }
01825
01826 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01827
01828 X11fd = initXconnection();
01829 #endif
01830
01831 {
01832 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
01833 if( FcGetVersion() < 20390 )
01834 {
01835 XftInit(0);
01836 XftInitFtLibrary();
01837 }
01838 #endif
01839 QFont::initialize();
01840 setlocale (LC_ALL, "");
01841 setlocale (LC_NUMERIC, "C");
01842 #ifdef Q_WS_X11
01843 if (XSupportsLocale ())
01844 {
01845
01846
01847 XOpenIM (X11display, 0, 0, 0);
01848 }
01849 #endif
01850 }
01851
01852 if (launch_kded)
01853 {
01854 if( new_startup )
01855 pid = launch( 2, "kded", "--new-startup" );
01856 else
01857 pid = launch( 1, "kded", 0 );
01858 #ifndef NDEBUG
01859 fprintf(stderr, "kdeinit: Launched KDED, pid = %ld result = %d\n", (long) pid, d.result);
01860 #endif
01861 handle_requests(pid);
01862 }
01863
01864 for(i = 1; i < argc; i++)
01865 {
01866 if (safe_argv[i][0] == '+')
01867 {
01868 pid = launch( 1, safe_argv[i]+1, 0);
01869 #ifndef NDEBUG
01870 fprintf(stderr, "kdeinit: Launched '%s', pid = %ld result = %d\n", safe_argv[i]+1, (long) pid, d.result);
01871 #endif
01872 handle_requests(pid);
01873 }
01874 else if (safe_argv[i][0] == '-'
01875 #ifdef KDEINIT_OOM_PROTECT
01876 || isdigit(safe_argv[i][0])
01877 #endif
01878 )
01879 {
01880
01881 }
01882 else
01883 {
01884 pid = launch( 1, safe_argv[i], 0 );
01885 #ifndef NDEBUG
01886 fprintf(stderr, "kdeinit: Launched '%s', pid = %ld result = %d\n", safe_argv[i], (long) pid, d.result);
01887 #endif
01888 }
01889 }
01890
01892 for(i = 0; i < argc; i++)
01893 {
01894 free(safe_argv[i]);
01895 }
01896 free (safe_argv);
01897
01898 kdeinit_setproctitle("kdeinit Running...");
01899
01900 if (!keep_running)
01901 return 0;
01902
01903 char c = 0;
01904 write(d.initpipe[1], &c, 1);
01905 close(d.initpipe[1]);
01906 d.initpipe[1] = -1;
01907
01908 handle_requests(0);
01909
01910 return 0;
01911 }
01912