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