mirror of https://github.com/FreeRDP/FreeRDP
commit
498b88a1da
|
@ -822,6 +822,8 @@ int main(int argc, char* argv[])
|
|||
struct thread_data* data;
|
||||
rdpChanMan* chanman;
|
||||
|
||||
freerdp_handle_signals();
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
freerdp_chanman_global_init();
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <freerdp/utils/wait_obj.h>
|
||||
#include <freerdp/utils/args.h>
|
||||
#include <freerdp/utils/passphrase.h>
|
||||
#include <freerdp/utils/signal.h>
|
||||
|
||||
#include "test_utils.h"
|
||||
|
||||
|
@ -58,6 +59,7 @@ int add_utils_suite(void)
|
|||
add_test_function(wait_obj);
|
||||
add_test_function(args);
|
||||
add_test_function(passphrase_read);
|
||||
add_test_function(handle_signals);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -629,3 +631,42 @@ void test_passphrase_read(void)
|
|||
passphrase_read_prompts_to_stderr_when_no_tty();
|
||||
passphrase_read_reads_from_stdin_when_no_tty();
|
||||
}
|
||||
|
||||
void handle_signals_resets_terminal(void)
|
||||
{
|
||||
int status, masterfd;
|
||||
char* slavedevice;
|
||||
struct termios test_flags;
|
||||
pid_t child_pid;
|
||||
|
||||
masterfd = posix_openpt(O_RDWR|O_NOCTTY);
|
||||
|
||||
if (masterfd == -1
|
||||
|| grantpt (masterfd) == -1
|
||||
|| unlockpt (masterfd) == -1
|
||||
|| (slavedevice = ptsname (masterfd)) == NULL)
|
||||
CU_FAIL_FATAL("Could not create pty");
|
||||
|
||||
terminal_fildes = open(slavedevice, O_RDWR|O_NOCTTY);
|
||||
tcgetattr(terminal_fildes, &orig_flags);
|
||||
new_flags = orig_flags;
|
||||
new_flags.c_lflag &= ~ECHO;
|
||||
tcsetattr(terminal_fildes, TCSANOW, &new_flags);
|
||||
terminal_needs_reset = 1;
|
||||
|
||||
if((child_pid = fork()) == 0)
|
||||
{
|
||||
freerdp_handle_signals();
|
||||
raise(SIGINT);
|
||||
}
|
||||
while(wait(&status) != -1);
|
||||
tcgetattr(terminal_fildes, &test_flags);
|
||||
CU_ASSERT_EQUAL(orig_flags.c_lflag, test_flags.c_lflag);
|
||||
close(masterfd);
|
||||
close(terminal_fildes);
|
||||
}
|
||||
|
||||
void test_handle_signals(void)
|
||||
{
|
||||
handle_signals_resets_terminal();
|
||||
}
|
||||
|
|
|
@ -29,3 +29,4 @@ void test_load_plugin(void);
|
|||
void test_wait_obj(void);
|
||||
void test_args(void);
|
||||
void test_passphrase_read(void);
|
||||
void test_handle_signals(void);
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* Signal handling
|
||||
*
|
||||
* Copyright 2011 Shea Levy <shea@shealevy.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __UTILS_SIGNAL_H
|
||||
#define __UTILS_SIGNAL_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#ifndef _WIN32
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
|
||||
extern volatile sig_atomic_t terminal_needs_reset;
|
||||
extern int terminal_fildes;
|
||||
extern struct termios orig_flags;
|
||||
extern struct termios new_flags;
|
||||
#endif
|
||||
|
||||
FREERDP_API int freerdp_handle_signals(void);
|
||||
|
||||
#endif /* __UTILS_SIGNAL_H */
|
|
@ -39,6 +39,7 @@ set(FREERDP_UTILS_SRCS
|
|||
registry.c
|
||||
certstore.c
|
||||
semaphore.c
|
||||
signal.c
|
||||
sleep.c
|
||||
stopwatch.c
|
||||
stream.c
|
||||
|
|
|
@ -32,16 +32,16 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
|
|||
#include <sys/stat.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <freerdp/utils/signal.h>
|
||||
|
||||
char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
|
||||
{
|
||||
char read_char;
|
||||
char* buf_iter;
|
||||
char term_name[L_ctermid];
|
||||
int term_file, write_file, read_file, reset_terminal = 0;
|
||||
int term_file, write_file;
|
||||
ssize_t nbytes;
|
||||
size_t read_bytes = 0;
|
||||
struct termios orig_flags, no_echo_flags;
|
||||
|
||||
if (bufsiz == 0)
|
||||
{
|
||||
|
@ -54,29 +54,29 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
|
|||
|| (term_file = open(term_name, O_RDWR)) == -1)
|
||||
{
|
||||
write_file = STDERR_FILENO;
|
||||
read_file = STDIN_FILENO;
|
||||
terminal_fildes = STDIN_FILENO;
|
||||
}
|
||||
else
|
||||
{
|
||||
write_file = term_file;
|
||||
read_file = term_file;
|
||||
terminal_fildes = term_file;
|
||||
}
|
||||
|
||||
if (tcgetattr(read_file, &orig_flags) != -1)
|
||||
if (tcgetattr(terminal_fildes, &orig_flags) != -1)
|
||||
{
|
||||
reset_terminal = 1;
|
||||
no_echo_flags = orig_flags;
|
||||
no_echo_flags.c_lflag &= ~ECHO;
|
||||
no_echo_flags.c_lflag |= ECHONL;
|
||||
if (tcsetattr(read_file, TCSAFLUSH, &no_echo_flags) == -1)
|
||||
reset_terminal = 0;
|
||||
new_flags = orig_flags;
|
||||
new_flags.c_lflag &= ~ECHO;
|
||||
new_flags.c_lflag |= ECHONL;
|
||||
terminal_needs_reset = 1;
|
||||
if (tcsetattr(terminal_fildes, TCSAFLUSH, &new_flags) == -1)
|
||||
terminal_needs_reset = 0;
|
||||
}
|
||||
|
||||
if (write(write_file, prompt, strlen(prompt)) == (ssize_t) -1)
|
||||
goto error;
|
||||
|
||||
buf_iter = buf;
|
||||
while ((nbytes = read(read_file, &read_char, sizeof read_char)) == (sizeof read_char))
|
||||
while ((nbytes = read(terminal_fildes, &read_char, sizeof read_char)) == (sizeof read_char))
|
||||
{
|
||||
if (read_char == '\n')
|
||||
break;
|
||||
|
@ -93,16 +93,16 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
|
|||
if (nbytes == (ssize_t) -1)
|
||||
goto error;
|
||||
|
||||
if (reset_terminal)
|
||||
if (terminal_needs_reset)
|
||||
{
|
||||
if (tcsetattr(read_file, TCSADRAIN, &orig_flags) == -1)
|
||||
if (tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags) == -1)
|
||||
goto error;
|
||||
reset_terminal = 0;
|
||||
terminal_needs_reset = 0;
|
||||
}
|
||||
|
||||
if (read_file != STDIN_FILENO)
|
||||
if (terminal_fildes != STDIN_FILENO)
|
||||
{
|
||||
if (close(read_file) == -1)
|
||||
if (close(terminal_fildes) == -1)
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -113,10 +113,10 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
|
|||
int saved_errno = errno;
|
||||
buf_iter = NULL;
|
||||
read_char = '\0';
|
||||
if (reset_terminal)
|
||||
tcsetattr(read_file, TCSANOW, &orig_flags);
|
||||
if (read_file != STDIN_FILENO)
|
||||
close(read_file);
|
||||
if (terminal_needs_reset)
|
||||
tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags);
|
||||
if (terminal_fildes != STDIN_FILENO)
|
||||
close(terminal_fildes);
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* Signal handling
|
||||
*
|
||||
* Copyright 2011 Shea Levy <shea@shealevy.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <freerdp/utils/signal.h>
|
||||
#ifdef _WIN32
|
||||
#include <errno.h>
|
||||
int freerdp_handle_signals(void)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
volatile sig_atomic_t terminal_needs_reset = 0;
|
||||
int terminal_fildes = 0;
|
||||
struct termios orig_flags;
|
||||
struct termios new_flags;
|
||||
|
||||
static void fatal_handler(int signum)
|
||||
{
|
||||
struct sigaction default_sigaction;
|
||||
sigset_t this_mask;
|
||||
|
||||
if (terminal_needs_reset)
|
||||
tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags);
|
||||
|
||||
default_sigaction.sa_handler = SIG_DFL;
|
||||
sigfillset(&(default_sigaction.sa_mask));
|
||||
default_sigaction.sa_flags = 0;
|
||||
|
||||
sigaction(signum, &default_sigaction, NULL);
|
||||
|
||||
sigemptyset(&this_mask);
|
||||
sigaddset(&this_mask, signum);
|
||||
pthread_sigmask(SIG_UNBLOCK, &this_mask, NULL);
|
||||
raise(signum);
|
||||
}
|
||||
|
||||
int freerdp_handle_signals(void)
|
||||
{
|
||||
const int fatal_signals[] = {
|
||||
SIGABRT,
|
||||
SIGALRM,
|
||||
SIGBUS,
|
||||
SIGFPE,
|
||||
SIGHUP,
|
||||
SIGILL,
|
||||
SIGINT,
|
||||
SIGKILL,
|
||||
SIGPIPE,
|
||||
SIGQUIT,
|
||||
SIGSEGV,
|
||||
SIGSTOP,
|
||||
SIGTERM,
|
||||
SIGTSTP,
|
||||
SIGTTIN,
|
||||
SIGTTOU,
|
||||
SIGUSR1,
|
||||
SIGUSR2,
|
||||
#ifdef SIGPOLL
|
||||
SIGPOLL,
|
||||
#endif
|
||||
#ifdef SIGPROF
|
||||
SIGPROF,
|
||||
#endif
|
||||
#ifdef SIGSYS
|
||||
SIGSYS,
|
||||
#endif
|
||||
SIGTRAP,
|
||||
#ifdef SIGVTALRM
|
||||
SIGVTALRM,
|
||||
#endif
|
||||
SIGXCPU,
|
||||
SIGXFSZ
|
||||
};
|
||||
int signal_index;
|
||||
sigset_t orig_set;
|
||||
struct sigaction orig_sigaction, fatal_sigaction;
|
||||
|
||||
sigfillset(&(fatal_sigaction.sa_mask));
|
||||
sigdelset(&(fatal_sigaction.sa_mask), SIGCONT);
|
||||
pthread_sigmask(SIG_BLOCK, &(fatal_sigaction.sa_mask), &orig_set);
|
||||
|
||||
fatal_sigaction.sa_handler = fatal_handler;
|
||||
fatal_sigaction.sa_flags = 0;
|
||||
|
||||
for (signal_index = 0;
|
||||
signal_index < (sizeof fatal_signals / sizeof fatal_signals[0]);
|
||||
signal_index++)
|
||||
if (sigaction(fatal_signals[signal_index],
|
||||
NULL, &orig_sigaction) == 0)
|
||||
if (orig_sigaction.sa_handler != SIG_IGN)
|
||||
sigaction(fatal_signals[signal_index],
|
||||
&fatal_sigaction, NULL);
|
||||
|
||||
pthread_sigmask(SIG_SETMASK, &orig_set, NULL);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue