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 HAVE_SYS_PRCTL_H
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 HAVE_SYS_PRCTL_H
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.cmd == LAUNCHER_EXEC) ||
01103 (request_header.cmd == LAUNCHER_EXT_EXEC) ||
01104 (request_header.cmd == LAUNCHER_SHELL ) ||
01105 (request_header.cmd == LAUNCHER_KWRAPPER) ||
01106 (request_header.cmd == LAUNCHER_EXEC_NEW))
01107 {
01108 pid_t pid;
01109 klauncher_header response_header;
01110 long response_data;
01111 long l;
01112 memcpy( &l, request_data, sizeof( long ));
01113 int argc = l;
01114 const char *name = request_data + sizeof(long);
01115 const char *args = name + strlen(name) + 1;
01116 const char *cwd = 0;
01117 int envc = 0;
01118 const char *envs = 0;
01119 const char *tty = 0;
01120 int avoid_loops = 0;
01121 const char *startup_id_str = "0";
01122
01123 #ifndef NDEBUG
01124 fprintf(stderr, "kdeinit: Got %s '%s' from %s.\n",
01125 (request_header.cmd == LAUNCHER_EXEC ? "EXEC" :
01126 (request_header.cmd == LAUNCHER_EXT_EXEC ? "EXT_EXEC" :
01127 (request_header.cmd == LAUNCHER_EXEC_NEW ? "EXEC_NEW" :
01128 (request_header.cmd == LAUNCHER_SHELL ? "SHELL" : "KWRAPPER" )))),
01129 name, launcher ? "launcher" : "socket" );
01130 #endif
01131
01132 const char *arg_n = args;
01133 for(int i = 1; i < argc; i++)
01134 {
01135 arg_n = arg_n + strlen(arg_n) + 1;
01136 }
01137
01138 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER )
01139 {
01140
01141 cwd = arg_n; arg_n += strlen(cwd) + 1;
01142 }
01143 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
01144 || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
01145 {
01146 memcpy( &l, arg_n, sizeof( long ));
01147 envc = l;
01148 arg_n += sizeof(long);
01149 envs = arg_n;
01150 for(int i = 0; i < envc; i++)
01151 {
01152 arg_n = arg_n + strlen(arg_n) + 1;
01153 }
01154 if( request_header.cmd == LAUNCHER_KWRAPPER )
01155 {
01156 tty = arg_n;
01157 arg_n += strlen( tty ) + 1;
01158 }
01159 }
01160
01161 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
01162 || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
01163 {
01164 memcpy( &l, arg_n, sizeof( long ));
01165 avoid_loops = l;
01166 arg_n += sizeof( long );
01167 }
01168
01169 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
01170 || request_header.cmd == LAUNCHER_EXT_EXEC )
01171 {
01172 startup_id_str = arg_n;
01173 arg_n += strlen( startup_id_str ) + 1;
01174 }
01175
01176 if ((request_header.arg_length > (arg_n - request_data)) &&
01177 (request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW ))
01178 {
01179
01180 cwd = arg_n; arg_n += strlen(cwd) + 1;
01181 }
01182
01183 if ((arg_n - request_data) != request_header.arg_length)
01184 {
01185 #ifndef NDEBUG
01186 fprintf(stderr, "kdeinit: EXEC request has invalid format.\n");
01187 #endif
01188 free(request_data);
01189 d.debug_wait = false;
01190 return;
01191 }
01192
01193
01194 QCString olddisplay = getenv(DISPLAY);
01195 QCString kdedisplay = getenv("KDE_DISPLAY");
01196 bool reset_display = (! olddisplay.isEmpty() &&
01197 ! kdedisplay.isEmpty() &&
01198 olddisplay != kdedisplay);
01199
01200 if (reset_display)
01201 setenv(DISPLAY, kdedisplay, true);
01202
01203 pid = launch( argc, name, args, cwd, envc, envs,
01204 request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER,
01205 tty, avoid_loops, startup_id_str );
01206
01207 if (reset_display) {
01208 unsetenv("KDE_DISPLAY");
01209 setenv(DISPLAY, olddisplay, true);
01210 }
01211
01212 if (pid && (d.result == 0))
01213 {
01214 response_header.cmd = LAUNCHER_OK;
01215 response_header.arg_length = sizeof(response_data);
01216 response_data = pid;
01217 write(sock, &response_header, sizeof(response_header));
01218 write(sock, &response_data, response_header.arg_length);
01219 }
01220 else
01221 {
01222 int l = d.errorMsg.length();
01223 if (l) l++;
01224 response_header.cmd = LAUNCHER_ERROR;
01225 response_header.arg_length = l;
01226 write(sock, &response_header, sizeof(response_header));
01227 if (l)
01228 write(sock, d.errorMsg.data(), l);
01229 }
01230 d.debug_wait = false;
01231 }
01232 else if (request_header.cmd == LAUNCHER_SETENV)
01233 {
01234 const char *env_name;
01235 const char *env_value;
01236 env_name = request_data;
01237 env_value = env_name + strlen(env_name) + 1;
01238
01239 #ifndef NDEBUG
01240 if (launcher)
01241 fprintf(stderr, "kdeinit: Got SETENV '%s=%s' from klauncher.\n", env_name, env_value);
01242 else
01243 fprintf(stderr, "kdeinit: Got SETENV '%s=%s' from socket.\n", env_name, env_value);
01244 #endif
01245
01246 if ( request_header.arg_length !=
01247 (int) (strlen(env_name) + strlen(env_value) + 2))
01248 {
01249 #ifndef NDEBUG
01250 fprintf(stderr, "kdeinit: SETENV request has invalid format.\n");
01251 #endif
01252 free(request_data);
01253 return;
01254 }
01255 setenv( env_name, env_value, 1);
01256 }
01257 else if (request_header.cmd == LAUNCHER_TERMINATE_KDE)
01258 {
01259 #ifndef NDEBUG
01260 fprintf(stderr,"kdeinit: terminate KDE.\n");
01261 #endif
01262 #ifdef Q_WS_X11
01263 kdeinit_xio_errhandler( 0L );
01264 #endif
01265 }
01266 else if (request_header.cmd == LAUNCHER_TERMINATE_KDEINIT)
01267 {
01268 #ifndef NDEBUG
01269 fprintf(stderr,"kdeinit: Killing kdeinit/klauncher.\n");
01270 #endif
01271 if (d.launcher_pid)
01272 kill(d.launcher_pid, SIGTERM);
01273 if (d.my_pid)
01274 kill(d.my_pid, SIGTERM);
01275 }
01276 else if (request_header.cmd == LAUNCHER_DEBUG_WAIT)
01277 {
01278 #ifndef NDEBUG
01279 fprintf(stderr,"kdeinit: Debug wait activated.\n");
01280 #endif
01281 d.debug_wait = true;
01282 }
01283 if (request_data)
01284 free(request_data);
01285 }
01286
01287 static void handle_requests(pid_t waitForPid)
01288 {
01289 int max_sock = d.wrapper;
01290 if (d.wrapper_old > max_sock)
01291 max_sock = d.wrapper_old;
01292 if (d.launcher_pid && (d.launcher[0] > max_sock))
01293 max_sock = d.launcher[0];
01294 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01295
01296 if (X11fd > max_sock)
01297 max_sock = X11fd;
01298 #endif
01299 max_sock++;
01300
01301 while(1)
01302 {
01303 fd_set rd_set;
01304 fd_set wr_set;
01305 fd_set e_set;
01306 int result;
01307 pid_t exit_pid;
01308 char c;
01309
01310
01311 while( read(d.deadpipe[0], &c, 1) == 1);
01312
01313
01314 do {
01315 exit_pid = waitpid(-1, 0, WNOHANG);
01316 if (exit_pid > 0)
01317 {
01318 #ifndef NDEBUG
01319 fprintf(stderr, "kdeinit: PID %ld terminated.\n", (long) exit_pid);
01320 #endif
01321 if (waitForPid && (exit_pid == waitForPid))
01322 return;
01323
01324 if (d.launcher_pid)
01325 {
01326
01327 klauncher_header request_header;
01328 long request_data[2];
01329 request_header.cmd = LAUNCHER_DIED;
01330 request_header.arg_length = sizeof(long) * 2;
01331 request_data[0] = exit_pid;
01332 request_data[1] = 0;
01333 write(d.launcher[0], &request_header, sizeof(request_header));
01334 write(d.launcher[0], request_data, request_header.arg_length);
01335 }
01336 }
01337 }
01338 while( exit_pid > 0);
01339
01340 FD_ZERO(&rd_set);
01341 FD_ZERO(&wr_set);
01342 FD_ZERO(&e_set);
01343
01344 if (d.launcher_pid)
01345 {
01346 FD_SET(d.launcher[0], &rd_set);
01347 }
01348 FD_SET(d.wrapper, &rd_set);
01349 if (d.wrapper_old)
01350 {
01351 FD_SET(d.wrapper_old, &rd_set);
01352 }
01353 FD_SET(d.deadpipe[0], &rd_set);
01354 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01355
01356 if(X11fd >= 0) FD_SET(X11fd, &rd_set);
01357 #endif
01358
01359 result = select(max_sock, &rd_set, &wr_set, &e_set, 0);
01360
01361
01362 if ((result > 0) && (FD_ISSET(d.wrapper, &rd_set)))
01363 {
01364 struct sockaddr_un client;
01365 kde_socklen_t sClient = sizeof(client);
01366 int sock = accept(d.wrapper, (struct sockaddr *)&client, &sClient);
01367 if (sock >= 0)
01368 {
01369 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
01370 if( !FcConfigUptoDate(NULL))
01371 FcInitReinitialize();
01372 #endif
01373 if (fork() == 0)
01374 {
01375 close_fds();
01376 handle_launcher_request(sock);
01377 exit(255);
01378 }
01379 close(sock);
01380 }
01381 }
01382 if ((result > 0) && (FD_ISSET(d.wrapper_old, &rd_set)))
01383 {
01384 struct sockaddr_un client;
01385 kde_socklen_t sClient = sizeof(client);
01386 int sock = accept(d.wrapper_old, (struct sockaddr *)&client, &sClient);
01387 if (sock >= 0)
01388 {
01389 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
01390 if( !FcConfigUptoDate(NULL))
01391 FcInitReinitialize();
01392 #endif
01393 if (fork() == 0)
01394 {
01395 close_fds();
01396 handle_launcher_request(sock);
01397 exit(255);
01398 }
01399 close(sock);
01400 }
01401 }
01402
01403
01404 if ((result > 0) && (d.launcher_pid) && (FD_ISSET(d.launcher[0], &rd_set)))
01405 {
01406 handle_launcher_request();
01407 if (waitForPid == d.launcher_pid)
01408 return;
01409 }
01410
01411
01412 #ifdef Q_WS_X11
01413
01414 if((result > 0) && (X11fd >= 0))
01415 {
01416 if(FD_ISSET(X11fd,&rd_set))
01417 {
01418 if (X11display != 0) {
01419 XEvent event_return;
01420 while (XPending(X11display))
01421 XNextEvent(X11display, &event_return);
01422 }
01423 }
01424 }
01425 #endif
01426 }
01427 }
01428
01429 static void kdeinit_library_path()
01430 {
01431 QStringList ltdl_library_path =
01432 QStringList::split(':', QFile::decodeName(getenv("LTDL_LIBRARY_PATH")));
01433 QStringList ld_library_path =
01434 QStringList::split(':', QFile::decodeName(getenv("LD_LIBRARY_PATH")));
01435
01436 QCString extra_path;
01437 QStringList candidates = s_instance->dirs()->resourceDirs("lib");
01438 for (QStringList::ConstIterator it = candidates.begin();
01439 it != candidates.end();
01440 it++)
01441 {
01442 QString d = *it;
01443 if (ltdl_library_path.contains(d))
01444 continue;
01445 if (ld_library_path.contains(d))
01446 continue;
01447 if (d[d.length()-1] == '/')
01448 {
01449 d.truncate(d.length()-1);
01450 if (ltdl_library_path.contains(d))
01451 continue;
01452 if (ld_library_path.contains(d))
01453 continue;
01454 }
01455 if ((d == "/lib") || (d == "/usr/lib"))
01456 continue;
01457
01458 QCString dir = QFile::encodeName(d);
01459
01460 if (access(dir, R_OK))
01461 continue;
01462
01463 if ( !extra_path.isEmpty())
01464 extra_path += ":";
01465 extra_path += dir;
01466 }
01467
01468 if (lt_dlinit())
01469 {
01470 const char * ltdlError = lt_dlerror();
01471 fprintf(stderr, "can't initialize dynamic loading: %s\n", ltdlError != 0 ? ltdlError : "(null)" );
01472 }
01473 if (!extra_path.isEmpty())
01474 lt_dlsetsearchpath(extra_path.data());
01475
01476 QCString display = getenv(DISPLAY);
01477 if (display.isEmpty())
01478 {
01479 fprintf(stderr, "kdeinit: Aborting. $"DISPLAY" is not set.\n");
01480 exit(255);
01481 }
01482 int i;
01483 if((i = display.findRev('.')) > display.findRev(':') && i >= 0)
01484 display.truncate(i);
01485
01486 QCString socketName = QFile::encodeName(locateLocal("socket", QString("kdeinit-%1").arg(display), s_instance));
01487 if (socketName.length() >= MAX_SOCK_FILE)
01488 {
01489 fprintf(stderr, "kdeinit: Aborting. Socket name will be too long:\n");
01490 fprintf(stderr, " '%s'\n", socketName.data());
01491 exit(255);
01492 }
01493 strcpy(sock_file_old, socketName.data());
01494
01495 display.replace(":","_");
01496 socketName = QFile::encodeName(locateLocal("socket", QString("kdeinit_%1").arg(display), s_instance));
01497 if (socketName.length() >= MAX_SOCK_FILE)
01498 {
01499 fprintf(stderr, "kdeinit: Aborting. Socket name will be too long:\n");
01500 fprintf(stderr, " '%s'\n", socketName.data());
01501 exit(255);
01502 }
01503 strcpy(sock_file, socketName.data());
01504 }
01505
01506 int kdeinit_xio_errhandler( Display *disp )
01507 {
01508
01509
01510 if ( disp )
01511 qWarning( "kdeinit: Fatal IO error: client killed" );
01512
01513 if (sock_file[0])
01514 {
01516 unlink(sock_file);
01517 }
01518 if (sock_file_old[0])
01519 {
01521 unlink(sock_file_old);
01522 }
01523
01524
01525 if (d.suicide)
01526 {
01527 if (d.launcher_pid)
01528 kill(d.launcher_pid, SIGTERM);
01529 exit( 0 );
01530 }
01531
01532 if ( disp )
01533 qWarning( "kdeinit: sending SIGHUP to children." );
01534
01535
01536 signal(SIGHUP, SIG_IGN);
01537 kill(0, SIGHUP);
01538
01539 sleep(2);
01540
01541 if ( disp )
01542 qWarning( "kdeinit: sending SIGTERM to children." );
01543
01544
01545 signal(SIGTERM, SIG_IGN);
01546 kill(0, SIGTERM);
01547
01548 if ( disp )
01549 qWarning( "kdeinit: Exit." );
01550
01551 exit( 0 );
01552 return 0;
01553 }
01554
01555 #ifdef Q_WS_X11
01556 int kdeinit_x_errhandler( Display *dpy, XErrorEvent *err )
01557 {
01558 #ifndef NDEBUG
01559 char errstr[256];
01560
01561 XGetErrorText( dpy, err->error_code, errstr, 256 );
01562 fprintf(stderr, "kdeinit: KDE detected X Error: %s %d\n"
01563 " Major opcode: %d\n"
01564 " Minor opcode: %d\n"
01565 " Resource id: 0x%lx\n",
01566 errstr, err->error_code, err->request_code, err->minor_code, err->resourceid );
01567 #else
01568 Q_UNUSED(dpy);
01569 Q_UNUSED(err);
01570 #endif
01571 return 0;
01572 }
01573 #endif
01574
01575
01576 #ifdef Q_WS_X11
01577
01578
01579 static void setupX()
01580 {
01581 XSetIOErrorHandler(kdeinit_xio_errhandler);
01582 XSetErrorHandler(kdeinit_x_errhandler);
01583 }
01584
01585
01586 static int initXconnection()
01587 {
01588 X11display = XOpenDisplay(NULL);
01589 if ( X11display != 0 ) {
01590 XCreateSimpleWindow(X11display, DefaultRootWindow(X11display), 0,0,1,1, \
01591 0,
01592 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)),
01593 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)) );
01594 #ifndef NDEBUG
01595 fprintf(stderr, "kdeinit: opened connection to %s\n", DisplayString(X11display));
01596 #endif
01597 int fd = XConnectionNumber( X11display );
01598 int on = 1;
01599 (void) setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, (int) sizeof(on));
01600 return fd;
01601 } else
01602 fprintf(stderr, "kdeinit: Can't connect to the X Server.\n" \
01603 "kdeinit: Might not terminate at end of session.\n");
01604
01605 return -1;
01606 }
01607 #endif
01608
01609 #ifdef __KCC
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629 extern "C" void _main(void);
01630 extern "C" void __call_ctors__Fv(void);
01631 static int main_called = 0;
01632 void _main(void)
01633 {
01634 if (main_called)
01635 return;
01636 main_called = 1;
01637 __call_ctors__Fv ();
01638 }
01639 #endif
01640
01641 static void secondary_child_handler(int)
01642 {
01643 waitpid(-1, 0, WNOHANG);
01644 }
01645
01646 int main(int argc, char **argv, char **envp)
01647 {
01648 int i;
01649 pid_t pid;
01650 int launch_dcop = 1;
01651 int launch_klauncher = 1;
01652 int launch_kded = 1;
01653 int keep_running = 1;
01654 d.suicide = false;
01655
01657 char **safe_argv = (char **) malloc( sizeof(char *) * argc);
01658 for(i = 0; i < argc; i++)
01659 {
01660 safe_argv[i] = strcpy((char*)malloc(strlen(argv[i])+1), argv[i]);
01661 if (strcmp(safe_argv[i], "--no-dcop") == 0)
01662 launch_dcop = 0;
01663 if (strcmp(safe_argv[i], "--no-klauncher") == 0)
01664 launch_klauncher = 0;
01665 if (strcmp(safe_argv[i], "--no-kded") == 0)
01666 launch_kded = 0;
01667 if (strcmp(safe_argv[i], "--suicide") == 0)
01668 d.suicide = true;
01669 if (strcmp(safe_argv[i], "--exit") == 0)
01670 keep_running = 0;
01671 if (strcmp(safe_argv[i], "--help") == 0)
01672 {
01673 printf("Usage: kdeinit [options]\n");
01674
01675
01676 printf(" --no-kded Do not start kded\n");
01677 printf(" --suicide Terminate when no KDE applications are left running\n");
01678
01679 exit(0);
01680 }
01681 }
01682
01683 pipe(d.initpipe);
01684
01685
01686
01687
01688 signal( SIGCHLD, secondary_child_handler);
01689 if (fork() > 0)
01690 {
01691 close(d.initpipe[1]);
01692 d.initpipe[1] = -1;
01693
01694 char c;
01695 while( read(d.initpipe[0], &c, 1) < 0);
01696
01697 close(d.initpipe[0]);
01698 d.initpipe[0] = -1;
01699 return 0;
01700 }
01701 close(d.initpipe[0]);
01702 d.initpipe[0] = -1;
01703 d.my_pid = getpid();
01704
01706 if(keep_running)
01707 setsid();
01708
01710 s_instance = new KInstance("kdeinit");
01711
01712 KGlobal::_instance = 0L;
01713
01715 kdeinit_initsetproctitle(argc, argv, envp);
01716 kdeinit_setproctitle("kdeinit Starting up...");
01717 kdeinit_library_path();
01718
01719 unsetenv("LD_BIND_NOW");
01720 unsetenv("DYLD_BIND_AT_LAUNCH");
01721 KApplication::loadedByKdeinit = true;
01722
01723 d.maxname = strlen(argv[0]);
01724 d.launcher_pid = 0;
01725 d.wrapper = 0;
01726 d.wrapper_old = 0;
01727 d.debug_wait = false;
01728 d.launcher_ok = false;
01729 d.lt_dlopen_flag = lt_dlopen_flag;
01730 lt_dlopen_flag |= LTDL_GLOBAL;
01731 init_signals();
01732 #ifdef Q_WS_X11
01733 setupX();
01734 #endif
01735
01736 if (keep_running)
01737 {
01738
01739
01740
01741
01742 init_kdeinit_socket();
01743 }
01744
01745 if (launch_dcop)
01746 {
01747 if (d.suicide)
01748 pid = launch( 3, "dcopserver", "--nosid\0--suicide" );
01749 else
01750 pid = launch( 2, "dcopserver", "--nosid" );
01751 #ifndef NDEBUG
01752 fprintf(stderr, "kdeinit: Launched DCOPServer, pid = %ld result = %d\n", (long) pid, d.result);
01753 #endif
01754 WaitPid(pid);
01755 if (!WIFEXITED(d.exit_status) || (WEXITSTATUS(d.exit_status) != 0))
01756 {
01757 fprintf(stderr, "kdeinit: DCOPServer could not be started, aborting.\n");
01758 exit(1);
01759 }
01760 }
01761 #ifndef __CYGWIN__
01762 if (!d.suicide && !getenv("KDE_IS_PRELINKED"))
01763 {
01764 QString konq = locate("lib", "libkonq.la", s_instance);
01765 if (!konq.isEmpty())
01766 (void) lt_dlopen(QFile::encodeName(konq).data());
01767 }
01768 #endif
01769 if (launch_klauncher)
01770 {
01771 pid = launch( 1, "klauncher", 0 );
01772 #ifndef NDEBUG
01773 fprintf(stderr, "kdeinit: Launched KLauncher, pid = %ld result = %d\n", (long) pid, d.result);
01774 #endif
01775 handle_requests(pid);
01776 }
01777
01778 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01779
01780 X11fd = initXconnection();
01781 #endif
01782
01783 {
01784 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
01785 XftInit(0);
01786 XftInitFtLibrary();
01787 #endif
01788 QFont::initialize();
01789 setlocale (LC_ALL, "");
01790 setlocale (LC_NUMERIC, "C");
01791 #ifdef Q_WS_X11
01792 if (XSupportsLocale ())
01793 {
01794
01795
01796 XOpenIM (X11display, 0, 0, 0);
01797 }
01798 #endif
01799 }
01800
01801 if (launch_kded)
01802 {
01803 pid = launch( 1, "kded", 0 );
01804 #ifndef NDEBUG
01805 fprintf(stderr, "kdeinit: Launched KDED, pid = %ld result = %d\n", (long) pid, d.result);
01806 #endif
01807 handle_requests(pid);
01808 }
01809
01810 for(i = 1; i < argc; i++)
01811 {
01812 if (safe_argv[i][0] == '+')
01813 {
01814 pid = launch( 1, safe_argv[i]+1, 0);
01815 #ifndef NDEBUG
01816 fprintf(stderr, "kdeinit: Launched '%s', pid = %ld result = %d\n", safe_argv[i]+1, (long) pid, d.result);
01817 #endif
01818 handle_requests(pid);
01819 }
01820 else if (safe_argv[i][0] == '-')
01821 {
01822
01823 }
01824 else
01825 {
01826 pid = launch( 1, safe_argv[i], 0 );
01827 #ifndef NDEBUG
01828 fprintf(stderr, "kdeinit: Launched '%s', pid = %ld result = %d\n", safe_argv[i], (long) pid, d.result);
01829 #endif
01830 }
01831 }
01832
01834 for(i = 0; i < argc; i++)
01835 {
01836 free(safe_argv[i]);
01837 }
01838 free (safe_argv);
01839
01840 kdeinit_setproctitle("kdeinit Running...");
01841
01842 if (!keep_running)
01843 return 0;
01844
01845 char c = 0;
01846 write(d.initpipe[1], &c, 1);
01847 close(d.initpipe[1]);
01848 d.initpipe[1] = -1;
01849
01850 handle_requests(0);
01851
01852 return 0;
01853 }
01854