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>
57 #include <tdeglobal.h>
58 #include <tdeconfig.h>
59 #include <klibloader.h>
60 #include <tdeapplication.h>
61 #include <tdelocale.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 <tdestartupinfo.h>
74 #include <tdeversion.h>
77 #include "tdelauncher_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(TDEINIT_USE_XFT) && defined(TDEINIT_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 TDEInstance *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 tdeinit_xio_errhandler( Display * );
165 int tdeinit_x_errhandler( Display *, XErrorEvent *err );
170 #include <tdeparts/plugin.h>
171 extern "C" KParts::Plugin* _tdeinit_init_tdeparts() {
return new KParts::Plugin(); }
173 #include <tdeio/authinfo.h>
174 extern "C" TDEIO::AuthInfo* _tdeioslave_init_tdeio() {
return new TDEIO::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,
"[tdeinit] %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,
"[tdeinit] Couldn't open() %s: %s\n", tty, strerror (errno) );
262 if( dup2( fd, STDOUT_FILENO ) < 0 )
264 fprintf(stderr,
"[tdeinit] Couldn't dup2() %s: %s\n", tty, strerror (errno) );
268 if( dup2( fd, STDERR_FILENO ) < 0 )
270 fprintf(stderr,
"[tdeinit] 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( TDEStartupInfoId&
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 TDEStartupInfoData data;
332 int desktop = get_current_desktop( X11_startup_notify_display );
333 data.setDesktop( desktop );
335 TDEStartupInfo::sendChangeX( X11_startup_notify_display,
id, data );
336 XFlush( X11_startup_notify_display );
339 static void complete_startup_info( TDEStartupInfoId&
id, pid_t pid )
341 if( X11_startup_notify_display == NULL )
344 TDEStartupInfo::sendFinishX( X11_startup_notify_display,
id );
347 TDEStartupInfoData data;
350 TDEStartupInfo::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 TDEINIT_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,
"tdelauncher") == 0) {
436 if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, d.launcher))
438 perror(
"[tdeinit] 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(
"[tdeinit] 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 TDEStartupInfoId 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(
"[tdeinit] 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 TDEStartupInfo::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 tdeinit_setproctitle(
"%s [tdeinit]%s", name.data(), procTitle.data() ? procTitle.data() :
"" );
580 tdeinit_setproctitle(
"[tdeinit] %s%s", name.data(), procTitle.data() ? procTitle.data() :
"" );
582 tdeinit_setproctitle(
"[tdeinit] %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(
"TDE_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,
"tdeinitmain");
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,
"[tdeinit] Suspending process\n"
663 "[tdeinit] 'gdb tdeinit %d' to debug\n"
664 "[tdeinit] '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,
"[tdeinit] %s is executable. Launching.\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(
"[tdeinit] Pipe closed unexpectedly");
735 perror(
"[tdeinit] 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(
"[tdeinit] Aborting. Can't create pipe: ");
784 options = fcntl(d.deadpipe[0], F_GETFL);
787 perror(
"[tdeinit] Aborting. Can't make pipe non-blocking: ");
791 if (fcntl(d.deadpipe[0], F_SETFL, options | O_NONBLOCK) == -1)
793 perror(
"[tdeinit] 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_tdeinit_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,
"[tdeinit] Aborting. $HOME not set!");
840 TQCString path = home_dir;
841 TQCString readOnly = getenv(
"TDE_HOME_READONLY");
842 if (access(path.data(), R_OK|W_OK))
846 fprintf(stderr,
"[tdeinit] Aborting. $HOME directory (%s) does not exist.\n", path.data());
849 else if (readOnly.isEmpty())
851 fprintf(stderr,
"[tdeinit] 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,
"[tdeinit] 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,
"[tdeinit] Shutting down running client.\n");
894 tdelauncher_header request_header;
895 request_header.cmd = LAUNCHER_TERMINATE_TDEINIT;
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(
"[tdeinit] Aborting. socket() failed: ");
915 options = fcntl(d.wrapper, F_GETFL);
918 perror(
"[tdeinit] Aborting. Can't make socket non-blocking: ");
923 if (fcntl(d.wrapper, F_SETFL, options | O_NONBLOCK) == -1)
925 perror(
"[tdeinit] 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(
"[tdeinit] Aborting. bind() failed: ");
940 fprintf(stderr,
"Could not bind to socket '%s'\n", sock_file);
950 if (chmod(sock_file, 0600) != 0)
952 perror(
"[tdeinit] 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(
"[tdeinit] 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,
"[tdeinit] Communication error with launcher. Exiting!\n");
1079 fprintf(stderr,
"[tdeinit] TDELauncher 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,
"tdelauncher", 0 );
1095 fprintf(stderr,
"[tdeinit] Relaunching TDELauncher, 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 tdelauncher_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 tdelauncher_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,
"[tdeinit] 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,
"[tdeinit] EXEC request has invalid format.\n");
1224 d.debug_wait =
false;
1229 TQCString olddisplay = getenv(DISPLAY);
1230 TQCString kdedisplay = getenv(
"TDE_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(
"TDE_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,
"[tdeinit] Got SETENV '%s=%s' from tdelauncher.\n", env_name, env_value);
1278 fprintf(stderr,
"[tdeinit] 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,
"[tdeinit] 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,
"[tdeinit] Terminating Trinity.\n");
1298 tdeinit_xio_errhandler( 0L );
1301 else if (request_header.cmd == LAUNCHER_TERMINATE_TDEINIT)
1304 fprintf(stderr,
"[tdeinit] Killing tdeinit/tdelauncher.\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,
"[tdeinit] 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);
1357 if (waitForPid && (exit_pid == waitForPid))
1363 tdelauncher_header request_header;
1364 long request_data[2];
1365 request_header.cmd = LAUNCHER_DIED;
1366 request_header.arg_length =
sizeof(long) * 2;
1367 request_data[0] = exit_pid;
1368 request_data[1] = 0;
1369 write(d.launcher[0], &request_header,
sizeof(request_header));
1370 write(d.launcher[0], request_data, request_header.arg_length);
1374 while( exit_pid > 0);
1382 FD_SET(d.launcher[0], &rd_set);
1384 FD_SET(d.wrapper, &rd_set);
1387 FD_SET(d.wrapper_old, &rd_set);
1389 FD_SET(d.deadpipe[0], &rd_set);
1390 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
1392 if(X11fd >= 0) FD_SET(X11fd, &rd_set);
1395 result = select(max_sock, &rd_set, &wr_set, &e_set, 0);
1398 if ((result > 0) && (FD_ISSET(d.wrapper, &rd_set)))
1400 struct sockaddr_un client;
1401 kde_socklen_t sClient =
sizeof(client);
1402 int sock = accept(d.wrapper, (
struct sockaddr *)&client, &sClient);
1405 #if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
1406 if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
1407 FcInitReinitialize();
1412 reset_oom_protect();
1413 handle_launcher_request(sock);
1419 if ((result > 0) && (FD_ISSET(d.wrapper_old, &rd_set)))
1421 struct sockaddr_un client;
1422 kde_socklen_t sClient =
sizeof(client);
1423 int sock = accept(d.wrapper_old, (
struct sockaddr *)&client, &sClient);
1426 #if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
1427 if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
1428 FcInitReinitialize();
1433 reset_oom_protect();
1434 handle_launcher_request(sock);
1442 if ((result > 0) && (d.launcher_pid) && (FD_ISSET(d.launcher[0], &rd_set)))
1444 handle_launcher_request();
1445 if (waitForPid == d.launcher_pid)
1452 if((result > 0) && (X11fd >= 0))
1454 if(FD_ISSET(X11fd,&rd_set))
1456 if (X11display != 0) {
1457 XEvent event_return;
1458 while (XPending(X11display))
1459 XNextEvent(X11display, &event_return);
1467 static void tdeinit_library_path()
1469 TQStringList ltdl_library_path =
1470 TQStringList::split(
':', TQFile::decodeName(getenv(
"LTDL_LIBRARY_PATH")));
1471 TQStringList ld_library_path =
1472 TQStringList::split(
':', TQFile::decodeName(getenv(
"LD_LIBRARY_PATH")));
1474 TQCString extra_path;
1475 TQStringList candidates = s_instance->dirs()->resourceDirs(
"lib");
1476 for (TQStringList::ConstIterator it = candidates.begin();
1477 it != candidates.end();
1481 if (ltdl_library_path.contains(d))
1483 if (ld_library_path.contains(d))
1485 if (d[d.length()-1] ==
'/')
1487 d.truncate(d.length()-1);
1488 if (ltdl_library_path.contains(d))
1490 if (ld_library_path.contains(d))
1493 if ((d ==
"/lib") || (d ==
"/usr/lib"))
1496 TQCString dir = TQFile::encodeName(d);
1498 if (access(dir, R_OK))
1501 if ( !extra_path.isEmpty())
1508 const char * ltdlError = lt_dlerror();
1509 fprintf(stderr,
"[tdeinit] Can't initialize dynamic loading: %s\n", ltdlError != 0 ? ltdlError :
"(null)" );
1511 if (!extra_path.isEmpty())
1512 lt_dlsetsearchpath(extra_path.data());
1514 TQCString display = getenv(DISPLAY);
1515 if (display.isEmpty())
1517 fprintf(stderr,
"[tdeinit] Aborting. $" DISPLAY
" is not set.\n");
1521 if((i = display.findRev(
'.')) > display.findRev(
':') && i >= 0)
1522 display.truncate(i);
1524 TQCString socketName = TQFile::encodeName(locateLocal(
"socket", TQString(
"tdeinit-%1").arg(TQString(display)), s_instance));
1525 if (socketName.length() >= MAX_SOCK_FILE)
1527 fprintf(stderr,
"[tdeinit] Aborting. Socket name will be too long:\n");
1528 fprintf(stderr,
" '%s'\n", socketName.data());
1531 strcpy(sock_file_old, socketName.data());
1533 display.replace(
":",
"_");
1534 socketName = TQFile::encodeName(locateLocal(
"socket", TQString(
"tdeinit_%1").arg(TQString(display)), s_instance));
1535 if (socketName.length() >= MAX_SOCK_FILE)
1537 fprintf(stderr,
"[tdeinit] Aborting. Socket name will be too long:\n");
1538 fprintf(stderr,
" '%s'\n", socketName.data());
1541 strcpy(sock_file, socketName.data());
1544 int tdeinit_xio_errhandler( Display *disp )
1549 tqWarning(
"[tdeinit] Fatal IO error: client killed" );
1556 if (sock_file_old[0])
1559 unlink(sock_file_old);
1566 kill(d.launcher_pid, SIGTERM);
1571 tqWarning(
"[tdeinit] sending SIGHUP to children." );
1574 signal(SIGHUP, SIG_IGN);
1580 tqWarning(
"[tdeinit] sending SIGTERM to children." );
1583 signal(SIGTERM, SIG_IGN);
1587 tqWarning(
"[tdeinit] Exit." );
1594 int tdeinit_x_errhandler( Display *dpy, XErrorEvent *err )
1599 XGetErrorText( dpy, err->error_code, errstr, 256 );
1600 fprintf(stderr,
"[tdeinit] TDE detected X Error: %s %d\n"
1601 " Major opcode: %d\n"
1602 " Minor opcode: %d\n"
1603 " Resource id: 0x%lx\n",
1604 errstr, err->error_code, err->request_code, err->minor_code, err->resourceid );
1617 static void setupX()
1620 XSetIOErrorHandler(tdeinit_xio_errhandler);
1621 XSetErrorHandler(tdeinit_x_errhandler);
1625 static int initXconnection()
1627 X11display = XOpenDisplay(NULL);
1628 if ( X11display != 0 ) {
1629 XCreateSimpleWindow(X11display, DefaultRootWindow(X11display), 0,0,1,1, \
1631 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)),
1632 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)) );
1634 fprintf(stderr,
"[tdeinit] Opened connection to %s\n", DisplayString(X11display));
1636 int fd = XConnectionNumber( X11display );
1638 (void) setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (
char *) &on, (int)
sizeof(on));
1641 fprintf(stderr,
"[tdeinit] Can't connect to the X Server.\n" \
1642 "[tdeinit] Might not terminate at end of session.\n");
1668 extern "C" void _main(
void);
1669 extern "C" void __call_ctors__Fv(
void);
1670 static int main_called = 0;
1676 __call_ctors__Fv ();
1680 static void secondary_child_handler(
int)
1682 waitpid(-1, 0, WNOHANG);
1685 int main(
int argc,
char **argv,
char **envp)
1689 int launch_dcop = 1;
1690 int launch_tdelauncher = 1;
1691 int launch_kded = 1;
1692 int keep_running = 1;
1693 int new_startup = 0;
1697 char **safe_argv = (
char **) malloc(
sizeof(
char *) * argc);
1698 for(i = 0; i < argc; i++)
1700 safe_argv[i] = strcpy((
char*)malloc(strlen(argv[i])+1), argv[i]);
1701 if (strcmp(safe_argv[i],
"--no-dcop") == 0)
1703 if (strcmp(safe_argv[i],
"--no-tdelauncher") == 0)
1704 launch_tdelauncher = 0;
1705 if (strcmp(safe_argv[i],
"--no-kded") == 0)
1707 if (strcmp(safe_argv[i],
"--suicide") == 0)
1709 if (strcmp(safe_argv[i],
"--exit") == 0)
1711 if (strcmp(safe_argv[i],
"--new-startup") == 0)
1713 #ifdef TDEINIT_OOM_PROTECT
1714 if (strcmp(safe_argv[i],
"--oom-pipe") == 0 && i+1<argc)
1715 oom_pipe = atol(argv[i+1]);
1717 if (strcmp(safe_argv[i],
"--help") == 0)
1719 printf(
"Usage: tdeinit [options]\n");
1722 printf(
" --no-kded Do not start kded\n");
1723 printf(
" --suicide Terminate when no TDE applications are left running\n");
1734 signal( SIGCHLD, secondary_child_handler);
1737 close(d.initpipe[1]);
1741 while( read(d.initpipe[0], &c, 1) < 0);
1743 close(d.initpipe[0]);
1747 close(d.initpipe[0]);
1749 d.my_pid = getpid();
1756 s_instance =
new TDEInstance(
"tdeinit");
1759 tdeinit_initsetproctitle(argc, argv, envp);
1760 tdeinit_library_path();
1764 TDEGlobal::_instance = 0L;
1766 unsetenv(
"LD_BIND_NOW");
1767 unsetenv(
"DYLD_BIND_AT_LAUNCH");
1768 TDEApplication::loadedByKdeinit =
true;
1770 d.maxname = strlen(argv[0]);
1774 d.debug_wait =
false;
1775 d.launcher_ok =
false;
1776 d.lt_dlopen_flag = lt_dlopen_flag;
1777 lt_dlopen_flag |= LTDL_GLOBAL;
1789 init_tdeinit_socket();
1795 pid = launch( 3,
"dcopserver",
"--nosid\0--suicide" );
1797 pid = launch( 2,
"dcopserver",
"--nosid" );
1799 fprintf(stderr,
"[tdeinit] Launched DCOPServer, pid = %ld result = %d\n", (
long) pid, d.result);
1802 if (!WIFEXITED(d.exit_status) || (WEXITSTATUS(d.exit_status) != 0))
1804 fprintf(stderr,
"[tdeinit] DCOPServer could not be started, aborting.\n");
1809 if (!d.suicide && !getenv(
"TDE_IS_PRELINKED"))
1811 TQString konq = locate(
"lib",
"libkonq.la", s_instance);
1812 if (!konq.isEmpty())
1813 (
void) lt_dlopen(TQFile::encodeName(konq).data());
1816 if (launch_tdelauncher)
1819 pid = launch( 2,
"tdelauncher",
"--new-startup" );
1821 pid = launch( 1,
"tdelauncher", 0 );
1823 fprintf(stderr,
"[tdeinit] Launched TDELauncher, pid = %ld result = %d\n", (
long) pid, d.result);
1825 handle_requests(pid);
1828 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
1830 X11fd = initXconnection();
1834 #if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
1835 if( FcGetVersion() < 20390 )
1841 TQFont::initialize();
1842 setlocale (LC_ALL,
"");
1843 setlocale (LC_NUMERIC,
"C");
1845 if (XSupportsLocale ())
1849 XOpenIM (X11display, 0, 0, 0);
1857 pid = launch( 2,
"kded",
"--new-startup" );
1859 pid = launch( 1,
"kded", 0 );
1861 fprintf(stderr,
"[tdeinit] Launched KDED, pid = %ld result = %d\n", (
long) pid, d.result);
1863 handle_requests(pid);
1866 for(i = 1; i < argc; i++)
1868 if (safe_argv[i][0] ==
'+')
1870 pid = launch( 1, safe_argv[i]+1, 0);
1872 fprintf(stderr,
"[tdeinit] Launched '%s', pid = %ld result = %d\n", safe_argv[i]+1, (
long) pid, d.result);
1874 handle_requests(pid);
1876 else if (safe_argv[i][0] ==
'-'
1877 #ifdef TDEINIT_OOM_PROTECT
1878 || isdigit(safe_argv[i][0])
1886 pid = launch( 1, safe_argv[i], 0 );
1888 fprintf(stderr,
"[tdeinit] Launched '%s', pid = %ld result = %d\n", safe_argv[i], (
long) pid, d.result);
1894 for(i = 0; i < argc; i++)
1900 tdeinit_setproctitle(
"[tdeinit] tdeinit Running...");
1906 write(d.initpipe[1], &c, 1);
1907 close(d.initpipe[1]);