27 #include <sys/types.h>
30 #include <sys/socket.h>
33 #ifdef HAVE_SYS_SELECT_H
34 #include <sys/select.h>
39 #include <setproctitle.h>
50 #include <tqdatetime.h>
51 #include <tqfileinfo.h>
52 #include <tqtextstream.h>
55 #include <kinstance.h>
56 #include <kstandarddirs.h>
59 #include <klibloader.h>
60 #include <kapplication.h>
63 #ifdef HAVE_SYS_PRCTL_H
64 #include <sys/prctl.h>
66 #define PR_SET_NAME 15
70 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
71 #include <kstartupinfo.h>
74 #include <kdeversion.h>
77 #include "klauncher_cmds.h"
83 #include <X11/Xatom.h>
91 # define LTDL_GLOBAL RTLD_GLOBAL
94 # define LTDL_GLOBAL DL_GLOBAL
96 # define LTDL_GLOBAL 0
100 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
101 #include <X11/Xft/Xft.h>
102 extern "C" FcBool XftInitFtLibrary (
void);
103 #include <fontconfig/fontconfig.h>
106 extern char **environ;
108 extern int lt_dlopen_flag;
111 static int X11fd = -1;
112 static Display *X11display = 0;
113 static int X11_startup_notify_fd = -1;
114 static Display *X11_startup_notify_display = 0;
116 static const KInstance *s_instance = 0;
117 #define MAX_SOCK_FILE 255
118 static char sock_file[MAX_SOCK_FILE];
119 static char sock_file_old[MAX_SOCK_FILE];
123 #define DISPLAY "DISPLAY"
124 #elif defined(Q_WS_QWS)
125 #define DISPLAY "QWS_DISPLAY"
126 #elif defined(Q_WS_MACX)
127 #define DISPLAY "MAC_DISPLAY"
128 #elif defined(K_WS_QTONLY)
129 #define DISPLAY "QT_DISPLAY"
131 #error Use QT/X11 or QT/Embedded
152 int (*func)(int,
char *[]);
153 int (*launcher_func)(int);
164 int kdeinit_xio_errhandler( Display * );
165 int kdeinit_x_errhandler( Display *, XErrorEvent *err );
170 #include <kparts/plugin.h>
171 extern "C" KParts::Plugin* _kinit_init_kparts() {
return new KParts::Plugin(); }
173 #include <kio/authinfo.h>
174 extern "C" KIO::AuthInfo* _kioslave_init_kio() {
return new KIO::AuthInfo(); }
180 static void close_fds()
182 if (d.deadpipe[0] != -1)
184 close(d.deadpipe[0]);
188 if (d.deadpipe[1] != -1)
190 close(d.deadpipe[1]);
194 if (d.initpipe[0] != -1)
196 close(d.initpipe[0]);
200 if (d.initpipe[1] != -1)
202 close(d.initpipe[1]);
208 close(d.launcher[0]);
218 close(d.wrapper_old);
221 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
228 if (X11_startup_notify_fd >= 0 && X11_startup_notify_fd != X11fd )
230 close(X11_startup_notify_fd);
231 X11_startup_notify_fd = -1;
235 signal(SIGCHLD, SIG_DFL);
236 signal(SIGPIPE, SIG_DFL);
239 static void exitWithErrorMsg(
const TQString &errorMsg)
241 fprintf( stderr,
"[kinit] %s\n", errorMsg.local8Bit().data() );
242 TQCString utf8ErrorMsg = errorMsg.utf8();
244 write(d.fd[1], &d.result, 1);
245 int l = utf8ErrorMsg.length();
246 write(d.fd[1], &l,
sizeof(
int));
247 write(d.fd[1], utf8ErrorMsg.data(), l);
252 static void setup_tty(
const char* tty )
254 if( tty == NULL || *tty ==
'\0' )
256 int fd = open( tty, O_WRONLY );
259 fprintf(stderr,
"[kinit] couldn't open() %s: %s\n", tty, strerror (errno) );
262 if( dup2( fd, STDOUT_FILENO ) < 0 )
264 fprintf(stderr,
"[kinit] couldn't dup2() %s: %s\n", tty, strerror (errno) );
268 if( dup2( fd, STDERR_FILENO ) < 0 )
270 fprintf(stderr,
"[kinit] couldn't dup2() %s: %s\n", tty, strerror (errno) );
278 static int get_current_desktop( Display* disp )
281 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
283 Atom net_current_desktop = XInternAtom( disp,
"_NET_CURRENT_DESKTOP", False );
286 unsigned char *data_ret;
287 unsigned long nitems_ret, unused;
288 if( XGetWindowProperty( disp, DefaultRootWindow( disp ), net_current_desktop,
289 0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret )
292 if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1)
293 desktop = *((
long *) data_ret) + 1;
295 XFree ((
char*) data_ret);
302 const char* get_env_var(
const char* var,
int envc,
const char* envs )
306 const char* env_l = envs;
307 int ln = strlen( var );
308 for (
int i = 0; i < envc; i++)
310 if( strncmp( env_l, var, ln ) == 0 )
312 while(*env_l != 0) env_l++;
319 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
321 static void init_startup_info( KStartupInfoId&
id,
const char* bin,
322 int envc,
const char* envs )
324 const char* dpy = get_env_var( DISPLAY
"=", envc, envs );
327 X11_startup_notify_display = XOpenDisplay( dpy );
328 if( X11_startup_notify_display == NULL )
330 X11_startup_notify_fd = XConnectionNumber( X11_startup_notify_display );
331 KStartupInfoData data;
332 int desktop = get_current_desktop( X11_startup_notify_display );
333 data.setDesktop( desktop );
335 KStartupInfo::sendChangeX( X11_startup_notify_display,
id, data );
336 XFlush( X11_startup_notify_display );
339 static void complete_startup_info( KStartupInfoId&
id, pid_t pid )
341 if( X11_startup_notify_display == NULL )
344 KStartupInfo::sendFinishX( X11_startup_notify_display,
id );
347 KStartupInfoData data;
350 KStartupInfo::sendChangeX( X11_startup_notify_display,
id, data );
352 XCloseDisplay( X11_startup_notify_display );
353 X11_startup_notify_display = NULL;
354 X11_startup_notify_fd = -1;
358 TQCString execpath_avoid_loops(
const TQCString& exec,
int envc,
const char* envs,
bool avoid_loops )
363 const char* path = get_env_var(
"PATH=", envc, envs );
365 paths = TQStringList::split( TQRegExp(
"[:\b]" ), path,
true );
368 paths = TQStringList::split( TQRegExp(
"[:\b]" ), getenv(
"PATH" ),
true );
369 TQCString execpath = TQFile::encodeName(
370 s_instance->dirs()->findExe( exec, paths.join( TQString(
":" ))));
371 if( avoid_loops && !execpath.isEmpty())
373 int pos = execpath.findRev(
'/' );
374 TQString bin_path = execpath.left( pos );
375 for( TQStringList::Iterator it = paths.begin();
378 if( ( *it ) == bin_path || ( *it ) == bin_path +
'/' )
383 execpath = TQFile::encodeName(
384 s_instance->dirs()->findExe( exec, paths.join( TQString(
":" ))));
389 #ifdef KDEINIT_OOM_PROTECT
390 static int oom_pipe = -1;
392 static void oom_protect_sighandler(
int ) {
395 static void reset_oom_protect() {
398 struct sigaction act, oldact;
399 act.sa_handler = oom_protect_sighandler;
401 sigemptyset( &act.sa_mask );
402 sigaction( SIGUSR1, &act, &oldact );
403 sigset_t sigs, oldsigs;
404 sigemptyset( &sigs );
405 sigaddset( &sigs, SIGUSR1 );
406 sigprocmask( SIG_BLOCK, &sigs, &oldsigs );
407 pid_t pid = getpid();
408 if( write( oom_pipe, &pid,
sizeof( pid_t )) > 0 ) {
409 sigsuspend( &oldsigs );
411 sigprocmask( SIG_SETMASK, &oldsigs, NULL );
412 sigaction( SIGUSR1, &oldact, NULL );
417 static void reset_oom_protect() {
421 static pid_t launch(
int argc,
const char *_name,
const char *args,
422 const char *cwd=0,
int envc=0,
const char *envs=0,
423 bool reset_env =
false,
424 const char *tty=0,
bool avoid_loops =
false,
425 const char* startup_id_str =
"0" )
432 if (strcmp(_name,
"klauncher") == 0) {
436 if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, d.launcher))
438 perror(
"[kinit] socketpair() failed!\n");
452 libpath = TQFile::encodeName(KLibLoader::findLibrary( lib, s_instance ));
453 execpath = execpath_avoid_loops( exec, envc, envs, avoid_loops );
459 name = name.mid( name.findRev(
'/') + 1);
461 if (lib.right(3) ==
".la")
473 perror(
"[kinit] pipe() failed!\n");
475 d.errorMsg = i18n(
"Unable to start new process.\n"
476 "The system may have reached the maximum number of open files possible or the maximum number of open files that you are allowed to use has been reached.").utf8();
483 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
485 KStartupInfoId startup_id;
486 startup_id.initId( startup_id_str );
487 if( !startup_id.none())
488 init_startup_info( startup_id, name, envc, envs );
495 perror(
"[kinit] fork() failed!\n");
497 d.errorMsg = i18n(
"Unable to create new process.\n"
498 "The system may have reached the maximum number of processes possible or the maximum number of processes that you are allowed to use has been reached.").utf8();
509 if (d.fd[1] == LAUNCHER_FD)
511 d.fd[1] = dup(d.fd[1]);
513 if (d.launcher[1] != LAUNCHER_FD)
515 dup2( d.launcher[1], LAUNCHER_FD);
516 close( d.launcher[1] );
518 close( d.launcher[0] );
528 TQStrList unset_envs;
529 for(
int tmp_env_count = 0;
530 environ[tmp_env_count];
532 unset_envs.append( environ[ tmp_env_count ] );
533 for( TQStrListIterator it( unset_envs );
534 it.current() != NULL ;
537 TQCString tmp( it.current());
538 int pos = tmp.find(
'=' );
540 unsetenv( tmp.left( pos ));
544 for (
int i = 0; i < envc; i++)
546 putenv((
char *)envs);
547 while(*envs != 0) envs++;
551 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
553 if( startup_id.none())
554 KStartupInfo::resetStartupEnv();
556 startup_id.setupStartupEnv();
561 d.argv = (
char **) malloc(
sizeof(
char *) * (argc+1));
562 d.argv[0] = (
char *) _name;
563 for (
int i = 1; i < argc; i++)
565 d.argv[i] = (
char *) args;
567 procTitle += (
char *) args;
568 while(*args != 0) args++;
574 #ifdef HAVE_SYS_PRCTL_H
576 r = prctl(PR_SET_NAME, (
unsigned long) name.data(), 0, 0, 0);
578 kdeinit_setproctitle(
"%s [kinit]%s", name.data(), procTitle.data() ? procTitle.data() :
"" );
580 kdeinit_setproctitle(
"[kinit] %s%s", name.data(), procTitle.data() ? procTitle.data() :
"" );
582 kdeinit_setproctitle(
"[kinit] %s%s", name.data(), procTitle.data() ? procTitle.data() :
"" );
587 if (libpath.isEmpty() && execpath.isEmpty())
589 TQString errorMsg = i18n(
"Could not find '%1' executable.").arg(TQFile::decodeName(_name));
590 exitWithErrorMsg(errorMsg);
593 if ( getenv(
"KDE_IS_PRELINKED") && !execpath.isEmpty() && !launcher)
596 if ( !libpath.isEmpty() )
598 d.handle = lt_dlopen( TQFile::encodeName(libpath) );
601 const char * ltdlError = lt_dlerror();
602 if (execpath.isEmpty())
605 TQString errorMsg = i18n(
"Could not open library '%1'.\n%2").arg(TQFile::decodeName(libpath))
606 .arg(ltdlError ? TQFile::decodeName(ltdlError) : i18n(
"Unknown error"));
607 exitWithErrorMsg(errorMsg);
612 fprintf(stderr,
"Could not open library %s: %s\n", lib.data(), ltdlError != 0 ? ltdlError :
"(null)" );
616 lt_dlopen_flag = d.lt_dlopen_flag;
620 write(d.fd[1], &d.result, 1);
624 fcntl(d.fd[1], F_SETFD, FD_CLOEXEC);
628 execvp(execpath.data(), d.argv);
630 write(d.fd[1], &d.result, 1);
635 d.sym = lt_dlsym( d.handle,
"kdeinitmain");
638 d.sym = lt_dlsym( d.handle,
"kdemain" );
641 #if ! KDE_IS_VERSION( 3, 90, 0 )
642 d.sym = lt_dlsym( d.handle,
"main");
646 const char * ltdlError = lt_dlerror();
647 fprintf(stderr,
"Could not find kdemain: %s\n", ltdlError != 0 ? ltdlError :
"(null)" );
648 TQString errorMsg = i18n(
"Could not find 'kdemain' in '%1'.\n%2").arg(TQString(libpath))
649 .arg(ltdlError ? TQFile::decodeName(ltdlError) : i18n(
"Unknown error"));
650 exitWithErrorMsg(errorMsg);
656 write(d.fd[1], &d.result, 1);
659 d.func = (int (*)(int,
char *[])) d.sym;
662 fprintf(stderr,
"[kinit] Suspending process\n"
663 "[kinit] 'gdb kdeinit %d' to debug\n"
664 "[kinit] 'kill -SIGCONT %d' to continue\n",
666 kill(getpid(), SIGSTOP);
673 exit( d.func(argc, d.argv));
681 close(d.launcher[1]);
682 d.launcher_pid = d.fork;
687 d.n = read(d.fd[0], &d.result, 1);
693 fprintf(stderr,
"[kinit] %s is executable and not a library. Launching with exec.\n", _name );
701 d.n = read(d.fd[0], &l,
sizeof(
int));
702 if (d.n ==
sizeof(
int))
706 d.n = read(d.fd[0], tmp.data(), l);
717 if (errno == ECHILD) {
720 if (errno == EINTR || errno == EAGAIN) {
731 perror(
"[kinit] Pipe closed unexpectedly");
735 perror(
"[kinit] Error reading from pipe");
740 if (launcher && (d.result == 0))
743 d.launcher_pid = d.fork;
746 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
748 if( !startup_id.none())
750 if( d.fork && d.result == 0 )
751 complete_startup_info( startup_id, d.fork );
753 complete_startup_info( startup_id, 0 );
759 static void sig_child_handler(
int)
770 write(d.deadpipe[1], &c, 1);
773 static void init_signals()
775 struct sigaction act;
778 if (pipe(d.deadpipe) != 0)
780 perror(
"[kinit] Aborting. Can't create pipe: ");
784 options = fcntl(d.deadpipe[0], F_GETFL);
787 perror(
"[kinit] Aborting. Can't make pipe non-blocking: ");
791 if (fcntl(d.deadpipe[0], F_SETFL, options | O_NONBLOCK) == -1)
793 perror(
"[kinit] Aborting. Can't make pipe non-blocking: ");
802 act.sa_handler=sig_child_handler;
803 sigemptyset(&(act.sa_mask));
804 sigaddset(&(act.sa_mask), SIGCHLD);
805 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
806 act.sa_flags = SA_NOCLDSTOP;
812 act.sa_flags |= SA_RESTART;
814 sigaction( SIGCHLD, &act, 0L);
816 act.sa_handler=SIG_IGN;
817 sigemptyset(&(act.sa_mask));
818 sigaddset(&(act.sa_mask), SIGPIPE);
819 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
821 sigaction( SIGPIPE, &act, 0L);
824 static void init_kdeinit_socket()
826 struct sockaddr_un sa;
827 struct sockaddr_un sa_old;
828 kde_socklen_t socklen;
830 const char *home_dir = getenv(
"HOME");
832 if (!home_dir || !home_dir[0])
834 fprintf(stderr,
"[kinit] Aborting. $HOME not set!");
840 TQCString path = home_dir;
841 TQCString readOnly = getenv(
"KDE_HOME_READONLY");
842 if (access(path.data(), R_OK|W_OK))
846 fprintf(stderr,
"[kinit] Aborting. $HOME directory (%s) does not exist.\n", path.data());
849 else if (readOnly.isEmpty())
851 fprintf(stderr,
"[kinit] Aborting. No write access to $HOME directory (%s).\n", path.data());
855 path = getenv(
"ICEAUTHORITY");
859 path +=
"/.ICEauthority";
861 if (access(path.data(), R_OK|W_OK) && (errno != ENOENT))
863 fprintf(stderr,
"[kinit] Aborting. No write access to '%s'.\n", path.data());
872 if (access(sock_file, W_OK) == 0)
875 struct sockaddr_un server;
881 s = socket(PF_UNIX, SOCK_STREAM, 0);
884 perror(
"socket() failed: ");
887 server.sun_family = AF_UNIX;
888 strcpy(server.sun_path, sock_file);
889 socklen =
sizeof(server);
891 if(connect(s, (
struct sockaddr *)&server, socklen) == 0)
893 fprintf(stderr,
"[kinit] Shutting down running client.\n");
894 klauncher_header request_header;
895 request_header.cmd = LAUNCHER_TERMINATE_KDEINIT;
896 request_header.arg_length = 0;
897 write(s, &request_header,
sizeof(request_header));
905 unlink(sock_file_old);
908 d.wrapper = socket(PF_UNIX, SOCK_STREAM, 0);
911 perror(
"[kinit] Aborting. socket() failed: ");
915 options = fcntl(d.wrapper, F_GETFL);
918 perror(
"[kinit] Aborting. Can't make socket non-blocking: ");
923 if (fcntl(d.wrapper, F_SETFL, options | O_NONBLOCK) == -1)
925 perror(
"[kinit] Aborting. Can't make socket non-blocking: ");
932 socklen =
sizeof(sa);
933 memset(&sa, 0, socklen);
934 sa.sun_family = AF_UNIX;
935 strcpy(sa.sun_path, sock_file);
936 if(bind(d.wrapper, (
struct sockaddr *)&sa, socklen) != 0)
938 if (max_tries == 0) {
939 perror(
"[kinit] Aborting. bind() failed: ");
940 fprintf(stderr,
"Could not bind to socket '%s'\n", sock_file);
950 if (chmod(sock_file, 0600) != 0)
952 perror(
"[kinit] Aborting. Can't set permissions on socket: ");
953 fprintf(stderr,
"Wrong permissions of socket '%s'\n", sock_file);
959 if(listen(d.wrapper, SOMAXCONN) < 0)
961 perror(
"[kinit] Aborting. listen() failed: ");
968 d.wrapper_old = socket(PF_UNIX, SOCK_STREAM, 0);
969 if (d.wrapper_old < 0)
975 options = fcntl(d.wrapper_old, F_GETFL);
979 close(d.wrapper_old);
984 if (fcntl(d.wrapper_old, F_SETFL, options | O_NONBLOCK) == -1)
987 close(d.wrapper_old);
995 socklen =
sizeof(sa_old);
996 memset(&sa_old, 0, socklen);
997 sa_old.sun_family = AF_UNIX;
998 strcpy(sa_old.sun_path, sock_file_old);
999 if(bind(d.wrapper_old, (
struct sockaddr *)&sa_old, socklen) != 0)
1001 if (max_tries == 0) {
1003 fprintf(stderr,
"Could not bind to socket '%s'\n", sock_file_old);
1004 close(d.wrapper_old);
1014 if (chmod(sock_file_old, 0600) != 0)
1016 fprintf(stderr,
"Wrong permissions of socket '%s'\n", sock_file);
1017 unlink(sock_file_old);
1018 close(d.wrapper_old);
1023 if(listen(d.wrapper_old, SOMAXCONN) < 0)
1026 unlink(sock_file_old);
1027 close(d.wrapper_old);
1036 static int read_socket(
int sock,
char *buffer,
int len)
1039 int bytes_left = len;
1040 while ( bytes_left > 0)
1042 result = read(sock, buffer, bytes_left);
1046 bytes_left -= result;
1048 else if (result == 0)
1050 else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
1056 static void WaitPid( pid_t waitForPid)
1061 result = waitpid(waitForPid, &d.exit_status, 0);
1062 if ((result == -1) && (errno == ECHILD))
1067 static void launcher_died()
1072 fprintf(stderr,
"[kinit] Communication error with launcher. Exiting!\n");
1079 fprintf(stderr,
"[kinit] KLauncher died unexpectedly.\n");
1084 kill(d.launcher_pid, SIGKILL);
1088 d.launcher_ok =
false;
1090 close(d.launcher[0]);
1093 pid_t pid = launch( 1,
"klauncher", 0 );
1095 fprintf(stderr,
"[kinit] Relaunching KLauncher, pid = %ld result = %d\n", (
long) pid, d.result);
1099 static void handle_launcher_request(
int sock = -1)
1101 bool launcher =
false;
1104 sock = d.launcher[0];
1108 klauncher_header request_header;
1109 char *request_data = 0L;
1110 int result = read_socket(sock, (
char *) &request_header,
sizeof(request_header));
1118 if ( request_header.arg_length != 0 )
1120 request_data = (
char *) malloc(request_header.arg_length);
1122 result = read_socket(sock, request_data, request_header.arg_length);
1132 if (request_header.cmd == LAUNCHER_OK)
1134 d.launcher_ok =
true;
1136 else if (request_header.arg_length &&
1137 ((request_header.cmd == LAUNCHER_EXEC) ||
1138 (request_header.cmd == LAUNCHER_EXT_EXEC) ||
1139 (request_header.cmd == LAUNCHER_SHELL ) ||
1140 (request_header.cmd == LAUNCHER_KWRAPPER) ||
1141 (request_header.cmd == LAUNCHER_EXEC_NEW)))
1144 klauncher_header response_header;
1147 memcpy( &l, request_data,
sizeof(
long ));
1149 const char *name = request_data +
sizeof(long);
1150 const char *args = name + strlen(name) + 1;
1151 const char *cwd = 0;
1153 const char *envs = 0;
1154 const char *tty = 0;
1155 int avoid_loops = 0;
1156 const char *startup_id_str =
"0";
1159 fprintf(stderr,
"[kinit] Got %s '%s' from %s.\n",
1160 (request_header.cmd == LAUNCHER_EXEC ?
"EXEC" :
1161 (request_header.cmd == LAUNCHER_EXT_EXEC ?
"EXT_EXEC" :
1162 (request_header.cmd == LAUNCHER_EXEC_NEW ?
"EXEC_NEW" :
1163 (request_header.cmd == LAUNCHER_SHELL ?
"SHELL" :
"KWRAPPER" )))),
1164 name, launcher ?
"launcher" :
"socket" );
1167 const char *arg_n = args;
1168 for(
int i = 1; i < argc; i++)
1170 arg_n = arg_n + strlen(arg_n) + 1;
1173 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER )
1176 cwd = arg_n; arg_n += strlen(cwd) + 1;
1178 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
1179 || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
1181 memcpy( &l, arg_n,
sizeof(
long ));
1183 arg_n +=
sizeof(long);
1185 for(
int i = 0; i < envc; i++)
1187 arg_n = arg_n + strlen(arg_n) + 1;
1189 if( request_header.cmd == LAUNCHER_KWRAPPER )
1192 arg_n += strlen( tty ) + 1;
1196 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
1197 || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
1199 memcpy( &l, arg_n,
sizeof(
long ));
1201 arg_n +=
sizeof( long );
1204 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
1205 || request_header.cmd == LAUNCHER_EXT_EXEC )
1207 startup_id_str = arg_n;
1208 arg_n += strlen( startup_id_str ) + 1;
1211 if ((request_header.arg_length > (arg_n - request_data)) &&
1212 (request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW ))
1215 cwd = arg_n; arg_n += strlen(cwd) + 1;
1218 if ((arg_n - request_data) != request_header.arg_length)
1221 fprintf(stderr,
"[kinit] EXEC request has invalid format.\n");
1224 d.debug_wait =
false;
1229 TQCString olddisplay = getenv(DISPLAY);
1230 TQCString kdedisplay = getenv(
"KDE_DISPLAY");
1231 bool reset_display = (! olddisplay.isEmpty() &&
1232 ! kdedisplay.isEmpty() &&
1233 olddisplay != kdedisplay);
1236 setenv(DISPLAY, kdedisplay,
true);
1238 pid = launch( argc, name, args, cwd, envc, envs,
1239 request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER,
1240 tty, avoid_loops, startup_id_str );
1242 if (reset_display) {
1243 unsetenv(
"KDE_DISPLAY");
1244 setenv(DISPLAY, olddisplay,
true);
1247 if (pid && (d.result == 0))
1249 response_header.cmd = LAUNCHER_OK;
1250 response_header.arg_length =
sizeof(response_data);
1251 response_data = pid;
1252 write(sock, &response_header,
sizeof(response_header));
1253 write(sock, &response_data, response_header.arg_length);
1257 int l = d.errorMsg.length();
1259 response_header.cmd = LAUNCHER_ERROR;
1260 response_header.arg_length = l;
1261 write(sock, &response_header,
sizeof(response_header));
1263 write(sock, d.errorMsg.data(), l);
1265 d.debug_wait =
false;
1267 else if (request_header.arg_length && request_header.cmd == LAUNCHER_SETENV)
1269 const char *env_name;
1270 const char *env_value;
1271 env_name = request_data;
1272 env_value = env_name + strlen(env_name) + 1;
1276 fprintf(stderr,
"[kinit] Got SETENV '%s=%s' from klauncher.\n", env_name, env_value);
1278 fprintf(stderr,
"[kinit] Got SETENV '%s=%s' from socket.\n", env_name, env_value);
1281 if ( request_header.arg_length !=
1282 (
int) (strlen(env_name) + strlen(env_value) + 2))
1285 fprintf(stderr,
"[kinit] SETENV request has invalid format.\n");
1290 setenv( env_name, env_value, 1);
1292 else if (request_header.cmd == LAUNCHER_TERMINATE_KDE)
1295 fprintf(stderr,
"[kinit] Terminating Trinity.\n");
1298 kdeinit_xio_errhandler( 0L );
1301 else if (request_header.cmd == LAUNCHER_TERMINATE_KDEINIT)
1304 fprintf(stderr,
"[kinit] Killing kdeinit/klauncher.\n");
1307 kill(d.launcher_pid, SIGTERM);
1309 kill(d.my_pid, SIGTERM);
1311 else if (request_header.cmd == LAUNCHER_DEBUG_WAIT)
1314 fprintf(stderr,
"[kinit] Debug wait activated.\n");
1316 d.debug_wait =
true;
1322 static void handle_requests(pid_t waitForPid)
1324 int max_sock = d.wrapper;
1325 if (d.wrapper_old > max_sock)
1326 max_sock = d.wrapper_old;
1327 if (d.launcher_pid && (d.launcher[0] > max_sock))
1328 max_sock = d.launcher[0];
1329 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
1331 if (X11fd > max_sock)
1346 while( read(d.deadpipe[0], &c, 1) == 1);
1350 exit_pid = waitpid(-1, 0, WNOHANG);
1354 fprintf(stderr,
"[kinit] PID %ld terminated.\n", (
long) exit_pid);
1356 if (waitForPid && (exit_pid == waitForPid))
1362 klauncher_header request_header;
1363 long request_data[2];
1364 request_header.cmd = LAUNCHER_DIED;
1365 request_header.arg_length =
sizeof(long) * 2;
1366 request_data[0] = exit_pid;
1367 request_data[1] = 0;
1368 write(d.launcher[0], &request_header,
sizeof(request_header));
1369 write(d.launcher[0], request_data, request_header.arg_length);
1373 while( exit_pid > 0);
1381 FD_SET(d.launcher[0], &rd_set);
1383 FD_SET(d.wrapper, &rd_set);
1386 FD_SET(d.wrapper_old, &rd_set);
1388 FD_SET(d.deadpipe[0], &rd_set);
1389 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
1391 if(X11fd >= 0) FD_SET(X11fd, &rd_set);
1394 result = select(max_sock, &rd_set, &wr_set, &e_set, 0);
1397 if ((result > 0) && (FD_ISSET(d.wrapper, &rd_set)))
1399 struct sockaddr_un client;
1400 kde_socklen_t sClient =
sizeof(client);
1401 int sock = accept(d.wrapper, (
struct sockaddr *)&client, &sClient);
1404 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
1405 if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
1406 FcInitReinitialize();
1411 reset_oom_protect();
1412 handle_launcher_request(sock);
1418 if ((result > 0) && (FD_ISSET(d.wrapper_old, &rd_set)))
1420 struct sockaddr_un client;
1421 kde_socklen_t sClient =
sizeof(client);
1422 int sock = accept(d.wrapper_old, (
struct sockaddr *)&client, &sClient);
1425 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
1426 if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
1427 FcInitReinitialize();
1432 reset_oom_protect();
1433 handle_launcher_request(sock);
1441 if ((result > 0) && (d.launcher_pid) && (FD_ISSET(d.launcher[0], &rd_set)))
1443 handle_launcher_request();
1444 if (waitForPid == d.launcher_pid)
1451 if((result > 0) && (X11fd >= 0))
1453 if(FD_ISSET(X11fd,&rd_set))
1455 if (X11display != 0) {
1456 XEvent event_return;
1457 while (XPending(X11display))
1458 XNextEvent(X11display, &event_return);
1466 static void kdeinit_library_path()
1468 TQStringList ltdl_library_path =
1469 TQStringList::split(
':', TQFile::decodeName(getenv(
"LTDL_LIBRARY_PATH")));
1470 TQStringList ld_library_path =
1471 TQStringList::split(
':', TQFile::decodeName(getenv(
"LD_LIBRARY_PATH")));
1473 TQCString extra_path;
1474 TQStringList candidates = s_instance->dirs()->resourceDirs(
"lib");
1475 for (TQStringList::ConstIterator it = candidates.begin();
1476 it != candidates.end();
1480 if (ltdl_library_path.contains(d))
1482 if (ld_library_path.contains(d))
1484 if (d[d.length()-1] ==
'/')
1486 d.truncate(d.length()-1);
1487 if (ltdl_library_path.contains(d))
1489 if (ld_library_path.contains(d))
1492 if ((d ==
"/lib") || (d ==
"/usr/lib"))
1495 TQCString dir = TQFile::encodeName(d);
1497 if (access(dir, R_OK))
1500 if ( !extra_path.isEmpty())
1507 const char * ltdlError = lt_dlerror();
1508 fprintf(stderr,
"can't initialize dynamic loading: %s\n", ltdlError != 0 ? ltdlError :
"(null)" );
1510 if (!extra_path.isEmpty())
1511 lt_dlsetsearchpath(extra_path.data());
1513 TQCString display = getenv(DISPLAY);
1514 if (display.isEmpty())
1516 fprintf(stderr,
"[kinit] Aborting. $"DISPLAY
" is not set.\n");
1520 if((i = display.findRev(
'.')) > display.findRev(
':') && i >= 0)
1521 display.truncate(i);
1523 TQCString socketName = TQFile::encodeName(locateLocal(
"socket", TQString(
"kdeinit-%1").arg(TQString(display)), s_instance));
1524 if (socketName.length() >= MAX_SOCK_FILE)
1526 fprintf(stderr,
"[kinit] Aborting. Socket name will be too long:\n");
1527 fprintf(stderr,
" '%s'\n", socketName.data());
1530 strcpy(sock_file_old, socketName.data());
1532 display.replace(
":",
"_");
1533 socketName = TQFile::encodeName(locateLocal(
"socket", TQString(
"kdeinit_%1").arg(TQString(display)), s_instance));
1534 if (socketName.length() >= MAX_SOCK_FILE)
1536 fprintf(stderr,
"[kinit] Aborting. Socket name will be too long:\n");
1537 fprintf(stderr,
" '%s'\n", socketName.data());
1540 strcpy(sock_file, socketName.data());
1543 int kdeinit_xio_errhandler( Display *disp )
1548 qWarning(
"[kinit] Fatal IO error: client killed" );
1555 if (sock_file_old[0])
1558 unlink(sock_file_old);
1565 kill(d.launcher_pid, SIGTERM);
1570 qWarning(
"[kinit] sending SIGHUP to children." );
1573 signal(SIGHUP, SIG_IGN);
1579 qWarning(
"[kinit] sending SIGTERM to children." );
1582 signal(SIGTERM, SIG_IGN);
1586 qWarning(
"[kinit] Exit." );
1593 int kdeinit_x_errhandler( Display *dpy, XErrorEvent *err )
1598 XGetErrorText( dpy, err->error_code, errstr, 256 );
1599 fprintf(stderr,
"[kinit] TDE detected X Error: %s %d\n"
1600 " Major opcode: %d\n"
1601 " Minor opcode: %d\n"
1602 " Resource id: 0x%lx\n",
1603 errstr, err->error_code, err->request_code, err->minor_code, err->resourceid );
1616 static void setupX()
1619 XSetIOErrorHandler(kdeinit_xio_errhandler);
1620 XSetErrorHandler(kdeinit_x_errhandler);
1624 static int initXconnection()
1626 X11display = XOpenDisplay(NULL);
1627 if ( X11display != 0 ) {
1628 XCreateSimpleWindow(X11display, DefaultRootWindow(X11display), 0,0,1,1, \
1630 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)),
1631 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)) );
1633 fprintf(stderr,
"[kinit] opened connection to %s\n", DisplayString(X11display));
1635 int fd = XConnectionNumber( X11display );
1637 (void) setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (
char *) &on, (int)
sizeof(on));
1640 fprintf(stderr,
"[kinit] Can't connect to the X Server.\n" \
1641 "[kinit] Might not terminate at end of session.\n");
1667 extern "C" void _main(
void);
1668 extern "C" void __call_ctors__Fv(
void);
1669 static int main_called = 0;
1675 __call_ctors__Fv ();
1679 static void secondary_child_handler(
int)
1681 waitpid(-1, 0, WNOHANG);
1684 int main(
int argc,
char **argv,
char **envp)
1688 int launch_dcop = 1;
1689 int launch_klauncher = 1;
1690 int launch_kded = 1;
1691 int keep_running = 1;
1692 int new_startup = 0;
1696 char **safe_argv = (
char **) malloc(
sizeof(
char *) * argc);
1697 for(i = 0; i < argc; i++)
1699 safe_argv[i] = strcpy((
char*)malloc(strlen(argv[i])+1), argv[i]);
1700 if (strcmp(safe_argv[i],
"--no-dcop") == 0)
1702 if (strcmp(safe_argv[i],
"--no-klauncher") == 0)
1703 launch_klauncher = 0;
1704 if (strcmp(safe_argv[i],
"--no-kded") == 0)
1706 if (strcmp(safe_argv[i],
"--suicide") == 0)
1708 if (strcmp(safe_argv[i],
"--exit") == 0)
1710 if (strcmp(safe_argv[i],
"--new-startup") == 0)
1712 #ifdef KDEINIT_OOM_PROTECT
1713 if (strcmp(safe_argv[i],
"--oom-pipe") == 0 && i+1<argc)
1714 oom_pipe = atol(argv[i+1]);
1716 if (strcmp(safe_argv[i],
"--help") == 0)
1718 printf(
"Usage: kdeinit [options]\n");
1721 printf(
" --no-kded Do not start kded\n");
1722 printf(
" --suicide Terminate when no KDE applications are left running\n");
1733 signal( SIGCHLD, secondary_child_handler);
1736 close(d.initpipe[1]);
1740 while( read(d.initpipe[0], &c, 1) < 0);
1742 close(d.initpipe[0]);
1746 close(d.initpipe[0]);
1748 d.my_pid = getpid();
1755 s_instance =
new KInstance(
"kdeinit");
1758 kdeinit_initsetproctitle(argc, argv, envp);
1759 kdeinit_library_path();
1763 KGlobal::_instance = 0L;
1765 unsetenv(
"LD_BIND_NOW");
1766 unsetenv(
"DYLD_BIND_AT_LAUNCH");
1767 KApplication::loadedByKdeinit =
true;
1769 d.maxname = strlen(argv[0]);
1773 d.debug_wait =
false;
1774 d.launcher_ok =
false;
1775 d.lt_dlopen_flag = lt_dlopen_flag;
1776 lt_dlopen_flag |= LTDL_GLOBAL;
1788 init_kdeinit_socket();
1794 pid = launch( 3,
"dcopserver",
"--nosid\0--suicide" );
1796 pid = launch( 2,
"dcopserver",
"--nosid" );
1798 fprintf(stderr,
"[kinit] Launched DCOPServer, pid = %ld result = %d\n", (
long) pid, d.result);
1801 if (!WIFEXITED(d.exit_status) || (WEXITSTATUS(d.exit_status) != 0))
1803 fprintf(stderr,
"[kinit] DCOPServer could not be started, aborting.\n");
1808 if (!d.suicide && !getenv(
"KDE_IS_PRELINKED"))
1810 TQString konq = locate(
"lib",
"libkonq.la", s_instance);
1811 if (!konq.isEmpty())
1812 (
void) lt_dlopen(TQFile::encodeName(konq).data());
1815 if (launch_klauncher)
1818 pid = launch( 2,
"klauncher",
"--new-startup" );
1820 pid = launch( 1,
"klauncher", 0 );
1822 fprintf(stderr,
"[kinit] Launched KLauncher, pid = %ld result = %d\n", (
long) pid, d.result);
1824 handle_requests(pid);
1827 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
1829 X11fd = initXconnection();
1833 #if defined(KDEINIT_USE_XFT) && defined(KDEINIT_USE_FONTCONFIG)
1834 if( FcGetVersion() < 20390 )
1840 TQFont::initialize();
1841 setlocale (LC_ALL,
"");
1842 setlocale (LC_NUMERIC,
"C");
1844 if (XSupportsLocale ())
1848 XOpenIM (X11display, 0, 0, 0);
1856 pid = launch( 2,
"kded",
"--new-startup" );
1858 pid = launch( 1,
"kded", 0 );
1860 fprintf(stderr,
"[kinit] Launched KDED, pid = %ld result = %d\n", (
long) pid, d.result);
1862 handle_requests(pid);
1865 for(i = 1; i < argc; i++)
1867 if (safe_argv[i][0] ==
'+')
1869 pid = launch( 1, safe_argv[i]+1, 0);
1871 fprintf(stderr,
"[kinit] Launched '%s', pid = %ld result = %d\n", safe_argv[i]+1, (
long) pid, d.result);
1873 handle_requests(pid);
1875 else if (safe_argv[i][0] ==
'-'
1876 #ifdef KDEINIT_OOM_PROTECT
1877 || isdigit(safe_argv[i][0])
1885 pid = launch( 1, safe_argv[i], 0 );
1887 fprintf(stderr,
"[kinit] Launched '%s', pid = %ld result = %d\n", safe_argv[i], (
long) pid, d.result);
1893 for(i = 0; i < argc; i++)
1899 kdeinit_setproctitle(
"kdeinit Running...");
1905 write(d.initpipe[1], &c, 1);
1906 close(d.initpipe[1]);