diff options
Diffstat (limited to 'nx-X11/programs/Xserver/hw/nxagent/Dialog.c')
-rw-r--r-- | nx-X11/programs/Xserver/hw/nxagent/Dialog.c | 563 |
1 files changed, 563 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Dialog.c b/nx-X11/programs/Xserver/hw/nxagent/Dialog.c new file mode 100644 index 000000000..c1db78344 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Dialog.c @@ -0,0 +1,563 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include "scrnintstr.h" +#include "Agent.h" + +#include <X11/Xlib.h> + +#include "opaque.h" + +#include "Args.h" +#include "Display.h" +#include "Dialog.h" + +#include "NX.h" +#include "NXlib.h" +#include "NXalert.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +int nxagentKillDialogPid = 0; +int nxagentSuspendDialogPid = 0; +int nxagentRootlessDialogPid = 0; +int nxagentPulldownDialogPid = 0; +int nxagentFontsReplacementDialogPid = 0; +int nxagentEnableRandRModeDialogPid = 0; +int nxagentDisableRandRModeDialogPid = 0; +int nxagentEnableDeferModePid = 0; +int nxagentDisableDeferModePid = 0; +int nxagentDisableXkbPid = 0; + +static int nxagentFailedReconnectionDialogPid = 0; + +char nxagentPulldownWindow[16]; + +char nxagentFailedReconnectionMessage[256]; + +void nxagentResetDialog(int pid) +{ + if (pid == nxagentRootlessDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting rootless dialog pid [%d].\n", nxagentRootlessDialogPid); + #endif + + nxagentRootlessDialogPid = 0; + } + else if (pid == nxagentPulldownDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting pulldown dialog pid [%d].\n", nxagentPulldownDialogPid); + #endif + + nxagentPulldownDialogPid = 0; + } + else if (pid == nxagentFontsReplacementDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentFontsReplacementDialog: Resetting fonts replacement dialog pid [%d].\n", + nxagentFontsReplacementDialogPid); + #endif + + nxagentFontsReplacementDialogPid = 0; + } + else if (pid == nxagentKillDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting kill dialog pid [%d].\n", nxagentKillDialogPid); + #endif + + nxagentKillDialogPid = 0; + } + else if (pid == nxagentSuspendDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting suspend dialog pid [%d].\n", nxagentSuspendDialogPid); + #endif + + nxagentSuspendDialogPid = 0; + } + else if (pid == nxagentFailedReconnectionDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting Failed Reconnection dialog pid [%d].\n", + nxagentFailedReconnectionDialogPid); + #endif + + nxagentFailedReconnectionDialogPid = 0; + } + else if (pid == nxagentEnableRandRModeDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting RandR mode dialog pid [%d].\n", + nxagentEnableRandRModeDialogPid); + #endif + + nxagentEnableRandRModeDialogPid = 0; + } + else if (pid == nxagentDisableRandRModeDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting NoRandR mode dialog pid [%d].\n", + nxagentDisableRandRModeDialogPid); + #endif + + nxagentDisableRandRModeDialogPid = 0; + } + else if (pid == nxagentEnableDeferModePid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting enable defer mode dialog pid [%d].\n", + nxagentEnableDeferModePid); + #endif + + nxagentEnableDeferModePid = 0; + } + else if (pid == nxagentDisableDeferModePid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting disable defer mode dialog pid [%d].\n", + nxagentDisableDeferModePid); + #endif + + nxagentDisableDeferModePid = 0; + } + else if (pid == nxagentDisableXkbPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting disable XKB dialog pid [%d].\n", + nxagentDisableXkbPid); + #endif + + nxagentDisableXkbPid = 0; + } +} + +void nxagentLaunchDialog(DialogType dialogType) +{ + char dialogDisplay[256]; + sigset_t set, oldSet; + int *pid; + char *type; + char *message; + int local; + const char *window = NULL; + + switch (dialogType) + { + case DIALOG_KILL_SESSION: + { + message = DIALOG_KILL_SESSION_MESSAGE; + type = DIALOG_KILL_SESSION_TYPE; + local = DIALOG_KILL_SESSION_LOCAL; + pid = &nxagentKillDialogPid; + + break; + } + case DIALOG_SUSPEND_SESSION: + { + message = DIALOG_SUSPEND_SESSION_MESSAGE; + type = DIALOG_SUSPEND_SESSION_TYPE; + local = DIALOG_SUSPEND_SESSION_LOCAL; + pid = &nxagentSuspendDialogPid; + + break; + } + case DIALOG_ROOTLESS: + { + message = DIALOG_ROOTLESS_MESSAGE; + type = DIALOG_ROOTLESS_TYPE; + local = DIALOG_ROOTLESS_LOCAL; + pid = &nxagentRootlessDialogPid; + + break; + } + case DIALOG_PULLDOWN: + { + message = DIALOG_PULLDOWN_MESSAGE; + type = DIALOG_PULLDOWN_TYPE; + local = DIALOG_PULLDOWN_LOCAL; + pid = &nxagentPulldownDialogPid; + window = nxagentPulldownWindow; + + break; + } + case DIALOG_FONT_REPLACEMENT: + { + message = DIALOG_FONT_REPLACEMENT_MESSAGE; + type = DIALOG_FONT_REPLACEMENT_TYPE; + local = DIALOG_FONT_REPLACEMENT_LOCAL; + pid = &nxagentFontsReplacementDialogPid; + + break; + } + case DIALOG_FAILED_RECONNECTION: + { + message = DIALOG_FAILED_RECONNECTION_MESSAGE; + type = DIALOG_FAILED_RECONNECTION_TYPE; + local = DIALOG_FAILED_RECONNECTION_LOCAL; + pid = &nxagentFailedReconnectionDialogPid; + + break; + } + case DIALOG_ENABLE_DESKTOP_RESIZE_MODE: + { + message = DIALOG_ENABLE_DESKTOP_RESIZE_MODE_MESSAGE; + type = DIALOG_ENABLE_DESKTOP_RESIZE_MODE_TYPE; + local = DIALOG_ENABLE_DESKTOP_RESIZE_MODE_LOCAL; + pid = &nxagentEnableRandRModeDialogPid; + + break; + } + case DIALOG_DISABLE_DESKTOP_RESIZE_MODE: + { + message = DIALOG_DISABLE_DESKTOP_RESIZE_MODE_MESSAGE; + type = DIALOG_DISABLE_DESKTOP_RESIZE_MODE_TYPE; + local = DIALOG_DISABLE_DESKTOP_RESIZE_MODE_LOCAL; + pid = &nxagentDisableRandRModeDialogPid; + + break; + } + case DIALOG_ENABLE_DEFER_MODE: + { + message = DIALOG_ENABLE_DEFER_MODE_MESSAGE; + type = DIALOG_ENABLE_DEFER_MODE_TYPE; + local = DIALOG_ENABLE_DEFER_MODE_LOCAL; + pid = &nxagentEnableDeferModePid; + + break; + } + case DIALOG_DISABLE_DEFER_MODE: + { + message = DIALOG_DISABLE_DEFER_MODE_MESSAGE; + type = DIALOG_DISABLE_DEFER_MODE_TYPE; + local = DIALOG_DISABLE_DEFER_MODE_LOCAL; + pid = &nxagentDisableDeferModePid; + + break; + } + case DIALOG_DISABLE_XKB: + { + message = DIALOG_DISABLE_XKB_MESSAGE; + type = DIALOG_DISABLE_XKB_TYPE; + local = DIALOG_DISABLE_XKB_LOCAL; + pid = &nxagentDisableXkbPid; + + break; + } + default: + { + #ifdef WARNING + fprintf(stderr, "nxagentLaunchDialog: Unknown Dialog type [%d].\n", dialogType); + #endif + + return; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentLaunchDialog: Launching dialog type [%d] message [%s].\n", type, message); + #endif + + if (dialogType == DIALOG_FAILED_RECONNECTION) + { + strncpy(dialogDisplay, nxagentDisplayName, 255); + } + else + { + strcpy(dialogDisplay, ":"); + strncat(dialogDisplay, display, 254); + } + + *(dialogDisplay + 255) = '\0'; + + /* + * We don't want to receive SIGCHLD + * before we store the child pid. + */ + + sigemptyset(&set); + + sigaddset(&set, SIGCHLD); + + sigprocmask(SIG_BLOCK, &set, &oldSet); + + *pid = NXTransDialog(nxagentDialogName, message, window, + type, local, dialogDisplay); + + #ifdef TEST + fprintf(stderr, "nxagentLaunchDialog: Launched dialog %s with pid [%d] on display %s.\n", + DECODE_DIALOG_TYPE(dialogType), *pid, dialogDisplay); + #endif + + *dialogDisplay = '\0'; + + /* + * Restore the previous set of + * blocked signal. + */ + + sigprocmask(SIG_SETMASK, &oldSet, NULL); +} + +void nxagentPulldownDialog(Window wid) +{ + snprintf(nxagentPulldownWindow, 15, "%ld", (long int) wid); + nxagentPulldownWindow[15] = 0; + + #ifdef TEST + fprintf(stderr, "nxagentPulldownDialog: Going to launch pulldown " + "dialog on window [%s].\n", nxagentPulldownWindow); + #endif + + nxagentLaunchDialog(DIALOG_PULLDOWN); + + nxagentPulldownWindow[0] = 0; +} + +void nxagentFailedReconnectionDialog(int alert, char *error) +{ + if (alert == 0) + { + #ifdef WARNING + fprintf(stderr, "nxagentFailedReconnectionDialog: WARNING! No valid alert provided. " + "Using the default.\n"); + #endif + + alert = FAILED_RESUME_DISPLAY_ALERT; + } + + if (NXDisplayError(nxagentDisplay) == 0 && + NXTransRunning(NX_FD_ANY) == 1) + { + NXTransAlert(alert, NX_ALERT_REMOTE); + + /* + * Make it possible to interrupt the + * loop with a signal. + */ + + while (NXDisplayError(nxagentDisplay) == 0 && + NXTransRunning(NX_FD_ANY) == 1) + { + struct timeval timeout; + + timeout.tv_sec = 30; + timeout.tv_usec = 0; + + NXTransContinue(&timeout); + } + } + else + { + int pid; + int status; + int options = 0; + + snprintf(nxagentFailedReconnectionMessage, 255, "Reconnection failed: %s", error); + + *(nxagentFailedReconnectionMessage + 255) = '\0'; + + nxagentLaunchDialog(DIALOG_FAILED_RECONNECTION); + + while ((pid = waitpid(nxagentFailedReconnectionDialogPid, &status, options)) == -1 && + errno == EINTR); + + if (pid == -1) + { + if (errno == ECHILD) + { + #ifdef WARNING + fprintf(stderr, "nxagentFailedReconnectionDialog: Got ECHILD waiting for child [%d].\n", + nxagentFailedReconnectionDialogPid); + #endif + + nxagentFailedReconnectionDialogPid = 0; + } + else + { + fprintf(stderr, "nxagentFailedReconnectionDialog: PANIC! Got unexpected error [%s] waiting " + "for child [%d].\n", strerror(errno), nxagentFailedReconnectionDialogPid); + } + } + else if (pid > 0) + { + if (WIFSTOPPED(status)) + { + #ifdef WARNING + fprintf(stderr, "nxagentFailedReconnectionDialog: Child process [%d] was stopped " + "with signal [%d].\n", pid, (WSTOPSIG(status))); + #endif + } + else + { + #ifdef WARNING + + if (WIFEXITED(status)) + { + fprintf(stderr, "nxagentFailedReconnectionDialog: Child process [%d] exited " + "with status [%d].\n", pid, (WEXITSTATUS(status))); + } + else if (WIFSIGNALED(status)) + { + fprintf(stderr, "nxagentFailedReconnectionDialog: Child process [%d] died " + "because of signal [%d].\n", pid, (WTERMSIG(status))); + } + + #endif + + nxagentResetDialog(pid); + } + } + #ifdef WARNING + else if (pid == 0) + { + fprintf(stderr, "nxagentFailedReconnectionDialog: No own child process exited.\n"); + } + #endif + } +} + +void nxagentTerminateDialog(DialogType type) +{ + int pid; + + switch (type) + { + case DIALOG_KILL_SESSION: + { + pid = nxagentKillDialogPid; + + break; + } + case DIALOG_SUSPEND_SESSION: + { + pid = nxagentSuspendDialogPid; + + break; + } + case DIALOG_ROOTLESS: + { + pid = nxagentRootlessDialogPid; + + break; + } + case DIALOG_PULLDOWN: + { + pid = nxagentPulldownDialogPid; + + break; + } + case DIALOG_FONT_REPLACEMENT: + { + pid = nxagentFontsReplacementDialogPid; + + break; + } + case DIALOG_FAILED_RECONNECTION: + { + pid = nxagentFailedReconnectionDialogPid; + + break; + } + case DIALOG_ENABLE_DESKTOP_RESIZE_MODE: + { + pid = nxagentEnableRandRModeDialogPid; + + break; + } + case DIALOG_DISABLE_DESKTOP_RESIZE_MODE: + { + pid = nxagentDisableRandRModeDialogPid; + + break; + } + case DIALOG_ENABLE_DEFER_MODE: + { + pid = nxagentEnableDeferModePid; + + break; + } + case DIALOG_DISABLE_DEFER_MODE: + { + pid = nxagentDisableDeferModePid; + + break; + } + case DIALOG_DISABLE_XKB: + { + pid = nxagentDisableXkbPid; + + break; + } + default: + { + #ifdef WARNING + fprintf(stderr, "nxagentTerminateDialog: Unknown dialog type [%d].\n", type); + #endif + + return; + } + } + + if (pid > 0) + { + if (kill(pid, SIGTERM) == -1) + { + #ifdef WARNING + fprintf(stderr, "nxagentTerminateDialog: Failed to terminate dialog pid [%d]: %s.\n", + pid, strerror(errno)); + #endif + } + } + #ifdef DEBUG + else + { + fprintf(stderr, "nxagentTerminateDialog: Dialog type [%d] is not running.\n", + type); + } + #endif +} + +void nxagentTerminateDialogs() +{ + DialogType type; + + #ifdef DEBUG + fprintf(stderr, "nxagentTerminateDialogs: Terminating all the running dialogs.\n"); + #endif + + for (type = DIALOG_FIRST_TAG; type < DIALOG_LAST_TAG; type++) + { + nxagentTerminateDialog(type); + } +} |