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