mirror of https://github.com/macssh/macssh.git
lsh 1.3.4 update
This commit is contained in:
parent
5b5e0e778c
commit
5318b19fca
BIN
lsh/ANNOUNCE
BIN
lsh/ANNOUNCE
Binary file not shown.
BIN
lsh/ChangeLog
BIN
lsh/ChangeLog
Binary file not shown.
Binary file not shown.
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
BIN
lsh/Makefile.am
BIN
lsh/Makefile.am
Binary file not shown.
Binary file not shown.
BIN
lsh/Makefile.in
BIN
lsh/Makefile.in
Binary file not shown.
BIN
lsh/README
BIN
lsh/README
Binary file not shown.
119
lsh/acconfig.h
119
lsh/acconfig.h
|
@ -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
|
BIN
lsh/acinclude.m4
BIN
lsh/acinclude.m4
Binary file not shown.
Binary file not shown.
BIN
lsh/config.h.in
BIN
lsh/config.h.in
Binary file not shown.
Binary file not shown.
BIN
lsh/configure.in
BIN
lsh/configure.in
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lsh/doc/HACKING
BIN
lsh/doc/HACKING
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lsh/doc/TODO
BIN
lsh/doc/TODO
Binary file not shown.
103
lsh/doc/lsh.html
103
lsh/doc/lsh.html
|
@ -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.
|
||||
|
|
BIN
lsh/doc/lsh.info
BIN
lsh/doc/lsh.info
Binary file not shown.
Binary file not shown.
BIN
lsh/install-sh
BIN
lsh/install-sh
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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)
|
||||
|
|
|
@ -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.
|
@ -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.
|
@ -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.
|
@ -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.
|
@ -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.
|
@ -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.
|
@ -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.
Binary file not shown.
|
@ -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}
|
||||
};
|
||||
|
||||
|
|
|
@ -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.
|
@ -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};
|
||||
|
|
BIN
lsh/src/cast.c.x
BIN
lsh/src/cast.c.x
Binary file not shown.
|
@ -32,7 +32,7 @@
|
|||
#include "cbc.c.x"
|
||||
|
||||
#if !HAVE_MEMXOR
|
||||
#include "memxor.h"
|
||||
#include "nettle/memxor.h"
|
||||
#endif
|
||||
|
||||
/* GABA:
|
||||
|
|
BIN
lsh/src/cbc.c.x
BIN
lsh/src/cbc.c.x
Binary file not shown.
|
@ -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.
|
@ -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.
|
@ -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.
|
@ -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.
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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);
|
||||
|
|
323
lsh/src/client.c
323
lsh/src/client.c
|
@ -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.
|
@ -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.
|
@ -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;
|
||||
}
|
|
@ -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 */
|
||||
|
|
@ -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.
|
@ -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.
|
@ -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.
|
@ -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.
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
||||
|
|
@ -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.
|
@ -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.
|
@ -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
Loading…
Reference in New Issue