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;
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 ( libpath.findRev( ".so" ) == -1 )
00462 execpath = exec;
00463 }
00464 if (!args)
00465 {
00466 argc = 1;
00467 }
00468
00469 if (0 > pipe(d.fd))
00470 {
00471 perror("kdeinit: pipe() failed!\n");
00472 d.result = 3;
00473 d.errorMsg = i18n("Unable to start new process.\n"
00474 "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();
00475 close(d.fd[0]);
00476 close(d.fd[1]);
00477 d.fork = 0;
00478 return d.fork;
00479 }
00480
00481 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00482
00483 KStartupInfoId startup_id;
00484 startup_id.initId( startup_id_str );
00485 if( !startup_id.none())
00486 init_startup_info( startup_id, name, envc, envs );
00487 #endif
00488
00489 d.errorMsg = 0;
00490 d.fork = fork();
00491 switch(d.fork) {
00492 case -1:
00493 perror("kdeinit: fork() failed!\n");
00494 d.result = 3;
00495 d.errorMsg = i18n("Unable to create new process.\n"
00496 "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();
00497 close(d.fd[0]);
00498 close(d.fd[1]);
00499 d.fork = 0;
00500 break;
00501 case 0:
00503 close(d.fd[0]);
00504 close_fds();
00505 if (launcher)
00506 {
00507 if (d.fd[1] == LAUNCHER_FD)
00508 {
00509 d.fd[1] = dup(d.fd[1]);
00510 }
00511 if (d.launcher[1] != LAUNCHER_FD)
00512 {
00513 dup2( d.launcher[1], LAUNCHER_FD);
00514 close( d.launcher[1] );
00515 }
00516 close( d.launcher[0] );
00517 }
00518 reset_oom_protect();
00519
00520 if (cwd && *cwd)
00521 chdir(cwd);
00522
00523 if( reset_env )
00524 {
00525
00526 QStrList unset_envs;
00527 for( int tmp_env_count = 0;
00528 environ[tmp_env_count];
00529 tmp_env_count++)
00530 unset_envs.append( environ[ tmp_env_count ] );
00531 for( QStrListIterator it( unset_envs );
00532 it.current() != NULL ;
00533 ++it )
00534 {
00535 QCString tmp( it.current());
00536 int pos = tmp.find( '=' );
00537 if( pos >= 0 )
00538 unsetenv( tmp.left( pos ));
00539 }
00540 }
00541
00542 for (int i = 0; i < envc; i++)
00543 {
00544 putenv((char *)envs);
00545 while(*envs != 0) envs++;
00546 envs++;
00547 }
00548
00549 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00550
00551 if( startup_id.none())
00552 KStartupInfo::resetStartupEnv();
00553 else
00554 startup_id.setupStartupEnv();
00555 #endif
00556 {
00557 int r;
00558 QCString procTitle;
00559 d.argv = (char **) malloc(sizeof(char *) * (argc+1));
00560 d.argv[0] = (char *) _name;
00561 for (int i = 1; i < argc; i++)
00562 {
00563 d.argv[i] = (char *) args;
00564 procTitle += " ";
00565 procTitle += (char *) args;
00566 while(*args != 0) args++;
00567 args++;
00568 }
00569 d.argv[argc] = 0;
00570
00572 #ifdef Q_OS_LINUX
00573
00574 r = prctl(PR_SET_NAME, (unsigned long) name.data(), 0, 0, 0);
00575 if ( r == 0 )
00576 kdeinit_setproctitle( "%s [kdeinit]%s", name.data(), procTitle.data() ? procTitle.data() : "" );
00577 else
00578 kdeinit_setproctitle( "kdeinit: %s%s", name.data(), procTitle.data() ? procTitle.data() : "" );
00579 #else
00580 kdeinit_setproctitle( "kdeinit: %s%s", name.data(), procTitle.data() ? procTitle.data() : "" );
00581 #endif
00582 }
00583
00584 d.handle = 0;
00585 if (libpath.isEmpty() && execpath.isEmpty())
00586 {
00587 QString errorMsg = i18n("Could not find '%1' executable.").arg(QFile::decodeName(_name));
00588 exitWithErrorMsg(errorMsg);
00589 }
00590
00591 if ( getenv("KDE_IS_PRELINKED") && !execpath.isEmpty() && !launcher)
00592 libpath.truncate(0);
00593
00594 if ( !libpath.isEmpty() )
00595 {
00596 d.handle = lt_dlopen( QFile::encodeName(libpath) );
00597 if (!d.handle )
00598 {
00599 const char * ltdlError = lt_dlerror();
00600 if (execpath.isEmpty())
00601 {
00602
00603 QString errorMsg = i18n("Could not open library '%1'.\n%2").arg(QFile::decodeName(libpath))
00604 .arg(ltdlError ? QFile::decodeName(ltdlError) : i18n("Unknown error"));
00605 exitWithErrorMsg(errorMsg);
00606 }
00607 else
00608 {
00609
00610 fprintf(stderr, "Could not open library %s: %s\n", lib.data(), ltdlError != 0 ? ltdlError : "(null)" );
00611 }
00612 }
00613 }
00614 lt_dlopen_flag = d.lt_dlopen_flag;
00615 if (!d.handle )
00616 {
00617 d.result = 2;
00618 write(d.fd[1], &d.result, 1);
00619
00620
00621
00622 fcntl(d.fd[1], F_SETFD, FD_CLOEXEC);
00623
00624 setup_tty( tty );
00625
00626 execvp(execpath.data(), d.argv);
00627 d.result = 1;
00628 write(d.fd[1], &d.result, 1);
00629 close(d.fd[1]);
00630 exit(255);
00631 }
00632
00633 d.sym = lt_dlsym( d.handle, "kdeinitmain");
00634 if (!d.sym )
00635 {
00636 d.sym = lt_dlsym( d.handle, "kdemain" );
00637 if ( !d.sym )
00638 {
00639 #if ! KDE_IS_VERSION( 3, 90, 0 )
00640 d.sym = lt_dlsym( d.handle, "main");
00641 #endif
00642 if (!d.sym )
00643 {
00644 const char * ltdlError = lt_dlerror();
00645 fprintf(stderr, "Could not find kdemain: %s\n", ltdlError != 0 ? ltdlError : "(null)" );
00646 QString errorMsg = i18n("Could not find 'kdemain' in '%1'.\n%2").arg(libpath)
00647 .arg(ltdlError ? QFile::decodeName(ltdlError) : i18n("Unknown error"));
00648 exitWithErrorMsg(errorMsg);
00649 }
00650 }
00651 }
00652
00653 d.result = 0;
00654 write(d.fd[1], &d.result, 1);
00655 close(d.fd[1]);
00656
00657 d.func = (int (*)(int, char *[])) d.sym;
00658 if (d.debug_wait)
00659 {
00660 fprintf(stderr, "kdeinit: Suspending process\n"
00661 "kdeinit: 'gdb kdeinit %d' to debug\n"
00662 "kdeinit: 'kill -SIGCONT %d' to continue\n",
00663 getpid(), getpid());
00664 kill(getpid(), SIGSTOP);
00665 }
00666 else
00667 {
00668 setup_tty( tty );
00669 }
00670
00671 exit( d.func(argc, d.argv));
00672
00673 break;
00674 default:
00676 close(d.fd[1]);
00677 if (launcher)
00678 {
00679 close(d.launcher[1]);
00680 d.launcher_pid = d.fork;
00681 }
00682 bool exec = false;
00683 for(;;)
00684 {
00685 d.n = read(d.fd[0], &d.result, 1);
00686 if (d.n == 1)
00687 {
00688 if (d.result == 2)
00689 {
00690 #ifndef NDEBUG
00691 fprintf(stderr, "Could not load library! Trying exec....\n");
00692 #endif
00693 exec = true;
00694 continue;
00695 }
00696 if (d.result == 3)
00697 {
00698 int l = 0;
00699 d.n = read(d.fd[0], &l, sizeof(int));
00700 if (d.n == sizeof(int))
00701 {
00702 QCString tmp;
00703 tmp.resize(l+1);
00704 d.n = read(d.fd[0], tmp.data(), l);
00705 tmp[l] = 0;
00706 if (d.n == l)
00707 d.errorMsg = tmp;
00708 }
00709 }
00710
00711 break;
00712 }
00713 if (d.n == -1)
00714 {
00715 if (errno == ECHILD) {
00716 continue;
00717 }
00718 if (errno == EINTR || errno == EAGAIN) {
00719 continue;
00720 }
00721 }
00722 if (exec)
00723 {
00724 d.result = 0;
00725 break;
00726 }
00727 if (d.n == 0)
00728 {
00729 perror("kdeinit: Pipe closed unexpectedly");
00730 d.result = 1;
00731 break;
00732 }
00733 perror("kdeinit: Error reading from pipe");
00734 d.result = 1;
00735 break;
00736 }
00737 close(d.fd[0]);
00738 if (launcher && (d.result == 0))
00739 {
00740
00741 d.launcher_pid = d.fork;
00742 }
00743 }
00744 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00745
00746 if( !startup_id.none())
00747 {
00748 if( d.fork && d.result == 0 )
00749 complete_startup_info( startup_id, d.fork );
00750 else
00751 complete_startup_info( startup_id, 0 );
00752 }
00753 #endif
00754 return d.fork;
00755 }
00756
00757 static void sig_child_handler(int)
00758 {
00759
00760
00761
00762
00763
00764
00765
00766
00767 char c = 0;
00768 write(d.deadpipe[1], &c, 1);
00769 }
00770
00771 static void init_signals()
00772 {
00773 struct sigaction act;
00774 long options;
00775
00776 if (pipe(d.deadpipe) != 0)
00777 {
00778 perror("kdeinit: Aborting. Can't create pipe: ");
00779 exit(255);
00780 }
00781
00782 options = fcntl(d.deadpipe[0], F_GETFL);
00783 if (options == -1)
00784 {
00785 perror("kdeinit: Aborting. Can't make pipe non-blocking: ");
00786 exit(255);
00787 }
00788
00789 if (fcntl(d.deadpipe[0], F_SETFL, options | O_NONBLOCK) == -1)
00790 {
00791 perror("kdeinit: Aborting. Can't make pipe non-blocking: ");
00792 exit(255);
00793 }
00794
00795
00796
00797
00798
00799
00800 act.sa_handler=sig_child_handler;
00801 sigemptyset(&(act.sa_mask));
00802 sigaddset(&(act.sa_mask), SIGCHLD);
00803 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
00804 act.sa_flags = SA_NOCLDSTOP;
00805
00806
00807
00808
00809 #ifdef SA_RESTART
00810 act.sa_flags |= SA_RESTART;
00811 #endif
00812 sigaction( SIGCHLD, &act, 0L);
00813
00814 act.sa_handler=SIG_IGN;
00815 sigemptyset(&(act.sa_mask));
00816 sigaddset(&(act.sa_mask), SIGPIPE);
00817 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
00818 act.sa_flags = 0;
00819 sigaction( SIGPIPE, &act, 0L);
00820 }
00821
00822 static void init_kdeinit_socket()
00823 {
00824 struct sockaddr_un sa;
00825 struct sockaddr_un sa_old;
00826 kde_socklen_t socklen;
00827 long options;
00828 const char *home_dir = getenv("HOME");
00829 int max_tries = 10;
00830 if (!home_dir || !home_dir[0])
00831 {
00832 fprintf(stderr, "kdeinit: Aborting. $HOME not set!");
00833 exit(255);
00834 }
00835 chdir(home_dir);
00836
00837 {
00838 QCString path = home_dir;
00839 QCString readOnly = getenv("KDE_HOME_READONLY");
00840 if (access(path.data(), R_OK|W_OK))
00841 {
00842 if (errno == ENOENT)
00843 {
00844 fprintf(stderr, "kdeinit: Aborting. $HOME directory (%s) does not exist.\n", path.data());
00845 exit(255);
00846 }
00847 else if (readOnly.isEmpty())
00848 {
00849 fprintf(stderr, "kdeinit: Aborting. No write access to $HOME directory (%s).\n", path.data());
00850 exit(255);
00851 }
00852 }
00853 path = getenv("ICEAUTHORITY");
00854 if (path.isEmpty())
00855 {
00856 path = home_dir;
00857 path += "/.ICEauthority";
00858 }
00859 if (access(path.data(), R_OK|W_OK) && (errno != ENOENT))
00860 {
00861 fprintf(stderr, "kdeinit: Aborting. No write access to '%s'.\n", path.data());
00862 exit(255);
00863 }
00864 }
00865
00870 if (access(sock_file, W_OK) == 0)
00871 {
00872 int s;
00873 struct sockaddr_un server;
00874
00875
00876
00877
00878
00879 s = socket(PF_UNIX, SOCK_STREAM, 0);
00880 if (s < 0)
00881 {
00882 perror("socket() failed: ");
00883 exit(255);
00884 }
00885 server.sun_family = AF_UNIX;
00886 strcpy(server.sun_path, sock_file);
00887 socklen = sizeof(server);
00888
00889 if(connect(s, (struct sockaddr *)&server, socklen) == 0)
00890 {
00891 fprintf(stderr, "kdeinit: Shutting down running client.\n");
00892 klauncher_header request_header;
00893 request_header.cmd = LAUNCHER_TERMINATE_KDEINIT;
00894 request_header.arg_length = 0;
00895 write(s, &request_header, sizeof(request_header));
00896 sleep(1);
00897 }
00898 close(s);
00899 }
00900
00902 unlink(sock_file);
00903 unlink(sock_file_old);
00904
00906 d.wrapper = socket(PF_UNIX, SOCK_STREAM, 0);
00907 if (d.wrapper < 0)
00908 {
00909 perror("kdeinit: Aborting. socket() failed: ");
00910 exit(255);
00911 }
00912
00913 options = fcntl(d.wrapper, F_GETFL);
00914 if (options == -1)
00915 {
00916 perror("kdeinit: Aborting. Can't make socket non-blocking: ");
00917 close(d.wrapper);
00918 exit(255);
00919 }
00920
00921 if (fcntl(d.wrapper, F_SETFL, options | O_NONBLOCK) == -1)
00922 {
00923 perror("kdeinit: Aborting. Can't make socket non-blocking: ");
00924 close(d.wrapper);
00925 exit(255);
00926 }
00927
00928 while (1) {
00930 socklen = sizeof(sa);
00931 memset(&sa, 0, socklen);
00932 sa.sun_family = AF_UNIX;
00933 strcpy(sa.sun_path, sock_file);
00934 if(bind(d.wrapper, (struct sockaddr *)&sa, socklen) != 0)
00935 {
00936 if (max_tries == 0) {
00937 perror("kdeinit: Aborting. bind() failed: ");
00938 fprintf(stderr, "Could not bind to socket '%s'\n", sock_file);
00939 close(d.wrapper);
00940 exit(255);
00941 }
00942 max_tries--;
00943 } else
00944 break;
00945 }
00946
00948 if (chmod(sock_file, 0600) != 0)
00949 {
00950 perror("kdeinit: Aborting. Can't set permissions on socket: ");
00951 fprintf(stderr, "Wrong permissions of socket '%s'\n", sock_file);
00952 unlink(sock_file);
00953 close(d.wrapper);
00954 exit(255);
00955 }
00956
00957 if(listen(d.wrapper, SOMAXCONN) < 0)
00958 {
00959 perror("kdeinit: Aborting. listen() failed: ");
00960 unlink(sock_file);
00961 close(d.wrapper);
00962 exit(255);
00963 }
00964
00966 d.wrapper_old = socket(PF_UNIX, SOCK_STREAM, 0);
00967 if (d.wrapper_old < 0)
00968 {
00969
00970 return;
00971 }
00972
00973 options = fcntl(d.wrapper_old, F_GETFL);
00974 if (options == -1)
00975 {
00976
00977 close(d.wrapper_old);
00978 d.wrapper_old = 0;
00979 return;
00980 }
00981
00982 if (fcntl(d.wrapper_old, F_SETFL, options | O_NONBLOCK) == -1)
00983 {
00984
00985 close(d.wrapper_old);
00986 d.wrapper_old = 0;
00987 return;
00988 }
00989
00990 max_tries = 10;
00991 while (1) {
00993 socklen = sizeof(sa_old);
00994 memset(&sa_old, 0, socklen);
00995 sa_old.sun_family = AF_UNIX;
00996 strcpy(sa_old.sun_path, sock_file_old);
00997 if(bind(d.wrapper_old, (struct sockaddr *)&sa_old, socklen) != 0)
00998 {
00999 if (max_tries == 0) {
01000
01001 fprintf(stderr, "Could not bind to socket '%s'\n", sock_file_old);
01002 close(d.wrapper_old);
01003 d.wrapper_old = 0;
01004 return;
01005 }
01006 max_tries--;
01007 } else
01008 break;
01009 }
01010
01012 if (chmod(sock_file_old, 0600) != 0)
01013 {
01014 fprintf(stderr, "Wrong permissions of socket '%s'\n", sock_file);
01015 unlink(sock_file_old);
01016 close(d.wrapper_old);
01017 d.wrapper_old = 0;
01018 return;
01019 }
01020
01021 if(listen(d.wrapper_old, SOMAXCONN) < 0)
01022 {
01023
01024 unlink(sock_file_old);
01025 close(d.wrapper_old);
01026 d.wrapper_old = 0;
01027 }
01028 }
01029
01030
01031
01032
01033
01034 static int read_socket(int sock, char *buffer, int len)
01035 {
01036 ssize_t result;
01037 int bytes_left = len;
01038 while ( bytes_left > 0)
01039 {
01040 result = read(sock, buffer, bytes_left);
01041 if (result > 0)
01042 {
01043 buffer += result;
01044 bytes_left -= result;
01045 }
01046 else if (result == 0)
01047 return -1;
01048 else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
01049 return -1;
01050 }
01051 return 0;
01052 }
01053
01054 static void WaitPid( pid_t waitForPid)
01055 {
01056 int result;
01057 while(1)
01058 {
01059 result = waitpid(waitForPid, &d.exit_status, 0);
01060 if ((result == -1) && (errno == ECHILD))
01061 return;
01062 }
01063 }
01064
01065 static void launcher_died()
01066 {
01067 if (!d.launcher_ok)
01068 {
01069
01070 fprintf(stderr, "kdeinit: Communication error with launcher. Exiting!\n");
01071 ::exit(255);
01072 return;
01073 }
01074
01075
01076 #ifndef NDEBUG
01077 fprintf(stderr, "kdeinit: KLauncher died unexpectedly.\n");
01078 #endif
01079
01080 if (d.launcher_pid)
01081 {
01082 kill(d.launcher_pid, SIGKILL);
01083 sleep(1);
01084 }
01085
01086 d.launcher_ok = false;
01087 d.launcher_pid = 0;
01088 close(d.launcher[0]);
01089 d.launcher[0] = -1;
01090
01091 pid_t pid = launch( 1, "klauncher", 0 );
01092 #ifndef NDEBUG
01093 fprintf(stderr, "kdeinit: Relaunching KLauncher, pid = %ld result = %d\n", (long) pid, d.result);
01094 #endif
01095 }
01096
01097 static void handle_launcher_request(int sock = -1)
01098 {
01099 bool launcher = false;
01100 if (sock < 0)
01101 {
01102 sock = d.launcher[0];
01103 launcher = true;
01104 }
01105
01106 klauncher_header request_header;
01107 char *request_data = 0L;
01108 int result = read_socket(sock, (char *) &request_header, sizeof(request_header));
01109 if (result != 0)
01110 {
01111 if (launcher)
01112 launcher_died();
01113 return;
01114 }
01115
01116 if ( request_header.arg_length != 0 )
01117 {
01118 request_data = (char *) malloc(request_header.arg_length);
01119
01120 result = read_socket(sock, request_data, request_header.arg_length);
01121 if (result != 0)
01122 {
01123 if (launcher)
01124 launcher_died();
01125 free(request_data);
01126 return;
01127 }
01128 }
01129
01130 if (request_header.cmd == LAUNCHER_OK)
01131 {
01132 d.launcher_ok = true;
01133 }
01134 else if (request_header.arg_length &&
01135 ((request_header.cmd == LAUNCHER_EXEC) ||
01136 (request_header.cmd == LAUNCHER_EXT_EXEC) ||
01137 (request_header.cmd == LAUNCHER_SHELL ) ||
01138 (request_header.cmd == LAUNCHER_KWRAPPER) ||
01139 (request_header.cmd == LAUNCHER_EXEC_NEW)))
01140 {
01141 pid_t pid;
01142 klauncher_header response_header;
01143 long response_data;
01144 long l;
01145 memcpy( &l, request_data, sizeof( long ));
01146 int argc = l;
01147 const char *name = request_data + sizeof(long);
01148 const char *args = name + strlen(name) + 1;
01149 const char *cwd = 0;
01150 int envc = 0;
01151 const char *envs = 0;
01152 const char *tty = 0;
01153 int avoid_loops = 0;
01154 const char *startup_id_str = "0";
01155
01156 #ifndef NDEBUG
01157 fprintf(stderr, "kdeinit: Got %s '%s' from %s.\n",
01158 (request_header.cmd == LAUNCHER_EXEC ? "EXEC" :
01159 (request_header.cmd == LAUNCHER_EXT_EXEC ? "EXT_EXEC" :
01160 (request_header.cmd == LAUNCHER_EXEC_NEW ? "EXEC_NEW" :
01161 (request_header.cmd == LAUNCHER_SHELL ? "SHELL" : "KWRAPPER" )))),
01162 name, launcher ? "launcher" : "socket" );
01163 #endif
01164
01165 const char *arg_n = args;
01166 for(int i = 1; i < argc; i++)
01167 {
01168 arg_n = arg_n + strlen(arg_n) + 1;
01169 }
01170
01171 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER )
01172 {
01173
01174 cwd = arg_n; arg_n += strlen(cwd) + 1;
01175 }
01176 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
01177 || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
01178 {
01179 memcpy( &l, arg_n, sizeof( long ));
01180 envc = l;
01181 arg_n += sizeof(long);
01182 envs = arg_n;
01183 for(int i = 0; i < envc; i++)
01184 {
01185 arg_n = arg_n + strlen(arg_n) + 1;
01186 }
01187 if( request_header.cmd == LAUNCHER_KWRAPPER )
01188 {
01189 tty = arg_n;
01190 arg_n += strlen( tty ) + 1;
01191 }
01192 }
01193
01194 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
01195 || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
01196 {
01197 memcpy( &l, arg_n, sizeof( long ));
01198 avoid_loops = l;
01199 arg_n += sizeof( long );
01200 }
01201
01202 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
01203 || request_header.cmd == LAUNCHER_EXT_EXEC )
01204 {
01205 startup_id_str = arg_n;
01206 arg_n += strlen( startup_id_str ) + 1;
01207 }
01208
01209 if ((request_header.arg_length > (arg_n - request_data)) &&
01210 (request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW ))
01211 {
01212
01213 cwd = arg_n; arg_n += strlen(cwd) + 1;
01214 }
01215
01216 if ((arg_n - request_data) != request_header.arg_length)
01217 {
01218 #ifndef NDEBUG
01219 fprintf(stderr, "kdeinit: EXEC request has invalid format.\n");
01220 #endif
01221 free(request_data);
01222 d.debug_wait = false;
01223 return;
01224 }
01225
01226
01227 QCString olddisplay = getenv(DISPLAY);
01228 QCString kdedisplay = getenv("KDE_DISPLAY");
01229 bool reset_display = (! olddisplay.isEmpty() &&
01230 ! kdedisplay.isEmpty() &&
01231 olddisplay != kdedisplay);
01232
01233 if (reset_display)
01234 setenv(DISPLAY, kdedisplay, true);
01235
01236 pid = launch( argc, name, args, cwd, envc, envs,
01237 request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER,
01238 tty, avoid_loops, startup_id_str );
01239
01240 if (reset_display) {
01241 unsetenv("KDE_DISPLAY");
01242 setenv(DISPLAY, olddisplay, true);
01243 }
01244
01245 if (pid && (d.result == 0))
01246 {
01247 response_header.cmd = LAUNCHER_OK;
01248 response_header.arg_length = sizeof(response_data);
01249 response_data = pid;
01250 write(sock, &response_header, sizeof(response_header));
01251 write(sock, &response_data, response_header.arg_length);
01252 }
01253 else
01254 {
01255 int l = d.errorMsg.length();
01256 if (l) l++;
01257 response_header.cmd = LAUNCHER_ERROR;
01258 response_header.arg_length = l;
01259 write(sock, &response_header, sizeof(response_header));
01260 if (l)
01261 write(sock, d.errorMsg.data(), l);
01262 }
01263 d.debug_wait = false;
01264 }
01265 else if (request_header.arg_length && request_header.cmd == LAUNCHER_SETENV)
01266 {
01267 const char *env_name;
01268 const char *env_value;
01269 env_name = request_data;
01270 env_value = env_name + strlen(env_name) + 1;
01271
01272 #ifndef NDEBUG
01273 if (launcher)
01274 fprintf(stderr, "kdeinit: Got SETENV '%s=%s' from klauncher.\n", env_name, env_value);
01275 else
01276 fprintf(stderr, "kdeinit: Got SETENV '%s=%s' from socket.\n", env_name, env_value);
01277 #endif
01278
01279 if ( request_header.arg_length !=
01280 (int) (strlen(env_name) + strlen(env_value) + 2))
01281 {
01282 #ifndef NDEBUG
01283 fprintf(stderr, "kdeinit: SETENV request has invalid format.\n");
01284 #endif
01285 free(request_data);
01286 return;
01287 }
01288 setenv( env_name, env_value, 1);
01289 }
01290 else if (request_header.cmd == LAUNCHER_TERMINATE_KDE)
01291 {
01292 #ifndef NDEBUG
01293 fprintf(stderr,"kdeinit: terminate KDE.\n");
01294 #endif
01295 #ifdef Q_WS_X11
01296 kdeinit_xio_errhandler( 0L );
01297 #endif
01298 }
01299 else if (request_header.cmd == LAUNCHER_TERMINATE_KDEINIT)
01300 {
01301 #ifndef NDEBUG
01302 fprintf(stderr,"kdeinit: Killing kdeinit/klauncher.\n");
01303 #endif
01304 if (d.launcher_pid)
01305 kill(d.launcher_pid, SIGTERM);
01306 if (d.my_pid)
01307 kill(d.my_pid, SIGTERM);
01308 }
01309 else if (request_header.cmd == LAUNCHER_DEBUG_WAIT)
01310 {
01311 #ifndef NDEBUG
01312 fprintf(stderr,"kdeinit: Debug wait activated.\n");
01313 #endif
01314 d.debug_wait = true;
01315 }
01316 if (request_data)
01317 free(request_data);
01318 }
01319
01320 static void handle_requests(pid_t waitForPid)
01321 {
01322 int max_sock = d.wrapper;
01323 if (d.wrapper_old > max_sock)
01324 max_sock = d.wrapper_old;
01325 if (d.launcher_pid && (d.launcher[0] > max_sock))
01326 max_sock = d.launcher[0];
01327 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01328
01329 if (X11fd > max_sock)
01330 max_sock = X11fd;
01331 #endif
01332 max_sock++;
01333
01334 while(1)
01335 {
01336 fd_set rd_set;
01337 fd_set wr_set;
01338 fd_set e_set;
01339 int result;
01340 pid_t exit_pid;
01341 char c;
01342
01343
01344 while( read(d.deadpipe[0], &c, 1) == 1);
01345
01346
01347 do {
01348 exit_pid = waitpid(-1, 0, WNOHANG);
01349 if (exit_pid > 0)
01350 {
01351 #ifndef NDEBUG
01352 fprintf(stderr, "kdeinit: PID %ld terminated.\n", (long) exit_pid);
01353 #endif
01354 if (waitForPid && (exit_pid == waitForPid))
01355 return;
01356
01357 if (d.launcher_pid)
01358 {
01359
01360 klauncher_header request_header;
01361 long request_data[2];
01362 request_header.cmd = LAUNCHER_DIED;
01363 request_header.arg_length = sizeof(long) * 2;
01364 request_data[0] = exit_pid;
01365 request_data[1] = 0;
01366 write(d.launcher[0], &request_header, sizeof(request_header));
01367 write(d.launcher[0], request_data, request_header.arg_length);
01368 }
01369 }
01370 }
01371 while( exit_pid > 0);
01372
01373 FD_ZERO(&rd_set);
01374 FD_ZERO(&wr_set);
01375 FD_ZERO(&e_set);
01376
01377 if (d.launcher_pid)
01378 {
01379 FD_SET(d.launcher[0], &rd_set);
01380 }
01381 FD_SET(d.wrapper, &rd_set);
01382 if (d.wrapper_old)
01383 {
01384 FD_SET(d.wrapper_old, &rd_set);
01385 }
01386 FD_SET(d.deadpipe[0], &rd_set);
01387 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01388
01389 if(X11fd >= 0) FD_SET(X11fd, &rd_set);
01390 #endif
01391
01392 result = select(max_sock, &rd_set, &wr_set, &e_set, 0);
01393
01394
01395 if ((result > 0) && (FD_ISSET(d.wrapper, &rd_set)))
01396 {
01397 struct sockaddr_un client;
01398 kde_socklen_t sClient = sizeof(client);
01399 int sock = accept(d.wrapper, (struct sockaddr *)&client, &sClient);
01400 if (sock >= 0)
01401 {
01402 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
01403 if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
01404 FcInitReinitialize();
01405 #endif
01406 if (fork() == 0)
01407 {
01408 close_fds();
01409 reset_oom_protect();
01410 handle_launcher_request(sock);
01411 exit(255);
01412 }
01413 close(sock);
01414 }
01415 }
01416 if ((result > 0) && (FD_ISSET(d.wrapper_old, &rd_set)))
01417 {
01418 struct sockaddr_un client;
01419 kde_socklen_t sClient = sizeof(client);
01420 int sock = accept(d.wrapper_old, (struct sockaddr *)&client, &sClient);
01421 if (sock >= 0)
01422 {
01423 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
01424 if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
01425 FcInitReinitialize();
01426 #endif
01427 if (fork() == 0)
01428 {
01429 close_fds();
01430 reset_oom_protect();
01431 handle_launcher_request(sock);
01432 exit(255);
01433 }
01434 close(sock);
01435 }
01436 }
01437
01438
01439 if ((result > 0) && (d.launcher_pid) && (FD_ISSET(d.launcher[0], &rd_set)))
01440 {
01441 handle_launcher_request();
01442 if (waitForPid == d.launcher_pid)
01443 return;
01444 }
01445
01446
01447 #ifdef Q_WS_X11
01448
01449 if((result > 0) && (X11fd >= 0))
01450 {
01451 if(FD_ISSET(X11fd,&rd_set))
01452 {
01453 if (X11display != 0) {
01454 XEvent event_return;
01455 while (XPending(X11display))
01456 XNextEvent(X11display, &event_return);
01457 }
01458 }
01459 }
01460 #endif
01461 }
01462 }
01463
01464 static void kdeinit_library_path()
01465 {
01466 QStringList ltdl_library_path =
01467 QStringList::split(':', QFile::decodeName(getenv("LTDL_LIBRARY_PATH")));
01468 QStringList ld_library_path =
01469 QStringList::split(':', QFile::decodeName(getenv("LD_LIBRARY_PATH")));
01470
01471 QCString extra_path;
01472 QStringList candidates = s_instance->dirs()->resourceDirs("lib");
01473 for (QStringList::ConstIterator it = candidates.begin();
01474 it != candidates.end();
01475 it++)
01476 {
01477 QString d = *it;
01478 if (ltdl_library_path.contains(d))
01479 continue;
01480 if (ld_library_path.contains(d))
01481 continue;
01482 if (d[d.length()-1] == '/')
01483 {
01484 d.truncate(d.length()-1);
01485 if (ltdl_library_path.contains(d))
01486 continue;
01487 if (ld_library_path.contains(d))
01488 continue;
01489 }
01490 if ((d == "/lib") || (d == "/usr/lib"))
01491 continue;
01492
01493 QCString dir = QFile::encodeName(d);
01494
01495 if (access(dir, R_OK))
01496 continue;
01497
01498 if ( !extra_path.isEmpty())
01499 extra_path += ":";
01500 extra_path += dir;
01501 }
01502
01503 if (lt_dlinit())
01504 {
01505 const char * ltdlError = lt_dlerror();
01506 fprintf(stderr, "can't initialize dynamic loading: %s\n", ltdlError != 0 ? ltdlError : "(null)" );
01507 }
01508 if (!extra_path.isEmpty())
01509 lt_dlsetsearchpath(extra_path.data());
01510
01511 QCString display = getenv(DISPLAY);
01512 if (display.isEmpty())
01513 {
01514 fprintf(stderr, "kdeinit: Aborting. $"DISPLAY" is not set.\n");
01515 exit(255);
01516 }
01517 int i;
01518 if((i = display.findRev('.')) > display.findRev(':') && i >= 0)
01519 display.truncate(i);
01520
01521 QCString socketName = QFile::encodeName(locateLocal("socket", QString("kdeinit-%1").arg(display), s_instance));
01522 if (socketName.length() >= MAX_SOCK_FILE)
01523 {
01524 fprintf(stderr, "kdeinit: Aborting. Socket name will be too long:\n");
01525 fprintf(stderr, " '%s'\n", socketName.data());
01526 exit(255);
01527 }
01528 strcpy(sock_file_old, socketName.data());
01529
01530 display.replace(":","_");
01531 socketName = QFile::encodeName(locateLocal("socket", QString("kdeinit_%1").arg(display), s_instance));
01532 if (socketName.length() >= MAX_SOCK_FILE)
01533 {
01534 fprintf(stderr, "kdeinit: Aborting. Socket name will be too long:\n");
01535 fprintf(stderr, " '%s'\n", socketName.data());
01536 exit(255);
01537 }
01538 strcpy(sock_file, socketName.data());
01539 }
01540
01541 int kdeinit_xio_errhandler( Display *disp )
01542 {
01543
01544
01545 if ( disp )
01546 qWarning( "kdeinit: Fatal IO error: client killed" );
01547
01548 if (sock_file[0])
01549 {
01551 unlink(sock_file);
01552 }
01553 if (sock_file_old[0])
01554 {
01556 unlink(sock_file_old);
01557 }
01558
01559
01560 if (d.suicide)
01561 {
01562 if (d.launcher_pid)
01563 kill(d.launcher_pid, SIGTERM);
01564 exit( 0 );
01565 }
01566
01567 if ( disp )
01568 qWarning( "kdeinit: sending SIGHUP to children." );
01569
01570
01571 signal(SIGHUP, SIG_IGN);
01572 kill(0, SIGHUP);
01573
01574 sleep(2);
01575
01576 if ( disp )
01577 qWarning( "kdeinit: sending SIGTERM to children." );
01578
01579
01580 signal(SIGTERM, SIG_IGN);
01581 kill(0, SIGTERM);
01582
01583 if ( disp )
01584 qWarning( "kdeinit: Exit." );
01585
01586 exit( 0 );
01587 return 0;
01588 }
01589
01590 #ifdef Q_WS_X11
01591 int kdeinit_x_errhandler( Display *dpy, XErrorEvent *err )
01592 {
01593 #ifndef NDEBUG
01594 char errstr[256];
01595
01596 XGetErrorText( dpy, err->error_code, errstr, 256 );
01597 fprintf(stderr, "kdeinit: KDE detected X Error: %s %d\n"
01598 " Major opcode: %d\n"
01599 " Minor opcode: %d\n"
01600 " Resource id: 0x%lx\n",
01601 errstr, err->error_code, err->request_code, err->minor_code, err->resourceid );
01602 #else
01603 Q_UNUSED(dpy);
01604 Q_UNUSED(err);
01605 #endif
01606 return 0;
01607 }
01608 #endif
01609
01610
01611 #ifdef Q_WS_X11
01612
01613
01614 static void setupX()
01615 {
01616 XSetIOErrorHandler(kdeinit_xio_errhandler);
01617 XSetErrorHandler(kdeinit_x_errhandler);
01618 }
01619
01620
01621 static int initXconnection()
01622 {
01623 X11display = XOpenDisplay(NULL);
01624 if ( X11display != 0 ) {
01625 XCreateSimpleWindow(X11display, DefaultRootWindow(X11display), 0,0,1,1, \
01626 0,
01627 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)),
01628 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)) );
01629 #ifndef NDEBUG
01630 fprintf(stderr, "kdeinit: opened connection to %s\n", DisplayString(X11display));
01631 #endif
01632 int fd = XConnectionNumber( X11display );
01633 int on = 1;
01634 (void) setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, (int) sizeof(on));
01635 return fd;
01636 } else
01637 fprintf(stderr, "kdeinit: Can't connect to the X Server.\n" \
01638 "kdeinit: Might not terminate at end of session.\n");
01639
01640 return -1;
01641 }
01642 #endif
01643
01644 #ifdef __KCC
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664 extern "C" void _main(void);
01665 extern "C" void __call_ctors__Fv(void);
01666 static int main_called = 0;
01667 void _main(void)
01668 {
01669 if (main_called)
01670 return;
01671 main_called = 1;
01672 __call_ctors__Fv ();
01673 }
01674 #endif
01675
01676 static void secondary_child_handler(int)
01677 {
01678 waitpid(-1, 0, WNOHANG);
01679 }
01680
01681 int main(int argc, char **argv, char **envp)
01682 {
01683 int i;
01684 pid_t pid;
01685 int launch_dcop = 1;
01686 int launch_klauncher = 1;
01687 int launch_kded = 1;
01688 int keep_running = 1;
01689 int new_startup = 0;
01690 d.suicide = false;
01691
01693 char **safe_argv = (char **) malloc( sizeof(char *) * argc);
01694 for(i = 0; i < argc; i++)
01695 {
01696 safe_argv[i] = strcpy((char*)malloc(strlen(argv[i])+1), argv[i]);
01697 if (strcmp(safe_argv[i], "--no-dcop") == 0)
01698 launch_dcop = 0;
01699 if (strcmp(safe_argv[i], "--no-klauncher") == 0)
01700 launch_klauncher = 0;
01701 if (strcmp(safe_argv[i], "--no-kded") == 0)
01702 launch_kded = 0;
01703 if (strcmp(safe_argv[i], "--suicide") == 0)
01704 d.suicide = true;
01705 if (strcmp(safe_argv[i], "--exit") == 0)
01706 keep_running = 0;
01707 if (strcmp(safe_argv[i], "--new-startup") == 0)
01708 new_startup = 1;
01709 #ifdef KDEINIT_OOM_PROTECT
01710 if (strcmp(safe_argv[i], "--oom-pipe") == 0 && i+1<argc)
01711 oom_pipe = atol(argv[i+1]);
01712 #endif
01713 if (strcmp(safe_argv[i], "--help") == 0)
01714 {
01715 printf("Usage: kdeinit [options]\n");
01716
01717
01718 printf(" --no-kded Do not start kded\n");
01719 printf(" --suicide Terminate when no KDE applications are left running\n");
01720
01721 exit(0);
01722 }
01723 }
01724
01725 pipe(d.initpipe);
01726
01727
01728
01729
01730 signal( SIGCHLD, secondary_child_handler);
01731 if (fork() > 0)
01732 {
01733 close(d.initpipe[1]);
01734 d.initpipe[1] = -1;
01735
01736 char c;
01737 while( read(d.initpipe[0], &c, 1) < 0);
01738
01739 close(d.initpipe[0]);
01740 d.initpipe[0] = -1;
01741 return 0;
01742 }
01743 close(d.initpipe[0]);
01744 d.initpipe[0] = -1;
01745 d.my_pid = getpid();
01746
01748 if(keep_running)
01749 setsid();
01750
01752 s_instance = new KInstance("kdeinit");
01753
01755 kdeinit_initsetproctitle(argc, argv, envp);
01756 kdeinit_library_path();
01757
01758
01759
01760 KGlobal::_instance = 0L;
01761
01762 unsetenv("LD_BIND_NOW");
01763 unsetenv("DYLD_BIND_AT_LAUNCH");
01764 KApplication::loadedByKdeinit = true;
01765
01766 d.maxname = strlen(argv[0]);
01767 d.launcher_pid = 0;
01768 d.wrapper = 0;
01769 d.wrapper_old = 0;
01770 d.debug_wait = false;
01771 d.launcher_ok = false;
01772 d.lt_dlopen_flag = lt_dlopen_flag;
01773 lt_dlopen_flag |= LTDL_GLOBAL;
01774 init_signals();
01775 #ifdef Q_WS_X11
01776 setupX();
01777 #endif
01778
01779 if (keep_running)
01780 {
01781
01782
01783
01784
01785 init_kdeinit_socket();
01786 }
01787
01788 if (launch_dcop)
01789 {
01790 if (d.suicide)
01791 pid = launch( 3, "dcopserver", "--nosid\0--suicide" );
01792 else
01793 pid = launch( 2, "dcopserver", "--nosid" );
01794 #ifndef NDEBUG
01795 fprintf(stderr, "kdeinit: Launched DCOPServer, pid = %ld result = %d\n", (long) pid, d.result);
01796 #endif
01797 WaitPid(pid);
01798 if (!WIFEXITED(d.exit_status) || (WEXITSTATUS(d.exit_status) != 0))
01799 {
01800 fprintf(stderr, "kdeinit: DCOPServer could not be started, aborting.\n");
01801 exit(1);
01802 }
01803 }
01804 #ifndef __CYGWIN__
01805 if (!d.suicide && !getenv("KDE_IS_PRELINKED"))
01806 {
01807 QString konq = KLibLoader::findLibrary( "libkonq", s_instance );
01808 if (!konq.isEmpty())
01809 (void) lt_dlopen(QFile::encodeName(konq).data());
01810 }
01811 #endif
01812 if (launch_klauncher)
01813 {
01814 if( new_startup )
01815 pid = launch( 2, "klauncher", "--new-startup" );
01816 else
01817 pid = launch( 1, "klauncher", 0 );
01818 #ifndef NDEBUG
01819 fprintf(stderr, "kdeinit: Launched KLauncher, pid = %ld result = %d\n", (long) pid, d.result);
01820 #endif
01821 handle_requests(pid);
01822 }
01823
01824 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01825
01826 X11fd = initXconnection();
01827 #endif
01828
01829 {
01830 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
01831 if( FcGetVersion() < 20390 )
01832 {
01833 XftInit(0);
01834 XftInitFtLibrary();
01835 }
01836 #endif
01837 QFont::initialize();
01838 setlocale (LC_ALL, "");
01839 setlocale (LC_NUMERIC, "C");
01840 #ifdef Q_WS_X11
01841 if (XSupportsLocale ())
01842 {
01843
01844
01845 XOpenIM (X11display, 0, 0, 0);
01846 }
01847 #endif
01848 }
01849
01850 if (launch_kded)
01851 {
01852 if( new_startup )
01853 pid = launch( 2, "kded", "--new-startup" );
01854 else
01855 pid = launch( 1, "kded", 0 );
01856 #ifndef NDEBUG
01857 fprintf(stderr, "kdeinit: Launched KDED, pid = %ld result = %d\n", (long) pid, d.result);
01858 #endif
01859 handle_requests(pid);
01860 }
01861
01862 for(i = 1; i < argc; i++)
01863 {
01864 if (safe_argv[i][0] == '+')
01865 {
01866 pid = launch( 1, safe_argv[i]+1, 0);
01867 #ifndef NDEBUG
01868 fprintf(stderr, "kdeinit: Launched '%s', pid = %ld result = %d\n", safe_argv[i]+1, (long) pid, d.result);
01869 #endif
01870 handle_requests(pid);
01871 }
01872 else if (safe_argv[i][0] == '-'
01873 #ifdef KDEINIT_OOM_PROTECT
01874 || isdigit(safe_argv[i][0])
01875 #endif
01876 )
01877 {
01878
01879 }
01880 else
01881 {
01882 pid = launch( 1, safe_argv[i], 0 );
01883 #ifndef NDEBUG
01884 fprintf(stderr, "kdeinit: Launched '%s', pid = %ld result = %d\n", safe_argv[i], (long) pid, d.result);
01885 #endif
01886 }
01887 }
01888
01890 for(i = 0; i < argc; i++)
01891 {
01892 free(safe_argv[i]);
01893 }
01894 free (safe_argv);
01895
01896 kdeinit_setproctitle("kdeinit Running...");
01897
01898 if (!keep_running)
01899 return 0;
01900
01901 char c = 0;
01902 write(d.initpipe[1], &c, 1);
01903 close(d.initpipe[1]);
01904 d.initpipe[1] = -1;
01905
01906 handle_requests(0);
01907
01908 return 0;
01909 }
01910