Merge branch 'master' of github.com:FreeRDP/FreeRDP

This commit is contained in:
Marc-André Moreau 2011-09-29 00:33:28 -04:00
commit 98d1ef12a5
7 changed files with 217 additions and 21 deletions

View File

@ -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();

View File

@ -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();
}

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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;
} }

115
libfreerdp-utils/signal.c Normal file
View File

@ -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