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>
62 #include <dcopglobal.h>
64 #ifdef HAVE_SYS_PRCTL_H
65 #include <sys/prctl.h>
67 #define PR_SET_NAME 15
71 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
72 #include <tdestartupinfo.h>
75 #include <tdeversion.h>
78 #include "tdelauncher_cmds.h"
84 #include <X11/Xatom.h>
92 # define LTDL_GLOBAL RTLD_GLOBAL
95 # define LTDL_GLOBAL DL_GLOBAL
97 # define LTDL_GLOBAL 0
101 #if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
102 #include <X11/Xft/Xft.h>
103 extern "C" FcBool XftInitFtLibrary (
void);
104 #include <fontconfig/fontconfig.h>
107 extern char **environ;
109 extern int lt_dlopen_flag;
112 static int X11fd = -1;
113 static Display *X11display = 0;
114 static int X11_startup_notify_fd = -1;
115 static Display *X11_startup_notify_display = 0;
117 static const TDEInstance *s_instance = 0;
118 #define MAX_SOCK_FILE 255
119 static char sock_file[MAX_SOCK_FILE];
120 static char sock_file_old[MAX_SOCK_FILE];
124 #define DISPLAY "DISPLAY"
125 #elif defined(TQ_WS_QWS)
126 #define DISPLAY "QWS_DISPLAY"
127 #elif defined(TQ_WS_MACX)
128 #define DISPLAY "MAC_DISPLAY"
129 #elif defined(K_WS_QTONLY)
130 #define DISPLAY "QT_DISPLAY"
132 #error Use QT/X11 or QT/Embedded
153 int (*func)(int,
char *[]);
154 int (*launcher_func)(int);
165 int tdeinit_xio_errhandler( Display * );
166 int tdeinit_x_errhandler( Display *, XErrorEvent *err );
171 #include <tdeparts/plugin.h>
172 extern "C" KParts::Plugin* _tdeinit_init_tdeparts() {
return new KParts::Plugin(); }
174 #include <tdeio/authinfo.h>
175 extern "C" TDEIO::AuthInfo* _tdeioslave_init_tdeio() {
return new TDEIO::AuthInfo(); }
181 static void close_fds()
183 if (d.deadpipe[0] != -1)
185 close(d.deadpipe[0]);
189 if (d.deadpipe[1] != -1)
191 close(d.deadpipe[1]);
195 if (d.initpipe[0] != -1)
197 close(d.initpipe[0]);
201 if (d.initpipe[1] != -1)
203 close(d.initpipe[1]);
209 close(d.launcher[0]);
219 close(d.wrapper_old);
222 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
229 if (X11_startup_notify_fd >= 0 && X11_startup_notify_fd != X11fd )
231 close(X11_startup_notify_fd);
232 X11_startup_notify_fd = -1;
236 signal(SIGCHLD, SIG_DFL);
237 signal(SIGPIPE, SIG_DFL);
240 static void exitWithErrorMsg(
const TQString &errorMsg)
242 fprintf( stderr,
"[tdeinit] %s\n", errorMsg.local8Bit().data() );
243 TQCString utf8ErrorMsg = errorMsg.utf8();
245 write(d.fd[1], &d.result, 1);
246 int l = utf8ErrorMsg.length();
247 write(d.fd[1], &l,
sizeof(
int));
248 write(d.fd[1], utf8ErrorMsg.data(), l);
253 static void setup_tty(
const char* tty )
255 if( tty == NULL || *tty ==
'\0' )
257 int fd = open( tty, O_WRONLY );
260 fprintf(stderr,
"[tdeinit] Couldn't open() %s: %s\n", tty, strerror (errno) );
263 if( dup2( fd, STDOUT_FILENO ) < 0 )
265 fprintf(stderr,
"[tdeinit] Couldn't dup2() %s: %s\n", tty, strerror (errno) );
269 if( dup2( fd, STDERR_FILENO ) < 0 )
271 fprintf(stderr,
"[tdeinit] Couldn't dup2() %s: %s\n", tty, strerror (errno) );
279 static int get_current_desktop( Display* disp )
282 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
284 Atom net_current_desktop = XInternAtom( disp,
"_NET_CURRENT_DESKTOP", False );
287 unsigned char *data_ret;
288 unsigned long nitems_ret, unused;
289 if( XGetWindowProperty( disp, DefaultRootWindow( disp ), net_current_desktop,
290 0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret )
293 if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1)
294 desktop = *((
long *) data_ret) + 1;
296 XFree ((
char*) data_ret);
303 const char* get_env_var(
const char* var,
int envc,
const char* envs )
307 const char* env_l = envs;
308 int ln = strlen( var );
309 for (
int i = 0; i < envc; i++)
311 if( strncmp( env_l, var, ln ) == 0 )
313 while(*env_l != 0) env_l++;
320 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
322 static void init_startup_info( TDEStartupInfoId&
id,
const char* bin,
323 int envc,
const char* envs )
325 const char* dpy = get_env_var( DISPLAY
"=", envc, envs );
328 X11_startup_notify_display = XOpenDisplay( dpy );
329 if( X11_startup_notify_display == NULL )
331 X11_startup_notify_fd = XConnectionNumber( X11_startup_notify_display );
332 TDEStartupInfoData data;
333 int desktop = get_current_desktop( X11_startup_notify_display );
334 data.setDesktop( desktop );
336 TDEStartupInfo::sendChangeX( X11_startup_notify_display,
id, data );
337 XFlush( X11_startup_notify_display );
340 static void complete_startup_info( TDEStartupInfoId&
id, pid_t pid )
342 if( X11_startup_notify_display == NULL )
345 TDEStartupInfo::sendFinishX( X11_startup_notify_display,
id );
348 TDEStartupInfoData data;
351 TDEStartupInfo::sendChangeX( X11_startup_notify_display,
id, data );
353 XCloseDisplay( X11_startup_notify_display );
354 X11_startup_notify_display = NULL;
355 X11_startup_notify_fd = -1;
359 TQCString execpath_avoid_loops(
const TQCString& exec,
int envc,
const char* envs,
bool avoid_loops )
364 const char* path = get_env_var(
"PATH=", envc, envs );
366 paths = TQStringList::split( TQRegExp(
"[:\b]" ), path,
true );
369 paths = TQStringList::split( TQRegExp(
"[:\b]" ), getenv(
"PATH" ),
true );
370 TQCString execpath = TQFile::encodeName(
371 s_instance->dirs()->findExe( exec, paths.join( TQString(
":" ))));
372 if( avoid_loops && !execpath.isEmpty())
374 int pos = execpath.findRev(
'/' );
375 TQString bin_path = execpath.left( pos );
376 for( TQStringList::Iterator it = paths.begin();
379 if( ( *it ) == bin_path || ( *it ) == bin_path +
'/' )
384 execpath = TQFile::encodeName(
385 s_instance->dirs()->findExe( exec, paths.join( TQString(
":" ))));
390 #ifdef TDEINIT_OOM_PROTECT
391 static int oom_pipe = -1;
393 static void oom_protect_sighandler(
int ) {
396 static void reset_oom_protect() {
399 struct sigaction act, oldact;
400 act.sa_handler = oom_protect_sighandler;
402 sigemptyset( &act.sa_mask );
403 sigaction( SIGUSR1, &act, &oldact );
404 sigset_t sigs, oldsigs;
405 sigemptyset( &sigs );
406 sigaddset( &sigs, SIGUSR1 );
407 sigprocmask( SIG_BLOCK, &sigs, &oldsigs );
408 pid_t pid = getpid();
409 if( write( oom_pipe, &pid,
sizeof( pid_t )) > 0 ) {
410 sigsuspend( &oldsigs );
412 sigprocmask( SIG_SETMASK, &oldsigs, NULL );
413 sigaction( SIGUSR1, &oldact, NULL );
418 static void reset_oom_protect() {
422 static pid_t launch(
int argc,
const char *_name,
const char *args,
423 const char *cwd=0,
int envc=0,
const char *envs=0,
424 bool reset_env =
false,
425 const char *tty=0,
bool avoid_loops =
false,
426 const char* startup_id_str =
"0" )
433 if (strcmp(_name,
"tdelauncher") == 0) {
437 if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, d.launcher))
439 perror(
"[tdeinit] socketpair() failed!\n");
453 libpath = TQFile::encodeName(KLibLoader::findLibrary( lib, s_instance ));
454 execpath = execpath_avoid_loops( exec, envc, envs, avoid_loops );
460 name = name.mid( name.findRev(
'/') + 1);
462 if (lib.right(3) ==
".la")
474 perror(
"[tdeinit] pipe() failed!\n");
476 d.errorMsg = i18n(
"Unable to start new process.\n"
477 "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();
484 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
486 TDEStartupInfoId startup_id;
487 startup_id.initId( startup_id_str );
488 if( !startup_id.none())
489 init_startup_info( startup_id, name, envc, envs );
496 perror(
"[tdeinit] fork() failed!\n");
498 d.errorMsg = i18n(
"Unable to create new process.\n"
499 "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();
510 if (d.fd[1] == LAUNCHER_FD)
512 d.fd[1] = dup(d.fd[1]);
514 if (d.launcher[1] != LAUNCHER_FD)
516 dup2( d.launcher[1], LAUNCHER_FD);
517 close( d.launcher[1] );
519 close( d.launcher[0] );
529 TQStrList unset_envs;
530 for(
int tmp_env_count = 0;
531 environ[tmp_env_count];
533 unset_envs.append( environ[ tmp_env_count ] );
534 for( TQStrListIterator it( unset_envs );
535 it.current() != NULL ;
538 TQCString tmp( it.current());
539 int pos = tmp.find(
'=' );
541 unsetenv( tmp.left( pos ));
545 for (
int i = 0; i < envc; i++)
547 putenv((
char *)envs);
548 while(*envs != 0) envs++;
552 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
554 if( startup_id.none())
555 TDEStartupInfo::resetStartupEnv();
557 startup_id.setupStartupEnv();
562 d.argv = (
char **) malloc(
sizeof(
char *) * (argc+1));
563 d.argv[0] = (
char *) _name;
564 for (
int i = 1; i < argc; i++)
566 d.argv[i] = (
char *) args;
568 procTitle += (
char *) args;
569 while(*args != 0) args++;
575 #ifdef HAVE_SYS_PRCTL_H
577 r = prctl(PR_SET_NAME, (
unsigned long) name.data(), 0, 0, 0);
579 tdeinit_setproctitle(
"%s [tdeinit]%s", name.data(), procTitle.data() ? procTitle.data() :
"" );
581 tdeinit_setproctitle(
"[tdeinit] %s%s", name.data(), procTitle.data() ? procTitle.data() :
"" );
583 tdeinit_setproctitle(
"[tdeinit] %s%s", name.data(), procTitle.data() ? procTitle.data() :
"" );
588 if (libpath.isEmpty() && execpath.isEmpty())
590 TQString errorMsg = i18n(
"Could not find '%1' executable.").arg(TQFile::decodeName(_name));
591 exitWithErrorMsg(errorMsg);
594 if ( getenv(
"TDE_IS_PRELINKED") && !execpath.isEmpty() && !launcher)
597 if ( !libpath.isEmpty() )
599 d.handle = lt_dlopen( TQFile::encodeName(libpath) );
602 const char * ltdlError = lt_dlerror();
603 if (execpath.isEmpty())
606 TQString errorMsg = i18n(
"Could not open library '%1'.\n%2").arg(TQFile::decodeName(libpath))
607 .arg(ltdlError ? TQFile::decodeName(ltdlError) : i18n(
"Unknown error"));
608 exitWithErrorMsg(errorMsg);
613 fprintf(stderr,
"Could not open library %s: %s\n", lib.data(), ltdlError != 0 ? ltdlError :
"(null)" );
617 lt_dlopen_flag = d.lt_dlopen_flag;
621 write(d.fd[1], &d.result, 1);
625 fcntl(d.fd[1], F_SETFD, FD_CLOEXEC);
629 execvp(execpath.data(), d.argv);
631 write(d.fd[1], &d.result, 1);
636 d.sym = lt_dlsym( d.handle,
"tdeinitmain");
639 d.sym = lt_dlsym( d.handle,
"kdemain" );
642 #if ! KDE_IS_VERSION( 3, 90, 0 )
643 d.sym = lt_dlsym( d.handle,
"main");
647 const char * ltdlError = lt_dlerror();
648 fprintf(stderr,
"Could not find kdemain: %s\n", ltdlError != 0 ? ltdlError :
"(null)" );
649 TQString errorMsg = i18n(
"Could not find 'kdemain' in '%1'.\n%2").arg(TQString(libpath))
650 .arg(ltdlError ? TQFile::decodeName(ltdlError) : i18n(
"Unknown error"));
651 exitWithErrorMsg(errorMsg);
657 write(d.fd[1], &d.result, 1);
660 d.func = (int (*)(int,
char *[])) d.sym;
663 fprintf(stderr,
"[tdeinit] Suspending process\n"
664 "[tdeinit] 'gdb tdeinit %d' to debug\n"
665 "[tdeinit] 'kill -SIGCONT %d' to continue\n",
667 kill(getpid(), SIGSTOP);
674 exit( d.func(argc, d.argv));
682 close(d.launcher[1]);
683 d.launcher_pid = d.fork;
688 d.n = read(d.fd[0], &d.result, 1);
694 fprintf(stderr,
"[tdeinit] %s is executable. Launching.\n", _name );
702 d.n = read(d.fd[0], &l,
sizeof(
int));
703 if (d.n ==
sizeof(
int))
707 d.n = read(d.fd[0], tmp.data(), l);
718 if (errno == ECHILD) {
721 if (errno == EINTR || errno == EAGAIN) {
732 perror(
"[tdeinit] Pipe closed unexpectedly");
736 perror(
"[tdeinit] Error reading from pipe");
741 if (launcher && (d.result == 0))
744 d.launcher_pid = d.fork;
747 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
749 if( !startup_id.none())
751 if( d.fork && d.result == 0 )
752 complete_startup_info( startup_id, d.fork );
754 complete_startup_info( startup_id, 0 );
760 static void sig_child_handler(
int)
771 write(d.deadpipe[1], &c, 1);
774 static void init_signals()
776 struct sigaction act;
779 if (pipe(d.deadpipe) != 0)
781 perror(
"[tdeinit] Aborting. Can't create pipe: ");
785 options = fcntl(d.deadpipe[0], F_GETFL);
788 perror(
"[tdeinit] Aborting. Can't make pipe non-blocking: ");
792 if (fcntl(d.deadpipe[0], F_SETFL, options | O_NONBLOCK) == -1)
794 perror(
"[tdeinit] Aborting. Can't make pipe non-blocking: ");
803 act.sa_handler=sig_child_handler;
804 sigemptyset(&(act.sa_mask));
805 sigaddset(&(act.sa_mask), SIGCHLD);
806 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
807 act.sa_flags = SA_NOCLDSTOP;
813 act.sa_flags |= SA_RESTART;
815 sigaction( SIGCHLD, &act, 0L);
817 act.sa_handler=SIG_IGN;
818 sigemptyset(&(act.sa_mask));
819 sigaddset(&(act.sa_mask), SIGPIPE);
820 sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
822 sigaction( SIGPIPE, &act, 0L);
825 static void init_tdeinit_socket()
827 struct sockaddr_un sa;
828 struct sockaddr_un sa_old;
829 kde_socklen_t socklen;
831 const char *home_dir = getenv(
"HOME");
833 if (!home_dir || !home_dir[0])
835 fprintf(stderr,
"[tdeinit] Aborting. $HOME not set!");
841 TQCString path = home_dir;
842 TQCString readOnly = getenv(
"TDE_HOME_READONLY");
843 if (access(path.data(), R_OK|W_OK))
847 fprintf(stderr,
"[tdeinit] Aborting. $HOME directory (%s) does not exist.\n", path.data());
850 else if (readOnly.isEmpty())
852 fprintf(stderr,
"[tdeinit] Aborting. No write access to $HOME directory (%s).\n", path.data());
856 path = IceAuthFileName();
857 if (access(path.data(), R_OK|W_OK) && (errno != ENOENT))
859 fprintf(stderr,
"[tdeinit] Aborting. No write access to '%s'.\n", path.data());
868 if (access(sock_file, W_OK) == 0)
871 struct sockaddr_un server;
877 s = socket(PF_UNIX, SOCK_STREAM, 0);
880 perror(
"socket() failed: ");
883 server.sun_family = AF_UNIX;
884 strcpy(server.sun_path, sock_file);
885 socklen =
sizeof(server);
887 if(connect(s, (
struct sockaddr *)&server, socklen) == 0)
889 fprintf(stderr,
"[tdeinit] Shutting down running client.\n");
890 tdelauncher_header request_header;
891 request_header.cmd = LAUNCHER_TERMINATE_TDEINIT;
892 request_header.arg_length = 0;
893 write(s, &request_header,
sizeof(request_header));
901 unlink(sock_file_old);
904 d.wrapper = socket(PF_UNIX, SOCK_STREAM, 0);
907 perror(
"[tdeinit] Aborting. socket() failed: ");
911 options = fcntl(d.wrapper, F_GETFL);
914 perror(
"[tdeinit] Aborting. Can't make socket non-blocking: ");
919 if (fcntl(d.wrapper, F_SETFL, options | O_NONBLOCK) == -1)
921 perror(
"[tdeinit] Aborting. Can't make socket non-blocking: ");
928 socklen =
sizeof(sa);
929 memset(&sa, 0, socklen);
930 sa.sun_family = AF_UNIX;
931 strcpy(sa.sun_path, sock_file);
932 if(bind(d.wrapper, (
struct sockaddr *)&sa, socklen) != 0)
934 if (max_tries == 0) {
935 perror(
"[tdeinit] Aborting. bind() failed: ");
936 fprintf(stderr,
"Could not bind to socket '%s'\n", sock_file);
946 if (chmod(sock_file, 0600) != 0)
948 perror(
"[tdeinit] Aborting. Can't set permissions on socket: ");
949 fprintf(stderr,
"Wrong permissions of socket '%s'\n", sock_file);
955 if(listen(d.wrapper, SOMAXCONN) < 0)
957 perror(
"[tdeinit] Aborting. listen() failed: ");
964 d.wrapper_old = socket(PF_UNIX, SOCK_STREAM, 0);
965 if (d.wrapper_old < 0)
971 options = fcntl(d.wrapper_old, F_GETFL);
975 close(d.wrapper_old);
980 if (fcntl(d.wrapper_old, F_SETFL, options | O_NONBLOCK) == -1)
983 close(d.wrapper_old);
991 socklen =
sizeof(sa_old);
992 memset(&sa_old, 0, socklen);
993 sa_old.sun_family = AF_UNIX;
994 strcpy(sa_old.sun_path, sock_file_old);
995 if(bind(d.wrapper_old, (
struct sockaddr *)&sa_old, socklen) != 0)
997 if (max_tries == 0) {
999 fprintf(stderr,
"Could not bind to socket '%s'\n", sock_file_old);
1000 close(d.wrapper_old);
1010 if (chmod(sock_file_old, 0600) != 0)
1012 fprintf(stderr,
"Wrong permissions of socket '%s'\n", sock_file);
1013 unlink(sock_file_old);
1014 close(d.wrapper_old);
1019 if(listen(d.wrapper_old, SOMAXCONN) < 0)
1022 unlink(sock_file_old);
1023 close(d.wrapper_old);
1032 static int read_socket(
int sock,
char *buffer,
int len)
1035 int bytes_left = len;
1036 while ( bytes_left > 0)
1038 result = read(sock, buffer, bytes_left);
1042 bytes_left -= result;
1044 else if (result == 0)
1046 else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
1052 static void WaitPid( pid_t waitForPid)
1057 result = waitpid(waitForPid, &d.exit_status, 0);
1058 if ((result == -1) && (errno == ECHILD))
1063 static void launcher_died()
1068 fprintf(stderr,
"[tdeinit] Communication error with launcher. Exiting!\n");
1075 fprintf(stderr,
"[tdeinit] TDELauncher died unexpectedly.\n");
1080 kill(d.launcher_pid, SIGKILL);
1084 d.launcher_ok =
false;
1086 close(d.launcher[0]);
1089 pid_t pid = launch( 1,
"tdelauncher", 0 );
1091 fprintf(stderr,
"[tdeinit] Relaunching TDELauncher, pid = %ld result = %d\n", (
long) pid, d.result);
1095 static void handle_launcher_request(
int sock = -1)
1097 bool launcher =
false;
1100 sock = d.launcher[0];
1104 tdelauncher_header request_header;
1105 char *request_data = 0L;
1106 int result = read_socket(sock, (
char *) &request_header,
sizeof(request_header));
1114 if ( request_header.arg_length != 0 )
1116 request_data = (
char *) malloc(request_header.arg_length);
1118 result = read_socket(sock, request_data, request_header.arg_length);
1128 if (request_header.cmd == LAUNCHER_OK)
1130 d.launcher_ok =
true;
1132 else if (request_header.arg_length &&
1133 ((request_header.cmd == LAUNCHER_EXEC) ||
1134 (request_header.cmd == LAUNCHER_EXT_EXEC) ||
1135 (request_header.cmd == LAUNCHER_SHELL ) ||
1136 (request_header.cmd == LAUNCHER_KWRAPPER) ||
1137 (request_header.cmd == LAUNCHER_EXEC_NEW)))
1140 tdelauncher_header response_header;
1143 memcpy( &l, request_data,
sizeof(
long ));
1145 const char *name = request_data +
sizeof(long);
1146 const char *args = name + strlen(name) + 1;
1147 const char *cwd = 0;
1149 const char *envs = 0;
1150 const char *tty = 0;
1151 int avoid_loops = 0;
1152 const char *startup_id_str =
"0";
1155 fprintf(stderr,
"[tdeinit] Got %s '%s' from %s.\n",
1156 (request_header.cmd == LAUNCHER_EXEC ?
"EXEC" :
1157 (request_header.cmd == LAUNCHER_EXT_EXEC ?
"EXT_EXEC" :
1158 (request_header.cmd == LAUNCHER_EXEC_NEW ?
"EXEC_NEW" :
1159 (request_header.cmd == LAUNCHER_SHELL ?
"SHELL" :
"KWRAPPER" )))),
1160 name, launcher ?
"launcher" :
"socket" );
1163 const char *arg_n = args;
1164 for(
int i = 1; i < argc; i++)
1166 arg_n = arg_n + strlen(arg_n) + 1;
1169 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER )
1172 cwd = arg_n; arg_n += strlen(cwd) + 1;
1174 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
1175 || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
1177 memcpy( &l, arg_n,
sizeof(
long ));
1179 arg_n +=
sizeof(long);
1181 for(
int i = 0; i < envc; i++)
1183 arg_n = arg_n + strlen(arg_n) + 1;
1185 if( request_header.cmd == LAUNCHER_KWRAPPER )
1188 arg_n += strlen( tty ) + 1;
1192 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
1193 || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
1195 memcpy( &l, arg_n,
sizeof(
long ));
1197 arg_n +=
sizeof( long );
1200 if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
1201 || request_header.cmd == LAUNCHER_EXT_EXEC )
1203 startup_id_str = arg_n;
1204 arg_n += strlen( startup_id_str ) + 1;
1207 if ((request_header.arg_length > (arg_n - request_data)) &&
1208 (request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW ))
1211 cwd = arg_n; arg_n += strlen(cwd) + 1;
1214 if ((arg_n - request_data) != request_header.arg_length)
1217 fprintf(stderr,
"[tdeinit] EXEC request has invalid format.\n");
1220 d.debug_wait =
false;
1225 TQCString olddisplay = getenv(DISPLAY);
1226 TQCString kdedisplay = getenv(
"TDE_DISPLAY");
1227 bool reset_display = (! olddisplay.isEmpty() &&
1228 ! kdedisplay.isEmpty() &&
1229 olddisplay != kdedisplay);
1232 setenv(DISPLAY, kdedisplay,
true);
1234 pid = launch( argc, name, args, cwd, envc, envs,
1235 request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER,
1236 tty, avoid_loops, startup_id_str );
1238 if (reset_display) {
1239 unsetenv(
"TDE_DISPLAY");
1240 setenv(DISPLAY, olddisplay,
true);
1243 if (pid && (d.result == 0))
1245 response_header.cmd = LAUNCHER_OK;
1246 response_header.arg_length =
sizeof(response_data);
1247 response_data = pid;
1248 write(sock, &response_header,
sizeof(response_header));
1249 write(sock, &response_data, response_header.arg_length);
1253 int l = d.errorMsg.length();
1255 response_header.cmd = LAUNCHER_ERROR;
1256 response_header.arg_length = l;
1257 write(sock, &response_header,
sizeof(response_header));
1259 write(sock, d.errorMsg.data(), l);
1261 d.debug_wait =
false;
1263 else if (request_header.arg_length && request_header.cmd == LAUNCHER_SETENV)
1265 const char *env_name;
1266 const char *env_value;
1267 env_name = request_data;
1268 env_value = env_name + strlen(env_name) + 1;
1272 fprintf(stderr,
"[tdeinit] Got SETENV '%s=%s' from tdelauncher.\n", env_name, env_value);
1274 fprintf(stderr,
"[tdeinit] Got SETENV '%s=%s' from socket.\n", env_name, env_value);
1277 if ( request_header.arg_length !=
1278 (
int) (strlen(env_name) + strlen(env_value) + 2))
1281 fprintf(stderr,
"[tdeinit] SETENV request has invalid format.\n");
1286 setenv( env_name, env_value, 1);
1288 else if (request_header.cmd == LAUNCHER_TERMINATE_KDE)
1291 fprintf(stderr,
"[tdeinit] Terminating Trinity.\n");
1294 tdeinit_xio_errhandler( 0L );
1297 else if (request_header.cmd == LAUNCHER_TERMINATE_TDEINIT)
1300 fprintf(stderr,
"[tdeinit] Killing tdeinit/tdelauncher.\n");
1303 kill(d.launcher_pid, SIGTERM);
1305 kill(d.my_pid, SIGTERM);
1307 else if (request_header.cmd == LAUNCHER_DEBUG_WAIT)
1310 fprintf(stderr,
"[tdeinit] Debug wait activated.\n");
1312 d.debug_wait =
true;
1318 static void handle_requests(pid_t waitForPid)
1320 int max_sock = d.wrapper;
1321 if (d.wrapper_old > max_sock)
1322 max_sock = d.wrapper_old;
1323 if (d.launcher_pid && (d.launcher[0] > max_sock))
1324 max_sock = d.launcher[0];
1325 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
1327 if (X11fd > max_sock)
1342 while( read(d.deadpipe[0], &c, 1) == 1);
1346 exit_pid = waitpid(-1, 0, WNOHANG);
1353 if (waitForPid && (exit_pid == waitForPid))
1359 tdelauncher_header request_header;
1360 long request_data[2];
1361 request_header.cmd = LAUNCHER_DIED;
1362 request_header.arg_length =
sizeof(long) * 2;
1363 request_data[0] = exit_pid;
1364 request_data[1] = 0;
1365 write(d.launcher[0], &request_header,
sizeof(request_header));
1366 write(d.launcher[0], request_data, request_header.arg_length);
1370 while( exit_pid > 0);
1378 FD_SET(d.launcher[0], &rd_set);
1380 FD_SET(d.wrapper, &rd_set);
1383 FD_SET(d.wrapper_old, &rd_set);
1385 FD_SET(d.deadpipe[0], &rd_set);
1386 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
1388 if(X11fd >= 0) FD_SET(X11fd, &rd_set);
1391 result = select(max_sock, &rd_set, &wr_set, &e_set, 0);
1394 if ((result > 0) && (FD_ISSET(d.wrapper, &rd_set)))
1396 struct sockaddr_un client;
1397 kde_socklen_t sClient =
sizeof(client);
1398 int sock = accept(d.wrapper, (
struct sockaddr *)&client, &sClient);
1401 #if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
1402 if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
1403 FcInitReinitialize();
1408 reset_oom_protect();
1409 handle_launcher_request(sock);
1415 if ((result > 0) && (FD_ISSET(d.wrapper_old, &rd_set)))
1417 struct sockaddr_un client;
1418 kde_socklen_t sClient =
sizeof(client);
1419 int sock = accept(d.wrapper_old, (
struct sockaddr *)&client, &sClient);
1422 #if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
1423 if( FcGetVersion() < 20390 && !FcConfigUptoDate(NULL))
1424 FcInitReinitialize();
1429 reset_oom_protect();
1430 handle_launcher_request(sock);
1438 if ((result > 0) && (d.launcher_pid) && (FD_ISSET(d.launcher[0], &rd_set)))
1440 handle_launcher_request();
1441 if (waitForPid == d.launcher_pid)
1448 if((result > 0) && (X11fd >= 0))
1450 if(FD_ISSET(X11fd,&rd_set))
1452 if (X11display != 0) {
1453 XEvent event_return;
1454 while (XPending(X11display))
1455 XNextEvent(X11display, &event_return);
1463 static void tdeinit_library_path()
1465 TQStringList ltdl_library_path =
1466 TQStringList::split(
':', TQFile::decodeName(getenv(
"LTDL_LIBRARY_PATH")));
1467 TQStringList ld_library_path =
1468 TQStringList::split(
':', TQFile::decodeName(getenv(
"LD_LIBRARY_PATH")));
1470 TQCString extra_path;
1471 TQStringList candidates = s_instance->dirs()->resourceDirs(
"lib");
1472 for (TQStringList::ConstIterator it = candidates.begin();
1473 it != candidates.end();
1477 if (ltdl_library_path.contains(d))
1479 if (ld_library_path.contains(d))
1481 if (d[d.length()-1] ==
'/')
1483 d.truncate(d.length()-1);
1484 if (ltdl_library_path.contains(d))
1486 if (ld_library_path.contains(d))
1489 if ((d ==
"/lib") || (d ==
"/usr/lib"))
1492 TQCString dir = TQFile::encodeName(d);
1494 if (access(dir, R_OK))
1497 if ( !extra_path.isEmpty())
1504 const char * ltdlError = lt_dlerror();
1505 fprintf(stderr,
"[tdeinit] Can't initialize dynamic loading: %s\n", ltdlError != 0 ? ltdlError :
"(null)" );
1507 if (!extra_path.isEmpty())
1508 lt_dlsetsearchpath(extra_path.data());
1510 TQCString display = getenv(DISPLAY);
1511 if (display.isEmpty())
1513 fprintf(stderr,
"[tdeinit] Aborting. $" DISPLAY
" is not set.\n");
1517 if((i = display.findRev(
'.')) > display.findRev(
':') && i >= 0)
1518 display.truncate(i);
1520 TQCString socketName = TQFile::encodeName(locateLocal(
"socket", TQString(
"tdeinit-%1").arg(TQString(display)), s_instance));
1521 if (socketName.length() >= MAX_SOCK_FILE)
1523 fprintf(stderr,
"[tdeinit] Aborting. Socket name will be too long:\n");
1524 fprintf(stderr,
" '%s'\n", socketName.data());
1527 strcpy(sock_file_old, socketName.data());
1529 display.replace(
":",
"_");
1530 socketName = TQFile::encodeName(locateLocal(
"socket", TQString(
"tdeinit_%1").arg(TQString(display)), s_instance));
1531 if (socketName.length() >= MAX_SOCK_FILE)
1533 fprintf(stderr,
"[tdeinit] Aborting. Socket name will be too long:\n");
1534 fprintf(stderr,
" '%s'\n", socketName.data());
1537 strcpy(sock_file, socketName.data());
1540 int tdeinit_xio_errhandler( Display *disp )
1545 tqWarning(
"[tdeinit] Fatal IO error: client killed" );
1552 if (sock_file_old[0])
1555 unlink(sock_file_old);
1562 kill(d.launcher_pid, SIGTERM);
1567 tqWarning(
"[tdeinit] sending SIGHUP to children." );
1570 signal(SIGHUP, SIG_IGN);
1576 tqWarning(
"[tdeinit] sending SIGTERM to children." );
1579 signal(SIGTERM, SIG_IGN);
1583 tqWarning(
"[tdeinit] Exit." );
1590 int tdeinit_x_errhandler( Display *dpy, XErrorEvent *err )
1595 XGetErrorText( dpy, err->error_code, errstr, 256 );
1596 fprintf(stderr,
"[tdeinit] TDE detected X Error: %s %d\n"
1597 " Major opcode: %d\n"
1598 " Minor opcode: %d\n"
1599 " Resource id: 0x%lx\n",
1600 errstr, err->error_code, err->request_code, err->minor_code, err->resourceid );
1613 static void setupX()
1616 XSetIOErrorHandler(tdeinit_xio_errhandler);
1617 XSetErrorHandler(tdeinit_x_errhandler);
1621 static int initXconnection()
1623 X11display = XOpenDisplay(NULL);
1624 if ( X11display != 0 ) {
1625 XCreateSimpleWindow(X11display, DefaultRootWindow(X11display), 0,0,1,1, \
1627 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)),
1628 BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)) );
1630 fprintf(stderr,
"[tdeinit] Opened connection to %s\n", DisplayString(X11display));
1632 int fd = XConnectionNumber( X11display );
1634 (void) setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (
char *) &on, (int)
sizeof(on));
1637 fprintf(stderr,
"[tdeinit] Can't connect to the X Server.\n" \
1638 "[tdeinit] Might not terminate at end of session.\n");
1664 extern "C" void _main(
void);
1665 extern "C" void __call_ctors__Fv(
void);
1666 static int main_called = 0;
1672 __call_ctors__Fv ();
1676 static void secondary_child_handler(
int)
1678 waitpid(-1, 0, WNOHANG);
1681 int main(
int argc,
char **argv,
char **envp)
1685 int launch_dcop = 1;
1686 int launch_tdelauncher = 1;
1687 int launch_kded = 1;
1688 int keep_running = 1;
1689 int new_startup = 0;
1693 char **safe_argv = (
char **) malloc(
sizeof(
char *) * argc);
1694 for(i = 0; i < argc; i++)
1696 safe_argv[i] = strcpy((
char*)malloc(strlen(argv[i])+1), argv[i]);
1697 if (strcmp(safe_argv[i],
"--no-dcop") == 0)
1699 if (strcmp(safe_argv[i],
"--no-tdelauncher") == 0)
1700 launch_tdelauncher = 0;
1701 if (strcmp(safe_argv[i],
"--no-kded") == 0)
1703 if (strcmp(safe_argv[i],
"--suicide") == 0)
1705 if (strcmp(safe_argv[i],
"--exit") == 0)
1707 if (strcmp(safe_argv[i],
"--new-startup") == 0)
1709 #ifdef TDEINIT_OOM_PROTECT
1710 if (strcmp(safe_argv[i],
"--oom-pipe") == 0 && i+1<argc)
1711 oom_pipe = atol(argv[i+1]);
1713 if (strcmp(safe_argv[i],
"--help") == 0)
1715 printf(
"Usage: tdeinit [options]\n");
1718 printf(
" --no-kded Do not start kded\n");
1719 printf(
" --suicide Terminate when no TDE applications are left running\n");
1730 signal( SIGCHLD, secondary_child_handler);
1733 close(d.initpipe[1]);
1737 while( read(d.initpipe[0], &c, 1) < 0);
1739 close(d.initpipe[0]);
1743 close(d.initpipe[0]);
1745 d.my_pid = getpid();
1752 s_instance =
new TDEInstance(
"tdeinit");
1755 tdeinit_initsetproctitle(argc, argv, envp);
1756 tdeinit_library_path();
1760 TDEGlobal::_instance = 0L;
1762 unsetenv(
"LD_BIND_NOW");
1763 unsetenv(
"DYLD_BIND_AT_LAUNCH");
1764 TDEApplication::loadedByKdeinit =
true;
1766 d.maxname = strlen(argv[0]);
1770 d.debug_wait =
false;
1771 d.launcher_ok =
false;
1772 d.lt_dlopen_flag = lt_dlopen_flag;
1773 lt_dlopen_flag |= LTDL_GLOBAL;
1785 init_tdeinit_socket();
1791 pid = launch( 3,
"dcopserver",
"--nosid\0--suicide" );
1793 pid = launch( 2,
"dcopserver",
"--nosid" );
1795 fprintf(stderr,
"[tdeinit] Launched DCOPServer, pid = %ld result = %d\n", (
long) pid, d.result);
1798 if (!WIFEXITED(d.exit_status) || (WEXITSTATUS(d.exit_status) != 0))
1800 fprintf(stderr,
"[tdeinit] DCOPServer could not be started, aborting.\n");
1805 if (!d.suicide && !getenv(
"TDE_IS_PRELINKED"))
1807 TQString konq = locate(
"lib",
"libkonq.la", s_instance);
1808 if (!konq.isEmpty())
1809 (void) lt_dlopen(TQFile::encodeName(konq).data());
1812 if (launch_tdelauncher)
1815 pid = launch( 2,
"tdelauncher",
"--new-startup" );
1817 pid = launch( 1,
"tdelauncher", 0 );
1819 fprintf(stderr,
"[tdeinit] Launched TDELauncher, pid = %ld result = %d\n", (
long) pid, d.result);
1821 handle_requests(pid);
1824 #if defined TQ_WS_X11 && ! defined K_WS_QTONLY
1826 X11fd = initXconnection();
1830 #if defined(TDEINIT_USE_XFT) && defined(TDEINIT_USE_FONTCONFIG)
1831 if( FcGetVersion() < 20390 )
1837 TQFont::initialize();
1838 setlocale (LC_ALL,
"");
1839 setlocale (LC_NUMERIC,
"C");
1841 if (XSupportsLocale ())
1845 XOpenIM (X11display, 0, 0, 0);
1853 pid = launch( 2,
"kded",
"--new-startup" );
1855 pid = launch( 1,
"kded", 0 );
1857 fprintf(stderr,
"[tdeinit] Launched KDED, pid = %ld result = %d\n", (
long) pid, d.result);
1859 handle_requests(pid);
1862 for(i = 1; i < argc; i++)
1864 if (safe_argv[i][0] ==
'+')
1866 pid = launch( 1, safe_argv[i]+1, 0);
1868 fprintf(stderr,
"[tdeinit] Launched '%s', pid = %ld result = %d\n", safe_argv[i]+1, (
long) pid, d.result);
1870 handle_requests(pid);
1872 else if (safe_argv[i][0] ==
'-'
1873 #ifdef TDEINIT_OOM_PROTECT
1874 || isdigit(safe_argv[i][0])
1882 pid = launch( 1, safe_argv[i], 0 );
1884 fprintf(stderr,
"[tdeinit] Launched '%s', pid = %ld result = %d\n", safe_argv[i], (
long) pid, d.result);
1890 for(i = 0; i < argc; i++)
1896 tdeinit_setproctitle(
"[tdeinit] tdeinit Running...");
1902 write(d.initpipe[1], &c, 1);
1903 close(d.initpipe[1]);