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 <tdeinstance.h>
56#include <tdestandarddirs.h>
59#include <klibloader.h>
60#include <tdeapplication.h>
62#include <dcopglobal.h>
64#ifdef HAVE_SYS_PRCTL_H
71#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
72#include <tdestartupinfo.h>
76#include "tdelauncher_cmds.h"
90# define LTDL_GLOBAL RTLD_GLOBAL
93# define LTDL_GLOBAL DL_GLOBAL
99#if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
100#include <X11/Xft/Xft.h>
101extern "C" FcBool XftInitFtLibrary (
void);
102#include <fontconfig/fontconfig.h>
105extern char **environ;
107extern int lt_dlopen_flag;
110static int X11fd = -1;
111static Display *X11display = 0;
112static int X11_startup_notify_fd = -1;
113static Display *X11_startup_notify_display = 0;
115static const TDEInstance *s_instance = 0;
116#define MAX_SOCK_FILE 255
117static char sock_file[MAX_SOCK_FILE];
118static char sock_file_old[MAX_SOCK_FILE];
122#define DISPLAY "DISPLAY"
123#elif defined(TQ_WS_QWS)
124#define DISPLAY "QWS_DISPLAY"
125#elif defined(TQ_WS_MACX)
126#define DISPLAY "MAC_DISPLAY"
127#elif defined(K_WS_QTONLY)
128#define DISPLAY "QT_DISPLAY"
130#error Use QT/X11 or QT/Embedded
151 int (*func)(int,
char *[]);
152 int (*launcher_func)(int);
163int tdeinit_xio_errhandler( Display * );
164int tdeinit_x_errhandler( Display *, XErrorEvent *err );
169#include <tdeparts/plugin.h>
170extern "C" KParts::Plugin* _tdeinit_init_tdeparts() {
return new KParts::Plugin(); }
172#include <tdeio/authinfo.h>
173extern "C" TDEIO::AuthInfo* _tdeioslave_init_tdeio() {
return new TDEIO::AuthInfo(); }
179static void close_fds()
181 if (d.deadpipe[0] != -1)
183 close(d.deadpipe[0]);
187 if (d.deadpipe[1] != -1)
189 close(d.deadpipe[1]);
193 if (d.initpipe[0] != -1)
195 close(d.initpipe[0]);
199 if (d.initpipe[1] != -1)
201 close(d.initpipe[1]);
207 close(d.launcher[0]);
217 close(d.wrapper_old);
220#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
227 if (X11_startup_notify_fd >= 0 && X11_startup_notify_fd != X11fd )
229 close(X11_startup_notify_fd);
230 X11_startup_notify_fd = -1;
234 signal(SIGCHLD, SIG_DFL);
235 signal(SIGPIPE, SIG_DFL);
238static void exitWithErrorMsg(
const TQString &errorMsg)
240 fprintf( stderr,
"[tdeinit] %s\n", errorMsg.local8Bit().data() );
241 TQCString utf8ErrorMsg = errorMsg.utf8();
243 write(d.fd[1], &d.result, 1);
244 int l = utf8ErrorMsg.length();
245 write(d.fd[1], &l,
sizeof(
int));
246 write(d.fd[1], utf8ErrorMsg.data(), l);
251static void setup_tty(
const char* tty )
253 if( tty == NULL || *tty ==
'\0' )
255 int fd = open( tty, O_WRONLY );
258 fprintf(stderr,
"[tdeinit] Couldn't open() %s: %s\n", tty, strerror (errno) );
261 if( dup2( fd, STDOUT_FILENO ) < 0 )
263 fprintf(stderr,
"[tdeinit] Couldn't dup2() %s: %s\n", tty, strerror (errno) );
267 if( dup2( fd, STDERR_FILENO ) < 0 )
269 fprintf(stderr,
"[tdeinit] Couldn't dup2() %s: %s\n", tty, strerror (errno) );
277static int get_current_desktop( Display* disp )
280#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
282 Atom net_current_desktop = XInternAtom( disp,
"_NET_CURRENT_DESKTOP", False );
285 unsigned char *data_ret;
286 unsigned long nitems_ret, unused;
287 if( XGetWindowProperty( disp, DefaultRootWindow( disp ), net_current_desktop,
288 0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret )
291 if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1)
292 desktop = *((
long *) data_ret) + 1;
294 XFree ((
char*) data_ret);
301const char* get_env_var(
const char* var,
int envc,
const char* envs )
305 const char* env_l = envs;
306 int ln = strlen( var );
307 for (
int i = 0; i < envc; i++)
309 if( strncmp( env_l, var, ln ) == 0 )
311 while(*env_l != 0) env_l++;
318#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
320static void init_startup_info( TDEStartupInfoId&
id,
const char* bin,
321 int envc,
const char* envs )
323 const char* dpy = get_env_var( DISPLAY
"=", envc, envs );
326 X11_startup_notify_display = XOpenDisplay( dpy );
327 if( X11_startup_notify_display == NULL )
329 X11_startup_notify_fd = XConnectionNumber( X11_startup_notify_display );
330 TDEStartupInfoData data;
331 int desktop = get_current_desktop( X11_startup_notify_display );
332 data.setDesktop( desktop );
334 TDEStartupInfo::sendChangeX( X11_startup_notify_display,
id, data );
335 XFlush( X11_startup_notify_display );
338static void complete_startup_info( TDEStartupInfoId&
id, pid_t pid )
340 if( X11_startup_notify_display == NULL )
343 TDEStartupInfo::sendFinishX( X11_startup_notify_display,
id );
346 TDEStartupInfoData data;
349 TDEStartupInfo::sendChangeX( X11_startup_notify_display,
id, data );
351 XCloseDisplay( X11_startup_notify_display );
352 X11_startup_notify_display = NULL;
353 X11_startup_notify_fd = -1;
357TQCString execpath_avoid_loops(
const TQCString& exec,
int envc,
const char* envs,
bool avoid_loops )
362 const char* path = get_env_var(
"PATH=", envc, envs );
364 paths = TQStringList::split( TQRegExp(
"[:\b]" ), path,
true );
367 paths = TQStringList::split( TQRegExp(
"[:\b]" ), getenv(
"PATH" ),
true );
368 TQCString execpath = TQFile::encodeName(
369 s_instance->dirs()->findExe( exec, paths.join( TQString(
":" ))));
370 if( avoid_loops && !execpath.isEmpty())
372 int pos = execpath.findRev(
'/' );
373 TQString bin_path = execpath.left( pos );
374 for( TQStringList::Iterator it = paths.begin();
377 if( ( *it ) == bin_path || ( *it ) == bin_path +
'/' )
382 execpath = TQFile::encodeName(
383 s_instance->dirs()->findExe( exec, paths.join( TQString(
":" ))));
388#ifdef TDEINIT_OOM_PROTECT
389static int oom_pipe = -1;
391static void oom_protect_sighandler(
int ) {
394static void reset_oom_protect() {
397 struct sigaction act, oldact;
398 act.sa_handler = oom_protect_sighandler;
400 sigemptyset( &act.sa_mask );
401 sigaction( SIGUSR1, &act, &oldact );
402 sigset_t sigs, oldsigs;
403 sigemptyset( &sigs );
404 sigaddset( &sigs, SIGUSR1 );
405 sigprocmask( SIG_BLOCK, &sigs, &oldsigs );
406 pid_t pid = getpid();
407 if( write( oom_pipe, &pid,
sizeof( pid_t )) > 0 ) {
408 sigsuspend( &oldsigs );
410 sigprocmask( SIG_SETMASK, &oldsigs, NULL );
411 sigaction( SIGUSR1, &oldact, NULL );
416static void reset_oom_protect() {
420static pid_t launch(
int argc,
const char *_name,
const char *args,
421 const char *cwd=0,
int envc=0,
const char *envs=0,
422 bool reset_env =
false,
423 const char *tty=0,
bool avoid_loops =
false,
424 const char* startup_id_str =
"0" )
431 if (strcmp(_name,
"tdelauncher") == 0) {
435 if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, d.launcher))
437 perror(
"[tdeinit] socketpair() failed!\n");
451 libpath = TQFile::encodeName(KLibLoader::findLibrary( lib, s_instance ));
452 execpath = execpath_avoid_loops( exec, envc, envs, avoid_loops );
458 name = name.mid( name.findRev(
'/') + 1);
460 if (lib.right(3) ==
".la")
472 perror(
"[tdeinit] pipe() failed!\n");
474 d.errorMsg = i18n(
"Unable to start new process.\n"
475 "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();
482#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
484 TDEStartupInfoId startup_id;
485 startup_id.initId( startup_id_str );
486 if( !startup_id.none())
487 init_startup_info( startup_id, name, envc, envs );
494 perror(
"[tdeinit] fork() failed!\n");
496 d.errorMsg = i18n(
"Unable to create new process.\n"
497 "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();
508 if (d.fd[1] == LAUNCHER_FD)
510 d.fd[1] = dup(d.fd[1]);
512 if (d.launcher[1] != LAUNCHER_FD)
514 dup2( d.launcher[1], LAUNCHER_FD);
515 close( d.launcher[1] );
517 close( d.launcher[0] );
527 TQStrList unset_envs;
528 for(
int tmp_env_count = 0;
529 environ[tmp_env_count];
531 unset_envs.append( environ[ tmp_env_count ] );
532 for( TQStrListIterator it( unset_envs );
533 it.current() != NULL ;
536 TQCString tmp( it.current());
537 int pos = tmp.find(
'=' );
539 unsetenv( tmp.left( pos ));
543 for (
int i = 0; i < envc; i++)
545 putenv((
char *)envs);
546 while(*envs != 0) envs++;
550#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
552 if( startup_id.none())
553 TDEStartupInfo::resetStartupEnv();
555 startup_id.setupStartupEnv();
560 d.argv = (
char **) malloc(
sizeof(
char *) * (argc+1));
561 d.argv[0] = (
char *) _name;
562 for (
int i = 1; i < argc; i++)
564 d.argv[i] = (
char *) args;
566 procTitle += (
char *) args;
567 while(*args != 0) args++;
573#ifdef HAVE_SYS_PRCTL_H
575 r = prctl(PR_SET_NAME, (
unsigned long) name.data(), 0, 0, 0);
577 tdeinit_setproctitle(
"%s [tdeinit]%s", name.data(), procTitle.data() ? procTitle.data() :
"" );
579 tdeinit_setproctitle(
"[tdeinit] %s%s", name.data(), procTitle.data() ? procTitle.data() :
"" );
581 tdeinit_setproctitle(
"[tdeinit] %s%s", name.data(), procTitle.data() ? procTitle.data() :
"" );
586 if (libpath.isEmpty() && execpath.isEmpty())
588 TQString errorMsg = i18n(
"Could not find '%1' executable.").arg(TQFile::decodeName(_name));
589 exitWithErrorMsg(errorMsg);
592 if ( getenv(
"TDE_IS_PRELINKED") && !execpath.isEmpty() && !launcher)
595 if ( !libpath.isEmpty() )
597 d.handle = lt_dlopen( TQFile::encodeName(libpath) );
600 const char * ltdlError = lt_dlerror();
601 if (execpath.isEmpty())
604 TQString errorMsg = i18n(
"Could not open library '%1'.\n%2").arg(TQFile::decodeName(libpath))
605 .arg(ltdlError ? TQFile::decodeName(ltdlError) : i18n(
"Unknown error"));
606 exitWithErrorMsg(errorMsg);
611 fprintf(stderr,
"Could not open library %s: %s\n", lib.data(), ltdlError != 0 ? ltdlError :
"(null)" );
615 lt_dlopen_flag = d.lt_dlopen_flag;
619 write(d.fd[1], &d.result, 1);
623 fcntl(d.fd[1], F_SETFD, FD_CLOEXEC);
627 execvp(execpath.data(), d.argv);
629 write(d.fd[1], &d.result, 1);
634 d.sym = lt_dlsym( d.handle,
"tdeinitmain");
637 d.sym = lt_dlsym( d.handle,
"kdemain" );
642 const char * ltdlError = lt_dlerror();
643 fprintf(stderr,
"Could not find kdemain: %s\n", ltdlError != 0 ? ltdlError :
"(null)" );
644 TQString errorMsg = i18n(
"Could not find 'kdemain' in '%1'.\n%2").arg(TQString(libpath))
645 .arg(ltdlError ? TQFile::decodeName(ltdlError) : i18n(
"Unknown error"));
646 exitWithErrorMsg(errorMsg);
652 write(d.fd[1], &d.result, 1);
655 d.func = (int (*)(int,
char *[])) d.sym;
658 fprintf(stderr,
"[tdeinit] Suspending process\n"
659 "[tdeinit] 'gdb tdeinit %d' to debug\n"
660 "[tdeinit] 'kill -SIGCONT %d' to continue\n",
662 kill(getpid(), SIGSTOP);
669 exit( d.func(argc, d.argv));
677 close(d.launcher[1]);
678 d.launcher_pid = d.fork;
683 d.n = read(d.fd[0], &d.result, 1);
689 fprintf(stderr,
"[tdeinit] %s is executable. Launching.\n", _name );
697 d.n = read(d.fd[0], &l,
sizeof(
int));
698 if (d.n ==
sizeof(
int))
702 d.n = read(d.fd[0], tmp.data(), l);
713 if (errno == ECHILD) {
716 if (errno == EINTR || errno == EAGAIN) {
727 perror(
"[tdeinit] Pipe closed unexpectedly");
731 perror(
"[tdeinit] Error reading from pipe");
736 if (launcher && (d.result == 0))
739 d.launcher_pid = d.fork;
742#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
744 if( !startup_id.none())
746 if( d.fork && d.result == 0 )
747 complete_startup_info( startup_id, d.fork );
749 complete_startup_info( startup_id, 0 );
755static void sig_child_handler(
int)
766 write(d.deadpipe[1], &c, 1);
769static void init_signals()
771 struct sigaction act;
774 if (pipe(d.deadpipe) != 0)
776 perror(
"[tdeinit] Aborting. Can't create pipe: ");
780 options = fcntl(d.deadpipe[0], F_GETFL);
783 perror(
"[tdeinit] Aborting. Can't make pipe non-blocking: ");
787 if (fcntl(d.deadpipe[0], F_SETFL, options | O_NONBLOCK) == -1)
789 perror(
"[tdeinit] Aborting. Can't make pipe non-blocking: ");
798 act.sa_handler=sig_child_handler;
799 sigemptyset(&(act.sa_mask));
800 sigaddset(&(act.sa_mask), SIGCHLD);
801 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
802 act.sa_flags = SA_NOCLDSTOP;
808 act.sa_flags |= SA_RESTART;
810 sigaction( SIGCHLD, &act, 0L);
812 act.sa_handler=SIG_IGN;
813 sigemptyset(&(act.sa_mask));
814 sigaddset(&(act.sa_mask), SIGPIPE);
815 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
817 sigaction( SIGPIPE, &act, 0L);
820static void init_tdeinit_socket()
822 struct sockaddr_un sa;
823 struct sockaddr_un sa_old;
824 kde_socklen_t socklen;
826 const char *home_dir = getenv(
"HOME");
828 if (!home_dir || !home_dir[0])
830 fprintf(stderr,
"[tdeinit] Aborting. $HOME not set!");
836 TQCString path = home_dir;
837 TQCString readOnly = getenv(
"TDE_HOME_READONLY");
838 if (access(path.data(), R_OK|W_OK))
842 fprintf(stderr,
"[tdeinit] Aborting. $HOME directory (%s) does not exist.\n", path.data());
845 else if (readOnly.isEmpty())
847 fprintf(stderr,
"[tdeinit] Aborting. No write access to $HOME directory (%s).\n", path.data());
851 path = IceAuthFileName();
852 if (access(path.data(), R_OK|W_OK) && (errno != ENOENT))
854 fprintf(stderr,
"[tdeinit] Aborting. No write access to '%s'.\n", path.data());
863 if (access(sock_file, W_OK) == 0)
866 struct sockaddr_un server;
872 s = socket(PF_UNIX, SOCK_STREAM, 0);
875 perror(
"socket() failed: ");
878 server.sun_family = AF_UNIX;
879 strcpy(server.sun_path, sock_file);
880 socklen =
sizeof(server);
882 if(connect(s, (
struct sockaddr *)&server, socklen) == 0)
884 fprintf(stderr,
"[tdeinit] Shutting down running client.\n");
885 tdelauncher_header request_header;
886 request_header.cmd = LAUNCHER_TERMINATE_TDEINIT;
887 request_header.arg_length = 0;
888 write(s, &request_header,
sizeof(request_header));
896 unlink(sock_file_old);
899 d.wrapper = socket(PF_UNIX, SOCK_STREAM, 0);
902 perror(
"[tdeinit] Aborting. socket() failed: ");
906 options = fcntl(d.wrapper, F_GETFL);
909 perror(
"[tdeinit] Aborting. Can't make socket non-blocking: ");
914 if (fcntl(d.wrapper, F_SETFL, options | O_NONBLOCK) == -1)
916 perror(
"[tdeinit] Aborting. Can't make socket non-blocking: ");
923 socklen =
sizeof(sa);
924 memset(&sa, 0, socklen);
925 sa.sun_family = AF_UNIX;
926 strcpy(sa.sun_path, sock_file);
927 if(bind(d.wrapper, (
struct sockaddr *)&sa, socklen) != 0)
929 if (max_tries == 0) {
930 perror(
"[tdeinit] Aborting. bind() failed: ");
931 fprintf(stderr,
"Could not bind to socket '%s'\n", sock_file);
941 if (chmod(sock_file, 0600) != 0)
943 perror(
"[tdeinit] Aborting. Can't set permissions on socket: ");
944 fprintf(stderr,
"Wrong permissions of socket '%s'\n", sock_file);
950 if(listen(d.wrapper, SOMAXCONN) < 0)
952 perror(
"[tdeinit] Aborting. listen() failed: ");
959 d.wrapper_old = socket(PF_UNIX, SOCK_STREAM, 0);
960 if (d.wrapper_old < 0)
966 options = fcntl(d.wrapper_old, F_GETFL);
970 close(d.wrapper_old);
975 if (fcntl(d.wrapper_old, F_SETFL, options | O_NONBLOCK) == -1)
978 close(d.wrapper_old);
986 socklen =
sizeof(sa_old);
987 memset(&sa_old, 0, socklen);
988 sa_old.sun_family = AF_UNIX;
989 strcpy(sa_old.sun_path, sock_file_old);
990 if(bind(d.wrapper_old, (
struct sockaddr *)&sa_old, socklen) != 0)
992 if (max_tries == 0) {
994 fprintf(stderr,
"Could not bind to socket '%s'\n", sock_file_old);
995 close(d.wrapper_old);
1005 if (chmod(sock_file_old, 0600) != 0)
1007 fprintf(stderr,
"Wrong permissions of socket '%s'\n", sock_file);
1008 unlink(sock_file_old);
1009 close(d.wrapper_old);
1014 if(listen(d.wrapper_old, SOMAXCONN) < 0)
1017 unlink(sock_file_old);
1018 close(d.wrapper_old);
1027static int read_socket(
int sock,
char *buffer,
int len)
1030 int bytes_left = len;
1031 while ( bytes_left > 0)
1033 result = read(sock, buffer, bytes_left);
1037 bytes_left -= result;
1039 else if (result == 0)
1041 else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
1047static void WaitPid( pid_t waitForPid)
1052 result = waitpid(waitForPid, &d.exit_status, 0);
1053 if ((result == -1) && (errno == ECHILD))
1058static void launcher_died()
1063 fprintf(stderr,
"[tdeinit] Communication error with launcher. Exiting!\n");
1070 fprintf(stderr,
"[tdeinit] TDELauncher died unexpectedly.\n");
1075 kill(d.launcher_pid, SIGKILL);
1079 d.launcher_ok =
false;
1081 close(d.launcher[0]);
1084 pid_t pid = launch( 1,
"tdelauncher", 0 );
1086 fprintf(stderr,
"[tdeinit] Relaunching TDELauncher, pid = %ld result = %d\n", (
long) pid, d.result);
1090static void handle_launcher_request(
int sock = -1)
1092 bool launcher =
false;
1095 sock = d.launcher[0];
1099 tdelauncher_header request_header;
1100 char *request_data = 0L;
1101 int result = read_socket(sock, (
char *) &request_header,
sizeof(request_header));
1109 if ( request_header.arg_length != 0 )
1111 request_data = (
char *) malloc(request_header.arg_length);
1113 result = read_socket(sock, request_data, request_header.arg_length);
1123 if (request_header.cmd == LAUNCHER_OK)
1125 d.launcher_ok =
true;
1127 else if (request_header.arg_length &&
1128 ((request_header.cmd == LAUNCHER_EXEC) ||
1129 (request_header.cmd == LAUNCHER_EXT_EXEC) ||
1130 (request_header.cmd == LAUNCHER_SHELL ) ||
1131 (request_header.cmd == LAUNCHER_KWRAPPER) ||
1132 (request_header.cmd == LAUNCHER_EXEC_NEW)))
1135 tdelauncher_header response_header;
1138 memcpy( &l, request_data,
sizeof(
long ));
1140 const char *name = request_data +
sizeof(long);
1141 const char *args = name + strlen(name) + 1;
1142 const char *cwd = 0;
1144 const char *envs = 0;
1145 const char *tty = 0;
1146 int avoid_loops = 0;
1147 const char *startup_id_str =
"0";
1150 fprintf(stderr,
"[tdeinit] Got %s '%s' from %s.\n",
1151 (request_header.cmd == LAUNCHER_EXEC ?
"EXEC" :
1152 (request_header.cmd == LAUNCHER_EXT_EXEC ?
"EXT_EXEC" :
1153 (request_header.cmd == LAUNCHER_EXEC_NEW ?
"EXEC_NEW" :
1154 (request_header.cmd == LAUNCHER_SHELL ?
"SHELL" :
"KWRAPPER" )))),
1155 name, launcher ?
"launcher" :
"socket" );
1158 const char *arg_n = args;
1159 for(
int i = 1; i < argc; i++)
1161 arg_n = arg_n + strlen(arg_n) + 1;
1164 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER )
1167 cwd = arg_n; arg_n += strlen(cwd) + 1;
1169 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
1170 || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
1172 memcpy( &l, arg_n,
sizeof(
long ));
1174 arg_n +=
sizeof(long);
1176 for(
int i = 0; i < envc; i++)
1178 arg_n = arg_n + strlen(arg_n) + 1;
1180 if( request_header.cmd == LAUNCHER_KWRAPPER )
1183 arg_n += strlen( tty ) + 1;
1187 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
1188 || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
1190 memcpy( &l, arg_n,
sizeof(
long ));
1192 arg_n +=
sizeof( long );
1195 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
1196 || request_header.cmd == LAUNCHER_EXT_EXEC )
1198 startup_id_str = arg_n;
1199 arg_n += strlen( startup_id_str ) + 1;
1202 if ((request_header.arg_length > (arg_n - request_data)) &&
1203 (request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW ))
1206 cwd = arg_n; arg_n += strlen(cwd) + 1;
1209 if ((arg_n - request_data) != request_header.arg_length)
1212 fprintf(stderr,
"[tdeinit] EXEC request has invalid format.\n");
1215 d.debug_wait =
false;
1220 TQCString olddisplay = getenv(DISPLAY);
1221 TQCString kdedisplay = getenv(
"TDE_DISPLAY");
1222 bool reset_display = (! olddisplay.isEmpty() &&
1223 ! kdedisplay.isEmpty() &&
1224 olddisplay != kdedisplay);
1227 setenv(DISPLAY, kdedisplay,
true);
1229 pid = launch( argc, name, args, cwd, envc, envs,
1230 request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER,
1231 tty, avoid_loops, startup_id_str );
1233 if (reset_display) {
1234 unsetenv(
"TDE_DISPLAY");
1235 setenv(DISPLAY, olddisplay,
true);
1238 if (pid && (d.result == 0))
1240 response_header.cmd = LAUNCHER_OK;
1241 response_header.arg_length =
sizeof(response_data);
1242 response_data = pid;
1243 write(sock, &response_header,
sizeof(response_header));
1244 write(sock, &response_data, response_header.arg_length);
1248 int l = d.errorMsg.length();
1250 response_header.cmd = LAUNCHER_ERROR;
1251 response_header.arg_length = l;
1252 write(sock, &response_header,
sizeof(response_header));
1254 write(sock, d.errorMsg.data(), l);
1256 d.debug_wait =
false;
1258 else if (request_header.arg_length && request_header.cmd == LAUNCHER_SETENV)
1260 const char *env_name;
1261 const char *env_value;
1262 env_name = request_data;
1263 env_value = env_name + strlen(env_name) + 1;
1267 fprintf(stderr,
"[tdeinit] Got SETENV '%s=%s' from tdelauncher.\n", env_name, env_value);
1269 fprintf(stderr,
"[tdeinit] Got SETENV '%s=%s' from socket.\n", env_name, env_value);
1272 if ( request_header.arg_length !=
1273 (
int) (strlen(env_name) + strlen(env_value) + 2))
1276 fprintf(stderr,
"[tdeinit] SETENV request has invalid format.\n");
1281 setenv( env_name, env_value, 1);
1283 else if (request_header.cmd == LAUNCHER_TERMINATE_KDE)
1286 fprintf(stderr,
"[tdeinit] Terminating Trinity.\n");
1289 tdeinit_xio_errhandler( 0L );
1292 else if (request_header.cmd == LAUNCHER_TERMINATE_TDEINIT)
1295 fprintf(stderr,
"[tdeinit] Killing tdeinit/tdelauncher.\n");
1298 kill(d.launcher_pid, SIGTERM);
1300 kill(d.my_pid, SIGTERM);
1302 else if (request_header.cmd == LAUNCHER_DEBUG_WAIT)
1305 fprintf(stderr,
"[tdeinit] Debug wait activated.\n");
1307 d.debug_wait =
true;
1313static void handle_requests(pid_t waitForPid)
1315 int max_sock = d.wrapper;
1316 if (d.wrapper_old > max_sock)
1317 max_sock = d.wrapper_old;
1318 if (d.launcher_pid && (d.launcher[0] > max_sock))
1319 max_sock = d.launcher[0];
1320#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
1322 if (X11fd > max_sock)
1337 while( read(d.deadpipe[0], &c, 1) == 1);
1341 exit_pid = waitpid(-1, 0, WNOHANG);
1348 if (waitForPid && (exit_pid == waitForPid))
1354 tdelauncher_header request_header;
1355 long request_data[2];
1356 request_header.cmd = LAUNCHER_DIED;
1357 request_header.arg_length =
sizeof(long) * 2;
1358 request_data[0] = exit_pid;
1359 request_data[1] = 0;
1360 write(d.launcher[0], &request_header,
sizeof(request_header));
1361 write(d.launcher[0], request_data, request_header.arg_length);
1365 while( exit_pid > 0);
1373 FD_SET(d.launcher[0], &rd_set);
1375 FD_SET(d.wrapper, &rd_set);
1378 FD_SET(d.wrapper_old, &rd_set);
1380 FD_SET(d.deadpipe[0], &rd_set);
1381#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
1383 if(X11fd >= 0) FD_SET(X11fd, &rd_set);
1386 result = select(max_sock, &rd_set, &wr_set, &e_set, 0);
1389 if ((result > 0) && (FD_ISSET(d.wrapper, &rd_set)))
1391 struct sockaddr_un client;
1392 kde_socklen_t sClient =
sizeof(client);
1393 int sock = accept(d.wrapper, (
struct sockaddr *)&client, &sClient);
1396#if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
1397 if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
1398 FcInitReinitialize();
1403 reset_oom_protect();
1404 handle_launcher_request(sock);
1410 if ((result > 0) && (FD_ISSET(d.wrapper_old, &rd_set)))
1412 struct sockaddr_un client;
1413 kde_socklen_t sClient =
sizeof(client);
1414 int sock = accept(d.wrapper_old, (
struct sockaddr *)&client, &sClient);
1417#if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
1418 if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
1419 FcInitReinitialize();
1424 reset_oom_protect();
1425 handle_launcher_request(sock);
1433 if ((result > 0) && (d.launcher_pid) && (FD_ISSET(d.launcher[0], &rd_set)))
1435 handle_launcher_request();
1436 if (waitForPid == d.launcher_pid)
1443 if((result > 0) && (X11fd >= 0))
1445 if(FD_ISSET(X11fd,&rd_set))
1447 if (X11display != 0) {
1448 XEvent event_return;
1449 while (XPending(X11display))
1450 XNextEvent(X11display, &event_return);
1458static void tdeinit_library_path()
1460 TQStringList ltdl_library_path =
1461 TQStringList::split(
':', TQFile::decodeName(getenv(
"LTDL_LIBRARY_PATH")));
1462 TQStringList ld_library_path =
1463 TQStringList::split(
':', TQFile::decodeName(getenv(
"LD_LIBRARY_PATH")));
1465 TQCString extra_path;
1466 TQStringList candidates = s_instance->dirs()->resourceDirs(
"lib");
1467 for (TQStringList::ConstIterator it = candidates.begin();
1468 it != candidates.end();
1472 if (ltdl_library_path.contains(d))
1474 if (ld_library_path.contains(d))
1476 if (d[d.length()-1] ==
'/')
1478 d.truncate(d.length()-1);
1479 if (ltdl_library_path.contains(d))
1481 if (ld_library_path.contains(d))
1484 if ((d ==
"/lib") || (d ==
"/usr/lib"))
1487 TQCString dir = TQFile::encodeName(d);
1489 if (access(dir, R_OK))
1492 if ( !extra_path.isEmpty())
1499 const char * ltdlError = lt_dlerror();
1500 fprintf(stderr,
"[tdeinit] Can't initialize dynamic loading: %s\n", ltdlError != 0 ? ltdlError :
"(null)" );
1502 if (!extra_path.isEmpty())
1503 lt_dlsetsearchpath(extra_path.data());
1505 TQCString display = getenv(DISPLAY);
1506 if (display.isEmpty())
1508 fprintf(stderr,
"[tdeinit] Aborting. $" DISPLAY
" is not set.\n");
1512 if((i = display.findRev(
'.')) > display.findRev(
':') && i >= 0)
1513 display.truncate(i);
1515 TQCString socketName = TQFile::encodeName(locateLocal(
"socket", TQString(
"tdeinit-%1").arg(TQString(display)), s_instance));
1516 if (socketName.length() >= MAX_SOCK_FILE)
1518 fprintf(stderr,
"[tdeinit] Aborting. Socket name will be too long:\n");
1519 fprintf(stderr,
" '%s'\n", socketName.data());
1522 strcpy(sock_file_old, socketName.data());
1524 display.replace(
":",
"_");
1525 socketName = TQFile::encodeName(locateLocal(
"socket", TQString(
"tdeinit_%1").arg(TQString(display)), s_instance));
1526 if (socketName.length() >= MAX_SOCK_FILE)
1528 fprintf(stderr,
"[tdeinit] Aborting. Socket name will be too long:\n");
1529 fprintf(stderr,
" '%s'\n", socketName.data());
1532 strcpy(sock_file, socketName.data());
1535int tdeinit_xio_errhandler( Display *disp )
1540 tqWarning(
"[tdeinit] Fatal IO error: client killed" );
1547 if (sock_file_old[0])
1550 unlink(sock_file_old);
1557 kill(d.launcher_pid, SIGTERM);
1562 tqWarning(
"[tdeinit] sending SIGHUP to children." );
1565 signal(SIGHUP, SIG_IGN);
1571 tqWarning(
"[tdeinit] sending SIGTERM to children." );
1574 signal(SIGTERM, SIG_IGN);
1578 tqWarning(
"[tdeinit] Exit." );
1585int tdeinit_x_errhandler( Display *dpy, XErrorEvent *err )
1590 XGetErrorText( dpy, err->error_code, errstr, 256 );
1591 fprintf(stderr,
"[tdeinit] TDE detected X Error: %s %d\n"
1592 " Major opcode: %d\n"
1593 " Minor opcode: %d\n"
1594 " Resource id: 0x%lx\n",
1595 errstr, err->error_code, err->request_code, err->minor_code, err->resourceid );
1611 XSetIOErrorHandler(tdeinit_xio_errhandler);
1612 XSetErrorHandler(tdeinit_x_errhandler);
1616static int initXconnection()
1618 X11display = XOpenDisplay(NULL);
1619 if ( X11display != 0 ) {
1620 XCreateSimpleWindow(X11display, DefaultRootWindow(X11display), 0,0,1,1, \
1622 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)),
1623 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)) );
1625 fprintf(stderr,
"[tdeinit] Opened connection to %s\n", DisplayString(X11display));
1627 int fd = XConnectionNumber( X11display );
1629 (void) setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (
char *) &on, (int)
sizeof(on));
1632 fprintf(stderr,
"[tdeinit] Can't connect to the X Server.\n" \
1633 "[tdeinit] Might not terminate at end of session.\n");
1659extern "C" void _main(
void);
1660extern "C" void __call_ctors__Fv(
void);
1661static int main_called = 0;
1667 __call_ctors__Fv ();
1671static void secondary_child_handler(
int)
1673 waitpid(-1, 0, WNOHANG);
1676int main(
int argc,
char **argv,
char **envp)
1680 int launch_dcop = 1;
1681 int launch_tdelauncher = 1;
1682 int launch_kded = 1;
1683 int keep_running = 1;
1684 int new_startup = 0;
1688 char **safe_argv = (
char **) malloc(
sizeof(
char *) * argc);
1689 for(i = 0; i < argc; i++)
1691 safe_argv[i] = strcpy((
char*)malloc(strlen(argv[i])+1), argv[i]);
1692 if (strcmp(safe_argv[i],
"--no-dcop") == 0)
1694 if (strcmp(safe_argv[i],
"--no-tdelauncher") == 0)
1695 launch_tdelauncher = 0;
1696 if (strcmp(safe_argv[i],
"--no-kded") == 0)
1698 if (strcmp(safe_argv[i],
"--suicide") == 0)
1700 if (strcmp(safe_argv[i],
"--exit") == 0)
1702 if (strcmp(safe_argv[i],
"--new-startup") == 0)
1704#ifdef TDEINIT_OOM_PROTECT
1705 if (strcmp(safe_argv[i],
"--oom-pipe") == 0 && i+1<argc)
1706 oom_pipe = atol(argv[i+1]);
1708 if (strcmp(safe_argv[i],
"--help") == 0)
1710 printf(
"Usage: tdeinit [options]\n");
1713 printf(
" --no-kded Do not start kded\n");
1714 printf(
" --suicide Terminate when no TDE applications are left running\n");
1725 signal( SIGCHLD, secondary_child_handler);
1728 close(d.initpipe[1]);
1732 while( read(d.initpipe[0], &c, 1) < 0);
1734 close(d.initpipe[0]);
1738 close(d.initpipe[0]);
1740 d.my_pid = getpid();
1747 s_instance =
new TDEInstance(
"tdeinit");
1750 tdeinit_initsetproctitle(argc, argv, envp);
1751 tdeinit_library_path();
1755 TDEGlobal::_instance = 0L;
1757 unsetenv(
"LD_BIND_NOW");
1758 unsetenv(
"DYLD_BIND_AT_LAUNCH");
1759 TDEApplication::loadedByKdeinit =
true;
1761 d.maxname = strlen(argv[0]);
1765 d.debug_wait =
false;
1766 d.launcher_ok =
false;
1767 d.lt_dlopen_flag = lt_dlopen_flag;
1768 lt_dlopen_flag |= LTDL_GLOBAL;
1780 init_tdeinit_socket();
1786 pid = launch( 3,
"dcopserver",
"--nosid\0--suicide" );
1788 pid = launch( 2,
"dcopserver",
"--nosid" );
1790 fprintf(stderr,
"[tdeinit] Launched DCOPServer, pid = %ld result = %d\n", (
long) pid, d.result);
1793 if (!WIFEXITED(d.exit_status) || (WEXITSTATUS(d.exit_status) != 0))
1795 fprintf(stderr,
"[tdeinit] DCOPServer could not be started, aborting.\n");
1800 if (!d.suicide && !getenv(
"TDE_IS_PRELINKED"))
1802 TQString konq = locate(
"lib",
"libkonq.la", s_instance);
1803 if (!konq.isEmpty())
1804 (void) lt_dlopen(TQFile::encodeName(konq).data());
1807 if (launch_tdelauncher)
1810 pid = launch( 2,
"tdelauncher",
"--new-startup" );
1812 pid = launch( 1,
"tdelauncher", 0 );
1814 fprintf(stderr,
"[tdeinit] Launched TDELauncher, pid = %ld result = %d\n", (
long) pid, d.result);
1816 handle_requests(pid);
1819#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
1821 X11fd = initXconnection();
1825#if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
1826 if( FcGetVersion() < 20390 )
1832 TQFont::initialize();
1833 setlocale (LC_ALL,
"");
1834 setlocale (LC_NUMERIC,
"C");
1836 if (XSupportsLocale ())
1840 XOpenIM (X11display, 0, 0, 0);
1848 pid = launch( 2,
"kded",
"--new-startup" );
1850 pid = launch( 1,
"kded", 0 );
1852 fprintf(stderr,
"[tdeinit] Launched KDED, pid = %ld result = %d\n", (
long) pid, d.result);
1854 handle_requests(pid);
1857 for(i = 1; i < argc; i++)
1859 if (safe_argv[i][0] ==
'+')
1861 pid = launch( 1, safe_argv[i]+1, 0);
1863 fprintf(stderr,
"[tdeinit] Launched '%s', pid = %ld result = %d\n", safe_argv[i]+1, (
long) pid, d.result);
1865 handle_requests(pid);
1867 else if (safe_argv[i][0] ==
'-'
1868#ifdef TDEINIT_OOM_PROTECT
1869 || isdigit(safe_argv[i][0])
1877 pid = launch( 1, safe_argv[i], 0 );
1879 fprintf(stderr,
"[tdeinit] Launched '%s', pid = %ld result = %d\n", safe_argv[i], (
long) pid, d.result);
1885 for(i = 0; i < argc; i++)
1891 tdeinit_setproctitle(
"[tdeinit] tdeinit Running...");
1897 write(d.initpipe[1], &c, 1);
1898 close(d.initpipe[1]);