lsh 1.3.4 update

This commit is contained in:
chombier 2001-09-18 17:17:34 +00:00
parent 5b5e0e778c
commit 5318b19fca
319 changed files with 6242 additions and 3882 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -62,8 +62,9 @@ typedef struct lshcontext {
sig_atomic_t _window_changed;
char *_envv[3]; // "HOME", "LOGNAME", "TERM"
char *_envv[4]; // "HOME", "LOGNAME", "TERM", "DISPLAY"
char _term[64]; // home and logname never change
char _display[64]; // home and logname never change
char _kpassword[64];
int _kindex;
int _pindex;

View File

@ -1,63 +1,15 @@
/* prefix.h */
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
/* #undef CRAY_STACKSEG_END */
/* Define if using alloca.c. */
/* #undef C_ALLOCA */
/* Define to empty if the keyword does not work. */
/* #undef const */
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
/* #undef CRAY_STACKSEG_END */
/* Define if the `getpgrp' function takes no argument. */
/* #undef GETPGRP_VOID */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef gid_t */
/* Define if you have alloca, as a function or macro. */
#define HAVE_ALLOCA 1
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#define HAVE_ALLOCA_H 1
/* Define if you don't have vprintf but do have _doprnt. */
/* #undef HAVE_DOPRNT */
/* Define if you have the vprintf function. */
#define HAVE_VPRINTF 1
/* Define as __inline if that's what the C compiler calls it. */
/* #undef inline */
/* Define to `unsigned' if <sys/types.h> doesn't define. */
/* #undef size_t */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
/* #undef STACK_DIRECTION */
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef uid_t */
/* Define if your processor stores words with the most significant
byte first (like Motorola and SPARC, unlike Intel and VAX). */
#define WORDS_BIGENDIAN 1
/* The installation prefix. */
/* #undef PREFIX */
/* Define to support non-standard packets of ssh2 */
#define DATAFELLOWS_WORKAROUNDS 1
/* Define to enable sanity checking on memory allocation and casting */
#define DEBUG_ALLOC 0
@ -65,41 +17,35 @@
/* Define to enable tracing */
#define DEBUG_TRACE 1
/* Define if zlib should be used */
#define WITH_ZLIB 1
/* Define to enable pty support */
#define WITH_PTY_SUPPORT 1
/* Define to enable fallback to SSH1 */
/* #undef WITH_SSH1_FALLBACK */
/* Location of the SSH1 daemon */
/* #undef SSHD1 */
/* Define if IDEA should be used */
/* #define WITH_IDEA 1 */
/* Define if SRP should be supported */
#define WITH_SRP 1
/* Define to enable tcp forwarding */
#define WITH_TCP_FORWARD 1
/* For Ipv6 support */
/* #undef WITH_IPV6 */
/* Define if the `getpgrp' function takes no argument. */
/* #undef GETPGRP_VOID */
/* Define if AI_NUMERICHOST exists */
/* #undef HAVE_AI_NUMERICHOST */
/* For utmp support */
/* #undef WITH_UTMP */
/* Define if you have alloca, as a function or macro. */
#define HAVE_ALLOCA 1
/* For kerberos */
/* #undef WITH_KERBEROS */
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#define HAVE_ALLOCA_H 1
/* Define to indicate that shutdown seems to work properly */
#define SHUTDOWN_WORKS_WITH_UNIX_SOCKETS 1
/* Define if you have the <argp.h> header file. */
/* #undef HAVE_ARGP_H */
/* Define if you have the cfmakeraw function. */
/* #undef HAVE_CFMAKERAW */
/* Define if you have the <crypt.h> header file. */
/* #undef HAVE_CRYPT_H */
/* Define if you don't have vprintf but do have _doprnt. */
/* #undef HAVE_DOPRNT */
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define if you have the gai_strerror function. */
/* #undef HAVE_GAI_STRERROR */
/* Define if the compiler understands __attribute__ */
/* #undef HAVE_GCC_ATTRIBUTE */
@ -107,63 +53,6 @@
/* Define if the compiler understands __FUNCTION__ */
/* #define HAVE_GCC_FUNCTION 1 */
/* Define if the compiler understands offsetof(TYPE, MEMBER) */
#define HAVE_C_OFFSETOF 1
/* Define if a we have working UNIX98 pty handling */
/* #undef HAVE_UNIX98_PTYS */
/* For BSD-style pty allocation */
/* #undef PTY_BSD_SCHEME_FIRST_CHARS */
/* #undef PTY_BSD_SCHEME_SECOND_CHARS */
/* #undef PTY_BSD_SCHEME */
/* syslog() available? */
#define HAVE_SYSLOG 1
/* struct utmp has a ut_host member */
/* #undef HAVE_UT_HOST */
/* struct utmp has a ut_name member */
/* #undef HAVE_UT_NAME */
/* struct utmp has a ut_user member */
/* #undef HAVE_UT_USER */
/* struct utmp has a ut_addr member */
/* #undef HAVE_UT_ADDR */
/* struct utmp has a ut_addr_v6 member */
/* #undef HAVE_UT_ADDR_V6 */
/* Length type used by getsockopt() */
/* #undef socklen_t */
/* Define to support non-standard packets of ssh2 */
#define DATAFELLOWS_WORKAROUNDS 1
/* Define to enable x11 forwarding */
/* #undef WITH_X11_FORWARD */
/* Define to enable authentication agent forwarding */
/* #undef WITH_AGENT_FORWARD */
/* The number of bytes in a int. */
#define SIZEOF_INT 4
/* The number of bytes in a long. */
#define SIZEOF_LONG 4
/* The number of bytes in a short. */
#define SIZEOF_SHORT 2
/* Define if you have the cfmakeraw function. */
/* #undef HAVE_CFMAKERAW */
/* Define if you have the gai_strerror function. */
/* #undef HAVE_GAI_STRERROR */
/* Define if you have the getaddrinfo function. */
/* #undef HAVE_GETADDRINFO */
@ -179,105 +68,21 @@
/* Define if you have the gettimeofday function. */
#define HAVE_GETTIMEOFDAY 1
/* Define if you have the inet_aton function. */
#define HAVE_INET_ATON 1
/* Define if you have the login function. */
/* #undef HAVE_LOGIN */
/* Define if you have the logout function. */
/* #undef HAVE_LOGOUT */
/* Define if you have the logwtmp function. */
/* #undef HAVE_LOGWTMP */
/* Define if you have the memxor function. */
/* #undef HAVE_MEMXOR */
/* Define if you have the openpty function. */
/* #undef HAVE_OPENPTY */
/* Define if you have the poll function. */
/* #undef HAVE_POLL */
/* Define if you have the select function. */
#define HAVE_SELECT 1
/* Define if you have the socket function. */
#define HAVE_SOCKET 1
/* Define if you have the strerror function. */
#define HAVE_STRERROR 1
/* Define if you have the strsignal function. */
#define HAVE_STRSIGNAL 1
/* Define if you have the strtol function. */
#define HAVE_STRTOL 1
/* Define if you have the syslog function. */
#define HAVE_SYSLOG 1
/* Define if you have the vsnprintf function. */
#define HAVE_VSNPRINTF 1
/* Define if you have the <argp.h> header file. */
/* #undef HAVE_ARGP_H */
/* Define if you have the <crypt.h> header file. */
/* #undef HAVE_CRYPT_H */
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define if you have the <gmp2/gmp.h> header file. */
/* #undef HAVE_GMP2_GMP_H */
/* Define if you have the <gmp.h> header file. */
#define HAVE_GMP_H 1
/* Define if you have the <gmp2/gmp.h> header file. */
/* #undef HAVE_GMP2_GMP_H */
/* Define if you have the inet_aton function. */
#define HAVE_INET_ATON 1
/* Define if you have the <inttypes.h> header file. */
/* #undef HAVE_INTTYPES_H */
/* Define if you have the <krb5.h> header file. */
/* #undef HAVE_KRB5_H */
/* Define if you have the <libutil.h> header file. */
/* #undef HAVE_LIBUTIL_H */
/* Define if you have the <poll.h> header file. */
/* #undef HAVE_POLL_H */
/* Define if you have the <pty.h> header file. */
/* #undef HAVE_PTY_H */
/* Define if you have the <shadow.h> header file. */
/* #undef HAVE_SHADOW_H */
/* Define if you have the <strings.h> header file. */
/* #undef HAVE_STRINGS_H */
/* Define if you have the <stropts.h> header file. */
/* #undef HAVE_STROPTS_H */
/* Define if you have the <sys/poll.h> header file. */
/* #undef HAVE_SYS_POLL_H */
/* Define if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define if you have the <syslog.h> header file. */
/* #define HAVE_SYSLOG_H 1 */
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define if you have the <utmp.h> header file. */
/* #undef HAVE_UTMP_H */
/* Define if you have the <utmpx.h> header file. */
/* #undef HAVE_UTMPX_H */
/* Define if you have the <zlib.h> header file. */
#define HAVE_ZLIB_H 1
/* Define if you have the crypt library (-lcrypt). */
/* #undef HAVE_LIBCRYPT */
@ -290,17 +95,235 @@
/* Define if you have the util library (-lutil). */
/* #undef HAVE_LIBUTIL */
/* Define if you have the xnet library (-lxnet). */
/* Define if you have the <libutil.h> header file. */
/* #undef HAVE_LIBUTIL_H */
/* Define if you have the `Xau' library (-lXau). */
/* #undef HAVE_LIBXAU */
/* Define if you have the `xnet' library (-lxnet). */
/* #undef HAVE_LIBXNET */
/* Define if you have the z library (-lz). */
/* #undef HAVE_LIBZ */
/* Define if you have the login function. */
/* #undef HAVE_LOGIN */
/* Define if you have the logout function. */
/* #undef HAVE_LOGOUT */
/* Define if you have the logwtmp function. */
/* #undef HAVE_LOGWTMP */
/* Define if you have the <memory.h> header file. */
/* #undef HAVE_MEMORY_H */
/* Define if you have the memxor function. */
/* #undef HAVE_MEMXOR */
/* Define if you have the openpty function. */
/* #undef HAVE_OPENPTY */
/* Define if you have the poll function. */
/* #undef HAVE_POLL */
/* Define if you have the <poll.h> header file. */
/* #undef HAVE_POLL_H */
/* Define if you have the <pty.h> header file. */
/* #undef HAVE_PTY_H */
/* Define if you have the select function. */
#define HAVE_SELECT 1
/* Define if you have the <shadow.h> header file. */
/* #undef HAVE_SHADOW_H */
/* Define if you have the socket function. */
#define HAVE_SOCKET 1
/* Define if you have the strerror function. */
/* #undef HAVE_STDLIB_H */
/* Define if you have the strerror function. */
#define HAVE_STRERROR 1
/* Define if you have the <strings.h> header file. */
/* #undef HAVE_STRINGS_H */
/* Define if you have the <string.h> header file. */
/* #undef HAVE_STRING_H */
/* Define if you have the <stropts.h> header file. */
/* #undef HAVE_STROPTS_H */
/* Define if you have the strsignal function. */
#define HAVE_STRSIGNAL 1
/* Define if you have the strtol function. */
#define HAVE_STRTOL 1
/* Define if `ut_addr' is member of `struct utmp'. */
/* #undef HAVE_STRUCT_UTMP_UT_ADDR */
/* Define if `ut_addr_v6' is member of `struct utmp'. */
/* #undef HAVE_STRUCT_UTMP_UT_ADDR_V6 */
/* Define if `ut_host' is member of `struct utmp'. */
/* #undef HAVE_STRUCT_UTMP_UT_HOST */
/* Define if `ut_name' is member of `struct utmp'. */
/* #undef HAVE_STRUCT_UTMP_UT_NAME */
/* Define if `ut_user' is member of `struct utmp'. */
/* #undef HAVE_STRUCT_UTMP_UT_USER */
/* syslog() available? */
#define HAVE_SYSLOG 1
/* Define if you have the <syslog.h> header file. */
/* #define HAVE_SYSLOG_H 1 */
/* Define if you have the <sys/poll.h> header file. */
/* #undef HAVE_SYS_POLL_H */
/* Define if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define if a we have working UNIX98 pty handling */
/* #undef HAVE_UNIX98_PTYS */
/* Define if you have the <utmpx.h> header file. */
/* #undef HAVE_UTMPX_H */
/* Define if you have the <utmp.h> header file. */
/* #undef HAVE_UTMP_H */
/* Define if you have the vprintf function. */
#define HAVE_VPRINTF 1
/* Define if you have the vsnprintf function. */
#define HAVE_VSNPRINTF 1
/* Define if you have the <X11/Xauth.h> header file. */
/* #undef HAVE_X11_XAUTH_H */
/* Define if you have the <zlib.h> header file. */
#define HAVE_ZLIB_H 1
/* Name of package */
#define PACKAGE "lsh"
/* The installation prefix. */
/* #undef PREFIX */
/* Traditional BSD pty handling */
/* #undef PTY_BSD_SCHEME */
/* Possible first characters in a /dev/ptyXX name */
/* #undef PTY_BSD_SCHEME_FIRST_CHARS */
/* Possible second characters in a /dev/ptyXX name */
/* #undef PTY_BSD_SCHEME_SECOND_CHARS */
/* sbin directory */
/* #undef SBINDIR */
/* Define to indicate that shutdown seems to work properly */
#define SHUTDOWN_WORKS_WITH_UNIX_SOCKETS 1
/* The number of bytes in a int. */
#define SIZEOF_INT 4
/* The number of bytes in a long. */
#define SIZEOF_LONG 4
/* The number of bytes in a short. */
#define SIZEOF_SHORT 2
/* Location of the SSH1 daemon */
/* #undef SSHD1 */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
/* #undef STACK_DIRECTION */
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
/* Version number of package */
#define VERSION "1.2"
#define VERSION "1.3.4"
/* Define to enable authentication agent forwarding */
/* #undef WITH_AGENT_FORWARD */
/* Use gcov */
/* #undef WITH_GCOV */
/* Define if IDEA should be used */
/* #define WITH_IDEA 1 */
/* For Ipv6 support */
/* #undef WITH_IPV6 */
/* For kerberos */
/* #undef WITH_KERBEROS */
/* Define to enable pty support */
#define WITH_PTY_SUPPORT 1
/* Define if SRP should be supported */
#define WITH_SRP 1
/* Define to enable fallback to SSH1 */
/* #undef WITH_SSH1_FALLBACK */
/* Define to enable tcp forwarding */
#define WITH_TCP_FORWARD 1
/* For utmp support */
/* #undef WITH_UTMP */
/* Define to enable x11 forwarding */
#define WITH_X11_FORWARD 1
/* Define if zlib should be used */
#define WITH_ZLIB 1
/* Define if your processor stores words with the most significant
byte first (like Motorola and SPARC, unlike Intel and VAX). */
#define WORDS_BIGENDIAN 1
/* Define to empty if the keyword does not work. */
/* #undef const */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef gid_t */
/* Define as __inline if that's what the C compiler calls it. */
/* #undef inline */
/* Define to `unsigned' if <sys/types.h> doesn't define. */
/* #undef size_t */
/* Length type used by getsockopt */
/* #undef socklen_t */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef uid_t */
/* MacOS Specific */

View File

@ -600,22 +600,22 @@ int AvailableFromTTY(int id, void *context)
* tty_getwinsize : replaces tty_getwinsize from liblsh
*/
int
tty_getwinsize(int fd, UINT32 *w, UINT32 *h, UINT32 *wp, UINT32 *hp)
tty_getwinsize(int fd, struct terminal_dimensions *dims)
{
FontInfo info;
*w = SIOUXSettings.columns;
*h = SIOUXSettings.rows;
*wp = 0;
*hp = 0;
dims->char_width = SIOUXSettings.columns;
dims->char_height = SIOUXSettings.rows;
dims->pixel_width = 0;
dims->pixel_height = 0;
/*
if (!FetchFontInfo(SIOUXSettings.fontid,SIOUXSettings.fontsize,SIOUXSettings.fontface, &info)) {
*wp = info.widMax;
*hp = info.ascent + info.descent;
dims->pixel_width = info.widMax;
dims->pixel_height = info.ascent + info.descent;
} else {
// just guess...
*wp = 12;
*hp = 16;
dims->pixel_width = 12;
dims->pixel_height = 16;
}
*/
return 1;
@ -672,11 +672,11 @@ char *getpass( const char *prompt )
* yes_or_no
*/
int yes_or_no(struct lsh_string *s, int def, int free)
int yes_or_no(const struct lsh_string *s, int def, int free)
{
struct lsh_string *prompt;
prompt = make_cstring(s, free);
prompt = make_string(s);
if (prompt) {
if (!quiet_flag) {
Str255 pprompt;

View File

@ -29,7 +29,10 @@
#include "werror.h"
#include "charset.h"
#include "format.h" /* For format_size_in_decimal() */
/* For format_size_in_decimal */
#include "format.h"
#include "gc.h"
#include "io.h"
#include "parse.h"
@ -43,6 +46,10 @@
#include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if HAVE_SYSLOG_H
#include <syslog.h>
#endif
@ -69,9 +76,11 @@ int syslog_flag = 0;
#else
extern Boolean gLogStdIO;
#endif
static const char *program_name = NULL;
#define WERROR_TRACE -1
#define WERROR_DEBUG -2
#define WERROR_LOG -3
static const struct argp_option
werror_options[] =
@ -80,17 +89,23 @@ werror_options[] =
{ "verbose", 'v', NULL, 0, "Verbose diagnostic messages", 0},
{ "trace", WERROR_TRACE, NULL, 0, "Detailed trace", 0 },
{ "debug", WERROR_DEBUG, NULL, 0, "Print huge amounts of debug information", 0 },
{ "log-file", WERROR_LOG, "File name", 0,
"Append messages to this file.", 0},
{ NULL, 0, NULL, 0, NULL, 0 }
};
static error_t
werror_argp_parser(int key, char *arg UNUSED,
struct argp_state *state UNUSED)
werror_argp_parser(int key, char *arg,
struct argp_state *state)
{
switch(key)
{
default:
return ARGP_ERR_UNKNOWN;
case ARGP_KEY_END:
case ARGP_KEY_INIT:
program_name = state->name;
break;
case 'q':
quiet_flag = 1;
break;
@ -103,6 +118,19 @@ werror_argp_parser(int key, char *arg UNUSED,
case WERROR_DEBUG:
debug_flag = 1;
break;
case WERROR_LOG:
{
/* FIXME: For clients, this is right: We only get lsh-related
* messages to the log file, and child processes are not
* affected. But for the server, perhaps we should also dup
* the logfile over stderr? */
int fd = open(arg, O_WRONLY | O_CREAT | O_APPEND, 0666);
if (fd < 0)
argp_error(state, "Failed to open log file `%s'.", arg);
else
set_error_stream(fd);
}
}
return 0;
}
@ -131,24 +159,24 @@ static const struct exception *
static const struct exception *
write_syslog(int fd UNUSED, UINT32 length, const UINT8 *data)
{
struct lsh_string *s = make_cstring_l(length, data);
struct lsh_string *s;
/* NOTE: make_cstring fails if the data contains any NUL characters. */
assert(s);
/* Data must not contain any NUL:s */
assert(!memchr(data, '\0', length));
/* NUL-terminate the string. */
s = ssh_format("%ls", length, data);
#if 0
/* Make sure the message is properly terminated with \0. */
snprintf(string_buffer, MIN(BUF_SIZE, length), "%s", data);
#endif
/* FIXME: Should we use different log levels for werror, verbose and
* debug? */
syslog(LOG_NOTICE, "%s", s->data);
syslog(LOG_NOTICE, "%s", lsh_get_cstring(s));
lsh_string_free(s);
return NULL;
}
/* FIXME: Delete argument and use program_name. */
void
set_error_syslog(const char *id)
{
@ -168,7 +196,7 @@ write_ignore(int fd UNUSED,
{ return NULL; }
void
set_error_stream(int fd, int with_poll)
set_error_stream(int fd)
{
lshcontext *context = (lshcontext *)pthread_getspecific(ssh2threadkey);
if ( !context ) {
@ -176,7 +204,18 @@ set_error_stream(int fd, int with_poll)
}
error_fd = fd;
error_write = with_poll ? write_raw_with_poll : write_raw;
error_write = write_raw;
}
void
set_error_nonblocking(int fd)
{
lshcontext *context = (lshcontext *)pthread_getspecific(ssh2threadkey);
if ( !context ) {
return;
}
if (error_fd == fd)
error_write = write_raw_with_poll;
}
int
@ -193,6 +232,10 @@ dup_error_stream(void)
else
{
int fd = dup(error_fd);
/* This function is used to get stderr away from the stdio fd
* range. In the unlikely event that dup returns an fd <=
* STDERR_FILENO, we treat that as an error. */
if (fd > STDERR_FILENO)
{
io_set_close_on_exec(fd);
@ -412,6 +455,12 @@ werror_paranoia_putc(UINT8 c)
void
werror_vformat(const char *f, va_list args)
{
if (program_name)
{
werror_write(strlen(program_name), program_name);
werror_write(2, ": ");
}
while (*f)
{
if (*f == '%')
@ -449,23 +498,11 @@ werror_vformat(const char *f, va_list args)
(do_hex ? werror_hex : werror_decimal)(va_arg(args, UINT32));
break;
case 'c':
werror_putc(va_arg(args, int));
(do_paranoia ? werror_paranoia_putc : werror_putc)(va_arg(args, int));
break;
case 'n':
werror_bignum(va_arg(args, MP_INT *), do_hex ? 16 : 10);
break;
case 'z':
{
char *s = va_arg(args, char *);
if (do_hex)
werror_hexdump(strlen(s), (unsigned char *)s);
while (*s)
(do_paranoia ? werror_paranoia_putc : werror_putc)(*s++);
break;
}
case 'a':
{
int atom = va_arg(args, int);
@ -542,9 +579,40 @@ werror_vformat(const char *f, va_list args)
if (do_free)
lsh_string_free(s);
}
break;
break;
}
case 't':
{
struct lsh_object *o = va_arg(args, struct lsh_object *);
const char *type;
if (!o)
type = "<NULL>";
else if (o->isa)
type = o->isa->name;
else
type = "<STATIC>";
werror_write(strlen(type), type);
break;
}
case 'z':
{
char *s = va_arg(args, char *);
if (do_hex)
werror_hexdump(strlen(s), s);
else if (do_paranoia)
while (*s)
werror_paranoia_putc(*s++);
else
werror_write(strlen(s), s);
break;
}
default:
fatal("werror_vformat: bad format string!\n");
break;
@ -563,12 +631,14 @@ werror(const char *format, ...)
if ( !context ) {
return;
}
if (!context->_quiet_flag)
/* It is somewhat reasonable to use both -q and -v. In this case
* werror()-messages should be displayed. */
if (context->_verbose_flag || !context->_quiet_flag)
{
if (gLogStdIO || (!context->_tracing && !context->_verbosing && !context->_debugging)) {
if (!gLogStdIO) {
werror_flush();
set_error_stream(STDERR_FILENO, 0);
set_error_stream(STDERR_FILENO);
}
}
va_start(args, format);
@ -577,7 +647,7 @@ werror(const char *format, ...)
werror_flush();
if (gLogStdIO || (!context->_tracing && !context->_verbosing && !context->_debugging)) {
if (!gLogStdIO) {
set_error_syslog("");
set_error_syslog("lsh");
}
}
}
@ -651,12 +721,12 @@ fatal(const char *format, ...)
if (context)
{
werror_flush();
set_error_stream(STDERR_FILENO, 0);
set_error_stream(STDERR_FILENO);
va_start(args, format);
werror_vformat(format, args);
va_end(args);
werror_flush();
set_error_syslog("");
set_error_syslog("lsh");
}
abort();
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lsh/NEWS

Binary file not shown.

Binary file not shown.

View File

@ -1,119 +0,0 @@
/* The name and version of this software distribution. These
* originates from AM_INIT_AUTOMAKE in the configure.in file. */
#undef PACKAGE
#undef VERSION
/* The installation prefix. */
#undef PREFIX
/* sbin directory */
#undef SBINDIR
/* Define to enable sanity checking on memory allocation and casting */
#undef DEBUG_ALLOC
/* Define to enable tracing */
#undef DEBUG_TRACE
/* Define if zlib should be used */
#undef WITH_ZLIB
/* Define if zlib.h is present */
#undef HAVE_ZLIB_H
/* Define to enable pty support */
#undef WITH_PTY_SUPPORT
/* Define to enable fallback to SSH1 */
#undef WITH_SSH1_FALLBACK
/* Location of the SSH1 daemon */
#undef SSHD1
/* Define if IDEA should be used */
#undef WITH_IDEA
/* Define if SRP should be supported */
#undef WITH_SRP
/* Define to enable tcp forwarding */
#undef WITH_TCP_FORWARD
/* For Ipv6 support */
#undef WITH_IPV6
/* Define if AI_NUMERICHOST exists */
#undef HAVE_AI_NUMERICHOST
/* For utmp support */
#undef WITH_UTMP
/* For kerberos */
#undef WITH_KERBEROS
/* Define to indicate that shutdown seems to work properly */
#undef SHUTDOWN_WORKS_WITH_UNIX_SOCKETS
/* Define if the compiler understands __attribute__ */
#undef HAVE_GCC_ATTRIBUTE
/* Define if the compiler understands __FUNCTION__ */
#undef HAVE_GCC_FUNCTION
/* Define if the compiler understands offsetof(TYPE, MEMBER) */
#undef HAVE_C_OFFSETOF
/* Define if a we have working UNIX98 pty handling */
#undef HAVE_UNIX98_PTYS
/* openpty() available? */
#undef HAVE_OPENPTY
/* For BSD-style pty allocation */
#undef PTY_BSD_SCHEME_FIRST_CHARS
#undef PTY_BSD_SCHEME_SECOND_CHARS
#undef PTY_BSD_SCHEME
/* Define if GMP is available */
#undef HAVE_LIBGMP
/* syslog() available? */
#undef HAVE_SYSLOG
/* struct utmp has a ut_host member */
#undef HAVE_UT_HOST
/* struct utmp has a ut_name member */
#undef HAVE_UT_NAME
/* struct utmp has a ut_user member */
#undef HAVE_UT_USER
/* struct utmp has a ut_addr member */
#undef HAVE_UT_ADDR
/* struct utmp has a ut_addr_v6 member */
#undef HAVE_UT_ADDR_V6
/* Length type used by getsockopt() */
#undef socklen_t
/* Define to support non-standard packets of ssh2 */
#undef DATAFELLOWS_WORKAROUNDS
/* Global variables needed by argp */
#undef HAVE_PROGRAM_INVOCATION_NAME
#undef HAVE_PROGRAM_INVOCATION_SHORT_NAME
/* Define to enable x11 forwarding */
#undef WITH_X11_FORWARD
/* Define to enable authentication agent forwarding */
#undef WITH_AGENT_FORWARD
/* Used by lsh_proxy.c */
#undef WITH_ALF
/* Use gcov */
#undef WITH_GCOV

Binary file not shown.

BIN
lsh/aclocal.m4 vendored

Binary file not shown.

Binary file not shown.

BIN
lsh/configure vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -24,7 +24,7 @@ Internet.
<p><code>lsh</code> is a component of the <small>GNU</small> system.
<p>This manual explains how to use and hack <code>lsh</code>; it corresponds to
<code>lsh</code> version 1.1.6.
<code>lsh</code> version 1.3.4.
<ul>
<li><a href="#Introduction">Introduction</a>:
@ -221,11 +221,12 @@ Up:<a rel=up href="#Introduction">Introduction</a>
<h2>Features</h2>
<p><code>lsh</code> does not only provide more secure replacements for
<code>telnet</code>, <code>rsh</code> and <code>rlogin</code>, it also provides some other
features to make it convenient to communicate securely. But <code>lsh</code> is
still in an early stage of development, so this section is expected to
grow with time. One goal for <code>lsh</code> is to make it reasonable easy to
extend it, without messing with the core security functionality.
<code>telnet</code>, <code>rsh</code> and <code>rlogin</code>, it also provides
some other features to make it convenient to communicate securely. This
section is expected to grow with time, as more features from the
wish-list are added to lsh. One goal for <code>lsh</code> is to make it
reasonable easy to extend it, without messing with the core security
functionality.
<p><code>lsh</code> can be configured to allow login based on a personal key-pair
consisting of a private and a public key, so that you can execute remote
@ -241,11 +242,22 @@ mechanism to delegate restricted logins.
is useful for tunneling otherwise insecure protocols, like telnet and
pop, through an encrypted <code>lsh</code> connection.
<p>Convenient tunneling of <small>X</small> is one of the most impressive features of the
original <code>ssh</code> programs. <code>lsh</code> doesn't do this yet. Other kind
of tunneling that may turn out to be useful include authentication (i.e.
<code>ssh-agent</code>), general forwarding of <small>UDP</small>, and why not also
general <small>IP</small>-tunneling.
<p>Convenient tunneling of <small>X</small> was one of the most impressive
features of the original <code>ssh</code> programs. The current version of
<code>lsh</code> implements <small>X</small>-forwarding, although the
<code>lshd</code> server doesn't provide that service yet.
<p>Whan <small>X</small> forwarding is in effect, the remote process is started
in an environment where the <code>DISPLAY</code> variable in the environment
points to a fake <small>X</small> server, connection to which are forwarded
to the <small>X</small> server in your local environment. <code>lsh</code> also
creates a new "fake" <code>MIT-MAGIC-COOKIE-1</code> for controlling access
control. Your real <small>X</small> authentication data is never sent to the
remote machine.
<p>Other kinds of tunneling that may turn out to be useful include
authentication (i.e. <code>ssh-agent</code>), general forwarding of
<small>UDP</small>, and why not also general <small>IP</small>-tunneling.
<p><hr>
Node:<a name="Related%20techniques">Related techniques</a>,
@ -292,9 +304,6 @@ back, for security reasons.
and Windows. <code>ossh</code> and later OpenSSH are derived from earlier
version av Tatu Ylönen's <code>ssh</code>, and are free software.
<p>Until <code>lsh</code> becomes stable and well tested, I would recommend using
some implementation of the <code>ssh-1</code> protocol.
<p><hr>
Node:<a name="ssh2">ssh2</a>,
Next:<a rel=next href="#Kerberos">Kerberos</a>,
@ -323,7 +332,7 @@ for recent versions of <code>ssh1</code>, but with a narrower definition of
"non-commercial use".
<p>Besides <code>lsh</code> there are few free implementations of the
<code>ssh-2</code> protocols, but since May 2000 it is supported also by
<code>ssh-2</code> protocols. Since May 2000 it is supported also by
OpenSSH.
<p><hr>
@ -584,9 +593,9 @@ the firewall in a secure way.
<li>Port forwarding is done in addition to anything else <code>lsh</code> is
doing. In the example above, a tunnel is set up, but <code>lsh</code> will
also start an interactive shell for you. Just like the <code>-L</code>
option was not present. If this is not what you want, the <code>-N</code>
option is for you (see <a href="#Invoking%20lsh">Invoking lsh</a>)
also start an interactive shell for you. Just as if the <code>-L</code>
option was not present. If this is not what you want, the <code>-N</code> or
<code>-B</code> option is for you (see <a href="#Invoking%20lsh">Invoking lsh</a>)
</ul>
<p>Remote forwarding is similar, but asks the <em>remote</em> machine to
@ -687,13 +696,11 @@ public key to the machines where you want to authorize it.
keypair on each of the systems, and on each system you authorize some or
all of your other public keys for login.
<p>Note that <code>lsh</code> does <em>not</em> currently encrypt your private
key in any way. That means that you can lose it if a backup tape gets
into the wrong hands, and if you use NFS it will likely be sent in the
clear across your local network. (Actually, you can encrypt the key
using a pass phrase, by passing the <code>-c 3des</code> option to
<code>lsh-writekey</code>, but <code>lsh</code> doesn't yet support decrypting
it).
<p>Note that <code>lsh-writekey</code> does <em>not</em> currently encrypt your
private key in any way. That means that you can lose it if a backup tape
gets into the wrong hands, and if you use NFS it will likely be sent in
the clear across your local network. To encrypt the key using a pass
phrase, give the <code>-c 3des</code> option to <code>lsh-writekey</code>.
<p><hr>
Node:<a name="srp">srp</a>,
@ -753,18 +760,20 @@ talking to the real server, he needs to know your password as well.
<p><small>SRP</small> support is disabled by default, but can be enabled by the
<code>--srp-keyexchange</code> option to <code>lshd</code> and <code>lsh</code>
(naturally, it won't be used unless enabled on both sides). At the time
of this writing, <small>SRP</small> is too new to be trusted, at least
according to conservative cryptographers (and remember that conservatism
is a virtue when it comes to security).
of this writing, <small>SRP</small> is too new to be trusted by conservative
cryptographers (and remember that conservatism is a virtue when it comes
to security).
<p>And even if <small>SRP</small> in itself is secure, the way <code>lsh</code>
integrates it into the <code>ssh</code> protocol has not had much peer review.
The bottom line of this disclaimer is that the <small>SRP</small> support in
<code>lsh</code> should be considered experimental.
<p>As far as I know, <small>SRP</small> is not supported by any other <code>ssh</code>
implementation. The protocol <code>lsh</code> uses is described in the
<code>doc/srp-spec.txt</code>.
<p>As far as I know, using <small>SRP</small> as a host authentication mechanism
is not supported by any other <code>ssh</code> implementation. The protocol
<code>lsh</code> uses is described in the <code>doc/srp-spec.txt</code>.
Implementations that use <small>SRP</small> only as a user authentication
mechanism are not compatible with <code>lsh</code>.
<p><hr>
Node:<a name="sexp">sexp</a>,
@ -778,7 +787,7 @@ Up:<a rel=up href="#Getting%20started">Getting started</a>
<p>Keys and most other objects <code>lsh</code> needs to store on disk are
represented as so called S-expressions or <dfn>sexps</dfn> for short.
S-expressions have their roots in the Lisp world, and a variant of them
are used in the Simple Public Key Infrastructure (<small>SPKI</small>).
in used in the Simple Public Key Infrastructure (<small>SPKI</small>).
Currently, <code>lsh</code>'s support for <small>SPKI</small> is quite limited,
but it uses <small>SPKI</small>'s formats for keys and Access Control Lists
(<small>ACL</small>:s).
@ -826,10 +835,9 @@ one or more personal keypairs, you need to convert the public keys to
</pre>
<p>You can then use the usual <code>lsh-authorize</code> on the converted
keys. For this to work, you must be using <small>DSA</small> keys:
<code>lsh</code> doesn't support <code>RSA</code>.
keys. <code>ssh-conv</code> supports both <small>DSA</small> and <code>RSA</code> keys.
<p>There is currently no tools for converting private keys.
<p>There are currently no tools for converting private keys.
<p><hr>
Node:<a name="Invoking%20lsh">Invoking lsh</a>,
@ -1014,11 +1022,6 @@ currently not implemented.
<br><dt><code>--no-publickey</code>
<dd>Don't attempt to log in using public key authentication.
<br><dt><code>--no-userauth</code>
<dd>Attempt to start a session without performing the user authentication
sub-protocol at all. This is the default if <small>SRP</small> was used for
the initial handshake, and should not make much sense otherwise.
</dl>
<p><hr>
@ -1075,14 +1078,16 @@ executed on the remote machine.
<br><dt><code>-G</code>
<dd>Open a gateway on the local machine. A gateway is a local socket,
located under /tmp, that can be used for controlling and using the ssh
connection. It is protected using the ordinary file permissions. This
feature is experimental.
connection. It is protected using the ordinary file permissions.
<br><dt><code>-N</code>
<dd>This is a no-operation action. It inhibits the default action, which is
to start an interactive shell on the remote machine. It is useful if you
want to set up a few forwarded tunnels, and nothing more.
want to set up a few forwarded tunnels or a gateway, and nothing more.
<br><dt><code>-B</code>
<dd>Put the client into the background after key exchange and
user authentication. Implies <code>-N</code>
</dl>
<p>If there are trailing arguments after the name of the remote system,
@ -1111,6 +1116,10 @@ applies to actions that create remote processes, i.e. <code>-E</code> and
<p>Currently, this option is ignored if there is no local terminal.
<br><dt><code>-x</code>
<dd>Request <small>X</small> forwarding. Applies to the <small>-E</small> and
<code>S</code> and the default actions.
<br><dt><code>--stdin</code>
<dd>Redirect the stdin of a remote process from a given, local, file.
Default is to use <code>lsh</code>'s stdin for the first process, and
@ -1129,7 +1138,7 @@ after it is used.
Analogous to the <code>--stdout</code> option.
<br><dt><code>-g</code>
<dd>Remote peers, aka Global forwarding. This option applies to the
<dd>Remote peers, aka global forwarding. This option applies to the
forwarding actions, i.e. <code>-L</code> and <code>-R</code>. By default, only
connections to the loopback interface, ip 127.0.0.1, are forwared. This
implies that only processes on the same machine can use the forwarded
@ -1170,6 +1179,10 @@ sent and received packets. It tries to avoid dumping highly sensitive data,
such as private keys and the contents of <code>SSH_MSG_USERAUTH_REQUEST</code>
messages, but you should still use it with care.
<br><dt><code>--log-file</code>
<dd>This option redirects all messages to a file. Takes one mandatory
argument: The name of that file.
</dl>
<p>Note that all these options are orthogonal. If you use <code>--trace</code>,
@ -1278,7 +1291,7 @@ details.
<br><dt><code>--login-shell</code>
<dd>Use the specified program as the login shell for all users, overriding
the login shell in the passwd database.
the login shell in the passwd database. Mainly useful for testing.
<br><dt><code>--srp-keyexchange</code>
<dd>Enable <small>SRP</small> keyexchange and user authentication.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -16,6 +16,11 @@ autoconf
(cd src/argp && autoconf)
(cd src/argp && autoheader)
automake -a
(cd src/nettle && ./.bootstrap)
(cd src/sftp && ./.bootstrap)
automake -a Makefile src/Makefile
(cd src/argp && automake -a)
(cd src/nettle && automake -a)
(cd src/sftp && automake -a)

View File

@ -5,5 +5,8 @@
# && grep -v '^rsa.c.x$' < src/.dist_classes-old > src/.dist_classes
# }
make && (cd src/testsuite && make check-more) && \
# make && (cd src/testsuite && make check-more) && \
# ./make_am --rethink && ./make_am && make && make distcheck
make && \
./make_am --rethink && ./make_am && make && make distcheck

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -118,10 +118,22 @@ mac_string(struct mac_algorithm *a,
struct lsh_string *
crypt_string(struct crypto_instance *c,
struct lsh_string *in,
const struct lsh_string *in,
int free)
{
struct lsh_string *out = (free ? in : lsh_string_alloc(in->length));
struct lsh_string *out;
if (free)
{
/* Do the encryption in place. The type cast is permissible
* because we're conceptually freeing the string and reusing the
* storage. */
out = (struct lsh_string *) in;
}
else
/* Allocate fresh storage. */
out = lsh_string_alloc(in->length);
CRYPT(c, in->length, in->data, out->data);
return out;
@ -131,7 +143,7 @@ crypt_string(struct crypto_instance *c,
* keys */
struct lsh_string *
crypt_string_pad(struct crypto_instance *c,
struct lsh_string *in,
const struct lsh_string *in,
int free)
{
struct lsh_string *s;
@ -150,7 +162,7 @@ crypt_string_pad(struct crypto_instance *c,
struct lsh_string *
crypt_string_unpad(struct crypto_instance *c,
struct lsh_string *in,
const struct lsh_string *in,
int free)
{
struct lsh_string *out;

Binary file not shown.

View File

@ -228,17 +228,17 @@ mac_string(struct mac_algorithm *a,
struct lsh_string *
crypt_string(struct crypto_instance *c,
struct lsh_string *in,
const struct lsh_string *in,
int free);
struct lsh_string *
crypt_string_pad(struct crypto_instance *c,
struct lsh_string *in,
const struct lsh_string *in,
int free);
struct lsh_string *
crypt_string_unpad(struct crypto_instance *c,
struct lsh_string *in,
const struct lsh_string *in,
int free);
#endif /* LSH_ABSTRACT_CRYPTO_H_INCLUDED */

Binary file not shown.

Binary file not shown.

View File

@ -49,10 +49,8 @@ extern int strcasecmp(const char * str1, const char * str2);
struct alist *
all_symmetric_algorithms()
{
return make_alist(9
#if WITH_IDEA
+1
#endif
struct crypto_algorithm *aes = crypto_cbc(&rijndael256_algorithm);
return make_alist(10
#if WITH_ZLIB
+1
#endif
@ -60,7 +58,8 @@ all_symmetric_algorithms()
ATOM_ARCFOUR, &crypto_arcfour_algorithm,
ATOM_BLOWFISH_CBC, crypto_cbc(&blowfish_algorithm),
ATOM_TWOFISH_CBC, crypto_cbc(&twofish256_algorithm),
ATOM_RIJNDAEL_CBC_LOCAL, crypto_cbc(&rijndael256_algorithm),
ATOM_AES256_CBC, aes,
ATOM_RIJNDAEL_CBC_LOCAL, aes,
ATOM_SERPENT_CBC_LOCAL, crypto_cbc(&serpent256_algorithm),
ATOM_3DES_CBC, crypto_cbc(make_des3()),
ATOM_CAST128_CBC, crypto_cbc(&cast128_algorithm),
@ -106,11 +105,12 @@ default_crypto_algorithms(struct alist *algorithms)
static struct int_list *
all_crypto_algorithms(struct alist *algorithms)
{
return filter_algorithms_l(algorithms, 8,
return filter_algorithms_l(algorithms, 9,
ATOM_3DES_CBC,
ATOM_TWOFISH_CBC,
ATOM_CAST128_CBC,
ATOM_SERPENT_CBC_LOCAL,
ATOM_AES256_CBC,
ATOM_RIJNDAEL_CBC_LOCAL,
ATOM_IDEA_CBC,
ATOM_BLOWFISH_CBC,
@ -177,6 +177,8 @@ lookup_crypto(struct alist *algorithms, const char *name, struct crypto_algorith
atom = ATOM_BLOWFISH_CBC;
else if (strcasecmp_list(name, "3des-cbc", "3des", NULL))
atom = ATOM_3DES_CBC;
else if (strcasecmp_list(name, "aes256-cbc", "aes-cbc", "aes", NULL))
atom = ATOM_AES256_CBC;
else if (strcasecmp_list(name, "rijndael-cbc@lysator.liu.se",
"rijndael-cbc", "rijndael", NULL))
atom = ATOM_RIJNDAEL_CBC_LOCAL;

Binary file not shown.

View File

@ -57,20 +57,6 @@ alist_addv(struct alist *a, unsigned n, va_list args)
return a;
}
#if 0
struct alist
*alist_add(struct alist *a, unsigned n, ...)
{
va_list args;
va_start(args, n);
alist_addv(a, n, args);
va_end(args);
return a;
}
#endif
struct alist_node
{
struct alist_node *next;

Binary file not shown.

View File

@ -67,9 +67,6 @@ struct alist;
(ALIST_CLASS(alist)->set((alist), (atom), (value)))
struct alist *alist_addv(struct alist *a, unsigned n, va_list args);
#if 0
struct alist *alist_add(struct alist *a, unsigned n, ...);
#endif
/* n is the number of pairs. The argument list should be terminated
* with -1, for sanity checks. */

Binary file not shown.

View File

@ -26,7 +26,7 @@
#include "werror.h"
#include "xalloc.h"
#include "arcfour.h"
#include "nettle/arcfour.h"
#include "arcfour.c.x"
@ -46,7 +46,7 @@ static void do_crypt_arcfour(struct crypto_instance *s,
if (length % 8)
fatal("Internal error\n");
arcfour_crypt(&self->ctx, dst, length, src);
arcfour_crypt(&self->ctx, length, dst, src);
}
static struct crypto_instance *

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lsh/src/argp/configure vendored

Binary file not shown.

View File

@ -1,7 +1,7 @@
/* ANSI-C code produced by gperf version 2.7 */
/* Command-line: gperf -LANSI-C -t -c -C -l -k1,3,6,10,$ -N gperf_atom */
/* Automatically generated by process_atoms,
* Sat Mar 17 21:49:57 CET 2001
* Tue Jun 26 23:51:53 CEST 2001
* Do not edit! */
struct atom_assoc { const char *name; int id; };
@ -118,218 +118,218 @@ gperf_atom (register const char *str, register unsigned int len)
};
static const struct atom_assoc wordlist[] =
{
{""},
{"", 0},
{"s", ATOM_S},
{""},
{"", 0},
{"set", ATOM_SET},
{"hash", ATOM_HASH},
{""}, {""},
{"", 0}, {"", 0},
{"ssh-dss", ATOM_SSH_DSS},
{""},
{"", 0},
{"salt", ATOM_SALT},
{""},
{"", 0},
{"*", ATOM_STAR},
{""}, {""},
{"", 0}, {"", 0},
{"TERM", ATOM_TERM},
{""},
{"", 0},
{"ABRT", ATOM_ABRT},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"ALRM", ATOM_ALRM},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0},
{"ssh-userauth", ATOM_SSH_USERAUTH},
{"INT", ATOM_INT},
{"PIPE", ATOM_PIPE},
{""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0},
{"HUP", ATOM_HUP},
{""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0},
{"ssh-rsa", ATOM_SSH_RSA},
{"ILL", ATOM_ILL},
{""}, {""},
{"", 0}, {"", 0},
{"q", ATOM_Q},
{""},
{"", 0},
{"acl", ATOM_ACL},
{"QUIT", ATOM_QUIT},
{"auth-ssh1-agent", ATOM_AUTH_SSH1_AGENT},
{""}, {""},
{"", 0}, {"", 0},
{"md5", ATOM_MD5},
{"SEGV", ATOM_SEGV},
{""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0},
{"KILL", ATOM_KILL},
{""}, {""},
{"", 0}, {"", 0},
{"iv", ATOM_IV},
{""}, {""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"sha1", ATOM_SHA1},
{""},
{"", 0},
{"signal", ATOM_SIGNAL},
{""},
{"", 0},
{"FPE", ATOM_FPE},
{"hmac-sha1", ATOM_HMAC_SHA1},
{""},
{"", 0},
{"a", ATOM_A},
{"session", ATOM_SESSION},
{""},
{"", 0},
{"auth-ssh1-agent-req", ATOM_AUTH_SSH1_AGENT_REQ},
{""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"auth-agent", ATOM_AUTH_AGENT},
{"r", ATOM_R},
{""},
{"", 0},
{"hmac-md5", ATOM_HMAC_MD5},
{"USR1", ATOM_USR1},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"hmac-sha1-96", ATOM_HMAC_SHA1_96},
{""},
{"", 0},
{"ssh-ring1", ATOM_SSH_RING1},
{""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0},
{"USR2", ATOM_USR2},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"auth-agent-req", ATOM_AUTH_AGENT_REQ},
{""},
{"", 0},
{"g", ATOM_G},
{""},
{"", 0},
{"tag", ATOM_TAG},
{""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0},
{"version", ATOM_VERSION},
{"env", ATOM_ENV},
{"subsystem", ATOM_SUBSYSTEM},
{""},
{"", 0},
{"n", ATOM_N},
{""}, {""},
{"", 0}, {"", 0},
{"data", ATOM_DATA},
{"shell", ATOM_SHELL},
{"hmac-md5-96", ATOM_HMAC_MD5_96},
{""},
{"", 0},
{"spki-sign-dss", ATOM_SPKI_SIGN_DSS},
{"hostbased", ATOM_HOSTBASED},
{""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0},
{"x11", ATOM_X11},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"p", ATOM_P},
{"twofish128-cbc", ATOM_TWOFISH128_CBC},
{""}, {""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"ssh-dss-kludge@lysator.liu.se", ATOM_SSH_DSS_KLUDGE_LOCAL},
{""},
{"", 0},
{"x", ATOM_X},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"b", ATOM_B},
{""},
{"", 0},
{"dsa", ATOM_DSA},
{""},
{"", 0},
{"x509v3-sign-dss", ATOM_X509V3_SIGN_DSS},
{""},
{"", 0},
{"twofish192-cbc", ATOM_TWOFISH192_CBC},
{"spki-sign-rsa", ATOM_SPKI_SIGN_RSA},
{""}, {""},
{"", 0}, {"", 0},
{"d", ATOM_D},
{"twofish256-cbc", ATOM_TWOFISH256_CBC},
{"password", ATOM_PASSWORD},
{""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0},
{"tcpip-forward", ATOM_TCPIP_FORWARD},
{"zlib", ATOM_ZLIB},
{""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0},
{"Xpkcs5v2", ATOM_XPKCS5V2},
{"signature", ATOM_SIGNATURE},
{""}, {""},
{"", 0}, {"", 0},
{"ssh-connection", ATOM_SSH_CONNECTION},
{""}, {""},
{"", 0}, {"", 0},
{"iterations", ATOM_ITERATIONS},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0},
{"y", ATOM_Y},
{""},
{"", 0},
{"xon-xoff", ATOM_XON_XOFF},
{"twofish-cbc", ATOM_TWOFISH_CBC},
{"x509v3-sign-rsa", ATOM_X509V3_SIGN_RSA},
{""},
{"", 0},
{"c", ATOM_C},
{""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"sequence", ATOM_SEQUENCE},
{""},
{"", 0},
{"arcfour", ATOM_ARCFOUR},
{"exit-status", ATOM_EXIT_STATUS},
{""}, {""},
{"", 0}, {"", 0},
{"name", ATOM_NAME},
{"forwarded-tcpip", ATOM_FORWARDED_TCPIP},
{""}, {""},
{"", 0}, {"", 0},
{"rsa-pkcs1-md5", ATOM_RSA_PKCS1_MD5},
{""},
{"", 0},
{"entry", ATOM_ENTRY},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0},
{"exit-signal", ATOM_EXIT_SIGNAL},
{""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0},
{"e", ATOM_E},
{"serpent128-cbc", ATOM_SERPENT128_CBC},
{""},
{"", 0},
{"rsa-pkcs1-sha1", ATOM_RSA_PKCS1_SHA1},
{""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0},
{"none", ATOM_NONE},
{""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0},
{"window-change", ATOM_WINDOW_CHANGE},
{""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0},
{"x11-req", ATOM_X11_REQ},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"serpent192-cbc", ATOM_SERPENT192_CBC},
{""},
{"", 0},
{"propagate", ATOM_PROPAGATE},
{""}, {""},
{"", 0}, {"", 0},
{"serpent256-cbc", ATOM_SERPENT256_CBC},
{""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0},
{"aes128-cbc", ATOM_AES128_CBC},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"srp-ring1-sha1@lysator.liu.se", ATOM_SRP_RING1_SHA1_LOCAL},
{""}, {""},
{"", 0}, {"", 0},
{"direct-tcpip", ATOM_DIRECT_TCPIP},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0}, {"", 0}, {"", 0}, {"", 0},
{"aes192-cbc", ATOM_AES192_CBC},
{"pgp-sign-rsa", ATOM_PGP_SIGN_RSA},
{""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0},
{"aes256-cbc", ATOM_AES256_CBC},
{"pgp-sign-dss", ATOM_PGP_SIGN_DSS},
{"password-encrypted", ATOM_PASSWORD_ENCRYPTED},
{""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0},
{"srp-verifier", ATOM_SRP_VERIFIER},
{""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0},
{"diffie-hellman-group1-sha1", ATOM_DIFFIE_HELLMAN_GROUP1_SHA1},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0},
{"pty-req", ATOM_PTY_REQ},
{""},
{"", 0},
{"certificate", ATOM_CERTIFICATE},
{""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0},
{"signal-unknown@lysator.liu.se", ATOM_SIGNAL_UNKNOWN_LOCAL},
{"rijndael-cbc@lysator.liu.se", ATOM_RIJNDAEL_CBC_LOCAL},
{"serpent-cbc@lysator.liu.se", ATOM_SERPENT_CBC_LOCAL},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0},
{"cast128-cbc", ATOM_CAST128_CBC},
{""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0},
{"exec", ATOM_EXEC},
{"cancel-tcpip-forward", ATOM_CANCEL_TCPIP_FORWARD},
{""}, {""},
{"", 0}, {"", 0},
{"prefix", ATOM_PREFIX},
{""}, {""},
{"", 0}, {"", 0},
{"3des-cbc", ATOM_3DES_CBC},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0}, {"", 0},
{"private-key", ATOM_PRIVATE_KEY},
{"publickey", ATOM_PUBLICKEY},
{""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"blowfish-cbc", ATOM_BLOWFISH_CBC},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"idea-cbc", ATOM_IDEA_CBC},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
{"", 0},
{"public-key", ATOM_PUBLIC_KEY}
};

View File

@ -26,7 +26,7 @@
#include "werror.h"
#include "xalloc.h"
#include "blowfish.h"
#include "nettle/blowfish.h"
#include <assert.h>
@ -38,7 +38,7 @@
(name blowfish_instance)
(super crypto_instance)
(vars
(ctx . "BLOWFISH_context")))
(ctx . "struct blowfish_ctx")))
*/
static void
@ -47,8 +47,7 @@ do_blowfish_encrypt(struct crypto_instance *s,
{
CAST(blowfish_instance, self, s);
FOR_BLOCKS(length, src, dst, BLOWFISH_BLOCKSIZE)
bf_encrypt_block(&self->ctx, dst, src);
blowfish_encrypt(&self->ctx, length, dst, src);
}
static void
@ -57,8 +56,7 @@ do_blowfish_decrypt(struct crypto_instance *s,
{
CAST(blowfish_instance, self, s);
FOR_BLOCKS(length, src, dst, BLOWFISH_BLOCKSIZE)
bf_decrypt_block(&self->ctx, dst, src);
blowfish_decrypt(&self->ctx, length, dst, src);
}
static struct crypto_instance *
@ -67,16 +65,15 @@ make_blowfish_instance(struct crypto_algorithm *algorithm, int mode,
{
NEW(blowfish_instance, self);
self->super.block_size = BLOWFISH_BLOCKSIZE;
self->super.block_size = BLOWFISH_BLOCK_SIZE;
self->super.crypt = ( (mode == CRYPTO_ENCRYPT)
? do_blowfish_encrypt
: do_blowfish_decrypt);
switch (bf_set_key(&self->ctx, key, algorithm->key_size))
{
case 0:
if (blowfish_set_key(&self->ctx, algorithm->key_size, key))
return &self->super;
default:
else
{
werror("Detected a weak blowfish key!\n");
KILL(self);
return NULL;
@ -88,10 +85,10 @@ make_blowfish_algorithm(UINT32 key_size)
{
NEW(crypto_algorithm, algorithm);
assert(key_size <= BLOWFISH_MAX_KEYSIZE);
assert(key_size >= BLOWFISH_MIN_KEYSIZE);
assert(key_size <= BLOWFISH_MAX_KEY_SIZE);
assert(key_size >= BLOWFISH_MIN_KEY_SIZE);
algorithm->block_size = BLOWFISH_BLOCKSIZE;
algorithm->block_size = BLOWFISH_BLOCK_SIZE;
algorithm->key_size = key_size;
algorithm->iv_size = 0;
algorithm->make_crypt = make_blowfish_instance;
@ -100,4 +97,5 @@ make_blowfish_algorithm(UINT32 key_size)
}
struct crypto_algorithm blowfish_algorithm =
{ STATIC_HEADER, BLOWFISH_BLOCKSIZE, BLOWFISH_KEYSIZE, 0, make_blowfish_instance};
{ STATIC_HEADER, BLOWFISH_BLOCK_SIZE, BLOWFISH_KEY_SIZE,
0, make_blowfish_instance};

Binary file not shown.

Binary file not shown.

View File

@ -27,7 +27,7 @@
#include "werror.h"
#include "xalloc.h"
#include "cast.h"
#include "nettle/cast128.h"
#include <assert.h>
@ -41,26 +41,26 @@ struct crypto_algorithm *make_cast_algorithm(UINT32 key_size);
(name cast_instance)
(super crypto_instance)
(vars
(ctx . "struct cast_key")))
(ctx . "struct cast128_ctx")))
*/
static void do_cast_encrypt(struct crypto_instance *s,
static void
do_cast_encrypt(struct crypto_instance *s,
UINT32 length, const UINT8 *src, UINT8 *dst)
{
CAST(cast_instance, self, s);
FOR_BLOCKS(length, src, dst, CAST_BLOCKSIZE)
cast_encrypt(&self->ctx, src, dst);
cast128_encrypt(&self->ctx, length, dst, src);
}
static void do_cast_decrypt(struct crypto_instance *s,
static void
do_cast_decrypt(struct crypto_instance *s,
UINT32 length, const UINT8 *src, UINT8 *dst)
{
CAST(cast_instance, self, s);
FOR_BLOCKS(length, src, dst, CAST_BLOCKSIZE)
cast_decrypt(&self->ctx, src, dst);
cast128_decrypt(&self->ctx, length, dst, src);
}
static struct crypto_instance *
@ -69,12 +69,12 @@ make_cast_instance(struct crypto_algorithm *algorithm, int mode,
{
NEW(cast_instance, self);
self->super.block_size = CAST_BLOCKSIZE;
self->super.block_size = CAST128_BLOCK_SIZE;
self->super.crypt = ( (mode == CRYPTO_ENCRYPT)
? do_cast_encrypt
: do_cast_decrypt);
cast_setkey(&self->ctx, key, algorithm->key_size);
cast128_set_key(&self->ctx, algorithm->key_size, key);
return &self->super;
}
@ -82,10 +82,10 @@ struct crypto_algorithm *make_cast_algorithm(UINT32 key_size)
{
NEW(crypto_algorithm, algorithm);
assert(key_size <= CAST_MAX_KEYSIZE);
assert(key_size >= CAST_MIN_KEYSIZE);
assert(key_size <= CAST128_MAX_KEY_SIZE);
assert(key_size >= CAST128_MIN_KEY_SIZE);
algorithm->block_size = CAST_BLOCKSIZE;
algorithm->block_size = CAST128_BLOCK_SIZE;
algorithm->key_size = key_size;
algorithm->iv_size = 0;
algorithm->make_crypt = make_cast_instance;
@ -94,4 +94,4 @@ struct crypto_algorithm *make_cast_algorithm(UINT32 key_size)
}
struct crypto_algorithm cast128_algorithm =
{ STATIC_HEADER, CAST_BLOCKSIZE, CAST_MAX_KEYSIZE, 0, make_cast_instance};
{ STATIC_HEADER, CAST128_BLOCK_SIZE, CAST128_MAX_KEY_SIZE, 0, make_cast_instance};

Binary file not shown.

View File

@ -32,7 +32,7 @@
#include "cbc.c.x"
#if !HAVE_MEMXOR
#include "memxor.h"
#include "nettle/memxor.h"
#endif
/* GABA:

Binary file not shown.

View File

@ -176,10 +176,6 @@ do_exc_finish_channel_handler(struct exception_handler *s,
* code in a live channel is supposed to raise
* EXC_FINISH_PENDING. The typical caller is a channel's
* CHANNEL_CLOSE callback that is called below. */
#if 0
if (!self->connection->table->channel_count)
EXCEPTION_RAISE(self->connection->e, &finish_read_exception);
#endif
break;
case EXC_FINISH_CHANNEL:
@ -274,6 +270,7 @@ make_channel_table(void)
object_queue_init(&table->local_ports);
object_queue_init(&table->remote_ports);
table->x11_display = NULL;
object_queue_init(&table->active_global_requests);
object_queue_init(&table->pending_global_requests);
@ -329,6 +326,7 @@ alloc_channel(struct channel_table *table)
table->next_channel = table->used_channels = i+1;
table->in_use[i] = CHANNEL_RESERVED;
table->channels[i] = NULL;
success:
table->channel_count++;
@ -369,13 +367,13 @@ use_channel(struct ssh_connection *connection,
channel->channel_number, local_channel_number);
}
/* FIXME: Delete connection argument */
void
register_channel(struct ssh_connection *connection,
UINT32 local_channel_number,
register_channel(UINT32 local_channel_number,
struct ssh_channel *channel,
int take_into_use)
{
struct channel_table *table = connection->table;
struct channel_table *table = channel->connection->table;
assert(table->in_use[local_channel_number] == CHANNEL_RESERVED);
assert(!table->channels[local_channel_number]);
@ -385,17 +383,19 @@ register_channel(struct ssh_connection *connection,
/* NOTE: Is this the right place to install this exception handler? */
channel->e =
make_exc_finish_channel_handler(connection,
make_exc_finish_channel_handler(channel->connection,
local_channel_number,
channel->e ? channel->e : connection->e,
(channel->e ? channel->e
: channel->connection->e),
HANDLER_CONTEXT);
table->channels[local_channel_number] = channel;
if (take_into_use)
use_channel(connection, local_channel_number);
use_channel(channel->connection, local_channel_number);
REMEMBER_RESOURCE(connection->resources, &channel->resources->super);
REMEMBER_RESOURCE(channel->connection->resources,
&channel->resources->super);
}
struct ssh_channel *
@ -433,7 +433,7 @@ adjust_rec_window(struct flow_controlled *f, UINT32 written)
* may live longer than the actual channel. */
if (! (channel->flags & (CHANNEL_RECEIVED_EOF | CHANNEL_RECEIVED_CLOSE
| CHANNEL_SENT_CLOSE)))
A_WRITE(channel->write,
C_WRITE(channel->connection,
prepare_window_adjust(channel, written));
}
@ -442,21 +442,11 @@ channel_start_receive(struct ssh_channel *channel,
UINT32 initial_window_size)
{
if (channel->rec_window_size < initial_window_size)
A_WRITE(channel->write,
C_WRITE(channel->connection,
prepare_window_adjust
(channel, initial_window_size - channel->rec_window_size));
}
/* Ugly macros to make it a little simpler to free the input packet at
* the right time. */
#define RETURN goto foo_finish
#define END(s) do { foo_finish: \
lsh_string_free((s)); \
return; } while(0)
/* Channel related messages */
/* GABA:
@ -608,8 +598,6 @@ DEFINE_PACKET_HANDLER(static, global_request_handler, connection, packet)
}
if (!req)
{
lsh_string_free(packet);
C_WRITE(connection, format_global_failure());
return;
}
@ -639,10 +627,7 @@ DEFINE_PACKET_HANDLER(static, global_request_handler, connection, packet)
}
}
else
{
PROTOCOL_ERROR(connection->e, "Invalid SSH_MSG_GLOBAL_REQUEST message.");
}
lsh_string_free(packet);
}
DEFINE_PACKET_HANDLER(static, global_success_handler,
@ -651,7 +636,7 @@ DEFINE_PACKET_HANDLER(static, global_success_handler,
if (packet->length != 1)
{
PROTOCOL_ERROR(connection->e, "Invalid GLOBAL_REQUEST_SUCCESS message.");
RETURN;
return;
}
assert(packet->data[0] == SSH_MSG_REQUEST_SUCCESS);
@ -666,7 +651,6 @@ DEFINE_PACKET_HANDLER(static, global_success_handler,
object_queue_remove_head(&connection->table->pending_global_requests));
COMMAND_RETURN(ctx->c, connection);
}
END(packet);
}
struct exception global_request_exception =
@ -678,7 +662,7 @@ DEFINE_PACKET_HANDLER(static, global_failure_handler,
if (packet->length != 1)
{
PROTOCOL_ERROR(connection->e, "Invalid GLOBAL_REQUEST_FAILURE message.");
RETURN;
return;
}
assert(packet->data[0] == SSH_MSG_REQUEST_FAILURE);
@ -693,7 +677,6 @@ DEFINE_PACKET_HANDLER(static, global_failure_handler,
object_queue_remove_head(&connection->table->pending_global_requests));
EXCEPTION_RAISE(ctx->e, &global_request_exception);
}
END(packet);
}
/* FIXME: Don't store the channel here, instead have it passed as the
@ -705,11 +688,13 @@ DEFINE_PACKET_HANDLER(static, global_failure_handler,
(name channel_request_continuation)
(super command_continuation)
(vars
;; FIXME: Delete connection argument
(connection object ssh_connection)
(channel object ssh_channel)
(active object request_status)))
*/
/* FIXME: Delete connection argument */
static void
send_channel_request_responses(struct ssh_connection *connection,
struct ssh_channel *channel,
@ -745,6 +730,7 @@ do_channel_request_response(struct command_continuation *s,
send_channel_request_responses(self->connection, self->channel, q);
}
/* FIXME: Delete connection argument */
static struct command_continuation *
make_channel_request_response(struct ssh_connection *connection,
struct ssh_channel *channel,
@ -765,6 +751,7 @@ make_channel_request_response(struct ssh_connection *connection,
(name channel_request_exception_handler)
(super exception_handler)
(vars
;; FIXME: Delete connection argument
(connection object ssh_connection)
(channel object ssh_channel)
(active object request_status)))
@ -791,6 +778,7 @@ do_exc_channel_request_handler(struct exception_handler *c,
EXCEPTION_RAISE(c->parent, e);
}
/* FIXME: Delete connection argument */
static struct exception_handler *
make_channel_request_exception_handler(struct ssh_connection *connection,
struct ssh_channel *channel,
@ -887,7 +875,7 @@ DEFINE_PACKET_HANDLER(static, channel_request_handler,
e, HANDLER_CONTEXT);
}
CHANNEL_REQUEST(req, channel, connection, &info, &buffer, c, e);
CHANNEL_REQUEST(req, channel, &info, &buffer, c, e);
}
else
{
@ -904,8 +892,6 @@ DEFINE_PACKET_HANDLER(static, channel_request_handler,
}
else
PROTOCOL_ERROR(connection->e, "Invalid SSH_MSG_CHANNEL_REQUEST message.");
lsh_string_free(packet);
}
@ -937,11 +923,10 @@ do_channel_open_continue(struct command_continuation *c,
channel->send_max_packet = self->send_max_packet;
channel->channel_number = self->remote_channel_number;
/* FIXME: Is the channel->write field really needed? */
channel->write = self->connection->write;
channel->connection = self->connection;
register_channel(self->connection,
self->local_channel_number, channel,
register_channel(self->local_channel_number,
channel,
1);
/* FIXME: Doesn't support sending extra arguments with the
@ -1135,8 +1120,6 @@ DEFINE_PACKET_HANDLER(static, channel_open_handler,
}
else
PROTOCOL_ERROR(connection->e, "Invalid SSH_MSG_CHANNEL_OPEN message.");
lsh_string_free(packet);
}
DEFINE_PACKET_HANDLER(static, window_adjust_handler,
@ -1158,8 +1141,6 @@ DEFINE_PACKET_HANDLER(static, window_adjust_handler,
struct ssh_channel *channel = lookup_channel(connection->table,
channel_number);
lsh_string_free(packet);
if (channel
&& !(channel->flags & CHANNEL_RECEIVED_CLOSE))
{
@ -1181,10 +1162,7 @@ DEFINE_PACKET_HANDLER(static, window_adjust_handler,
}
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(connection->e, "Invalid CHANNEL_WINDOW_ADJUST message.");
}
}
DEFINE_PACKET_HANDLER(static, channel_data_handler,
@ -1206,8 +1184,6 @@ DEFINE_PACKET_HANDLER(static, channel_data_handler,
struct ssh_channel *channel = lookup_channel(connection->table,
channel_number);
lsh_string_free(packet);
if (channel && channel->receive
&& !(channel->flags & (CHANNEL_RECEIVED_EOF
| CHANNEL_RECEIVED_CLOSE)))
@ -1255,10 +1231,7 @@ DEFINE_PACKET_HANDLER(static, channel_data_handler,
}
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(connection->e, "Invalid CHANNEL_DATA message.");
}
}
DEFINE_PACKET_HANDLER(static, channel_extended_data_handler,
@ -1282,8 +1255,6 @@ DEFINE_PACKET_HANDLER(static, channel_extended_data_handler,
struct ssh_channel *channel = lookup_channel(connection->table,
channel_number);
lsh_string_free(packet);
if (channel && channel->receive
&& !(channel->flags & (CHANNEL_RECEIVED_EOF
| CHANNEL_RECEIVED_CLOSE)))
@ -1341,10 +1312,7 @@ DEFINE_PACKET_HANDLER(static, channel_extended_data_handler,
}
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(connection->e, "Invalid CHANNEL_EXTENDED_DATA message.");
}
}
DEFINE_PACKET_HANDLER(static, channel_eof_handler,
@ -1364,8 +1332,6 @@ DEFINE_PACKET_HANDLER(static, channel_eof_handler,
struct ssh_channel *channel = lookup_channel(connection->table,
channel_number);
lsh_string_free(packet);
if (channel)
{
if (channel->flags & (CHANNEL_RECEIVED_EOF | CHANNEL_RECEIVED_CLOSE))
@ -1407,10 +1373,7 @@ DEFINE_PACKET_HANDLER(static, channel_eof_handler,
}
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(connection->e, "Invalid CHANNEL_EOF message");
}
}
DEFINE_PACKET_HANDLER(static, channel_close_handler,
@ -1430,8 +1393,6 @@ DEFINE_PACKET_HANDLER(static, channel_close_handler,
struct ssh_channel *channel = lookup_channel(connection->table,
channel_number);
lsh_string_free(packet);
if (channel)
{
verbose("Receiving CLOSE on channel %i (local %i)\n",
@ -1452,13 +1413,6 @@ DEFINE_PACKET_HANDLER(static, channel_close_handler,
werror("Unexpected channel CLOSE.\n");
}
#if 0
/* FIXME: Which eof-handlers rely on being called in
* this case? */
if (! (channel->flags & (CHANNEL_RECEIVED_EOF))
&& channel->eof)
CHANNEL_EOF(channel);
#endif
if (channel->flags & CHANNEL_SENT_CLOSE)
{
static const struct exception finish_exception
@ -1479,10 +1433,7 @@ DEFINE_PACKET_HANDLER(static, channel_close_handler,
}
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(connection->e, "Invalid CHANNEL_CLOSE message");
}
}
DEFINE_PACKET_HANDLER(static, channel_open_confirm_handler,
@ -1509,8 +1460,6 @@ DEFINE_PACKET_HANDLER(static, channel_open_confirm_handler,
lookup_channel_reserved(connection->table,
local_channel_number);
lsh_string_free(packet);
if (channel)
{
struct command_continuation *c = channel->open_continuation;
@ -1535,10 +1484,7 @@ DEFINE_PACKET_HANDLER(static, channel_open_confirm_handler,
}
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(connection->e, "Invalid CHANNEL_OPEN_CONFIRMATION message.");
}
}
DEFINE_PACKET_HANDLER(static, channel_open_failure_handler,
@ -1569,8 +1515,6 @@ DEFINE_PACKET_HANDLER(static, channel_open_failure_handler,
lookup_channel_reserved(connection->table,
channel_number);
lsh_string_free(packet);
if (channel)
{
static const struct exception finish_exception
@ -1588,10 +1532,7 @@ DEFINE_PACKET_HANDLER(static, channel_open_failure_handler,
channel_number);
}
else
{
PROTOCOL_ERROR(connection->e, "Invalid CHANNEL_OPEN_FAILURE message.");
lsh_string_free(packet);
}
}
DEFINE_PACKET_HANDLER(static, channel_success_handler,
@ -1610,8 +1551,6 @@ DEFINE_PACKET_HANDLER(static, channel_success_handler,
&& parse_eod(&buffer)
&& (channel = lookup_channel(connection->table, channel_number)))
{
lsh_string_free(packet);
if (object_queue_is_empty(&channel->pending_requests))
{
werror("do_channel_success: Unexpected message. Ignoring.\n");
@ -1625,10 +1564,7 @@ DEFINE_PACKET_HANDLER(static, channel_success_handler,
}
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(connection->e, "Invalid CHANNEL_SUCCESS message");
}
}
DEFINE_PACKET_HANDLER(static, channel_failure_handler,
@ -1647,8 +1583,6 @@ DEFINE_PACKET_HANDLER(static, channel_failure_handler,
&& parse_eod(&buffer)
&& (channel = lookup_channel(connection->table, channel_number)))
{
lsh_string_free(packet);
if (object_queue_is_empty(&channel->pending_requests))
{
werror("do_channel_failure: No handler. Ignoring.\n");
@ -1665,10 +1599,7 @@ DEFINE_PACKET_HANDLER(static, channel_failure_handler,
}
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(connection->e, "Invalid CHANNEL_FAILURE message.");
}
}
@ -1715,13 +1646,17 @@ void init_connection_service(struct ssh_connection *connection)
= &global_failure_handler;
}
DEFINE_COMMAND_SIMPLE(connection_service_command, a)
DEFINE_COMMAND(connection_service_command)
(struct command *s UNUSED,
struct lsh_object *a,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST(ssh_connection, connection, a);
init_connection_service(connection);
return a;
COMMAND_RETURN(c, connection);
}
struct lsh_string *
@ -1744,7 +1679,7 @@ channel_close(struct ssh_channel *channel)
channel->flags |= CHANNEL_SENT_CLOSE;
A_WRITE(channel->write, format_channel_close(channel) );
C_WRITE(channel->connection, format_channel_close(channel) );
if (channel->flags & CHANNEL_RECEIVED_CLOSE)
EXCEPTION_RAISE(channel->e, &finish_exception);
@ -1768,7 +1703,7 @@ channel_eof(struct ssh_channel *channel)
verbose("Sending EOF on channel %i\n", channel->channel_number);
channel->flags |= CHANNEL_SENT_EOF;
A_WRITE(channel->write, format_channel_eof(channel) );
C_WRITE(channel->connection, format_channel_eof(channel) );
if ( (channel->flags & CHANNEL_CLOSE_AT_EOF)
&& (channel->flags & (CHANNEL_RECEIVED_EOF | CHANNEL_NO_WAIT_FOR_EOF)) )
@ -1783,7 +1718,11 @@ void
init_channel(struct ssh_channel *channel)
{
/* channel->super.handler = do_read_channel; */
#if 0
channel->write = NULL;
#endif
channel->connection = NULL;
channel->super.report = adjust_rec_window;
channel->flags = CHANNEL_CLOSE_AT_EOF;
@ -1885,7 +1824,7 @@ do_channel_write(struct abstract_write *w,
channel_eof(closure->channel);
}
else
A_WRITE(closure->channel->write,
C_WRITE(closure->channel->connection,
channel_transmit_data(closure->channel, packet) );
}
@ -1903,7 +1842,7 @@ do_channel_write_extended(struct abstract_write *w,
channel_eof(closure->super.channel);
}
else
A_WRITE(closure->super.channel->write,
C_WRITE(closure->super.channel->connection,
channel_transmit_extended(closure->super.channel,
closure->type,
packet));
@ -1942,7 +1881,8 @@ make_channel_read_data(struct ssh_channel *channel)
*
* gives 9 bytes of overhead, including the length field. */
return make_read_data(channel, make_channel_write(channel)); }
return make_read_data(channel, make_channel_write(channel));
}
struct io_callback *
make_channel_read_stderr(struct ssh_channel *channel)

Binary file not shown.

View File

@ -119,11 +119,7 @@ struct channel_request_info
(send_window_size . UINT32)
(send_max_packet . UINT32)
; FIXME: Perhaps this should be moved to the channel_table, and
; a pointer to that table be stored here instead?
; Now that we pass the connection pointer to most functions,
; is this field needed at all?
(write object abstract_write)
(connection object ssh_connection)
(request_types object alist)
@ -232,6 +228,12 @@ struct channel_request_info
(local_ports struct object_queue)
(remote_ports struct object_queue)
; Used if we're currently forwarding X11
; To support several screens at the same time,
; this should be replaced with a list, analogous to
; the remote_ports list above.
(x11_display object client_x11_display)
; Global requests that we have received, and should reply to
; in the right order
(active_global_requests struct object_queue)
@ -302,15 +304,14 @@ make_channel_open_exception(UINT32 error_code, const char *msg);
(vars
(handler method void
"struct ssh_channel *channel"
"struct ssh_connection *connection"
"struct channel_request_info *info"
"struct simple_buffer *args"
"struct command_continuation *c"
"struct exception_handler *e")))
*/
#define CHANNEL_REQUEST(s, c, conn, i, a, n, e) \
((s)->handler((s), (c), (conn), (i), (a), (n), (e)))
#define CHANNEL_REQUEST(s, c, i, a, n, e) \
((s)->handler((s), (c), (i), (a), (n), (e)))
void init_channel(struct ssh_channel *channel);
@ -324,8 +325,7 @@ use_channel(struct ssh_connection *connection,
UINT32 local_channel_number);
void
register_channel(struct ssh_connection *connection,
UINT32 local_channel_number,
register_channel(UINT32 local_channel_number,
struct ssh_channel *channel,
int take_into_use);
@ -410,8 +410,8 @@ struct lsh_string *channel_transmit_extended(struct ssh_channel *channel,
void init_connection_service(struct ssh_connection *connection);
extern struct command_simple connection_service_command;
#define INIT_CONNECTION_SERVICE (&connection_service_command.super.super)
extern struct command connection_service_command;
#define INIT_CONNECTION_SERVICE (&connection_service_command.super)
#endif /* LSH_CHANNEL_H_INCLUDED */

Binary file not shown.

View File

@ -72,7 +72,7 @@ do_channel_open_command(struct command *s,
* need not pass the connection to NEW_CHANNEL. */
channel->open_continuation = c;
channel->e = e;
register_channel(connection, index, channel, 0);
register_channel(index, channel, 0);
C_WRITE(connection, request);
}
@ -94,7 +94,7 @@ do_channel_request_command(struct command *s,
object_queue_add_tail(&channel->pending_requests,
&make_command_context(c, e)->super);
A_WRITE(channel->write, request);
C_WRITE(channel->connection, request);
}
void
@ -116,16 +116,17 @@ do_channel_global_command(struct command *s,
C_WRITE(connection, request);
}
struct lsh_object *
do_install_global_request_handler(struct collect_info_2 *info,
struct lsh_object *a,
struct lsh_object *b)
void
do_install_global_request_handler(struct command_2 *s,
struct lsh_object *a1,
struct lsh_object *a2,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST(install_info, self, info);
CAST(ssh_connection, connection, a);
CAST_SUBTYPE(global_request, handler, b);
CAST(install_info, self, s);
CAST(ssh_connection, connection, a1);
CAST_SUBTYPE(global_request, handler, a2);
assert(!info->next);
assert(handler);
trace("Installing global request handler for '%a'\n", self->name);
@ -134,19 +135,20 @@ do_install_global_request_handler(struct collect_info_2 *info,
self->name,
&handler->super);
return a;
COMMAND_RETURN(c, connection);
}
struct lsh_object *
do_install_channel_open_handler(struct collect_info_2 *info,
struct lsh_object *a,
struct lsh_object *b)
void
do_install_channel_open_handler(struct command_2 *s,
struct lsh_object *a1,
struct lsh_object *a2,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST(install_info, self, info);
CAST(ssh_connection, connection, a);
CAST_SUBTYPE(channel_open, handler, b);
CAST(install_info, self, s);
CAST(ssh_connection, connection, a1);
CAST_SUBTYPE(channel_open, handler, a2);
assert(!info->next);
assert(handler);
trace("Installing channel open handler for '%a'\n", self->name);
@ -155,9 +157,10 @@ do_install_channel_open_handler(struct collect_info_2 *info,
self->name,
&handler->super);
return a;
COMMAND_RETURN(c, connection);
}
/* Special cases, when the handler is known early */
/* Takes a connection as argument, and installs a fix handler */

Binary file not shown.

View File

@ -107,25 +107,29 @@ make_install_global_request_handler(UINT32 name,
/* GABA:
(class
(name install_info)
(super collect_info_2)
(super command_2)
(vars
(name . int)))
*/
struct lsh_object *
do_install_global_request_handler(struct collect_info_2 *info,
struct lsh_object *a,
struct lsh_object *b);
struct lsh_object *
do_install_channel_open_handler(struct collect_info_2 *info,
struct lsh_object *a,
struct lsh_object *b);
void
do_install_global_request_handler(struct command_2 *s,
struct lsh_object *a1,
struct lsh_object *a2,
struct command_continuation *c,
struct exception_handler *e);
void
do_install_channel_open_handler(struct command_2 *s,
struct lsh_object *a1,
struct lsh_object *a2,
struct command_continuation *c,
struct exception_handler *e);
#define STATIC_INSTALL_GLOBAL_HANDLER(atom) \
{ STATIC_COLLECT_2_FINAL(do_install_global_request_handler),(atom) }
{ { { STATIC_HEADER, do_command_2 }, do_install_global_request_handler }, atom }
#define STATIC_INSTALL_OPEN_HANDLER(atom) \
{ STATIC_COLLECT_2_FINAL(do_install_channel_open_handler),(atom) }
{ { { STATIC_HEADER, do_command_2 }, do_install_channel_open_handler }, atom }
struct command *
make_install_fix_global_request_handler(UINT32 name,

Binary file not shown.

137
lsh/src/channel_forward.c Normal file
View File

@ -0,0 +1,137 @@
/* channel_forward.h
*
* General channel type for forwarding data to an fd
*
* $Id$ */
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 1998, 2001 Balázs Scheidler, Niels Möller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "channel_forward.h"
#include "io.h"
#include "ssh.h"
#include "werror.h"
#include "xalloc.h"
#include <assert.h>
#include <errno.h>
#include <string.h>
#define GABA_DEFINE
#include "channel_forward.h.x"
#undef GABA_DEFINE
/* NOTE: Adds the socket to the channel's resource list */
void
init_channel_forward(struct channel_forward *self,
struct lsh_fd *socket, UINT32 initial_window)
{
assert(socket);
init_channel(&self->super);
/* The rest of the callbacks are not set up until tcpip_start_io. */
/* NOTE: We don't need a close handler, as the channel's resource
* list is taken care of automatically. */
self->super.rec_window_size = initial_window;
/* FIXME: Make maximum packet size configurable. */
self->super.rec_max_packet = SSH_MAX_PACKET - SSH_CHANNEL_MAX_PACKET_FUZZ;
self->socket = socket;
REMEMBER_RESOURCE(self->super.resources, &socket->super);
}
struct channel_forward *
make_channel_forward(struct lsh_fd *socket, UINT32 initial_window)
{
NEW(channel_forward, self);
init_channel_forward(self, socket, initial_window);
return self;
}
static void
do_channel_forward_receive(struct ssh_channel *c,
int type, struct lsh_string *data)
{
CAST(channel_forward, closure, c);
switch (type)
{
case CHANNEL_DATA:
A_WRITE(&closure->socket->write_buffer->super, data);
break;
case CHANNEL_STDERR_DATA:
werror("Ignoring unexpected stderr data.\n");
lsh_string_free(data);
break;
default:
fatal("Internal error. do_channel_forward_receive");
}
}
static void
do_channel_forward_send_adjust(struct ssh_channel *s,
UINT32 i UNUSED)
{
CAST(channel_forward, self, s);
self->socket->want_read = 1;
}
static void
do_channel_forward_eof(struct ssh_channel *s)
{
CAST(channel_forward, self, s);
if (shutdown (self->socket->fd, SHUT_WR) < 0)
werror("do_channel_forward_eof, shutdown failed, (errno = %i): %z\n",
errno, STRERROR(errno));
}
/* NOTE: Because this function is called by
* do_open_forwarded_tcpip_continuation, the same restrictions apply.
* I.e we can not assume that the channel is completely initialized
* (channel_open_continuation has not yet done its work), and we can't
* send any packets. */
void
channel_forward_start_io(struct channel_forward *channel)
{
channel->super.receive = do_channel_forward_receive;
channel->super.send_adjust = do_channel_forward_send_adjust;
channel->super.eof = do_channel_forward_eof;
/* Install callbacks on the local socket.
* NOTE: We don't install any channel_io_exception_handler. */
io_read_write(channel->socket,
make_channel_read_data(&channel->super),
/* FIXME: Make this configurable */
SSH_MAX_PACKET * 10, /* self->block_size, */
make_channel_read_close_callback(&channel->super));
/* Flow control */
channel->socket->write_buffer->report = &channel->super.super;
}

55
lsh/src/channel_forward.h Normal file
View File

@ -0,0 +1,55 @@
/* channel_forward.h
*
* General channel type for forwarding data to an fd
*
* $Id$ */
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 1998, 2001 Balázs Scheidler, Niels Möller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef LSH_CHANNEL_FORWARD_H_INCLUDED
#define LSH_CHANNEL_FORWARD_H_INCLUDED
#include "channel.h"
#define GABA_DECLARE
#include "channel_forward.h.x"
#undef GABA_DECLARE
/* GABA:
(class
(name channel_forward)
(super ssh_channel)
(vars
(socket object lsh_fd)))
*/
void
init_channel_forward(struct channel_forward *self,
struct lsh_fd *socket, UINT32 initial_window);
struct channel_forward *
make_channel_forward(struct lsh_fd *socket, UINT32 initial_window);
void
channel_forward_start_io(struct channel_forward *channel_forward);
#endif /* LSH_CHANNEL_FORWARD_H_INCLUDED */

View File

@ -0,0 +1,31 @@
/*
CLASS:channel_forward:ssh_channel
*/
#ifndef GABA_DEFINE
struct channel_forward
{
struct ssh_channel super;
struct lsh_fd *socket;
};
extern struct lsh_class channel_forward_class;
#endif /* !GABA_DEFINE */
#ifndef GABA_DECLARE
static void
do_channel_forward_mark(struct lsh_object *o,
void (*mark)(struct lsh_object *o))
{
struct channel_forward *i = (struct channel_forward *) o;
mark((struct lsh_object *) i->socket);
}
struct lsh_class channel_forward_class =
{
STATIC_HEADER,
&(ssh_channel_class),
"channel_forward",
sizeof(struct channel_forward),
do_channel_forward_mark,
NULL,
};
#endif /* !GABA_DECLARE */

View File

@ -66,7 +66,8 @@ int ucs4_to_local(UINT32 c)
};
}
struct lsh_string *local_to_utf8(struct lsh_string *s, int free)
struct lsh_string *
local_to_utf8(struct lsh_string *s, int free)
{
#if ALLOCA_68K_BUG
ALLOCA_START(alloca_ref);

View File

@ -21,6 +21,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if MACOS
#include "lsh_context.h"
#endif
#include "client.h"
#include "abstract_io.h"
@ -33,6 +37,7 @@
#include "pad.h"
#include "parse.h"
#include "ssh.h"
#include "suspend.h"
#include "tcpforward_commands.h"
#include "translate_signal.h"
#include "werror.h"
@ -51,6 +56,10 @@
#include <sys/stat.h>
#include <fcntl.h>
#if MACOS
extern int strcasecmp(const char * str1, const char * str2);
#endif
#include "lsh_argp.h"
#define GABA_DEFINE
@ -59,6 +68,8 @@
#include "client.c.x"
#define DEFAULT_ESCAPE_CHAR '~'
static struct lsh_string *
format_service_request(int name)
{
@ -104,16 +115,12 @@ do_accept_service(struct packet_handler *c,
&& (name == closure->service)))
&& parse_eod(&buffer))
{
lsh_string_free(packet);
connection->dispatch[SSH_MSG_SERVICE_ACCEPT] = &connection_fail_handler;
COMMAND_RETURN(closure->c, connection);
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(closure->e, "Invalid SSH_MSG_SERVICE_ACCEPT message");
}
}
struct packet_handler *
@ -170,7 +177,6 @@ make_request_service(int service)
static void
do_exit_status(struct channel_request *c,
struct ssh_channel *channel,
struct ssh_connection *connection UNUSED,
struct channel_request_info *info,
struct simple_buffer *args,
struct command_continuation *s,
@ -191,14 +197,6 @@ do_exit_status(struct channel_request *c,
ALIST_SET(channel->request_types, ATOM_EXIT_STATUS, NULL);
ALIST_SET(channel->request_types, ATOM_EXIT_SIGNAL, NULL);
#if 0
/* Send EOF, if we haven't done that already. */
/* FIXME: Make this behaviour configurable, there may be some
* child process alive that we could talk to. */
channel_eof(channel);
#endif
COMMAND_RETURN(s, NULL);
}
else
@ -209,7 +207,6 @@ do_exit_status(struct channel_request *c,
static void
do_exit_signal(struct channel_request *c,
struct ssh_channel *channel,
struct ssh_connection *connection UNUSED,
struct channel_request_info *info,
struct simple_buffer *args,
struct command_continuation *s,
@ -227,7 +224,7 @@ do_exit_signal(struct channel_request *c,
UINT32 language_length;
if (!info->want_reply
&& parse_uint32(args, &signal)
&& parse_atom(args, &signal)
&& parse_boolean(args, &core)
&& parse_string(args, &length, &msg)
&& parse_string(args, &language_length, &language)
@ -238,11 +235,6 @@ do_exit_signal(struct channel_request *c,
*closure->exit_status = 7;
#if 0
signal = signal_network_to_local(signal);
werror("%ups", length, msg);
#endif
werror("Remote process was killed by signal: %ups %z\n",
length, msg,
core ? "(core dumped remotely)\n": "");
@ -250,13 +242,6 @@ do_exit_signal(struct channel_request *c,
ALIST_SET(channel->request_types, ATOM_EXIT_STATUS, NULL);
ALIST_SET(channel->request_types, ATOM_EXIT_SIGNAL, NULL);
#if 0
/* Send EOF, if we haven't done that already. */
/* FIXME: Make this behaviour configurable, there may be some
* child process alive that we could talk to. */
channel_eof(channel);
#endif
COMMAND_RETURN(s, NULL);
}
else
@ -307,7 +292,7 @@ new_session(struct channel_open_command *s,
CAST(session_open_command, self, s);
struct ssh_channel *res;
self->session->write = connection->write;
self->session->connection = connection;
*request = format_channel_open(ATOM_SESSION,
local_channel_number,
@ -406,11 +391,16 @@ make_client_session(struct client_options *options);
void
init_client_options(struct client_options *self,
struct io_backend *backend,
struct randomness_with_poll *random,
struct exception_handler *handler,
int *exit_code)
{
self->backend = backend;
self->random = random;
self->tty = make_unix_interact(backend);
self->escape = -1;
self->handler = handler;
self->exit_code = exit_code;
@ -423,6 +413,7 @@ init_client_options(struct client_options *self,
self->with_remote_peers = 0;
self->with_pty = -1;
self->with_x11 = 0;
self->stdin_file = NULL;
self->stdout_file = NULL;
@ -437,6 +428,7 @@ init_client_options(struct client_options *self,
#endif
self->used_stdin = 0;
self->used_pty = 0;
self->used_x11 = 0;
self->start_shell = 1;
self->remote_forward = 0;
@ -445,23 +437,31 @@ init_client_options(struct client_options *self,
}
/* Host to connect to */
DEFINE_COMMAND_SIMPLE(client_options2remote, a)
DEFINE_COMMAND(client_options2remote)
(struct command *s UNUSED,
struct lsh_object *a,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST_SUBTYPE(client_options, options, a);
trace("client.c: client_options2remote\n");
return &options->remote->super;
COMMAND_RETURN(c, options->remote);
}
/* Host to connect to */
DEFINE_COMMAND_SIMPLE(client_options2actions, a)
DEFINE_COMMAND(client_options2actions)
(struct command *s UNUSED,
struct lsh_object *a,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST_SUBTYPE(client_options, options, a);
trace("client.c: client_options2actions, %i actions\n",
options->actions.length);
return &queue_to_list(&options->actions)->super.super;
COMMAND_RETURN(c, queue_to_list(&options->actions));
}
static const struct argp_option
@ -478,6 +478,9 @@ client_options[] =
#endif
{ "nop", 'N', NULL, 0, "No operation (suppresses the default action, "
"which is to spawn a remote shell)", 0 },
#if !MACOS
{ "background", 'B', NULL, 0, "Put process into the background. Implies -N.", 0 },
#endif
{ "execute", 'E', "command", 0, "Execute a command on the remote machine", 0 },
{ "shell", 'S', "command", 0, "Spawn a remote shell", 0 },
/* { "gateway", 'G', NULL, 0, "Setup a local gateway", 0 }, */
@ -510,6 +513,8 @@ client_options[] =
{ "pty", 't', NULL, 0, "Request a remote pty (default).", 0 },
{ "no-pty", 't' | ARG_NOT, NULL, 0, "Don't request a remote pty.", 0 },
#endif /* WITH_PTY_SUPPORT */
{ "escape-char", 'e', "Character", 0, "Escape char. `none' means disable. "
"Default is to use `~' if we have a tty, otherwise none.", 0 },
{ NULL, 0, NULL, 0, NULL, 0 }
};
@ -544,19 +549,10 @@ make_client_start_session(struct command *request)
return r;
}
/* Create an interactive session */
static struct command *
client_shell_session(struct client_options *options)
static void
client_maybe_pty(struct client_options *options,
struct object_queue *q)
{
struct command *get_pty = NULL;
struct command *get_shell;
struct object_list *session_requests;
struct ssh_channel *session = make_client_session(options);
if (!session)
return NULL;
#if WITH_PTY_SUPPORT
if (options->with_pty && !options->used_pty)
{
@ -564,40 +560,75 @@ client_shell_session(struct client_options *options)
if (options->tty && INTERACT_IS_TTY(options->tty))
{
get_pty = make_pty_request(options->tty);
if (!get_pty)
{
werror("lsh: Can't use tty (probably getattr or atexit failed).\n");
}
}
else
{
werror("lsh: No tty available.\n");
}
}
struct command *get_pty = make_pty_request(options->tty);
get_shell = make_client_start_session(&request_shell.super);
/* FIXME: We need a non-varargs constructor for lists. */
if (get_pty)
session_requests
= make_object_list(2,
object_queue_add_tail(q,
/* Ignore EXC_CHANNEL_REQUEST for the pty allocation call. */
make_catch_apply
&make_catch_apply
(make_catch_handler_info(EXC_ALL, EXC_CHANNEL_REQUEST,
0, NULL),
get_pty),
get_shell, -1);
get_pty)->super);
else
#endif /* WITH_PTY_SUPPORT */
session_requests = make_object_list(1, get_shell, -1);
werror("lsh: Can't use tty (probably getattr or atexit failed).\n");
}
else
werror("lsh: No tty available.\n");
}
#endif
}
static void
client_maybe_x11(struct client_options *options,
struct object_queue *q)
{
if (options->with_x11)
{
char *display = getenv("DISPLAY");
struct command *request = NULL;
assert(options->random);
if (display)
request = make_forward_x11(display, &options->random->super);
if (request)
{
object_queue_add_tail(q, &request->super);
options->used_x11 = 1;
}
else
werror("Can't find any local X11 display to forward.\n");
}
}
/* Create an interactive session */
static struct command *
client_shell_session(struct client_options *options)
{
struct ssh_channel *session = make_client_session(options);
if (session)
{
struct object_queue session_requests;
object_queue_init(&session_requests);
client_maybe_pty(options, &session_requests);
client_maybe_x11(options, &session_requests);
object_queue_add_tail(&session_requests,
&make_client_start_session(&request_shell.super)->super);
{
CAST_SUBTYPE(command, r,
make_start_session
(make_open_session_command(session), session_requests));
(make_open_session_command(session),
queue_to_list_and_kill(&session_requests)));
return r;
}
}
else
return NULL;
}
/* Create a session executing a command line */
@ -608,15 +639,27 @@ client_command_session(struct client_options *options,
struct ssh_channel *session = make_client_session(options);
if (session)
{
struct object_queue session_requests;
object_queue_init(&session_requests);
/* NOTE: Doesn't ask for a pty. That's traditional behaviour,
* although perhaps not the Right Thing. */
client_maybe_pty(options, &session_requests);
client_maybe_x11(options, &session_requests);
object_queue_add_tail(&session_requests,
&make_client_start_session(make_exec_request(command))->super);
{
CAST_SUBTYPE(command, r,
make_start_session
(make_open_session_command(session),
make_object_list
(1, make_client_start_session(make_exec_request(command)),
-1)));
queue_to_list_and_kill(&session_requests)));
return r;
}
}
return NULL;
}
@ -742,6 +785,72 @@ fork_output(int out)
}
#endif
/* FIXME: Use const? */
#define DEFINE_CALLBACK(name) \
static void do_##name(struct lsh_callback *self); \
static struct lsh_callback \
name = { STATIC_HEADER, do_##name }; \
static void do_##name(struct lsh_callback *self UNUSED)
/* A callback that exits the process immediately. */
DEFINE_CALLBACK(exit_callback)
{
exit(EXIT_SUCCESS);
}
DEFINE_CALLBACK(verbose_callback)
{
verbose_flag = !verbose_flag;
if (verbose_flag)
verbose("Enabling verbose messages\n");
}
DEFINE_CALLBACK(debug_callback)
{
debug_flag = !debug_flag;
if (debug_flag)
debug("Enabling debug messages\n");
}
DEFINE_CALLBACK(quiet_callback)
{
quiet_flag = !quiet_flag;
if (!quiet_flag)
werror("Enabling warning messages\n");
}
DEFINE_COMMAND(background_process)
(struct command *s UNUSED,
struct lsh_object *a,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
#if MACOS
werror("background_process: fork unimplemented\n");
COMMAND_RETURN(c, a);
#else
switch (fork())
{
case 0:
/* Child */
/* FIXME: Should we create a new process group, close our tty
* and stdio, etc? */
COMMAND_RETURN(c, a);
break;
case -1:
/* Error */
werror("background_process: fork failed (errno = %i): %z\n",
errno, STRERROR(errno));
COMMAND_RETURN(c, a);
break;
default:
/* Parent */
_exit(EXIT_SUCCESS);
}
#endif
}
/* Create a session object. stdout and stderr are shared (although
* with independent lsh_fd objects). stdin can be used by only one
* session (until something "session-control"/"job-control" is added).
@ -752,6 +861,9 @@ make_client_session(struct client_options *options)
int in;
int out;
int err;
int is_tty = 0;
struct escape_info *escape = NULL;
debug("lsh.c: Setting up stdin\n");
@ -768,6 +880,8 @@ make_client_session(struct client_options *options)
else
{
in = (options->stdin_fork ? fork_input : dup)(STDIN_FILENO);
is_tty = isatty(STDIN_FILENO);
options->used_stdin = 1;
}
}
@ -779,6 +893,33 @@ make_client_session(struct client_options *options)
return NULL;
}
/* Attach the escape char handler, if appropriate. */
if (options->escape > 0)
{
verbose("Enabling explicit escape character `%pc'\n",
options->escape);
escape = make_escape_info(options->escape);
}
else if ( (options->escape < 0) && is_tty)
{
verbose("Enabling default escape character `%pc'\n",
DEFAULT_ESCAPE_CHAR);
escape = make_escape_info(DEFAULT_ESCAPE_CHAR);
}
/* Bind ^Z to suspend. */
if (escape)
{
/* Bind ^Z to suspend. */
escape->dispatch[26] = &suspend_callback;
escape->dispatch['.'] = &exit_callback;
/* Toggle the verbosity flags */
escape->dispatch['d'] = &debug_callback;
escape->dispatch['v'] = &verbose_callback;
escape->dispatch['q'] = &quiet_callback;
}
debug("lsh.c: Setting up stdout\n");
if (options->stdout_file)
@ -806,11 +947,10 @@ make_client_session(struct client_options *options)
{
err = dup(STDERR_FILENO);
#if MACOS
/* always log to console */
/*set_error_stream(STDERR_FILENO, 1);*/
set_error_syslog("lsh");
// set_error_syslog("lsh");
set_error_nonblocking(STDERR_FILENO);
#else
set_error_stream(STDERR_FILENO, 1);
set_error_nonblocking(STDERR_FILENO);
#endif
}
@ -826,16 +966,21 @@ make_client_session(struct client_options *options)
options->stdin_file = options->stdout_file = options->stderr_file = NULL;
return make_client_session_channel
(io_read(make_lsh_fd(options->backend, in, options->handler),
(io_read(make_lsh_fd(options->backend,
in, "client stdin", options->handler),
NULL, NULL),
io_write(make_lsh_fd(options->backend, out, options->handler),
io_write(make_lsh_fd(options->backend,
out, "client stdout", options->handler),
BLOCK_SIZE, NULL),
io_write(make_lsh_fd(options->backend, err, options->handler),
io_write(make_lsh_fd(options->backend,
err, "client stderr", options->handler),
BLOCK_SIZE, NULL),
escape,
WINDOW_SIZE,
options->exit_code);
}
/* Parse the argument for -R and -L */
int
client_parse_forward_arg(char *arg,
@ -960,6 +1105,14 @@ client_argp_parser(int key, char *arg, struct argp_state *state)
if (options->start_shell)
client_add_action(options, client_shell_session(options));
if (options->used_x11)
client_add_action(options,
make_install_fix_channel_open_handler
(ATOM_X11,
make_channel_open_x11(options->backend)));
/* Install suspend-handler */
suspend_install_handler();
break;
case 'p':
@ -970,6 +1123,16 @@ client_argp_parser(int key, char *arg, struct argp_state *state)
options->user = arg;
break;
case 'e':
if (arg[0] && !arg[1])
/* A single char argument */
options->escape = arg[0];
else if (!strcasecmp(arg, "none"))
options->escape = 0;
else
argp_error(state, "Invalid escape char: `%s'. "
"You must use a single character or `none'.", arg);
break;
case 'E':
client_add_action(options, client_command_session(options, ssh_format("%lz", arg)));
break;
@ -1020,6 +1183,13 @@ client_argp_parser(int key, char *arg, struct argp_state *state)
options->start_shell = 0;
break;
#if !defined(MACOS)
case 'B':
options->start_shell = 0;
client_add_action(options, &background_process);
break;
#endif
CASE_FLAG('g', with_remote_peers);
#if WITH_PTY_SUPPORT
@ -1072,6 +1242,7 @@ client_argp_parser(int key, char *arg, struct argp_state *state)
goto loop_done;
}
loop_done:
;
}
break;
#endif

Binary file not shown.

View File

@ -6,7 +6,7 @@
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 1998 Niels Möller
* Copyright (C) 1998, 1999, 2000, 2001 Niels Möller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -36,7 +36,6 @@
/* The argp option group for actions. */
#define CLIENT_ARGP_ACTION_GROUP 100
#define CLIENT_ARGP_MODIFIER_GROUP 200
struct packet_handler *
@ -62,6 +61,20 @@ do_request_service(struct command *s,
{ STATIC_COMMAND(do_request_service), service }
struct command *make_request_service(int service);
/* GABA:
(class
(name escape_info)
(vars
(escape . UINT8)
; Handlers, indexed by character.
(dispatch array (object lsh_callback) "0x100")))
*/
struct escape_info *make_escape_info(UINT8 escape);
struct abstract_write *
make_handle_escape(struct escape_info *info, struct abstract_write *next);
struct channel_request *make_handle_exit_status(int *exit_code);
struct channel_request *make_handle_exit_signal(int *exit_code);
@ -78,6 +91,7 @@ struct ssh_channel *
make_client_session_channel(struct lsh_fd *in,
struct lsh_fd *out,
struct lsh_fd *err,
struct escape_info *escape,
UINT32 initial_window,
int *exit_status);
@ -87,14 +101,31 @@ make_exec_request(struct lsh_string *command);
struct command *
make_pty_request(struct interact *tty);
struct channel_open *
make_channel_open_x11(struct io_backend *backend);
struct command *
make_forward_x11(const char *display_string,
struct randomness *random);
struct client_x11_display *
make_client_x11_display(const char *display, struct lsh_string *fake);
/* GABA:
(class
(name client_options)
(vars
(backend object io_backend)
;; Used only by lsh, NULL for lshg.
(random object randomness_with_poll)
(tty object interact)
; -1 means default.
(escape . int)
; For i/o exceptions
(handler object exception_handler)
@ -112,6 +143,8 @@ make_pty_request(struct interact *tty);
; -1 means default behaviour
(with_pty . int)
(with_x11 . int)
; Session modifiers
(stdin_file . "const char *")
(stdout_file . "const char *")
@ -126,6 +159,7 @@ make_pty_request(struct interact *tty);
; True if the process's stdin or pty (respectively) has been used.
(used_stdin . int)
(used_pty . int)
(used_x11 . int)
(start_shell . int)
(remote_forward . int)
@ -135,6 +169,7 @@ make_pty_request(struct interact *tty);
void
init_client_options(struct client_options *options,
struct io_backend *backend,
struct randomness_with_poll *random,
struct exception_handler *handler,
int *exit_code);
@ -147,11 +182,11 @@ client_parse_forward_arg(char *arg,
UINT32 *listen_port,
struct address_info **target);
extern struct command_simple client_options2remote;
#define OPTIONS2REMOTE (&client_options2remote.super.super)
extern struct command client_options2remote;
#define OPTIONS2REMOTE (&client_options2remote.super)
extern struct command_simple client_options2actions;
#define OPTIONS2ACTIONS (&client_options2actions.super.super)
extern struct command client_options2actions;
#define OPTIONS2ACTIONS (&client_options2actions.super)
extern const struct argp client_argp;

Binary file not shown.

236
lsh/src/client_escape.c Normal file
View File

@ -0,0 +1,236 @@
/* client_escape.h
*
* Escape char handling.
*
* $Id$ */
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 1998, 1999, 2000, 2001 Niels Möller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "client.h"
#include "format.h"
#include "werror.h"
#include "xalloc.h"
#include <assert.h>
#include <string.h>
/* This must be defined before including the .x file. */
enum escape_state { GOT_NONE, GOT_NEWLINE, GOT_ESCAPE };
#include "client_escape.c.x"
struct escape_info *
make_escape_info(UINT8 escape)
{
NEW(escape_info, self);
unsigned i;
self->escape = escape;
for (i = 0; i<0x100; i++)
self->dispatch[i] = NULL;
return self;
}
/* GABA:
(class
(name escape_handler)
(super abstract_write_pipe)
(vars
(info object escape_info)
; Number of characters of the prefix NL escape
; that have been read.
(state . "enum escape_state")))
*/
static inline int
newlinep(UINT8 c)
{
return (c == '\n') || (c == '\r');
}
/* Search for NEWLINE ESCAPE, starting at pos. If successful, returns
* 1 and returns the index of the escape char. Otherwise, returns
* zero. */
static UINT32
scan_escape(struct lsh_string *packet, UINT32 pos, UINT8 escape)
{
for ( ; (pos + 2) <= packet->length; pos++)
{
if (newlinep(packet->data[pos])
&& (packet->data[pos+1] == escape))
return pos + 1;
}
return 0;
}
/* Returns 1 for the quote action. */
static int
escape_dispatch(struct escape_info *info,
UINT8 c)
{
struct lsh_callback *f;
if (c == info->escape)
return 1;
f = info->dispatch[c];
if (f)
LSH_CALLBACK(f);
else
werror("<escape> `%pc' not defined.\n", c);
return 0;
}
static void
do_escape_handler(struct abstract_write *s, struct lsh_string *packet)
{
CAST(escape_handler, self, s);
UINT32 pos;
UINT32 done;
#if 0
trace("do_escape_handler: state = %i, packet length = %i\n",
self->state, packet->length);
#endif
if (!packet)
{
/* EOF. Pass it on */
A_WRITE(self->super.next, packet);
return;
}
assert(packet->length);
/* done is the length of the prefix of the data that is already
* consumed in one way or the other, while pos is the next position
* where it makes sense to look for the escape sequence. */
done = pos = 0;
/* Look for an escape at the start of the packet. */
switch (self->state)
{
case GOT_NEWLINE:
/* We already got newline. Is the next character the escape? */
if (packet->data[0] == self->info->escape)
{
if (packet->length == 1)
{
self->state = GOT_ESCAPE;
lsh_string_free(packet);
return;
}
else
{
pos = 2;
if (escape_dispatch(self->info, packet->data[1]))
/* The quote action. Keep the escape. */
done = 1;
else
done = 2;
}
}
break;
case GOT_ESCAPE:
pos = 1;
if (escape_dispatch(self->info, packet->data[0]))
/* The quote action. Keep the escape. */
done = 0;
else
done = 1;
break;
case GOT_NONE:
/* No special processing needed. */
break;
}
while ( (pos = scan_escape(packet, pos, self->info->escape)) )
{
/* We found another escape char! */
/* First, pass on the data before the escape. */
assert(pos > done);
A_WRITE(self->super.next,
ssh_format("%ls", pos - done, packet->data + done));
/* Point to the action character. */
pos++;
if (pos == packet->length)
{
/* Remember how far we got. */
self->state = GOT_ESCAPE;
lsh_string_free(packet);
return;
}
if (escape_dispatch(self->info, packet->data[pos]))
/* Keep escape */
done = pos;
else
done = pos + 1;
pos++;
}
/* Handle any data after the final escape */
if (done < packet->length)
{
/* Rember if the last character is a newline. */
if (newlinep(packet->data[packet->length - 1]))
self->state = GOT_NEWLINE;
else
self->state = GOT_NONE;
/* Send data on */
if (done)
{
/* Partial packet */
A_WRITE(self->super.next,
ssh_format("%ls", packet->length - done,
packet->data + done));
lsh_string_free(packet);
}
else
A_WRITE(self->super.next, packet);
}
else
{
self->state = GOT_NONE;
lsh_string_free(packet);
}
}
struct abstract_write *
make_handle_escape(struct escape_info *info, struct abstract_write *next)
{
NEW(escape_handler, self);
self->super.super.write = do_escape_handler;
self->super.next = next;
self->info = info;
self->state = GOT_NONE;
return &self->super.super;
}

32
lsh/src/client_escape.c.x Normal file
View File

@ -0,0 +1,32 @@
/*
CLASS:escape_handler:abstract_write_pipe
*/
#ifndef GABA_DEFINE
struct escape_handler
{
struct abstract_write_pipe super;
struct escape_info *info;
enum escape_state state;
};
extern struct lsh_class escape_handler_class;
#endif /* !GABA_DEFINE */
#ifndef GABA_DECLARE
static void
do_escape_handler_mark(struct lsh_object *o,
void (*mark)(struct lsh_object *o))
{
struct escape_handler *i = (struct escape_handler *) o;
mark((struct lsh_object *) i->info);
}
struct lsh_class escape_handler_class =
{
STATIC_HEADER,
&(abstract_write_pipe_class),
"escape_handler",
sizeof(struct escape_handler),
do_escape_handler_mark,
NULL,
};
#endif /* !GABA_DECLARE */

View File

@ -74,7 +74,7 @@ do_handle_dh_reply(struct packet_handler *c,
trace("handle_dh_reply\n");
server_key = dh_process_server_msg(&closure->dh, &signature, packet);
lsh_string_free(packet);
if (!server_key)
{
disconnect_kex_failed(connection, "Bad dh-reply\r\n");
@ -204,7 +204,6 @@ do_srp_client_proof_handler(struct packet_handler *s,
int res = srp_process_server_proof(self->srp->m2,
packet);
lsh_string_free(packet);
connection->dispatch[SSH_MSG_KEXSRP_PROOF] = &connection_fail_handler;

Binary file not shown.

View File

@ -26,6 +26,7 @@
#include "channel_commands.h"
#include "format.h"
#include "interact.h"
#include "tty.h"
#include "werror.h"
#include "xalloc.h"
@ -66,7 +67,7 @@ make_client_tty_resource(struct interact *tty,
struct terminal_attributes *attr)
{
NEW(client_tty_resource, self);
resource_init(&self->super, do_kill_client_tty_resource);
init_resource(&self->super, do_kill_client_tty_resource);
self->tty = tty;
self->attr = attr;
@ -103,7 +104,7 @@ do_client_winch_handler(struct window_change_callback *s,
if (!INTERACT_WINDOW_SIZE(tty, &dims))
return;
A_WRITE(self->channel->write,
C_WRITE(self->channel->connection,
format_window_change(self->channel, &dims));
}
@ -140,7 +141,7 @@ do_pty_continuation(struct command_continuation *s,
struct terminal_attributes *raw;
assert(x);
verbose("lsh: pty request succeeded\n");
verbose("pty request succeeded\n");
raw = TERM_MAKE_RAW(self->req->attr);
if (!INTERACT_SET_ATTRIBUTES(self->req->tty, raw))
@ -180,7 +181,7 @@ do_format_pty_request(struct channel_request_command *s,
{
CAST(pty_request, self, s);
verbose("lsh: Requesting a remote pty.\n");
verbose("Requesting a remote pty.\n");
*c = make_pty_continuation(self, *c);
@ -211,11 +212,11 @@ make_pty_request(struct interact *tty)
req->dims.char_width = req->dims.char_height
= req->dims.pixel_width = req->dims.pixel_height = 0;
req->super.format_request = do_format_pty_request;
req->super.super.call = do_channel_request_command;
req->super.format_request = do_format_pty_request;
req->tty = tty;
req->term = term ? format_cstring(term) : ssh_format("");
req->term = term ? make_string(term) : ssh_format("");
return &req->super.super;
}

Binary file not shown.

View File

@ -27,6 +27,7 @@
#include "channel_commands.h"
#include "client.h"
#include "io.h"
#include "read_data.h"
#include "ssh.h"
#include "werror.h"
#include "xalloc.h"
@ -46,6 +47,8 @@
(out object lsh_fd)
(err object lsh_fd)
; Escape char handling
(escape object escape_info)
; Where to save the exit code.
(exit_status . "int *")))
*/
@ -60,9 +63,6 @@ do_client_session_eof(struct ssh_channel *c)
close_fd_nicely(session->out);
close_fd_nicely(session->err);
#if 0
close_fd(session->in);
#endif
}
static void
@ -107,6 +107,19 @@ do_send_adjust(struct ssh_channel *s,
self->in->want_read = 1;
}
/* Escape char handling */
static struct io_callback *
client_read_stdin(struct client_session_channel *session)
{
struct abstract_write *write = make_channel_write(&session->super);
if (session->escape)
write = make_handle_escape(session->escape, write);
return make_read_data(&session->super, write);
}
/* We have a remote shell */
static void
do_client_io(struct command *s UNUSED,
@ -142,7 +155,8 @@ do_client_io(struct command *s UNUSED,
/* Set up the fd we read from. */
channel->send_adjust = do_send_adjust;
session->in->read = make_channel_read_data(channel);
/* Setup escape char handler, if appropriate. */
session->in->read = client_read_stdin(session);
/* FIXME: Perhaps there is some way to arrange that channel.c calls
* the CHANNEL_SEND_ADJUST method instead? */
@ -175,6 +189,7 @@ struct ssh_channel *
make_client_session_channel(struct lsh_fd *in,
struct lsh_fd *out,
struct lsh_fd *err,
struct escape_info *escape,
UINT32 initial_window,
int *exit_status)
{
@ -197,6 +212,11 @@ make_client_session_channel(struct lsh_fd *in,
self->in = in;
self->out = out;
self->err = err;
self->escape = escape;
REMEMBER_RESOURCE(self->super.resources, &in->super);
REMEMBER_RESOURCE(self->super.resources, &out->super);
REMEMBER_RESOURCE(self->super.resources, &err->super);
/* Flow control */
out->write_buffer->report = &self->super.super;

Binary file not shown.

View File

@ -39,6 +39,18 @@ struct client_userauth;
#include "client_userauth.c.x"
static struct lsh_string *
format_userauth_none(struct lsh_string *name,
int service)
{
return ssh_format("%c%S%a%a",
SSH_MSG_USERAUTH_REQUEST,
name,
service,
ATOM_NONE);
}
/* The last parameters says whether or not to free the password. */
struct lsh_string *
format_userauth_password(struct lsh_string *name,
int service,
@ -126,6 +138,7 @@ format_userauth_publickey(struct lsh_string *name,
(name client_userauth)
(super command)
(vars
; The name should already be converted to utf8
(username string) ; Remote user name to authenticate as.
(service_name . int) ; Service we want to access.
(methods object object_list) ; Authentication methods, in order.
@ -200,8 +213,6 @@ do_userauth_success(struct packet_handler *c,
{
unsigned i;
lsh_string_free(packet);
verbose("User authentication successful.\n");
for (i = SSH_FIRST_USERAUTH_GENERIC; i < SSH_FIRST_CONNECTION_GENERIC; i++)
@ -210,10 +221,7 @@ do_userauth_success(struct packet_handler *c,
COMMAND_RETURN(self->c, connection);
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(connection->e, "Invalid USERAUTH_SUCCESS message");
}
}
static struct packet_handler *
@ -250,6 +258,14 @@ userauth_method_is_useful(struct client_userauth *userauth,
unsigned i;
#if 0
debug("userauth_method_is_useful, advertised:\n");
for(i = 0; i < LIST_LENGTH(advertised); i++)
debug(" %a\n", LIST(advertised)[i]);
debug(" method: type = %a, class = %t\n", method->type, method);
#endif
for(i = 0; i < LIST_LENGTH(advertised); i++)
if (LIST(advertised)[i] == method->type)
return 1;
@ -280,8 +296,6 @@ do_userauth_failure(struct packet_handler *c,
&& parse_boolean(&buffer, &partial_success)
&& parse_eod(&buffer))
{
lsh_string_free(packet);
if (partial_success)
/* Doesn't help us */
werror("Received SSH_MSH_USERAUTH_FAILURE "
@ -297,10 +311,7 @@ do_userauth_failure(struct packet_handler *c,
methods, self->state->current));
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(connection->e, "Invalid USERAUTH_FAILURE message.");
}
KILL(methods);
}
@ -345,8 +356,6 @@ do_userauth_banner(struct packet_handler *self UNUSED,
}
else
PROTOCOL_ERROR(connection->e, "Invalid USERAUTH_SUCCESS message");
lsh_string_free(packet);
}
static struct packet_handler userauth_banner_handler =
@ -496,7 +505,7 @@ make_client_userauth(struct lsh_string *username,
NEW(client_userauth, self);
self->super.call = do_client_userauth;
self->username = username;
self->username = local_to_utf8(username, 1);
self->service_name = service_name;
self->methods = methods;
@ -504,6 +513,70 @@ make_client_userauth(struct lsh_string *username,
}
/* None authentication */
/* GABA:
(class
(name client_none_state)
(super client_userauth_failure)
(vars
(e object exception_handler)))
*/
static void
do_none_failure(struct client_userauth_failure *s, int again)
{
CAST(client_none_state, self, s);
static const struct exception need_auth =
STATIC_EXCEPTION(EXC_USERAUTH, "Need real authentication.");
trace("client_userauth.c: do_none_failure\n");
if (again)
werror("Odd. Server says we should try the `none'authentication method again.\n");
EXCEPTION_RAISE(self->e, &need_auth);
}
static struct client_userauth_failure *
make_client_none_state(struct exception_handler *e)
{
NEW(client_none_state, self);
trace("client_userauth.c: make_client_none_state\n");
self->super.failure = do_none_failure;
self->e = e;
return &self->super;
}
static struct client_userauth_failure *
do_none_login(struct client_userauth_method *s UNUSED,
struct client_userauth *userauth,
struct ssh_connection *connection,
struct exception_handler *e)
{
trace("client_userauth.c: do_none_login\n");
C_WRITE(connection,
format_userauth_none(userauth->username,
userauth->service_name));
return make_client_none_state(e);
}
static struct client_userauth_method
client_userauth_none =
{ STATIC_HEADER, ATOM_NONE, do_none_login };
struct client_userauth_method *
make_client_none_auth(void)
{
return &client_userauth_none;
}
/* Password authentication */
#define MAX_PASSWD 100
@ -544,7 +617,7 @@ send_password(struct client_password_state *state)
}
C_WRITE(state->connection,
format_userauth_password(local_to_utf8(state->userauth->username, 0),
format_userauth_password(state->userauth->username,
state->userauth->service_name,
local_to_utf8(passwd, 1),
1));
@ -619,6 +692,7 @@ make_client_password_state(struct client_userauth *userauth,
(tty object interact)))
*/
static struct client_userauth_failure *
do_password_login(struct client_userauth_method *s,
struct client_userauth *userauth,
@ -642,6 +716,7 @@ struct client_userauth_method *
make_client_password_auth(struct interact *tty)
{
NEW(client_password_method, self);
self->super.type = ATOM_PASSWORD;
self->super.login = do_password_login;
self->tty = tty;
@ -806,7 +881,6 @@ do_userauth_pk_ok(struct packet_handler *s,
&& parse_string(&buffer, &keyblob_length, &keyblob)
&& parse_eod(&buffer))
#endif
{
CAST(keypair, key, LIST(self->state->keys)[self->state->done]);
verbose("SSH_MSG_USERAUTH_PK_OK received\n");
@ -819,16 +893,17 @@ do_userauth_pk_ok(struct packet_handler *s,
#if DATAFELLOWS_WORKAROUNDS
if (connection->peer_flags & PEER_USERAUTH_REQUEST_KLUDGE)
request = format_userauth_publickey(local_to_utf8(self->state->userauth->username, 0),
request = format_userauth_publickey(self->state->userauth->username,
ATOM_SSH_USERAUTH,
key->type,
key->public);
else
#endif /* DATAFELLOWS_WORKAROUNDS */
request = format_userauth_publickey(local_to_utf8(self->state->userauth->username, 0),
request = format_userauth_publickey(self->state->userauth->username,
self->state->userauth->service_name,
key->type,
key->public);
signed_data = ssh_format("%S%lS", connection->session_id, request);
request = ssh_format("%flS%fS",
request,
@ -840,15 +915,11 @@ do_userauth_pk_ok(struct packet_handler *s,
else
werror("client_userauth.c: Unexpected key in USERAUTH_PK_OK message.\n");
lsh_string_free(packet);
client_publickey_next(self->state);
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(self->state->e, "Invalid USERAUTH_PK_OK message");
}
}
static struct packet_handler *
make_pk_ok_handler(struct client_publickey_state *state)
@ -884,8 +955,10 @@ do_publickey_login(struct client_userauth_method *s,
{
CAST(keypair, key, LIST(self->keys)[i]);
/* NOTE: The PEER_USERAUTH_REQUEST_KLUDGE only applies to the
* signed data. */
C_WRITE(connection,
format_userauth_publickey_query(local_to_utf8(userauth->username, 0),
format_userauth_publickey_query(userauth->username,
userauth->service_name,
key->type, key->public));
}
@ -899,6 +972,7 @@ make_client_publickey_auth(struct object_list *keys)
{
NEW(client_publickey_method, self);
self->super.type = ATOM_PUBLICKEY;
self->super.login = do_publickey_login;
self->keys = keys;

Binary file not shown.

View File

@ -40,6 +40,7 @@ format_userauth_password(struct lsh_string *name,
int free);
/* Consumes the username */
struct command *make_client_userauth(struct lsh_string *username,
int service_name,
struct object_list *methods);
@ -50,5 +51,8 @@ make_client_password_auth(struct interact *tty);
struct client_userauth_method *
make_client_publickey_auth(struct object_list *);
struct client_userauth_method *
make_client_none_auth(void);
#endif /* LSH_CLIENT_USERAUTH_H_INCLUDED */

768
lsh/src/client_x11.c Normal file
View File

@ -0,0 +1,768 @@
/* client_x11.c
*
* Client side of X11 forwaarding.
*
* $Id$ */
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 2001 Niels Möller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "client.h"
#include "channel_forward.h"
#include "format.h"
#include "ssh.h"
#include "werror.h"
#include "xalloc.h"
#include "xauth.h"
#include "client_x11.c.x"
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
/* First port number for X, according to RFC 1013 */
#define X11_BASE_PORT 6000
#define X11_WINDOW_SIZE 10000
#define X11_COOKIE_LENGTH 16
/* ;; GABA:
(class
(name client_x11_auth_info)
(vars
; Fake MIT-COOKIE-1
(fake string)
; Real authentication info
(name string)
(auth string)))
*/
/* FIXME: Perhaps merge auth_info directly into this struct */
/* GABA:
(class
(name client_x11_display)
(vars
(address_length . socklen_t)
(address space "struct sockaddr")
; Default screen
(screen . UINT16)
; Fake MIT-COOKIE-1
(fake string)
; Real authentication info
(auth_name string)
(auth_data string)))
*/
/* GABA:
(class
(name channel_open_x11)
(super channel_open)
(vars
(backend object io_backend)))
*/
/* GABA:
(class
(name client_x11_channel)
(super channel_forward)
(vars
(display object client_x11_display)
(state . int)
(little_endian . int)
(name_length . unsigned)
(auth_length . unsigned)
(i . UINT32)
(buffer string)))
*/
/* This function is responsible for checking the fake cookie, and
* replacing it with the real one.
*
* It intercepts the first packet sent by the client, which has the
* following format:
*
* Type Possible or typical values
*
* uint8_t byte-order 'B' (big endian) or 'L' (little endian)
* uint8_t pad 0
* uint16_t major-version Usually 11
* uint16_t minor-version Usually 0.
* uint16_t name_length 18
* uint16_t auth_length 16
* uint16_t pad What's this?
* uint8_t [name_length] name "MIT-MAGIC-COOKIE-1"
* uint8_t [auth_length] auth Authentication data
*
* The last fields; name and auth, are padded to a multiple of four octets.
*
* The typical setup packet, with a 16-octet cookie, is 48 octets.
*/
/* Observed data:
*
* $10 = {0x42, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x12, 0x0, 0x10, 0x0, 0xa4, 0x4d,
* 0x49, 0x54, 0x2d, 0x4d, 0x41, 0x47, 0x49, 0x43, 0x2d, 0x43, 0x4f, 0x4f,
* 0x4b, 0x49, 0x45, 0x2d, 0x31, 0xff, 0xf7, 0x8b, 0x1e, 0x2c, 0xa0, 0x98,
* 0x11, 0x27, 0x82, 0xa9, 0x0, 0x2d, 0xc4, 0x68, 0x7f, 0x66, 0x2b}
*
*/
/* From Pike's X.pmod:
*
* /( Always uses network byteorder (big endian)
* string msg = sprintf("B\0%2c%2c%2c%2c\0\0%s%s",
* 11, 0,
* strlen(auth_data->name), strlen(auth_data->data),
* ._Xlib.pad(auth_data->name), ._Xlib.pad(auth_data->data));
*/
#define MIT_COOKIE_NAME "MIT-MAGIC-COOKIE-1"
#define MIT_COOKIE_NAME_LENGTH 18
#define MIT_COOKIE_LENGTH 16
#define X11_SETUP_VERSION_LENGTH 6
#define X11_SETUP_HEADER_LENGTH 12
/* The size of a connection setup message with a 16 octet
* MIT-MAGIC-COOKIE-1. Using such a low value leaks the information
* that we expect a 16-octet cookie, but I don't think that's areal
* problem. */
#define X11_SETUP_MAX_LENGTH 48
enum { CLIENT_X11_START,
CLIENT_X11_GOT_LENGTHS,
CLIENT_X11_OK,
CLIENT_X11_DENIED
};
/* And the other, little-endian, byteorder */
#define LE_READ_UINT16(p) \
( (((uint32_t) (p)[1]) << 8) \
| ((uint32_t) (p)[0]))
#define LE_WRITE_UINT16(p, i) \
do { \
(p)[1] = ((i) >> 8) & 0xff; \
(p)[0] = (i) & 0xff; \
} while(0)
/* FIXME: This function is a little ugly. It would get cleaner if we
* just replaced the channel's receive function pointer with NULL on
* failure and do_channel_forward_receive on success. */
static void
do_client_channel_x11_receive(struct ssh_channel *s,
int type, struct lsh_string *data)
{
CAST(client_x11_channel, self, s);
if (type != CHANNEL_DATA)
{
werror("Ignoring unexpected stderr data.\n");
lsh_string_free(data);
}
else switch (self->state)
{
case CLIENT_X11_OK:
A_WRITE(&self->super.socket->write_buffer->super, data);
break;
fail:
channel_close(&self->super.super);
self->state = CLIENT_X11_DENIED;
break;
case CLIENT_X11_DENIED:
/* Any data on the channel should be stopped before we get
* here; the CHANNEL_SENT_CLOSE should be set. */
fatal("Internal error!\n");
default:
{
/* Copy data to buffer */
UINT32 left = self->buffer->length - self->i;
/* The small initial window size should ensure that we don't get
* more data. */
assert(data->length <= left);
memcpy(self->buffer->data + self->i, data->data,
data->length);
self->i += data->length;
lsh_string_free(data);
switch (self->state)
{
case CLIENT_X11_START:
/* We need byte-order, major, minor and name_length,
* which is 6 octets */
if (self->i < X11_SETUP_HEADER_LENGTH)
break;
self->state = CLIENT_X11_GOT_LENGTHS;
switch (self->buffer->data[0])
{
case 'B': /* Big endian */
self->little_endian = 0;
self->name_length = READ_UINT16(self->buffer->data + 6);
self->auth_length = READ_UINT16(self->buffer->data + 8);
break;
case 'L': /* Little endian */
self->little_endian = 1;
self->name_length = LE_READ_UINT16(self->buffer->data + 6);
self->auth_length = LE_READ_UINT16(self->buffer->data + 8);
break;
default:
werror("client_x11.c: Bad endian indicator.\n");
goto fail;
}
if ( (self->name_length > 20)
|| (self->auth_length > 16) )
{
werror("client_x11.c: Too long auth name or cookie\n");
goto fail;
}
/* Fall through */
case CLIENT_X11_GOT_LENGTHS:
{
const unsigned pad_length[4] = { 0, 3, 2, 1 };
#define PAD(l) (pad_length[ (l) % 4])
UINT32 auth_offset = X11_SETUP_HEADER_LENGTH
+ self->name_length + PAD(self->name_length);
UINT32 length = auth_offset + self->auth_length
+ pad_length[self->auth_length % 4];
if (self->i < length)
break;
debug("Received cookie of type `%ps': %xs\n",
self->name_length, self->buffer->data + X11_SETUP_HEADER_LENGTH,
self->auth_length, self->buffer->data + auth_offset);
/* Ok, now we have the connection setup message. Check if it's ok. */
if ( (self->name_length == MIT_COOKIE_NAME_LENGTH)
&& !memcmp(self->buffer->data + X11_SETUP_HEADER_LENGTH,
MIT_COOKIE_NAME, MIT_COOKIE_NAME_LENGTH)
&& lsh_string_eq_l(self->display->fake,
self->auth_length,
self->buffer->data + auth_offset))
{
struct lsh_string *msg;
UINT8 lengths[4];
static const UINT8 pad[3] = { 0, 0, 0 };
/* Cookies match! */
verbose("client_x11: Allowing X11 connection; cookies match.\n");
if (self->little_endian)
{
LE_WRITE_UINT16(lengths, self->display->auth_name->length);
LE_WRITE_UINT16(lengths + 2, self->display->auth_data->length);
}
else
{
WRITE_UINT16(lengths, self->display->auth_name->length);
WRITE_UINT16(lengths + 2, self->display->auth_data->length);
}
/* FIXME: Perhaps it would be easier to build the message by hand than
* using ssh_format? */
/* Construct the real setup message. */
msg = ssh_format("%ls%ls%c%c%ls%ls%ls%ls",
X11_SETUP_VERSION_LENGTH, self->buffer->data,
4, lengths,
0, 0,
self->display->auth_name->length,
self->display->auth_name->data,
PAD(self->display->auth_name->length), pad,
self->display->auth_data->length,
self->display->auth_data->data,
self->i - length,
self->buffer + self->i);
lsh_string_free(self->buffer);
self->buffer = NULL;
/* Bump window size */
channel_start_receive(&self->super.super, X11_WINDOW_SIZE - msg->length);
debug("client_x11.c: Sending real X11 setup message: %xS\n",
msg);
/* Send real x11 connection setup message. */
A_WRITE(&self->super.socket->write_buffer->super, msg);
self->state = CLIENT_X11_OK;
}
else
{
werror("client_x11: X11 connection denied; bad cookie.\n");
goto fail;
}
break;
#undef PAD
}
default:
fatal("Internal error. do_client_channel_x11_receive");
break;
}
}
break;
}
}
static struct client_x11_channel *
make_client_x11_channel(struct lsh_fd *fd,
struct client_x11_display *display)
{
NEW(client_x11_channel, self);
/* Use a limited window size for the setup */
init_channel_forward(&self->super, fd, X11_SETUP_MAX_LENGTH);
self->display = display;
self->state = 0;
self->buffer = lsh_string_alloc(X11_SETUP_MAX_LENGTH);
return self;
}
/* GABA:
(class
(name channel_open_x11_continuation)
(super command_continuation)
(vars
(display object client_x11_display)
(up object command_continuation)))
*/
static void
do_channel_open_x11_continuation(struct command_continuation *s,
struct lsh_object *a)
{
CAST(channel_open_x11_continuation, self, s);
CAST(lsh_fd, fd, a);
struct client_x11_channel *channel = make_client_x11_channel(fd, self->display);
channel_forward_start_io(&channel->super);
channel->super.super.receive = do_client_channel_x11_receive;
COMMAND_RETURN(self->up, channel);
}
static struct command_continuation *
make_channel_open_x11_continuation(struct client_x11_display *display,
struct command_continuation *up)
{
NEW(channel_open_x11_continuation, self);
self->super.c = do_channel_open_x11_continuation;
self->display = display;
self->up = up;
return &self->super;
}
/* Exception handler that promotes connect errors to CHANNEL_OPEN
* exceptions */
static void
do_exc_x11_connect_handler(struct exception_handler *s,
const struct exception *e)
{
switch(e->type)
{
case EXC_IO_CONNECT:
EXCEPTION_RAISE(s->parent,
make_channel_open_exception(SSH_OPEN_CONNECT_FAILED,
e->msg));
break;
default:
EXCEPTION_RAISE(s->parent, e);
}
}
static struct exception_handler *
make_exc_x11_connect_handler(struct exception_handler *parent,
const char *context)
{
return make_exception_handler(do_exc_x11_connect_handler, parent, context);
}
static void
do_channel_open_x11(struct channel_open *s,
struct ssh_connection *connection,
struct channel_open_info *info UNUSED,
struct simple_buffer *args,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(channel_open_x11, self, s);
UINT32 originator_length;
const UINT8 *originator;
UINT32 originator_port;
if (parse_string(args, &originator_length, &originator)
&& parse_uint32(args, &originator_port)
&& parse_eod(args))
{
struct client_x11_display *display = connection->table->x11_display;
verbose("x11 connection attempt, originator: %s:%i\n",
originator_length, originator, originator_port);
if (display)
{
struct lsh_fd *fd
= io_connect(self->backend,
display->address,
display->address_length,
make_channel_open_x11_continuation(display,
c),
make_exc_x11_connect_handler(e, HANDLER_CONTEXT));
if (fd)
REMEMBER_RESOURCE(connection->resources, &fd->super);
else
EXCEPTION_RAISE(e,
make_channel_open_exception(SSH_OPEN_CONNECT_FAILED,
STRERROR(errno)));
/* FIXME: To handle single-connection feature,
* remove the display here. */
}
else
EXCEPTION_RAISE(e, make_channel_open_exception
(SSH_OPEN_CONNECT_FAILED,
"No X11 forwarding has been requested."));
}
else
{
werror("do_channel_open_x11: Invalid message!\n");
PROTOCOL_ERROR(connection->e, "Invalid CHANNEL_OPEN x11 message.");
}
}
struct channel_open *
make_channel_open_x11(struct io_backend *backend)
{
NEW(channel_open_x11, self);
self->super.handler = do_channel_open_x11;
self->backend = backend;
return &self->super;
}
/* Format is host:display.screen, where display and screen are numbers */
static int
parse_display(struct client_x11_display *self, const char *display)
{
struct lsh_string *host;
const char *num;
unsigned num_length;
unsigned display_num;
/* Get host name */
if (display[0] == ':')
{
/* Local transport */
host = NULL;
display++;
}
else
{
const char *separator = strchr(display, ':');
size_t length;
if (!separator)
return 0;
length = separator - display;
host = ssh_format("%ls", length, display);
display = separator + 1;
}
/* Get display number */
{
char *end;
num = display;
display_num = strtol(display, &end, 0);
num_length = end - num;
if (!num_length)
{
lsh_string_free(host);
return 0;
}
if (!*end)
/* Default screen number */
self->screen = 0;
else if (*end != '.')
{
lsh_string_free(host);
return 0;
}
else
{
display = end + 1;
self->screen = strtol(display, &end, 0);
if (*end)
{
lsh_string_free(host);
return 0;
}
}
}
if (host)
{
/* NOTE: How do we support IPv6 displays? I have no idea how
* that would work with xauth. Actually, xauth ought to use DNS
* names rather than IP addresses. */
struct address_info *a = make_address_info(host, X11_BASE_PORT + display_num);
self->address = address_info2sockaddr(&self->address_length, a, NULL, 1);
KILL(a);
if (!self->address)
return 0;
}
else
{
/* Local transport */
struct lsh_string *name = ssh_format("/tmp/.X11-unix/X%di", display_num);
struct sockaddr_un *sa;
verbose("Using local X11 transport `%pS'\n", name);
self->address_length = offsetof(struct sockaddr_un, sun_path) + name->length;
sa = lsh_space_alloc(self->address_length);
sa->sun_family = AF_UNIX;
memcpy(sa->sun_path, name->data, name->length);
lsh_string_free(name);
self->address = (struct sockaddr *) sa;
}
if (!xauth_lookup(self->address,
num_length, num,
&self->auth_name,
&self->auth_data))
{
/* Fallback: Don't use xauth, and hope that the X server uses
* xhost to let us in anyway. */
werror("Can't find any xauth information for X11 display.\n");
self->auth_name = ssh_format("");
self->auth_data = ssh_format("");
}
return 1;
}
struct client_x11_display *
make_client_x11_display(const char *display, struct lsh_string *fake)
{
NEW(client_x11_display, self);
self->fake = fake;
if (!parse_display(self, display))
{
werror("Can't parse X11 display: `%z'\n", display);
KILL(self);
return NULL;
}
return self;
}
/* GABA:
(class
(name client_x11_display_resource)
(super resource)
(vars
(connection object ssh_connection)
(display object client_x11_display)))
*/
static void
do_kill_x11_display(struct resource *s)
{
CAST(client_x11_display_resource, self, s);
if (self->super.alive)
{
self->super.alive = 0;
if (self->connection->table->x11_display == self->display)
self->connection->table->x11_display = NULL;
else
werror("do_kill_x11_display: Display has been replaced.\n");
}
}
static struct resource *
make_client_x11_display_resource(struct ssh_connection *connection,
struct client_x11_display *display)
{
NEW(client_x11_display_resource, self);
init_resource(&self->super, do_kill_x11_display);
self->connection = connection;
self->display = display;
return &self->super;
}
/* GABA:
(class
(name request_x11_continuation)
(super command_continuation)
(vars
(connection object ssh_connection)
(display object client_x11_display)
(up object command_continuation)))
*/
static void
do_request_x11_continuation(struct command_continuation *s,
struct lsh_object *a)
{
CAST(request_x11_continuation, self, s);
CAST_SUBTYPE(ssh_channel, channel, a);
verbose("X11 request succeeded\n");
if (self->connection->table->x11_display)
werror("client_x11.c: Replacing old x11 forwarding.\n");
self->connection->table->x11_display = self->display;
REMEMBER_RESOURCE(channel->resources,
make_client_x11_display_resource(self->connection,
self->display));
COMMAND_RETURN(self->up, a);
}
static struct command_continuation *
make_request_x11_continuation(struct ssh_connection *connection,
struct client_x11_display *display,
struct command_continuation *up)
{
NEW(request_x11_continuation, self);
self->super.c = do_request_x11_continuation;
self->connection = connection;
self->display = display;
self->up = up;
return &self->super;
}
/* GABA:
(class
(name request_x11_forward_command)
(super channel_request_command)
(vars
(connection object ssh_connection)
(display object client_x11_display)))
*/
static struct lsh_string *
do_format_request_x11_forward(struct channel_request_command *s,
struct ssh_channel *channel,
struct command_continuation **c)
{
CAST(request_x11_forward_command, self, s);
verbose("Requesting X11 forwarding.\n");
*c = make_request_x11_continuation(channel->connection,
self->display, *c);
/* NOTE: The cookie is hex encoded, appearantly so that it can be
* passed directly to the xauth command line. That's really ugly,
* but it's how the other ssh implementations do it. */
return format_channel_request(ATOM_X11_REQ, channel, 1, "%c%s%xS%i",
0, /* Single connection not supported */
MIT_COOKIE_NAME_LENGTH, MIT_COOKIE_NAME,
self->display->fake,
self->display->screen);
}
/* Consumes fake */
struct command *
make_forward_x11(const char *display_string,
struct randomness *random)
{
struct lsh_string *fake = lsh_string_alloc(X11_COOKIE_LENGTH);
struct client_x11_display *display;
RANDOM(random, fake->length, fake->data);
debug("Generated X11 fake cookie %xS\n", fake);
/* This deallocates fake if it fails. */
display = make_client_x11_display(display_string, fake);
if (display)
{
NEW(request_x11_forward_command, self);
self->super.super.call = do_channel_request_command;
self->super.format_request = do_format_request_x11_forward;
self->display = display;
return &self->super.super;
}
else
return NULL;
}

250
lsh/src/client_x11.c.x Normal file
View File

@ -0,0 +1,250 @@
/*
CLASS:client_x11_display:
*/
#ifndef GABA_DEFINE
struct client_x11_display
{
struct lsh_object super;
socklen_t address_length;
struct sockaddr (*(address));
UINT16 screen;
struct lsh_string *fake;
struct lsh_string *auth_name;
struct lsh_string *auth_data;
};
extern struct lsh_class client_x11_display_class;
#endif /* !GABA_DEFINE */
#ifndef GABA_DECLARE
static void
do_client_x11_display_free(struct lsh_object *o)
{
struct client_x11_display *i = (struct client_x11_display *) o;
if ( i->address )
lsh_space_free(i->address);
if ( i->fake )
lsh_string_free(i->fake);
if ( i->auth_name )
lsh_string_free(i->auth_name);
if ( i->auth_data )
lsh_string_free(i->auth_data);
}
struct lsh_class client_x11_display_class =
{
STATIC_HEADER,
NULL,
"client_x11_display",
sizeof(struct client_x11_display),
NULL,
do_client_x11_display_free,
};
#endif /* !GABA_DECLARE */
/*
CLASS:channel_open_x11:channel_open
*/
#ifndef GABA_DEFINE
struct channel_open_x11
{
struct channel_open super;
struct io_backend *backend;
};
extern struct lsh_class channel_open_x11_class;
#endif /* !GABA_DEFINE */
#ifndef GABA_DECLARE
static void
do_channel_open_x11_mark(struct lsh_object *o,
void (*mark)(struct lsh_object *o))
{
struct channel_open_x11 *i = (struct channel_open_x11 *) o;
mark((struct lsh_object *) i->backend);
}
struct lsh_class channel_open_x11_class =
{
STATIC_HEADER,
&(channel_open_class),
"channel_open_x11",
sizeof(struct channel_open_x11),
do_channel_open_x11_mark,
NULL,
};
#endif /* !GABA_DECLARE */
/*
CLASS:client_x11_channel:channel_forward
*/
#ifndef GABA_DEFINE
struct client_x11_channel
{
struct channel_forward super;
struct client_x11_display *display;
int state;
int little_endian;
unsigned name_length;
unsigned auth_length;
UINT32 i;
struct lsh_string *buffer;
};
extern struct lsh_class client_x11_channel_class;
#endif /* !GABA_DEFINE */
#ifndef GABA_DECLARE
static void
do_client_x11_channel_mark(struct lsh_object *o,
void (*mark)(struct lsh_object *o))
{
struct client_x11_channel *i = (struct client_x11_channel *) o;
mark((struct lsh_object *) i->display);
}
static void
do_client_x11_channel_free(struct lsh_object *o)
{
struct client_x11_channel *i = (struct client_x11_channel *) o;
lsh_string_free(i->buffer);
}
struct lsh_class client_x11_channel_class =
{
STATIC_HEADER,
&(channel_forward_class),
"client_x11_channel",
sizeof(struct client_x11_channel),
do_client_x11_channel_mark,
do_client_x11_channel_free,
};
#endif /* !GABA_DECLARE */
/*
CLASS:channel_open_x11_continuation:command_continuation
*/
#ifndef GABA_DEFINE
struct channel_open_x11_continuation
{
struct command_continuation super;
struct client_x11_display *display;
struct command_continuation *up;
};
extern struct lsh_class channel_open_x11_continuation_class;
#endif /* !GABA_DEFINE */
#ifndef GABA_DECLARE
static void
do_channel_open_x11_continuation_mark(struct lsh_object *o,
void (*mark)(struct lsh_object *o))
{
struct channel_open_x11_continuation *i = (struct channel_open_x11_continuation *) o;
mark((struct lsh_object *) i->display);
mark((struct lsh_object *) i->up);
}
struct lsh_class channel_open_x11_continuation_class =
{
STATIC_HEADER,
&(command_continuation_class),
"channel_open_x11_continuation",
sizeof(struct channel_open_x11_continuation),
do_channel_open_x11_continuation_mark,
NULL,
};
#endif /* !GABA_DECLARE */
/*
CLASS:client_x11_display_resource:resource
*/
#ifndef GABA_DEFINE
struct client_x11_display_resource
{
struct resource super;
struct ssh_connection *connection;
struct client_x11_display *display;
};
extern struct lsh_class client_x11_display_resource_class;
#endif /* !GABA_DEFINE */
#ifndef GABA_DECLARE
static void
do_client_x11_display_resource_mark(struct lsh_object *o,
void (*mark)(struct lsh_object *o))
{
struct client_x11_display_resource *i = (struct client_x11_display_resource *) o;
mark((struct lsh_object *) i->connection);
mark((struct lsh_object *) i->display);
}
struct lsh_class client_x11_display_resource_class =
{
STATIC_HEADER,
&(resource_class),
"client_x11_display_resource",
sizeof(struct client_x11_display_resource),
do_client_x11_display_resource_mark,
NULL,
};
#endif /* !GABA_DECLARE */
/*
CLASS:request_x11_continuation:command_continuation
*/
#ifndef GABA_DEFINE
struct request_x11_continuation
{
struct command_continuation super;
struct ssh_connection *connection;
struct client_x11_display *display;
struct command_continuation *up;
};
extern struct lsh_class request_x11_continuation_class;
#endif /* !GABA_DEFINE */
#ifndef GABA_DECLARE
static void
do_request_x11_continuation_mark(struct lsh_object *o,
void (*mark)(struct lsh_object *o))
{
struct request_x11_continuation *i = (struct request_x11_continuation *) o;
mark((struct lsh_object *) i->connection);
mark((struct lsh_object *) i->display);
mark((struct lsh_object *) i->up);
}
struct lsh_class request_x11_continuation_class =
{
STATIC_HEADER,
&(command_continuation_class),
"request_x11_continuation",
sizeof(struct request_x11_continuation),
do_request_x11_continuation_mark,
NULL,
};
#endif /* !GABA_DECLARE */
/*
CLASS:request_x11_forward_command:channel_request_command
*/
#ifndef GABA_DEFINE
struct request_x11_forward_command
{
struct channel_request_command super;
struct ssh_connection *connection;
struct client_x11_display *display;
};
extern struct lsh_class request_x11_forward_command_class;
#endif /* !GABA_DEFINE */
#ifndef GABA_DECLARE
static void
do_request_x11_forward_command_mark(struct lsh_object *o,
void (*mark)(struct lsh_object *o))
{
struct request_x11_forward_command *i = (struct request_x11_forward_command *) o;
mark((struct lsh_object *) i->connection);
mark((struct lsh_object *) i->display);
}
struct lsh_class request_x11_forward_command_class =
{
STATIC_HEADER,
&(channel_request_command_class),
"request_x11_forward_command",
sizeof(struct request_x11_forward_command),
do_request_x11_forward_command_mark,
NULL,
};
#endif /* !GABA_DECLARE */

View File

@ -24,6 +24,7 @@
*/
#include "command.h"
#include "werror.h"
#include "xalloc.h"
#include <assert.h>
@ -33,54 +34,29 @@
/* Combinators */
/* Ix == x */
DEFINE_COMMAND_SIMPLE(command_I, a) { return a; }
DEFINE_COMMAND(command_I)
(struct command *s UNUSED,
struct lsh_object *a,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
COMMAND_RETURN(c, a);
}
/* ((K x) y) == x */
/* Represents (K x) */
/* GABA:
(class
(name command_K_1)
(super command_simple)
(vars
(x object lsh_object)))
*/
static struct lsh_object *
do_simple_command_K_1(struct command_simple *s,
struct lsh_object *ignored UNUSED)
DEFINE_COMMAND2(command_K)
(struct command_2 *s UNUSED,
struct lsh_object *x,
struct lsh_object *y UNUSED,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST(command_K_1, self, s);
return self->x;
COMMAND_RETURN(c, x);
}
struct command *make_command_K_1(struct lsh_object *x)
{
NEW(command_K_1, res);
res->x = x;
res->super.super.call = do_call_simple_command;
res->super.call_simple = do_simple_command_K_1;
return &res->super.super;
}
DEFINE_COMMAND_SIMPLE(command_K, a)
{ return &make_command_K_1(a)->super; }
/* ((S f) g)x == (f x)(g x) */
/* Represents ((S f) g) */
/* GABA:
(class
(name command_S_2)
(super command_simple)
(vars
(f object command)
(g object command)))
*/
/* ((S f) g) x == (f x)(g x) */
/* Receives the value of (f x) */
/* GABA:
@ -119,286 +95,89 @@ make_command_S_continuation(struct command *g,
return &c->super.super;
}
static void
do_command_S_2(struct command *s,
DEFINE_COMMAND3(command_S)
(struct lsh_object *f,
struct lsh_object *g,
struct lsh_object *x,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(command_S_2, self, s);
COMMAND_CALL(self->f, x,
make_command_S_continuation(self->g, x, c, e),
e);
}
static struct lsh_object *
do_simple_command_S_2(struct command_simple *s,
struct lsh_object *x)
{
CAST(command_S_2, self, s);
CAST_SUBTYPE(command_simple, fs, self->f);
CAST_SUBTYPE(command_simple, gs, self->g);
CAST_SUBTYPE(command_simple, op, COMMAND_SIMPLE_CALL(fs, x));
return COMMAND_SIMPLE_CALL(op, COMMAND_SIMPLE_CALL(gs, x));
}
struct command *make_command_S_2(struct command *f,
struct command *g)
{
NEW(command_S_2, res);
res->f = f;
res->g = g;
res->super.super.call = do_command_S_2;
res->super.call_simple = do_simple_command_S_2;
return &res->super.super;
}
struct lsh_object *collect_S_2(struct collect_info_2 *info,
struct lsh_object *f,
struct lsh_object *g)
{
CAST_SUBTYPE(command, cf, f);
CAST_SUBTYPE(command, cg, g);
assert(!info->next);
return &make_command_S_2(cf, cg)->super;
COMMAND_CALL(cf, x,
make_command_S_continuation(cg, x, c, e),
e);
}
struct collect_info_2 collect_info_S_2 =
STATIC_COLLECT_2_FINAL(collect_S_2);
/* S' k f g x == k (f x) (g x) */
struct collect_info_1 command_S =
STATIC_COLLECT_1(&collect_info_S_2);
/* S' c f g x == c (f x) (g x) */
/* Represents S' c f g */
/* GABA:
(class
(name command_Sp_3)
(super command_simple)
(vars
(c object command)
(f object command)
(g object command)))
*/
static void
do_command_Sp_3(struct command *s,
DEFINE_COMMAND4(command_Sp)
(struct lsh_object *k,
struct lsh_object *f,
struct lsh_object *g,
struct lsh_object *x,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(command_Sp_3, self, s);
COMMAND_CALL(self->f, x,
make_apply(self->c,
make_command_S_continuation(self->g,
CAST_SUBTYPE(command, ck, k);
CAST_SUBTYPE(command, cf, f);
CAST_SUBTYPE(command, cg, g);
trace("command_Sp\n");
COMMAND_CALL(cf, x,
make_apply(ck,
make_command_S_continuation(cg,
x, c, e),
e),
e);
}
static struct lsh_object *
do_simple_command_Sp_3(struct command_simple *s,
struct lsh_object *x)
{
CAST(command_Sp_3, self, s);
CAST_SUBTYPE(command_simple, cs, self->c);
CAST_SUBTYPE(command_simple, fs, self->f);
CAST_SUBTYPE(command_simple, gs, self->g);
CAST_SUBTYPE(command_simple, op, COMMAND_SIMPLE_CALL(cs, COMMAND_SIMPLE_CALL(fs, x)));
return COMMAND_SIMPLE_CALL(op, COMMAND_SIMPLE_CALL(gs, x));
}
struct command *make_command_Sp_3(struct command *c,
struct command *f,
struct command *g)
{
NEW(command_Sp_3, res);
res->c = c;
res->f = f;
res->g = g;
res->super.super.call = do_command_Sp_3;
res->super.call_simple = do_simple_command_Sp_3;
return &res->super.super;
}
struct lsh_object *collect_Sp_3(struct collect_info_3 *info UNUSED,
struct lsh_object *c,
struct lsh_object *f,
struct lsh_object *g)
{
CAST_SUBTYPE(command, cc, c);
CAST_SUBTYPE(command, cf, f);
CAST_SUBTYPE(command, cg, g);
return &make_command_Sp_3(cc, cf, cg)->super;
}
struct collect_info_3 collect_info_Sp_3 =
STATIC_COLLECT_3_FINAL(collect_Sp_3);
struct collect_info_2 collect_info_Sp_2 =
STATIC_COLLECT_2(&collect_info_Sp_3);
struct collect_info_1 command_Sp =
STATIC_COLLECT_1(&collect_info_Sp_2);
/* B f g x == f (g x) */
/* Represents (B f g) */
/* GABA:
(class
(name command_B_2)
(super command_simple)
(vars
(f object command)
(g object command)))
*/
static void
do_command_B_2(struct command *s,
DEFINE_COMMAND3(command_B)
(struct lsh_object *f,
struct lsh_object *g,
struct lsh_object *x,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(command_B_2, self, s);
COMMAND_CALL(self->g, x,
make_apply(self->f, c, e), e);
}
static struct lsh_object *
do_simple_command_B_2(struct command_simple *s,
struct lsh_object *x)
{
CAST(command_B_2, self, s);
CAST_SUBTYPE(command_simple, fs, self->f);
CAST_SUBTYPE(command_simple, gs, self->g);
return COMMAND_SIMPLE_CALL(fs, COMMAND_SIMPLE_CALL(gs, x));
}
struct command *
make_command_B_2(struct command *f,
struct command *g)
{
NEW(command_B_2, res);
res->f = f;
res->g = g;
res->super.super.call = do_command_B_2;
res->super.call_simple = do_simple_command_B_2;
return &res->super.super;
}
struct lsh_object *collect_B_2(struct collect_info_2 *info,
struct lsh_object *f,
struct lsh_object *g)
{
CAST_SUBTYPE(command, cf, f);
CAST_SUBTYPE(command, cg, g);
assert(!info->next);
return &make_command_B_2(cf, cg)->super;
trace("command_B, f = %xi, cf = %xi, g = %xi, cg = %xi\n",
f, cf, g, cg);
COMMAND_CALL(cg, x,
make_apply(cf, c, e), e);
}
struct collect_info_2 collect_info_B_2 =
STATIC_COLLECT_2_FINAL(collect_B_2);
struct collect_info_1 command_B =
STATIC_COLLECT_1(&collect_info_B_2);
/* B' c f g x == c (f (g x)) */
/* Represents (B' c f g) */
/* GABA:
(class
(name command_Bp_3)
(super command_simple)
(vars
(c object command)
(f object command)
(g object command)))
*/
static void
do_command_Bp_3(struct command *s,
/* B' k f g x == k (f (g x)) */
DEFINE_COMMAND4(command_Bp)
(struct lsh_object *k,
struct lsh_object *f,
struct lsh_object *g,
struct lsh_object *x,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(command_Bp_3, self, s);
COMMAND_CALL(self->g, x,
make_apply(self->f,
make_apply(self->c, c, e), e),
CAST_SUBTYPE(command, ck, k);
CAST_SUBTYPE(command, cf, f);
CAST_SUBTYPE(command, cg, g);
trace("command_Bp\n");
COMMAND_CALL(cg, x,
make_apply(cf,
make_apply(ck, c, e), e),
e);
}
static struct lsh_object *
do_simple_command_Bp_3(struct command_simple *s,
struct lsh_object *x)
{
CAST(command_Bp_3, self, s);
CAST_SUBTYPE(command_simple, cs, self->c);
CAST_SUBTYPE(command_simple, fs, self->f);
CAST_SUBTYPE(command_simple, gs, self->g);
return COMMAND_SIMPLE_CALL(cs, COMMAND_SIMPLE_CALL(fs, COMMAND_SIMPLE_CALL(gs, x)));
}
struct command *
make_command_Bp_3(struct command *c,
struct command *f,
struct command *g)
{
NEW(command_Bp_3, res);
res->c = c;
res->f = f;
res->g = g;
res->super.super.call = do_command_Bp_3;
res->super.call_simple = do_simple_command_Bp_3;
return &res->super.super;
}
struct lsh_object *collect_Bp_3(struct collect_info_3 *info UNUSED,
struct lsh_object *c,
struct lsh_object *f,
struct lsh_object *g)
{
CAST_SUBTYPE(command, cc, c);
CAST_SUBTYPE(command, cf, f);
CAST_SUBTYPE(command, cg, g);
return &make_command_Bp_3(cc, cf, cg)->super;
}
struct collect_info_3 collect_info_Bp_3 =
STATIC_COLLECT_3_FINAL(collect_Bp_3);
struct collect_info_2 collect_info_Bp_2 =
STATIC_COLLECT_2(&collect_info_Bp_3);
struct collect_info_1 command_Bp =
STATIC_COLLECT_1(&collect_info_Bp_2);
/* ((C f) y) x == (f x) y */
/* Represents ((C f) g) */
/* GABA:
(class
(name command_C_2)
(super command_simple)
(vars
(f object command)
(y object lsh_object)))
*/
/* GABA:
(class
(name command_C_continuation)
@ -431,129 +210,44 @@ make_command_C_continuation(struct lsh_object *y,
return &c->super.super;
}
static void
do_command_C_2(struct command *s,
DEFINE_COMMAND3(command_C)
(struct lsh_object *f,
struct lsh_object *y,
struct lsh_object *x,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(command_C_2, self, s);
CAST_SUBTYPE(command, cf, f);
COMMAND_CALL(self->f, x,
make_command_C_continuation(self->y, c, e),
trace("command_C\n");
COMMAND_CALL(cf, x,
make_command_C_continuation(y, c, e),
e);
}
static struct lsh_object *do_simple_command_C_2(struct command_simple *s,
struct lsh_object *x)
{
CAST(command_C_2, self, s);
CAST_SUBTYPE(command_simple, f, self->f);
CAST_SUBTYPE(command_simple, v, COMMAND_SIMPLE_CALL(f, x));
return COMMAND_SIMPLE_CALL(v, self->y);
}
struct command *
make_command_C_2(struct command *f,
struct lsh_object *y)
{
NEW(command_C_2, res);
res->f = f;
res->y = y;
res->super.super.call = do_command_C_2;
res->super.call_simple = do_simple_command_C_2;
return &res->super.super;
}
struct lsh_object *collect_C_2(struct collect_info_2 *info,
/* C' k f y x == k (f x) y */
DEFINE_COMMAND4(command_Cp)
(struct lsh_object *k,
struct lsh_object *f,
struct lsh_object *y)
{
CAST_SUBTYPE(command, cf, f);
assert(!info->next);
return &make_command_C_2(cf, y)->super;
}
struct collect_info_2 collect_info_C_2 =
STATIC_COLLECT_2_FINAL(collect_C_2);
struct collect_info_1 command_C =
STATIC_COLLECT_1(&collect_info_C_2);
/* C' c f y x == c (f x) y */
/* Represents (C' c f y x) */
/* GABA:
(class
(name command_Cp_3)
(super command_simple)
(vars
(c object command)
(f object command)
(y object lsh_object)))
*/
static void
do_command_Cp_3(struct command *s,
struct lsh_object *y,
struct lsh_object *x,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(command_Cp_3, self, s);
COMMAND_CALL(self->f, x,
make_apply(self->c,
make_command_C_continuation(self->y, c, e), e),
e);
}
static struct lsh_object *
do_simple_command_Cp_3(struct command_simple *s,
struct lsh_object *x)
{
CAST(command_Cp_3, self, s);
CAST_SUBTYPE(command_simple, cs, self->c);
CAST_SUBTYPE(command_simple, fs, self->f);
CAST_SUBTYPE(command_simple, op, COMMAND_SIMPLE_CALL(cs, COMMAND_SIMPLE_CALL(fs, x)));
return COMMAND_SIMPLE_CALL(op, self->y);
}
struct command *
make_command_Cp_3(struct command *c,
struct command *f,
struct lsh_object *y)
{
NEW(command_Cp_3, res);
res->c = c;
res->f = f;
res->y = y;
res->super.super.call = do_command_Cp_3;
res->super.call_simple = do_simple_command_Cp_3;
return &res->super.super;
}
struct lsh_object *
collect_Cp_3(struct collect_info_3 *info UNUSED,
struct lsh_object *c,
struct lsh_object *f,
struct lsh_object *y)
{
CAST_SUBTYPE(command, cc, c);
CAST_SUBTYPE(command, ck, k);
CAST_SUBTYPE(command, cf, f);
return &make_command_Cp_3(cc, cf, y)->super;
trace("command_Cp\n");
#if 0
werror("command_Cp: k: %t, f: %t, y: %t, x: %t\n",
k, f, y, x);
#endif
COMMAND_CALL(cf, x,
make_apply(ck,
make_command_C_continuation(y, c, e), e),
e);
}
struct collect_info_3 collect_info_Cp_3 =
STATIC_COLLECT_3_FINAL(collect_Cp_3);
struct collect_info_2 collect_info_Cp_2 =
STATIC_COLLECT_2(&collect_info_Cp_3);
struct collect_info_1 command_Cp =
STATIC_COLLECT_1(&collect_info_Cp_2);

Binary file not shown.

View File

@ -89,39 +89,273 @@ make_apply(struct command *f,
return &res->super.super;
}
struct lsh_object *gaba_apply(struct lsh_object *f,
/* GABA:
(class
(name gaba_continuation)
(super command_continuation)
(vars
(value object lsh_object)))
*/
static void
do_gaba_continuation(struct command_continuation *c,
struct lsh_object *x)
{
CAST_SUBTYPE(command_simple, cf, f);
return COMMAND_SIMPLE_CALL(cf, x);
CAST(gaba_continuation, self, c);
assert(!self->value);
self->value = x;
}
struct lsh_object *
gaba_apply(struct lsh_object *f,
struct lsh_object *x)
{
CAST_SUBTYPE(command, cf, f);
struct gaba_continuation c =
{ { STATIC_HEADER, do_gaba_continuation }, NULL };
COMMAND_CALL(cf, x, &c.super, &default_exception_handler);
return c.value;
}
/* A command taking 2 arguments */
/* GABA:
(class
(name command_2_invoke)
(super command)
(vars
(f object command_2)
(a1 object lsh_object)))
*/
static void
do_command_2_invoke(struct command *s, struct lsh_object *a2,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(command_2_invoke, self, s);
COMMAND_2_INVOKE(self->f, self->a1, a2, c, e);
}
struct command *
make_command_2_invoke(struct command_2 *f,
struct lsh_object *a1)
{
NEW(command_2_invoke, self);
self->super.call = do_command_2_invoke;
self->f = f;
self->a1 = a1;
return &self->super;
}
void
do_call_simple_command(struct command *s,
struct lsh_object *arg,
do_command_2(struct command *s,
struct lsh_object *a1,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST_SUBTYPE(command_simple, self, s);
COMMAND_RETURN(c, COMMAND_SIMPLE_CALL(self, arg));
CAST_SUBTYPE(command_2, self, s);
COMMAND_RETURN(c, make_command_2_invoke(self, a1));
}
/* A command taking 3 arguments */
/* GABA:
(class
(name command_3_invoke_2)
(super command)
(vars
(f object command_3)
(a1 object lsh_object)
(a2 object lsh_object)))
*/
static void
do_command_3_invoke_2(struct command *s,
struct lsh_object *a3,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(command_3_invoke_2, self, s);
self->f->invoke(self->a1, self->a2, a3, c, e);
}
struct command *
make_command_3_invoke_2(struct command_3 *f,
struct lsh_object *a1,
struct lsh_object *a2)
{
NEW(command_3_invoke_2, self);
self->super.call = do_command_3_invoke_2;
self->f = f;
self->a1 = a1;
self->a2 = a2;
return &self->super;
}
/* GABA:
(class
(name command_3_invoke)
(super command)
(vars
(f object command_3)
(a1 object lsh_object)))
*/
static void
do_command_3_invoke(struct command *s,
struct lsh_object *a2,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST(command_3_invoke, self, s);
COMMAND_RETURN(c, make_command_3_invoke_2(self->f, self->a1, a2));
}
struct command *
make_command_3_invoke(struct command_3 *f,
struct lsh_object *a1)
{
NEW(command_3_invoke, self);
self->super.call = do_command_3_invoke;
self->f = f;
self->a1 = a1;
return &self->super;
}
void
do_command_3(struct command *s,
struct lsh_object *a1,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST_SUBTYPE(command_3, self, s);
COMMAND_RETURN(c, make_command_3_invoke(self, a1));
}
/* Unimplemented command */
/* A command taking 4 arguments */
/* GABA:
(class
(name command_4_invoke_3)
(super command)
(vars
(f object command_4)
(a1 object lsh_object)
(a2 object lsh_object)
(a3 object lsh_object)))
*/
static void
do_command_unimplemented(struct command *s UNUSED,
struct lsh_object *o UNUSED,
struct command_continuation *c UNUSED,
do_command_4_invoke_3(struct command *s,
struct lsh_object *a4,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(command_4_invoke_3, self, s);
self->f->invoke(self->a1, self->a2, self->a3, a4, c, e);
}
struct command *
make_command_4_invoke_3(struct command_4 *f,
struct lsh_object *a1,
struct lsh_object *a2,
struct lsh_object *a3)
{
NEW(command_4_invoke_3, self);
self->super.call = do_command_4_invoke_3;
self->f = f;
self->a1 = a1;
self->a2 = a2;
self->a3 = a3;
return &self->super;
}
/* GABA:
(class
(name command_4_invoke_2)
(super command)
(vars
(f object command_4)
(a1 object lsh_object)
(a2 object lsh_object)))
*/
static void
do_command_4_invoke_2(struct command *s,
struct lsh_object *a3,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{ fatal("command.c: Unimplemented command.\n"); }
{
CAST(command_4_invoke_2, self, s);
COMMAND_RETURN(c, make_command_4_invoke_3(self->f, self->a1, self->a2, a3));
}
static struct lsh_object *
do_command_simple_unimplemented(struct command_simple *s UNUSED,
struct lsh_object *o UNUSED)
{ fatal("command.c: Unimplemented simple command.\n"); }
struct command *
make_command_4_invoke_2(struct command_4 *f,
struct lsh_object *a1,
struct lsh_object *a2)
{
NEW(command_4_invoke_2, self);
struct command_simple command_unimplemented =
{ { STATIC_HEADER, do_command_unimplemented}, do_command_simple_unimplemented};
self->super.call = do_command_4_invoke_2;
self->f = f;
self->a1 = a1;
self->a2 = a2;
return &self->super;
}
/* GABA:
(class
(name command_4_invoke)
(super command)
(vars
(f object command_4)
(a1 object lsh_object)))
*/
static void
do_command_4_invoke(struct command *s,
struct lsh_object *a2,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST(command_4_invoke, self, s);
COMMAND_RETURN(c, make_command_4_invoke_2(self->f, self->a1, a2));
}
struct command *
make_command_4_invoke(struct command_4 *f,
struct lsh_object *a1)
{
NEW(command_4_invoke, self);
self->super.call = do_command_4_invoke;
self->f = f;
self->a1 = a1;
return &self->super;
}
void
do_command_4(struct command *s,
struct lsh_object *a1,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST_SUBTYPE(command_4, self, s);
COMMAND_RETURN(c, make_command_4_invoke(self, a1));
}
/* Tracing */
@ -142,15 +376,9 @@ do_trace_continuation(struct command_continuation *s,
struct lsh_object *x)
{
CAST(trace_continuation, self, s);
const char *type;
if (x)
type = (x->isa) ? x->isa->name : "<STATIC>";
else
type = "<NULL>";
trace("Leaving %z, value of type %z.\n",
self->name, type);
trace("Leaving %z, value of type %t.\n",
self->name, x);
COMMAND_RETURN(self->real, x);
}
@ -210,90 +438,6 @@ struct lsh_object *collect_trace(const char *name, struct lsh_object *c)
}
#endif /* DEBUG_TRACE */
/* Collecting arguments */
struct lsh_object *
do_collect_1(struct command_simple *s, struct lsh_object *a)
{
CAST(collect_info_1, self, s);
return self->f(self, a);
}
/* GABA:
(class
(name collect_state_1)
(super command_simple)
(vars
(info object collect_info_2)
(a object lsh_object)))
*/
/* GABA:
(class
(name collect_state_2)
(super command_simple)
(vars
(info object collect_info_3)
(a object lsh_object)
(b object lsh_object)))
*/
/* GABA:
(class
(name collect_state_3)
(super command_simple)
(vars
(info object collect_info_4)
(a object lsh_object)
(b object lsh_object)
(c object lsh_object)))
*/
static struct lsh_object *
do_collect_2(struct command_simple *s,
struct lsh_object *x)
{
CAST(collect_state_1, self, s);
return self->info->f(self->info, self->a, x);
}
struct lsh_object *
make_collect_state_1(struct collect_info_1 *info,
struct lsh_object *a)
{
NEW(collect_state_1, self);
self->info = info->next;
self->a = a;
self->super.call_simple = do_collect_2;
self->super.super.call = do_call_simple_command;
return &self->super.super.super;
}
static struct lsh_object *
do_collect_3(struct command_simple *s,
struct lsh_object *x)
{
CAST(collect_state_2, self, s);
return self->info->f(self->info, self->a, self->b, x);
}
struct lsh_object *
make_collect_state_2(struct collect_info_2 *info,
struct lsh_object *a,
struct lsh_object *b)
{
NEW(collect_state_2, self);
self->info = info->next;
self->a = a;
self->b = b;
self->super.call_simple = do_collect_3;
self->super.super.call = do_call_simple_command;
return &self->super.super.super;
}
/* GABA:
(class
(name parallell_progn)
@ -335,11 +479,17 @@ struct command *make_parallell_progn(struct object_list *body)
}
}
DEFINE_COMMAND_SIMPLE(progn_command, a)
DEFINE_COMMAND(progn_command)
(struct command *s UNUSED,
struct lsh_object *a,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST(object_list, body, a);
return LIST_LENGTH(body) ? &make_parallell_progn(body)->super
: &command_I.super.super;
COMMAND_RETURN(c, (LIST_LENGTH(body)
? make_parallell_progn(body)
: &command_I));
}
/* Catch command
@ -464,42 +614,45 @@ make_catch_apply(struct catch_handler_info *info,
/* GABA:
(class
(name catch_collect_body)
(super command_simple)
(super command)
(vars
(info object catch_handler_info)))
*/
static struct lsh_object *
do_catch_collect_body(struct command_simple *s,
struct lsh_object *a)
static void
do_catch_collect_body(struct command *s,
struct lsh_object *a,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST(catch_collect_body, self, s);
CAST_SUBTYPE(command, body, a);
return &make_catch_apply(self->info, body)->super;
COMMAND_RETURN(c, make_catch_apply(self->info, body));
}
static struct command *
make_catch_collect_body(struct catch_handler_info *info)
{
NEW(catch_collect_body, self);
self->super.super.call = do_call_simple_command;
self->super.call_simple = do_catch_collect_body;
self->super.call = do_catch_collect_body;
self->info = info;
return &self->super.super;
return &self->super;
}
struct lsh_object *
do_catch_simple(struct command_simple *s,
struct lsh_object *a)
void
do_catch_simple(struct command *s,
struct lsh_object *a,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST(catch_command, self, s);
CAST_SUBTYPE(command, f, a);
return &(make_catch_collect_body(make_catch_handler_info(self->mask,
self->value, self->ignore_value, f))
->super);
COMMAND_RETURN(c,
make_catch_collect_body
(make_catch_handler_info(self->mask,
self->value, self->ignore_value, f)));
}
@ -541,13 +694,15 @@ make_catch_report_apply(struct report_exception_info *info,
return &self->super;
}
struct lsh_object *
do_catch_report_collect(struct command_simple *s,
struct lsh_object *a)
void
do_catch_report_collect(struct command *s,
struct lsh_object *a,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
CAST(catch_report_collect, self, s);
CAST_SUBTYPE(command, body, a);
return &make_catch_report_apply(self->info, body)->super;
COMMAND_RETURN(c,
make_catch_report_apply(self->info, body));
}

Binary file not shown.

View File

@ -46,6 +46,8 @@
(c method void "struct lsh_object *result")))
*/
#define COMMAND_RETURN(r, v) ((r)->c((r), (struct lsh_object *) (v)))
/* GABA:
(class
(name command)
@ -55,57 +57,159 @@
"struct exception_handler *e")))
*/
/* GABA:
(class
(name command_simple)
(super command)
(vars
; Like call, but returns the value immediately rather than
; using a continuation function.
(call_simple method "struct lsh_object *" "struct lsh_object *")))
*/
#define COMMAND_CALL(f, a, c, e) \
((void)&(f), ((f)->call((f), (struct lsh_object *) (a), (c), (e))))
#define COMMAND_RETURN(r, v) ((r)->c((r), (struct lsh_object *) (v)))
#define COMMAND_SIMPLE_CALL(f, a) \
((f)->call_simple((f), (struct lsh_object *)(a)))
/* NOTE: Except when inheriting command, use DEFINE_COMMAND instead. */
#define STATIC_COMMAND(f) { STATIC_HEADER, f }
#define STATIC_COMMAND_SIMPLE(f) \
{ STATIC_COMMAND(do_call_simple_command), f}
#define DEFINE_COMMAND_SIMPLE(cname, ARG) \
static struct lsh_object * \
do_simple_##cname(struct command_simple *, \
struct lsh_object *a); \
\
struct command_simple cname = \
STATIC_COMMAND_SIMPLE(do_simple_##cname); \
\
static struct lsh_object * \
do_simple_##cname(struct command_simple *s UNUSED, \
struct lsh_object *ARG)
#define DEFINE_COMMAND(cname, ARG, CC, EXC) \
#define DEFINE_COMMAND(cname) \
static void \
do_##cname(struct command *s UNUSED, \
struct lsh_object *ARG, \
struct command_continuation *CC, \
struct exception_handler *EXC); \
do_##cname(struct command *, \
struct lsh_object *, \
struct command_continuation *, \
struct exception_handler *); \
\
struct command cname = \
STATIC_COMMAND(do_##cname); \
\
static void \
do_##cname(struct command *s UNUSED, \
struct lsh_object *ARG, \
struct command_continuation *CC, \
struct exception_handler *EXC)
do_##cname
/* A command taking 2 arguments */
/* GABA:
(class
(name command_2)
(super command)
(vars
(invoke method void
"struct lsh_object *a1"
"struct lsh_object *a2"
"struct command_continuation *c"
"struct exception_handler *e"))))
*/
#define COMMAND_2_INVOKE(s, a1, a2, c, e) \
((s)->invoke((s), (a1), (a2), (c), (e)))
void
do_command_2(struct command *s,
struct lsh_object *a1,
struct command_continuation *c,
struct exception_handler *e);
struct command *
make_command_2_invoke(struct command_2 *f,
struct lsh_object *a1);
#define DEFINE_COMMAND2(cname) \
static void \
do_##cname(struct command_2 *, \
struct lsh_object *, \
struct lsh_object *, \
struct command_continuation *, \
struct exception_handler *); \
\
struct command_2 cname = \
{ { STATIC_HEADER, do_command_2 }, do_##cname }; \
\
static void \
do_##cname
/* A command taking 3 arguments */
/* GABA:
(class
(name command_3)
(super command)
(vars
(invoke pointer
(function void "struct lsh_object *a1"
"struct lsh_object *a2"
"struct lsh_object *a3"
"struct command_continuation *c"
"struct exception_handler *e"))))
*/
void
do_command_3(struct command *s,
struct lsh_object *a1,
struct command_continuation *c,
struct exception_handler *e);
struct command *
make_command_3_invoke(struct command_3 *f,
struct lsh_object *a1);
struct command *
make_command_3_invoke_2(struct command_3 *f,
struct lsh_object *a1,
struct lsh_object *a2);
#define DEFINE_COMMAND3(cname) \
static void \
do_##cname(struct lsh_object *, \
struct lsh_object *, \
struct lsh_object *, \
struct command_continuation *, \
struct exception_handler *); \
\
struct command_3 cname = \
{ { STATIC_HEADER, do_command_3 }, do_##cname }; \
\
static void \
do_##cname
/* A command taking 4 arguments */
/* GABA:
(class
(name command_4)
(super command)
(vars
(invoke pointer
(function void "struct lsh_object *a1"
"struct lsh_object *a2"
"struct lsh_object *a3"
"struct lsh_object *a4"
"struct command_continuation *c"
"struct exception_handler *e"))))
*/
void
do_command_4(struct command *s,
struct lsh_object *a1,
struct command_continuation *c,
struct exception_handler *e);
struct command *
make_command_4_invoke(struct command_4 *f,
struct lsh_object *a1);
struct command *
make_command_4_invoke_2(struct command_4 *f,
struct lsh_object *a1,
struct lsh_object *a2);
struct command *
make_command_4_invoke_3(struct command_4 *f,
struct lsh_object *a1,
struct lsh_object *a2,
struct lsh_object *a3);
#define DEFINE_COMMAND4(cname) \
static void \
do_##cname(struct lsh_object *, \
struct lsh_object *, \
struct lsh_object *, \
struct lsh_object *, \
struct command_continuation *, \
struct exception_handler *); \
\
struct command_4 cname = \
{ { STATIC_HEADER, do_command_4 }, do_##cname }; \
\
static void \
do_##cname
void do_call_simple_command(struct command *s,
@ -114,7 +218,7 @@ void do_call_simple_command(struct command *s,
struct exception_handler *e);
struct command *make_parallell_progn(struct object_list *body);
extern struct command_simple progn_command;
extern struct command progn_command;
extern struct command_continuation discard_continuation;
@ -153,14 +257,14 @@ make_command_context(struct command_continuation *c,
/* GABA:
(class
(name catch_command)
(super command_simple)
(super command)
(vars
(mask . UINT32)
(value . UINT32)
; Ignore return values from body. This means that the catch
; will return *only* if some exception is raised. Useful for
; reading until some EOF exception ir raised.
; reading until some EOF exception is raised.
(ignore_value . int))) */
struct catch_handler_info *
@ -172,18 +276,20 @@ struct command *
make_catch_apply(struct catch_handler_info *info,
struct command *body);
struct lsh_object *
do_catch_simple(struct command_simple *s,
struct lsh_object *a);
void
do_catch_simple(struct command *s,
struct lsh_object *a,
struct command_continuation *c,
struct exception_handler *e);
#define STATIC_CATCH_COMMAND(m, v, i) \
{ STATIC_COMMAND_SIMPLE(do_catch_simple), (m), (v), (i) }
{ STATIC_COMMAND(do_catch_simple), (m), (v), (i) }
/* GABA:
(class
(name catch_report_collect)
(super command_simple)
(super command)
(vars
(info object report_exception_info)))
*/
@ -192,79 +298,14 @@ struct command *
make_catch_report_apply(struct report_exception_info *info,
struct command *body);
struct lsh_object *
do_catch_report_collect(struct command_simple *s,
struct lsh_object *a);
void
do_catch_report_collect(struct command *s,
struct lsh_object *a,
struct command_continuation *c,
struct exception_handler *e);
#define STATIC_CATCH_REPORT(i) \
{ STATIC_COMMAND_SIMPLE(do_catch_report_collect), i }
/* Commands that need to collect some arguments before actually doing
* anything. */
/* The collect_info_n classes keeps track about what to do with the
* next argument. As long as we collect arguments without doing
* anything, the f field in collect_info_n will point to the
* constructor make_collect_state_n. */
/* GABA:
(class
(name collect_info_3)
(vars
(f method "struct lsh_object *"
"struct lsh_object *" "struct lsh_object *"
"struct lsh_object *")))
*/
/* GABA:
(class
(name collect_info_2)
(vars
(f method "struct lsh_object *"
"struct lsh_object *" "struct lsh_object *")
(next object collect_info_3)))
*/
/* GABA:
(class
(name collect_info_1)
(super command_simple)
(vars
(f method "struct lsh_object *"
"struct lsh_object *")
(next object collect_info_2)))
*/
struct lsh_object *
do_collect_1(struct command_simple *s, struct lsh_object *a);
struct lsh_object *
make_collect_state_1(struct collect_info_1 *info,
struct lsh_object *a);
struct lsh_object *
make_collect_state_2(struct collect_info_2 *info,
struct lsh_object *a,
struct lsh_object *b);
#define STATIC_COLLECT_1(next) \
{ { { STATIC_HEADER, do_call_simple_command }, do_collect_1}, \
make_collect_state_1, next }
#define STATIC_COLLECT_2(next) \
{ STATIC_HEADER, make_collect_state_2, next }
#define STATIC_COLLECT_2_FINAL(f) \
{ STATIC_HEADER, f, NULL }
#define STATIC_COLLECT_3_FINAL(f) \
{ STATIC_HEADER, f }
extern struct command_simple command_unimplemented;
#define COMMAND_UNIMPLEMENTED (&command_unimplemented.super.super)
extern struct command command_die_on_null;
{ STATIC_COMMAND(do_catch_report_collect), i }
#if DEBUG_TRACE
@ -278,7 +319,7 @@ struct lsh_object *collect_trace(const char *name, struct lsh_object *real);
/* Useful clobal commands */
#define PROG1 (&command_K.super.super)
#define PROGN (&progn_command.super.super)
#define PROGN (&progn_command.super)
/* The GABA_* macros are used by automatically generated evaluation code */
@ -291,94 +332,72 @@ struct lsh_object *gaba_apply(struct lsh_object *f,
#define GABA_APPLY gaba_apply
extern struct command_simple command_I;
#define GABA_VALUE_I (&command_I.super.super)
extern struct command command_I;
#define GABA_VALUE_I (&command_I.super)
#define GABA_APPLY_I_1(x) (x)
extern struct command_simple command_K;
extern struct command_2 command_K;
struct command *make_command_K_1(struct lsh_object *x);
#define GABA_VALUE_K (&command_K.super.super)
#define GABA_APPLY_K_1(x) ((struct lsh_object *) make_command_K_1(x))
#define GABA_APPLY_K_1(x) \
((struct lsh_object *) make_command_2_invoke(&command_K, (x)))
extern struct collect_info_1 command_S;
extern struct collect_info_2 collect_info_S_2;
extern struct command_3 command_S;
struct command *make_command_S_2(struct command *f,
struct command *g);
#define GABA_VALUE_S (&command_S.super.super)
#define GABA_APPLY_S_1(f) \
((struct lsh_object *) make_command_3_invoke(&command_S, (f)))
#define GABA_APPLY_S_2(f, g) \
((struct lsh_object *) make_command_3_invoke_2(&command_S, (f), (g)))
struct lsh_object *collect_S_2(struct collect_info_2 *info,
struct lsh_object *f,
struct lsh_object *g);
extern struct command_4 command_Sp;
#define GABA_VALUE_S (&command_S.super.super.super)
#define GABA_APPLY_S_1(f) (make_collect_state_1(&command_S, (f)))
#define GABA_APPLY_S_2(f, g) (collect_S_2(&collect_info_S_2, (f), (g)))
extern struct collect_info_1 command_Sp;
extern struct collect_info_2 collect_info_Sp_2;
extern struct collect_info_3 collect_info_Sp_3;
struct command *make_command_Sp_3(struct command *c,
struct command *f,
struct command *g);
struct lsh_object *collect_Sp_3(struct collect_info_3 *info,
struct lsh_object *c,
struct lsh_object *f,
struct lsh_object *g);
#define GABA_VALUE_Sp (&command_Sp.super.super.super)
#define GABA_APPLY_Sp_1(c) (make_collect_state_1(&command_Sp, (c)))
#define GABA_VALUE_Sp (&command_Sp.super.super)
#define GABA_APPLY_Sp_1(c) \
((struct lsh_object *) make_command_4_invoke(&command_Sp, (f)))
#define GABA_APPLY_Sp_2(c, f) \
(make_collect_state_2(&collect_info_Sp_2, (c), (f)))
#define GABA_APPLY_Sp_3(c, f, g) (collect_Sp_3(&collect_info_Sp_3, (c), (f), (g)))
((struct lsh_object *) make_command_4_invoke_2(&command_Sp, (c), (f)))
#define GABA_APPLY_Sp_3(c, f, g) \
((struct lsh_object *) make_command_4_invoke_3(&command_Sp, (c), (f), (g)))
extern struct collect_info_1 command_B;
extern struct collect_info_2 collect_info_B_2;
extern struct command_3 command_B;
struct command *make_command_B_2(struct command *f,
struct command *g);
struct lsh_object *collect_B_2(struct collect_info_2 *info,
struct lsh_object *f,
struct lsh_object *g);
#define GABA_VALUE_B (&command_B.super.super)
#define GABA_APPLY_B_1(f) \
((struct lsh_object *) make_command_3_invoke(&command_B, (f)))
#define GABA_APPLY_B_2(f, g) \
((struct lsh_object *) make_command_3_invoke_2(&command_B, (f), (g)))
#define GABA_VALUE_B (&command_B.super.super.super)
#define GABA_APPLY_B_1(f) (make_collect_state_1(&command_B, (f)))
#define GABA_APPLY_B_2(f, g) (collect_B_2(&collect_info_B_2, (f), (g)))
extern struct command_4 command_Bp;
extern struct collect_info_1 command_Bp;
extern struct collect_info_2 collect_info_Bp_2;
extern struct collect_info_3 collect_info_Bp_3;
struct command *make_command_Bp_3(struct command *c,
struct command *f,
struct command *g);
struct lsh_object *collect_Bp_3(struct collect_info_3 *info,
struct lsh_object *c,
struct lsh_object *f,
struct lsh_object *g);
#define GABA_VALUE_Bp (&command_Bp.super.super.super)
#define GABA_APPLY_Bp_1(c) (make_collect_state_1(&command_Bp, (c)))
#define GABA_VALUE_Bp (&command_Bp.super.super)
#define GABA_APPLY_Bp_1(c) \
((struct lsh_object *) make_command_4_invoke(&command_Bp, (c)))
#define GABA_APPLY_Bp_2(c, f) \
(make_collect_state_2(&collect_info_Bp_2, (c), (f)))
#define GABA_APPLY_Bp_3(c, f, g) (collect_Bp_3(&collect_info_Bp_3, (c), (f), (g)))
((struct lsh_object *) make_command_4_invoke_2(&command_Bp, (c), (f)))
#define GABA_APPLY_Bp_3(c, f, g) \
((struct lsh_object *) make_command_4_invoke_3(&command_Bp, (c), (f), (g)))
extern struct collect_info_1 command_C;
extern struct collect_info_2 collect_info_C_2;
extern struct command_3 command_C;
struct command *
make_command_C_2(struct command *f,
struct lsh_object *y);
struct lsh_object *
collect_C_2(struct collect_info_2 *info,
struct lsh_object *f,
struct lsh_object *y);
#define GABA_VALUE_C (&command_C.super.super)
#define GABA_APPLY_C_1(f) \
((struct lsh_object *) make_command_3_invoke(&command_C, (f)))
#define GABA_APPLY_C_2(f, g) \
((struct lsh_object *) make_command_3_invoke_2(&command_C, (f), (g)))
#define GABA_VALUE_C (&command_C.super.super.super)
#define GABA_APPLY_C_1(f) (make_collect_state_1(&command_C, (f)))
#define GABA_APPLY_C_2(f, y) (collect_C_2(&collect_info_C_2, (f), (y)))
#if 1
extern struct command_4 command_Cp;
#define GABA_VALUE_Cp (&command_Cp.super.super)
#define GABA_APPLY_Cp_1(c) \
((struct lsh_object *) make_command_4_invoke(&command_Cp, (c)))
#define GABA_APPLY_Cp_2(c, f) \
((struct lsh_object *) make_command_4_invoke_2(&command_Cp, (c), (f)))
#define GABA_APPLY_Cp_3(c, f, g) \
((struct lsh_object *) make_command_4_invoke_3(&command_Cp, (c), (f), (g)))
#else
extern struct collect_info_1 command_Cp;
extern struct collect_info_2 collect_info_Cp_2;
@ -400,5 +419,6 @@ collect_Cp_3(struct collect_info_3 *info,
(make_collect_state_2(&collect_info_Cp_2, (c), (f)))
#define GABA_APPLY_Cp_3(c, f, y) (collect_Cp_3(&collect_info_Cp_3, (c), (f), (y)))
#endif
#endif /* LSH_COMMAND_H_INCLUDED */

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More