mirror of https://github.com/FreeRDP/FreeRDP
Merge branch 'master' of github.com:FreeRDP/FreeRDP
This commit is contained in:
commit
98d1ef12a5
|
@ -904,6 +904,8 @@ int main(int argc, char* argv[])
|
||||||
struct thread_data* data;
|
struct thread_data* data;
|
||||||
rdpChanMan* chanman;
|
rdpChanMan* chanman;
|
||||||
|
|
||||||
|
freerdp_handle_signals();
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
freerdp_chanman_global_init();
|
freerdp_chanman_global_init();
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <freerdp/utils/wait_obj.h>
|
#include <freerdp/utils/wait_obj.h>
|
||||||
#include <freerdp/utils/args.h>
|
#include <freerdp/utils/args.h>
|
||||||
#include <freerdp/utils/passphrase.h>
|
#include <freerdp/utils/passphrase.h>
|
||||||
|
#include <freerdp/utils/signal.h>
|
||||||
|
|
||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
|
|
||||||
|
@ -58,6 +59,7 @@ int add_utils_suite(void)
|
||||||
add_test_function(wait_obj);
|
add_test_function(wait_obj);
|
||||||
add_test_function(args);
|
add_test_function(args);
|
||||||
add_test_function(passphrase_read);
|
add_test_function(passphrase_read);
|
||||||
|
add_test_function(handle_signals);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -629,3 +631,42 @@ void test_passphrase_read(void)
|
||||||
passphrase_read_prompts_to_stderr_when_no_tty();
|
passphrase_read_prompts_to_stderr_when_no_tty();
|
||||||
passphrase_read_reads_from_stdin_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_wait_obj(void);
|
||||||
void test_args(void);
|
void test_args(void);
|
||||||
void test_passphrase_read(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
|
registry.c
|
||||||
certstore.c
|
certstore.c
|
||||||
semaphore.c
|
semaphore.c
|
||||||
|
signal.c
|
||||||
sleep.c
|
sleep.c
|
||||||
stopwatch.c
|
stopwatch.c
|
||||||
stream.c
|
stream.c
|
||||||
|
|
|
@ -32,16 +32,16 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <freerdp/utils/signal.h>
|
||||||
|
|
||||||
char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
|
char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
|
||||||
{
|
{
|
||||||
char read_char;
|
char read_char;
|
||||||
char* buf_iter;
|
char* buf_iter;
|
||||||
char term_name[L_ctermid];
|
char term_name[L_ctermid];
|
||||||
int term_file, write_file, read_file, reset_terminal = 0;
|
int term_file, write_file;
|
||||||
ssize_t nbytes;
|
ssize_t nbytes;
|
||||||
size_t read_bytes = 0;
|
size_t read_bytes = 0;
|
||||||
struct termios orig_flags, no_echo_flags;
|
|
||||||
|
|
||||||
if (bufsiz == 0)
|
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)
|
|| (term_file = open(term_name, O_RDWR)) == -1)
|
||||||
{
|
{
|
||||||
write_file = STDERR_FILENO;
|
write_file = STDERR_FILENO;
|
||||||
read_file = STDIN_FILENO;
|
terminal_fildes = STDIN_FILENO;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
write_file = term_file;
|
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;
|
new_flags = orig_flags;
|
||||||
no_echo_flags = orig_flags;
|
new_flags.c_lflag &= ~ECHO;
|
||||||
no_echo_flags.c_lflag &= ~ECHO;
|
new_flags.c_lflag |= ECHONL;
|
||||||
no_echo_flags.c_lflag |= ECHONL;
|
terminal_needs_reset = 1;
|
||||||
if (tcsetattr(read_file, TCSAFLUSH, &no_echo_flags) == -1)
|
if (tcsetattr(terminal_fildes, TCSAFLUSH, &new_flags) == -1)
|
||||||
reset_terminal = 0;
|
terminal_needs_reset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write(write_file, prompt, strlen(prompt)) == (ssize_t) -1)
|
if (write(write_file, prompt, strlen(prompt)) == (ssize_t) -1)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
buf_iter = buf;
|
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')
|
if (read_char == '\n')
|
||||||
break;
|
break;
|
||||||
|
@ -93,16 +93,16 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
|
||||||
if (nbytes == (ssize_t) -1)
|
if (nbytes == (ssize_t) -1)
|
||||||
goto error;
|
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;
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,10 +113,10 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
|
||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
buf_iter = NULL;
|
buf_iter = NULL;
|
||||||
read_char = '\0';
|
read_char = '\0';
|
||||||
if (reset_terminal)
|
if (terminal_needs_reset)
|
||||||
tcsetattr(read_file, TCSANOW, &orig_flags);
|
tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags);
|
||||||
if (read_file != STDIN_FILENO)
|
if (terminal_fildes != STDIN_FILENO)
|
||||||
close(read_file);
|
close(terminal_fildes);
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
return NULL;
|
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