summaryrefslogtreecommitdiffstats
path: root/kinit/wrapper.c
diff options
context:
space:
mode:
Diffstat (limited to 'kinit/wrapper.c')
-rw-r--r--kinit/wrapper.c546
1 files changed, 0 insertions, 546 deletions
diff --git a/kinit/wrapper.c b/kinit/wrapper.c
deleted file mode 100644
index d22ba5080..000000000
--- a/kinit/wrapper.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
- This file is part of the KDE libraries
- Copyright (c) 1999 Waldo Bastian <bastian@kde.org>
- (c) 1999 Mario Weilguni <mweilguni@sime.com>
- (c) 2001 Lubos Lunak <l.lunak@kde.org>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License version 2 as published by the Free Software Foundation.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#include <config.h>
-
-#include "tdelauncher_cmds.h"
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/un.h>
-
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <signal.h>
-
-extern char **environ;
-
-static char *getDisplay()
-{
- const char *display;
- char *result;
- char *screen;
- char *colon;
- char *i;
-/*
- don't test for a value from tqglobal.h but instead distinguish
- Qt/X11 from Qt/Embedded by the fact that Qt/E apps have -DQWS
- on the commandline (which in tqglobal.h however triggers Q_WS_QWS,
- but we don't want to include that here) (Simon)
-#ifdef Q_WS_X11
- */
-#if !defined(QWS)
- display = getenv("DISPLAY");
-#else
- display = getenv("QWS_DISPLAY");
-#endif
- if (!display || !*display)
- {
- display = ":0";
- }
- result = malloc(strlen(display)+1);
- if (result == NULL)
- return NULL;
-
- strcpy(result, display);
- screen = strrchr(result, '.');
- colon = strrchr(result, ':');
- if (screen && (screen > colon))
- *screen = '\0';
- while((i = strchr(result, ':')))
- *i = '_';
- return result;
-}
-
-/*
- * Write 'len' bytes from 'buffer' into 'sock'.
- * returns 0 on success, -1 on failure.
- */
-static int write_socket(int sock, char *buffer, int len)
-{
- ssize_t result;
- int bytes_left = len;
- while ( bytes_left > 0)
- {
- result = write(sock, buffer, bytes_left);
- if (result > 0)
- {
- buffer += result;
- bytes_left -= result;
- }
- else if (result == 0)
- return -1;
- else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
- return -1;
- }
- return 0;
-}
-
-/*
- * Read 'len' bytes from 'sock' into 'buffer'.
- * returns 0 on success, -1 on failure.
- */
-static int read_socket(int sock, char *buffer, int len)
-{
- ssize_t result;
- int bytes_left = len;
- while ( bytes_left > 0)
- {
- result = read(sock, buffer, bytes_left);
- if (result > 0)
- {
- buffer += result;
- bytes_left -= result;
- }
- else if (result == 0)
- return -1;
- else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
- return -1;
- }
- return 0;
-}
-
-static int openSocket()
-{
- kde_socklen_t socklen;
- int s;
- struct sockaddr_un server;
-#define MAX_SOCK_FILE 255
- char sock_file[MAX_SOCK_FILE + 1];
- const char *home_dir = getenv("HOME");
- const char *kde_home = getenv("TDEHOME");
- char *display;
-
- sock_file[0] = sock_file[MAX_SOCK_FILE] = 0;
-
- if (!kde_home || !kde_home[0])
- {
- kde_home = "~/.trinity/";
- }
-
- if (kde_home[0] == '~')
- {
- if (!home_dir || !home_dir[0])
- {
- fprintf(stderr, "[tdeinit wrapper] Warning: $HOME not set!\n");
- return -1;
- }
- if (strlen(home_dir) > (MAX_SOCK_FILE-100))
- {
- fprintf(stderr, "[tdeinit wrapper] Warning: Home directory path too long!\n");
- return -1;
- }
- kde_home++;
- strncpy(sock_file, home_dir, MAX_SOCK_FILE);
- }
- strncat(sock_file, kde_home, MAX_SOCK_FILE - strlen(sock_file));
-
- /** Strip trailing '/' **/
- if ( sock_file[strlen(sock_file)-1] == '/')
- sock_file[strlen(sock_file)-1] = 0;
-
- strncat(sock_file, "/socket-", MAX_SOCK_FILE - strlen(sock_file));
- if( getenv("XAUTHLOCALHOSTNAME"))
- strncat(sock_file, getenv("XAUTHLOCALHOSTNAME"), MAX_SOCK_FILE - strlen(sock_file) - 1);
- else if (gethostname(sock_file+strlen(sock_file), MAX_SOCK_FILE - strlen(sock_file) - 1) != 0)
- {
- perror("[tdeinit wrapper] Warning: Could not determine hostname: ");
- return -1;
- }
- sock_file[sizeof(sock_file)-1] = '\0';
-
- /* append $DISPLAY */
- display = getDisplay();
- if (display == NULL)
- {
- fprintf(stderr, "[tdeinit wrapper] Error: Could not determine display.\n");
- return -1;
- }
-
- if (strlen(sock_file)+strlen(display)+strlen("/tdeinit_")+2 > MAX_SOCK_FILE)
- {
- fprintf(stderr, "[tdeinit wrapper] Warning: Socket name will be too long.\n");
- free (display);
- return -1;
- }
- strcat(sock_file, "/tdeinit_");
- strcat(sock_file, display);
- free(display);
-
- if (strlen(sock_file) >= sizeof(server.sun_path))
- {
- fprintf(stderr, "[tdeinit wrapper] Warning: Path of socket file exceeds UNIX_PATH_MAX.\n");
- return -1;
- }
-
- /*
- * create the socket stream
- */
- s = socket(PF_UNIX, SOCK_STREAM, 0);
- if (s < 0)
- {
- perror("[tdeinit wrapper] Warning: socket creation failed: ");
- return -1;
- }
-
- server.sun_family = AF_UNIX;
- strcpy(server.sun_path, sock_file);
- socklen = sizeof(server);
- if(connect(s, (struct sockaddr *)&server, socklen) == -1)
- {
- perror("[tdeinit wrapper] Warning: socket connection failed: ");
- close(s);
- return -1;
- }
- return s;
-}
-
-static pid_t kwrapper_pid;
-static volatile pid_t got_sig; /* = 0 */
-static pid_t last_sig; /* = 0 */
-
-static void sig_pass_handler( int signo );
-static void setup_signals( void );
-
-static void setup_signal_handler( int signo, int clean )
-{
- struct sigaction sa;
- if( clean )
- sa.sa_handler = SIG_DFL;
- else
- sa.sa_handler = sig_pass_handler;
- sigemptyset( &sa.sa_mask );
- sigaddset( &sa.sa_mask, signo );
- sa.sa_flags = 0; /* don't use SA_RESTART */
- sigaction( signo, &sa, 0 );
-}
-
-static void sig_pass_handler( int signo )
-{
- int save_errno = errno;
- if( signo == SIGTSTP )
- kill( kwrapper_pid, SIGSTOP ); /* pass the signal to the real process */
- else /* SIGTSTP wouldn't work ... I don't think is much */
- kill( kwrapper_pid, signo ); /* of a problem */
- got_sig = signo;
- if( got_sig == SIGCONT )
- setup_signals(); /* restore signals */
- errno = save_errno;
-}
-
-static void setup_signals()
-{
- setup_signal_handler( SIGHUP, 0 );
- setup_signal_handler( SIGINT, 0 );
- setup_signal_handler( SIGQUIT, 0 );
- setup_signal_handler( SIGILL, 0 ); /* e.g. this one is probably doesn't make sense to pass */
- setup_signal_handler( SIGABRT, 0 ); /* but anyway ... */
- setup_signal_handler( SIGFPE, 0 );
- /* SIGKILL can't be handled :( */
- setup_signal_handler( SIGSEGV, 0 );
- setup_signal_handler( SIGPIPE, 0 );
- setup_signal_handler( SIGALRM, 0 );
- setup_signal_handler( SIGTERM, 0 );
- setup_signal_handler( SIGUSR1, 0 );
- setup_signal_handler( SIGUSR2, 0 );
- setup_signal_handler( SIGCHLD, 0 ); /* is this a good idea ??? */
- setup_signal_handler( SIGCONT, 0 ); /* SIGSTOP can't be handled, but SIGTSTP and SIGCONT can */
- /* SIGSTOP */ /* which should be enough */
- setup_signal_handler( SIGTSTP, 0 );
- setup_signal_handler( SIGTTIN, 0 ); /* is this a good idea ??? */
- setup_signal_handler( SIGTTOU, 0 ); /* is this a good idea ??? */
- /* some more ? */
-}
-
-static void kwrapper_run( pid_t pid )
-{
- kwrapper_pid = pid;
- setup_signals();
- for(;;)
- {
- sleep( 1 ); /* poll and see if the real process is still alive */
- if( got_sig != last_sig ) /* did we get a signal ? */
- {
- last_sig = got_sig;
- if( got_sig == SIGCHLD )
- ; /* nothing, ignore */
- else if( got_sig == SIGCONT )
- ; /* done in signal handler */
- else /* do the default action ( most of them quit the app ) */
- {
- setup_signal_handler( got_sig, 1 );
- raise( got_sig ); /* handle the signal again */
- }
- }
- if( kill( pid, 0 ) < 0 )
- break;
- }
- /* I'm afraid it won't be that easy to get the return value ... */
-}
-
-int main(int argc, char **argv)
-{
- int i;
- int wrapper = 0;
- int ext_wrapper = 0;
- int kwrapper = 0;
- long arg_count;
- long env_count;
- tdelauncher_header header;
- char *start, *p, *buffer;
- char cwd[8192];
- const char *tty = NULL;
- long avoid_loops = 0;
- const char* startup_id = NULL;
- int sock;
-
- long size = 0;
-
- start = argv[0];
- p = start + strlen(argv[0]);
- while (--p > start)
- {
- if (*p == '/') break;
- }
- if ( p > start)
- p++;
- start = p;
-
- if (strcmp(start, "tdeinit_wrapper") == 0)
- wrapper = 1;
- else if (strcmp(start, "kshell") == 0)
- ext_wrapper = 1;
- else if (strcmp(start, "kwrapper") == 0)
- kwrapper = 1;
- else if (strcmp(start, "tdeinit_shutdown") == 0)
- {
- if( argc > 1)
- {
- fprintf(stderr, "[tdeinit wrapper] Usage: %s\n\n", start);
- fprintf(stderr, "[tdeinit wrapper] Shuts down tdeinit master process and terminates all processes spawned from it.\n");
- exit( 255 );
- }
- sock = openSocket();
- if( sock < 0 )
- {
- fprintf( stderr, "[tdeinit wrapper] Error: Can't contact tdeinit!\n" );
- exit( 255 );
- }
- header.cmd = LAUNCHER_TERMINATE_KDE;
- header.arg_length = 0;
- write_socket(sock, (char *) &header, sizeof(header));
- return 0;
- }
-
- if (wrapper || ext_wrapper || kwrapper)
- {
- argv++;
- argc--;
- if (argc < 1)
- {
- fprintf(stderr, "[tdeinit wrapper] Usage: %s <application> [<args>]\n", start);
- exit(255); /* usage should be documented somewhere ... */
- }
- start = argv[0];
- }
-
- sock = openSocket();
- if( sock < 0 ) /* couldn't contact tdeinit, start argv[ 0 ] directly */
- {
- execvp( argv[ 0 ], argv );
- fprintf( stderr, "[tdeinit wrapper] Error: Can't run %s !\n", argv[ 0 ] );
- exit( 255 );
- }
-
- if( !wrapper && !ext_wrapper && !kwrapper )
- { /* was called as a symlink */
- avoid_loops = 1;
-#if defined(WE_ARE_KWRAPPER)
- kwrapper = 1;
-#elif defined(WE_ARE_KSHELL)
- ext_wrapper = 1;
-#else
- wrapper = 1;
-#endif
- }
-
- arg_count = argc;
-
- size += sizeof(long); /* Number of arguments*/
-
- size += strlen(start)+1; /* Size of first argument. */
-
- for(i = 1; i < argc; i++)
- {
- size += strlen(argv[i])+1;
- }
- if( wrapper )
- {
- size += sizeof(long); /* empty envs */
- }
- if (ext_wrapper || kwrapper)
- {
- if (!getcwd(cwd, 8192))
- cwd[0] = '\0';
- size += strlen(cwd)+1;
-
- env_count = 0;
- size += sizeof(long); /* Number of env.vars. */
-
- for(; environ[env_count] ; env_count++)
- {
- int l = strlen(environ[env_count])+1;
- size += l;
- }
-
- if( kwrapper )
- {
- tty = ttyname(1);
- if (!tty || !isatty(2))
- tty = "";
- size += strlen(tty)+1;
- }
- }
-
- size += sizeof( avoid_loops );
-
- if( !wrapper )
- {
- startup_id = getenv( "DESKTOP_STARTUP_ID" );
- if( startup_id == NULL )
- startup_id = "";
- size += strlen( startup_id ) + 1;
- }
-
- if (wrapper)
- header.cmd = LAUNCHER_EXEC_NEW;
- else if (kwrapper)
- header.cmd = LAUNCHER_KWRAPPER;
- else
- header.cmd = LAUNCHER_SHELL;
- header.arg_length = size;
- write_socket(sock, (char *) &header, sizeof(header));
-
- buffer = (char *) malloc(size);
- if (buffer == NULL)
- {
- fprintf(stderr, "[tdeinit wrapper] Error: malloc() failed.");
- exit(255);
- }
- p = buffer;
-
- memcpy(p, &arg_count, sizeof(arg_count));
- p += sizeof(arg_count);
-
- memcpy(p, start, strlen(start)+1);
- p += strlen(start)+1;
-
- for(i = 1; i < argc; i++)
- {
- memcpy(p, argv[i], strlen(argv[i])+1);
- p += strlen(argv[i])+1;
- }
-
- if( wrapper )
- {
- long dummy = 0;
- memcpy(p, &dummy, sizeof(dummy)); /* empty envc */
- p+= sizeof( dummy );
- }
- if (ext_wrapper || kwrapper)
- {
- memcpy(p, cwd, strlen(cwd)+1);
- p+= strlen(cwd)+1;
-
- memcpy(p, &env_count, sizeof(env_count));
- p+= sizeof(env_count);
-
- for(i = 0; i < env_count; i++)
- {
- int l = strlen(environ[i])+1;
- memcpy(p, environ[i], l);
- p += l;
- }
-
- if( kwrapper )
- {
- memcpy(p, tty, strlen(tty)+1);
- p+=strlen(tty)+1;
- }
- }
-
- memcpy( p, &avoid_loops, sizeof( avoid_loops ));
- p += sizeof( avoid_loops );
-
- if( !wrapper )
- {
- memcpy(p, startup_id, strlen(startup_id)+1);
- p+= strlen(startup_id)+1;
- }
-
- if( p - buffer != size ) /* should fail only if you change this source and do */
- /* a stupid mistake, it should be assert() actually */
- {
- fprintf(stderr, "[tdeinit wrapper] Oops. Invalid format.\n");
- exit(255);
- }
-
- write_socket(sock, buffer, size);
- free( buffer );
-
- if (read_socket(sock, (char *) &header, sizeof(header))==-1)
- {
- fprintf(stderr, "[tdeinit wrapper] Communication error.\n");
- exit(255);
- }
-
- if (header.cmd == LAUNCHER_OK)
- {
- long pid;
- buffer = (char *) malloc(header.arg_length);
- if (buffer == NULL)
- {
- fprintf(stderr, "[tdeinit wrapper] Error: malloc() failed\n");
- exit(255);
- }
- read_socket(sock, buffer, header.arg_length);
- pid = *((long *) buffer);
- if ( !(!kwrapper) )
- kwrapper_run( pid );
- }
- else if (header.cmd == LAUNCHER_ERROR)
- {
- fprintf(stderr, "[tdeinit wrapper] Could not launch '%s'.\n", start);
- exit(255);
- }
- else
- {
- fprintf(stderr, "[tdeinit wrapper] Unexpected response (response = %ld).\n", header.cmd);
- exit(255);
- }
- exit(0);
-}