00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <sys/types.h>
00025 #include <sys/time.h>
00026 #include <sys/stat.h>
00027 #include <sys/socket.h>
00028 #include <sys/un.h>
00029 #include <sys/wait.h>
00030 #ifdef HAVE_SYS_SELECT_H
00031 #include <sys/select.h>
00032 #endif
00033
00034 #include <errno.h>
00035 #include <fcntl.h>
00036 #include "proctitle.h"
00037 #include <signal.h>
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <unistd.h>
00042 #include <locale.h>
00043
00044 #include <QtCore/QLibrary>
00045 #include <QtCore/QString>
00046 #include <QtCore/QFile>
00047 #include <QtCore/QDate>
00048 #include <QtCore/QFileInfo>
00049 #include <QtCore/QTextStream>
00050 #include <QtCore/QRegExp>
00051 #include <QtGui/QFont>
00052 #include <kcomponentdata.h>
00053 #include <kstandarddirs.h>
00054 #include <kglobal.h>
00055 #include <kconfig.h>
00056 #include <klibloader.h>
00057 #include <kapplication.h>
00058 #include <klocale.h>
00059 #include <kdebug.h>
00060
00061 #ifdef Q_OS_LINUX
00062 #include <sys/prctl.h>
00063 #ifndef PR_SET_NAME
00064 #define PR_SET_NAME 15
00065 #endif
00066 #endif
00067
00068 #include <kdeversion.h>
00069
00070 #include "klauncher_cmds.h"
00071
00072 #ifdef Q_WS_X11
00073 #include <X11/Xlib.h>
00074 #include <X11/Xatom.h>
00075 #include <fixx11h.h>
00076 #include <kstartupinfo.h>
00077 #endif
00078
00079 #if KDE_IS_VERSION( 3, 90, 0 )
00080 #ifdef __GNUC__
00081 #warning Check if Linux OOM-killer still sucks and if yes, forwardport revision 579164 and following fixes.
00082 #endif
00083 #endif
00084
00085 extern char **environ;
00086
00087 #ifdef Q_WS_X11
00088 static int X11fd = -1;
00089 static Display *X11display = 0;
00090 static int X11_startup_notify_fd = -1;
00091 static Display *X11_startup_notify_display = 0;
00092 #endif
00093 static KComponentData *s_instance = 0;
00094 #define MAX_SOCK_FILE 255
00095 static char sock_file[MAX_SOCK_FILE];
00096
00097
00098 #ifdef Q_WS_X11
00099 #define DISPLAY "DISPLAY"
00100 #elif defined(Q_WS_QWS)
00101 #define DISPLAY "QWS_DISPLAY"
00102 #elif defined(Q_WS_MACX)
00103 #define DISPLAY "MAC_DISPLAY"
00104 #elif defined(Q_WS_WIN)
00105 #define DISPLAY "WIN_DISPLAY"
00106 #else
00107 #error Use QT/X11 or QT/Embedded
00108 #endif
00109
00110
00111 static struct {
00112 int maxname;
00113 int fd[2];
00114 int launcher[2];
00115 int deadpipe[2];
00116 int initpipe[2];
00117 int wrapper;
00118 int wrapper_old;
00119 char result;
00120 int exit_status;
00121 pid_t fork;
00122 pid_t launcher_pid;
00123 pid_t kded_pid;
00124 pid_t my_pid;
00125 int n;
00126 char **argv;
00127 int (*func)(int, char *[]);
00128 int (*launcher_func)(int);
00129 bool debug_wait;
00130 QByteArray errorMsg;
00131 bool launcher_ok;
00132 bool suicide;
00133 } d;
00134
00135 #ifdef Q_WS_X11
00136 extern "C" {
00137 int kdeinit_xio_errhandler( Display * );
00138 int kdeinit_x_errhandler( Display *, XErrorEvent *err );
00139 }
00140 #endif
00141
00142
00143 #include <kparts/plugin.h>
00144 extern "C" KParts::Plugin* _kinit_init_kparts() { return new KParts::Plugin(); }
00145
00146 #include <kio/authinfo.h>
00147 extern "C" KIO::AuthInfo* _kioslave_init_kio() { return new KIO::AuthInfo(); }
00148
00149
00150
00151
00152
00153 static void close_fds()
00154 {
00155 if (d.deadpipe[0] != -1)
00156 {
00157 close(d.deadpipe[0]);
00158 d.deadpipe[0] = -1;
00159 }
00160
00161 if (d.deadpipe[1] != -1)
00162 {
00163 close(d.deadpipe[1]);
00164 d.deadpipe[1] = -1;
00165 }
00166
00167 if (d.initpipe[0] != -1)
00168 {
00169 close(d.initpipe[0]);
00170 d.initpipe[0] = -1;
00171 }
00172
00173 if (d.initpipe[1] != -1)
00174 {
00175 close(d.initpipe[1]);
00176 d.initpipe[1] = -1;
00177 }
00178
00179 if (d.launcher_pid)
00180 {
00181 close(d.launcher[0]);
00182 d.launcher_pid = 0;
00183 }
00184 if (d.wrapper)
00185 {
00186 close(d.wrapper);
00187 d.wrapper = 0;
00188 }
00189 if (d.wrapper_old)
00190 {
00191 close(d.wrapper_old);
00192 d.wrapper_old = 0;
00193 }
00194 #ifdef Q_WS_X11
00195 if (X11fd >= 0)
00196 {
00197 close(X11fd);
00198 X11fd = -1;
00199 }
00200 if (X11_startup_notify_fd >= 0 && X11_startup_notify_fd != X11fd )
00201 {
00202 close(X11_startup_notify_fd);
00203 X11_startup_notify_fd = -1;
00204 }
00205 #endif
00206
00207 signal(SIGCHLD, SIG_DFL);
00208 signal(SIGPIPE, SIG_DFL);
00209 }
00210
00211 static void exitWithErrorMsg(const QString &errorMsg)
00212 {
00213 fprintf( stderr, "%s\n", errorMsg.toLocal8Bit().data() );
00214 QByteArray utf8ErrorMsg = errorMsg.toUtf8();
00215 d.result = 3;
00216 write(d.fd[1], &d.result, 1);
00217 int l = utf8ErrorMsg.length();
00218 write(d.fd[1], &l, sizeof(int));
00219 write(d.fd[1], utf8ErrorMsg.data(), l);
00220 close(d.fd[1]);
00221 exit(255);
00222 }
00223
00224 static void setup_tty( const char* tty )
00225 {
00226 if( tty == NULL || *tty == '\0' )
00227 return;
00228 int fd = open( tty, O_WRONLY );
00229 if( fd < 0 )
00230 {
00231 perror( "kdeinit4: couldn't open() tty" );
00232 return;
00233 }
00234 if( dup2( fd, STDOUT_FILENO ) < 0 )
00235 {
00236 perror( "kdeinit4: couldn't dup2() tty" );
00237 close( fd );
00238 return;
00239 }
00240 if( dup2( fd, STDERR_FILENO ) < 0 )
00241 {
00242 perror( "kdeinit4: couldn't dup2() tty" );
00243 close( fd );
00244 return;
00245 }
00246 close( fd );
00247 }
00248
00249
00250 static int get_current_desktop( Display* disp )
00251 {
00252 int desktop = 0;
00253 #ifdef Q_WS_X11 // Only X11 supports multiple desktops
00254 Atom net_current_desktop = XInternAtom( disp, "_NET_CURRENT_DESKTOP", False );
00255 Atom type_ret;
00256 int format_ret;
00257 unsigned char *data_ret;
00258 unsigned long nitems_ret, unused;
00259 if( XGetWindowProperty( disp, DefaultRootWindow( disp ), net_current_desktop,
00260 0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret )
00261 == Success)
00262 {
00263 if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1)
00264 desktop = *((long *) data_ret) + 1;
00265 if (data_ret)
00266 XFree ((char*) data_ret);
00267 }
00268 #endif
00269 return desktop;
00270 }
00271
00272
00273 const char* get_env_var( const char* var, int envc, const char* envs )
00274 {
00275 if( envc > 0 )
00276 {
00277 const char* env_l = envs;
00278 int ln = strlen( var );
00279 for (int i = 0; i < envc; i++)
00280 {
00281 if( strncmp( env_l, var, ln ) == 0 )
00282 return env_l + ln;
00283 while(*env_l != 0) env_l++;
00284 env_l++;
00285 }
00286 }
00287 return NULL;
00288 }
00289
00290 #ifdef Q_WS_X11
00291 static void init_startup_info( KStartupInfoId& id, const char* bin,
00292 int envc, const char* envs )
00293 {
00294 const char* dpy = get_env_var( DISPLAY"=", envc, envs );
00295
00296
00297 X11_startup_notify_display = XOpenDisplay( dpy );
00298 if( X11_startup_notify_display == NULL )
00299 return;
00300 X11_startup_notify_fd = XConnectionNumber( X11_startup_notify_display );
00301 KStartupInfoData data;
00302 int desktop = get_current_desktop( X11_startup_notify_display );
00303 data.setDesktop( desktop );
00304 data.setBin( bin );
00305 KStartupInfo::sendChangeX( X11_startup_notify_display, id, data );
00306 XFlush( X11_startup_notify_display );
00307 }
00308
00309 static void complete_startup_info( KStartupInfoId& id, pid_t pid )
00310 {
00311 if( X11_startup_notify_display == NULL )
00312 return;
00313 if( pid == 0 )
00314 KStartupInfo::sendFinishX( X11_startup_notify_display, id );
00315 else
00316 {
00317 KStartupInfoData data;
00318 data.addPid( pid );
00319 data.setHostname();
00320 KStartupInfo::sendChangeX( X11_startup_notify_display, id, data );
00321 }
00322 XCloseDisplay( X11_startup_notify_display );
00323 X11_startup_notify_display = NULL;
00324 X11_startup_notify_fd = -1;
00325 }
00326 #endif
00327
00328 QByteArray execpath_avoid_loops( const QByteArray& exec, int envc, const char* envs, bool avoid_loops )
00329 {
00330 QStringList paths;
00331 if( envc > 0 )
00332 {
00333 const char* path = get_env_var( "PATH=", envc, envs );
00334 if( path != NULL )
00335 paths = QString(path).split( QRegExp( "[:\b]" ));
00336 }
00337 else
00338 paths = QString( getenv("PATH") ).split( QRegExp( "[:\b]" ), QString::KeepEmptyParts );
00339 QByteArray execpath = QFile::encodeName(
00340 s_instance->dirs()->findExe( exec, paths.join( QString( ":" ))));
00341 if( avoid_loops && !execpath.isEmpty())
00342 {
00343 int pos = execpath.lastIndexOf( '/' );
00344 QString bin_path = execpath.left( pos );
00345 for( QStringList::Iterator it = paths.begin();
00346 it != paths.end();
00347 ++it )
00348 if( ( *it ) == bin_path || ( *it ) == bin_path + '/' )
00349 {
00350 paths.erase( it );
00351 break;
00352 }
00353 execpath = QFile::encodeName(
00354 s_instance->dirs()->findExe( exec, paths.join( QString( ":" ))));
00355 }
00356 return execpath;
00357 }
00358
00359 static pid_t launch(int argc, const char *_name, const char *args,
00360 const char *cwd=0, int envc=0, const char *envs=0,
00361 bool reset_env = false,
00362 const char *tty=0, bool avoid_loops = false,
00363 const char* startup_id_str = "0" )
00364 {
00365 int launcher = 0;
00366 QByteArray lib;
00367 QByteArray name;
00368 QByteArray exec;
00369
00370 if (strcmp(_name, "klauncher") == 0) {
00371
00372
00373
00374 if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, d.launcher))
00375 {
00376 perror("kdeinit4: socketpair() failed!\n");
00377 exit(255);
00378 }
00379 launcher = 1;
00380 }
00381
00382 QByteArray libpath;
00383 QByteArray execpath;
00384 if (_name[0] != '/')
00385 {
00386 lib = name = _name;
00387 exec = name;
00388 libpath = QFile::encodeName(KLibLoader::findLibrary(lib.constData(), *s_instance));
00389 execpath = execpath_avoid_loops( exec, envc, envs, avoid_loops );
00390 }
00391 else
00392 {
00393 lib = _name;
00394 name = _name;
00395 name = name.mid( name.lastIndexOf('/') + 1);
00396 exec = _name;
00397 if (lib.endsWith(".la"))
00398 libpath = lib;
00399 else
00400 execpath = exec;
00401 }
00402 fprintf(stderr,"kdeinit4: preparing to launch %s\n", execpath.constData());
00403 if (!args)
00404 {
00405 argc = 1;
00406 }
00407
00408 if (0 > pipe(d.fd))
00409 {
00410 perror("kdeinit4: pipe() failed!\n");
00411 d.result = 3;
00412 d.errorMsg = i18n("Unable to start new process.\n"
00413 "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();
00414 close(d.fd[0]);
00415 close(d.fd[1]);
00416 d.fork = 0;
00417 return d.fork;
00418 }
00419
00420 #ifdef Q_WS_X11
00421 KStartupInfoId startup_id;
00422 startup_id.initId( startup_id_str );
00423 if( !startup_id.none())
00424 init_startup_info( startup_id, name, envc, envs );
00425 #endif
00426
00427 d.errorMsg = 0;
00428 d.fork = fork();
00429 switch(d.fork) {
00430 case -1:
00431 perror("kdeinit4: fork() failed!\n");
00432 d.result = 3;
00433 d.errorMsg = i18n("Unable to create new process.\n"
00434 "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();
00435 close(d.fd[0]);
00436 close(d.fd[1]);
00437 d.fork = 0;
00438 break;
00439 case 0:
00440 {
00442 close(d.fd[0]);
00443 close_fds();
00444 if (launcher)
00445 {
00446 if (d.fd[1] == LAUNCHER_FD)
00447 {
00448 d.fd[1] = dup(d.fd[1]);
00449 }
00450 if (d.launcher[1] != LAUNCHER_FD)
00451 {
00452 dup2( d.launcher[1], LAUNCHER_FD);
00453 close( d.launcher[1] );
00454 }
00455 close( d.launcher[0] );
00456 }
00457
00458 if (cwd && *cwd)
00459 chdir(cwd);
00460
00461 if( reset_env )
00462 {
00463
00464 QList<QByteArray> unset_envs;
00465 for( int tmp_env_count = 0;
00466 environ[tmp_env_count];
00467 tmp_env_count++)
00468 unset_envs.append( environ[ tmp_env_count ] );
00469 foreach(QByteArray tmp, unset_envs)
00470 {
00471 int pos = tmp.indexOf( '=' );
00472 if( pos >= 0 )
00473 unsetenv( tmp.left( pos ));
00474 }
00475 }
00476
00477 for (int i = 0; i < envc; i++)
00478 {
00479 putenv((char *)envs);
00480 while(*envs != 0) envs++;
00481 envs++;
00482 }
00483
00484 #ifdef Q_WS_X11
00485 if( startup_id.none())
00486 KStartupInfo::resetStartupEnv();
00487 else
00488 startup_id.setupStartupEnv();
00489 #endif
00490 {
00491 int r;
00492 QByteArray procTitle;
00493 d.argv = (char **) malloc(sizeof(char *) * (argc+1));
00494 d.argv[0] = (char *) _name;
00495 #ifdef Q_WS_MAC
00496 QString argvexe = s_instance->dirs()->findExe(QString::fromLatin1(d.argv[0]));
00497 if (!argvexe.isEmpty()) {
00498 QByteArray cstr = argvexe.toLocal8Bit();
00499 kDebug(7016) << "kdeinit4: launch() setting argv: " << cstr.data();
00500 d.argv[0] = strdup(cstr.data());
00501 }
00502 #endif
00503 for (int i = 1; i < argc; i++)
00504 {
00505 d.argv[i] = (char *) args;
00506 procTitle += ' ';
00507 procTitle += (char *) args;
00508 while(*args != 0) args++;
00509 args++;
00510 }
00511 d.argv[argc] = 0;
00512
00514 #ifdef Q_OS_LINUX
00515
00516 r = prctl(PR_SET_NAME, (unsigned long) name.data(), 0, 0, 0);
00517 if ( r == 0 )
00518 proctitle_set( "%s [kdeinit]%s", name.data(), procTitle.data() ? procTitle.data() : "" );
00519 else
00520 proctitle_set( "kdeinit4: %s%s", name.data(), procTitle.data() ? procTitle.data() : "" );
00521 #else
00522 proctitle_set( "kdeinit4: %s%s", name.data(), procTitle.data() ? procTitle.data() : "" );
00523 #endif
00524 }
00525
00526 if (libpath.isEmpty() && execpath.isEmpty())
00527 {
00528 QString errorMsg = i18n("Could not find '%1' executable.", QFile::decodeName(_name));
00529 exitWithErrorMsg(errorMsg);
00530 }
00531
00532
00533 if ( getenv("KDE_IS_PRELINKED") && !execpath.isEmpty() && !launcher)
00534 libpath.truncate(0);
00535
00536 QLibrary l(libpath);
00537
00538 if ( !libpath.isEmpty() )
00539 {
00540 if (!l.load() || !l.isLoaded() )
00541 {
00542 QString ltdlError (l.errorString());
00543 if (execpath.isEmpty())
00544 {
00545
00546 QString errorMsg = i18n("Could not open library '%1'.\n%2", QFile::decodeName(libpath), ltdlError);
00547 exitWithErrorMsg(errorMsg);
00548 }
00549 else
00550 {
00551
00552 fprintf(stderr, "Could not open library %s: %s\n", lib.data(),
00553 qPrintable(ltdlError) );
00554 }
00555 }
00556 }
00557 if (!l.isLoaded())
00558 {
00559 d.result = 2;
00560 write(d.fd[1], &d.result, 1);
00561
00562
00563
00564 fcntl(d.fd[1], F_SETFD, FD_CLOEXEC);
00565
00566 setup_tty( tty );
00567
00568 QByteArray executable = execpath.data();
00569 #ifdef Q_WS_MAC
00570 QString bundlepath = s_instance->dirs()->findExe( execpath.data() );
00571 if (!bundlepath.isEmpty())
00572 executable = QFile::encodeName(bundlepath);
00573 #endif
00574
00575 if (!executable.isEmpty())
00576 execvp(executable, d.argv);
00577
00578 d.result = 1;
00579 write(d.fd[1], &d.result, 1);
00580 close(d.fd[1]);
00581 exit(255);
00582 }
00583
00584 void * sym = l.resolve( "kdeinitmain");
00585 if (!sym )
00586 {
00587 sym = l.resolve( "kdemain" );
00588 if ( !sym )
00589 {
00590 QString ltdlError = l.errorString();
00591 fprintf(stderr, "Could not find kdemain: %s\n", qPrintable(ltdlError) );
00592 QString errorMsg = i18n("Could not find 'kdemain' in '%1'.\n%2",
00593 QLatin1String(libpath), ltdlError);
00594 exitWithErrorMsg(errorMsg);
00595 }
00596 }
00597
00598 d.result = 0;
00599 write(d.fd[1], &d.result, 1);
00600 close(d.fd[1]);
00601
00602 d.func = (int (*)(int, char *[])) sym;
00603 if (d.debug_wait)
00604 {
00605 fprintf(stderr, "kdeinit4: Suspending process\n"
00606 "kdeinit4: 'gdb kdeinit4 %d' to debug\n"
00607 "kdeinit4: 'kill -SIGCONT %d' to continue\n",
00608 getpid(), getpid());
00609 kill(getpid(), SIGSTOP);
00610 }
00611 else
00612 {
00613 setup_tty( tty );
00614 }
00615
00616 exit( d.func(argc, d.argv));
00617
00618 break;
00619 }
00620 default:
00622 close(d.fd[1]);
00623 if (launcher)
00624 {
00625 close(d.launcher[1]);
00626 d.launcher_pid = d.fork;
00627 }
00628 bool exec = false;
00629 for(;;)
00630 {
00631 d.n = read(d.fd[0], &d.result, 1);
00632 if (d.n == 1)
00633 {
00634 if (d.result == 2)
00635 {
00636 #ifndef NDEBUG
00637
00638 #endif
00639 exec = true;
00640 continue;
00641 }
00642 if (d.result == 3)
00643 {
00644 int l = 0;
00645 d.n = read(d.fd[0], &l, sizeof(int));
00646 if (d.n == sizeof(int))
00647 {
00648 QByteArray tmp;
00649 tmp.resize(l+1);
00650 d.n = read(d.fd[0], tmp.data(), l);
00651 tmp[l] = 0;
00652 if (d.n == l)
00653 d.errorMsg = tmp;
00654 }
00655 }
00656
00657 break;
00658 }
00659 if (d.n == -1)
00660 {
00661 if (errno == ECHILD) {
00662 continue;
00663 }
00664 if (errno == EINTR || errno == EAGAIN) {
00665 continue;
00666 }
00667 }
00668 if (exec)
00669 {
00670 d.result = 0;
00671 break;
00672 }
00673 if (d.n == 0)
00674 {
00675 fprintf(stderr,"kdeinit4: (%s %s) Pipe closed unexpectedly", name.constData(), execpath.constData());
00676 perror("kdeinit4: Pipe closed unexpectedly");
00677 d.result = 1;
00678 break;
00679 }
00680 perror("kdeinit4: Error reading from pipe");
00681 d.result = 1;
00682 break;
00683 }
00684 close(d.fd[0]);
00685 if (launcher && (d.result == 0))
00686 {
00687
00688 d.launcher_pid = d.fork;
00689 }
00690 }
00691 #ifdef Q_WS_X11
00692 if( !startup_id.none())
00693 {
00694 if( d.fork && d.result == 0 )
00695 complete_startup_info( startup_id, d.fork );
00696 else
00697 complete_startup_info( startup_id, 0 );
00698 }
00699 #endif
00700 return d.fork;
00701 }
00702
00703 static void sig_child_handler(int)
00704 {
00705
00706
00707
00708
00709
00710
00711
00712
00713 char c = 0;
00714 write(d.deadpipe[1], &c, 1);
00715 }
00716
00717 static void init_signals()
00718 {
00719 struct sigaction act;
00720 long options;
00721
00722 if (pipe(d.deadpipe) != 0)
00723 {
00724 perror("kdeinit4: Aborting. Can't create pipe: ");
00725 exit(255);
00726 }
00727
00728 options = fcntl(d.deadpipe[0], F_GETFL);
00729 if (options == -1)
00730 {
00731 perror("kdeinit4: Aborting. Can't make pipe non-blocking: ");
00732 exit(255);
00733 }
00734
00735 if (fcntl(d.deadpipe[0], F_SETFL, options | O_NONBLOCK) == -1)
00736 {
00737 perror("kdeinit4: Aborting. Can't make pipe non-blocking: ");
00738 exit(255);
00739 }
00740
00741
00742
00743
00744
00745
00746 act.sa_handler=sig_child_handler;
00747 sigemptyset(&(act.sa_mask));
00748 sigaddset(&(act.sa_mask), SIGCHLD);
00749 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
00750 act.sa_flags = SA_NOCLDSTOP;
00751
00752
00753
00754
00755 #ifdef SA_RESTART
00756 act.sa_flags |= SA_RESTART;
00757 #endif
00758 sigaction( SIGCHLD, &act, 0L);
00759
00760 act.sa_handler=SIG_IGN;
00761 sigemptyset(&(act.sa_mask));
00762 sigaddset(&(act.sa_mask), SIGPIPE);
00763 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
00764 act.sa_flags = 0;
00765 sigaction( SIGPIPE, &act, 0L);
00766 }
00767
00768 static void init_kdeinit_socket()
00769 {
00770 struct sockaddr_un sa;
00771
00772 kde_socklen_t socklen;
00773 long options;
00774 const char *home_dir = getenv("HOME");
00775 int max_tries = 10;
00776 if (!home_dir || !home_dir[0])
00777 {
00778 fprintf(stderr, "kdeinit4: Aborting. $HOME not set!");
00779 exit(255);
00780 }
00781 chdir(home_dir);
00782
00783 {
00784 QByteArray path = home_dir;
00785 QByteArray readOnly = getenv("KDE_HOME_READONLY");
00786 if (access(path.data(), R_OK|W_OK))
00787 {
00788 if (errno == ENOENT)
00789 {
00790 fprintf(stderr, "kdeinit4: Aborting. $HOME directory (%s) does not exist.\n", path.data());
00791 exit(255);
00792 }
00793 else if (readOnly.isEmpty())
00794 {
00795 fprintf(stderr, "kdeinit4: Aborting. No write access to $HOME directory (%s).\n", path.data());
00796 exit(255);
00797 }
00798 }
00799 #if 0 // obsolete in kde4. Should we check writing to another file instead?
00800 path = getenv("ICEAUTHORITY");
00801 if (path.isEmpty())
00802 {
00803 path = home_dir;
00804 path += "/.ICEauthority";
00805 }
00806 if (access(path.data(), R_OK|W_OK) && (errno != ENOENT))
00807 {
00808 fprintf(stderr, "kdeinit4: Aborting. No write access to '%s'.\n", path.data());
00809 exit(255);
00810 }
00811 #endif
00812 }
00813
00818 if (access(sock_file, W_OK) == 0)
00819 {
00820 int s;
00821 struct sockaddr_un server;
00822
00823
00824
00825
00826
00827 s = socket(PF_UNIX, SOCK_STREAM, 0);
00828 if (s < 0)
00829 {
00830 perror("socket() failed: ");
00831 exit(255);
00832 }
00833 server.sun_family = AF_UNIX;
00834 strcpy(server.sun_path, sock_file);
00835 socklen = sizeof(server);
00836
00837 if(connect(s, (struct sockaddr *)&server, socklen) == 0)
00838 {
00839 fprintf(stderr, "kdeinit4: Shutting down running client.\n");
00840 klauncher_header request_header;
00841 request_header.cmd = LAUNCHER_TERMINATE_KDEINIT;
00842 request_header.arg_length = 0;
00843 write(s, &request_header, sizeof(request_header));
00844 sleep(1);
00845 }
00846 close(s);
00847 }
00848
00850 unlink(sock_file);
00851
00852
00854 d.wrapper = socket(PF_UNIX, SOCK_STREAM, 0);
00855 if (d.wrapper < 0)
00856 {
00857 perror("kdeinit4: Aborting. socket() failed: ");
00858 exit(255);
00859 }
00860
00861 options = fcntl(d.wrapper, F_GETFL);
00862 if (options == -1)
00863 {
00864 perror("kdeinit4: Aborting. Can't make socket non-blocking: ");
00865 close(d.wrapper);
00866 exit(255);
00867 }
00868
00869 if (fcntl(d.wrapper, F_SETFL, options | O_NONBLOCK) == -1)
00870 {
00871 perror("kdeinit4: Aborting. Can't make socket non-blocking: ");
00872 close(d.wrapper);
00873 exit(255);
00874 }
00875
00876 while (1) {
00878 socklen = sizeof(sa);
00879 memset(&sa, 0, socklen);
00880 sa.sun_family = AF_UNIX;
00881 strcpy(sa.sun_path, sock_file);
00882 if(bind(d.wrapper, (struct sockaddr *)&sa, socklen) != 0)
00883 {
00884 if (max_tries == 0) {
00885 perror("kdeinit4: Aborting. bind() failed: ");
00886 fprintf(stderr, "Could not bind to socket '%s'\n", sock_file);
00887 close(d.wrapper);
00888 exit(255);
00889 }
00890 max_tries--;
00891 } else
00892 break;
00893 }
00894
00896 if (chmod(sock_file, 0600) != 0)
00897 {
00898 perror("kdeinit4: Aborting. Can't set permissions on socket: ");
00899 fprintf(stderr, "Wrong permissions of socket '%s'\n", sock_file);
00900 unlink(sock_file);
00901 close(d.wrapper);
00902 exit(255);
00903 }
00904
00905 if(listen(d.wrapper, SOMAXCONN) < 0)
00906 {
00907 perror("kdeinit4: Aborting. listen() failed: ");
00908 unlink(sock_file);
00909 close(d.wrapper);
00910 exit(255);
00911 }
00912
00913 #if 0
00914
00915 d.wrapper_old = socket(PF_UNIX, SOCK_STREAM, 0);
00916 if (d.wrapper_old < 0)
00917 {
00918
00919 return;
00920 }
00921
00922 options = fcntl(d.wrapper_old, F_GETFL);
00923 if (options == -1)
00924 {
00925
00926 close(d.wrapper_old);
00927 d.wrapper_old = 0;
00928 return;
00929 }
00930
00931 if (fcntl(d.wrapper_old, F_SETFL, options | O_NONBLOCK) == -1)
00932 {
00933
00934 close(d.wrapper_old);
00935 d.wrapper_old = 0;
00936 return;
00937 }
00938
00939 max_tries = 10;
00940 while (1) {
00942 socklen = sizeof(sa_old);
00943 memset(&sa_old, 0, socklen);
00944 sa_old.sun_family = AF_UNIX;
00945 strcpy(sa_old.sun_path, sock_file_old);
00946 if(bind(d.wrapper_old, (struct sockaddr *)&sa_old, socklen) != 0)
00947 {
00948 if (max_tries == 0) {
00949
00950 fprintf(stderr, "Could not bind to socket '%s'\n", sock_file_old);
00951 close(d.wrapper_old);
00952 d.wrapper_old = 0;
00953 return;
00954 }
00955 max_tries--;
00956 } else
00957 break;
00958 }
00959
00961 if (chmod(sock_file_old, 0600) != 0)
00962 {
00963 fprintf(stderr, "Wrong permissions of socket '%s'\n", sock_file);
00964 unlink(sock_file_old);
00965 close(d.wrapper_old);
00966 d.wrapper_old = 0;
00967 return;
00968 }
00969
00970 if(listen(d.wrapper_old, SOMAXCONN) < 0)
00971 {
00972
00973 unlink(sock_file_old);
00974 close(d.wrapper_old);
00975 d.wrapper_old = 0;
00976 }
00977 #endif
00978 }
00979
00980
00981
00982
00983
00984 static int read_socket(int sock, char *buffer, int len)
00985 {
00986 ssize_t result;
00987 int bytes_left = len;
00988 while ( bytes_left > 0)
00989 {
00990 result = read(sock, buffer, bytes_left);
00991 if (result > 0)
00992 {
00993 buffer += result;
00994 bytes_left -= result;
00995 }
00996 else if (result == 0)
00997 return -1;
00998 else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
00999 return -1;
01000 }
01001 return 0;
01002 }
01003
01004 static void launcher_died()
01005 {
01006 if (!d.launcher_ok)
01007 {
01008
01009 fprintf(stderr, "kdeinit4: Communication error with launcher. Exiting!\n");
01010 ::exit(255);
01011 return;
01012 }
01013
01014
01015 #ifndef NDEBUG
01016 fprintf(stderr, "kdeinit4: KLauncher died unexpectedly.\n");
01017 #endif
01018
01019 if (d.launcher_pid)
01020 {
01021 kill(d.launcher_pid, SIGKILL);
01022 sleep(1);
01023 }
01024
01025 d.launcher_ok = false;
01026 d.launcher_pid = 0;
01027 close(d.launcher[0]);
01028 d.launcher[0] = -1;
01029
01030 pid_t pid = launch( 1, "klauncher", 0 );
01031 #ifndef NDEBUG
01032 fprintf(stderr, "kdeinit4: Relaunching KLauncher, pid = %ld result = %d\n", (long) pid, d.result);
01033 #endif
01034 }
01035
01036 static void handle_launcher_request(int sock = -1)
01037 {
01038 bool launcher = false;
01039 if (sock < 0)
01040 {
01041 sock = d.launcher[0];
01042 launcher = true;
01043 }
01044
01045 klauncher_header request_header;
01046 char *request_data = 0L;
01047 int result = read_socket(sock, (char *) &request_header, sizeof(request_header));
01048 if (result != 0)
01049 {
01050 if (launcher)
01051 launcher_died();
01052 return;
01053 }
01054
01055 if ( request_header.arg_length != 0 )
01056 {
01057 request_data = (char *) malloc(request_header.arg_length);
01058
01059 result = read_socket(sock, request_data, request_header.arg_length);
01060 if (result != 0)
01061 {
01062 if (launcher)
01063 launcher_died();
01064 free(request_data);
01065 return;
01066 }
01067 }
01068
01069 if (request_header.cmd == LAUNCHER_OK)
01070 {
01071 d.launcher_ok = true;
01072 }
01073 else if (request_header.arg_length &&
01074 ((request_header.cmd == LAUNCHER_EXEC) ||
01075 (request_header.cmd == LAUNCHER_EXT_EXEC) ||
01076 (request_header.cmd == LAUNCHER_SHELL ) ||
01077 (request_header.cmd == LAUNCHER_KWRAPPER) ||
01078 (request_header.cmd == LAUNCHER_EXEC_NEW)))
01079 {
01080 pid_t pid;
01081 klauncher_header response_header;
01082 long response_data;
01083 long l;
01084 memcpy( &l, request_data, sizeof( long ));
01085 int argc = l;
01086 const char *name = request_data + sizeof(long);
01087 const char *args = name + strlen(name) + 1;
01088 const char *cwd = 0;
01089 int envc = 0;
01090 const char *envs = 0;
01091 const char *tty = 0;
01092 int avoid_loops = 0;
01093 const char *startup_id_str = "0";
01094
01095 #ifndef NDEBUG
01096 fprintf(stderr, "kdeinit4: Got %s '%s' from %s.\n",
01097 (request_header.cmd == LAUNCHER_EXEC ? "EXEC" :
01098 (request_header.cmd == LAUNCHER_EXT_EXEC ? "EXT_EXEC" :
01099 (request_header.cmd == LAUNCHER_EXEC_NEW ? "EXEC_NEW" :
01100 (request_header.cmd == LAUNCHER_SHELL ? "SHELL" : "KWRAPPER" )))),
01101 name, launcher ? "launcher" : "socket" );
01102 #endif
01103
01104 const char *arg_n = args;
01105 for(int i = 1; i < argc; i