• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KInit

  • sources
  • kde-4.14
  • kdelibs
  • kinit
kinit.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the KDE libraries
3  * Copyright (c) 1999-2000 Waldo Bastian <bastian@kde.org>
4  * (c) 1999 Mario Weilguni <mweilguni@sime.com>
5  * (c) 2001 Lubos Lunak <l.lunak@kde.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License version 2 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #define QT_NO_CAST_FROM_ASCII
23 
24 #include <config.h>
25 #include <config-kdeinit.h>
26 
27 #include <sys/types.h>
28 #include <sys/time.h>
29 #include <sys/resource.h>
30 #include <sys/stat.h>
31 #include <sys/socket.h>
32 #include <sys/un.h>
33 #include <sys/wait.h>
34 #ifdef HAVE_SYS_SELECT_H
35 #include <sys/select.h> // Needed on some systems.
36 #endif
37 
38 #include <ctype.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include "proctitle.h"
42 #include <signal.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <locale.h>
48 
49 #include <QtCore/QLibrary>
50 #include <QtCore/QString>
51 #include <QtCore/QFile>
52 #include <QtCore/QDate>
53 #include <QtCore/QFileInfo>
54 #include <QtCore/QRegExp>
55 #include <QtGui/QFont>
56 #include <kcomponentdata.h>
57 #include <klibrary.h>
58 #include <kdemacros.h>
59 #include <kstandarddirs.h>
60 #include <kglobal.h>
61 #include <kconfig.h>
62 #include <kapplication.h>
63 #include <klocale.h>
64 #include <kdebug.h>
65 #include <kde_file.h>
66 #include <ksavefile.h>
67 
68 #ifdef Q_OS_LINUX
69 #include <sys/prctl.h>
70 #ifndef PR_SET_NAME
71 #define PR_SET_NAME 15
72 #endif
73 #endif
74 
75 #ifdef Q_WS_MACX
76 #include <kkernel_mac.h>
77 #endif
78 
79 #include <kdeversion.h>
80 
81 #include "klauncher_cmds.h"
82 
83 #ifdef Q_WS_X11
84 #include <X11/Xlib.h>
85 #include <X11/Xatom.h>
86 #include <fixx11h.h>
87 #include <kstartupinfo.h>
88 #endif
89 
90 #ifdef Q_WS_X11
91 static const char *extra_libs[] = {
92  "libkio.so.5",
93  "libkparts.so.4",
94 #ifdef __KDE_HAVE_GCC_VISIBILITY
95  "libplasma.so.3"
96 #endif
97 };
98 #endif
99 
100 // #define SKIP_PROCTITLE 1
101 
102 extern char **environ;
103 
104 #ifdef Q_WS_X11
105 static int X11fd = -1;
106 static Display *X11display = 0;
107 static int X11_startup_notify_fd = -1;
108 static Display *X11_startup_notify_display = 0;
109 #endif
110 static KComponentData *s_instance = 0;
111 #define MAX_SOCK_FILE 255
112 static char sock_file[MAX_SOCK_FILE];
113 
114 #ifdef Q_WS_X11
115 #define DISPLAY "DISPLAY"
116 #elif defined(Q_WS_QWS)
117 #define DISPLAY "QWS_DISPLAY"
118 #elif defined(Q_WS_MACX)
119 #define DISPLAY "MAC_DISPLAY"
120 #elif defined(Q_WS_WIN)
121 #define DISPLAY "WIN_DISPLAY"
122 #else
123 #error Use QT/X11 or QT/Embedded
124 #endif
125 
126 /* Group data */
127 static struct {
128  int maxname;
129  int fd[2];
130  int launcher[2]; /* socket pair for launcher communication */
131  int deadpipe[2]; /* pipe used to detect dead children */
132  int initpipe[2];
133  int wrapper; /* socket for wrapper communication */
134  int accepted_fd; /* socket accepted and that must be closed in the child process */
135  char result;
136  int exit_status;
137  pid_t fork;
138  pid_t launcher_pid;
139  pid_t kded_pid;
140  int n;
141  char **argv;
142  int (*func)(int, char *[]);
143  int (*launcher_func)(int);
144  bool debug_wait;
145  QByteArray errorMsg;
146  bool launcher_ok;
147  bool suicide;
148 } d;
149 
150 struct child
151 {
152  pid_t pid;
153  int sock; /* fd to write message when child is dead*/
154  struct child *next;
155 };
156 
157 static struct child *children;
158 
159 #ifdef Q_WS_X11
160 extern "C" {
161 int kdeinit_xio_errhandler( Display * );
162 int kdeinit_x_errhandler( Display *, XErrorEvent *err );
163 }
164 #endif
165 
166 #ifdef KDEINIT_OOM_PROTECT
167 static int oom_pipe = -1;
168 #endif
169 
170 /*
171  * Clean up the file descriptor table by closing all file descriptors
172  * that are still open.
173  *
174  * This function is called very early in the main() function, so that
175  * we don't leak anything that was leaked to us.
176  */
177 static void cleanup_fds()
178 {
179  int maxfd = FD_SETSIZE;
180  struct rlimit rl;
181  if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
182  maxfd = rl.rlim_max;
183  for (int fd = 3; fd < maxfd; ++fd)
184  {
185 #ifdef KDEINIT_OOM_PROTECT
186  if( fd != oom_pipe )
187 #endif
188  close(fd);
189  }
190 }
191 
192 /*
193  * Close fd's which are only useful for the parent process.
194  * Restore default signal handlers.
195  */
196 static void close_fds()
197 {
198  while (struct child *child = children) {
199  close(child->sock);
200  children = child->next;
201  free(child);
202  }
203 
204  if (d.deadpipe[0] != -1)
205  {
206  close(d.deadpipe[0]);
207  d.deadpipe[0] = -1;
208  }
209 
210  if (d.deadpipe[1] != -1)
211  {
212  close(d.deadpipe[1]);
213  d.deadpipe[1] = -1;
214  }
215 
216  if (d.initpipe[0] != -1)
217  {
218  close(d.initpipe[0]);
219  d.initpipe[0] = -1;
220  }
221 
222  if (d.initpipe[1] != -1)
223  {
224  close(d.initpipe[1]);
225  d.initpipe[1] = -1;
226  }
227 
228  if (d.launcher[0] != -1)
229  {
230  close(d.launcher[0]);
231  d.launcher[0] = -1;
232  }
233  if (d.wrapper != -1)
234  {
235  close(d.wrapper);
236  d.wrapper = -1;
237  }
238  if (d.accepted_fd != -1)
239  {
240  close(d.accepted_fd);
241  d.accepted_fd = -1;
242  }
243 #ifdef Q_WS_X11
244  if (X11fd >= 0)
245  {
246  close(X11fd);
247  X11fd = -1;
248  }
249  if (X11_startup_notify_fd >= 0 && X11_startup_notify_fd != X11fd )
250  {
251  close(X11_startup_notify_fd);
252  X11_startup_notify_fd = -1;
253  }
254 #endif
255 
256  KDE_signal(SIGCHLD, SIG_DFL);
257  KDE_signal(SIGPIPE, SIG_DFL);
258 }
259 
260 /* Notify wrapper program that the child it started has finished. */
261 static void child_died(pid_t exit_pid, int exit_status)
262 {
263  struct child *child, **childptr = &children;
264 
265  while ((child = *childptr))
266  {
267  if (child->pid == exit_pid)
268  {
269  /* Send a message with the return value of the child on the control socket */
270  klauncher_header request_header;
271  long request_data[2];
272  request_header.cmd = LAUNCHER_CHILD_DIED;
273  request_header.arg_length = sizeof(long) * 2;
274  request_data[0] = exit_pid;
275  request_data[1] = exit_status;
276  write(child->sock, &request_header, sizeof(request_header));
277  write(child->sock, request_data, request_header.arg_length);
278  close(child->sock);
279 
280  *childptr = child->next;
281  free(child);
282  return;
283  }
284 
285  childptr = &child->next;
286  }
287 }
288 
289 
290 static void exitWithErrorMsg(const QString &errorMsg)
291 {
292  fprintf( stderr, "%s\n", errorMsg.toLocal8Bit().data() );
293  QByteArray utf8ErrorMsg = errorMsg.toUtf8();
294  d.result = 3; // Error with msg
295  write(d.fd[1], &d.result, 1);
296  int l = utf8ErrorMsg.length();
297  write(d.fd[1], &l, sizeof(int));
298  write(d.fd[1], utf8ErrorMsg.data(), l);
299  close(d.fd[1]);
300  exit(255);
301 }
302 
303 static void setup_tty( const char* tty )
304 {
305  if( tty == NULL || *tty == '\0' )
306  return;
307  int fd = KDE_open( tty, O_WRONLY );
308  if( fd < 0 )
309  {
310  perror( "kdeinit4: could not open() tty" );
311  return;
312  }
313  if( dup2( fd, STDOUT_FILENO ) < 0 )
314  {
315  perror( "kdeinit4: could not dup2() stdout tty" );
316  }
317  if( dup2( fd, STDERR_FILENO ) < 0 )
318  {
319  perror( "kdeinit4: could not dup2() stderr tty" );
320  }
321  close( fd );
322 }
323 
324 // from kdecore/netwm.cpp
325 static int get_current_desktop( Display* disp )
326 {
327  int desktop = 0; // no desktop by default
328 #ifdef Q_WS_X11 // Only X11 supports multiple desktops
329  Atom net_current_desktop = XInternAtom( disp, "_NET_CURRENT_DESKTOP", False );
330  Atom type_ret;
331  int format_ret;
332  unsigned char *data_ret;
333  unsigned long nitems_ret, unused;
334  if( XGetWindowProperty( disp, DefaultRootWindow( disp ), net_current_desktop,
335  0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret )
336  == Success)
337  {
338  if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1)
339  desktop = *((long *) data_ret) + 1;
340  if (data_ret)
341  XFree ((char*) data_ret);
342  }
343 #endif
344  return desktop;
345 }
346 
347 // var has to be e.g. "DISPLAY=", i.e. with =
348 const char* get_env_var( const char* var, int envc, const char* envs )
349 {
350  if( envc > 0 )
351  { // get the var from envs
352  const char* env_l = envs;
353  int ln = strlen( var );
354  for (int i = 0; i < envc; i++)
355  {
356  if( strncmp( env_l, var, ln ) == 0 )
357  return env_l + ln;
358  while(*env_l != 0) env_l++;
359  env_l++;
360  }
361  }
362  return NULL;
363 }
364 
365 #ifdef Q_WS_X11
366 static void init_startup_info( KStartupInfoId& id, const char* bin,
367  int envc, const char* envs )
368 {
369  const char* dpy = get_env_var( DISPLAY"=", envc, envs );
370  // this may be called in a child, so it can't use display open using X11display
371  // also needed for multihead
372  X11_startup_notify_display = XOpenDisplay( dpy );
373  if( X11_startup_notify_display == NULL )
374  return;
375  X11_startup_notify_fd = XConnectionNumber( X11_startup_notify_display );
376  KStartupInfoData data;
377  int desktop = get_current_desktop( X11_startup_notify_display );
378  data.setDesktop( desktop );
379  data.setBin(QFile::decodeName(bin));
380  KStartupInfo::sendChangeX( X11_startup_notify_display, id, data );
381  XFlush( X11_startup_notify_display );
382 }
383 
384 static void complete_startup_info( KStartupInfoId& id, pid_t pid )
385 {
386  if( X11_startup_notify_display == NULL )
387  return;
388  if( pid == 0 ) // failure
389  KStartupInfo::sendFinishX( X11_startup_notify_display, id );
390  else
391  {
392  KStartupInfoData data;
393  data.addPid( pid );
394  data.setHostname();
395  KStartupInfo::sendChangeX( X11_startup_notify_display, id, data );
396  }
397  XCloseDisplay( X11_startup_notify_display );
398  X11_startup_notify_display = NULL;
399  X11_startup_notify_fd = -1;
400 }
401 #endif
402 
403 QByteArray execpath_avoid_loops( const QByteArray& exec, int envc, const char* envs, bool avoid_loops )
404 {
405  QStringList paths;
406  const QRegExp pathSepRegExp(QString::fromLatin1("[:\b]"));
407  if( envc > 0 ) /* use the passed environment */
408  {
409  const char* path = get_env_var( "PATH=", envc, envs );
410  if( path != NULL )
411  paths = QFile::decodeName(path).split(pathSepRegExp);
412  } else {
413  paths = QString::fromLocal8Bit(qgetenv("PATH")).split(pathSepRegExp, QString::KeepEmptyParts);
414  }
415  QString execpath =
416  s_instance->dirs()->findExe(QFile::decodeName(exec), paths.join(QLatin1String(":")));
417  if (avoid_loops && !execpath.isEmpty()) {
418  const int pos = execpath.lastIndexOf(QLatin1Char('/'));
419  const QString bin_path = execpath.left(pos);
420  for( QStringList::Iterator it = paths.begin();
421  it != paths.end();
422  ++it ) {
423  if( *it == bin_path || *it == bin_path + QLatin1Char('/')) {
424  paths.erase( it );
425  break; // -->
426  }
427  }
428  execpath = s_instance->dirs()->findExe(QFile::decodeName(exec), paths.join(QLatin1String(":")));
429  }
430  return QFile::encodeName(execpath);
431 }
432 
433 #ifdef KDEINIT_OOM_PROTECT
434 static void oom_protect_sighandler( int ) {
435 }
436 
437 static void reset_oom_protect() {
438  if( oom_pipe <= 0 )
439  return;
440  struct sigaction act, oldact;
441  act.sa_handler = oom_protect_sighandler;
442  act.sa_flags = 0;
443  sigemptyset( &act.sa_mask );
444  sigaction( SIGUSR1, &act, &oldact );
445  sigset_t sigs, oldsigs;
446  sigemptyset( &sigs );
447  sigaddset( &sigs, SIGUSR1 );
448  sigprocmask( SIG_BLOCK, &sigs, &oldsigs );
449  pid_t pid = getpid();
450  if( write( oom_pipe, &pid, sizeof( pid_t )) > 0 ) {
451  sigsuspend( &oldsigs ); // wait for the signal to come
452  } else {
453 #ifndef NDEBUG
454  fprintf( stderr, "Failed to reset OOM protection: %d\n", pid );
455 #endif
456  }
457  sigprocmask( SIG_SETMASK, &oldsigs, NULL );
458  sigaction( SIGUSR1, &oldact, NULL );
459  close( oom_pipe );
460  oom_pipe = -1;
461 }
462 #else
463 static void reset_oom_protect() {
464 }
465 #endif
466 
467 static pid_t launch(int argc, const char *_name, const char *args,
468  const char *cwd=0, int envc=0, const char *envs=0,
469  bool reset_env = false,
470  const char *tty=0, bool avoid_loops = false,
471  const char* startup_id_str = "0" ) // krazy:exclude=doublequote_chars
472 {
473  QString lib;
474  QByteArray name;
475  QByteArray exec;
476  QString libpath;
477  QByteArray execpath;
478 
479  if (_name[0] != '/') {
480  name = _name;
481  lib = QFile::decodeName(name);
482  exec = name;
483  KLibrary klib(QLatin1String("libkdeinit4_") + lib, *s_instance );
484  libpath = klib.fileName();
485  if( libpath.isEmpty()) {
486  KLibrary klib(lib, *s_instance);
487  libpath = klib.fileName();
488  }
489  execpath = execpath_avoid_loops(exec, envc, envs, avoid_loops);
490  } else {
491  name = _name;
492  lib = QFile::decodeName(name);
493  name = name.mid(name.lastIndexOf('/') + 1);
494  exec = _name;
495  if (lib.endsWith(QLatin1String(".so")))
496  libpath = lib;
497  else {
498  // try to match an absolute path to an executable binary (either in bin/ or in libexec/)
499  // to a kdeinit module in the same prefix
500  if( lib.contains( QLatin1String( "/lib" KDELIBSUFF "/kde4/libexec/" ))) {
501  libpath = QString( lib ).replace( QLatin1String( "/lib" KDELIBSUFF "/kde4/libexec/" ),
502  QLatin1String("/lib" KDELIBSUFF "/libkdeinit4_")) + QLatin1String(".so");
503  } else if( lib.contains( QLatin1String( "/bin/" ))) {
504  libpath = QString( lib ).replace( QLatin1String( "/bin/" ),
505  QLatin1String("/lib" KDELIBSUFF "/libkdeinit4_")) + QLatin1String(".so");
506  }
507  // Don't confuse the user with "Could not load libkdeinit4_foo.so" if it doesn't exist
508  if (!QFile::exists(libpath)) {
509  libpath.clear();
510  }
511  execpath = exec;
512  }
513  }
514 #ifndef NDEBUG
515  fprintf(stderr,"kdeinit4: preparing to launch %s\n", libpath.isEmpty()
516  ? execpath.constData() : libpath.toUtf8().constData());
517 #endif
518  if (!args) {
519  argc = 1;
520  }
521 
522  if (0 > pipe(d.fd))
523  {
524  perror("kdeinit4: pipe() failed");
525  d.result = 3;
526  d.errorMsg = i18n("Unable to start new process.\n"
527  "The system may have reached the maximum number of open files possible or the maximum number of open files that you are allowed to use has been reached.").toUtf8();
528  d.fork = 0;
529  return d.fork;
530  }
531 
532 #ifdef Q_WS_X11
533  KStartupInfoId startup_id;
534  startup_id.initId( startup_id_str );
535  if( !startup_id.none())
536  init_startup_info( startup_id, name, envc, envs );
537 #endif
538  // find out this path before forking, doing it afterwards
539  // crashes on some platforms, notably OSX
540 #ifdef Q_WS_MAC
541  const QString bundlepath = s_instance->dirs()->findExe(QFile::decodeName(execpath));
542 #endif
543 
544  d.errorMsg = 0;
545  d.fork = fork();
546  switch(d.fork) {
547  case -1:
548  perror("kdeinit4: fork() failed");
549  d.result = 3;
550  d.errorMsg = i18n("Unable to create new process.\n"
551  "The system may have reached the maximum number of processes possible or the maximum number of processes that you are allowed to use has been reached.").toUtf8();
552  close(d.fd[0]);
553  close(d.fd[1]);
554  d.fork = 0;
555  break;
556  case 0:
557  {
559  close(d.fd[0]);
560  close_fds();
561  reset_oom_protect();
562 
563  // Try to chdir, either to the requested directory or to the user's document path by default.
564  // We ignore errors - if you write a desktop file with Exec=foo and Path=/doesnotexist,
565  // we still want to execute `foo` even if the chdir() failed.
566  if (cwd && *cwd) {
567  (void)chdir(cwd);
568  }
569 
570  if( reset_env ) // KWRAPPER/SHELL
571  {
572 
573  QList<QByteArray> unset_envs;
574  for( int tmp_env_count = 0;
575  environ[tmp_env_count];
576  tmp_env_count++)
577  unset_envs.append( environ[ tmp_env_count ] );
578  foreach(const QByteArray &tmp, unset_envs)
579  {
580  int pos = tmp.indexOf( '=' );
581  if( pos >= 0 )
582  unsetenv( tmp.left( pos ));
583  }
584  }
585 
586  for (int i = 0; i < envc; i++)
587  {
588  putenv((char *)envs);
589  while(*envs != 0) envs++;
590  envs++;
591  }
592 
593 #ifdef Q_WS_X11
594  if( startup_id.none())
595  KStartupInfo::resetStartupEnv();
596  else
597  startup_id.setupStartupEnv();
598 #endif
599  {
600  int r;
601  QByteArray procTitle;
602  d.argv = (char **) malloc(sizeof(char *) * (argc+1));
603  d.argv[0] = (char *) _name;
604 #ifdef Q_WS_MAC
605  QString argvexe = s_instance->dirs()->findExe(QString::fromLatin1(d.argv[0]));
606  if (!argvexe.isEmpty()) {
607  QByteArray cstr = argvexe.toLocal8Bit();
608  kDebug(7016) << "kdeinit4: launch() setting argv: " << cstr.data();
609  d.argv[0] = strdup(cstr.data());
610  }
611 #endif
612  for (int i = 1; i < argc; i++)
613  {
614  d.argv[i] = (char *) args;
615  procTitle += ' ';
616  procTitle += (char *) args;
617  while(*args != 0) args++;
618  args++;
619  }
620  d.argv[argc] = 0;
621 
622 #ifndef SKIP_PROCTITLE
623 
624 #ifdef Q_OS_LINUX
625  /* set the process name, so that killall works like intended */
626  r = prctl(PR_SET_NAME, (unsigned long) name.data(), 0, 0, 0);
627  if ( r == 0 )
628  proctitle_set( "%s [kdeinit]%s", name.data(), procTitle.data() ? procTitle.data() : "" );
629  else
630  proctitle_set( "kdeinit4: %s%s", name.data(), procTitle.data() ? procTitle.data() : "" );
631 #else
632  proctitle_set( "kdeinit4: %s%s", name.data(), procTitle.data() ? procTitle.data() : "" );
633 #endif
634 #endif
635  }
636 
637  if (libpath.isEmpty() && execpath.isEmpty())
638  {
639  QString errorMsg = i18n("Could not find '%1' executable.", QFile::decodeName(_name));
640  exitWithErrorMsg(errorMsg);
641  }
642 
643 
644  if ( !qgetenv("KDE_IS_PRELINKED").isEmpty() && !execpath.isEmpty())
645  libpath.truncate(0);
646 
647  QLibrary l(libpath);
648 
649  if ( !libpath.isEmpty() )
650  {
651  if (!l.load() || !l.isLoaded() )
652  {
653  QString ltdlError (l.errorString());
654  if (execpath.isEmpty())
655  {
656  // Error
657  QString errorMsg = i18n("Could not open library '%1'.\n%2", libpath, ltdlError);
658  exitWithErrorMsg(errorMsg);
659  }
660  else
661  {
662  // Print warning
663  fprintf(stderr, "Could not open library %s: %s\n", qPrintable(lib),
664  qPrintable(ltdlError) );
665  }
666  }
667  }
668  if (!l.isLoaded())
669  {
670  d.result = 2; // Try execing
671  write(d.fd[1], &d.result, 1);
672 
673  // We set the close on exec flag.
674  // Closing of d.fd[1] indicates that the execvp succeeded!
675  fcntl(d.fd[1], F_SETFD, FD_CLOEXEC);
676 
677  setup_tty( tty );
678 
679  QByteArray executable = execpath;
680 #ifdef Q_WS_MAC
681  if (!bundlepath.isEmpty())
682  executable = QFile::encodeName(bundlepath);
683 #endif
684 
685  if (!executable.isEmpty())
686  execvp(executable, d.argv);
687 
688  d.result = 1; // Error
689  write(d.fd[1], &d.result, 1);
690  close(d.fd[1]);
691  exit(255);
692  }
693 
694  void * sym = l.resolve( "kdeinitmain");
695  if (!sym )
696  {
697  sym = l.resolve( "kdemain" );
698  if ( !sym )
699  {
700  QString ltdlError = l.errorString();
701  fprintf(stderr, "Could not find kdemain: %s\n", qPrintable(ltdlError) );
702  QString errorMsg = i18n("Could not find 'kdemain' in '%1'.\n%2",
703  libpath, ltdlError);
704  exitWithErrorMsg(errorMsg);
705  }
706  }
707 
708  d.result = 0; // Success
709  write(d.fd[1], &d.result, 1);
710  close(d.fd[1]);
711 
712  d.func = (int (*)(int, char *[])) sym;
713  if (d.debug_wait)
714  {
715  fprintf(stderr, "kdeinit4: Suspending process\n"
716  "kdeinit4: 'gdb kdeinit4 %d' to debug\n"
717  "kdeinit4: 'kill -SIGCONT %d' to continue\n",
718  getpid(), getpid());
719  kill(getpid(), SIGSTOP);
720  }
721  else
722  {
723  setup_tty( tty );
724  }
725 
726  exit( d.func(argc, d.argv)); /* Launch! */
727 
728  break;
729  }
730  default:
732  close(d.fd[1]);
733  bool exec = false;
734  for(;;)
735  {
736  d.n = read(d.fd[0], &d.result, 1);
737  if (d.n == 1)
738  {
739  if (d.result == 2)
740  {
741 #ifndef NDEBUG
742  //fprintf(stderr, "kdeinit4: no kdeinit module, trying exec....\n");
743 #endif
744  exec = true;
745  continue;
746  }
747  if (d.result == 3)
748  {
749  int l = 0;
750  d.n = read(d.fd[0], &l, sizeof(int));
751  if (d.n == sizeof(int))
752  {
753  QByteArray tmp;
754  tmp.resize(l+1);
755  d.n = read(d.fd[0], tmp.data(), l);
756  tmp[l] = 0;
757  if (d.n == l)
758  d.errorMsg = tmp;
759  }
760  }
761  // Finished
762  break;
763  }
764  if (d.n == -1)
765  {
766  if (errno == ECHILD) { // a child died.
767  continue;
768  }
769  if (errno == EINTR || errno == EAGAIN) { // interrupted or more to read
770  continue;
771  }
772  }
773  if (d.n == 0)
774  {
775  if (exec) {
776  d.result = 0;
777  } else {
778  fprintf(stderr,"kdeinit4: (%s %s) Pipe closed unexpectedly", name.constData(), execpath.constData());
779  perror("kdeinit4: Pipe closed unexpectedly");
780  d.result = 1; // Error
781  }
782  break;
783  }
784  perror("kdeinit4: Error reading from pipe");
785  d.result = 1; // Error
786  break;
787  }
788  close(d.fd[0]);
789  }
790 #ifdef Q_WS_X11
791  if( !startup_id.none())
792  {
793  if( d.fork && d.result == 0 ) // launched successfully
794  complete_startup_info( startup_id, d.fork );
795  else // failure, cancel ASN
796  complete_startup_info( startup_id, 0 );
797  }
798 #endif
799  return d.fork;
800 }
801 
802 extern "C" {
803 
804 static void sig_child_handler(int)
805 {
806  /*
807  * Write into the pipe of death.
808  * This way we are sure that we return from the select()
809  *
810  * A signal itself causes select to return as well, but
811  * this creates a race-condition in case the signal arrives
812  * just before we enter the select.
813  */
814  char c = 0;
815  write(d.deadpipe[1], &c, 1);
816 }
817 
818 }
819 
820 static void init_signals()
821 {
822  struct sigaction act;
823  long options;
824 
825  if (pipe(d.deadpipe) != 0)
826  {
827  perror("kdeinit4: Aborting. Can not create pipe");
828  exit(255);
829  }
830 
831  options = fcntl(d.deadpipe[0], F_GETFL);
832  if (options == -1)
833  {
834  perror("kdeinit4: Aborting. Can not make pipe non-blocking");
835  exit(255);
836  }
837 
838  if (fcntl(d.deadpipe[0], F_SETFL, options | O_NONBLOCK) == -1)
839  {
840  perror("kdeinit4: Aborting. Can not make pipe non-blocking");
841  exit(255);
842  }
843 
844  /*
845  * A SIGCHLD handler is installed which sends a byte into the
846  * pipe of death. This is to ensure that a dying child causes
847  * an exit from select().
848  */
849  act.sa_handler=sig_child_handler;
850  sigemptyset(&(act.sa_mask));
851  sigaddset(&(act.sa_mask), SIGCHLD);
852  sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
853  act.sa_flags = SA_NOCLDSTOP;
854 
855  // CC: take care of SunOS which automatically restarts interrupted system
856  // calls (and thus does not have SA_RESTART)
857 
858 #ifdef SA_RESTART
859  act.sa_flags |= SA_RESTART;
860 #endif
861  sigaction( SIGCHLD, &act, 0L);
862 
863  act.sa_handler=SIG_IGN;
864  sigemptyset(&(act.sa_mask));
865  sigaddset(&(act.sa_mask), SIGPIPE);
866  sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0L);
867  act.sa_flags = 0;
868  sigaction( SIGPIPE, &act, 0L);
869 }
870 
871 static void init_kdeinit_socket()
872 {
873  struct sockaddr_un sa;
874  kde_socklen_t socklen;
875  long options;
876  const QByteArray home_dir = qgetenv("HOME");
877  int max_tries = 10;
878  if (home_dir.isEmpty())
879  {
880  fprintf(stderr, "kdeinit4: Aborting. $HOME not set!");
881  exit(255);
882  }
883  if (chdir(home_dir) != 0) {
884  fprintf(stderr, "kdeinit4: Aborting. Couldn't enter '%s'!", home_dir.constData());
885  exit(255);
886  }
887 
888  {
889  QByteArray path = home_dir;
890  QByteArray readOnly = qgetenv("KDE_HOME_READONLY");
891  if (access(path.data(), R_OK|W_OK))
892  {
893  if (errno == ENOENT)
894  {
895  fprintf(stderr, "kdeinit4: Aborting. $HOME directory (%s) does not exist.\n", path.data());
896  exit(255);
897  }
898  else if (readOnly.isEmpty())
899  {
900  fprintf(stderr, "kdeinit4: Aborting. No write access to $HOME directory (%s).\n", path.data());
901  exit(255);
902  }
903  }
904 #if 0 // obsolete in kde4. Should we check writing to another file instead?
905  path = qgetenv("ICEAUTHORITY");
906  if (path.isEmpty())
907  {
908  path = home_dir;
909  path += "/.ICEauthority";
910  }
911  if (access(path.data(), R_OK|W_OK) && (errno != ENOENT))
912  {
913  fprintf(stderr, "kdeinit4: Aborting. No write access to '%s'.\n", path.data());
914  exit(255);
915  }
916 #endif
917  }
918 
923  if (access(sock_file, W_OK) == 0)
924  {
925  int s;
926  struct sockaddr_un server;
927 
928 // fprintf(stderr, "kdeinit4: Warning, socket_file already exists!\n");
929  /*
930  * create the socket stream
931  */
932  s = socket(PF_UNIX, SOCK_STREAM, 0);
933  if (s < 0)
934  {
935  perror("socket() failed");
936  exit(255);
937  }
938  server.sun_family = AF_UNIX;
939  strcpy(server.sun_path, sock_file);
940  socklen = sizeof(server);
941 
942  if(connect(s, (struct sockaddr *)&server, socklen) == 0)
943  {
944  fprintf(stderr, "kdeinit4: Shutting down running client.\n");
945  klauncher_header request_header;
946  request_header.cmd = LAUNCHER_TERMINATE_KDEINIT;
947  request_header.arg_length = 0;
948  write(s, &request_header, sizeof(request_header));
949  sleep(1); // Give it some time
950  }
951  close(s);
952  }
953 
955  unlink(sock_file);
956 
958  d.wrapper = socket(PF_UNIX, SOCK_STREAM, 0);
959  if (d.wrapper < 0)
960  {
961  perror("kdeinit4: Aborting. socket() failed");
962  exit(255);
963  }
964 
965  options = fcntl(d.wrapper, F_GETFL);
966  if (options == -1)
967  {
968  perror("kdeinit4: Aborting. Can not make socket non-blocking");
969  close(d.wrapper);
970  exit(255);
971  }
972 
973  if (fcntl(d.wrapper, F_SETFL, options | O_NONBLOCK) == -1)
974  {
975  perror("kdeinit4: Aborting. Can not make socket non-blocking");
976  close(d.wrapper);
977  exit(255);
978  }
979 
980  while (1) {
982  socklen = sizeof(sa);
983  memset(&sa, 0, socklen);
984  sa.sun_family = AF_UNIX;
985  strcpy(sa.sun_path, sock_file);
986  if(bind(d.wrapper, (struct sockaddr *)&sa, socklen) != 0)
987  {
988  if (max_tries == 0) {
989  perror("kdeinit4: Aborting. bind() failed");
990  fprintf(stderr, "Could not bind to socket '%s'\n", sock_file);
991  close(d.wrapper);
992  exit(255);
993  }
994  max_tries--;
995  } else
996  break;
997  }
998 
1000  if (chmod(sock_file, 0600) != 0)
1001  {
1002  perror("kdeinit4: Aborting. Can not set permissions on socket");
1003  fprintf(stderr, "Wrong permissions of socket '%s'\n", sock_file);
1004  unlink(sock_file);
1005  close(d.wrapper);
1006  exit(255);
1007  }
1008 
1009  if(listen(d.wrapper, SOMAXCONN) < 0)
1010  {
1011  perror("kdeinit4: Aborting. listen() failed");
1012  unlink(sock_file);
1013  close(d.wrapper);
1014  exit(255);
1015  }
1016 }
1017 
1018 /*
1019  * Read 'len' bytes from 'sock' into buffer.
1020  * returns 0 on success, -1 on failure.
1021  */
1022 static int read_socket(int sock, char *buffer, int len)
1023 {
1024  ssize_t result;
1025  int bytes_left = len;
1026  while ( bytes_left > 0)
1027  {
1028  result = read(sock, buffer, bytes_left);
1029  if (result > 0)
1030  {
1031  buffer += result;
1032  bytes_left -= result;
1033  }
1034  else if (result == 0)
1035  return -1;
1036  else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
1037  return -1;
1038  }
1039  return 0;
1040 }
1041 
1042 static void start_klauncher()
1043 {
1044  if (socketpair(AF_UNIX, SOCK_STREAM, 0, d.launcher) < 0) {
1045  perror("kdeinit4: socketpair() failed");
1046  exit(255);
1047  }
1048  char args[32];
1049  strcpy(args, "--fd=");
1050  sprintf(args + 5, "%d", d.launcher[1]);
1051  d.launcher_pid = launch( 2, "klauncher", args );
1052  close(d.launcher[1]);
1053 #ifndef NDEBUG
1054  fprintf(stderr, "kdeinit4: Launched KLauncher, pid = %ld, result = %d\n",
1055  (long) d.launcher_pid, d.result);
1056 #endif
1057 }
1058 
1059 static void launcher_died()
1060 {
1061  if (!d.launcher_ok)
1062  {
1063  /* This is bad. */
1064  fprintf(stderr, "kdeinit4: Communication error with launcher. Exiting!\n");
1065  ::exit(255);
1066  return;
1067  }
1068 
1069  // KLauncher died... restart
1070 #ifndef NDEBUG
1071  fprintf(stderr, "kdeinit4: KLauncher died unexpectedly.\n");
1072 #endif
1073  // Make sure it's really dead.
1074  if (d.launcher_pid)
1075  {
1076  kill(d.launcher_pid, SIGKILL);
1077  sleep(1); // Give it some time
1078  }
1079 
1080  d.launcher_ok = false;
1081  d.launcher_pid = 0;
1082  close(d.launcher[0]);
1083  d.launcher[0] = -1;
1084 
1085  start_klauncher();
1086 }
1087 
1088 static bool handle_launcher_request(int sock, const char *who)
1089 {
1090  (void)who; // for NDEBUG
1091 
1092  klauncher_header request_header;
1093  char *request_data = 0L;
1094  int result = read_socket(sock, (char *) &request_header, sizeof(request_header));
1095  if (result != 0)
1096  {
1097  return false;
1098  }
1099 
1100  if ( request_header.arg_length != 0 )
1101  {
1102  request_data = (char *) malloc(request_header.arg_length);
1103 
1104  result = read_socket(sock, request_data, request_header.arg_length);
1105  if (result != 0)
1106  {
1107  free(request_data);
1108  return false;
1109  }
1110  }
1111 
1112  //kDebug() << "Got cmd" << request_header.cmd << commandToString(request_header.cmd);
1113  if (request_header.cmd == LAUNCHER_OK)
1114  {
1115  d.launcher_ok = true;
1116  }
1117  else if (request_header.arg_length &&
1118  ((request_header.cmd == LAUNCHER_EXEC) ||
1119  (request_header.cmd == LAUNCHER_EXT_EXEC) ||
1120  (request_header.cmd == LAUNCHER_SHELL ) ||
1121  (request_header.cmd == LAUNCHER_KWRAPPER) ||
1122  (request_header.cmd == LAUNCHER_EXEC_NEW)))
1123  {
1124  pid_t pid;
1125  klauncher_header response_header;
1126  long response_data;
1127  long l;
1128  memcpy( &l, request_data, sizeof( long ));
1129  int argc = l;
1130  const char *name = request_data + sizeof(long);
1131  const char *args = name + strlen(name) + 1;
1132  const char *cwd = 0;
1133  int envc = 0;
1134  const char *envs = 0;
1135  const char *tty = 0;
1136  int avoid_loops = 0;
1137  const char *startup_id_str = "0"; // krazy:exclude=doublequote_chars
1138 
1139 #ifndef NDEBUG
1140  fprintf(stderr, "kdeinit4: Got %s '%s' from %s.\n",
1141  commandToString(request_header.cmd),
1142  name, who);
1143 #endif
1144 
1145  const char *arg_n = args;
1146  for(int i = 1; i < argc; i++)
1147  {
1148  arg_n = arg_n + strlen(arg_n) + 1;
1149  }
1150 
1151  if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER )
1152  {
1153  // Shell or kwrapper
1154  cwd = arg_n; arg_n += strlen(cwd) + 1;
1155  }
1156  if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
1157  || request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW )
1158  {
1159  memcpy( &l, arg_n, sizeof( long ));
1160  envc = l;
1161  arg_n += sizeof(long);
1162  envs = arg_n;
1163  for(int i = 0; i < envc; i++)
1164  {
1165  arg_n = arg_n + strlen(arg_n) + 1;
1166  }
1167  if( request_header.cmd == LAUNCHER_KWRAPPER )
1168  {
1169  tty = arg_n;
1170  arg_n += strlen( tty ) + 1;
1171  }
1172  }
1173 
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 )
1176  {
1177  memcpy( &l, arg_n, sizeof( long ));
1178  avoid_loops = l;
1179  arg_n += sizeof( long );
1180  }
1181 
1182  if( request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER
1183  || request_header.cmd == LAUNCHER_EXT_EXEC )
1184  {
1185  startup_id_str = arg_n;
1186  arg_n += strlen( startup_id_str ) + 1;
1187  }
1188 
1189  if ((request_header.arg_length > (arg_n - request_data)) &&
1190  (request_header.cmd == LAUNCHER_EXT_EXEC || request_header.cmd == LAUNCHER_EXEC_NEW ))
1191  {
1192  // Optional cwd
1193  cwd = arg_n; arg_n += strlen(cwd) + 1;
1194  }
1195 
1196  if ((arg_n - request_data) != request_header.arg_length)
1197  {
1198 #ifndef NDEBUG
1199  fprintf(stderr, "kdeinit4: EXEC request has invalid format.\n");
1200 #endif
1201  free(request_data);
1202  d.debug_wait = false;
1203  return true; // sure?
1204  }
1205 
1206  // support for the old a bit broken way of setting DISPLAY for multihead
1207  QByteArray olddisplay = qgetenv(DISPLAY);
1208  QByteArray kdedisplay = qgetenv("KDE_DISPLAY");
1209  bool reset_display = (! olddisplay.isEmpty() &&
1210  ! kdedisplay.isEmpty() &&
1211  olddisplay != kdedisplay);
1212 
1213  if (reset_display)
1214  setenv(DISPLAY, kdedisplay, true);
1215 
1216  pid = launch( argc, name, args, cwd, envc, envs,
1217  request_header.cmd == LAUNCHER_SHELL || request_header.cmd == LAUNCHER_KWRAPPER,
1218  tty, avoid_loops, startup_id_str );
1219 
1220  if (reset_display) {
1221  unsetenv("KDE_DISPLAY");
1222  setenv(DISPLAY, olddisplay, true);
1223  }
1224 
1225  if (pid && (d.result == 0))
1226  {
1227  response_header.cmd = LAUNCHER_OK;
1228  response_header.arg_length = sizeof(response_data);
1229  response_data = pid;
1230  write(sock, &response_header, sizeof(response_header));
1231  write(sock, &response_data, response_header.arg_length);
1232 
1233  /* add new child to list */
1234  struct child *child = (struct child *) malloc(sizeof(struct child));
1235  child->pid = pid;
1236  child->sock = dup(sock);
1237  child->next = children;
1238  children = child;
1239  }
1240  else
1241  {
1242  int l = d.errorMsg.length();
1243  if (l) l++; // Include trailing null.
1244  response_header.cmd = LAUNCHER_ERROR;
1245  response_header.arg_length = l;
1246  write(sock, &response_header, sizeof(response_header));
1247  if (l)
1248  write(sock, d.errorMsg.data(), l);
1249  }
1250  d.debug_wait = false;
1251  }
1252  else if (request_header.arg_length && request_header.cmd == LAUNCHER_SETENV)
1253  {
1254  const char *env_name;
1255  const char *env_value;
1256  env_name = request_data;
1257  env_value = env_name + strlen(env_name) + 1;
1258 
1259 #ifndef NDEBUG
1260  fprintf(stderr, "kdeinit4: Got SETENV '%s=%s' from %s.\n", env_name, env_value, who);
1261 #endif
1262 
1263  if ( request_header.arg_length !=
1264  (int) (strlen(env_name) + strlen(env_value) + 2))
1265  {
1266 #ifndef NDEBUG
1267  fprintf(stderr, "kdeinit4: SETENV request has invalid format.\n");
1268 #endif
1269  free(request_data);
1270  return true; // sure?
1271  }
1272  setenv( env_name, env_value, 1);
1273  }
1274  else if (request_header.cmd == LAUNCHER_TERMINATE_KDE)
1275  {
1276 #ifndef NDEBUG
1277  fprintf(stderr,"kdeinit4: terminate KDE.\n");
1278 #endif
1279 #ifdef Q_WS_X11
1280  kdeinit_xio_errhandler( 0L );
1281 #endif
1282  }
1283  else if (request_header.cmd == LAUNCHER_TERMINATE_KDEINIT)
1284  {
1285 #ifndef NDEBUG
1286  fprintf(stderr,"kdeinit4: Got termination request (PID %ld).\n", (long) getpid());
1287 #endif
1288  if (d.launcher_pid) {
1289  kill(d.launcher_pid, SIGTERM);
1290  d.launcher_pid = 0;
1291  close(d.launcher[0]);
1292  d.launcher[0] = -1;
1293  }
1294  unlink(sock_file);
1295  if (children) {
1296  close(d.wrapper);
1297  d.wrapper = -1;
1298 #ifndef NDEBUG
1299  fprintf(stderr,"kdeinit4: Closed sockets, but not exiting until all children terminate.\n");
1300 #endif
1301  } else {
1302  raise(SIGTERM);
1303  }
1304  }
1305  else if (request_header.cmd == LAUNCHER_DEBUG_WAIT)
1306  {
1307 #ifndef NDEBUG
1308  fprintf(stderr,"kdeinit4: Debug wait activated.\n");
1309 #endif
1310  d.debug_wait = true;
1311  }
1312  if (request_data)
1313  free(request_data);
1314  return true;
1315 }
1316 
1317 static void handle_requests(pid_t waitForPid)
1318 {
1319  int max_sock = d.deadpipe[0];
1320  if (d.wrapper > max_sock)
1321  max_sock = d.wrapper;
1322  if (d.launcher[0] > max_sock)
1323  max_sock = d.launcher[0];
1324 #ifdef Q_WS_X11
1325  if (X11fd > max_sock)
1326  max_sock = X11fd;
1327 #endif
1328  max_sock++;
1329 
1330  while(1)
1331  {
1332  fd_set rd_set;
1333  fd_set wr_set;
1334  fd_set e_set;
1335  int result;
1336  pid_t exit_pid;
1337  int exit_status;
1338  char c;
1339 
1340  /* Flush the pipe of death */
1341  while( read(d.deadpipe[0], &c, 1) == 1)
1342  {}
1343 
1344  /* Handle dying children */
1345  do {
1346  exit_pid = waitpid(-1, &exit_status, WNOHANG);
1347  if (exit_pid > 0)
1348  {
1349 #ifndef NDEBUG
1350  fprintf(stderr, "kdeinit4: PID %ld terminated.\n", (long) exit_pid);
1351 #endif
1352  if (waitForPid && (exit_pid == waitForPid))
1353  return;
1354 
1355  if( WIFEXITED( exit_status )) // fix process return value
1356  exit_status = WEXITSTATUS(exit_status);
1357  else if( WIFSIGNALED(exit_status))
1358  exit_status = 128 + WTERMSIG( exit_status );
1359  child_died(exit_pid, exit_status);
1360 
1361  if (d.wrapper < 0 && !children) {
1362 #ifndef NDEBUG
1363  fprintf(stderr, "kdeinit4: Last child terminated, exiting (PID %ld).\n",
1364  (long) getpid());
1365 #endif
1366  raise(SIGTERM);
1367  }
1368  }
1369  }
1370  while( exit_pid > 0);
1371 
1372  FD_ZERO(&rd_set);
1373  FD_ZERO(&wr_set);
1374  FD_ZERO(&e_set);
1375 
1376  if (d.launcher[0] >= 0)
1377  FD_SET(d.launcher[0], &rd_set);
1378  if (d.wrapper >= 0)
1379  FD_SET(d.wrapper, &rd_set);
1380  FD_SET(d.deadpipe[0], &rd_set);
1381 #ifdef Q_WS_X11
1382  if(X11fd >= 0) FD_SET(X11fd, &rd_set);
1383 #endif
1384 
1385  result = select(max_sock, &rd_set, &wr_set, &e_set, 0);
1386  if (result < 0) {
1387  if (errno == EINTR || errno == EAGAIN)
1388  continue;
1389  perror("kdeinit4: Aborting. select() failed");
1390  return;
1391  }
1392 
1393  /* Handle wrapper request */
1394  if (d.wrapper >= 0 && FD_ISSET(d.wrapper, &rd_set))
1395  {
1396  struct sockaddr_un client;
1397  kde_socklen_t sClient = sizeof(client);
1398  int sock = accept(d.wrapper, (struct sockaddr *)&client, &sClient);
1399  if (sock >= 0)
1400  {
1401  d.accepted_fd = sock;
1402  handle_launcher_request(sock, "wrapper");
1403  close(sock);
1404  d.accepted_fd = -1;
1405  }
1406  }
1407 
1408  /* Handle launcher request */
1409  if (d.launcher[0] >= 0 && FD_ISSET(d.launcher[0], &rd_set))
1410  {
1411  if (!handle_launcher_request(d.launcher[0], "launcher"))
1412  launcher_died();
1413  if (waitForPid == d.launcher_pid)
1414  return;
1415  }
1416 
1417 #ifdef Q_WS_X11
1418  /* Look for incoming X11 events */
1419  if(X11fd >= 0 && FD_ISSET(X11fd,&rd_set)) {
1420  if (X11display != 0) {
1421  XEvent event_return;
1422  while (XPending(X11display))
1423  XNextEvent(X11display, &event_return);
1424  }
1425  }
1426 #endif
1427  }
1428 }
1429 
1430 static void kdeinit_library_path()
1431 {
1432  const QStringList ltdl_library_path =
1433  QFile::decodeName(qgetenv("LTDL_LIBRARY_PATH")).split(QLatin1Char(':'),QString::SkipEmptyParts);
1434 #ifdef Q_OS_DARWIN
1435  const QByteArray ldlibpath = qgetenv("DYLD_LIBRARY_PATH");
1436 #else
1437  const QByteArray ldlibpath = qgetenv("LD_LIBRARY_PATH");
1438 #endif
1439  const QStringList ld_library_path =
1440  QFile::decodeName(ldlibpath).split(QLatin1Char(':'),QString::SkipEmptyParts);
1441 
1442  QByteArray extra_path;
1443  const QStringList candidates = s_instance->dirs()->resourceDirs("lib");
1444  for (QStringList::ConstIterator it = candidates.begin();
1445  it != candidates.end();
1446  ++it)
1447  {
1448  QString d = *it;
1449  if (ltdl_library_path.contains(d))
1450  continue;
1451  if (ld_library_path.contains(d))
1452  continue;
1453  if (d[d.length()-1] == QLatin1Char('/'))
1454  {
1455  d.truncate(d.length()-1);
1456  if (ltdl_library_path.contains(d))
1457  continue;
1458  if (ld_library_path.contains(d))
1459  continue;
1460  }
1461  if ((d == QLatin1String("/lib")) || (d == QLatin1String("/usr/lib")))
1462  continue;
1463 
1464  QByteArray dir = QFile::encodeName(d);
1465 
1466  if (access(dir, R_OK))
1467  continue;
1468 
1469  if ( !extra_path.isEmpty())
1470  extra_path += ':';
1471  extra_path += dir;
1472  }
1473 
1474 // if (!extra_path.isEmpty())
1475 // lt_dlsetsearchpath(extra_path.data());
1476 
1477  QByteArray display = qgetenv(DISPLAY);
1478  if (display.isEmpty())
1479  {
1480 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
1481  fprintf(stderr, "kdeinit4: Aborting. $"DISPLAY" is not set.\n");
1482  exit(255);
1483 #endif
1484  }
1485  int i;
1486  if((i = display.lastIndexOf('.')) > display.lastIndexOf(':') && i >= 0)
1487  display.truncate(i);
1488 
1489  display.replace(':','_');
1490 #ifdef __APPLE__
1491  display.replace('/','_');
1492 #endif
1493  // WARNING, if you change the socket name, adjust kwrapper too
1494  const QString socketFileName = QString::fromLatin1("kdeinit4_%1").arg(QLatin1String(display));
1495  QByteArray socketName = QFile::encodeName(KStandardDirs::locateLocal("socket", socketFileName, *s_instance));
1496  if (socketName.length() >= MAX_SOCK_FILE)
1497  {
1498  fprintf(stderr, "kdeinit4: Aborting. Socket name will be too long:\n");
1499  fprintf(stderr, " '%s'\n", socketName.data());
1500  exit(255);
1501  }
1502  strcpy(sock_file, socketName.data());
1503 }
1504 
1505 int kdeinit_xio_errhandler( Display *disp )
1506 {
1507  // disp is 0L when KDE shuts down. We don't want those warnings then.
1508 
1509  if ( disp )
1510  qWarning( "kdeinit4: Fatal IO error: client killed" );
1511 
1512  if (sock_file[0])
1513  {
1515  unlink(sock_file);
1516  }
1517 
1518  // Don't kill our children in suicide mode, they may still be in use
1519  if (d.suicide)
1520  {
1521  if (d.launcher_pid)
1522  kill(d.launcher_pid, SIGTERM);
1523  if (d.kded_pid)
1524  kill(d.kded_pid, SIGTERM);
1525  exit( 0 );
1526  }
1527 
1528  if ( disp )
1529  qWarning( "kdeinit4: sending SIGHUP to children." );
1530 
1531  /* this should remove all children we started */
1532  KDE_signal(SIGHUP, SIG_IGN);
1533  kill(0, SIGHUP);
1534 
1535  sleep(2);
1536 
1537  if ( disp )
1538  qWarning( "kdeinit4: sending SIGTERM to children." );
1539 
1540  /* and if they don't listen to us, this should work */
1541  KDE_signal(SIGTERM, SIG_IGN);
1542  kill(0, SIGTERM);
1543 
1544  if ( disp )
1545  qWarning( "kdeinit4: Exit." );
1546 
1547  exit( 0 );
1548  return 0;
1549 }
1550 
1551 #ifdef Q_WS_X11
1552 int kdeinit_x_errhandler( Display *dpy, XErrorEvent *err )
1553 {
1554 #ifndef NDEBUG
1555  char errstr[256];
1556  // kdeinit almost doesn't use X, and therefore there shouldn't be any X error
1557  XGetErrorText( dpy, err->error_code, errstr, 256 );
1558  fprintf(stderr, "kdeinit4(%d) : KDE detected X Error: %s %d\n"
1559  " Major opcode: %d\n"
1560  " Minor opcode: %d\n"
1561  " Resource id: 0x%lx\n",
1562  getpid(), errstr, err->error_code, err->request_code, err->minor_code, err->resourceid );
1563 
1564  //kDebug() << kBacktrace();
1565 
1566 #else
1567  Q_UNUSED(dpy);
1568  Q_UNUSED(err);
1569 #endif
1570  return 0;
1571 }
1572 #endif
1573 
1574 #ifdef Q_WS_X11
1575 // needs to be done sooner than initXconnection() because of also opening
1576 // another X connection for startup notification purposes
1577 static void setupX()
1578 {
1579  XSetIOErrorHandler(kdeinit_xio_errhandler);
1580  XSetErrorHandler(kdeinit_x_errhandler);
1581 /*
1582  Handle the tricky case of running via kdesu/su/sudo/etc. There the usual case
1583  is that kdesu (etc.) creates a file with xauth information, sets XAUTHORITY,
1584  runs the command and removes the xauth file after the command finishes. However,
1585  dbus and kdeinit daemon currently don't clean up properly and keeping running.
1586  Which means that running a KDE app via kdesu the second time talks to kdeinit
1587  with obsolete xauth information, which makes it unable to connect to X or launch
1588  any X11 applications.
1589  Even fixing the cleanup probably wouldn't be sufficient, since it'd be possible to
1590  launch one kdesu session, another one, exit the first one and the app from the second
1591  session would be using kdeinit from the first one.
1592  So the trick here is to duplicate the xauth file to another file in KDE's tmp
1593  location, make the file have a consistent name so that future sessions will use it
1594  as well, point XAUTHORITY there and never remove the file (except for possible
1595  tmp cleanup).
1596 */
1597  if( !qgetenv( "XAUTHORITY" ).isEmpty()) {
1598  QByteArray display = qgetenv( DISPLAY );
1599  int i;
1600  if((i = display.lastIndexOf('.')) > display.lastIndexOf(':') && i >= 0)
1601  display.truncate(i);
1602  display.replace(':','_');
1603 #ifdef __APPLE__
1604  display.replace('/','_');
1605 #endif
1606  QString xauth = s_instance->dirs()->saveLocation( "tmp" ) + QLatin1String( "xauth-" )
1607  + QString::number( getuid()) + QLatin1String( "-" ) + QString::fromLocal8Bit( display );
1608  KSaveFile xauthfile( xauth );
1609  QFile xauthfrom( QFile::decodeName( qgetenv( "XAUTHORITY" )));
1610  if( !xauthfrom.open( QFile::ReadOnly ) || !xauthfile.open( QFile::WriteOnly )
1611  || xauthfile.write( xauthfrom.readAll()) != xauthfrom.size() || !xauthfile.finalize()) {
1612  xauthfile.abort();
1613  } else {
1614  setenv( "XAUTHORITY", QFile::encodeName( xauth ), true );
1615  }
1616  }
1617 }
1618 
1619 // Borrowed from kdebase/kaudio/kaudioserver.cpp
1620 static int initXconnection()
1621 {
1622  X11display = XOpenDisplay(NULL);
1623  if ( X11display != 0 ) {
1624  XCreateSimpleWindow(X11display, DefaultRootWindow(X11display), 0,0,1,1, \
1625  0,
1626  BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)),
1627  BlackPixelOfScreen(DefaultScreenOfDisplay(X11display)) );
1628 #ifndef NDEBUG
1629  fprintf(stderr, "kdeinit4: opened connection to %s\n", DisplayString(X11display));
1630 #endif
1631  int fd = XConnectionNumber( X11display );
1632  int on = 1;
1633  (void) setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, (int) sizeof(on));
1634  return fd;
1635  } else
1636  fprintf(stderr, "kdeinit4: Can not connect to the X Server.\n" \
1637  "kdeinit4: Might not terminate at end of session.\n");
1638 
1639  return -1;
1640 }
1641 #endif
1642 
1643 extern "C" {
1644 
1645 static void secondary_child_handler(int)
1646 {
1647  waitpid(-1, 0, WNOHANG);
1648 }
1649 
1650 }
1651 
1652 int main(int argc, char **argv, char **envp)
1653 {
1654 #ifndef _WIN32_WCE
1655  setlocale (LC_ALL, "");
1656  setlocale (LC_NUMERIC, "C");
1657 #endif
1658 
1659  pid_t pid;
1660  bool do_fork = true;
1661  int launch_klauncher = 1;
1662  int launch_kded = 1;
1663  int keep_running = 1;
1664  d.suicide = false;
1665 
1667  char **safe_argv = (char **) malloc( sizeof(char *) * argc);
1668  for(int i = 0; i < argc; i++)
1669  {
1670  safe_argv[i] = strcpy((char*)malloc(strlen(argv[i])+1), argv[i]);
1671  if (strcmp(safe_argv[i], "--no-klauncher") == 0)
1672  launch_klauncher = 0;
1673  if (strcmp(safe_argv[i], "--no-kded") == 0)
1674  launch_kded = 0;
1675 #ifdef Q_WS_MACX
1676  // make it nofork to match KUniqueApplication, technically command-line incompatible
1677  if (strcmp(safe_argv[i], "--nofork") == 0)
1678 #else
1679  if (strcmp(safe_argv[i], "--no-fork") == 0)
1680 #endif
1681  do_fork = false;
1682  if (strcmp(safe_argv[i], "--suicide") == 0)
1683  d.suicide = true;
1684  if (strcmp(safe_argv[i], "--exit") == 0)
1685  keep_running = 0;
1686  if (strcmp(safe_argv[i], "--version") == 0)
1687  {
1688  printf("Qt: %s\n", qVersion());
1689  printf("KDE: %s\n", KDE_VERSION_STRING);
1690  exit(0);
1691  }
1692 #ifdef KDEINIT_OOM_PROTECT
1693  if (strcmp(safe_argv[i], "--oom-pipe") == 0 && i+1<argc)
1694  oom_pipe = atol(argv[i+1]);
1695 #endif
1696  if (strcmp(safe_argv[i], "--help") == 0)
1697  {
1698  printf("Usage: kdeinit4 [options]\n");
1699  // printf(" --no-dcop Do not start dcopserver\n");
1700 #ifdef Q_WS_MACX
1701  printf(" --nofork Do not fork\n");
1702 #else
1703  printf(" --no-fork Do not fork\n");
1704 #endif
1705  // printf(" --no-klauncher Do not start klauncher\n");
1706  printf(" --no-kded Do not start kded\n");
1707  printf(" --suicide Terminate when no KDE applications are left running\n");
1708  printf(" --version Show version information\n");
1709  // printf(" --exit Terminate when kded has run\n");
1710  exit(0);
1711  }
1712  }
1713 
1714  cleanup_fds();
1715 
1716  // Redirect stdout to stderr. We have no reason to use stdout anyway.
1717  // This minimizes our impact on commands used in pipes.
1718  (void)dup2(2, 1);
1719 
1720  if (do_fork) {
1721 #ifdef Q_WS_MACX
1722  mac_fork_and_reexec_self();
1723 #else
1724  if (pipe(d.initpipe) != 0) {
1725  perror("kdeinit4: pipe failed");
1726  return 1;
1727  }
1728 
1729  // Fork here and let parent process exit.
1730  // Parent process may only exit after all required services have been
1731  // launched. (dcopserver/klauncher and services which start with '+')
1732  KDE_signal( SIGCHLD, secondary_child_handler);
1733  if (fork() > 0) // Go into background
1734  {
1735  close(d.initpipe[1]);
1736  d.initpipe[1] = -1;
1737  // wait till init is complete
1738  char c;
1739  while( read(d.initpipe[0], &c, 1) < 0)
1740  ;
1741  // then exit;
1742  close(d.initpipe[0]);
1743  d.initpipe[0] = -1;
1744  return 0;
1745  }
1746  close(d.initpipe[0]);
1747  d.initpipe[0] = -1;
1748 #endif
1749  }
1750 
1752  if(keep_running)
1753  setsid();
1754 
1756  s_instance = new KComponentData("kdeinit4", QByteArray(), KComponentData::SkipMainComponentRegistration);
1757 
1759 #ifndef SKIP_PROCTITLE
1760  proctitle_init(argc, argv, envp);
1761 #endif
1762 
1763  kdeinit_library_path();
1764  // Don't make our instance the global instance
1765  // (do it only after kdeinit_library_path, that one indirectly uses KConfig,
1766  // which seems to be buggy and always use KGlobal instead of the matching KComponentData)
1767  Q_ASSERT(!KGlobal::hasMainComponent());
1768  // don't change envvars before proctitle_init()
1769  unsetenv("LD_BIND_NOW");
1770  unsetenv("DYLD_BIND_AT_LAUNCH");
1771  KApplication::loadedByKdeinit = true;
1772 
1773  d.maxname = strlen(argv[0]);
1774  d.launcher_pid = 0;
1775  d.kded_pid = 0;
1776  d.wrapper = -1;
1777  d.accepted_fd = -1;
1778  d.debug_wait = false;
1779  d.launcher_ok = false;
1780  children = NULL;
1781  init_signals();
1782 #ifdef Q_WS_X11
1783  setupX();
1784 #endif
1785 
1786  if (keep_running)
1787  {
1788  /*
1789  * Create ~/.kde/tmp-<hostname>/kdeinit4-<display> socket for incoming wrapper
1790  * requests.
1791  */
1792  init_kdeinit_socket();
1793  }
1794 #ifdef Q_WS_X11
1795  if (!d.suicide && qgetenv("KDE_IS_PRELINKED").isEmpty()) {
1796  const int extrasCount = sizeof(extra_libs)/sizeof(extra_libs[0]);
1797  for (int i=0; i<extrasCount; i++) {
1798  QString extra = KStandardDirs::locate("lib", QLatin1String(extra_libs[i]), *s_instance);
1799 
1800  // can't use KLibLoader here as it would unload the library
1801  // again
1802  if (!extra.isEmpty()) {
1803  QLibrary l(extra);
1804  l.setLoadHints(QLibrary::ExportExternalSymbolsHint);
1805  (void)l.load();
1806  }
1807 #ifndef NDEBUG
1808  else {
1809  fprintf( stderr, "%s was not found.\n", extra_libs[i] );
1810  }
1811 #endif
1812 
1813  }
1814  }
1815 #endif
1816  if (launch_klauncher)
1817  {
1818  start_klauncher();
1819  handle_requests(d.launcher_pid); // Wait for klauncher to be ready
1820  }
1821 
1822 #ifdef Q_WS_X11
1823  X11fd = initXconnection();
1824 #endif
1825 
1826  {
1827  QFont::initialize();
1828 #ifdef Q_WS_X11
1829  if (XSupportsLocale ())
1830  {
1831  // Similar to QApplication::create_xim()
1832  // but we need to use our own display
1833  XOpenIM (X11display, 0, 0, 0);
1834  }
1835 #endif
1836  }
1837 
1838  if (launch_kded)
1839  {
1840  setenv("KDED_STARTED_BY_KDEINIT", "1", true);
1841  pid = launch( 1, KDED_EXENAME, 0 );
1842  unsetenv("KDED_STARTED_BY_KDEINIT");
1843 #ifndef NDEBUG
1844  fprintf(stderr, "kdeinit4: Launched KDED, pid = %ld result = %d\n", (long) pid, d.result);
1845 #endif
1846  d.kded_pid = pid;
1847  handle_requests(pid);
1848  }
1849 
1850  for(int i = 1; i < argc; i++)
1851  {
1852  if (safe_argv[i][0] == '+')
1853  {
1854  pid = launch( 1, safe_argv[i]+1, 0);
1855 #ifndef NDEBUG
1856  fprintf(stderr, "kdeinit4: Launched '%s', pid = %ld result = %d\n", safe_argv[i]+1, (long) pid, d.result);
1857 #endif
1858  handle_requests(pid);
1859  }
1860  else if (safe_argv[i][0] == '-'
1861 #ifdef KDEINIT_OOM_PROTECT
1862  || isdigit(safe_argv[i][0])
1863 #endif
1864  )
1865  {
1866  // Ignore
1867  }
1868  else
1869  {
1870  pid = launch( 1, safe_argv[i], 0 );
1871 #ifndef NDEBUG
1872  fprintf(stderr, "kdeinit4: Launched '%s', pid = %ld result = %d\n", safe_argv[i], (long) pid, d.result);
1873 #endif
1874  }
1875  }
1876 
1878  for(int i = 0; i < argc; i++)
1879  {
1880  free(safe_argv[i]);
1881  }
1882  free (safe_argv);
1883 
1884 #ifndef SKIP_PROCTITLE
1885  proctitle_set("kdeinit4 Running...");
1886 #endif
1887 
1888  if (!keep_running)
1889  return 0;
1890 
1891  if (d.initpipe[1] != -1)
1892  {
1893  char c = 0;
1894  write(d.initpipe[1], &c, 1); // Kdeinit is started.
1895  close(d.initpipe[1]);
1896  d.initpipe[1] = -1;
1897  }
1898 
1899  handle_requests(0);
1900 
1901  return 0;
1902 }
1903 
1904 
KStandardDirs::saveLocation
QString saveLocation(const char *type, const QString &suffix=QString(), bool create=true) const
i18n
QString i18n(const char *text)
klauncher_cmds.h
reset_oom_protect
static void reset_oom_protect()
Definition: kinit.cpp:463
secondary_child_handler
static void secondary_child_handler(int)
Definition: kinit.cpp:1645
setupX
static void setupX()
Definition: kinit.cpp:1577
LAUNCHER_EXT_EXEC
#define LAUNCHER_EXT_EXEC
Definition: klauncher_cmds.h:123
result
char result
Definition: kinit.cpp:135
QString::truncate
void truncate(int position)
perror
QDebug perror(QDebug s, KDebugTag)
kdebug.h
get_env_var
const char * get_env_var(const char *var, int envc, const char *envs)
Definition: kinit.cpp:348
handle_launcher_request
static bool handle_launcher_request(int sock, const char *who)
Definition: kinit.cpp:1088
QByteArray
init_kdeinit_socket
static void init_kdeinit_socket()
Definition: kinit.cpp:871
kkernel_mac.h
QByteArray::lastIndexOf
int lastIndexOf(char ch, int from) const
QString::split
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
suicide
bool suicide
Definition: kinit.cpp:147
exitWithErrorMsg
static void exitWithErrorMsg(const QString &errorMsg)
Definition: kinit.cpp:290
KStandardDirs::locate
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
kconfig.h
ksavefile.h
KSaveFile
KSaveFile::open
virtual bool open(OpenMode flags=QIODevice::ReadWrite)
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
QLibrary::setLoadHints
void setLoadHints(QFlags< QLibrary::LoadHint > hints)
QByteArray::isEmpty
bool isEmpty() const
init_signals
static void init_signals()
Definition: kinit.cpp:820
KDED_EXENAME
#define KDED_EXENAME
Definition: kinit_win.cpp:54
kded_pid
pid_t kded_pid
Definition: kinit.cpp:139
chmod
int chmod(const QString &path, mode_t mode)
QList::erase
iterator erase(iterator pos)
listen
QTcpServer * listen(const QString &protocol, const QHostAddress &address=QHostAddress::Any, quint16 port=0, QObject *parent=0)
QStringList::join
QString join(const QString &separator) const
QByteArray::length
int length() const
QFile::exists
bool exists() const
LAUNCHER_SHELL
#define LAUNCHER_SHELL
Definition: klauncher_cmds.h:85
KSaveFile::abort
void abort()
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
klocale.h
KDE_VERSION_STRING
#define KDE_VERSION_STRING
mac_fork_and_reexec_self
void mac_fork_and_reexec_self()
argv
char ** argv
Definition: kinit.cpp:141
launch
static pid_t launch(int argc, const char *_name, const char *args, const char *cwd=0, int envc=0, const char *envs=0, bool reset_env=false, const char *tty=0, bool avoid_loops=false, const char *startup_id_str="0")
Definition: kinit.cpp:467
QFile
QString::lastIndexOf
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
start_klauncher
static void start_klauncher()
Definition: kinit.cpp:1042
proctitle_init
void proctitle_init(int argc, char *argv[], char *envp[])
Set up the memory space for setting the proctitle.
Definition: proctitle.cpp:89
child_died
static void child_died(pid_t exit_pid, int exit_status)
Definition: kinit.cpp:261
handle_requests
static void handle_requests(pid_t waitForPid)
Definition: kinit.cpp:1317
QString::clear
void clear()
LAUNCHER_EXEC_NEW
#define LAUNCHER_EXEC_NEW
Definition: klauncher_cmds.h:164
QByteArray::resize
void resize(int size)
LAUNCHER_DEBUG_WAIT
#define LAUNCHER_DEBUG_WAIT
Definition: klauncher_cmds.h:113
QRegExp
kdeinit_library_path
static void kdeinit_library_path()
Definition: kinit.cpp:1430
QByteArray::indexOf
int indexOf(char ch, int from) const
proctitle_set
void proctitle_set(const char *fmt,...)
Change the process title.
Definition: proctitle.cpp:142
kglobal.h
main
int main(int argc, char **argv, char **envp)
Definition: kinit.cpp:1652
QString::number
QString number(int n, int base)
QString::fromLocal8Bit
QString fromLocal8Bit(const char *str, int size)
QList::append
void append(const T &value)
launcher_pid
pid_t launcher_pid
Definition: kinit.cpp:138
MAX_SOCK_FILE
#define MAX_SOCK_FILE
Definition: kinit.cpp:111
maxname
int maxname
Definition: kinit.cpp:128
d
static struct @0 d
debug_wait
bool debug_wait
Definition: kinit.cpp:144
QString::isEmpty
bool isEmpty() const
commandToString
const char * commandToString(int command)
Definition: klauncher_cmds.cpp:23
QByteArray::constData
const char * constData() const
QIODevice::readAll
QByteArray readAll()
QByteArray::replace
QByteArray & replace(int pos, int len, const char *after)
LAUNCHER_CHILD_DIED
#define LAUNCHER_CHILD_DIED
Definition: klauncher_cmds.h:57
KLibrary
X11_startup_notify_display
static Display * X11_startup_notify_display
Definition: kinit.cpp:108
X11fd
static int X11fd
Definition: kinit.cpp:105
LAUNCHER_TERMINATE_KDEINIT
#define LAUNCHER_TERMINATE_KDEINIT
Definition: klauncher_cmds.h:111
QString::endsWith
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QList::Iterator
typedef Iterator
QByteArray::truncate
void truncate(int pos)
KLibrary::fileName
QString fileName
QString
QList< QByteArray >
LAUNCHER_EXEC
#define LAUNCHER_EXEC
Definition: klauncher_cmds.h:33
QByteArray::mid
QByteArray mid(int pos, int len) const
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
setup_tty
static void setup_tty(const char *tty)
Definition: kinit.cpp:303
execpath_avoid_loops
QByteArray execpath_avoid_loops(const QByteArray &exec, int envc, const char *envs, bool avoid_loops)
Definition: kinit.cpp:403
QStringList
QLibrary::isLoaded
bool isLoaded() const
QList::end
iterator end()
QString::toLocal8Bit
QByteArray toLocal8Bit() const
extra_libs
static const char * extra_libs[]
Definition: kinit.cpp:91
s_instance
static KComponentData * s_instance
Definition: kinit.cpp:110
fork
pid_t fork
Definition: kinit.cpp:137
QLibrary::load
bool load()
QString::contains
bool contains(QChar ch, Qt::CaseSensitivity cs) const
QFile::size
virtual qint64 size() const
KSaveFile::finalize
bool finalize()
QLatin1Char
cleanup_fds
static void cleanup_fds()
Definition: kinit.cpp:177
sock_file
static char sock_file[MAX_SOCK_FILE]
Definition: kinit.cpp:112
LAUNCHER_KWRAPPER
#define LAUNCHER_KWRAPPER
Definition: klauncher_cmds.h:144
KStandardDirs::resourceDirs
QStringList resourceDirs(const char *type) const
init_startup_info
static void init_startup_info(KStartupInfoId &id, const char *bin, int envc, const char *envs)
Definition: kinit.cpp:366
launcher_died
static void launcher_died()
Definition: kinit.cpp:1059
environ
char ** environ
QString::replace
QString & replace(int position, int n, QChar after)
QByteArray::left
QByteArray left(int len) const
klauncher_header::cmd
long cmd
Definition: klauncher_cmds.h:27
X11display
static Display * X11display
Definition: kinit.cpp:106
close_fds
static void close_fds()
Definition: kinit.cpp:196
initXconnection
static int initXconnection()
Definition: kinit.cpp:1620
initpipe
int initpipe[2]
Definition: kinit.cpp:132
complete_startup_info
static void complete_startup_info(KStartupInfoId &id, pid_t pid)
Definition: kinit.cpp:384
QLibrary::resolve
void * resolve(const char *symbol)
QLatin1String
func
int(* func)(int, char *[])
Definition: kinit.cpp:142
KStandardDirs::locateLocal
static QString locateLocal(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
access
int access(const QString &path, int mode)
kstandarddirs.h
LAUNCHER_ERROR
#define LAUNCHER_ERROR
Definition: klauncher_cmds.h:76
read_socket
static int read_socket(int sock, char *buffer, int len)
Definition: kinit.cpp:1022
KComponentData::SkipMainComponentRegistration
KStandardDirs::findExe
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
get_current_desktop
static int get_current_desktop(Display *disp)
Definition: kinit.cpp:325
QList::ConstIterator
typedef ConstIterator
LAUNCHER_TERMINATE_KDE
#define LAUNCHER_TERMINATE_KDE
Definition: klauncher_cmds.h:104
exit_status
int exit_status
Definition: kinit.cpp:136
QLibrary
launcher_func
int(* launcher_func)(int)
Definition: kinit.cpp:143
KGlobal::hasMainComponent
bool hasMainComponent()
QString::length
int length() const
QByteArray::data
char * data()
QString::left
QString left(int n) const
QIODevice::write
qint64 write(const char *data, qint64 maxSize)
QString::fromLatin1
QString fromLatin1(const char *str, int size)
kdeinit_xio_errhandler
int kdeinit_xio_errhandler(Display *)
Definition: kinit.cpp:1505
DISPLAY
#define DISPLAY
Definition: kinit.cpp:115
LAUNCHER_SETENV
#define LAUNCHER_SETENV
Definition: klauncher_cmds.h:45
launcher
int launcher[2]
Definition: kinit.cpp:130
isdigit
#define isdigit(c)
X11_startup_notify_fd
static int X11_startup_notify_fd
Definition: kinit.cpp:107
kdeinit_x_errhandler
int kdeinit_x_errhandler(Display *, XErrorEvent *err)
Definition: kinit.cpp:1552
LAUNCHER_OK
#define LAUNCHER_OK
Definition: klauncher_cmds.h:67
errorMsg
QByteArray errorMsg
Definition: kinit.cpp:145
kcomponentdata.h
sig_child_handler
static void sig_child_handler(int)
Definition: kinit.cpp:804
klibrary.h
deadpipe
int deadpipe[2]
Definition: kinit.cpp:131
children
static struct child * children
Definition: kinit.cpp:157
klauncher_header::arg_length
long arg_length
Definition: klauncher_cmds.h:28
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
proctitle.h
wrapper
int wrapper
Definition: kinit.cpp:133
fd
int fd[2]
Definition: kinit.cpp:129
QList::begin
iterator begin()
PR_SET_NAME
#define PR_SET_NAME
Definition: kinit.cpp:71
KComponentData
accepted_fd
int accepted_fd
Definition: kinit.cpp:134
launcher_ok
bool launcher_ok
Definition: kinit.cpp:146
QFile::encodeName
QByteArray encodeName(const QString &fileName)
QFile::decodeName
QString decodeName(const QByteArray &localFileName)
n
int n
Definition: kinit.cpp:140
klauncher_header
Definition: klauncher_cmds.h:25
QLibrary::errorString
QString errorString() const
KComponentData::dirs
KStandardDirs * dirs() const
QString::toUtf8
QByteArray toUtf8() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:23:53 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KInit

Skip menu "KInit"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal