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