1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-14 00:19:50 +02:00

2005-01-26 Moritz Schulte <moritz@g10code.com>

* command-ssh.c: New file.
	* Makefile.am (gpg_agent_SOURCES): New source file: command-ssh.c.

	* findkey.c (modify_description): New function.
	(agent_key_from_file): Support comment field in key s-expressions.

	* gpg-agent.c (enum cmd_and_opt_values): New item: oSSHSupport.
	(opts) New entry for oSSHSupport.
	New variable: socket_name_ssh.
	(cleanup_do): New function based on cleanup().
	(cleanup): Use cleanup_do() for socket_name and socket_name_ssh.
	(main): New switch case for oSSHSupport.
	(main): Move socket name creation code to ...
	(create_socket_name): ... this new function.
	(main): Use create_socket_name() for creating socket names for
	socket_name and for socket_name_ssh in case ssh support is
	enabled.
	Move socket creation code to ...
	(create_server_socket): ... this new function.
	(main): Use create_server_socket() for creating sockets.
	In case standard_socket is set, do not only store a socket name in
	socket_name, but also in socket_name_ssh.
	Generate additional environment info strings for ssh support.
	Pass additional ssh socket argument to handle_connections.
	(start_connection_thread_ssh): New function.
	(handle_connections): Use select to multiplex between gpg-agent
	and ssh-agent protocol.

	* agent.h (struct opt): New member: ssh_support.
	Declare function: start_command_handler_ssh.
This commit is contained in:
Moritz Schulte 2005-01-26 22:20:21 +00:00
parent 6cb495ca5c
commit a5d3f8a6e7
5 changed files with 468 additions and 126 deletions

View File

@ -1,3 +1,36 @@
2005-01-26 Moritz Schulte <moritz@g10code.com>
* command-ssh.c: New file.
* Makefile.am (gpg_agent_SOURCES): New source file: command-ssh.c.
* findkey.c (modify_description): New function.
(agent_key_from_file): Support comment field in key s-expressions.
* gpg-agent.c (enum cmd_and_opt_values): New item: oSSHSupport.
(opts) New entry for oSSHSupport.
New variable: socket_name_ssh.
(cleanup_do): New function based on cleanup().
(cleanup): Use cleanup_do() for socket_name and socket_name_ssh.
(main): New switch case for oSSHSupport.
(main): Move socket name creation code to ...
(create_socket_name): ... this new function.
(main): Use create_socket_name() for creating socket names for
socket_name and for socket_name_ssh in case ssh support is
enabled.
Move socket creation code to ...
(create_server_socket): ... this new function.
(main): Use create_server_socket() for creating sockets.
In case standard_socket is set, do not only store a socket name in
socket_name, but also in socket_name_ssh.
Generate additional environment info strings for ssh support.
Pass additional ssh socket argument to handle_connections.
(start_connection_thread_ssh): New function.
(handle_connections): Use select to multiplex between gpg-agent
and ssh-agent protocol.
* agent.h (struct opt): New member: ssh_support.
Declare function: start_command_handler_ssh.
2005-01-04 Werner Koch <wk@g10code.com> 2005-01-04 Werner Koch <wk@g10code.com>
* trustlist.c (agent_marktrusted): Use "Cancel" for the first * trustlist.c (agent_marktrusted): Use "Cancel" for the first

View File

@ -1,4 +1,4 @@
# Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. # Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
# #
# This file is part of GnuPG. # This file is part of GnuPG.
# #
@ -29,7 +29,7 @@ AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS)
gpg_agent_SOURCES = \ gpg_agent_SOURCES = \
gpg-agent.c agent.h \ gpg-agent.c agent.h \
command.c \ command.c command-ssh.c \
query.c \ query.c \
cache.c \ cache.c \
trans.c \ trans.c \

View File

@ -1,5 +1,5 @@
/* agent.h - Global definitions for the agent /* agent.h - Global definitions for the agent
* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -66,6 +66,7 @@ struct {
int allow_preset_passphrase; int allow_preset_passphrase;
int keep_tty; /* don't switch the TTY (for pinentry) on request */ int keep_tty; /* don't switch the TTY (for pinentry) on request */
int keep_display; /* don't switch the DISPLAY (for pinentry) on request */ int keep_display; /* don't switch the DISPLAY (for pinentry) on request */
int ssh_support; /* Enable ssh-agent emulation. */
} opt; } opt;
@ -136,6 +137,9 @@ void agent_init_default_ctrl (struct server_control_s *ctrl);
/*-- command.c --*/ /*-- command.c --*/
void start_command_handler (int, int); void start_command_handler (int, int);
/*-- command-ssh.c --*/
void start_command_handler_ssh (int);
/*-- findkey.c --*/ /*-- findkey.c --*/
int agent_write_private_key (const unsigned char *grip, int agent_write_private_key (const unsigned char *grip,
const void *buffer, size_t length, int force); const void *buffer, size_t length, int force);

View File

@ -1,5 +1,5 @@
/* findkey.c - locate the secret key /* findkey.c - locate the secret key
* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -140,6 +140,108 @@ try_unprotect_cb (struct pin_entry_info_s *pi)
} }
/* Modify a Key description, replacing certain special format
characters. List of currently supported replacements:
%% -> %
%c -> <COMMENT>. */
static int
modify_description (const char *description,
const char *comment, size_t comment_length,
char **description_modified)
{
size_t description_length;
size_t description_new_length;
gpg_error_t err;
char *description_new;
unsigned int i, j;
unsigned int special;
description_length = strlen (description);
description_new_length = description_length;
description_new = NULL;
/* Calculate length. */
special = 0;
for (i = 0; i < description_length; i++)
{
if (description[i] == '%')
special = 1;
else
{
if (special)
{
description_new_length -= 2;
switch (description[i])
{
case 'c':
/* Comment. */
description_new_length += comment_length;
break;
case '%':
description_new_length += 1;
break;
}
special = 0;
}
}
}
/* Allocate. */
description_new = xtrymalloc (description_new_length + 1);
if (! description_new)
{
err = gpg_error_from_errno (errno);
goto out;
}
/* Fill. */
for (i = j = 0; i < description_length; i++)
{
if (description[i] == '%')
special = 1;
else
{
if (special)
{
switch (description[i])
{
case 'c':
/* Comment. */
if (comment)
{
strncpy (description_new + j, comment, comment_length);
j += comment_length;
}
break;
case '%':
description_new[j] = '%';
j++;
break;
}
special = 0;
}
else
{
description_new[j] = description[i];
j++;
}
}
}
description_new[j] = 0;
*description_modified = description_new;
err = 0;
out:
return err;
}
/* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP /* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
should be the hex encoded keygrip of that key to be used with the should be the hex encoded keygrip of that key to be used with the
caching mechanism. DESC_TEXT may be set to override the default caching mechanism. DESC_TEXT may be set to override the default
@ -292,10 +394,42 @@ agent_key_from_file (CTRL ctrl, const char *desc_text,
case PRIVATE_KEY_CLEAR: case PRIVATE_KEY_CLEAR:
break; /* no unprotection needed */ break; /* no unprotection needed */
case PRIVATE_KEY_PROTECTED: case PRIVATE_KEY_PROTECTED:
rc = unprotect (ctrl, desc_text, &buf, grip, ignore_cache); {
if (rc) gcry_sexp_t comment_sexp;
log_error ("failed to unprotect the secret key: %s\n", size_t comment_length;
gpg_strerror (rc)); char *desc_text_final;
const char *comment;
comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
if (comment_sexp)
comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
else
{
comment = NULL;
comment_length = 0;
}
if (desc_text)
{
rc = modify_description (desc_text,
comment, comment_length, &desc_text_final);
if (rc)
log_error ("failed to modify description: %s\n", gpg_strerror (rc));
}
else
desc_text_final = NULL;
if (! rc)
{
rc = unprotect (ctrl, desc_text_final, &buf, grip, ignore_cache);
if (rc)
log_error ("failed to unprotect the secret key: %s\n",
gpg_strerror (rc));
}
gcry_sexp_release (comment_sexp);
xfree (desc_text_final);
}
break; break;
case PRIVATE_KEY_SHADOWED: case PRIVATE_KEY_SHADOWED:
if (shadow_info) if (shadow_info)

View File

@ -1,5 +1,6 @@
/* gpg-agent.c - The GnuPG Agent /* gpg-agent.c - The GnuPG Agent
* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. * Copyright (C) 2000, 2001, 2002, 2003,
* 2005 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -91,7 +92,8 @@ enum cmd_and_opt_values
oAllowMarkTrusted, oAllowMarkTrusted,
oAllowPresetPassphrase, oAllowPresetPassphrase,
oKeepTTY, oKeepTTY,
oKeepDISPLAY oKeepDISPLAY,
oSSHSupport
}; };
@ -144,6 +146,7 @@ static ARGPARSE_OPTS opts[] = {
N_("allow clients to mark keys as \"trusted\"")}, N_("allow clients to mark keys as \"trusted\"")},
{ oAllowPresetPassphrase, "allow-preset-passphrase", 0, { oAllowPresetPassphrase, "allow-preset-passphrase", 0,
N_("allow presetting passphrase")}, N_("allow presetting passphrase")},
{ oSSHSupport, "ssh-support", 0, "Enable SSH-Agent emulation" },
{0} {0}
}; };
@ -163,6 +166,9 @@ static int maybe_setuid = 1;
/* Name of the communication socket */ /* Name of the communication socket */
static char *socket_name; static char *socket_name;
/* Name of the communication socket used for ssh-agent-emulation. */
static char *socket_name_ssh;
/* Default values for options passed to the pinentry. */ /* Default values for options passed to the pinentry. */
static char *default_display; static char *default_display;
static char *default_ttyname; static char *default_ttyname;
@ -183,7 +189,7 @@ static char *current_logfile;
/* Local prototypes. */ /* Local prototypes. */
static void create_directories (void); static void create_directories (void);
#ifdef USE_GNU_PTH #ifdef USE_GNU_PTH
static void handle_connections (int listen_fd); static void handle_connections (int listen_fd, int listen_fd_ssh);
/* Pth wrapper function definitions. */ /* Pth wrapper function definitions. */
GCRY_THREAD_OPTION_PTH_IMPL; GCRY_THREAD_OPTION_PTH_IMPL;
#endif /*USE_GNU_PTH*/ #endif /*USE_GNU_PTH*/
@ -297,22 +303,29 @@ set_debug (void)
static void static void
cleanup (void) cleanup_do (char *name)
{ {
if (socket_name && *socket_name) if (name && *name)
{ {
char *p; char *p;
remove (socket_name); remove (name);
p = strrchr (socket_name, '/'); p = strrchr (name, '/');
if (p) if (p)
{ {
*p = 0; *p = 0;
rmdir (socket_name); rmdir (name);
*p = '/'; *p = '/';
} }
*socket_name = 0; *name = 0;
} }
}
static void
cleanup (void)
{
cleanup_do (socket_name);
cleanup_do (socket_name_ssh);
} }
@ -404,6 +417,105 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
} }
static void
create_socket_name (char **name, int standard_socket,
struct sockaddr_un *serv_addr,
char *standard_identifier, char *identifier)
{
char *p;
if (standard_socket)
*name = make_filename (opt.homedir, standard_identifier, NULL);
else
{
*name = xstrdup (identifier);
p = strrchr (*name, '/');
if (! p)
BUG ();
*p = 0;
if (!mkdtemp (*name))
{
log_error (_("can't create directory `%s': %s\n"),
*name, strerror (errno));
exit (1);
}
*p = '/';
}
if (strchr (*name, PATHSEP_C))
{
log_error ("`%s' are not allowed in the socket name\n", PATHSEP_S);
exit (1);
}
if (strlen (*name) + 1 >= sizeof serv_addr->sun_path)
{
log_error ("name of socket too long\n");
exit (1);
}
}
static int
create_server_socket (struct sockaddr_un *serv_addr,
int standard_socket, const char *name)
{
socklen_t len;
int fd;
int rc;
#ifdef HAVE_W32_SYSTEM
fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0);
#else
fd = socket (AF_UNIX, SOCK_STREAM, 0);
#endif
if (fd == -1)
{
log_error ("can't create socket: %s\n", strerror (errno));
exit (1);
}
memset (serv_addr, 0, sizeof *serv_addr);
serv_addr->sun_family = AF_UNIX;
strcpy (serv_addr->sun_path, name);
len = (offsetof (struct sockaddr_un, sun_path)
+ strlen (serv_addr->sun_path) + 1);
#ifdef HAVE_W32_SYSTEM
rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
if ((rc == -1) && standard_socket)
{
remove (name);
rc = bind (fd, (struct sockaddr*) serv_addr, len);
}
#else
rc = bind (fd, (struct sockaddr*) serv_addr, len);
if ((rc == -1) && standard_socket && (errno == EADDRINUSE))
{
remove (name);
rc = bind (fd, (struct sockaddr*) serv_addr, len);
}
#endif
if (rc == -1)
{
log_error ("error binding socket to `%s': %s\n",
serv_addr->sun_path, strerror (errno));
close (fd);
exit (1);
}
if (listen (fd, 5 ) == -1)
{
log_error ("listen() failed: %s\n", strerror (errno));
close (fd);
exit (1);
}
if (opt.verbose)
log_info ("listening on socket `%s'\n", socket_name);
return fd;
}
int int
main (int argc, char **argv ) main (int argc, char **argv )
{ {
@ -596,6 +708,12 @@ main (int argc, char **argv )
case oKeepTTY: opt.keep_tty = 1; break; case oKeepTTY: opt.keep_tty = 1; break;
case oKeepDISPLAY: opt.keep_display = 1; break; case oKeepDISPLAY: opt.keep_display = 1; break;
case oSSHSupport:
opt.ssh_support = 1;
opt.keep_tty = 1;
opt.keep_display = 1;
break;
default : pargs.err = configfp? 1:2; break; default : pargs.err = configfp? 1:2; break;
} }
} }
@ -745,11 +863,10 @@ main (int argc, char **argv )
else else
{ /* Regular server mode */ { /* Regular server mode */
int fd; int fd;
int rc; int fd_ssh;
pid_t pid; pid_t pid;
int len;
struct sockaddr_un serv_addr; struct sockaddr_un serv_addr;
char *p; struct sockaddr_un serv_addr_ssh;
/* Remove the DISPLAY variable so that a pinentry does not /* Remove the DISPLAY variable so that a pinentry does not
default to a specific display. There is still a default default to a specific display. There is still a default
@ -761,90 +878,26 @@ main (int argc, char **argv )
#endif #endif
/* Create the socket name . */ /* Create the socket name . */
if (standard_socket) create_socket_name (&socket_name, standard_socket, &serv_addr,
socket_name = make_filename (opt.homedir, "S.gpg-agent", NULL); "S.gpg-agent", "/tmp/gpg-XXXXXX/S.gpg-agent");
if (opt.ssh_support)
create_socket_name (&socket_name_ssh, standard_socket, &serv_addr_ssh,
"S.gpg-agent.ssh", "/tmp/gpg-XXXXXX/S.gpg-agent.ssh");
fd = create_server_socket (&serv_addr,
standard_socket, socket_name);
if (opt.ssh_support)
fd_ssh = create_server_socket (&serv_addr_ssh,
standard_socket, socket_name_ssh);
else else
{ /* Make the compiler happy. */
socket_name = xstrdup ("/tmp/gpg-XXXXXX/S.gpg-agent"); fd_ssh = -1;
p = strrchr (socket_name, '/');
if (!p)
BUG ();
*p = 0;;
if (!mkdtemp(socket_name))
{
log_error (_("can't create directory `%s': %s\n"),
socket_name, strerror(errno) );
exit (1);
}
*p = '/';
}
if (strchr (socket_name, PATHSEP_C) )
{
log_error ("`%s' are not allowed in the socket name\n", PATHSEP_S);
exit (1);
}
if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path )
{
log_error ("name of socket too long\n");
exit (1);
}
#ifdef HAVE_W32_SYSTEM
fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0);
#else
fd = socket (AF_UNIX, SOCK_STREAM, 0);
#endif
if (fd == -1)
{
log_error ("can't create socket: %s\n", strerror(errno) );
exit (1);
}
memset (&serv_addr, 0, sizeof serv_addr);
serv_addr.sun_family = AF_UNIX;
strcpy (serv_addr.sun_path, socket_name);
len = (offsetof (struct sockaddr_un, sun_path)
+ strlen(serv_addr.sun_path) + 1);
#ifdef HAVE_W32_SYSTEM
rc = _w32_sock_bind (fd, (struct sockaddr*)&serv_addr, len);
if (rc == -1 && standard_socket)
{
remove (socket_name);
rc = bind (fd, (struct sockaddr*)&serv_addr, len);
}
#else
rc = bind (fd, (struct sockaddr*)&serv_addr, len);
if (rc == -1 && standard_socket && errno == EADDRINUSE)
{
remove (socket_name);
rc = bind (fd, (struct sockaddr*)&serv_addr, len);
}
#endif
if (rc == -1)
{
log_error ("error binding socket to `%s': %s\n",
serv_addr.sun_path, strerror (errno) );
close (fd);
exit (1);
}
if (listen (fd, 5 ) == -1)
{
log_error ("listen() failed: %s\n", strerror (errno));
close (fd);
exit (1);
}
if (opt.verbose)
log_info ("listening on socket `%s'\n", socket_name );
fflush (NULL); fflush (NULL);
#ifdef HAVE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
pid = getpid (); pid = getpid ();
printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid); printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid);
printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid);
#else /*!HAVE_W32_SYSTEM*/ #else /*!HAVE_W32_SYSTEM*/
pid = fork (); pid = fork ();
if (pid == (pid_t)-1) if (pid == (pid_t)-1)
@ -854,7 +907,7 @@ main (int argc, char **argv )
} }
else if (pid) else if (pid)
{ /* We are the parent */ { /* We are the parent */
char *infostr; char *infostr, *infostr_ssh_sock, *infostr_ssh_pid;
close (fd); close (fd);
@ -866,8 +919,29 @@ main (int argc, char **argv )
kill (pid, SIGTERM); kill (pid, SIGTERM);
exit (1); exit (1);
} }
if (opt.ssh_support)
{
if (asprintf (&infostr_ssh_sock, "SSH_AUTH_SOCK=%s",
socket_name_ssh) < 0)
{
log_error ("out of core\n");
kill (pid, SIGTERM);
exit (1);
}
if (asprintf (&infostr_ssh_pid, "SSH_AGENT_PID=%u",
pid) < 0)
{
log_error ("out of core\n");
kill (pid, SIGTERM);
exit (1);
}
}
*socket_name = 0; /* don't let cleanup() remove the socket - *socket_name = 0; /* don't let cleanup() remove the socket -
the child should do this from now on */ the child should do this from now on */
if (opt.ssh_support)
*socket_name_ssh = 0;
if (argc) if (argc)
{ /* run the program given on the commandline */ { /* run the program given on the commandline */
if (putenv (infostr)) if (putenv (infostr))
@ -877,6 +951,20 @@ main (int argc, char **argv )
kill (pid, SIGTERM ); kill (pid, SIGTERM );
exit (1); exit (1);
} }
if (putenv (infostr_ssh_sock))
{
log_error ("failed to set environment: %s\n",
strerror (errno) );
kill (pid, SIGTERM );
exit (1);
}
if (putenv (infostr_ssh_pid))
{
log_error ("failed to set environment: %s\n",
strerror (errno) );
kill (pid, SIGTERM );
exit (1);
}
execvp (argv[0], argv); execvp (argv[0], argv);
log_error ("failed to run the command: %s\n", strerror (errno)); log_error ("failed to run the command: %s\n", strerror (errno));
kill (pid, SIGTERM); kill (pid, SIGTERM);
@ -890,12 +978,29 @@ main (int argc, char **argv )
{ {
*strchr (infostr, '=') = ' '; *strchr (infostr, '=') = ' ';
printf ( "setenv %s\n", infostr); printf ( "setenv %s\n", infostr);
if (opt.ssh_support)
{
*strchr (infostr_ssh_sock, '=') = ' ';
printf ( "setenv %s\n", infostr_ssh_sock);
*strchr (infostr_ssh_pid, '=') = ' ';
printf ( "setenv %s\n", infostr_ssh_pid);
}
} }
else else
{ {
printf ( "%s; export GPG_AGENT_INFO;\n", infostr); printf ( "%s; export GPG_AGENT_INFO;\n", infostr);
if (opt.ssh_support)
{
printf ( "%s; export SSH_AUTH_SOCK;\n", infostr_ssh_sock);
printf ( "%s; export SSH_AGENT_PID;\n", infostr_ssh_pid);
}
} }
free (infostr); free (infostr);
if (opt.ssh_support)
{
free (infostr_ssh_sock);
free (infostr_ssh_pid);
}
exit (0); exit (0);
} }
/*NEVER REACHED*/ /*NEVER REACHED*/
@ -949,7 +1054,7 @@ main (int argc, char **argv )
sa.sa_flags = 0; sa.sa_flags = 0;
sigaction (SIGPIPE, &sa, NULL); sigaction (SIGPIPE, &sa, NULL);
#endif #endif
handle_connections (fd); handle_connections (fd, opt.ssh_support ? fd_ssh : -1);
} }
else else
#endif /*!USE_GNU_PTH*/ #endif /*!USE_GNU_PTH*/
@ -1230,16 +1335,37 @@ start_connection_thread (void *arg)
return NULL; return NULL;
} }
static void *
start_connection_thread_ssh (void *arg)
{
int fd = (int)arg;
if (opt.verbose)
log_info ("ssh handler for fd %d started\n", fd);
/* FIXME: Move this housekeeping into a ticker function. Calling it
for each connection should work but won't work anymore if our
cleints start to keep connections. */
agent_trustlist_housekeeping ();
start_command_handler_ssh (fd);
if (opt.verbose)
log_info ("ssh handler for fd %d terminated\n", fd);
return NULL;
}
static void static void
handle_connections (int listen_fd) handle_connections (int listen_fd, int listen_fd_ssh)
{ {
pth_attr_t tattr; pth_attr_t tattr;
pth_event_t ev; pth_event_t ev;
sigset_t sigs; sigset_t sigs;
int signo; int signo;
struct sockaddr_un paddr; struct sockaddr_un paddr;
socklen_t plen = sizeof( paddr ); socklen_t plen = sizeof ( paddr );
fd_set fdset, read_fdset;
int ret;
int fd; int fd;
tattr = pth_attr_new(); tattr = pth_attr_new();
@ -1259,6 +1385,11 @@ handle_connections (int listen_fd)
ev = NULL; ev = NULL;
#endif #endif
FD_ZERO (&fdset);
FD_SET (listen_fd, &fdset);
if (listen_fd_ssh != -1)
FD_SET (listen_fd_ssh, &fdset);
for (;;) for (;;)
{ {
if (shutdown_pending) if (shutdown_pending)
@ -1275,28 +1406,68 @@ handle_connections (int listen_fd)
continue; continue;
} }
fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev); read_fdset = fdset;
if (fd == -1) ret = pth_select (FD_SETSIZE, &read_fdset, NULL, NULL, NULL);
{ if (ret == -1)
#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */ {
if (pth_event_status (ev) == PTH_STATUS_OCCURRED) log_error ("pth_select failed: %s - waiting 1s\n",
#else strerror (errno));
if (pth_event_occurred (ev)) pth_sleep (1);
#endif continue;
{
handle_signal (signo);
continue;
}
log_error ("accept failed: %s - waiting 1s\n", strerror (errno));
pth_sleep(1);
continue;
} }
if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) if (FD_ISSET (listen_fd, &read_fdset))
{ {
log_error ("error spawning connection handler: %s\n", fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev);
strerror (errno) ); if (fd == -1)
close (fd); {
#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */
if (pth_event_status (ev) == PTH_STATUS_OCCURRED)
#else
if (pth_event_occurred (ev))
#endif
{
handle_signal (signo);
continue;
}
log_error ("accept failed: %s - waiting 1s\n", strerror (errno));
pth_sleep(1);
continue;
}
if (!pth_spawn (tattr, start_connection_thread, (void*)fd))
{
log_error ("error spawning connection handler: %s\n",
strerror (errno) );
close (fd);
}
}
else if ((listen_fd_ssh != -1) && FD_ISSET (listen_fd_ssh, &read_fdset))
{
fd = pth_accept_ev (listen_fd_ssh, (struct sockaddr *)&paddr, &plen, ev);
if (fd == -1)
{
#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */
if (pth_event_status (ev) == PTH_STATUS_OCCURRED)
#else
if (pth_event_occurred (ev))
#endif
{
handle_signal (signo);
continue;
}
log_error ("accept failed: %s - waiting 1s\n", strerror (errno));
pth_sleep(1);
continue;
}
if (!pth_spawn (tattr, start_connection_thread_ssh, (void*)fd))
{
log_error ("error spawning connection handler: %s\n",
strerror (errno) );
close (fd);
}
} }
} }