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