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