guacamole-server-1.3.0/0000755000175100001440000000000013772471154011765 500000000000000guacamole-server-1.3.0/bin/0000755000175100001440000000000013772471154012535 500000000000000guacamole-server-1.3.0/bin/guacctl0000755000175100001440000001652513770536336014040 00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # guacctl # ------- # # Utility for sending Guacamole-specific console codes for controlling a # terminal session, such as: # # * Downloading files (SSH only) # * Setting the destination directory for uploads (SSH only) # * Redirecting output to a named pipe stream (SSH or telnet) # # This script may also be run as "guacget", in which case the script accepts # no options and assumes anything given on the commandline is a file to be # downloaded. # ## ## Given the name of a file, which may be a relative path, produce the full, ## real, non-relative path for that same file. ## ## @param FILENAME ## The name of the file to produce the full path of. ## fullpath() { FILENAME="$1" DIR=`dirname "$FILENAME"` FILE=`basename "$FILENAME"` (cd "$DIR" && echo "$PWD/$FILE") } ## ## Sends the Guacamole-specific console code for initiating a download. ## ## @param FILENAME ## The full path of the file to download. ## send_download_file() { FILENAME="$1" printf "\033]482200;%s\007" "$FILENAME" } ## ## Sends the Guacamole-specific console code for setting the upload directory. ## ## @param FILENAME ## The full path to the directory which should receive uploads. ## send_set_directory() { FILENAME="$1" printf "\033]482201;%s\007" "$FILENAME" } ## ## Sends the Guacamole-specific console code for redirecting output to a named ## pipe stream (instead of the terminal emulator) ## ## @param NAME ## The name of the pipe stream to open. ## send_open_pipe_stream() { NAME="$1" printf "\033]482202;%s\007" "$NAME" } ## ## Sends the Guacamole-specific console code for redirecting output back to the ## terminal emulator ## send_close_pipe_stream() { printf "\033]482203;\007" } ## ## Sends the Guacamole-specific console code for resizing the scrollback ## buffer. ## ## @param ROWS ## The number of rows that the scrollback buffer should contain. ## send_resize_scrollback() { ROWS="$1" printf "\033]482204;%s\007" "$ROWS" } ## ## Prints the given error text to STDERR. ## ## @param ... ## The text to print as an error message. ## error() { echo "$NAME:" "$@" >&2 } ## ## Prints usage documentation for this script. ## usage() { cat >&2 <])]) # libpng AC_CHECK_LIB([png], [png_write_png], [PNG_LIBS=-lpng], AC_MSG_ERROR("libpng is required for writing png messages")) # libjpeg AC_CHECK_LIB([jpeg], [jpeg_start_compress], [JPEG_LIBS=-ljpeg], AC_MSG_ERROR("libjpeg is required for writing jpeg messages")) # Cairo AC_CHECK_LIB([cairo], [cairo_create], [CAIRO_LIBS=-lcairo], AC_MSG_ERROR("Cairo is required for drawing instructions")) # libpthread AC_CHECK_LIB([pthread], [pthread_create], [PTHREAD_LIBS=-lpthread AC_DEFINE([HAVE_LIBPTHREAD],, [Whether libpthread was found])]) # Include libdl for dlopen() if necessary AC_CHECK_LIB([dl], [dlopen], [DL_LIBS=-ldl], [AC_CHECK_DECL([dlopen],, AC_MSG_ERROR("libdl is required on systems which do not otherwise provide dlopen()"), [#include ])]) # OSSP UUID AC_CHECK_LIB([ossp-uuid], [uuid_make], [UUID_LIBS=-lossp-uuid], AC_CHECK_LIB([uuid], [uuid_make], [UUID_LIBS=-luuid], AC_MSG_ERROR("The OSSP UUID library is required"))) # Check for and validate OSSP uuid.h header AC_CHECK_HEADERS([ossp/uuid.h]) AC_CHECK_DECL([uuid_make],, AC_MSG_ERROR("No OSSP uuid.h found in include path"), [#ifdef HAVE_OSSP_UUID_H #include #else #include #endif ]) # cunit AC_CHECK_LIB([cunit], [CU_run_test], [CUNIT_LIBS=-lcunit]) AC_SUBST(DL_LIBS) AC_SUBST(MATH_LIBS) AC_SUBST(PNG_LIBS) AC_SUBST(JPEG_LIBS) AC_SUBST(CAIRO_LIBS) AC_SUBST(PTHREAD_LIBS) AC_SUBST(UUID_LIBS) AC_SUBST(CUNIT_LIBS) # Library functions AC_CHECK_FUNCS([clock_gettime gettimeofday memmove memset select strdup nanosleep]) AC_CHECK_DECL([png_get_io_ptr], [AC_DEFINE([HAVE_PNG_GET_IO_PTR],, [Whether png_get_io_ptr() is defined])],, [#include ]) AC_CHECK_DECL([cairo_format_stride_for_width], [AC_DEFINE([HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH],, [Whether cairo_format_stride_for_width() is defined])],, [#include ]) AC_CHECK_DECL([poll], [AC_DEFINE([HAVE_POLL],, [Whether poll() is defined])],, [#include ]) AC_CHECK_DECL([strlcpy], [AC_DEFINE([HAVE_STRLCPY],, [Whether strlcpy() is defined])],, [#include ]) AC_CHECK_DECL([strlcat], [AC_DEFINE([HAVE_STRLCAT],, [Whether strlcat() is defined])],, [#include ]) # Typedefs AC_TYPE_SIZE_T AC_TYPE_SSIZE_T # Bundled libguac AC_SUBST([LIBGUAC_LTLIB], '$(top_builddir)/src/libguac/libguac.la') AC_SUBST([LIBGUAC_INCLUDE], '-I$(top_srcdir)/src/libguac') # Common non-libguac utility library AC_SUBST([COMMON_LTLIB], '$(top_builddir)/src/common/libguac_common.la') AC_SUBST([COMMON_INCLUDE], '-I$(top_srcdir)/src/common') # Common PulseAudio utility library AC_SUBST([PULSE_LTLIB], '$(top_builddir)/src/pulse/libguac_pulse.la') AC_SUBST([PULSE_INCLUDE], '-I$(top_srcdir)/src/pulse') # Common base SSH client AC_SUBST([COMMON_SSH_LTLIB], '$(top_builddir)/src/common-ssh/libguac_common_ssh.la') AC_SUBST([COMMON_SSH_INCLUDE], '-I$(top_srcdir)/src/common-ssh') # RDP support AC_SUBST([LIBGUAC_CLIENT_RDP_LTLIB], '$(top_builddir)/src/protocols/rdp/libguac-client-rdp.la') AC_SUBST([LIBGUAC_CLIENT_RDP_INCLUDE], '-I$(top_srcdir)/src/protocols/rdp') # Terminal emulator AC_SUBST([TERMINAL_LTLIB], '$(top_builddir)/src/terminal/libguac_terminal.la') AC_SUBST([TERMINAL_INCLUDE], '-I$(top_srcdir)/src/terminal $(PANGO_CFLAGS) $(PANGOCAIRO_CFLAGS) $(COMMON_INCLUDE)') # Init directory AC_ARG_WITH(init_dir, [AS_HELP_STRING([--with-init-dir=], [install init scripts to the given directory]) ],init_dir=$withval) AM_CONDITIONAL([ENABLE_INIT], [test "x${init_dir}" != "x"]) AC_SUBST(init_dir) # Systemd directory AC_ARG_WITH(systemd_dir, [AS_HELP_STRING([--with-systemd-dir=], [install systemd units to the given directory]) ],systemd_dir=$withval) AM_CONDITIONAL([ENABLE_SYSTEMD], [test "x${systemd_dir}" != "x"]) AC_SUBST(systemd_dir) # guacd config file AC_ARG_WITH(guacd_conf, [AS_HELP_STRING([--with-guacd-conf=], [the full path to the guacd config file @<:@default=/etc/guacamole/guacd.conf@:>@])], [guacd_conf=$withval], [guacd_conf=/etc/guacamole/guacd.conf]) AC_DEFINE_UNQUOTED([GUACD_CONF_FILE], ["$guacd_conf"], [The full path to the guacd config file]) # # libavcodec # have_libavcodec=disabled AC_ARG_WITH([libavcodec], [AS_HELP_STRING([--with-libavcodec], [use libavcodec when encoding video @<:@default=check@:>@])], [], [with_libavcodec=check]) if test "x$with_libavcodec" != "xno" then have_libavcodec=yes PKG_CHECK_MODULES([AVCODEC], [libavcodec],, [have_libavcodec=no]); fi AM_CONDITIONAL([ENABLE_AVCODEC], [test "x${have_libavcodec}" = "xyes"]) # # libavformat # have_libavformat=disabled AC_ARG_WITH([libavformat], [AS_HELP_STRING([--with-libavformat], [use libavformat when encoding video @<:@default=check@:>@])], []. [with_libavformat=check]) if test "x$with_libavformat" != "xno" then have_libavformat=yes PKG_CHECK_MODULES([AVFORMAT], [libavformat],, [have_libavformat=no]); fi AM_CONDITIONAL([ENABLE_AVFORMAT], [test "x${have_libavformat}" = "xyes"]) # # libavutil # have_libavutil=disabled AC_ARG_WITH([libavutil], [AS_HELP_STRING([--with-libavutil], [use libavutil when encoding video @<:@default=check@:>@])], [], [with_libavutil=check]) if test "x$with_libavutil" != "xno" then have_libavutil=yes PKG_CHECK_MODULES([AVUTIL], [libavutil],, [have_libavutil=no]); fi AM_CONDITIONAL([ENABLE_AVUTIL], [test "x${have_libavutil}" = "xyes"]) # # libswscale # have_libswscale=disabled AC_ARG_WITH([libswscale], [AS_HELP_STRING([--with-libswscale], [use libswscale when encoding video @<:@default=check@:>@])], [], [with_libswscale=check]) if test "x$with_libswscale" != "xno" then have_libswscale=yes PKG_CHECK_MODULES([SWSCALE], [libswscale],, [have_libswscale=no]); fi AM_CONDITIONAL([ENABLE_SWSCALE], [test "x${have_libswscale}" = "xyes"]) # # libssl # have_ssl=disabled SSL_LIBS= AC_ARG_WITH([ssl], [AS_HELP_STRING([--with-ssl], [support SSL encryption @<:@default=check@:>@])], [], [with_ssl=check]) if test "x$with_ssl" != "xno" then have_ssl=yes AC_CHECK_HEADER(openssl/ssl.h,, [have_ssl=no]) AC_CHECK_LIB([ssl], [SSL_CTX_new], [SSL_LIBS="$SSL_LIBS -lssl -lcrypto"], [have_ssl=no]) if test "x${have_ssl}" = "xno" then AC_MSG_WARN([ -------------------------------------------- Unable to find libssl. guacd will not support SSL connections. --------------------------------------------]) else AC_DEFINE([ENABLE_SSL],, [Whether SSL-related support is enabled]) # OpenSSL 1.1 accessor function for DSA signature values AC_CHECK_DECL([DSA_SIG_get0], [AC_DEFINE([HAVE_DSA_SIG_GET0],, [Whether libssl provides DSA_SIG_get0()])],, [#include ]) # OpenSSL 1.1 accessor function for DSA public key parameters AC_CHECK_DECL([DSA_get0_pqg], [AC_DEFINE([HAVE_DSA_GET0_PQG],, [Whether libssl provides DSA_get0_pqg()])],, [#include ]) # OpenSSL 1.1 accessor function for DSA public/private key values AC_CHECK_DECL([DSA_get0_key], [AC_DEFINE([HAVE_DSA_GET0_KEY],, [Whether libssl provides DSA_get0_key()])],, [#include ]) # OpenSSL 1.1 accessor function for RSA public/private key values AC_CHECK_DECL([RSA_get0_key], [AC_DEFINE([HAVE_RSA_GET0_KEY],, [Whether libssl provides RSA_get0_key()])],, [#include ]) # OpenSSL 1.1 does away with explicit threading callbacks AC_MSG_CHECKING([whether libssl requires threading callbacks]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ #include #if OPENSSL_VERSION_NUMBER < 0x10100000L #error Threading callbacks required. #endif int main() { return 0; } ]])], [AC_MSG_RESULT([no])], [AC_MSG_RESULT([yes]) AC_DEFINE([OPENSSL_REQUIRES_THREADING_CALLBACKS],, [Whether OpenSSL requires explicit threading callbacks for threadsafety])]) fi fi AM_CONDITIONAL([ENABLE_SSL], [test "x${have_ssl}" = "xyes"]) AC_SUBST(SSL_LIBS) # # Winsock # have_winsock=disabled WINSOCK_LIBS= AC_ARG_WITH([winsock], [AS_HELP_STRING([--with-winsock], [support Windows Sockets API @<:@default=check@:>@])], [], [with_winsock=check]) if test "x$with_winsock" != "xno" then have_winsock=yes AC_CHECK_LIB([wsock32], [main], [WINSOCK_LIBS="-lwsock32"] [AC_DEFINE([ENABLE_WINSOCK],, [Whether Windows Socket API support is enabled])], [have_winsock=no]) fi AM_CONDITIONAL([ENABLE_WINSOCK], [test "x${have_winsock}" = "xyes"]) AC_SUBST(WINSOCK_LIBS) # # Ogg Vorbis # have_vorbis=disabled VORBIS_LIBS= AC_ARG_WITH([vorbis], [AS_HELP_STRING([--with-vorbis], [support Ogg Vorbis @<:@default=check@:>@])], [], [with_vorbis=check]) if test "x$with_vorbis" != "xno" then have_vorbis=yes AC_CHECK_HEADER(vorbis/vorbisenc.h,, [have_vorbis=no]) AC_CHECK_LIB([ogg], [ogg_stream_init], [VORBIS_LIBS="$VORBIS_LIBS -logg"], [have_vorbis=no]) AC_CHECK_LIB([vorbis], [vorbis_block_init], [VORBIS_LIBS="$VORBIS_LIBS -lvorbis"], [have_vorbis=no]) AC_CHECK_LIB([vorbisenc], [vorbis_encode_init], [VORBIS_LIBS="$VORBIS_LIBS -lvorbisenc"], [have_vorbis=no]) if test "x${have_vorbis}" = "xno" then AC_MSG_WARN([ -------------------------------------------- Unable to find libogg / libvorbis / libvorbisenc. Sound will not be encoded with Ogg Vorbis. --------------------------------------------]) else AC_DEFINE([ENABLE_OGG],, [Whether support for Ogg Vorbis is enabled]) fi fi AM_CONDITIONAL([ENABLE_OGG], [test "x${have_vorbis}" = "xyes"]) AC_SUBST(VORBIS_LIBS) # # PulseAudio # have_pulse=disabled PULSE_LIBS= AC_ARG_WITH([pulse], [AS_HELP_STRING([--with-pulse], [support PulseAudio @<:@default=check@:>@])], [], [with_pulse=check]) if test "x$with_pulse" != "xno" then have_pulse=yes AC_CHECK_LIB([pulse], [pa_context_new], [PULSE_LIBS="$PULSE_LIBS -lpulse"], [have_pulse=no]) if test "x${have_pulse}" = "xno" then AC_MSG_WARN([ -------------------------------------------- Unable to find libpulse Sound support for VNC will be disabled --------------------------------------------]) else AC_DEFINE([ENABLE_PULSE],, [Whether PulseAudio support is enabled]) fi fi AM_CONDITIONAL([ENABLE_PULSE], [test "x${have_pulse}" = "xyes"]) AC_SUBST(PULSE_LIBS) # # PANGO # have_pango=disabled AC_ARG_WITH([pango], [AS_HELP_STRING([--with-pango], [support Pango text layout @<:@default=check@:>@])], [], [with_pango=check]) if test "x$with_pango" != "xno" then have_pango=yes PKG_CHECK_MODULES([PANGO], [pango],, [have_pango=no]); PKG_CHECK_MODULES([PANGOCAIRO], [pangocairo],, [have_pango=no]); fi # # Terminal emulator # have_terminal=disabled AC_ARG_WITH([terminal], [AS_HELP_STRING([--with-terminal], [support text-based protocols @<:@default=check@:>@])], [], [with_terminal=check]) if test "x$with_terminal" != "xno" then have_terminal=yes if test "x${have_pango}" != "xyes" then have_terminal=no fi fi AM_CONDITIONAL([ENABLE_TERMINAL], [test "x${have_terminal}" = "xyes"]) # # libVNCServer # have_libvncserver=disabled VNC_LIBS= AC_ARG_WITH([vnc], [AS_HELP_STRING([--with-vnc], [support VNC @<:@default=check@:>@])], [], [with_vnc=check]) if test "x$with_vnc" != "xno" then have_libvncserver=yes AC_CHECK_LIB([vncclient], [rfbInitClient], [VNC_LIBS="$VNC_LIBS -lvncclient"], [have_libvncserver=no]) fi AM_CONDITIONAL([ENABLE_VNC], [test "x${have_libvncserver}" = "xyes"]) AC_SUBST(VNC_LIBS) # # Repeater support within libVNCServer # if test "x${have_libvncserver}" = "xyes" then have_vnc_repeater=yes AC_CHECK_MEMBERS([rfbClient.destHost, rfbClient.destPort], [], [have_vnc_repeater=no], [[#include ]]) if test "x${have_vnc_repeater}" = "xno" then AC_MSG_WARN([ -------------------------------------------- No repeater support found in libvncclient. Support for VNC repeaters will not be built. --------------------------------------------]) else AC_DEFINE([ENABLE_VNC_REPEATER],, [Whether support for VNC repeaters is enabled.]) fi fi # # Listening support within libVNCServer # if test "x${have_libvncserver}" = "xyes" then have_vnc_listen=yes AC_CHECK_DECL([listenForIncomingConnectionsNoFork], [], [have_vnc_listen=no], [[#include ]]) if test "x${have_vnc_listen}" = "xno" then AC_MSG_WARN([ -------------------------------------------- No listening support found in libvncclient. Support for listen-mode connections will not be built. --------------------------------------------]) else AC_DEFINE([ENABLE_VNC_LISTEN],, [Whether support for listen-mode VNC connections is enabled.]) fi fi # # TLS Locking Support within libVNCServer # if test "x${have_libvncserver}" = "xyes" then have_vnc_tls_locking=yes AC_CHECK_MEMBERS([rfbClient.LockWriteToTLS, rfbClient.UnlockWriteToTLS], [], [have_vnc_tls_locking=no], [[#include ]]) if test "x${have_vnc_tls_locking}" = "xno" then AC_MSG_WARN([ -------------------------------------------- This version of libvncclient lacks support for TLS locking. VNC connections that use TLS may experience instability as documented in GUACAMOLE-414]) else AC_DEFINE([ENABLE_VNC_TLS_LOCKING],, [Whether support for TLS locking within VNC is enabled.]) fi fi # # FreeRDP 2 (libfreerdp2, libfreerdp-client2, and libwinpr2) # have_freerdp2=disabled FREERDP2_PLUGIN_DIR= AC_ARG_WITH([rdp], [AS_HELP_STRING([--with-rdp], [support RDP @<:@default=check@:>@])], [], [with_rdp=check]) # FreeRDP plugin directory AC_ARG_WITH(freerdp_plugin_dir, [AS_HELP_STRING([--with-freerdp-plugin-dir=], [install FreeRDP plugins to the given directory @<:@default=check@:>@]) ],FREERDP2_PLUGIN_DIR=$withval) # Preserve CPPFLAGS so it can be restored later, following the addition of # options specific to FreeRDP tests OLDCPPFLAGS="$CPPFLAGS" if test "x$with_rdp" != "xno" then have_freerdp2=yes PKG_CHECK_MODULES([RDP], [freerdp2 freerdp-client2 winpr2], [CPPFLAGS="${RDP_CFLAGS} -Werror $CPPFLAGS"] [AS_IF([test "x${FREERDP2_PLUGIN_DIR}" = "x"], [FREERDP2_PLUGIN_DIR="`$PKG_CONFIG --variable=libdir freerdp2`/freerdp2"])], [AC_MSG_WARN([ -------------------------------------------- Unable to find FreeRDP (libfreerdp2 / libfreerdp-client2 / libwinpr2) RDP will be disabled. --------------------------------------------]) have_freerdp2=no]) fi # Available color conversion functions if test "x$have_freerdp2" = "xyes" then # FreeRDP 2.0.0-rc3 and older referred to FreeRDPConvertColor() as # ConvertColor() AC_CHECK_DECL([FreeRDPConvertColor], [AC_DEFINE([HAVE_FREERDPCONVERTCOLOR],, [Whether FreeRDPConvertColor() is defined])],, [#include ]) fi # It is difficult or impossible to test for variations in FreeRDP behavior in # between releases, as the change in behavior may not (yet) be associated with # a corresponding change in version number and may not have any detectable # effect on the FreeRDP API AC_ARG_ENABLE(allow_freerdp_snapshots, [AS_HELP_STRING([--enable-allow-freerdp-snapshots], [allow building against unknown development snapshots of FreeRDP]) ],allow_freerdp_snapshots=yes) if test "x${have_freerdp2}" = "xyes" -a "x${allow_freerdp_snapshots}" != "xyes" then AC_MSG_CHECKING([whether FreeRDP appears to be a development version]) AC_EGREP_CPP([\"[0-9]+\\.[0-9]+\\.[0-9]+(-rc[0-9]+)?\"], [ #include FREERDP_VERSION_FULL ], [AC_MSG_RESULT([no])], [AC_MSG_RESULT([yes])] [AC_MSG_ERROR([ -------------------------------------------- You are building against a development version of FreeRDP. Non-release versions of FreeRDP may have differences in behavior that are impossible to check for at build time. This may result in memory leaks or other strange behavior. *** PLEASE USE A RELEASED VERSION OF FREERDP IF POSSIBLE *** If you are ABSOLUTELY CERTAIN that building against this version of FreeRDP is OK, rerun configure with the --enable-allow-freerdp-snapshots --------------------------------------------])]) fi # Variation in memory internal allocation/free behavior for bitmaps if test "x${have_freerdp2}" = "xyes" then # FreeRDP 2.0.0-rc0 and older automatically free rdpBitmap and its # associated data member within Bitmap_Free(), relying on the # implementation-specific free handler to free only implementation-specific # data. This changed in commit 2cf10cc, and implementations must now # manually free all data associated with the rdpBitmap, even data which # was not allocated by the implementation. AC_MSG_CHECKING([whether Bitmap_Free() frees the rdpBitmap and its image data]) AC_EGREP_CPP([\"2\\.0\\.0-dev\"], [ #include FREERDP_VERSION_FULL ], [AC_MSG_RESULT([yes])] [AC_DEFINE([FREERDP_BITMAP_FREE_FREES_BITMAP],, [Whether Bitmap_Free() frees the rdpBitmap and its image data])], [AC_MSG_RESULT([no])]) fi # Variation in memory internal allocation/free behavior for channel streams if test "x${have_freerdp2}" = "xyes" then # FreeRDP 2.0.0-rc3 through 2.0.0-rc4 automatically free the wStream # provided to pVirtualChannelWriteEx(). This changed in commit 1b78b59, and # implementations must manually free the wStream after it is no longer # needed (after the write is complete or cancelled). AC_MSG_CHECKING([whether pVirtualChannelWriteEx() frees the wStream upon completion]) AC_EGREP_CPP([\"2\\.0\\.0-(rc|dev)[3-4]\"], [ #include FREERDP_VERSION_FULL ], [AC_MSG_RESULT([yes])] [AC_DEFINE([FREERDP_SVC_CORE_FREES_WSTREAM],, [Whether pVirtualChannelWriteEx() frees the wStream upon completion])], [AC_MSG_RESULT([no])]) fi # Glyph callback variants if test "x${have_freerdp2}" = "xyes" then # FreeRDP 2.0.0-rc3 and older used UINT32 for integer parameters to all # rdpGlyph callbacks AC_MSG_CHECKING([whether rdpGlyph callbacks accept INT32 integer parameters]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ #include #include #include BOOL test_begindraw(rdpContext* context, INT32 x, INT32 y, INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor, BOOL redundant); rdpGlyph glyph = { .BeginDraw = test_begindraw }; int main() { return (int) glyph.BeginDraw(NULL, 0, 0, 0, 0, 0, 0, FALSE); } ]])], [AC_MSG_RESULT([yes])] [AC_DEFINE([FREERDP_GLYPH_CALLBACKS_ACCEPT_INT32],, [Whether rdpGlyph callbacks accept INT32 integer parameters])], [AC_MSG_RESULT([no])]) fi # CLIPRDR callback variants if test "x${have_freerdp2}" = "xyes" then # FreeRDP 2.0.0-rc3 and older did not use const for CLIPRDR callbacks AC_MSG_CHECKING([whether CLIPRDR callbacks require const for their final parameter]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ #include #include UINT test_monitor_ready(CliprdrClientContext* cliprdr, const CLIPRDR_MONITOR_READY* monitor_ready); CliprdrClientContext context = { .MonitorReady = test_monitor_ready }; int main() { return (int) context.MonitorReady(NULL, NULL); } ]])], [AC_MSG_RESULT([yes])] [AC_DEFINE([FREERDP_CLIPRDR_CALLBACKS_REQUIRE_CONST],, [Whether CLIPRDR callbacks require const for the final parameter])], [AC_MSG_RESULT([no])]) fi # RAIL callback variants if test "x${have_freerdp2}" = "xyes" then # FreeRDP 2.0.0-rc3 and older did not use const for RAIL callbacks AC_MSG_CHECKING([whether RAIL callbacks require const for their final parameter]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ #include #include UINT test_server_handshake(RailClientContext* rail, const RAIL_HANDSHAKE_ORDER* handshake); RailClientContext context = { .ServerHandshake = test_server_handshake }; int main() { return (int) context.ServerHandshake(NULL, NULL); } ]])], [AC_MSG_RESULT([yes])] [AC_DEFINE([FREERDP_RAIL_CALLBACKS_REQUIRE_CONST],, [Whether RAIL callbacks require const for the final parameter])], [AC_MSG_RESULT([no])]) fi # Support for receiving unannounced orders from the RDP server if test "x${have_freerdp2}" = "xyes" then AC_CHECK_MEMBERS([rdpSettings.AllowUnanouncedOrdersFromServer],, [AC_MSG_WARN([ -------------------------------------------- This version of FreeRDP does not support relaxed order checks. RDP servers that send orders that the client did not announce as supported (such as the VirtualBox RDP server) will likely not be usable. See: https://issues.apache.org/jira/browse/GUACAMOLE-962 --------------------------------------------])], [[#include ]]) fi # Restore CPPFLAGS, removing FreeRDP-specific options needed for testing CPPFLAGS="$OLDCPPFLAGS" AC_SUBST(FREERDP2_PLUGIN_DIR) AM_CONDITIONAL([ENABLE_RDP], [test "x${have_freerdp2}" = "xyes"]) # # libssh2 # have_libssh2=disabled SSH_LIBS= AC_ARG_WITH([ssh], [AS_HELP_STRING([--with-ssh], [support SSH @<:@default=check@:>@])], [], [with_ssh=check]) AC_ARG_ENABLE(ssh_agent, [AS_HELP_STRING([--enable-ssh-agent], [enable built-in ssh-agent]) ],enable_ssh_agent=yes) if test "x$with_ssh" != "xno" then have_libssh2=yes AC_CHECK_LIB([ssh2], [libssh2_session_init_ex], [SSH_LIBS="$SSH_LIBS -lssh2"], [have_libssh2=no]) fi AM_CONDITIONAL([ENABLE_COMMON_SSH], [test "x${have_libssh2}" = "xyes" \ -a "x${have_ssl}" = "xyes"]) AM_COND_IF([ENABLE_COMMON_SSH], [AC_DEFINE([ENABLE_COMMON_SSH],, [Whether support for the common SSH core is enabled])]) AM_CONDITIONAL([ENABLE_SSH], [test "x${have_libssh2}" = "xyes" \ -a "x${have_terminal}" = "xyes" \ -a "x${have_ssl}" = "xyes"]) AC_SUBST(SSH_LIBS) # # Underlying crypto library usage of libssh2 # if test "x${have_libssh2}" = "xyes" then # Whether libssh2 was built against libgcrypt AC_CHECK_LIB([ssh2], [gcry_control], [AC_CHECK_HEADER(gcrypt.h, [AC_DEFINE([LIBSSH2_USES_GCRYPT],, [Whether libssh2 was built against libgcrypt])], [AC_MSG_WARN([ -------------------------------------------- libssh2 appears to be built against libgcrypt, but the libgcrypt headers could not be found. SSH will be disabled. --------------------------------------------]) have_libssh2=no])]) fi # # Agent forwarding support within libssh2 # have_ssh_agent=no if test "x${have_libssh2}" = "xyes" -a "x${enable_ssh_agent}" = "xyes" then AC_CHECK_DECL([libssh2_channel_request_auth_agent], [have_ssh_agent=yes], [], [[#include ]]) if test "x${have_ssh_agent}" = "xno" then AC_MSG_ERROR([ -------------------------------------------- Agent forwarding support was requested but no such support was found in libssh2. --------------------------------------------]) else AC_DEFINE([ENABLE_SSH_AGENT],, [Whether agent forwarding support for SSH is enabled]) fi fi AM_CONDITIONAL([ENABLE_SSH_AGENT], [test "x${have_ssh_agent}" = "xyes" \ -a "x${enable_ssh_agent}" = "xyes"]) # # libtelnet # have_libtelnet=disabled TELNET_LIBS= AC_ARG_WITH([telnet], [AS_HELP_STRING([--with-telnet], [support Telnet @<:@default=check@:>@])], [], [with_telnet=check]) if test "x$with_telnet" != "xno" then have_libtelnet=yes AC_CHECK_LIB([telnet], [telnet_init], [TELNET_LIBS="$TELNET_LIBS -ltelnet"], [have_libtelnet=no]) fi AM_CONDITIONAL([ENABLE_TELNET], [test "x${have_libtelnet}" = "xyes" \ -a "x${have_terminal}" = "xyes"]) AC_SUBST(TELNET_LIBS) # # libwebp # have_webp=disabled WEBP_LIBS= AC_ARG_WITH([webp], [AS_HELP_STRING([--with-webp], [support WebP image encoding @<:@default=check@:>@])], [], [with_webp=check]) if test "x$with_webp" != "xno" then have_webp=yes AC_CHECK_HEADER(webp/encode.h,, [have_webp=no]) AC_CHECK_LIB([webp], [WebPEncode], [WEBP_LIBS="$WEBP_LIBS -lwebp"], [have_webp=no]) if test "x${have_webp}" = "xno" then AC_MSG_WARN([ -------------------------------------------- Unable to find libwebp. Images will not be encoded using WebP. --------------------------------------------]) else AC_DEFINE([ENABLE_WEBP],, [Whether WebP support is enabled]) fi fi AM_CONDITIONAL([ENABLE_WEBP], [test "x${have_webp}" = "xyes"]) AC_SUBST(WEBP_LIBS) # # libwebsockets # have_libwebsockets=disabled WEBSOCKETS_LIBS= AC_ARG_WITH([websockets], [AS_HELP_STRING([--with-websockets], [support WebSockets @<:@default=check@:>@])], [], [with_websockets=check]) if test "x$with_websockets" != "xno" then have_libwebsockets=yes AC_CHECK_LIB([websockets], [lws_create_context], [WEBSOCKETS_LIBS="$WEBSOCKETS_LIBS -lwebsockets"], [AC_MSG_WARN([ -------------------------------------------- Unable to find libwebsockets. Support for Kubernetes will be disabled. --------------------------------------------]) have_libwebsockets=no]) fi if test "x$with_websockets" != "xno" then # Check for client-specific closed event, which must be used in favor of # the generic closed event if libwebsockets is recent enough to provide # this AC_CHECK_DECL([LWS_CALLBACK_CLIENT_CLOSED], [AC_DEFINE([HAVE_LWS_CALLBACK_CLIENT_CLOSED],, [Whether LWS_CALLBACK_CLIENT_CLOSED is defined])],, [#include ]) # Older versions of libwebsockets may not define a flag for requesting # global initialization of OpenSSL, instead performing that initialization # by default AC_CHECK_DECL([LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT], [AC_DEFINE([HAVE_LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT],, [Whether LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT is defined])],, [#include ]) # Older versions of libwebsockets do not define special macros for SSL # connection flags, instead relying on documented integer values AC_CHECK_DECL([LCCSCF_USE_SSL], [AC_DEFINE([HAVE_LCCSCF_USE_SSL],, [Whether LCCSCF_USE_SSL is defined])],, [#include ]) # Older versions of libwebsockets do not define a dummy callback which # must be invoked after the main event callback is invoked; the main event # callback must instead manually return zero AC_CHECK_DECL([lws_callback_http_dummy], [AC_DEFINE([HAVE_LWS_CALLBACK_HTTP_DUMMY],, [Whether lws_callback_http_dummy() is defined])],, [#include ]) fi AM_CONDITIONAL([ENABLE_WEBSOCKETS], [test "x${have_libwebsockets}" = "xyes"]) AC_SUBST(WEBSOCKETS_LIBS) # # Kubernetes # AC_ARG_ENABLE([kubernetes], [AS_HELP_STRING([--disable-kubernetes], [do not build support for attaching to Kubernetes pods])], [], [enable_kubernetes=yes]) AM_CONDITIONAL([ENABLE_KUBERNETES], [test "x${enable_kubernetes}" = "xyes" \ -a "x${have_libwebsockets}" = "xyes" \ -a "x${have_ssl}" = "xyes" \ -a "x${have_terminal}" = "xyes"]) # # guacd # AC_ARG_ENABLE([guacd], [AS_HELP_STRING([--disable-guacd], [do not build the Guacamole proxy daemon])], [], [enable_guacd=yes]) AM_CONDITIONAL([ENABLE_GUACD], [test "x${enable_guacd}" = "xyes"]) # # guacenc # AC_ARG_ENABLE([guacenc], [AS_HELP_STRING([--disable-guacenc], [do not build the Guacamole video encoding tool])], [], [enable_guacenc=yes]) AM_CONDITIONAL([ENABLE_GUACENC], [test "x${enable_guacenc}" = "xyes" \ -a "x${have_libavcodec}" = "xyes" \ -a "x${have_libavutil}" = "xyes" \ -a "x${have_libswscale}" = "xyes" \ -a "x${have_libavformat}" = "xyes"]) # # guaclog # AC_ARG_ENABLE([guaclog], [AS_HELP_STRING([--disable-guaclog], [do not build the Guacamole input logging tool])], [], [enable_guaclog=yes]) AM_CONDITIONAL([ENABLE_GUACLOG], [test "x${enable_guaclog}" = "xyes"]) # # Output Makefiles # AC_CONFIG_FILES([Makefile doc/Doxyfile src/common/Makefile src/common/tests/Makefile src/common-ssh/Makefile src/common-ssh/tests/Makefile src/terminal/Makefile src/libguac/Makefile src/libguac/tests/Makefile src/guacd/Makefile src/guacd/man/guacd.8 src/guacd/man/guacd.conf.5 src/guacenc/Makefile src/guacenc/man/guacenc.1 src/guaclog/Makefile src/guaclog/man/guaclog.1 src/pulse/Makefile src/protocols/kubernetes/Makefile src/protocols/rdp/Makefile src/protocols/rdp/tests/Makefile src/protocols/ssh/Makefile src/protocols/telnet/Makefile src/protocols/vnc/Makefile]) AC_OUTPUT # # Protocol build status # AM_COND_IF([ENABLE_KUBERNETES], [build_kubernetes=yes], [build_kubernetes=no]) AM_COND_IF([ENABLE_RDP], [build_rdp=yes], [build_rdp=no]) AM_COND_IF([ENABLE_SSH], [build_ssh=yes], [build_ssh=no]) AM_COND_IF([ENABLE_TELNET], [build_telnet=yes], [build_telnet=no]) AM_COND_IF([ENABLE_VNC], [build_vnc=yes], [build_vnc=no]) # # Service / tool build status # AM_COND_IF([ENABLE_GUACD], [build_guacd=yes], [build_guacd=no]) AM_COND_IF([ENABLE_GUACENC], [build_guacenc=yes], [build_guacenc=no]) AM_COND_IF([ENABLE_GUACLOG], [build_guaclog=yes], [build_guaclog=no]) # # Init scripts # AM_COND_IF([ENABLE_INIT], [build_init="${init_dir}"], [build_init=no]) # # Systemd units # AM_COND_IF([ENABLE_SYSTEMD], [build_systemd="${systemd_dir}"], [build_systemd=no]) # # FreeRDP plugins # AM_COND_IF([ENABLE_RDP], [build_rdp_plugins="${FREERDP2_PLUGIN_DIR}"], [build_rdp_plugins=no]) # # Display summary # echo " ------------------------------------------------ $PACKAGE_NAME version $PACKAGE_VERSION ------------------------------------------------ Library status: freerdp2 ............ ${have_freerdp2} pango ............... ${have_pango} libavcodec .......... ${have_libavcodec} libavformat.......... ${have_libavformat} libavutil ........... ${have_libavutil} libssh2 ............. ${have_libssh2} libssl .............. ${have_ssl} libswscale .......... ${have_libswscale} libtelnet ........... ${have_libtelnet} libVNCServer ........ ${have_libvncserver} libvorbis ........... ${have_vorbis} libpulse ............ ${have_pulse} libwebsockets ....... ${have_libwebsockets} libwebp ............. ${have_webp} wsock32 ............. ${have_winsock} Protocol support: Kubernetes .... ${build_kubernetes} RDP ........... ${build_rdp} SSH ........... ${build_ssh} Telnet ........ ${build_telnet} VNC ........... ${build_vnc} Services / tools: guacd ...... ${build_guacd} guacenc .... ${build_guacenc} guaclog .... ${build_guaclog} FreeRDP plugins: ${build_rdp_plugins} Init scripts: ${build_init} Systemd units: ${build_systemd} Type \"make\" to compile $PACKAGE_NAME. " guacamole-server-1.3.0/config.h.in0000644000175100001440000001430513772471100013722 00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* Whether support for the common SSH core is enabled */ #undef ENABLE_COMMON_SSH /* Whether support for Ogg Vorbis is enabled */ #undef ENABLE_OGG /* Whether PulseAudio support is enabled */ #undef ENABLE_PULSE /* Whether agent forwarding support for SSH is enabled */ #undef ENABLE_SSH_AGENT /* Whether SSL-related support is enabled */ #undef ENABLE_SSL /* Whether support for listen-mode VNC connections is enabled. */ #undef ENABLE_VNC_LISTEN /* Whether support for VNC repeaters is enabled. */ #undef ENABLE_VNC_REPEATER /* Whether support for TLS locking within VNC is enabled. */ #undef ENABLE_VNC_TLS_LOCKING /* Whether WebP support is enabled */ #undef ENABLE_WEBP /* Whether Windows Socket API support is enabled */ #undef ENABLE_WINSOCK /* Whether Bitmap_Free() frees the rdpBitmap and its image data */ #undef FREERDP_BITMAP_FREE_FREES_BITMAP /* Whether CLIPRDR callbacks require const for the final parameter */ #undef FREERDP_CLIPRDR_CALLBACKS_REQUIRE_CONST /* Whether rdpGlyph callbacks accept INT32 integer parameters */ #undef FREERDP_GLYPH_CALLBACKS_ACCEPT_INT32 /* Whether RAIL callbacks require const for the final parameter */ #undef FREERDP_RAIL_CALLBACKS_REQUIRE_CONST /* Whether pVirtualChannelWriteEx() frees the wStream upon completion */ #undef FREERDP_SVC_CORE_FREES_WSTREAM /* The full path to the guacd config file */ #undef GUACD_CONF_FILE /* Define to 1 if you have the header file. */ #undef HAVE_CAIRO_CAIRO_H /* Whether cairo_format_stride_for_width() is defined */ #undef HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Whether libssl provides DSA_get0_key() */ #undef HAVE_DSA_GET0_KEY /* Whether libssl provides DSA_get0_pqg() */ #undef HAVE_DSA_GET0_PQG /* Whether libssl provides DSA_SIG_get0() */ #undef HAVE_DSA_SIG_GET0 /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Whether FreeRDPConvertColor() is defined */ #undef HAVE_FREERDPCONVERTCOLOR /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Whether LCCSCF_USE_SSL is defined */ #undef HAVE_LCCSCF_USE_SSL /* Whether libpthread was found */ #undef HAVE_LIBPTHREAD /* Whether LWS_CALLBACK_CLIENT_CLOSED is defined */ #undef HAVE_LWS_CALLBACK_CLIENT_CLOSED /* Whether lws_callback_http_dummy() is defined */ #undef HAVE_LWS_CALLBACK_HTTP_DUMMY /* Whether LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT is defined */ #undef HAVE_LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the `nanosleep' function. */ #undef HAVE_NANOSLEEP /* Define to 1 if you have the header file. */ #undef HAVE_OSSP_UUID_H /* Define to 1 if you have the header file. */ #undef HAVE_PNGSTRUCT_H /* Whether png_get_io_ptr() is defined */ #undef HAVE_PNG_GET_IO_PTR /* Whether poll() is defined */ #undef HAVE_POLL /* Define to 1 if `AllowUnanouncedOrdersFromServer' is a member of `rdpSettings'. */ #undef HAVE_RDPSETTINGS_ALLOWUNANOUNCEDORDERSFROMSERVER /* Define to 1 if `destHost' is a member of `rfbClient'. */ #undef HAVE_RFBCLIENT_DESTHOST /* Define to 1 if `destPort' is a member of `rfbClient'. */ #undef HAVE_RFBCLIENT_DESTPORT /* Define to 1 if `LockWriteToTLS' is a member of `rfbClient'. */ #undef HAVE_RFBCLIENT_LOCKWRITETOTLS /* Define to 1 if `UnlockWriteToTLS' is a member of `rfbClient'. */ #undef HAVE_RFBCLIENT_UNLOCKWRITETOTLS /* Whether libssl provides RSA_get0_key() */ #undef HAVE_RSA_GET0_KEY /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Whether strlcat() is defined */ #undef HAVE_STRLCAT /* Whether strlcpy() is defined */ #undef HAVE_STRLCPY /* Define to 1 if you have the header file. */ #undef HAVE_SYSLOG_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Whether libssh2 was built against libgcrypt */ #undef LIBSSH2_USES_GCRYPT /* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Whether OpenSSL requires explicit threading callbacks for threadsafety */ #undef OPENSSL_REQUIRES_THREADING_CALLBACKS /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* Uses X/Open and POSIX APIs */ #undef _XOPEN_SOURCE /* Uses BSD-specific APIs (if available) */ #undef __BSD_VISIBLE /* Define to `unsigned int' if does not define. */ #undef size_t /* Define to `int' if does not define. */ #undef ssize_t guacamole-server-1.3.0/util/0000755000175100001440000000000013772471154012742 500000000000000guacamole-server-1.3.0/util/generate-test-runner.pl0000755000175100001440000001252213764613616017304 00000000000000#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # generate-test-runner.pl # # Generates a test runner for the .c files given on the command line. Each .c # file may declare any number of tests so long as each test uses CUnit and is # declared with the following convention: # # void test_SUITENAME__TESTNAME() { # ... # } # # where TESTNAME is the arbitrary name of the test and SUITENAME is the # arbitrary name of the test suite that this test belongs to. # # Absolutely all tests MUST follow the above convention if they are to be # picked up by this script. Functions which are not tests MUST NOT follow # the above convention. # use strict; my $num_tests = 0; my %test_suites = (); # Parse all test declarations from given file while (<>) { if ((my $suite_name, my $test_name) = m/^void\s+test_(\w+)__(\w+)/) { $num_tests++; $test_suites{$suite_name} //= (); push @{$test_suites{$suite_name}}, $test_name; } } # Bail out if there's nothing to write if ($num_tests == 0) { die "No unit tests... :(\n"; } # # Common test runner header # print <<'END'; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include /** * The current test number, as required by the TAP format. This value is * automatically incremented by tap_log_test_completed() after each test is * run. */ int tap_test_number = 1; /** * Logs the status of a CUnit test which just completed. This implementation * logs test completion in TAP format. * * @param test * The CUnit test which just completed. * * @param suite * The CUnit test suite associated with the test. * * @param failure * The head element of the test failure list, or NULL if the test passed. */ static void tap_log_test_completed(const CU_pTest test, const CU_pSuite suite, const CU_pFailureRecord failure) { /* Log success/failure in TAP format */ if (failure == NULL) printf("ok %i - [%s] %s: OK\n", tap_test_number, suite->pName, test->pName); else printf("not ok %i - [%s] %s: Assertion failed on %s:%i: %s\n", tap_test_number, suite->pName, test->pName, failure->strFileName, failure->uiLineNumber, failure->strCondition); tap_test_number++; } END # # Prototypes for all test functions # while ((my $suite_name, my $test_names) = each (%test_suites)) { print "\n/* Automatically-generated prototypes for the $suite_name suite */\n"; foreach my $test_name (@{ $test_names }) { print "void test_${suite_name}__${test_name}();\n"; } } # # Beginning of main() function body for test runner # print <<"END"; /* Automatically-generated test runner */ int main() { /* Init CUnit test registry */ if (CU_initialize_registry() != CUE_SUCCESS) return CU_get_error(); END # # Within main(), register each test and its corresponding test suite # while ((my $suite_name, my $test_names) = each (%test_suites)) { print <<" END"; /* Create and register all tests for the $suite_name suite */ CU_pSuite $suite_name = CU_add_suite("$suite_name", NULL, NULL); if ($suite_name == NULL END foreach my $test_name (@{ $test_names }) { print <<" END"; || CU_add_test($suite_name, "$test_name", test_${suite_name}__${test_name}) == NULL END } print <<" END"; ) goto cleanup; END } # # End of main() function # print <<"END"; /* Force line-buffered output to ensure log messages are visible even if * a test crashes */ setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stderr, NULL, _IOLBF, 0); /* Write TAP header */ printf("1..$num_tests\\n"); /* Run all tests in all suites */ CU_set_test_complete_handler(tap_log_test_completed); CU_run_all_tests(); cleanup: /* Tests complete */ CU_cleanup_registry(); return CU_get_error(); } END guacamole-server-1.3.0/doc/0000755000175100001440000000000013772471154012532 500000000000000guacamole-server-1.3.0/doc/Doxyfile.in0000644000175100001440000000306413676721353014572 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Project name / version # PROJECT_NAME = libguac PROJECT_NUMBER = @PACKAGE_VERSION@ # # Warn about undocumented parameters and return values, but do not fill output # with verbose progress info. # QUIET = YES WARN_NO_PARAMDOC = YES # # Output format # ALPHABETICAL_INDEX = YES GENERATE_HTML = YES GENERATE_LATEX = NO IGNORE_PREFIX = guac_ vguac_ OPTIMIZE_OUTPUT_FOR_C = YES OUTPUT_DIRECTORY = doxygen-output RECURSIVE = YES SHOW_INCLUDE_FILES = NO # # Input format # CASE_SENSE_NAMES = YES EXCLUDE_SYMBOLS = __* guac_palette* FILE_PATTERNS = *.h INPUT = ../src/libguac/guacamole JAVADOC_AUTOBRIEF = YES STRIP_FROM_PATH = ../src/libguac TAB_SIZE = 4 TYPEDEF_HIDES_STRUCT = YES guacamole-server-1.3.0/.dockerignore0000644000175100001440000000117513676721353014367 00000000000000# Docker build spec Dockerfile # Git repository metadata .git **/.gitignore # Object code **/*.o **/*.so **/*.lo **/*.la # gcov files **/*.gcda **/*.gcov **/*.gcno # Backup files **/*~ # Release files **/*.tar.gz # Files currently being edited by vim or vi **/*.swp # automake/autoconf **/.deps/ **/.dirstamp **/.libs/ **/Makefile **/Makefile.in aclocal.m4 autom4te.cache/ m4/* **/!README compile config.guess config.h config.h.in config.log config.status config.sub configure depcomp install-sh libtool ltmain.sh missing stamp-h1 test-driver # Test binaries tests/test_* !tests/test_*.[ch] # Generated docs doc/doxygen-output guacamole-server-1.3.0/aclocal.m40000644000175100001440000015467213772471076013567 00000000000000# generated automatically by aclocal 1.16.1 -*- Autoconf -*- # Copyright (C) 1996-2018 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 11 (pkg-config-0.29.1) dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.1]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], dnl [DESCRIPTION], [DEFAULT]) dnl ------------------------------------------ dnl dnl Prepare a "--with-" configure option using the lowercase dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and dnl PKG_CHECK_MODULES in a single macro. AC_DEFUN([PKG_WITH_MODULES], [ m4_pushdef([with_arg], m4_tolower([$1])) m4_pushdef([description], [m4_default([$5], [build with ]with_arg[ support])]) m4_pushdef([def_arg], [m4_default([$6], [auto])]) m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) m4_case(def_arg, [yes],[m4_pushdef([with_without], [--without-]with_arg)], [m4_pushdef([with_without],[--with-]with_arg)]) AC_ARG_WITH(with_arg, AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, [AS_TR_SH([with_]with_arg)=def_arg]) AS_CASE([$AS_TR_SH([with_]with_arg)], [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], [auto],[PKG_CHECK_MODULES([$1],[$2], [m4_n([def_action_if_found]) $3], [m4_n([def_action_if_not_found]) $4])]) m4_popdef([with_arg]) m4_popdef([description]) m4_popdef([def_arg]) ])dnl PKG_WITH_MODULES dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [DESCRIPTION], [DEFAULT]) dnl ----------------------------------------------- dnl dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES dnl check._[VARIABLE-PREFIX] is exported as make variable. AC_DEFUN([PKG_HAVE_WITH_MODULES], [ PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) AM_CONDITIONAL([HAVE_][$1], [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) ])dnl PKG_HAVE_WITH_MODULES dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [DESCRIPTION], [DEFAULT]) dnl ------------------------------------------------------ dnl dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make dnl and preprocessor variable. AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], [ PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) ])dnl PKG_HAVE_DEFINE_WITH_MODULES # Copyright (C) 2002-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.16.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.16.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_COND_IF -*- Autoconf -*- # Copyright (C) 2008-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_COND_IF # _AM_COND_ELSE # _AM_COND_ENDIF # -------------- # These macros are only used for tracing. m4_define([_AM_COND_IF]) m4_define([_AM_COND_ELSE]) m4_define([_AM_COND_ENDIF]) # AM_COND_IF(COND, [IF-TRUE], [IF-FALSE]) # --------------------------------------- # If the shell condition COND is true, execute IF-TRUE, otherwise execute # IF-FALSE. Allow automake to learn about conditional instantiating macros # (the AC_CONFIG_FOOS). AC_DEFUN([AM_COND_IF], [m4_ifndef([_AM_COND_VALUE_$1], [m4_fatal([$0: no such condition "$1"])])dnl _AM_COND_IF([$1])dnl if test -z "$$1_TRUE"; then : m4_n([$2])[]dnl m4_ifval([$3], [_AM_COND_ELSE([$1])dnl else $3 ])dnl _AM_COND_ENDIF([$1])dnl fi[]dnl ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. Try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking is enabled. # This creates each '.Po' and '.Plo' makefile fragment that we'll need in # order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) guacamole-server-1.3.0/README0000644000175100001440000001373413702142276012566 00000000000000 ------------------------------------------------------------ About this README ------------------------------------------------------------ This README is intended to provide quick and to-the-point documentation for technical users intending to compile parts of Apache Guacamole themselves. Source archives are available from the downloads section of the project website: http://guacamole.apache.org/ A full manual is available as well: http://guacamole.apache.org/doc/gug/ ------------------------------------------------------------ What is guacamole-server? ------------------------------------------------------------ The guacamole-server package is a set of software which forms the basis of the Guacamole stack. It consists of guacd, libguac, and several protocol support libraries. guacd is the Guacamole proxy daemon used by the Guacamole web application and framework. As JavaScript cannot handle binary protocols (like VNC and remote desktop) efficiently, a new text-based protocol was developed which would contain a common superset of the operations needed for efficient remote desktop access, but would be easy for JavaScript programs to process. guacd is the proxy which translates between arbitrary protocols and the Guacamole protocol. ------------------------------------------------------------ Required dependencies ------------------------------------------------------------ All software within guacamole-server is built using the popular GNU Automake, and thus provides the standard configure script. Before compiling, at least the following required dependencies must already be installed: 1) Cairo (http://cairographics.org/) 2) libjpeg-turbo (http://libjpeg-turbo.virtualgl.org/) OR libjpeg (http://www.ijg.org/) 3) libpng (http://www.libpng.org/pub/png/libpng.html) 4) OSSP UUID (http://www.ossp.org/pkg/lib/uuid/) ------------------------------------------------------------ Optional dependencies ------------------------------------------------------------ In addition, the following optional dependencies may be installed in order to enable optional features of Guacamole. Note that while the various supported protocols are technically optional, you will no doubt wish to install the dependencies of at least ONE supported protocol, as Guacamole would be useless otherwise. RDP: * FreeRDP (http://www.freerdp.com/) SSH: * libssh2 (http://www.libssh2.org/) * OpenSSL (https://www.openssl.org/) * Pango (http://www.pango.org/) Telnet: * libtelnet (https://github.com/seanmiddleditch/libtelnet) * Pango (http://www.pango.org/) VNC: * libVNCserver (http://libvnc.github.io/) Support for audio within VNC: * PulseAudio (http://www.freedesktop.org/wiki/Software/PulseAudio/) Support for SFTP file transfer for VNC or RDP: * libssh2 (http://www.libssh2.org/) * OpenSSL (https://www.openssl.org/) Support for WebP image compression: * libwebp (https://developers.google.com/speed/webp/) "guacenc" video encoding utility: * FFmpeg (https://ffmpeg.org/) ------------------------------------------------------------ Compiling and installing guacd, libguac, etc. ------------------------------------------------------------ All software within guacamole-server is built using the popular GNU Automake, and thus provides the standard configure script. 1) Run configure $ ./configure Assuming all dependencies have been installed, this should succeed without errors. If you wish to install the init script as well, you need to specify the location where your system init scripts are located (typically /etc/init.d): $ ./configure --with-init-dir=/etc/init.d Running configure in this manner will cause the "make install" step to install an init script to the specified directory, which you can then activate using the service management mechanism provided by your distribution). 2) Run make $ make guacd, libguac, and any available protocol support libraries will now compile. 3) Install (as root) # make install All software that was just built, including documentation, will be installed. guacd will install to your /usr/local/sbin directory by default. You can change the install location by using the --prefix option for configure. ------------------------------------------------------------ Running guacd ------------------------------------------------------------ If you installed the init script during compile and install, you should be able to start guacd through the service management utilities provided by your distribution (if any) or by running the init script directly (as root): # /etc/init.d/guacd start Root access is needed to write the pidfile /var/run/guacd.pid. You can also run guacd itself directly without the init script (as any user): $ guacd guacd currently takes several command-line options: -b HOST Changes the host or address that guacd listens on. -l PORT Changes the port that guacd listens on (the default is port 4822). -p PIDFILE Causes guacd to write the PID of the daemon process to the specified file. This is useful for init scripts and is used by the provided init script. -L LEVEL Sets the maximum level at which guacd will log messages to syslog and, if running in the foreground, the console. Legal values are debug, info, warning, and error. The default value is info. -f Causes guacd to run in the foreground, rather than automatically forking into the background. Additional information can be found in the guacd man page: $ man guacd ------------------------------------------------------------ Reporting problems ------------------------------------------------------------ Please report any bugs encountered by opening a new issue in the JIRA system hosted at: https://issues.apache.org/jira/browse/GUACAMOLE guacamole-server-1.3.0/build-aux/0000755000175100001440000000000013772471155013660 500000000000000guacamole-server-1.3.0/build-aux/depcomp0000755000175100001440000005602013772471103015151 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2018 Free Software Foundation, Inc. # 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, 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, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: guacamole-server-1.3.0/build-aux/compile0000755000175100001440000001632713772471101015156 00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2018 Free Software Foundation, Inc. # Written by Tom Tromey . # # 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, 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, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: guacamole-server-1.3.0/build-aux/missing0000755000175100001440000001533613772471101015176 00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1996-2018 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # 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, 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, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=https://www.perl.org/ flex_URL=https://github.com/westes/flex gnu_software_URL=https://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: guacamole-server-1.3.0/build-aux/ltmain.sh0000644000175100001440000117106713772471072015433 00000000000000#! /bin/sh ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in ## by inline-source v2014-01-03.01 # libtool (GNU libtool) 2.4.6 # Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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, see . PROGRAM=libtool PACKAGE=libtool VERSION=2.4.6 package_revision=2.4.6 ## ------ ## ## Usage. ## ## ------ ## # Run './libtool --help' for help with using this script from the # command line. ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # After configure completes, it has a better idea of some of the # shell tools we need than the defaults used by the functions shared # with bootstrap, so set those here where they can still be over- # ridden by the user, but otherwise take precedence. : ${AUTOCONF="autoconf"} : ${AUTOMAKE="automake"} ## -------------------------- ## ## Source external libraries. ## ## -------------------------- ## # Much of our low-level functionality needs to be sourced from external # libraries, which are installed to $pkgauxdir. # Set a version string for this script. scriptversion=2015-01-20.17; # UTC # General shell script boiler plate, and helper functions. # Written by Gary V. Vaughan, 2004 # Copyright (C) 2004-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # 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 3 of the License, or # (at your option) any later version. # As a special exception to the GNU General Public License, if you distribute # this file as part of a program or library that is built using GNU Libtool, # you may include this file under the same distribution terms that you use # for the rest of that program. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNES 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, see . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## Usage. ## ## ------ ## # Evaluate this file near the top of your script to gain access to # the functions and variables defined here: # # . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh # # If you need to override any of the default environment variable # settings, do that before evaluating this file. ## -------------------- ## ## Shell normalisation. ## ## -------------------- ## # Some shells need a little help to be as Bourne compatible as possible. # Before doing anything else, make sure all that help has been provided! DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # NLS nuisances: We save the old values in case they are required later. _G_user_locale= _G_safe_locale= for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test set = \"\${$_G_var+set}\"; then save_$_G_var=\$$_G_var $_G_var=C export $_G_var _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Make sure IFS has a sensible default sp=' ' nl=' ' IFS="$sp $nl" # There are apparently some retarded systems that use ';' as a PATH separator! if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi ## ------------------------- ## ## Locate command utilities. ## ## ------------------------- ## # func_executable_p FILE # ---------------------- # Check that FILE is an executable regular file. func_executable_p () { test -f "$1" && test -x "$1" } # func_path_progs PROGS_LIST CHECK_FUNC [PATH] # -------------------------------------------- # Search for either a program that responds to --version with output # containing "GNU", or else returned by CHECK_FUNC otherwise, by # trying all the directories in PATH with each of the elements of # PROGS_LIST. # # CHECK_FUNC should accept the path to a candidate program, and # set $func_check_prog_result if it truncates its output less than # $_G_path_prog_max characters. func_path_progs () { _G_progs_list=$1 _G_check_func=$2 _G_PATH=${3-"$PATH"} _G_path_prog_max=0 _G_path_prog_found=false _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} for _G_dir in $_G_PATH; do IFS=$_G_save_IFS test -z "$_G_dir" && _G_dir=. for _G_prog_name in $_G_progs_list; do for _exeext in '' .EXE; do _G_path_prog=$_G_dir/$_G_prog_name$_exeext func_executable_p "$_G_path_prog" || continue case `"$_G_path_prog" --version 2>&1` in *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; *) $_G_check_func $_G_path_prog func_path_progs_result=$func_check_prog_result ;; esac $_G_path_prog_found && break 3 done done done IFS=$_G_save_IFS test -z "$func_path_progs_result" && { echo "no acceptable sed could be found in \$PATH" >&2 exit 1 } } # We want to be able to use the functions in this file before configure # has figured out where the best binaries are kept, which means we have # to search for them ourselves - except when the results are already set # where we skip the searches. # Unless the user overrides by setting SED, search the path for either GNU # sed, or the sed that truncates its output the least. test -z "$SED" && { _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for _G_i in 1 2 3 4 5 6 7; do _G_sed_script=$_G_sed_script$nl$_G_sed_script done echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed _G_sed_script= func_check_prog_sed () { _G_path_prog=$1 _G_count=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo '' >> conftest.nl "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin rm -f conftest.sed SED=$func_path_progs_result } # Unless the user overrides by setting GREP, search the path for either GNU # grep, or the grep that truncates its output the least. test -z "$GREP" && { func_check_prog_grep () { _G_path_prog=$1 _G_count=0 _G_path_prog_max=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo 'GREP' >> conftest.nl "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin GREP=$func_path_progs_result } ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # All uppercase variable names are used for environment variables. These # variables can be overridden by the user before calling a script that # uses them if a suitable command of that name is not already available # in the command search PATH. : ${CP="cp -f"} : ${ECHO="printf %s\n"} : ${EGREP="$GREP -E"} : ${FGREP="$GREP -F"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} ## -------------------- ## ## Useful sed snippets. ## ## -------------------- ## sed_dirname='s|/[^/]*$||' sed_basename='s|^.*/||' # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s|\([`"$\\]\)|\\\1|g' # Same as above, but do not quote variable references. sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' # Sed substitution that converts a w32 file name or path # that contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-'\' parameter expansions in output of sed_double_quote_subst that # were '\'-ed in input to the same. If an odd number of '\' preceded a # '$' in input to sed_double_quote_subst, that '$' was protected from # expansion. Since each input '\' is now two '\'s, look for any number # of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. _G_bs='\\' _G_bs2='\\\\' _G_bs4='\\\\\\\\' _G_dollar='\$' sed_double_backslash="\ s/$_G_bs4/&\\ /g s/^$_G_bs2$_G_dollar/$_G_bs&/ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g s/\n//g" ## ----------------- ## ## Global variables. ## ## ----------------- ## # Except for the global variables explicitly listed below, the following # functions in the '^func_' namespace, and the '^require_' namespace # variables initialised in the 'Resource management' section, sourcing # this file will not pollute your global namespace with anything # else. There's no portable way to scope variables in Bourne shell # though, so actually running these functions will sometimes place # results into a variable named after the function, and often use # temporary variables in the '^_G_' namespace. If you are careful to # avoid using those namespaces casually in your sourcing script, things # should continue to work as you expect. And, of course, you can freely # overwrite any of the functions or variables defined here before # calling anything to customize them. EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. # Allow overriding, eg assuming that you follow the convention of # putting '$debug_cmd' at the start of all your functions, you can get # bash to show function call trace with: # # debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name debug_cmd=${debug_cmd-":"} exit_cmd=: # By convention, finish your script with: # # exit $exit_status # # so that you can set exit_status to non-zero if you want to indicate # something went wrong during execution without actually bailing out at # the point of failure. exit_status=$EXIT_SUCCESS # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath=$0 # The name of this program. progname=`$ECHO "$progpath" |$SED "$sed_basename"` # Make sure we have an absolute progpath for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` progdir=`cd "$progdir" && pwd` progpath=$progdir/$progname ;; *) _G_IFS=$IFS IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS=$_G_IFS test -x "$progdir/$progname" && break done IFS=$_G_IFS test -n "$progdir" || progdir=`pwd` progpath=$progdir/$progname ;; esac ## ----------------- ## ## Standard options. ## ## ----------------- ## # The following options affect the operation of the functions defined # below, and should be set appropriately depending on run-time para- # meters passed on the command line. opt_dry_run=false opt_quiet=false opt_verbose=false # Categories 'all' and 'none' are always available. Append any others # you will pass as the first argument to func_warning from your own # code. warning_categories= # By default, display warnings according to 'opt_warning_types'. Set # 'warning_func' to ':' to elide all warnings, or func_fatal_error to # treat the next displayed warning as a fatal error. warning_func=func_warn_and_continue # Set to 'all' to display all warnings, 'none' to suppress all # warnings, or a space delimited list of some subset of # 'warning_categories' to display only the listed warnings. opt_warning_types=all ## -------------------- ## ## Resource management. ## ## -------------------- ## # This section contains definitions for functions that each ensure a # particular resource (a file, or a non-empty configuration variable for # example) is available, and if appropriate to extract default values # from pertinent package files. Call them using their associated # 'require_*' variable to ensure that they are executed, at most, once. # # It's entirely deliberate that calling these functions can set # variables that don't obey the namespace limitations obeyed by the rest # of this file, in order that that they be as useful as possible to # callers. # require_term_colors # ------------------- # Allow display of bold text on terminals that support it. require_term_colors=func_require_term_colors func_require_term_colors () { $debug_cmd test -t 1 && { # COLORTERM and USE_ANSI_COLORS environment variables take # precedence, because most terminfo databases neglect to describe # whether color sequences are supported. test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} if test 1 = "$USE_ANSI_COLORS"; then # Standard ANSI escape sequences tc_reset='' tc_bold=''; tc_standout='' tc_red=''; tc_green='' tc_blue=''; tc_cyan='' else # Otherwise trust the terminfo database after all. test -n "`tput sgr0 2>/dev/null`" && { tc_reset=`tput sgr0` test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` tc_standout=$tc_bold test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` } fi } require_term_colors=: } ## ----------------- ## ## Function library. ## ## ----------------- ## # This section contains a variety of useful functions to call in your # scripts. Take note of the portable wrappers for features provided by # some modern shells, which will fall back to slower equivalents on # less featureful shells. # func_append VAR VALUE # --------------------- # Append VALUE onto the existing contents of VAR. # We should try to minimise forks, especially on Windows where they are # unreasonably slow, so skip the feature probes when bash or zsh are # being used: if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then : ${_G_HAVE_ARITH_OP="yes"} : ${_G_HAVE_XSI_OPS="yes"} # The += operator was introduced in bash 3.1 case $BASH_VERSION in [12].* | 3.0 | 3.0*) ;; *) : ${_G_HAVE_PLUSEQ_OP="yes"} ;; esac fi # _G_HAVE_PLUSEQ_OP # Can be empty, in which case the shell is probed, "yes" if += is # useable or anything else if it does not work. test -z "$_G_HAVE_PLUSEQ_OP" \ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ && _G_HAVE_PLUSEQ_OP=yes if test yes = "$_G_HAVE_PLUSEQ_OP" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_append () { $debug_cmd eval "$1+=\$2" }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_append () { $debug_cmd eval "$1=\$$1\$2" } fi # func_append_quoted VAR VALUE # ---------------------------- # Quote VALUE and append to the end of shell variable VAR, separated # by a space. if test yes = "$_G_HAVE_PLUSEQ_OP"; then eval 'func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1+=\\ \$func_quote_for_eval_result" }' else func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1=\$$1\\ \$func_quote_for_eval_result" } fi # func_append_uniq VAR VALUE # -------------------------- # Append unique VALUE onto the existing contents of VAR, assuming # entries are delimited by the first character of VALUE. For example: # # func_append_uniq options " --another-option option-argument" # # will only append to $options if " --another-option option-argument " # is not already present somewhere in $options already (note spaces at # each end implied by leading space in second argument). func_append_uniq () { $debug_cmd eval _G_current_value='`$ECHO $'$1'`' _G_delim=`expr "$2" : '\(.\)'` case $_G_delim$_G_current_value$_G_delim in *"$2$_G_delim"*) ;; *) func_append "$@" ;; esac } # func_arith TERM... # ------------------ # Set func_arith_result to the result of evaluating TERMs. test -z "$_G_HAVE_ARITH_OP" \ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ && _G_HAVE_ARITH_OP=yes if test yes = "$_G_HAVE_ARITH_OP"; then eval 'func_arith () { $debug_cmd func_arith_result=$(( $* )) }' else func_arith () { $debug_cmd func_arith_result=`expr "$@"` } fi # func_basename FILE # ------------------ # Set func_basename_result to FILE with everything up to and including # the last / stripped. if test yes = "$_G_HAVE_XSI_OPS"; then # If this shell supports suffix pattern removal, then use it to avoid # forking. Hide the definitions single quotes in case the shell chokes # on unsupported syntax... _b='func_basename_result=${1##*/}' _d='case $1 in */*) func_dirname_result=${1%/*}$2 ;; * ) func_dirname_result=$3 ;; esac' else # ...otherwise fall back to using sed. _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` if test "X$func_dirname_result" = "X$1"; then func_dirname_result=$3 else func_append func_dirname_result "$2" fi' fi eval 'func_basename () { $debug_cmd '"$_b"' }' # func_dirname FILE APPEND NONDIR_REPLACEMENT # ------------------------------------------- # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. eval 'func_dirname () { $debug_cmd '"$_d"' }' # func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT # -------------------------------------------------------- # Perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # For efficiency, we do not delegate to the functions above but instead # duplicate the functionality here. eval 'func_dirname_and_basename () { $debug_cmd '"$_b"' '"$_d"' }' # func_echo ARG... # ---------------- # Echo program name prefixed message. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname: $_G_line" done IFS=$func_echo_IFS } # func_echo_all ARG... # -------------------- # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_echo_infix_1 INFIX ARG... # ------------------------------ # Echo program name, followed by INFIX on the first line, with any # additional lines not showing INFIX. func_echo_infix_1 () { $debug_cmd $require_term_colors _G_infix=$1; shift _G_indent=$_G_infix _G_prefix="$progname: $_G_infix: " _G_message=$* # Strip color escape sequences before counting printable length for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" do test -n "$_G_tc" && { _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` } done _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes func_echo_infix_1_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_infix_1_IFS $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 _G_prefix=$_G_indent done IFS=$func_echo_infix_1_IFS } # func_error ARG... # ----------------- # Echo program name prefixed message to standard error. func_error () { $debug_cmd $require_term_colors func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 } # func_fatal_error ARG... # ----------------------- # Echo program name prefixed message to standard error, and exit. func_fatal_error () { $debug_cmd func_error "$*" exit $EXIT_FAILURE } # func_grep EXPRESSION FILENAME # ----------------------------- # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $debug_cmd $GREP "$1" "$2" >/dev/null 2>&1 } # func_len STRING # --------------- # Set func_len_result to the length of STRING. STRING may not # start with a hyphen. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_len () { $debug_cmd func_len_result=${#1} }' else func_len () { $debug_cmd func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } fi # func_mkdir_p DIRECTORY-PATH # --------------------------- # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { $debug_cmd _G_directory_path=$1 _G_dir_list= if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then # Protect directory names starting with '-' case $_G_directory_path in -*) _G_directory_path=./$_G_directory_path ;; esac # While some portion of DIR does not yet exist... while test ! -d "$_G_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. _G_dir_list=$_G_directory_path:$_G_dir_list # If the last portion added has no slash in it, the list is done case $_G_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` done _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` func_mkdir_p_IFS=$IFS; IFS=: for _G_dir in $_G_dir_list; do IFS=$func_mkdir_p_IFS # mkdir can fail with a 'File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$_G_dir" 2>/dev/null || : done IFS=$func_mkdir_p_IFS # Bail out if we (or some other process) failed to create a directory. test -d "$_G_directory_path" || \ func_fatal_error "Failed to create '$1'" fi } # func_mktempdir [BASENAME] # ------------------------- # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, BASENAME is the basename for that directory. func_mktempdir () { $debug_cmd _G_template=${TMPDIR-/tmp}/${1-$progname} if test : = "$opt_dry_run"; then # Return a directory name, but don't create it in dry-run mode _G_tmpdir=$_G_template-$$ else # If mktemp works, use that first and foremost _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` if test ! -d "$_G_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race _G_tmpdir=$_G_template-${RANDOM-0}$$ func_mktempdir_umask=`umask` umask 0077 $MKDIR "$_G_tmpdir" umask $func_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$_G_tmpdir" || \ func_fatal_error "cannot create temporary directory '$_G_tmpdir'" fi $ECHO "$_G_tmpdir" } # func_normal_abspath PATH # ------------------------ # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. func_normal_abspath () { $debug_cmd # These SED scripts presuppose an absolute path with a trailing slash. _G_pathcar='s|^/\([^/]*\).*$|\1|' _G_pathcdr='s|^/[^/]*||' _G_removedotparts=':dotsl s|/\./|/|g t dotsl s|/\.$|/|' _G_collapseslashes='s|/\{1,\}|/|g' _G_finalslash='s|/*$|/|' # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` while :; do # Processed it all yet? if test / = "$func_normal_abspath_tpath"; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result"; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_notquiet ARG... # -------------------- # Echo program name prefixed message only when not in quiet mode. func_notquiet () { $debug_cmd $opt_quiet || func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_relative_path SRCDIR DSTDIR # -------------------------------- # Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. func_relative_path () { $debug_cmd func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=$func_dirname_result if test -z "$func_relative_path_tlibdir"; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test -n "$func_stripname_result"; then func_append func_relative_path_result "/$func_stripname_result" fi # Normalisation. If bindir is libdir, return '.' else relative path. if test -n "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result" func_relative_path_result=$func_stripname_result fi test -n "$func_relative_path_result" || func_relative_path_result=. : } # func_quote_for_eval ARG... # -------------------------- # Aesthetically quote ARGs to be evaled later. # This function returns two values: # i) func_quote_for_eval_result # double-quoted, suitable for a subsequent eval # ii) func_quote_for_eval_unquoted_result # has all characters that are still active within double # quotes backslashified. func_quote_for_eval () { $debug_cmd func_quote_for_eval_unquoted_result= func_quote_for_eval_result= while test 0 -lt $#; do case $1 in *[\\\`\"\$]*) _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; *) _G_unquoted_arg=$1 ;; esac if test -n "$func_quote_for_eval_unquoted_result"; then func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" else func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" fi case $_G_unquoted_arg in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and variable expansion # for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_quoted_arg=\"$_G_unquoted_arg\" ;; *) _G_quoted_arg=$_G_unquoted_arg ;; esac if test -n "$func_quote_for_eval_result"; then func_append func_quote_for_eval_result " $_G_quoted_arg" else func_append func_quote_for_eval_result "$_G_quoted_arg" fi shift done } # func_quote_for_expand ARG # ------------------------- # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { $debug_cmd case $1 in *[\\\`\"]*) _G_arg=`$ECHO "$1" | $SED \ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; *) _G_arg=$1 ;; esac case $_G_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_arg=\"$_G_arg\" ;; esac func_quote_for_expand_result=$_G_arg } # func_stripname PREFIX SUFFIX NAME # --------------------------------- # strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_stripname () { $debug_cmd # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary variable first. func_stripname_result=$3 func_stripname_result=${func_stripname_result#"$1"} func_stripname_result=${func_stripname_result%"$2"} }' else func_stripname () { $debug_cmd case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; esac } fi # func_show_eval CMD [FAIL_EXP] # ----------------------------- # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} func_quote_for_expand "$_G_cmd" eval "func_notquiet $func_quote_for_expand_result" $opt_dry_run || { eval "$_G_cmd" _G_status=$? if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_show_eval_locale CMD [FAIL_EXP] # ------------------------------------ # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} $opt_quiet || { func_quote_for_expand "$_G_cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || { eval "$_G_user_locale $_G_cmd" _G_status=$? eval "$_G_safe_locale" if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_tr_sh # ---------- # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { $debug_cmd case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_verbose ARG... # ------------------- # Echo program name prefixed message in verbose mode only. func_verbose () { $debug_cmd $opt_verbose && func_echo "$*" : } # func_warn_and_continue ARG... # ----------------------------- # Echo program name prefixed warning message to standard error. func_warn_and_continue () { $debug_cmd $require_term_colors func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 } # func_warning CATEGORY ARG... # ---------------------------- # Echo program name prefixed warning message to standard error. Warning # messages can be filtered according to CATEGORY, where this function # elides messages where CATEGORY is not listed in the global variable # 'opt_warning_types'. func_warning () { $debug_cmd # CATEGORY must be in the warning_categories list! case " $warning_categories " in *" $1 "*) ;; *) func_internal_error "invalid warning category '$1'" ;; esac _G_category=$1 shift case " $opt_warning_types " in *" $_G_category "*) $warning_func ${1+"$@"} ;; esac } # func_sort_ver VER1 VER2 # ----------------------- # 'sort -V' is not generally available. # Note this deviates from the version comparison in automake # in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a # but this should suffice as we won't be specifying old # version formats or redundant trailing .0 in bootstrap.conf. # If we did want full compatibility then we should probably # use m4_version_compare from autoconf. func_sort_ver () { $debug_cmd printf '%s\n%s\n' "$1" "$2" \ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n } # func_lt_ver PREV CURR # --------------------- # Return true if PREV and CURR are in the correct order according to # func_sort_ver, otherwise false. Use it like this: # # func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." func_lt_ver () { $debug_cmd test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: #! /bin/sh # Set a version string for this script. scriptversion=2014-01-07.03; # UTC # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 # Copyright (C) 2010-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # 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 3 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, see . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## Usage. ## ## ------ ## # This file is a library for parsing options in your shell scripts along # with assorted other useful supporting features that you can make use # of too. # # For the simplest scripts you might need only: # # #!/bin/sh # . relative/path/to/funclib.sh # . relative/path/to/options-parser # scriptversion=1.0 # func_options ${1+"$@"} # eval set dummy "$func_options_result"; shift # ...rest of your script... # # In order for the '--version' option to work, you will need to have a # suitably formatted comment like the one at the top of this file # starting with '# Written by ' and ending with '# warranty; '. # # For '-h' and '--help' to work, you will also need a one line # description of your script's purpose in a comment directly above the # '# Written by ' line, like the one at the top of this file. # # The default options also support '--debug', which will turn on shell # execution tracing (see the comment above debug_cmd below for another # use), and '--verbose' and the func_verbose function to allow your script # to display verbose messages only when your user has specified # '--verbose'. # # After sourcing this file, you can plug processing for additional # options by amending the variables from the 'Configuration' section # below, and following the instructions in the 'Option parsing' # section further down. ## -------------- ## ## Configuration. ## ## -------------- ## # You should override these variables in your script after sourcing this # file so that they reflect the customisations you have added to the # option parser. # The usage line for option parsing errors and the start of '-h' and # '--help' output messages. You can embed shell variables for delayed # expansion at the time the message is displayed, but you will need to # quote other shell meta-characters carefully to prevent them being # expanded when the contents are evaled. usage='$progpath [OPTION]...' # Short help message in response to '-h' and '--help'. Add to this or # override it after sourcing this library to reflect the full set of # options your script accepts. usage_message="\ --debug enable verbose shell tracing -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -v, --verbose verbosely report processing --version print version information and exit -h, --help print short or long help message and exit " # Additional text appended to 'usage_message' in response to '--help'. long_help_message=" Warning categories include: 'all' show all warnings 'none' turn off all the warnings 'error' warnings are treated as fatal errors" # Help message printed before fatal option parsing errors. fatal_help="Try '\$progname --help' for more information." ## ------------------------- ## ## Hook function management. ## ## ------------------------- ## # This section contains functions for adding, removing, and running hooks # to the main code. A hook is just a named list of of function, that can # be run in order later on. # func_hookable FUNC_NAME # ----------------------- # Declare that FUNC_NAME will run hooks added with # 'func_add_hook FUNC_NAME ...'. func_hookable () { $debug_cmd func_append hookable_fns " $1" } # func_add_hook FUNC_NAME HOOK_FUNC # --------------------------------- # Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must # first have been declared "hookable" by a call to 'func_hookable'. func_add_hook () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not accept hook functions." ;; esac eval func_append ${1}_hooks '" $2"' } # func_remove_hook FUNC_NAME HOOK_FUNC # ------------------------------------ # Remove HOOK_FUNC from the list of functions called by FUNC_NAME. func_remove_hook () { $debug_cmd eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' } # func_run_hooks FUNC_NAME [ARG]... # --------------------------------- # Run all hook functions registered to FUNC_NAME. # It is assumed that the list of hook functions contains nothing more # than a whitespace-delimited list of legal shell function names, and # no effort is wasted trying to catch shell meta-characters or preserve # whitespace. func_run_hooks () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook funcions.n" ;; esac eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do eval $_G_hook '"$@"' # store returned options list back into positional # parameters for next 'cmd' execution. eval _G_hook_result=\$${_G_hook}_result eval set dummy "$_G_hook_result"; shift done func_quote_for_eval ${1+"$@"} func_run_hooks_result=$func_quote_for_eval_result } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list in your hook function, remove any # options that you action, and then pass back the remaining unprocessed # options in '_result', escaped suitably for # 'eval'. Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # func_quote_for_eval ${1+"$@"} # my_options_prep_result=$func_quote_for_eval_result # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # # Note that for efficiency, we parse as many options as we can # # recognise in a loop before passing the remainder back to the # # caller on the first unrecognised argument we encounter. # while test $# -gt 0; do # opt=$1; shift # case $opt in # --silent|-s) opt_silent=: ;; # # Separate non-argument short options: # -s*) func_split_short_opt "$_G_opt" # set dummy "$func_split_short_opt_name" \ # "-$func_split_short_opt_arg" ${1+"$@"} # shift # ;; # *) set dummy "$_G_opt" "$*"; shift; break ;; # esac # done # # func_quote_for_eval ${1+"$@"} # my_silent_option_result=$func_quote_for_eval_result # } # func_add_hook func_parse_options my_silent_option # # # my_option_validation () # { # $debug_cmd # # $opt_silent && $opt_verbose && func_fatal_help "\ # '--silent' and '--verbose' options are mutually exclusive." # # func_quote_for_eval ${1+"$@"} # my_option_validation_result=$func_quote_for_eval_result # } # func_add_hook func_validate_options my_option_validation # # You'll alse need to manually amend $usage_message to reflect the extra # options you parse. It's preferable to append if you can, so that # multiple option parsing hooks can be added safely. # func_options [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the # individual implementations for details. func_hookable func_options func_options () { $debug_cmd func_options_prep ${1+"$@"} eval func_parse_options \ ${func_options_prep_result+"$func_options_prep_result"} eval func_validate_options \ ${func_parse_options_result+"$func_parse_options_result"} eval func_run_hooks func_options \ ${func_validate_options_result+"$func_validate_options_result"} # save modified positional parameters for caller func_options_result=$func_run_hooks_result } # func_options_prep [ARG]... # -------------------------- # All initialisations required before starting the option parse loop. # Note that when calling hook functions, we pass through the list of # positional parameters. If a hook function modifies that list, and # needs to propogate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before # returning. func_hookable func_options_prep func_options_prep () { $debug_cmd # Option defaults: opt_verbose=false opt_warning_types= func_run_hooks func_options_prep ${1+"$@"} # save modified positional parameters for caller func_options_prep_result=$func_run_hooks_result } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd func_parse_options_result= # this just eases exit handling while test $# -gt 0; do # Defer to hook functions for initial option parsing, so they # get priority in the event of reusing an option name. func_run_hooks func_parse_options ${1+"$@"} # Adjust func_parse_options positional parameters to match eval set dummy "$func_run_hooks_result"; shift # Break out of the loop if we already parsed every option. test $# -gt 0 || break _G_opt=$1 shift case $_G_opt in --debug|-x) debug_cmd='set -x' func_echo "enabling shell trace mode" $debug_cmd ;; --no-warnings|--no-warning|--no-warn) set dummy --warnings none ${1+"$@"} shift ;; --warnings|--warning|-W) test $# = 0 && func_missing_arg $_G_opt && break case " $warning_categories $1" in *" $1 "*) # trailing space prevents matching last $1 above func_append_uniq opt_warning_types " $1" ;; *all) opt_warning_types=$warning_categories ;; *none) opt_warning_types=none warning_func=: ;; *error) opt_warning_types=$warning_categories warning_func=func_fatal_error ;; *) func_fatal_error \ "unsupported warning category: '$1'" ;; esac shift ;; --verbose|-v) opt_verbose=: ;; --version) func_version ;; -\?|-h) func_usage ;; --help) func_help ;; # Separate optargs to long options (plugins may need this): --*=*) func_split_equals "$_G_opt" set dummy "$func_split_equals_lhs" \ "$func_split_equals_rhs" ${1+"$@"} shift ;; # Separate optargs to short options: -W*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "$func_split_short_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-v*|-x*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} func_parse_options_result=$func_quote_for_eval_result } # func_validate_options [ARG]... # ------------------------------ # Perform any sanity checks on option settings and/or unconsumed # arguments. func_hookable func_validate_options func_validate_options () { $debug_cmd # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" func_run_hooks func_validate_options ${1+"$@"} # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE # save modified positional parameters for caller func_validate_options_result=$func_run_hooks_result } ## ----------------- ## ## Helper functions. ## ## ----------------- ## # This section contains the helper functions used by the rest of the # hookable option parser framework in ascii-betical order. # func_fatal_help ARG... # ---------------------- # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { $debug_cmd eval \$ECHO \""Usage: $usage"\" eval \$ECHO \""$fatal_help"\" func_error ${1+"$@"} exit $EXIT_FAILURE } # func_help # --------- # Echo long help message to standard output and exit. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message" exit 0 } # func_missing_arg ARGNAME # ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $debug_cmd func_error "Missing argument for '$1'." exit_cmd=exit } # func_split_equals STRING # ------------------------ # Set func_split_equals_lhs and func_split_equals_rhs shell variables after # splitting STRING at the '=' sign. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_equals () { $debug_cmd func_split_equals_lhs=${1%%=*} func_split_equals_rhs=${1#*=} test "x$func_split_equals_lhs" = "x$1" \ && func_split_equals_rhs= }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_equals () { $debug_cmd func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` func_split_equals_rhs= test "x$func_split_equals_lhs" = "x$1" \ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` } fi #func_split_equals # func_split_short_opt SHORTOPT # ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_short_opt () { $debug_cmd func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"} }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_short_opt () { $debug_cmd func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` } fi #func_split_short_opt # func_usage # ---------- # Echo short help message to standard output and exit. func_usage () { $debug_cmd func_usage_message $ECHO "Run '$progname --help |${PAGER-more}' for full usage" exit 0 } # func_usage_message # ------------------ # Echo short help message to standard output. func_usage_message () { $debug_cmd eval \$ECHO \""Usage: $usage"\" echo $SED -n 's|^# || /^Written by/{ x;p;x } h /^Written by/q' < "$progpath" echo eval \$ECHO \""$usage_message"\" } # func_version # ------------ # Echo version message to standard output and exit. func_version () { $debug_cmd printf '%s\n' "$progname $scriptversion" $SED -n ' /(C)/!b go :more /\./!{ N s|\n# | | b more } :go /^# Written by /,/# warranty; / { s|^# || s|^# *$|| s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| p } /^# Written by / { s|^# || p } /^warranty; /q' < "$progpath" exit $? } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: # Set a version string. scriptversion='(GNU libtool) 2.4.6' # func_echo ARG... # ---------------- # Libtool also displays the current mode in messages, so override # funclib.sh func_echo with this custom definition. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" done IFS=$func_echo_IFS } # func_warning ARG... # ------------------- # Libtool warnings are not categorized, so override funclib.sh # func_warning with this simpler definition. func_warning () { $debug_cmd $warning_func ${1+"$@"} } ## ---------------- ## ## Options parsing. ## ## ---------------- ## # Hook in the functions to make sure our own options are parsed during # the option parsing loop. usage='$progpath [OPTION]... [MODE-ARG]...' # Short help message in response to '-h'. usage_message="Options: --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --mode=MODE use operation mode MODE --no-warnings equivalent to '-Wnone' --preserve-dup-deps don't remove duplicate dependency libraries --quiet, --silent don't print informational messages --tag=TAG use configuration variables from tag TAG -v, --verbose print more informational messages than default --version print version information -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -h, --help, --help-all print short, long, or detailed help message " # Additional text appended to 'usage_message' in response to '--help'. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. When passed as first option, '--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. Try '$progname --help --mode=MODE' for a more detailed description of MODE. When reporting a bug, please describe a test case to reproduce it and include the following information: host-triplet: $host shell: $SHELL compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) version: $progname (GNU libtool) 2.4.6 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to . GNU libtool home page: . General help using GNU software: ." exit 0 } # func_lo2o OBJECT-NAME # --------------------- # Transform OBJECT-NAME from a '.lo' suffix to the platform specific # object suffix. lo2o=s/\\.lo\$/.$objext/ o2lo=s/\\.$objext\$/.lo/ if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_lo2o () { case $1 in *.lo) func_lo2o_result=${1%.lo}.$objext ;; * ) func_lo2o_result=$1 ;; esac }' # func_xform LIBOBJ-OR-SOURCE # --------------------------- # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) # suffix to a '.lo' libtool-object suffix. eval 'func_xform () { func_xform_result=${1%.*}.lo }' else # ...otherwise fall back to using sed. func_lo2o () { func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` } func_xform () { func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` } fi # func_fatal_configuration ARG... # ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_fatal_error ${1+"$@"} \ "See the $PACKAGE documentation for more information." \ "Fatal configuration error." } # func_config # ----------- # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # ------------- # Display the features supported by this script. func_features () { echo "host: $host" if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag TAGNAME # ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname=$1 re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf=/$re_begincf/,/$re_endcf/p # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # libtool_options_prep [ARG]... # ----------------------------- # Preparation for options parsed by libtool. libtool_options_prep () { $debug_mode # Option defaults: opt_config=false opt_dlopen= opt_dry_run=false opt_help=false opt_mode= opt_preserve_dup_deps=false opt_quiet=false nonopt= preserve_args= # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Pass back the list of options. func_quote_for_eval ${1+"$@"} libtool_options_prep_result=$func_quote_for_eval_result } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _G_opt=$1 shift case $_G_opt in --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) func_config ;; --dlopen|-dlopen) opt_dlopen="${opt_dlopen+$opt_dlopen }$1" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) func_features ;; --finish) set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $_G_opt && break opt_mode=$1 case $1 in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $_G_opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_quiet=false func_append preserve_args " $_G_opt" ;; --no-warnings|--no-warning|--no-warn) opt_warning=false func_append preserve_args " $_G_opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $_G_opt" ;; --silent|--quiet) opt_quiet=: opt_verbose=false func_append preserve_args " $_G_opt" ;; --tag) test $# = 0 && func_missing_arg $_G_opt && break opt_tag=$1 func_append preserve_args " $_G_opt $1" func_enable_tag "$1" shift ;; --verbose|-v) opt_quiet=false opt_verbose=: func_append preserve_args " $_G_opt" ;; # An option not handled by this hook function: *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} libtool_parse_options_result=$func_quote_for_eval_result } func_add_hook func_parse_options libtool_parse_options # libtool_validate_options [ARG]... # --------------------------------- # Perform any sanity checks on option settings and/or unconsumed # arguments. libtool_validate_options () { # save first non-option argument if test 0 -lt $#; then nonopt=$1 shift fi # preserve --debug test : = "$debug_cmd" || func_append preserve_args " --debug" case $host in # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match test yes != "$build_libtool_libs" \ && test yes != "$build_old_libs" \ && func_fatal_configuration "not configured to build any kind of library" # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test execute != "$opt_mode"; then func_error "unrecognized option '-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help=$help help="Try '$progname --help --mode=$opt_mode' for more information." } # Pass back the unparsed argument list func_quote_for_eval ${1+"$@"} libtool_validate_options_result=$func_quote_for_eval_result } func_add_hook func_validate_options libtool_validate_options # Process options as early as possible so that --help and --version # can return quickly. func_options ${1+"$@"} eval set dummy "$func_options_result"; shift ## ----------- ## ## Main. ## ## ----------- ## magic='%%%MAGIC variable%%%' magic_exe='%%%MAGIC EXE variable%%%' # Global variables. extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # func_generated_by_libtool # True iff stdin has been generated by Libtool. This function is only # a basic sanity check; it will hardly flush out determined imposters. func_generated_by_libtool_p () { $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test yes = "$lalib_p" } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { test -f "$1" && $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $debug_cmd save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # 'FILE.' does not work on cygwin managed mounts. func_source () { $debug_cmd case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $debug_cmd if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=$1 if test yes = "$build_libtool_libs"; then write_lobj=\'$2\' else write_lobj=none fi if test yes = "$build_old_libs"; then write_oldobj=\'$3\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $debug_cmd # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $debug_cmd if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $debug_cmd # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $debug_cmd if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result=$1 fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $debug_cmd if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result=$3 fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $debug_cmd case $4 in $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $debug_cmd $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $debug_cmd case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result=$1 } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $debug_cmd if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd=func_convert_path_$func_stripname_result fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $debug_cmd func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result=$1 } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_dll_def_p FILE # True iff FILE is a Windows DLL '.def' file. # Keep in sync with _LT_DLL_DEF_P in libtool.m4 func_dll_def_p () { $debug_cmd func_dll_def_p_tmp=`$SED -n \ -e 's/^[ ]*//' \ -e '/^\(;.*\)*$/d' \ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ -e q \ "$1"` test DEF = "$func_dll_def_p_tmp" } # func_mode_compile arg... func_mode_compile () { $debug_cmd # Get the compilation command and the source file. base_compile= srcfile=$nonopt # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg=$arg arg_mode=normal ;; target ) libobj=$arg arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs=$IFS; IFS=, for arg in $args; do IFS=$save_ifs func_append_quoted lastarg "$arg" done IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg=$srcfile srcfile=$arg ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj=$func_basename_result } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test yes = "$build_libtool_libs" \ || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname=$func_basename_result xdir=$func_dirname_result lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test no = "$compiler_c_o"; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext lockfile=$output_obj.lock else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test warn = "$need_locks"; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test yes = "$build_old_libs"; then if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a '.o' file suitable for static linking -static only build a '.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a 'standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix '.c' with the library object suffix, '.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to '-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the '--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the 'install' or 'cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE use a list of object files found in FILE to specify objects -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with '-') are ignored. Every other argument is treated as a filename. Files ending in '.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in '.la', then a libtool library is created, only library objects ('.lo' files) may be specified, and '-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created using 'ar' and 'ranlib', or on Windows using 'lib'. If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test : = "$opt_help"; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | $SED '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $debug_cmd # The first argument is the command name. cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "'$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir=$func_dirname_result ;; *) func_warning "'-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir=$absdir # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic=$magic # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file=$progdir/$program fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if $opt_dry_run; then # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd=\$cmd$args fi } test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $debug_cmd libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "'$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument '$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the '-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the '$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the '$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the '$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $debug_cmd # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=false stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=: if $isdir; then destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." destdir=$func_dirname_result destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "'$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir=$func_dirname_result func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking '$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname=$1 shift srcname=$realname test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme= ;; esac ;; os2*) case $realname in *_dll.a) tstripme= ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try 'ln -sf' first, because the 'ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name=$func_basename_result instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest=$destfile destfile= ;; *) func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext= case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=.exe fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script '$wrapper'" finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then func_warning "'$lib' has not been installed in '$libdir'" finalize=false fi done relink_command= func_source "$wrapper" outputname= if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file=$func_basename_result outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_quiet || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file=$outputname else func_warning "cannot relink '$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name=$func_basename_result # Set up the ranlib parameters. oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $debug_cmd my_outputname=$1 my_originator=$2 my_pic_p=${3-false} my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* External symbol declarations for the compiler. */\ " if test yes = "$dlself"; then func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi func_show_eval '$RM "${nlist}I"' if test -n "$global_symbol_to_import"; then eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[];\ " if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ static void lt_syminit(void) { LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; for (; symbol->name; ++symbol) {" $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" echo >> "$output_objdir/$my_dlsyms" "\ } }" fi echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = { {\"$my_originator\", (void *) 0}," if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ {\"@INIT@\", (void *) <_syminit}," fi case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $debug_cmd win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then case $nm_interface in "MS dumpbin") if func_cygming_ms_implib_p "$1" || func_cygming_gnu_implib_p "$1" then win32_nmres=import else win32_nmres= fi ;; *) func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s|.*|import| p q } }'` ;; esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $debug_cmd sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $debug_cmd match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive that possess that section. Heuristic: eliminate # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $debug_cmd if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result= fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $debug_cmd f_ex_an_ar_dir=$1; shift f_ex_an_ar_oldlib=$1 if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $debug_cmd my_gentop=$1; shift my_oldlibs=${1+"$@"} my_oldobjs= my_xlib= my_xabs= my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` func_basename "$darwin_archive" darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches; do func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" cd "unfat-$$/$darwin_base_archive-$darwin_arch" func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result=$my_oldobjs } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* declarations of non-ANSI functions */ #if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ #if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC #elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined other platforms ... */ #endif #if defined PATH_MAX # define LT_PATHMAX PATH_MAX #elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free (stale); stale = 0; } \ } while (0) #if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; size_t tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined HAVE_DOS_BASED_FILE_SYSTEM if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined HAVE_DOS_BASED_FILE_SYSTEM } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = (size_t) (q - p); p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (STREQ (str, pat)) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else size_t len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { size_t orig_value_len = strlen (orig_value); size_t add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ size_t len = strlen (new_value); while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $debug_cmd case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_suncc_cstd_abi # !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! # Several compiler flags select an ABI that is incompatible with the # Cstd library. Avoid specifying it if any are in CXXFLAGS. func_suncc_cstd_abi () { $debug_cmd case " $compile_command " in *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) suncc_use_cstd_abi=no ;; *) suncc_use_cstd_abi=yes ;; esac } # func_mode_link arg... func_mode_link () { $debug_cmd case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=false prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test yes != "$build_libtool_libs" \ && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg=$1 shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir=$arg prev= continue ;; dlfiles|dlprefiles) $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=: } case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test no = "$dlself"; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test dlprefiles = "$prev"; then dlself=yes elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols=$arg test -f "$arg" \ || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex=$arg prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir=$arg prev= continue ;; mllvm) # Clang does not use LLVM to link, so we can simply discard any # '-mllvm $arg' options when doing the link step. prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object fi # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; os2dllname) os2dllname=$arg prev= continue ;; precious_regex) precious_files_regex=$arg prev= continue ;; release) release=-$arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds=$arg prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg=$arg case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between '-L' and '$1'" else func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of '$dir'" dir=$absdir ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test X-lc = "X$arg" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc due to us having libc/libc_r. test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test X-lc = "X$arg" && continue ;; esac elif test X-lc_r = "X$arg"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -mllvm) prev=mllvm continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module=$wl-multi_module continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "'-no-install' is ignored for $host" func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -os2dllname) prev=os2dllname continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ -specs=*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; -Z*) if test os2 = "`expr $host : '.*\(os2\)'`"; then # OS/2 uses -Zxxx to specify OS/2-specific options compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case $arg in -Zlinker | -Zstack) prev=xcompiler ;; esac continue else # Otherwise treat like 'Some other compiler flag' below func_quote_for_eval "$arg" arg=$func_quote_for_eval_result fi ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result test none = "$pic_object" || { # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object } # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the '$prevarg' option requires an argument" if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname=$func_basename_result libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" # Definition is injected by LT_CONFIG during libtool generation. func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" func_dirname "$output" "/" "" output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs=$tmp_deplibs fi if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass"; then libs=$deplibs deplibs= fi if test prog = "$linkmode"; then case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs=$dlprefiles fi if test dlopen = "$pass"; then # Collect dlpreopened libraries save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test lib != "$linkmode" && test prog != "$linkmode"; then func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib=$searchdir/lib$name$search_ext if test -f "$lib"; then if test .la = "$search_ext"; then found=: else found=false fi break 2 fi done done if $found; then # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll=$l done if test "X$ll" = "X$old_library"; then # only static version available found=false func_dirname "$lib" "" "." ladir=$func_dirname_result lib=$ladir/$old_library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi else # deplib doesn't seem to be a libtool library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l *.ltframework) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=: fi ;; pass_all) valid_a_lib=: ;; esac if $valid_a_lib; then echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." fi ;; esac continue ;; prog) if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test conv = "$pass"; then deplibs="$deplib $deplibs" elif test prog = "$linkmode"; then if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=: continue ;; esac # case $deplib $found || test -f "$lib" \ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir=$func_dirname_result dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass" || { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test yes = "$prefer_static_libs" || test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib=$l done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. if test dlopen = "$pass"; then test -z "$libdir" \ && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || test yes != "$dlopen_support" || test no = "$build_libtool_libs" then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir=$ladir fi ;; esac func_basename "$lib" laname=$func_basename_result # Find the relevant object directory and library name. if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library '$lib' was moved." dir=$ladir absdir=$abs_ladir libdir=$abs_ladir else dir=$lt_sysroot$libdir absdir=$lt_sysroot$libdir fi test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir=$ladir absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else dir=$ladir/$objdir absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test dlpreopen = "$pass"; then if test -z "$libdir" && test prog = "$linkmode"; then func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=false if test no != "$link_all_deplibs" || test -z "$library_names" || test no = "$build_libtool_libs"; then linkalldeplibs=: fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && { { test no = "$prefer_static_libs" || test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if $alldeplibs && { test pass_all = "$deplibs_check_method" || { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule=$dlpremoduletest break fi done if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test lib = "$linkmode" && test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result versuffix=-$major ;; esac eval soname=\"$soname_spec\" else soname=$realname fi # Make a new name for the extract_expsyms_cmds to use soroot=$soname func_basename "$soroot" soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test no = "$hardcode_direct"; then add=$dir/$linklib case $host in *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add=$dir/$old_library fi elif test -n "$old_library"; then add=$dir/$old_library fi fi esac elif test no = "$hardcode_minus_L"; then case $host in *-*-sunos*) add_shlibpath=$dir ;; esac add_dir=-L$dir add=-l$name elif test no = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; relink) if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$dir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name elif test yes = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; *) lib_linked=no ;; esac if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test yes != "$hardcode_direct" && test yes != "$hardcode_minus_L" && test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$libdir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$libdir add=-l$name elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add=-l$name elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib"; then add=$inst_prefix_dir$libdir/$linklib else add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir=-L$libdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name fi if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test unsupported != "$hardcode_direct"; then test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test yes = "$build_libtool_libs"; then # Not a shared library if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test lib = "$linkmode"; then if test -n "$dependency_libs" && { test yes != "$hardcode_into_libs" || test yes = "$build_old_libs" || test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of '$dir'" absdir=$dir fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names"; then for tmp in $deplibrary_names; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl"; then depdepl=$absdir/$objdir/$depdepl darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) path=-L$absdir/$objdir ;; esac else eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "'$deplib' seems to be moved" path=-L$absdir fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test link = "$pass"; then if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs=$newdependency_libs if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test dlopen != "$pass"; then test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= } if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" else vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Add Sun CC postdeps if required: test CXX = "$tagname" && { case $host_os in linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; solaris*) func_cc_basename "$CC" case $func_cc_basename_result in CC* | sunCC*) func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; esac } # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i= ;; esac if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test prog = "$linkmode"; then dlfiles=$newdlfiles fi if test prog = "$linkmode" || test lib = "$linkmode"; then dlprefiles=$newdlprefiles fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs=$output func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test no = "$module" \ && func_fatal_help "libtool library '$output' must begin with 'lib'" if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test pass_all != "$deplibs_check_method"; then func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test no = "$dlself" \ || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test 1 -lt "$#" \ && func_warning "ignoring multiple '-rpath's for a libtool library" install_libdir=$1 oldlibs= if test -z "$rpath"; then if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift IFS=$save_ifs test -n "$7" && \ func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major=$1 number_minor=$2 number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|freebsd-elf|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_revision ;; freebsd-aout|qnx|sunos) current=$number_major revision=$number_minor age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_minor lt_irix_increment=no ;; esac ;; no) current=$1 revision=$2 age=$3 ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT '$current' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION '$revision' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE '$age' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE '$age' is greater than the current interface number '$current'" func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" # On Darwin other compilers case $CC in nagfor*) verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" ;; *) verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; esac ;; freebsd-aout) major=.$current versuffix=.$current.$revision ;; freebsd-elf) func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; irix | nonstopux) if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring_prefix$major.$iface:$verstring done # Before this point, $major must not contain '.'. major=.$major versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=.$current.$age.$revision verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring:$iface.0 done # Make executables depend on our current version. func_append verstring ":$current.0" ;; qnx) major=.$current versuffix=.$current ;; sco) major=.$current versuffix=.$current ;; sunos) major=.$current versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result versuffix=-$major ;; *) func_fatal_configuration "unknown library version type '$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring=0.0 ;; esac if test no = "$need_version"; then versuffix= else versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided if test yes,no = "$avoid_version,$need_version"; then major= versuffix= verstring= fi # Check to see if the archive will have undefined symbols. if test yes = "$allow_undefined"; then if test unsupported = "$allow_undefined_flag"; then if test yes = "$build_old_libs"; then func_warning "undefined symbols not allowed in $host shared libraries; building static only" build_libtool_libs=no else func_fatal_error "can't build $host shared library unless -no-undefined is specified" fi fi else # Don't allow undefined symbols. allow_undefined_flag=$no_undefined_flag fi fi func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" test " " = "$libobjs" && libobjs= if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release= versuffix= major= newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib= ;; esac fi if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test yes = "$allow_libtool_libs_with_static_runtimes"; then for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test yes = "$droppeddeps"; then if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test yes = "$build_libtool_libs"; then # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath=$finalize_rpath test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath=$finalize_shlibpath test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname=$realname fi if test -z "$dlname"; then dlname=$soname fi lib=$output_objdir/$realname linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS=$save_ifs if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi ${skipped_export-false} && { func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi } libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs=$IFS; IFS='~' for cmd in $cmds; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs # Restore the uninstalled library and exit if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. dlname=$soname fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ func_warning "'-version-info' is ignored for objects" test -n "$release" && \ func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj=$output ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # if reload_cmds runs $LD directly, get rid of -Wl from # whole_archive_flag_spec and hope we can get by with turning comma # into space. case $reload_cmds in *\$LD[\ \$]*) wl= ;; esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS } if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "'-version-info' is ignored for programs" test -n "$release" && \ func_warning "'-release' is ignored for programs" $preload \ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " $wl-bind_at_load" func_append finalize_command " $wl-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath=$rpath rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath=$rpath if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=false ;; *cygwin* | *mingw* ) test yes = "$build_libtool_libs" || wrappers_required=false ;; *) if test no = "$need_relink" || test yes != "$build_libtool_libs"; then wrappers_required=false fi ;; esac $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.$objext"; then func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test yes = "$no_install"; then # We don't need to create a wrapper script. link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi case $hardcode_action,$fast_install in relink,*) # Fast installation is not supported link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath func_warning "this platform does not like uninstalled shared libraries" func_warning "'$output' will be relinked during installation" ;; *,yes) link_command=$finalize_var$compile_command$finalize_rpath relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` ;; *,no) link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath ;; *,needless) link_command=$finalize_var$compile_command$finalize_rpath relink_command= ;; esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource=$output_path/$objdir/lt-$output_name.c cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do case $build_libtool_libs in convenience) oldobjs="$libobjs_save $symfileobj" addlibs=$convenience build_libtool_libs=no ;; module) oldobjs=$libobjs_save addlibs=$old_convenience build_libtool_libs=no ;; *) oldobjs="$old_deplibs $non_pic_objects" $preload && test -f "$symfileobj" \ && func_append oldobjs " $symfileobj" addlibs=$old_convenience ;; esac if test -n "$addlibs"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test yes = "$installed"; then if test -z "$install_libdir"; then break fi output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name=$func_basename_result func_resolve_sysroot "$deplib" eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } if test link = "$opt_mode" || test relink = "$opt_mode"; then func_mode_link ${1+"$@"} fi # func_mode_uninstall arg... func_mode_uninstall () { $debug_cmd RM=$nonopt files= rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic for arg do case $arg in -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir=$func_dirname_result if test . = "$dir"; then odir=$objdir else odir=$dir/$objdir fi func_basename "$file" name=$func_basename_result test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif $rmforce; then continue fi rmfiles=$file case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.$objext" if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name"; then func_append rmfiles " $odir/lt-$noexename.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then func_mode_uninstall ${1+"$@"} fi test -z "$opt_mode" && { help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: guacamole-server-1.3.0/build-aux/config.sub0000755000175100001440000007530413772471101015563 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2018 Free Software Foundation, Inc. timestamp='2018-08-29' # This file 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 3 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, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo "$1" exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Split fields of configuration type IFS="-" read -r field1 field2 field3 field4 <&2 exit 1 ;; *-*-*-*) basic_machine=$field1-$field2 os=$field3-$field4 ;; *-*-*) # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two # parts maybe_os=$field2-$field3 case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \ | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ | storm-chaos* | os2-emx* | rtmk-nova*) basic_machine=$field1 os=$maybe_os ;; android-linux) basic_machine=$field1-unknown os=linux-android ;; *) basic_machine=$field1-$field2 os=$field3 ;; esac ;; *-*) # A lone config we happen to match not fitting any patern case $field1-$field2 in decstation-3100) basic_machine=mips-dec os= ;; *-*) # Second component is usually, but not always the OS case $field2 in # Prevent following clause from handling this valid os sun*os*) basic_machine=$field1 os=$field2 ;; # Manufacturers dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ | unicom* | ibm* | next | hp | isi* | apollo | altos* \ | convergent* | ncr* | news | 32* | 3600* | 3100* \ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ | ultra | tti* | harris | dolphin | highlevel | gould \ | cbm | ns | masscomp | apple | axis | knuth | cray \ | microblaze* | sim | cisco \ | oki | wec | wrs | winbond) basic_machine=$field1-$field2 os= ;; *) basic_machine=$field1 os=$field2 ;; esac ;; esac ;; *) # Convert single-component short-hands not valid as part of # multi-component configurations. case $field1 in 386bsd) basic_machine=i386-pc os=bsd ;; a29khif) basic_machine=a29k-amd os=udi ;; adobe68k) basic_machine=m68010-adobe os=scout ;; alliant) basic_machine=fx80-alliant os= ;; altos | altos3068) basic_machine=m68k-altos os= ;; am29k) basic_machine=a29k-none os=bsd ;; amdahl) basic_machine=580-amdahl os=sysv ;; amiga) basic_machine=m68k-unknown os= ;; amigaos | amigados) basic_machine=m68k-unknown os=amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=sysv4 ;; apollo68) basic_machine=m68k-apollo os=sysv ;; apollo68bsd) basic_machine=m68k-apollo os=bsd ;; aros) basic_machine=i386-pc os=aros ;; aux) basic_machine=m68k-apple os=aux ;; balance) basic_machine=ns32k-sequent os=dynix ;; blackfin) basic_machine=bfin-unknown os=linux ;; cegcc) basic_machine=arm-unknown os=cegcc ;; convex-c1) basic_machine=c1-convex os=bsd ;; convex-c2) basic_machine=c2-convex os=bsd ;; convex-c32) basic_machine=c32-convex os=bsd ;; convex-c34) basic_machine=c34-convex os=bsd ;; convex-c38) basic_machine=c38-convex os=bsd ;; cray) basic_machine=j90-cray os=unicos ;; crds | unos) basic_machine=m68k-crds os= ;; da30) basic_machine=m68k-da30 os= ;; decstation | pmax | pmin | dec3100 | decstatn) basic_machine=mips-dec os= ;; delta88) basic_machine=m88k-motorola os=sysv3 ;; dicos) basic_machine=i686-pc os=dicos ;; djgpp) basic_machine=i586-pc os=msdosdjgpp ;; ebmon29k) basic_machine=a29k-amd os=ebmon ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=ose ;; gmicro) basic_machine=tron-gmicro os=sysv ;; go32) basic_machine=i386-pc os=go32 ;; h8300hms) basic_machine=h8300-hitachi os=hms ;; h8300xray) basic_machine=h8300-hitachi os=xray ;; h8500hms) basic_machine=h8500-hitachi os=hms ;; harris) basic_machine=m88k-harris os=sysv3 ;; hp300) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=bsd ;; hp300hpux) basic_machine=m68k-hp os=hpux ;; hppaosf) basic_machine=hppa1.1-hp os=osf ;; hppro) basic_machine=hppa1.1-hp os=proelf ;; i386mach) basic_machine=i386-mach os=mach ;; vsta) basic_machine=i386-pc os=vsta ;; isi68 | isi) basic_machine=m68k-isi os=sysv ;; m68knommu) basic_machine=m68k-unknown os=linux ;; magnum | m3230) basic_machine=mips-mips os=sysv ;; merlin) basic_machine=ns32k-utek os=sysv ;; mingw64) basic_machine=x86_64-pc os=mingw64 ;; mingw32) basic_machine=i686-pc os=mingw32 ;; mingw32ce) basic_machine=arm-unknown os=mingw32ce ;; monitor) basic_machine=m68k-rom68k os=coff ;; morphos) basic_machine=powerpc-unknown os=morphos ;; moxiebox) basic_machine=moxie-unknown os=moxiebox ;; msdos) basic_machine=i386-pc os=msdos ;; msys) basic_machine=i686-pc os=msys ;; mvs) basic_machine=i370-ibm os=mvs ;; nacl) basic_machine=le32-unknown os=nacl ;; ncr3000) basic_machine=i486-ncr os=sysv4 ;; netbsd386) basic_machine=i386-pc os=netbsd ;; netwinder) basic_machine=armv4l-rebel os=linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=newsos ;; news1000) basic_machine=m68030-sony os=newsos ;; necv70) basic_machine=v70-nec os=sysv ;; nh3000) basic_machine=m68k-harris os=cxux ;; nh[45]000) basic_machine=m88k-harris os=cxux ;; nindy960) basic_machine=i960-intel os=nindy ;; mon960) basic_machine=i960-intel os=mon960 ;; nonstopux) basic_machine=mips-compaq os=nonstopux ;; os400) basic_machine=powerpc-ibm os=os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=ose ;; os68k) basic_machine=m68k-none os=os68k ;; paragon) basic_machine=i860-intel os=osf ;; parisc) basic_machine=hppa-unknown os=linux ;; pw32) basic_machine=i586-unknown os=pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=rdos ;; rdos32) basic_machine=i386-pc os=rdos ;; rom68k) basic_machine=m68k-rom68k os=coff ;; sa29200) basic_machine=a29k-amd os=udi ;; sei) basic_machine=mips-sei os=seiux ;; sequent) basic_machine=i386-sequent os= ;; sps7) basic_machine=m68k-bull os=sysv2 ;; st2000) basic_machine=m68k-tandem os= ;; stratus) basic_machine=i860-stratus os=sysv4 ;; sun2) basic_machine=m68000-sun os= ;; sun2os3) basic_machine=m68000-sun os=sunos3 ;; sun2os4) basic_machine=m68000-sun os=sunos4 ;; sun3) basic_machine=m68k-sun os= ;; sun3os3) basic_machine=m68k-sun os=sunos3 ;; sun3os4) basic_machine=m68k-sun os=sunos4 ;; sun4) basic_machine=sparc-sun os= ;; sun4os3) basic_machine=sparc-sun os=sunos3 ;; sun4os4) basic_machine=sparc-sun os=sunos4 ;; sun4sol2) basic_machine=sparc-sun os=solaris2 ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun os= ;; sv1) basic_machine=sv1-cray os=unicos ;; symmetry) basic_machine=i386-sequent os=dynix ;; t3e) basic_machine=alphaev5-cray os=unicos ;; t90) basic_machine=t90-cray os=unicos ;; toad1) basic_machine=pdp10-xkl os=tops20 ;; tpf) basic_machine=s390x-ibm os=tpf ;; udi29k) basic_machine=a29k-amd os=udi ;; ultra3) basic_machine=a29k-nyu os=sym1 ;; v810 | necv810) basic_machine=v810-nec os=none ;; vaxv) basic_machine=vax-dec os=sysv ;; vms) basic_machine=vax-dec os=vms ;; vxworks960) basic_machine=i960-wrs os=vxworks ;; vxworks68) basic_machine=m68k-wrs os=vxworks ;; vxworks29k) basic_machine=a29k-wrs os=vxworks ;; xbox) basic_machine=i686-pc os=mingw32 ;; ymp) basic_machine=ymp-cray os=unicos ;; *) basic_machine=$1 os= ;; esac ;; esac # Decode 1-component or ad-hoc basic machines case $basic_machine in # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) cpu=hppa1.1 vendor=winbond ;; op50n) cpu=hppa1.1 vendor=oki ;; op60c) cpu=hppa1.1 vendor=oki ;; ibm*) cpu=i370 vendor=ibm ;; orion105) cpu=clipper vendor=highlevel ;; mac | mpw | mac-mpw) cpu=m68k vendor=apple ;; pmac | pmac-mpw) cpu=powerpc vendor=apple ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) cpu=m68000 vendor=att ;; 3b*) cpu=we32k vendor=att ;; bluegene*) cpu=powerpc vendor=ibm os=cnk ;; decsystem10* | dec10*) cpu=pdp10 vendor=dec os=tops10 ;; decsystem20* | dec20*) cpu=pdp10 vendor=dec os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) cpu=m68k vendor=motorola ;; dpx2*) cpu=m68k vendor=bull os=sysv3 ;; encore | umax | mmax) cpu=ns32k vendor=encore ;; elxsi) cpu=elxsi vendor=elxsi os=${os:-bsd} ;; fx2800) cpu=i860 vendor=alliant ;; genix) cpu=ns32k vendor=ns ;; h3050r* | hiux*) cpu=hppa1.1 vendor=hitachi os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) cpu=m68000 vendor=hp ;; hp9k3[2-9][0-9]) cpu=m68k vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) cpu=hppa1.1 vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; i*86v32) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc os=sysv32 ;; i*86v4*) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc os=sysv4 ;; i*86v) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc os=sysv ;; i*86sol2) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc os=solaris2 ;; j90 | j90-cray) cpu=j90 vendor=cray os=${os:-unicos} ;; iris | iris4d) cpu=mips vendor=sgi case $os in irix*) ;; *) os=irix4 ;; esac ;; miniframe) cpu=m68000 vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) cpu=m68k vendor=atari os=mint ;; news-3600 | risc-news) cpu=mips vendor=sony os=newsos ;; next | m*-next) cpu=m68k vendor=next case $os in nextstep* ) ;; ns2*) os=nextstep2 ;; *) os=nextstep3 ;; esac ;; np1) cpu=np1 vendor=gould ;; op50n-* | op60c-*) cpu=hppa1.1 vendor=oki os=proelf ;; pa-hitachi) cpu=hppa1.1 vendor=hitachi os=hiuxwe2 ;; pbd) cpu=sparc vendor=tti ;; pbb) cpu=m68k vendor=tti ;; pc532) cpu=ns32k vendor=pc532 ;; pn) cpu=pn vendor=gould ;; power) cpu=power vendor=ibm ;; ps2) cpu=i386 vendor=ibm ;; rm[46]00) cpu=mips vendor=siemens ;; rtpc | rtpc-*) cpu=romp vendor=ibm ;; sde) cpu=mipsisa32 vendor=sde os=${os:-elf} ;; simso-wrs) cpu=sparclite vendor=wrs os=vxworks ;; tower | tower-32) cpu=m68k vendor=ncr ;; vpp*|vx|vx-*) cpu=f301 vendor=fujitsu ;; w65) cpu=w65 vendor=wdc ;; w89k-*) cpu=hppa1.1 vendor=winbond os=proelf ;; none) cpu=none vendor=none ;; leon|leon[3-9]) cpu=sparc vendor=$basic_machine ;; leon-*|leon[3-9]-*) cpu=sparc vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; *-*) IFS="-" read -r cpu vendor <&2 exit 1 ;; esac ;; esac # Here we canonicalize certain aliases for manufacturers. case $vendor in digital*) vendor=dec ;; commodore*) vendor=cbm ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x$os != x ] then case $os in # First match some system type aliases that might get confused # with valid system types. # solaris* is a basic system type, with this one exception. auroraux) os=auroraux ;; bluegene*) os=cnk ;; solaris1 | solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; solaris) os=solaris2 ;; unixware*) os=sysv4.2uw ;; gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # es1800 is here to avoid being matched by es* (a different OS) es1800*) os=ose ;; # Some version numbers need modification chorusos*) os=chorusos ;; isc) os=isc2.2 ;; sco6) os=sco5v6 ;; sco5) os=sco3.2v5 ;; sco4) os=sco3.2v4 ;; sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` ;; sco3.2v[4-9]* | sco5v6*) # Don't forget version if it is 3.2v4 or newer. ;; scout) # Don't match below ;; sco*) os=sco3.2v2 ;; psos*) os=psos ;; # Now accept the basic system types. # The portable systems comes first. # Each alternative MUST end in a * to match a version number. # sysv* is not here because it comes later, after sysvr4. gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\ | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ | sym* | kopensolaris* | plan9* \ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ | aos* | aros* | cloudabi* | sortix* \ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ | knetbsd* | mirbsd* | netbsd* \ | bitrig* | openbsd* | solidbsd* | libertybsd* \ | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \ | chorusrdb* | cegcc* | glidix* \ | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \ | linux-newlib* | linux-musl* | linux-uclibc* \ | uxpv* | beos* | mpeix* | udk* | moxiebox* \ | interix* | uwin* | mks* | rhapsody* | darwin* \ | openstep* | oskit* | conix* | pw32* | nonstopux* \ | storm-chaos* | tops10* | tenex* | tops20* | its* \ | os2* | vos* | palmos* | uclinux* | nucleus* \ | morphos* | superux* | rtmk* | windiss* \ | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ | skyos* | haiku* | rdos* | toppers* | drops* | es* \ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ | midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; qnx*) case $cpu in x86 | i*86) ;; *) os=nto-$os ;; esac ;; hiux*) os=hiuxwe2 ;; nto-qnx*) ;; nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; sim | xray | os68k* | v88r* \ | windows* | osx | abug | netware* | os9* \ | macos* | mpw* | magic* | mmixware* | mon960* | lnews*) ;; linux-dietlibc) os=linux-dietlibc ;; linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; lynx*178) os=lynxos178 ;; lynx*5) os=lynxos5 ;; lynx*) os=lynxos ;; mac*) os=`echo "$os" | sed -e 's|mac|macos|'` ;; opened*) os=openedition ;; os400*) os=os400 ;; sunos5*) os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; sunos6*) os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; wince*) os=wince ;; utek*) os=bsd ;; dynix*) os=bsd ;; acis*) os=aos ;; atheos*) os=atheos ;; syllable*) os=syllable ;; 386bsd) os=bsd ;; ctix* | uts*) os=sysv ;; nova*) os=rtmk-nova ;; ns2) os=nextstep2 ;; nsk*) os=nsk ;; # Preserve the version number of sinix5. sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; sinix*) os=sysv4 ;; tpf*) os=tpf ;; triton*) os=sysv3 ;; oss*) os=sysv3 ;; svr4*) os=sysv4 ;; svr3) os=sysv3 ;; sysvr4) os=sysv4 ;; # This must come after sysvr4. sysv*) ;; ose*) os=ose ;; *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) os=mint ;; zvmoe) os=zvmoe ;; dicos*) os=dicos ;; pikeos*) # Until real need of OS specific support for # particular features comes up, bare metal # configurations are quite functional. case $cpu in arm*) os=eabi ;; *) os=elf ;; esac ;; nacl*) ;; ios) ;; none) ;; *-eabi) ;; *) echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $cpu-$vendor in score-*) os=elf ;; spu-*) os=elf ;; *-acorn) os=riscix1.2 ;; arm*-rebel) os=linux ;; arm*-semi) os=aout ;; c4x-* | tic4x-*) os=coff ;; c8051-*) os=elf ;; clipper-intergraph) os=clix ;; hexagon-*) os=elf ;; tic54x-*) os=coff ;; tic55x-*) os=coff ;; tic6x-*) os=coff ;; # This must come before the *-dec entry. pdp10-*) os=tops20 ;; pdp11-*) os=none ;; *-dec | vax-*) os=ultrix4.2 ;; m68*-apollo) os=domain ;; i386-sun) os=sunos4.0.2 ;; m68000-sun) os=sunos3 ;; m68*-cisco) os=aout ;; mep-*) os=elf ;; mips*-cisco) os=elf ;; mips*-*) os=elf ;; or32-*) os=coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=sysv3 ;; sparc-* | *-sun) os=sunos4.1.1 ;; pru-*) os=elf ;; *-be) os=beos ;; *-ibm) os=aix ;; *-knuth) os=mmixware ;; *-wec) os=proelf ;; *-winbond) os=proelf ;; *-oki) os=proelf ;; *-hp) os=hpux ;; *-hitachi) os=hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=sysv ;; *-cbm) os=amigaos ;; *-dg) os=dgux ;; *-dolphin) os=sysv3 ;; m68k-ccur) os=rtu ;; m88k-omron*) os=luna ;; *-next) os=nextstep ;; *-sequent) os=ptx ;; *-crds) os=unos ;; *-ns) os=genix ;; i370-*) os=mvs ;; *-gould) os=sysv ;; *-highlevel) os=bsd ;; *-encore) os=bsd ;; *-sgi) os=irix ;; *-siemens) os=sysv4 ;; *-masscomp) os=rtu ;; f30[01]-fujitsu | f700-fujitsu) os=uxpv ;; *-rom68k) os=coff ;; *-*bug) os=coff ;; *-apple) os=macos ;; *-atari*) os=mint ;; *-wrs) os=vxworks ;; *) os=none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. case $vendor in unknown) case $os in riscix*) vendor=acorn ;; sunos*) vendor=sun ;; cnk*|-aix*) vendor=ibm ;; beos*) vendor=be ;; hpux*) vendor=hp ;; mpeix*) vendor=hp ;; hiux*) vendor=hitachi ;; unos*) vendor=crds ;; dgux*) vendor=dg ;; luna*) vendor=omron ;; genix*) vendor=ns ;; clix*) vendor=intergraph ;; mvs* | opened*) vendor=ibm ;; os400*) vendor=ibm ;; ptx*) vendor=sequent ;; tpf*) vendor=ibm ;; vxsim* | vxworks* | windiss*) vendor=wrs ;; aux*) vendor=apple ;; hms*) vendor=hitachi ;; mpw* | macos*) vendor=apple ;; *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) vendor=atari ;; vos*) vendor=stratus ;; esac ;; esac echo "$cpu-$vendor-$os" exit # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: guacamole-server-1.3.0/build-aux/tap-driver.sh0000755000175100001440000004601313772471101016207 00000000000000#! /bin/sh # Copyright (C) 2011-2018 Free Software Foundation, Inc. # # 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, 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, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . scriptversion=2013-12-23.17; # UTC # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u me=tap-driver.sh fatal () { echo "$me: fatal: $*" >&2 exit 1 } usage_error () { echo "$me: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat < # trap : 1 3 2 13 15 if test $merge -gt 0; then exec 2>&1 else exec 2>&3 fi "$@" echo $? ) | LC_ALL=C ${AM_TAP_AWK-awk} \ -v me="$me" \ -v test_script_name="$test_name" \ -v log_file="$log_file" \ -v trs_file="$trs_file" \ -v expect_failure="$expect_failure" \ -v merge="$merge" \ -v ignore_exit="$ignore_exit" \ -v comments="$comments" \ -v diag_string="$diag_string" \ ' # TODO: the usages of "cat >&3" below could be optimized when using # GNU awk, and/on on systems that supports /dev/fd/. # Implementation note: in what follows, `result_obj` will be an # associative array that (partly) simulates a TAP result object # from the `TAP::Parser` perl module. ## ----------- ## ## FUNCTIONS ## ## ----------- ## function fatal(msg) { print me ": " msg | "cat >&2" exit 1 } function abort(where) { fatal("internal error " where) } # Convert a boolean to a "yes"/"no" string. function yn(bool) { return bool ? "yes" : "no"; } function add_test_result(result) { if (!test_results_index) test_results_index = 0 test_results_list[test_results_index] = result test_results_index += 1 test_results_seen[result] = 1; } # Whether the test script should be re-run by "make recheck". function must_recheck() { for (k in test_results_seen) if (k != "XFAIL" && k != "PASS" && k != "SKIP") return 1 return 0 } # Whether the content of the log file associated to this test should # be copied into the "global" test-suite.log. function copy_in_global_log() { for (k in test_results_seen) if (k != "PASS") return 1 return 0 } function get_global_test_result() { if ("ERROR" in test_results_seen) return "ERROR" if ("FAIL" in test_results_seen || "XPASS" in test_results_seen) return "FAIL" all_skipped = 1 for (k in test_results_seen) if (k != "SKIP") all_skipped = 0 if (all_skipped) return "SKIP" return "PASS"; } function stringify_result_obj(result_obj) { if (result_obj["is_unplanned"] || result_obj["number"] != testno) return "ERROR" if (plan_seen == LATE_PLAN) return "ERROR" if (result_obj["directive"] == "TODO") return result_obj["is_ok"] ? "XPASS" : "XFAIL" if (result_obj["directive"] == "SKIP") return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL; if (length(result_obj["directive"])) abort("in function stringify_result_obj()") return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL } function decorate_result(result) { color_name = color_for_result[result] if (color_name) return color_map[color_name] "" result "" color_map["std"] # If we are not using colorized output, or if we do not know how # to colorize the given result, we should return it unchanged. return result } function report(result, details) { if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/) { msg = ": " test_script_name add_test_result(result) } else if (result == "#") { msg = " " test_script_name ":" } else { abort("in function report()") } if (length(details)) msg = msg " " details # Output on console might be colorized. print decorate_result(result) msg # Log the result in the log file too, to help debugging (this is # especially true when said result is a TAP error or "Bail out!"). print result msg | "cat >&3"; } function testsuite_error(error_message) { report("ERROR", "- " error_message) } function handle_tap_result() { details = result_obj["number"]; if (length(result_obj["description"])) details = details " " result_obj["description"] if (plan_seen == LATE_PLAN) { details = details " # AFTER LATE PLAN"; } else if (result_obj["is_unplanned"]) { details = details " # UNPLANNED"; } else if (result_obj["number"] != testno) { details = sprintf("%s # OUT-OF-ORDER (expecting %d)", details, testno); } else if (result_obj["directive"]) { details = details " # " result_obj["directive"]; if (length(result_obj["explanation"])) details = details " " result_obj["explanation"] } report(stringify_result_obj(result_obj), details) } # `skip_reason` should be empty whenever planned > 0. function handle_tap_plan(planned, skip_reason) { planned += 0 # Avoid getting confused if, say, `planned` is "00" if (length(skip_reason) && planned > 0) abort("in function handle_tap_plan()") if (plan_seen) { # Error, only one plan per stream is acceptable. testsuite_error("multiple test plans") return; } planned_tests = planned # The TAP plan can come before or after *all* the TAP results; we speak # respectively of an "early" or a "late" plan. If we see the plan line # after at least one TAP result has been seen, assume we have a late # plan; in this case, any further test result seen after the plan will # be flagged as an error. plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN) # If testno > 0, we have an error ("too many tests run") that will be # automatically dealt with later, so do not worry about it here. If # $plan_seen is true, we have an error due to a repeated plan, and that # has already been dealt with above. Otherwise, we have a valid "plan # with SKIP" specification, and should report it as a particular kind # of SKIP result. if (planned == 0 && testno == 0) { if (length(skip_reason)) skip_reason = "- " skip_reason; report("SKIP", skip_reason); } } function extract_tap_comment(line) { if (index(line, diag_string) == 1) { # Strip leading `diag_string` from `line`. line = substr(line, length(diag_string) + 1) # And strip any leading and trailing whitespace left. sub("^[ \t]*", "", line) sub("[ \t]*$", "", line) # Return what is left (if any). return line; } return ""; } # When this function is called, we know that line is a TAP result line, # so that it matches the (perl) RE "^(not )?ok\b". function setup_result_obj(line) { # Get the result, and remove it from the line. result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0) sub("^(not )?ok[ \t]*", "", line) # If the result has an explicit number, get it and strip it; otherwise, # automatically assing the next progresive number to it. if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/) { match(line, "^[0-9]+") # The final `+ 0` is to normalize numbers with leading zeros. result_obj["number"] = substr(line, 1, RLENGTH) + 0 line = substr(line, RLENGTH + 1) } else { result_obj["number"] = testno } if (plan_seen == LATE_PLAN) # No further test results are acceptable after a "late" TAP plan # has been seen. result_obj["is_unplanned"] = 1 else if (plan_seen && testno > planned_tests) result_obj["is_unplanned"] = 1 else result_obj["is_unplanned"] = 0 # Strip trailing and leading whitespace. sub("^[ \t]*", "", line) sub("[ \t]*$", "", line) # This will have to be corrected if we have a "TODO"/"SKIP" directive. result_obj["description"] = line result_obj["directive"] = "" result_obj["explanation"] = "" if (index(line, "#") == 0) return # No possible directive, nothing more to do. # Directives are case-insensitive. rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*" # See whether we have the directive, and if yes, where. pos = match(line, rx "$") if (!pos) pos = match(line, rx "[^a-zA-Z0-9_]") # If there was no TAP directive, we have nothing more to do. if (!pos) return # Let`s now see if the TAP directive has been escaped. For example: # escaped: ok \# SKIP # not escaped: ok \\# SKIP # escaped: ok \\\\\# SKIP # not escaped: ok \ # SKIP if (substr(line, pos, 1) == "#") { bslash_count = 0 for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--) bslash_count += 1 if (bslash_count % 2) return # Directive was escaped. } # Strip the directive and its explanation (if any) from the test # description. result_obj["description"] = substr(line, 1, pos - 1) # Now remove the test description from the line, that has been dealt # with already. line = substr(line, pos) # Strip the directive, and save its value (normalized to upper case). sub("^[ \t]*#[ \t]*", "", line) result_obj["directive"] = toupper(substr(line, 1, 4)) line = substr(line, 5) # Now get the explanation for the directive (if any), with leading # and trailing whitespace removed. sub("^[ \t]*", "", line) sub("[ \t]*$", "", line) result_obj["explanation"] = line } function get_test_exit_message(status) { if (status == 0) return "" if (status !~ /^[1-9][0-9]*$/) abort("getting exit status") if (status < 127) exit_details = "" else if (status == 127) exit_details = " (command not found?)" else if (status >= 128 && status <= 255) exit_details = sprintf(" (terminated by signal %d?)", status - 128) else if (status > 256 && status <= 384) # We used to report an "abnormal termination" here, but some Korn # shells, when a child process die due to signal number n, can leave # in $? an exit status of 256+n instead of the more standard 128+n. # Apparently, both behaviours are allowed by POSIX (2008), so be # prepared to handle them both. See also Austing Group report ID # 0000051 exit_details = sprintf(" (terminated by signal %d?)", status - 256) else # Never seen in practice. exit_details = " (abnormal termination)" return sprintf("exited with status %d%s", status, exit_details) } function write_test_results() { print ":global-test-result: " get_global_test_result() > trs_file print ":recheck: " yn(must_recheck()) > trs_file print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file for (i = 0; i < test_results_index; i += 1) print ":test-result: " test_results_list[i] > trs_file close(trs_file); } BEGIN { ## ------- ## ## SETUP ## ## ------- ## '"$init_colors"' # Properly initialized once the TAP plan is seen. planned_tests = 0 COOKED_PASS = expect_failure ? "XPASS": "PASS"; COOKED_FAIL = expect_failure ? "XFAIL": "FAIL"; # Enumeration-like constants to remember which kind of plan (if any) # has been seen. It is important that NO_PLAN evaluates "false" as # a boolean. NO_PLAN = 0 EARLY_PLAN = 1 LATE_PLAN = 2 testno = 0 # Number of test results seen so far. bailed_out = 0 # Whether a "Bail out!" directive has been seen. # Whether the TAP plan has been seen or not, and if yes, which kind # it is ("early" is seen before any test result, "late" otherwise). plan_seen = NO_PLAN ## --------- ## ## PARSING ## ## --------- ## is_first_read = 1 while (1) { # Involutions required so that we are able to read the exit status # from the last input line. st = getline if (st < 0) # I/O error. fatal("I/O error while reading from input stream") else if (st == 0) # End-of-input { if (is_first_read) abort("in input loop: only one input line") break } if (is_first_read) { is_first_read = 0 nextline = $0 continue } else { curline = nextline nextline = $0 $0 = curline } # Copy any input line verbatim into the log file. print | "cat >&3" # Parsing of TAP input should stop after a "Bail out!" directive. if (bailed_out) continue # TAP test result. if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/) { testno += 1 setup_result_obj($0) handle_tap_result() } # TAP plan (normal or "SKIP" without explanation). else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/) { # The next two lines will put the number of planned tests in $0. sub("^1\\.\\.", "") sub("[^0-9]*$", "") handle_tap_plan($0, "") continue } # TAP "SKIP" plan, with an explanation. else if ($0 ~ /^1\.\.0+[ \t]*#/) { # The next lines will put the skip explanation in $0, stripping # any leading and trailing whitespace. This is a little more # tricky in truth, since we want to also strip a potential leading # "SKIP" string from the message. sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "") sub("[ \t]*$", ""); handle_tap_plan(0, $0) } # "Bail out!" magic. # Older versions of prove and TAP::Harness (e.g., 3.17) did not # recognize a "Bail out!" directive when preceded by leading # whitespace, but more modern versions (e.g., 3.23) do. So we # emulate the latter, "more modern" behaviour. else if ($0 ~ /^[ \t]*Bail out!/) { bailed_out = 1 # Get the bailout message (if any), with leading and trailing # whitespace stripped. The message remains stored in `$0`. sub("^[ \t]*Bail out![ \t]*", ""); sub("[ \t]*$", ""); # Format the error message for the bailout_message = "Bail out!" if (length($0)) bailout_message = bailout_message " " $0 testsuite_error(bailout_message) } # Maybe we have too look for dianogtic comments too. else if (comments != 0) { comment = extract_tap_comment($0); if (length(comment)) report("#", comment); } } ## -------- ## ## FINISH ## ## -------- ## # A "Bail out!" directive should cause us to ignore any following TAP # error, as well as a non-zero exit status from the TAP producer. if (!bailed_out) { if (!plan_seen) { testsuite_error("missing test plan") } else if (planned_tests != testno) { bad_amount = testno > planned_tests ? "many" : "few" testsuite_error(sprintf("too %s tests run (expected %d, got %d)", bad_amount, planned_tests, testno)) } if (!ignore_exit) { # Fetch exit status from the last line. exit_message = get_test_exit_message(nextline) if (exit_message) testsuite_error(exit_message) } } write_test_results() exit 0 } # End of "BEGIN" block. ' # TODO: document that we consume the file descriptor 3 :-( } 3>"$log_file" test $? -eq 0 || fatal "I/O or internal error" # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: guacamole-server-1.3.0/build-aux/config.guess0000755000175100001440000012617313772471101016121 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2018 Free Software Foundation, Inc. timestamp='2018-08-29' # This file 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 3 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, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. tmp= # shellcheck disable=SC2172 trap 'test -z "$tmp" || rm -fr "$tmp"' 1 2 13 15 trap 'exitcode=$?; test -z "$tmp" || rm -fr "$tmp"; exit $exitcode' 0 set_cc_for_build() { : "${TMPDIR=/tmp}" # shellcheck disable=SC2039 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } dummy=$tmp/dummy case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in ,,) echo "int x;" > "$dummy.c" for driver in cc gcc c89 c99 ; do if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$driver" break fi done if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac } # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "$UNAME_SYSTEM" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu set_cc_for_build cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" # If ldd exists, use it to detect musl libc. if command -v ldd >/dev/null && \ ldd --version 2>&1 | grep -q ^musl then LIBC=musl fi ;; esac # Note: order is significant - the case branches are not exclusive. case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ "/sbin/$sysctl" 2>/dev/null || \ "/usr/sbin/$sysctl" 2>/dev/null || \ echo unknown)` case "$UNAME_MACHINE_ARCH" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` machine="${arch}${endian}"-unknown ;; *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case "$UNAME_MACHINE_ARCH" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case "$UNAME_MACHINE_ARCH" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "$machine-${os}${release}${abi-}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" exit ;; *:MidnightBSD:*:*) echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:Sortix:*:*) echo "$UNAME_MACHINE"-unknown-sortix exit ;; *:Redox:*:*) echo "$UNAME_MACHINE"-unknown-redox exit ;; mips:OSF1:*.*) echo mips-dec-osf1 exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) UNAME_REL="`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" case `isainfo -b` in 32) echo i386-pc-solaris2"$UNAME_REL" ;; 64) echo x86_64-pc-solaris2"$UNAME_REL" ;; esac exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ [ "$TARGET_BINARY_INTERFACE"x = x ] then echo m88k-dg-dgux"$UNAME_RELEASE" else echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/lslpp ] ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` case "$UNAME_MACHINE" in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "$sc_cpu_version" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "$sc_kernel_bits" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if [ "$HP_ARCH" = "" ]; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ "$HP_ARCH" = hppa2.0w ] then set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo "$UNAME_MACHINE"-unknown-osf1mk else echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; arm:FreeBSD:*:*) UNAME_PROCESSOR=`uname -p` set_cc_for_build if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi else echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf fi exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case "$UNAME_PROCESSOR" in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) echo "$UNAME_MACHINE"-pc-cygwin exit ;; *:MINGW64*:*) echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) echo "$UNAME_MACHINE"-pc-mingw32 exit ;; *:MSYS*:*) echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) case "$UNAME_MACHINE" in x86) echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; i*:UWIN*:*) echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; *:Minix:*:*) echo "$UNAME_MACHINE"-unknown-minix exit ;; aarch64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; e2k:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; k1om:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } ;; mips64el:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-"$LIBC" exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-"$LIBC" exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-"$LIBC" exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; xtensa*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv"$UNAME_RELEASE" else echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux"$UNAME_RELEASE" exit ;; SX-ACE:SUPER-UX:*:*) echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-*:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk"$UNAME_RELEASE" exit ;; NSR-*:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk"$UNAME_RELEASE" exit ;; NSV-*:NONSTOP_KERNEL:*:*) echo nsv-tandem-nsk"$UNAME_RELEASE" exit ;; NSX-*:NONSTOP_KERNEL:*:*) echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. # shellcheck disable=SC2154 if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) echo "$UNAME_MACHINE"-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac echo "$0: unable to guess system type" >&2 case "$UNAME_MACHINE:$UNAME_SYSTEM" in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = "$UNAME_MACHINE" UNAME_RELEASE = "$UNAME_RELEASE" UNAME_SYSTEM = "$UNAME_SYSTEM" UNAME_VERSION = "$UNAME_VERSION" EOF exit 1 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: guacamole-server-1.3.0/build-aux/install-sh0000755000175100001440000003601013772471101015573 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2018-03-11.20; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) # Note that $RANDOM variable is not portable (e.g. dash); Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writeable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p' feature. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: guacamole-server-1.3.0/build-aux/test-driver0000755000175100001440000001104213772471102015764 00000000000000#! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2018-03-07.03; # UTC # Copyright (C) 2011-2018 Free Software Foundation, Inc. # # 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, 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, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <$log_file 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then tweaked_estatus=1 else tweaked_estatus=$estatus fi case $tweaked_estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report the test outcome and exit status in the logs, so that one can # know whether the test passed or failed simply by looking at the '.log' # file, without the need of also peaking into the corresponding '.trs' # file (automake bug#11814). echo "$res $test_name (exit status: $estatus)" >>$log_file # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: guacamole-server-1.3.0/src/0000755000175100001440000000000013772471157012557 500000000000000guacamole-server-1.3.0/src/common-ssh/0000755000175100001440000000000013772471156014641 500000000000000guacamole-server-1.3.0/src/common-ssh/common-ssh/0000755000175100001440000000000013772471156016724 500000000000000guacamole-server-1.3.0/src/common-ssh/common-ssh/user.h0000644000175100001440000000634113613156714017771 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_SSH_USER_H #define GUAC_COMMON_SSH_USER_H #include "key.h" /** * Data describing an SSH user, including their credentials. */ typedef struct guac_common_ssh_user { /** * The username of this user. */ char* username; /** * The password which should be used to authenticate this user, if any, or * NULL if a private key will be used instead. */ char* password; /** * The private key which should be used to authenticate this user, if any, * or NULL if a password will be used instead. */ guac_common_ssh_key* private_key; } guac_common_ssh_user; /** * Creates a new SSH user with the given username. When additionally populated * with a password or private key, this user can then be used for * authentication. * * @param username * The username of the user being created. * * @return * A new SSH user having the given username, but no associated password * or private key. */ guac_common_ssh_user* guac_common_ssh_create_user(const char* username); /** * Destroys the given user object, releasing all associated resources. * * @param user * The user to destroy. */ void guac_common_ssh_destroy_user(guac_common_ssh_user* user); /** * Associates the given user with the given password, such that that password * is used for future authentication attempts. * * @param user * The user to associate with the given password. * * @param password * The password to associate with the given user. */ void guac_common_ssh_user_set_password(guac_common_ssh_user* user, const char* password); /** * Imports the given private key, associating that key with the given user. If * necessary to decrypt the key, a passphrase may be specified. The private key * must be provided in base64 form. If the private key is imported * successfully, it will be used for future authentication attempts. * * @param user * The user to associate with the given private key. * * @param private_key * The base64-encoded private key to import. * * @param passphrase * The passphrase to use to decrypt the given private key, or NULL if no * passphrase should be used. * * @return * Zero if the private key is successfully imported, or non-zero if the * private key could not be imported due to an error. */ int guac_common_ssh_user_import_key(guac_common_ssh_user* user, char* private_key, char* passphrase); #endif guacamole-server-1.3.0/src/common-ssh/common-ssh/sftp.h0000644000175100001440000002365513764613616020004 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_SSH_SFTP_H #define GUAC_COMMON_SSH_SFTP_H #include "common/json.h" #include "ssh.h" #include #include #include #include /** * Maximum number of bytes per path. */ #define GUAC_COMMON_SSH_SFTP_MAX_PATH 2048 /** * Maximum number of path components per path. */ #define GUAC_COMMON_SSH_SFTP_MAX_DEPTH 1024 /** * Representation of an SFTP-driven filesystem object. Unlike guac_object, this * structure is not tied to any particular user. */ typedef struct guac_common_ssh_sftp_filesystem { /** * The human-readable display name of this filesystem. */ char* name; /** * The distinct SSH session used for SFTP. */ guac_common_ssh_session* ssh_session; /** * SFTP session, used for file transfers. */ LIBSSH2_SFTP* sftp_session; /** * The path to the directory to expose to the user as a filesystem object. */ char root_path[GUAC_COMMON_SSH_SFTP_MAX_PATH]; /** * The path files will be sent to, if uploaded directly via a "file" * instruction. */ char upload_path[GUAC_COMMON_SSH_SFTP_MAX_PATH]; /** * If downloads from SFTP to the local browser should be disabled. */ int disable_download; /** * If uploads from the local browser to SFTP should be disabled. */ int disable_upload; } guac_common_ssh_sftp_filesystem; /** * The current state of a directory listing operation. */ typedef struct guac_common_ssh_sftp_ls_state { /** * The SFTP filesystem being listed. */ guac_common_ssh_sftp_filesystem* filesystem; /** * Reference to the directory currently being listed over SFTP. This * directory must already be open from a call to libssh2_sftp_opendir(). */ LIBSSH2_SFTP_HANDLE* directory; /** * The absolute path of the directory being listed. */ char directory_name[GUAC_COMMON_SSH_SFTP_MAX_PATH]; /** * The current state of the JSON directory object being written. */ guac_common_json_state json_state; } guac_common_ssh_sftp_ls_state; /** * Creates a new Guacamole filesystem object which provides access to files * and directories via SFTP using the given SSH session. When the filesystem * will no longer be used, it must be explicitly destroyed with * guac_common_ssh_destroy_sftp_filesystem(). The resulting object is not * automatically exposed to users of the connection - filesystem operations * must be mediated either through various handlers or through exposing a * filesystem guac_object via guac_common_ssh_alloc_sftp_filesystem_object(). * * @param session * The session to use to provide SFTP. This session will automatically be * destroyed when this filesystem is destroyed. * * @param root_path * The path accessible via SFTP to consider the root path of the filesystem * exposed to the user. Only the contents of this path will be available * via the filesystem object. * * @param name * The name to send as the name of the filesystem whenever it is exposed * to a user, or NULL to automatically generate a name from the provided * root_path. * * @param disable_download * Whether downloads from the SFTP share to the local browser should be * disabled. * * @param disable_upload * Whether uploads from the local browser to SFTP should be disabled. * * @return * A new SFTP filesystem object, not yet exposed to users. */ guac_common_ssh_sftp_filesystem* guac_common_ssh_create_sftp_filesystem( guac_common_ssh_session* session, const char* root_path, const char* name, int disable_download, int disable_upload); /** * Destroys the given filesystem object, disconnecting from SFTP and freeing * and associated resources. Any associated session or user objects must be * explicitly destroyed. * * @param filesystem * The filesystem object to destroy. */ void guac_common_ssh_destroy_sftp_filesystem( guac_common_ssh_sftp_filesystem* filesystem); /** * Creates and exposes a new filesystem guac_object to the given user, * providing access to the files within the given SFTP filesystem. The * allocated guac_object must eventually be freed via guac_user_free_object(). * * @param filesystem * The filesystem object to expose. * * @param user * The user that the SFTP filesystem should be exposed to. * * @return * A new Guacamole filesystem object, configured to use SFTP for uploading * and downloading files. */ guac_object* guac_common_ssh_alloc_sftp_filesystem_object( guac_common_ssh_sftp_filesystem* filesystem, guac_user* user); /** * Allocates a new filesystem guac_object for the given user, returning the * resulting guac_object. This function is provided for convenience, as it is * can be used as the callback for guac_client_foreach_user() or * guac_client_for_owner(). Note that this guac_object will be tracked * internally by libguac, will be provided to us in the parameters of handlers * related to that guac_object, and will automatically be freed when the * associated guac_user is freed, so the return value of this function can * safely be ignored. * * If either the given user or the given filesystem are NULL, then this * function has no effect. * * @param user * The use to expose the filesystem to, or NULL if nothing should be * exposed. * * @param data * A pointer to the guac_common_ssh_sftp_filesystem instance to expose * to the given user, or NULL if nothing should be exposed. * * @return * The guac_object allocated for the newly-exposed filesystem, or NULL if * no filesystem object could be allocated. */ void* guac_common_ssh_expose_sftp_filesystem(guac_user* user, void* data); /** * Initiates an SFTP file download to the user via the Guacamole "file" * instruction. The download will be automatically monitored and continued * after this function terminates in response to "ack" instructions received by * the user. * * @param filesystem * The filesystem containing the file to be downloaded. * * @param user * The user that should receive the file (via a "file" instruction). * * @param filename * The filename of the file to download, relative to the given filesystem. * * @return * The file stream created for the file download, already configured to * properly handle "ack" responses, etc. from the user. */ guac_stream* guac_common_ssh_sftp_download_file( guac_common_ssh_sftp_filesystem* filesystem, guac_user* user, char* filename); /** * Handles an incoming stream from a Guacamole "file" instruction, saving the * contents of that stream to the file having the given name within the * upload directory set by guac_common_ssh_sftp_set_upload_path(). * * @param filesystem * The filesystem that should receive the uploaded file. * * @param user * The user who is attempting to open the file stream (the user that sent * the "file" instruction). * * @param stream * The stream through which the uploaded file data will be received. * * @param mimetype * The mimetype of the data being received. * * @param filename * The filename of the file to write to. This filename will always be taken * relative to the upload path set by * guac_common_ssh_sftp_set_upload_path(). * * @return * Zero if the incoming stream has been handled successfully, non-zero on * failure. */ int guac_common_ssh_sftp_handle_file_stream( guac_common_ssh_sftp_filesystem* filesystem, guac_user* user, guac_stream* stream, char* mimetype, char* filename); /** * Set the destination directory for future uploads submitted via * guac_common_ssh_sftp_handle_file_stream(). This function has no bearing * on the destination directories of files uploaded with "put" instructions. * * @param filesystem * The filesystem to set the upload path of. * * @param path * The path to use for future uploads submitted via the * guac_common_ssh_sftp_handle_file_stream() function. */ void guac_common_ssh_sftp_set_upload_path( guac_common_ssh_sftp_filesystem* filesystem, const char* path); /** * Given an arbitrary absolute path, which may contain "..", ".", and * backslashes, creates an equivalent absolute path which does NOT contain * relative path components (".." or "."), backslashes, or empty path * components. With the exception of paths referring to the root directory, the * resulting path is guaranteed to not contain trailing slashes. * * Normalization will fail if the given path is not absolute, is too long, or * contains more than GUAC_COMMON_SSH_SFTP_MAX_DEPTH path components. * * @param fullpath * The buffer to populate with the normalized path. The normalized path * will not contain relative path components like ".." or ".", nor will it * contain backslashes. This buffer MUST be at least * GUAC_COMMON_SSH_SFTP_MAX_PATH bytes in size. * * @param path * The absolute path to normalize. * * @return * Non-zero if normalization succeeded, zero otherwise. */ int guac_common_ssh_sftp_normalize_path(char* fullpath, const char* path); #endif guacamole-server-1.3.0/src/common-ssh/common-ssh/dsa-compat.h0000644000175100001440000000352313676721353021050 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_SSH_DSA_COMPAT_H #define GUAC_COMMON_SSH_DSA_COMPAT_H #include "config.h" #include #include #ifndef HAVE_DSA_GET0_PQG /** * DSA_get0_pqg() implementation for versions of OpenSSL which lack this * function (pre 1.1). * * See: https://www.openssl.org/docs/man1.1.0/crypto/DSA_get0_pqg.html */ void DSA_get0_pqg(const DSA* dsa_key, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g); #endif #ifndef HAVE_DSA_GET0_KEY /** * DSA_get0_key() implementation for versions of OpenSSL which lack this * function (pre 1.1). * * See: https://www.openssl.org/docs/man1.1.0/crypto/DSA_get0_key.html */ void DSA_get0_key(const DSA* dsa_key, const BIGNUM** pub_key, const BIGNUM** priv_key); #endif #ifndef HAVE_DSA_SIG_GET0 /** * DSA_SIG_get0() implementation for versions of OpenSSL which lack this * function (pre 1.1). * * See: https://www.openssl.org/docs/man1.1.0/crypto/DSA_SIG_get0.html */ void DSA_SIG_get0(const DSA_SIG* dsa_sig, const BIGNUM** r, const BIGNUM** s); #endif #endif guacamole-server-1.3.0/src/common-ssh/common-ssh/buffer.h0000644000175100001440000000706113676721353020272 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_SSH_BUFFER_H #define GUAC_COMMON_SSH_BUFFER_H #include "config.h" #include #include /** * Writes the given byte to the given buffer, advancing the buffer pointer by * one byte. * * @param buffer * The buffer to write to. * * @param value * The value to write. */ void guac_common_ssh_buffer_write_byte(char** buffer, uint8_t value); /** * Writes the given integer to the given buffer, advancing the buffer pointer * four bytes. * * @param buffer * The buffer to write to. * * @param value * The value to write. */ void guac_common_ssh_buffer_write_uint32(char** buffer, uint32_t value); /** * Writes the given string and its length to the given buffer, advancing the * buffer pointer by the size of the length (four bytes) and the size of the * string. * * @param buffer * The buffer to write to. * * @param string * The string value to write. * * @param length * The length of the string to write, in bytes. */ void guac_common_ssh_buffer_write_string(char** buffer, const char* string, int length); /** * Writes the given BIGNUM the given buffer, advancing the buffer pointer by * the size of the length (four bytes) and the size of the BIGNUM. * * @param buffer * The buffer to write to. * * @param value * The value to write. */ void guac_common_ssh_buffer_write_bignum(char** buffer, const BIGNUM* value); /** * Writes the given data the given buffer, advancing the buffer pointer by the * given length. * * @param data * The arbitrary data to write. * * @param length * The length of data to write, in bytes. */ void guac_common_ssh_buffer_write_data(char** buffer, const char* data, int length); /** * Reads a single byte from the given buffer, advancing the buffer by one byte. * * @param buffer * The buffer to read from. * * @return * The value read from the buffer. */ uint8_t guac_common_ssh_buffer_read_byte(char** buffer); /** * Reads an integer from the given buffer, advancing the buffer by four bytes. * * @param buffer * The buffer to read from. * * @return * The value read from the buffer. */ uint32_t guac_common_ssh_buffer_read_uint32(char** buffer); /** * Reads a string and its length from the given buffer, advancing the buffer * by the size of the length (four bytes) and the size of the string, and * returning a pointer to the buffer. The length of the string is stored in * the given int. * * @param buffer * The buffer to read from. * * @param length * A pointer to an integer into which the length of the read string will * be stored. * * @return * A pointer to the value within the buffer. */ char* guac_common_ssh_buffer_read_string(char** buffer, int* length); #endif guacamole-server-1.3.0/src/common-ssh/common-ssh/key.h0000644000175100001440000001413613702142276017601 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_SSH_KEY_H #define GUAC_COMMON_SSH_KEY_H #include "config.h" #include #include #include /** * The expected header of RSA private keys. */ #define SSH_RSA_KEY_HEADER "-----BEGIN RSA PRIVATE KEY-----" /** * The expected header of DSA private keys. */ #define SSH_DSA_KEY_HEADER "-----BEGIN DSA PRIVATE KEY-----" /** * The size of single number within a DSA signature, in bytes. */ #define DSA_SIG_NUMBER_SIZE 20 /** * The size of a DSA signature, in bytes. */ #define DSA_SIG_SIZE DSA_SIG_NUMBER_SIZE*2 /** * The type of an SSH key. */ typedef enum guac_common_ssh_key_type { /** * RSA key. */ SSH_KEY_RSA, /** * DSA key. */ SSH_KEY_DSA } guac_common_ssh_key_type; /** * Abstraction of a key used for SSH authentication. */ typedef struct guac_common_ssh_key { /** * The type of this key. */ guac_common_ssh_key_type type; /** * Underlying RSA private key, if any. */ RSA* rsa; /** * Underlying DSA private key, if any. */ DSA* dsa; /** * The associated public key, encoded as necessary for SSH. */ char* public_key; /** * The length of the public key, in bytes. */ int public_key_length; /** * The private key, encoded as necessary for SSH. */ char* private_key; /** * The length of the private key, in bytes. */ int private_key_length; } guac_common_ssh_key; /** * Allocates a new key containing the given private key data and specified * passphrase. If unable to read the key, NULL is returned. * * @param data * The base64-encoded data to decode when reading the key. * * @param length * The length of the provided data, in bytes. * * @param passphrase * The passphrase to use when decrypting the key, if any, or an empty * string or NULL if no passphrase is needed. * * @return * The decoded, decrypted private key, or NULL if the key could not be * decoded. */ guac_common_ssh_key* guac_common_ssh_key_alloc(char* data, int length, char* passphrase); /** * Returns a statically-allocated string describing the most recent SSH key * error. * * @return * A statically-allocated string describing the most recent SSH key error. */ const char* guac_common_ssh_key_error(); /** * Frees all memory associated with the given key. * * @param key * The key to free. */ void guac_common_ssh_key_free(guac_common_ssh_key* key); /** * Signs the given data using the given key, returning the length of the * signature in bytes, or a value less than zero on error. * * @param key * The key to use when signing the given data. * * @param data * The arbitrary data to sign. * * @param length * The length of the arbitrary data being signed, in bytes. * * @param sig * The buffer into which the signature should be written. The buffer must * be at least DSA_SIG_SIZE for DSA keys. For RSA keys, the signature size * is dependent only on key size, and is equal to the length of the * modulus, in bytes. * * @return * The number of bytes in the resulting signature. */ int guac_common_ssh_key_sign(guac_common_ssh_key* key, const char* data, int length, unsigned char* sig); /** * Verifies the host key for the given hostname/port combination against * one or more known_hosts entries. The known_host entries can either be a * single host_key, provided by the client, or a set of known_hosts entries * provided in the /etc/guacamole/ssh_known_hosts file. Failure to correctly * load the known_hosts entries will result in a connection abort and a returned * error code. A return code of zero indiciates that either no known_hosts entries * were provided, or that the verification succeeded (match). Negative values * indicate internal libssh2 error codes; positive values indicate a failure * during verification of the host key against the known hosts. * * @param session * A pointer to the LIBSSH2_SESSION structure of the SSH connection already * in progress. * * @param client * The current guac_client instance for which the known_hosts checking is * being performed. * * @param host_key * The known host entry provided by the client. If this is non-null and not * empty, it will be the only host key loaded and used for verification. If * this is null or empty an attempt will be made to read the * /etc/guacamole/ssh_known_hosts file and load entries from it. * * @param hostname * The hostname or IP of the server that is being verified. * * @param port * The port number of the server being verified. * * @param remote_hostkey * The host key of the remote system being verified. * * @param remote_hostkey_len * The length of the remote host key being verified * * @return * The status of the known_hosts check. This will be zero if no entries * are provided or if the match succeeds, negative to indicate internal * libssh2 errors, or positive to indicate failures during host key * checking. */ int guac_common_ssh_verify_host_key(LIBSSH2_SESSION* session, guac_client* client, const char* host_key, const char* hostname, int port, const char* remote_hostkey, const size_t remote_hostkey_len); #endif guacamole-server-1.3.0/src/common-ssh/common-ssh/ssh.h0000644000175100001440000001157413764613616017622 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_SSH_H #define GUAC_COMMON_SSH_H #include "user.h" #include #include /** * Handler for retrieving additional credentials. * * @param client * The Guacamole Client associated with this need for additional * credentials. * * @param cred_name * The name of the credential being requested, which will be shared * with the client in order to generate a meaningful prompt. * * @return * A newly-allocated string containing the credentials provided by * the user, which must be freed by a call to free(). */ typedef char* guac_ssh_credential_handler(guac_client* client, char* cred_name); /** * An SSH session, backed by libssh2 and associated with a particular * Guacamole client. */ typedef struct guac_common_ssh_session { /** * The Guacamole client using this SSH session. */ guac_client* client; /** * The user that will be authenticating via SSH. */ guac_common_ssh_user* user; /** * The underlying SSH session from libssh2. */ LIBSSH2_SESSION* session; /** * The file descriptor of the socket being used for the SSH connection. */ int fd; /** * Callback function to retrieve credentials. */ guac_ssh_credential_handler* credential_handler; } guac_common_ssh_session; /** * Initializes the underlying SSH and encryption libraries used by Guacamole. * This function must be called before any other guac_common_ssh_*() functions * are called. * * @param client * The Guacamole client that will be using SSH. * * @return * Zero if initialization, or non-zero if an error occurs. */ int guac_common_ssh_init(guac_client* client); /** * Cleans up the underlying SSH and encryption libraries used by Guacamole. * This function must be called once no other guac_common_ssh_*() functions * will be used. */ void guac_common_ssh_uninit(); /** * Connects to the SSH server running at the given hostname and port, and * authenticates as the given user. If an error occurs while connecting or * authenticating, the Guacamole client will automatically and fatally abort. * The user object provided must eventually be explicitly destroyed, but should * not be destroyed until this session is destroyed, assuming the session is * successfully created. * * @param client * The Guacamole client that will be using SSH. * * @param hostname * The hostname of the SSH server to connect to. * * @param port * The port to connect to on the given hostname. * * @param user * The user to authenticate as, once connected. * * @param keepalive * How frequently the connection should send keepalive packets, in * seconds. Zero disables keepalive packets, and 2 is the minimum * configurable value. * * @param host_key * The known public host key of the server, as provided by the client. If * provided the identity of the server will be checked against this key, * and a mis-match between this and the server identity will cause the * connection to fail. If not provided, no checks will be done and the * connection will proceed. * * @param credential_handler * The handler function for retrieving additional credentials from the user * as required by the SSH server, or NULL if the user will not be asked * for additional credentials. * * @return * A new SSH session if the connection and authentication succeed, or NULL * if the connection or authentication were not successful. */ guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client, const char* hostname, const char* port, guac_common_ssh_user* user, int keepalive, const char* host_key, guac_ssh_credential_handler* credential_handler); /** * Disconnects and destroys the given SSH session, freeing all associated * resources. Any associated user must be explicitly destroyed, and will not * be destroyed automatically. * * @param session * The SSH session to destroy. */ void guac_common_ssh_destroy_session(guac_common_ssh_session* session); #endif guacamole-server-1.3.0/src/common-ssh/common-ssh/rsa-compat.h0000644000175100001440000000237313676721353021070 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_SSH_RSA_COMPAT_H #define GUAC_COMMON_SSH_RSA_COMPAT_H #include "config.h" #include #include #ifndef HAVE_RSA_GET0_KEY /** * RSA_get0_key() implementation for versions of OpenSSL which lack this * function (pre 1.1). * * See: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html */ void RSA_get0_key(const RSA* rsa_key, const BIGNUM** n, const BIGNUM** e, const BIGNUM**d); #endif #endif guacamole-server-1.3.0/src/common-ssh/key.c0000644000175100001440000002354213702142276015512 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common-ssh/buffer.h" #include "common-ssh/dsa-compat.h" #include "common-ssh/key.h" #include "common-ssh/rsa-compat.h" #include #include #include #include #include #include #include #include #include #include #include guac_common_ssh_key* guac_common_ssh_key_alloc(char* data, int length, char* passphrase) { guac_common_ssh_key* key; BIO* key_bio; char* public_key; char* pos; /* Create BIO for reading key from memory */ key_bio = BIO_new_mem_buf(data, length); /* If RSA key, load RSA */ if (length > sizeof(SSH_RSA_KEY_HEADER)-1 && memcmp(SSH_RSA_KEY_HEADER, data, sizeof(SSH_RSA_KEY_HEADER)-1) == 0) { RSA* rsa_key; const BIGNUM* key_e; const BIGNUM* key_n; /* Read key */ rsa_key = PEM_read_bio_RSAPrivateKey(key_bio, NULL, NULL, passphrase); if (rsa_key == NULL) return NULL; /* Allocate key */ key = malloc(sizeof(guac_common_ssh_key)); key->rsa = rsa_key; /* Set type */ key->type = SSH_KEY_RSA; /* Allocate space for public key */ public_key = malloc(4096); pos = public_key; /* Retrieve public key */ RSA_get0_key(rsa_key, &key_n, &key_e, NULL); /* Send public key formatted for SSH */ guac_common_ssh_buffer_write_string(&pos, "ssh-rsa", sizeof("ssh-rsa")-1); guac_common_ssh_buffer_write_bignum(&pos, key_e); guac_common_ssh_buffer_write_bignum(&pos, key_n); /* Save public key to structure */ key->public_key = public_key; key->public_key_length = pos - public_key; } /* If DSA key, load DSA */ else if (length > sizeof(SSH_DSA_KEY_HEADER)-1 && memcmp(SSH_DSA_KEY_HEADER, data, sizeof(SSH_DSA_KEY_HEADER)-1) == 0) { DSA* dsa_key; const BIGNUM* key_p; const BIGNUM* key_q; const BIGNUM* key_g; const BIGNUM* pub_key; /* Read key */ dsa_key = PEM_read_bio_DSAPrivateKey(key_bio, NULL, NULL, passphrase); if (dsa_key == NULL) return NULL; /* Allocate key */ key = malloc(sizeof(guac_common_ssh_key)); key->dsa = dsa_key; /* Set type */ key->type = SSH_KEY_DSA; /* Allocate space for public key */ public_key = malloc(4096); pos = public_key; /* Retrieve public key */ DSA_get0_pqg(dsa_key, &key_p, &key_q, &key_g); DSA_get0_key(dsa_key, &pub_key, NULL); /* Send public key formatted for SSH */ guac_common_ssh_buffer_write_string(&pos, "ssh-dss", sizeof("ssh-dss")-1); guac_common_ssh_buffer_write_bignum(&pos, key_p); guac_common_ssh_buffer_write_bignum(&pos, key_q); guac_common_ssh_buffer_write_bignum(&pos, key_g); guac_common_ssh_buffer_write_bignum(&pos, pub_key); /* Save public key to structure */ key->public_key = public_key; key->public_key_length = pos - public_key; } /* Otherwise, unsupported type */ else { BIO_free(key_bio); return NULL; } /* Copy private key to structure */ key->private_key_length = length; key->private_key = malloc(length); memcpy(key->private_key, data, length); BIO_free(key_bio); return key; } const char* guac_common_ssh_key_error() { /* Return static error string */ return ERR_reason_error_string(ERR_get_error()); } void guac_common_ssh_key_free(guac_common_ssh_key* key) { /* Free key-specific data */ if (key->type == SSH_KEY_RSA) RSA_free(key->rsa); else if (key->type == SSH_KEY_DSA) DSA_free(key->dsa); free(key->private_key); free(key->public_key); free(key); } int guac_common_ssh_key_sign(guac_common_ssh_key* key, const char* data, int length, unsigned char* sig) { const EVP_MD* md; unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int dlen, len; /* Get SHA1 digest */ if ((md = EVP_get_digestbynid(NID_sha1)) == NULL) return -1; /* Allocate digest context */ EVP_MD_CTX* md_ctx = EVP_MD_CTX_create(); if (md_ctx == NULL) return -1; /* Digest data */ EVP_DigestInit(md_ctx, md); EVP_DigestUpdate(md_ctx, data, length); EVP_DigestFinal(md_ctx, digest, &dlen); /* Digest context no longer needed */ EVP_MD_CTX_destroy(md_ctx); /* Sign with key */ switch (key->type) { case SSH_KEY_RSA: if (RSA_sign(NID_sha1, digest, dlen, sig, &len, key->rsa) == 1) return len; break; case SSH_KEY_DSA: { DSA_SIG* dsa_sig = DSA_do_sign(digest, dlen, key->dsa); if (dsa_sig != NULL) { const BIGNUM* sig_r; const BIGNUM* sig_s; /* Retrieve DSA signature values */ DSA_SIG_get0(dsa_sig, &sig_r, &sig_s); /* Compute size of each half of signature */ int rlen = BN_num_bytes(sig_r); int slen = BN_num_bytes(sig_s); /* Ensure each number is within the required size */ if (rlen > DSA_SIG_NUMBER_SIZE || slen > DSA_SIG_NUMBER_SIZE) return -1; /* Init to all zeroes */ memset(sig, 0, DSA_SIG_SIZE); /* Add R at the end of the first block of the signature */ BN_bn2bin(sig_r, sig + DSA_SIG_SIZE - DSA_SIG_NUMBER_SIZE - rlen); /* Add S at the end of the second block of the signature */ BN_bn2bin(sig_s, sig + DSA_SIG_SIZE - slen); /* Done */ DSA_SIG_free(dsa_sig); return DSA_SIG_SIZE; } } } return -1; } int guac_common_ssh_verify_host_key(LIBSSH2_SESSION* session, guac_client* client, const char* host_key, const char* hostname, int port, const char* remote_hostkey, const size_t remote_hostkey_len) { LIBSSH2_KNOWNHOSTS* ssh_known_hosts = libssh2_knownhost_init(session); int known_hosts = 0; /* Add host key provided from settings */ if (host_key && strcmp(host_key, "") != 0) { known_hosts = libssh2_knownhost_readline(ssh_known_hosts, host_key, strlen(host_key), LIBSSH2_KNOWNHOST_FILE_OPENSSH); /* readline function returns 0 on success, so we increment to indicate a valid entry */ if (known_hosts == 0) known_hosts++; } /* Otherwise, we look for a ssh_known_hosts file within GUACAMOLE_HOME and read that in. */ else { const char *guac_known_hosts = "/etc/guacamole/ssh_known_hosts"; if (access(guac_known_hosts, F_OK) != -1) known_hosts = libssh2_knownhost_readfile(ssh_known_hosts, guac_known_hosts, LIBSSH2_KNOWNHOST_FILE_OPENSSH); } /* If there's an error provided, abort connection and return that. */ if (known_hosts < 0) { char* errmsg; int errval = libssh2_session_last_error(session, &errmsg, NULL, 0); guac_client_log(client, GUAC_LOG_ERROR, "Error %d trying to load SSH host keys: %s", errval, errmsg); libssh2_knownhost_free(ssh_known_hosts); return known_hosts; } /* No host keys were loaded, so we bail out checking and continue the connection. */ else if (known_hosts == 0) { guac_client_log(client, GUAC_LOG_WARNING, "No known host keys provided, host identity will not be verified."); libssh2_knownhost_free(ssh_known_hosts); return known_hosts; } /* Check remote host key against known hosts */ int kh_check = libssh2_knownhost_checkp(ssh_known_hosts, hostname, port, remote_hostkey, remote_hostkey_len, LIBSSH2_KNOWNHOST_TYPE_PLAIN| LIBSSH2_KNOWNHOST_KEYENC_RAW, NULL); /* Deal with the return of the host key check */ switch (kh_check) { case LIBSSH2_KNOWNHOST_CHECK_MATCH: guac_client_log(client, GUAC_LOG_DEBUG, "Host key match found for %s", hostname); break; case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND: guac_client_log(client, GUAC_LOG_ERROR, "Host key not found for %s.", hostname); break; case LIBSSH2_KNOWNHOST_CHECK_MISMATCH: guac_client_log(client, GUAC_LOG_ERROR, "Host key does not match known hosts entry for %s", hostname); break; case LIBSSH2_KNOWNHOST_CHECK_FAILURE: default: guac_client_log(client, GUAC_LOG_ERROR, "Host %s could not be checked against known hosts.", hostname); } /* Return the check value */ libssh2_knownhost_free(ssh_known_hosts); return kh_check; } guacamole-server-1.3.0/src/common-ssh/dsa-compat.c0000644000175100001440000000330613676721353016757 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include #include #include #ifndef HAVE_DSA_GET0_PQG void DSA_get0_pqg(const DSA* dsa_key, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g) { /* Retrieve all requested internal values */ if (p != NULL) *p = dsa_key->p; if (q != NULL) *q = dsa_key->q; if (g != NULL) *g = dsa_key->g; } #endif #ifndef HAVE_DSA_GET0_KEY void DSA_get0_key(const DSA* dsa_key, const BIGNUM** pub_key, const BIGNUM** priv_key) { /* Retrieve all requested internal values */ if (pub_key != NULL) *pub_key = dsa_key->pub_key; if (priv_key != NULL) *priv_key = dsa_key->priv_key; } #endif #ifndef HAVE_DSA_SIG_GET0 void DSA_SIG_get0(const DSA_SIG* dsa_sig, const BIGNUM** r, const BIGNUM** s) { /* Retrieve all requested internal values */ if (r != NULL) *r = dsa_sig->r; if (s != NULL) *s = dsa_sig->s; } #endif guacamole-server-1.3.0/src/common-ssh/tests/0000755000175100001440000000000013772471156016003 500000000000000guacamole-server-1.3.0/src/common-ssh/tests/sftp/0000755000175100001440000000000013772471156016757 500000000000000guacamole-server-1.3.0/src/common-ssh/tests/sftp/normalize_path.c0000644000175100001440000002431613764613616022065 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common-ssh/sftp.h" #include #include /** * Test which verifies absolute Windows-style paths are correctly normalized to * absolute paths with UNIX separators and no relative components. */ void test_sftp__normalize_absolute_windows() { char normalized[GUAC_COMMON_SSH_SFTP_MAX_PATH]; CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "\\"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "\\foo\\bar\\baz"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/foo/bar/baz", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "\\foo\\bar\\..\\baz\\"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/foo/baz", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "\\foo\\bar\\..\\..\\baz\\a\\..\\b"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/baz/b", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "\\foo\\.\\bar\\baz"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/foo/bar/baz", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "\\foo\\bar\\..\\..\\..\\..\\..\\..\\baz"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/baz", sizeof(normalized)); } /** * Test which verifies absolute UNIX-style paths are correctly normalized to * absolute paths with UNIX separators and no relative components. */ void test_sftp__normalize_absolute_unix() { char normalized[GUAC_COMMON_SSH_SFTP_MAX_PATH]; CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "/"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "/foo/bar/baz"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/foo/bar/baz", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "/foo/bar/../baz/"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/foo/baz", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "/foo/bar/../../baz/a/../b"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/baz/b", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "/foo/./bar/baz"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/foo/bar/baz", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "/foo/bar/../../../../../../baz"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/baz", sizeof(normalized)); } /** * Test which verifies absolute paths consisting of mixed Windows and UNIX path * separators are correctly normalized to absolute paths with UNIX separators * and no relative components. */ void test_sftp__normalize_absolute_mixed() { char normalized[GUAC_COMMON_SSH_SFTP_MAX_PATH]; CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "\\foo/bar\\baz"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/foo/bar/baz", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "/foo\\bar/..\\baz/"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/foo/baz", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "\\foo/bar\\../../baz\\a\\..\\b"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/baz/b", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "\\foo\\.\\bar/baz"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/foo/bar/baz", sizeof(normalized)); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "\\foo/bar\\../..\\..\\..\\../..\\baz"), 0); CU_ASSERT_NSTRING_EQUAL(normalized, "/baz", sizeof(normalized)); } /** * Test which verifies relative Windows-style paths are always rejected. */ void test_sftp__normalize_relative_windows() { char normalized[GUAC_COMMON_SSH_SFTP_MAX_PATH]; CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, ""), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "."), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, ".."), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "foo"), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, ".\\foo"), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "..\\foo"), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "foo\\bar\\baz"), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, ".\\foo\\bar\\baz"), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "..\\foo\\bar\\baz"), 0); } /** * Test which verifies relative UNIX-style paths are always rejected. */ void test_sftp__normalize_relative_unix() { char normalized[GUAC_COMMON_SSH_SFTP_MAX_PATH]; CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, ""), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "."), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, ".."), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "foo"), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "./foo"), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "../foo"), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "foo/bar/baz"), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "./foo/bar/baz"), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "../foo/bar/baz"), 0); } /** * Test which verifies relative paths consisting of mixed Windows and UNIX path * separators are always rejected. */ void test_sftp__normalize_relative_mixed() { char normalized[GUAC_COMMON_SSH_SFTP_MAX_PATH]; CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "foo\\bar/baz"), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, ".\\foo/bar/baz"), 0); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, "../foo\\bar\\baz"), 0); } /** * Generates a dynamically-allocated path having the given number of bytes, not * counting the null-terminator. The path will contain only UNIX-style path * separators. The returned path must eventually be freed with a call to * free(). * * @param length * The number of bytes to include in the generated path, not counting the * null-terminator. If -1, the length of the path will be automatically * determined from the provided max_depth. * * @param max_depth * The maximum number of path components to include within the generated * path. * * @return * A dynamically-allocated path containing the given number of bytes, not * counting the null-terminator. This path must eventually be freed with a * call to free(). */ static char* generate_path(int length, int max_depth) { /* If no length given, calculate space required from max_depth */ if (length == -1) length = max_depth * 2; int i; char* input = malloc(length + 1); /* Fill path with /x/x/x/x/x/x/x/x/x/x/.../xxxxxxxxx... */ for (i = 0; i < length; i++) { if (max_depth > 0 && i % 2 == 0) { input[i] = '/'; max_depth--; } else input[i] = 'x'; } /* Add null terminator */ input[length] = '\0'; return input; } /** * Test which verifies that paths exceeding the maximum path length are * rejected. */ void test_sftp__normalize_long() { char* input; char normalized[GUAC_COMMON_SSH_SFTP_MAX_PATH]; /* Exceeds maximum length by a factor of 2 */ input = generate_path(GUAC_COMMON_SSH_SFTP_MAX_PATH * 2, GUAC_COMMON_SSH_SFTP_MAX_DEPTH); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, input), 0); free(input); /* Exceeds maximum length by one byte */ input = generate_path(GUAC_COMMON_SSH_SFTP_MAX_PATH, GUAC_COMMON_SSH_SFTP_MAX_DEPTH); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, input), 0); free(input); /* Exactly maximum length */ input = generate_path(GUAC_COMMON_SSH_SFTP_MAX_PATH - 1, GUAC_COMMON_SSH_SFTP_MAX_DEPTH); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, input), 0); free(input); } /** * Test which verifies that paths exceeding the maximum path depth are * rejected. */ void test_sftp__normalize_deep() { char* input; char normalized[GUAC_COMMON_SSH_SFTP_MAX_PATH]; /* Exceeds maximum depth by a factor of 2 */ input = generate_path(-1, GUAC_COMMON_SSH_SFTP_MAX_DEPTH * 2); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, input), 0); free(input); /* Exceeds maximum depth by one component */ input = generate_path(-1, GUAC_COMMON_SSH_SFTP_MAX_DEPTH + 1); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, input), 0); free(input); /* Exactly maximum depth (should still be rejected as SFTP depth limits are * set such that a path with the maximum depth will exceed the maximum * length) */ input = generate_path(-1, GUAC_COMMON_SSH_SFTP_MAX_DEPTH); CU_ASSERT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, input), 0); free(input); /* Less than maximum depth */ input = generate_path(-1, GUAC_COMMON_SSH_SFTP_MAX_DEPTH - 1); CU_ASSERT_NOT_EQUAL(guac_common_ssh_sftp_normalize_path(normalized, input), 0); free(input); } guacamole-server-1.3.0/src/common-ssh/tests/Makefile.in0000644000175100001440000012011613772471101017757 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ check_PROGRAMS = test_common_ssh$(EXEEXT) subdir = src/common-ssh/tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__dirstamp = $(am__leading_dot)dirstamp am_test_common_ssh_OBJECTS = \ sftp/test_common_ssh-normalize_path.$(OBJEXT) nodist_test_common_ssh_OBJECTS = \ test_common_ssh-_generated_runner.$(OBJEXT) test_common_ssh_OBJECTS = $(am_test_common_ssh_OBJECTS) \ $(nodist_test_common_ssh_OBJECTS) test_common_ssh_DEPENDENCIES = AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = test_common_ssh_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(test_common_ssh_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = \ ./$(DEPDIR)/test_common_ssh-_generated_runner.Po \ sftp/$(DEPDIR)/test_common_ssh-normalize_path.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(test_common_ssh_SOURCES) $(nodist_test_common_ssh_SOURCES) DIST_SOURCES = $(test_common_ssh_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp \ $(top_srcdir)/build-aux/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 TESTS = $(check_PROGRAMS) test_common_ssh_SOURCES = \ sftp/normalize_path.c test_common_ssh_CFLAGS = \ -Werror -Wall -pedantic \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ test_common_ssh_LDADD = \ @CUNIT_LIBS@ \ @COMMON_SSH_LTLIB@ \ @COMMON_LTLIB@ # # Autogenerate test runner # GEN_RUNNER = $(top_srcdir)/util/generate-test-runner.pl CLEANFILES = _generated_runner.c nodist_test_common_ssh_SOURCES = \ _generated_runner.c # Use automake's TAP test driver for running any tests LOG_DRIVER = \ env AM_TAP_AWK='$(AWK)' \ $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/common-ssh/tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/common-ssh/tests/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list sftp/$(am__dirstamp): @$(MKDIR_P) sftp @: > sftp/$(am__dirstamp) sftp/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) sftp/$(DEPDIR) @: > sftp/$(DEPDIR)/$(am__dirstamp) sftp/test_common_ssh-normalize_path.$(OBJEXT): sftp/$(am__dirstamp) \ sftp/$(DEPDIR)/$(am__dirstamp) test_common_ssh$(EXEEXT): $(test_common_ssh_OBJECTS) $(test_common_ssh_DEPENDENCIES) $(EXTRA_test_common_ssh_DEPENDENCIES) @rm -f test_common_ssh$(EXEEXT) $(AM_V_CCLD)$(test_common_ssh_LINK) $(test_common_ssh_OBJECTS) $(test_common_ssh_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f sftp/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_common_ssh-_generated_runner.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@sftp/$(DEPDIR)/test_common_ssh-normalize_path.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< sftp/test_common_ssh-normalize_path.o: sftp/normalize_path.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_ssh_CFLAGS) $(CFLAGS) -MT sftp/test_common_ssh-normalize_path.o -MD -MP -MF sftp/$(DEPDIR)/test_common_ssh-normalize_path.Tpo -c -o sftp/test_common_ssh-normalize_path.o `test -f 'sftp/normalize_path.c' || echo '$(srcdir)/'`sftp/normalize_path.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sftp/$(DEPDIR)/test_common_ssh-normalize_path.Tpo sftp/$(DEPDIR)/test_common_ssh-normalize_path.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sftp/normalize_path.c' object='sftp/test_common_ssh-normalize_path.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_ssh_CFLAGS) $(CFLAGS) -c -o sftp/test_common_ssh-normalize_path.o `test -f 'sftp/normalize_path.c' || echo '$(srcdir)/'`sftp/normalize_path.c sftp/test_common_ssh-normalize_path.obj: sftp/normalize_path.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_ssh_CFLAGS) $(CFLAGS) -MT sftp/test_common_ssh-normalize_path.obj -MD -MP -MF sftp/$(DEPDIR)/test_common_ssh-normalize_path.Tpo -c -o sftp/test_common_ssh-normalize_path.obj `if test -f 'sftp/normalize_path.c'; then $(CYGPATH_W) 'sftp/normalize_path.c'; else $(CYGPATH_W) '$(srcdir)/sftp/normalize_path.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sftp/$(DEPDIR)/test_common_ssh-normalize_path.Tpo sftp/$(DEPDIR)/test_common_ssh-normalize_path.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sftp/normalize_path.c' object='sftp/test_common_ssh-normalize_path.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_ssh_CFLAGS) $(CFLAGS) -c -o sftp/test_common_ssh-normalize_path.obj `if test -f 'sftp/normalize_path.c'; then $(CYGPATH_W) 'sftp/normalize_path.c'; else $(CYGPATH_W) '$(srcdir)/sftp/normalize_path.c'; fi` test_common_ssh-_generated_runner.o: _generated_runner.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_ssh_CFLAGS) $(CFLAGS) -MT test_common_ssh-_generated_runner.o -MD -MP -MF $(DEPDIR)/test_common_ssh-_generated_runner.Tpo -c -o test_common_ssh-_generated_runner.o `test -f '_generated_runner.c' || echo '$(srcdir)/'`_generated_runner.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_common_ssh-_generated_runner.Tpo $(DEPDIR)/test_common_ssh-_generated_runner.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='_generated_runner.c' object='test_common_ssh-_generated_runner.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_ssh_CFLAGS) $(CFLAGS) -c -o test_common_ssh-_generated_runner.o `test -f '_generated_runner.c' || echo '$(srcdir)/'`_generated_runner.c test_common_ssh-_generated_runner.obj: _generated_runner.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_ssh_CFLAGS) $(CFLAGS) -MT test_common_ssh-_generated_runner.obj -MD -MP -MF $(DEPDIR)/test_common_ssh-_generated_runner.Tpo -c -o test_common_ssh-_generated_runner.obj `if test -f '_generated_runner.c'; then $(CYGPATH_W) '_generated_runner.c'; else $(CYGPATH_W) '$(srcdir)/_generated_runner.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_common_ssh-_generated_runner.Tpo $(DEPDIR)/test_common_ssh-_generated_runner.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='_generated_runner.c' object='test_common_ssh-_generated_runner.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_ssh_CFLAGS) $(CFLAGS) -c -o test_common_ssh-_generated_runner.obj `if test -f '_generated_runner.c'; then $(CYGPATH_W) '_generated_runner.c'; else $(CYGPATH_W) '$(srcdir)/_generated_runner.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: $(check_PROGRAMS) @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_common_ssh.log: test_common_ssh$(EXEEXT) @p='test_common_ssh$(EXEEXT)'; \ b='test_common_ssh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f sftp/$(DEPDIR)/$(am__dirstamp) -rm -f sftp/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/test_common_ssh-_generated_runner.Po -rm -f sftp/$(DEPDIR)/test_common_ssh-normalize_path.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/test_common_ssh-_generated_runner.Po -rm -f sftp/$(DEPDIR)/test_common_ssh-normalize_path.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am .PRECIOUS: Makefile _generated_runner.c: $(test_common_ssh_SOURCES) $(AM_V_GEN) $(GEN_RUNNER) $(test_common_ssh_SOURCES) > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/common-ssh/tests/Makefile.am0000644000175100001440000000405513764613616017763 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 # # Unit tests for common SSH support # check_PROGRAMS = test_common_ssh TESTS = $(check_PROGRAMS) test_common_ssh_SOURCES = \ sftp/normalize_path.c test_common_ssh_CFLAGS = \ -Werror -Wall -pedantic \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ test_common_ssh_LDADD = \ @CUNIT_LIBS@ \ @COMMON_SSH_LTLIB@ \ @COMMON_LTLIB@ # # Autogenerate test runner # GEN_RUNNER = $(top_srcdir)/util/generate-test-runner.pl CLEANFILES = _generated_runner.c _generated_runner.c: $(test_common_ssh_SOURCES) $(AM_V_GEN) $(GEN_RUNNER) $(test_common_ssh_SOURCES) > $@ nodist_test_common_ssh_SOURCES = \ _generated_runner.c # Use automake's TAP test driver for running any tests LOG_DRIVER = \ env AM_TAP_AWK='$(AWK)' \ $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh guacamole-server-1.3.0/src/common-ssh/rsa-compat.c0000644000175100001440000000225513676721353016777 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include #include #include #ifndef HAVE_RSA_GET0_KEY void RSA_get0_key(const RSA* rsa_key, const BIGNUM** n, const BIGNUM** e, const BIGNUM**d) { /* Retrieve all requested internal values */ if (n != NULL) *n = rsa_key->n; if (e != NULL) *e = rsa_key->e; if (d != NULL) *d = rsa_key->d; } #endif guacamole-server-1.3.0/src/common-ssh/user.c0000644000175100001440000000455513613156714015706 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common-ssh/key.h" #include "common-ssh/user.h" #include #include guac_common_ssh_user* guac_common_ssh_create_user(const char* username) { guac_common_ssh_user* user = malloc(sizeof(guac_common_ssh_user)); /* Init user */ user->username = strdup(username); user->password = NULL; user->private_key = NULL; return user; } void guac_common_ssh_destroy_user(guac_common_ssh_user* user) { /* Free private key, if present */ if (user->private_key != NULL) guac_common_ssh_key_free(user->private_key); /* Free all other data */ free(user->password); free(user->username); free(user); } void guac_common_ssh_user_set_password(guac_common_ssh_user* user, const char* password) { /* Replace current password with given value */ free(user->password); user->password = strdup(password); } int guac_common_ssh_user_import_key(guac_common_ssh_user* user, char* private_key, char* passphrase) { /* Free existing private key, if present */ if (user->private_key != NULL) guac_common_ssh_key_free(user->private_key); /* Attempt to read key without passphrase if none given */ if (passphrase == NULL) user->private_key = guac_common_ssh_key_alloc(private_key, strlen(private_key), ""); /* Otherwise, use provided passphrase */ else user->private_key = guac_common_ssh_key_alloc(private_key, strlen(private_key), passphrase); /* Fail if key could not be read */ return user->private_key == NULL; } guacamole-server-1.3.0/src/common-ssh/Makefile.in0000644000175100001440000010624113772471101016620 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/common-ssh ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libguac_common_ssh_la_DEPENDENCIES = am_libguac_common_ssh_la_OBJECTS = libguac_common_ssh_la-buffer.lo \ libguac_common_ssh_la-dsa-compat.lo \ libguac_common_ssh_la-rsa-compat.lo \ libguac_common_ssh_la-sftp.lo libguac_common_ssh_la-ssh.lo \ libguac_common_ssh_la-key.lo libguac_common_ssh_la-user.lo libguac_common_ssh_la_OBJECTS = $(am_libguac_common_ssh_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libguac_common_ssh_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) \ $(libguac_common_ssh_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libguac_common_ssh_la-buffer.Plo \ ./$(DEPDIR)/libguac_common_ssh_la-dsa-compat.Plo \ ./$(DEPDIR)/libguac_common_ssh_la-key.Plo \ ./$(DEPDIR)/libguac_common_ssh_la-rsa-compat.Plo \ ./$(DEPDIR)/libguac_common_ssh_la-sftp.Plo \ ./$(DEPDIR)/libguac_common_ssh_la-ssh.Plo \ ./$(DEPDIR)/libguac_common_ssh_la-user.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libguac_common_ssh_la_SOURCES) DIST_SOURCES = $(libguac_common_ssh_la_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir distdir-am am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 noinst_LTLIBRARIES = libguac_common_ssh.la SUBDIRS = . tests libguac_common_ssh_la_SOURCES = \ buffer.c \ dsa-compat.c \ rsa-compat.c \ sftp.c \ ssh.c \ key.c \ user.c noinst_HEADERS = \ common-ssh/buffer.h \ common-ssh/dsa-compat.h \ common-ssh/rsa-compat.h \ common-ssh/key.h \ common-ssh/sftp.h \ common-ssh/ssh.h \ common-ssh/user.h libguac_common_ssh_la_CFLAGS = \ -Werror -Wall -pedantic \ @COMMON_INCLUDE@ \ @LIBGUAC_INCLUDE@ libguac_common_ssh_la_LIBADD = \ @LIBGUAC_LTLIB@ libguac_common_ssh_la_LDFLAGS = \ @PTHREAD_LIBS@ \ @SSH_LIBS@ \ @SSL_LIBS@ all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/common-ssh/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/common-ssh/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libguac_common_ssh.la: $(libguac_common_ssh_la_OBJECTS) $(libguac_common_ssh_la_DEPENDENCIES) $(EXTRA_libguac_common_ssh_la_DEPENDENCIES) $(AM_V_CCLD)$(libguac_common_ssh_la_LINK) $(libguac_common_ssh_la_OBJECTS) $(libguac_common_ssh_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_ssh_la-buffer.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_ssh_la-dsa-compat.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_ssh_la-key.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_ssh_la-rsa-compat.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_ssh_la-sftp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_ssh_la-ssh.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_ssh_la-user.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libguac_common_ssh_la-buffer.lo: buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_common_ssh_la-buffer.lo -MD -MP -MF $(DEPDIR)/libguac_common_ssh_la-buffer.Tpo -c -o libguac_common_ssh_la-buffer.lo `test -f 'buffer.c' || echo '$(srcdir)/'`buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_ssh_la-buffer.Tpo $(DEPDIR)/libguac_common_ssh_la-buffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='buffer.c' object='libguac_common_ssh_la-buffer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_common_ssh_la-buffer.lo `test -f 'buffer.c' || echo '$(srcdir)/'`buffer.c libguac_common_ssh_la-dsa-compat.lo: dsa-compat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_common_ssh_la-dsa-compat.lo -MD -MP -MF $(DEPDIR)/libguac_common_ssh_la-dsa-compat.Tpo -c -o libguac_common_ssh_la-dsa-compat.lo `test -f 'dsa-compat.c' || echo '$(srcdir)/'`dsa-compat.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_ssh_la-dsa-compat.Tpo $(DEPDIR)/libguac_common_ssh_la-dsa-compat.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dsa-compat.c' object='libguac_common_ssh_la-dsa-compat.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_common_ssh_la-dsa-compat.lo `test -f 'dsa-compat.c' || echo '$(srcdir)/'`dsa-compat.c libguac_common_ssh_la-rsa-compat.lo: rsa-compat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_common_ssh_la-rsa-compat.lo -MD -MP -MF $(DEPDIR)/libguac_common_ssh_la-rsa-compat.Tpo -c -o libguac_common_ssh_la-rsa-compat.lo `test -f 'rsa-compat.c' || echo '$(srcdir)/'`rsa-compat.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_ssh_la-rsa-compat.Tpo $(DEPDIR)/libguac_common_ssh_la-rsa-compat.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsa-compat.c' object='libguac_common_ssh_la-rsa-compat.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_common_ssh_la-rsa-compat.lo `test -f 'rsa-compat.c' || echo '$(srcdir)/'`rsa-compat.c libguac_common_ssh_la-sftp.lo: sftp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_common_ssh_la-sftp.lo -MD -MP -MF $(DEPDIR)/libguac_common_ssh_la-sftp.Tpo -c -o libguac_common_ssh_la-sftp.lo `test -f 'sftp.c' || echo '$(srcdir)/'`sftp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_ssh_la-sftp.Tpo $(DEPDIR)/libguac_common_ssh_la-sftp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sftp.c' object='libguac_common_ssh_la-sftp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_common_ssh_la-sftp.lo `test -f 'sftp.c' || echo '$(srcdir)/'`sftp.c libguac_common_ssh_la-ssh.lo: ssh.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_common_ssh_la-ssh.lo -MD -MP -MF $(DEPDIR)/libguac_common_ssh_la-ssh.Tpo -c -o libguac_common_ssh_la-ssh.lo `test -f 'ssh.c' || echo '$(srcdir)/'`ssh.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_ssh_la-ssh.Tpo $(DEPDIR)/libguac_common_ssh_la-ssh.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ssh.c' object='libguac_common_ssh_la-ssh.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_common_ssh_la-ssh.lo `test -f 'ssh.c' || echo '$(srcdir)/'`ssh.c libguac_common_ssh_la-key.lo: key.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_common_ssh_la-key.lo -MD -MP -MF $(DEPDIR)/libguac_common_ssh_la-key.Tpo -c -o libguac_common_ssh_la-key.lo `test -f 'key.c' || echo '$(srcdir)/'`key.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_ssh_la-key.Tpo $(DEPDIR)/libguac_common_ssh_la-key.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='key.c' object='libguac_common_ssh_la-key.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_common_ssh_la-key.lo `test -f 'key.c' || echo '$(srcdir)/'`key.c libguac_common_ssh_la-user.lo: user.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_common_ssh_la-user.lo -MD -MP -MF $(DEPDIR)/libguac_common_ssh_la-user.Tpo -c -o libguac_common_ssh_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_ssh_la-user.Tpo $(DEPDIR)/libguac_common_ssh_la-user.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user.c' object='libguac_common_ssh_la-user.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_common_ssh_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-recursive -rm -f ./$(DEPDIR)/libguac_common_ssh_la-buffer.Plo -rm -f ./$(DEPDIR)/libguac_common_ssh_la-dsa-compat.Plo -rm -f ./$(DEPDIR)/libguac_common_ssh_la-key.Plo -rm -f ./$(DEPDIR)/libguac_common_ssh_la-rsa-compat.Plo -rm -f ./$(DEPDIR)/libguac_common_ssh_la-sftp.Plo -rm -f ./$(DEPDIR)/libguac_common_ssh_la-ssh.Plo -rm -f ./$(DEPDIR)/libguac_common_ssh_la-user.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/libguac_common_ssh_la-buffer.Plo -rm -f ./$(DEPDIR)/libguac_common_ssh_la-dsa-compat.Plo -rm -f ./$(DEPDIR)/libguac_common_ssh_la-key.Plo -rm -f ./$(DEPDIR)/libguac_common_ssh_la-rsa-compat.Plo -rm -f ./$(DEPDIR)/libguac_common_ssh_la-sftp.Plo -rm -f ./$(DEPDIR)/libguac_common_ssh_la-ssh.Plo -rm -f ./$(DEPDIR)/libguac_common_ssh_la-user.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--depfiles check check-am clean clean-generic clean-libtool \ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/common-ssh/sftp.c0000644000175100001440000010007013764613616015677 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common-ssh/sftp.h" #include "common-ssh/ssh.h" #include #include #include #include #include #include #include #include #include #include #include int guac_common_ssh_sftp_normalize_path(char* fullpath, const char* path) { int path_depth = 0; const char* path_components[GUAC_COMMON_SSH_SFTP_MAX_DEPTH]; /* If original path is not absolute, normalization fails */ if (path[0] != '\\' && path[0] != '/') return 0; /* Create scratch copy of path excluding leading slash (we will be * replacing path separators with null terminators and referencing those * substrings directly as path components) */ char path_scratch[GUAC_COMMON_SSH_SFTP_MAX_PATH - 1]; int length = guac_strlcpy(path_scratch, path + 1, sizeof(path_scratch)); /* Fail if provided path is too long */ if (length >= sizeof(path_scratch)) return 0; /* Locate all path components within path */ const char* current_path_component = &(path_scratch[0]); for (int i = 0; i <= length; i++) { /* If current character is a path separator, parse as component */ char c = path_scratch[i]; if (c == '/' || c == '\\' || c == '\0') { /* Terminate current component */ path_scratch[i] = '\0'; /* If component refers to parent, just move up in depth */ if (strcmp(current_path_component, "..") == 0) { if (path_depth > 0) path_depth--; } /* Otherwise, if component not current directory, add to list */ else if (strcmp(current_path_component, ".") != 0 && strcmp(current_path_component, "") != 0) { /* Fail normalization if path is too deep */ if (path_depth >= GUAC_COMMON_SSH_SFTP_MAX_DEPTH) return 0; path_components[path_depth++] = current_path_component; } /* Update start of next component */ current_path_component = &(path_scratch[i+1]); } /* end if separator */ } /* end for each character */ /* Add leading slash for resulting absolute path */ fullpath[0] = '/'; /* Append normalized components to path, separated by slashes */ guac_strljoin(fullpath + 1, path_components, path_depth, "/", GUAC_COMMON_SSH_SFTP_MAX_PATH - 1); return 1; } /** * Translates the last error message received by the SFTP layer of an SSH * session into a Guacamole protocol status code. * * @param filesystem * The object (not guac_object) defining the filesystem associated with the * SFTP and SSH sessions. * * @return * The Guacamole protocol status code corresponding to the last reported * error of the SFTP layer, if nay, or GUAC_PROTOCOL_STATUS_SUCCESS if no * error has occurred. */ static guac_protocol_status guac_sftp_get_status( guac_common_ssh_sftp_filesystem* filesystem) { /* Get libssh2 objects */ LIBSSH2_SFTP* sftp = filesystem->sftp_session; LIBSSH2_SESSION* session = filesystem->ssh_session->session; /* Return success code if no error occurred */ if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_SFTP_PROTOCOL) return GUAC_PROTOCOL_STATUS_SUCCESS; /* Translate SFTP error codes defined by * https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02 (the most * commonly-implemented standard) */ switch (libssh2_sftp_last_error(sftp)) { /* SSH_FX_OK (not an error) */ case 0: return GUAC_PROTOCOL_STATUS_SUCCESS; /* SSH_FX_EOF (technically not an error) */ case 1: return GUAC_PROTOCOL_STATUS_SUCCESS; /* SSH_FX_NO_SUCH_FILE */ case 2: return GUAC_PROTOCOL_STATUS_RESOURCE_NOT_FOUND; /* SSH_FX_PERMISSION_DENIED */ case 3: return GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN; /* SSH_FX_FAILURE */ case 4: return GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR; /* SSH_FX_BAD_MESSAGE */ case 5: return GUAC_PROTOCOL_STATUS_SERVER_ERROR; /* SSH_FX_NO_CONNECTION / SSH_FX_CONNECTION_LOST */ case 6: case 7: return GUAC_PROTOCOL_STATUS_UPSTREAM_TIMEOUT; /* SSH_FX_OP_UNSUPPORTED */ case 8: return GUAC_PROTOCOL_STATUS_UNSUPPORTED; /* Return generic error if cause unknown */ default: return GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR; } } /** * Concatenates the given filename with the given path, separating the two * with a single forward slash. The full result must be no more than * GUAC_COMMON_SSH_SFTP_MAX_PATH bytes long, counting null terminator. * * @param fullpath * The buffer to store the result within. This buffer must be at least * GUAC_COMMON_SSH_SFTP_MAX_PATH bytes long. * * @param path * The path to append the filename to. * * @param filename * The filename to append to the path. * * @return * Non-zero if the filename is valid and was successfully appended to the * path, zero otherwise. */ static int guac_ssh_append_filename(char* fullpath, const char* path, const char* filename) { int length; /* Disallow "." as a filename */ if (strcmp(filename, ".") == 0) return 0; /* Disallow ".." as a filename */ if (strcmp(filename, "..") == 0) return 0; /* Filenames may not contain slashes */ if (strchr(filename, '/') != NULL) return 0; /* Copy base path */ length = guac_strlcpy(fullpath, path, GUAC_COMMON_SSH_SFTP_MAX_PATH); /* * Append trailing slash only if: * 1) Trailing slash is not already present * 2) Path is non-empty */ if (length > 0 && fullpath[length - 1] != '/') length += guac_strlcpy(fullpath + length, "/", GUAC_COMMON_SSH_SFTP_MAX_PATH - length); /* Append filename */ length += guac_strlcpy(fullpath + length, filename, GUAC_COMMON_SSH_SFTP_MAX_PATH - length); /* Verify path length is within maximum */ if (length >= GUAC_COMMON_SSH_SFTP_MAX_PATH) return 0; /* Append was successful */ return 1; } /** * Concatenates the given paths, separating the two with a single forward * slash. The full result must be no more than GUAC_COMMON_SSH_SFTP_MAX_PATH * bytes long, counting null terminator. * * @param fullpath * The buffer to store the result within. This buffer must be at least * GUAC_COMMON_SSH_SFTP_MAX_PATH bytes long. * * @param path_a * The path to place at the beginning of the resulting path. * * @param path_b * The path to append after path_a within the resulting path. * * @return * Non-zero if the paths were successfully concatenated together, zero * otherwise. */ static int guac_ssh_append_path(char* fullpath, const char* path_a, const char* path_b) { int length; /* Copy first half of path */ length = guac_strlcpy(fullpath, path_a, GUAC_COMMON_SSH_SFTP_MAX_PATH); if (length >= GUAC_COMMON_SSH_SFTP_MAX_PATH) return 0; /* Ensure path ends with trailing slash */ if (length == 0 || fullpath[length - 1] != '/') length += guac_strlcpy(fullpath + length, "/", GUAC_COMMON_SSH_SFTP_MAX_PATH - length); /* Skip past leading slashes in second path */ while (*path_b == '/') path_b++; /* Append final half of path */ length += guac_strlcpy(fullpath + length, path_b, GUAC_COMMON_SSH_SFTP_MAX_PATH - length); /* Verify path length is within maximum */ if (length >= GUAC_COMMON_SSH_SFTP_MAX_PATH) return 0; /* Append was successful */ return 1; } /** * Handler for blob messages which continue an inbound SFTP data transfer * (upload). The data associated with the given stream is expected to be a * pointer to an open LIBSSH2_SFTP_HANDLE for the file to which the data * should be written. * * @param user * The user receiving the blob message. * * @param stream * The Guacamole protocol stream associated with the received blob message. * * @param data * The data received within the blob. * * @param length * The length of the received data, in bytes. * * @return * Zero if the blob is handled successfully, or non-zero on error. */ static int guac_common_ssh_sftp_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { /* Pull file from stream */ LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data; /* Attempt write */ if (libssh2_sftp_write(file, data, length) == length) { guac_user_log(user, GUAC_LOG_DEBUG, "%i bytes written", length); guac_protocol_send_ack(user->socket, stream, "SFTP: OK", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(user->socket); } /* Inform of any errors */ else { guac_user_log(user, GUAC_LOG_INFO, "Unable to write to file"); guac_protocol_send_ack(user->socket, stream, "SFTP: Write failed", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(user->socket); } return 0; } /** * Handler for end messages which terminate an inbound SFTP data transfer * (upload). The data associated with the given stream is expected to be a * pointer to an open LIBSSH2_SFTP_HANDLE for the file to which the data * has been written and which should now be closed. * * @param user * The user receiving the end message. * * @param stream * The Guacamole protocol stream associated with the received end message. * * @return * Zero if the file is closed successfully, or non-zero on error. */ static int guac_common_ssh_sftp_end_handler(guac_user* user, guac_stream* stream) { /* Pull file from stream */ LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data; /* Attempt to close file */ if (libssh2_sftp_close(file) == 0) { guac_user_log(user, GUAC_LOG_DEBUG, "File closed"); guac_protocol_send_ack(user->socket, stream, "SFTP: OK", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(user->socket); } else { guac_user_log(user, GUAC_LOG_INFO, "Unable to close file"); guac_protocol_send_ack(user->socket, stream, "SFTP: Close failed", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(user->socket); } return 0; } int guac_common_ssh_sftp_handle_file_stream( guac_common_ssh_sftp_filesystem* filesystem, guac_user* user, guac_stream* stream, char* mimetype, char* filename) { char fullpath[GUAC_COMMON_SSH_SFTP_MAX_PATH]; LIBSSH2_SFTP_HANDLE* file; /* Ignore upload if uploads have been disabled */ if (filesystem->disable_upload) { guac_user_log(user, GUAC_LOG_WARNING, "A upload attempt has " "been blocked due to uploads being disabled, however it " "should have been blocked at a higher level. This is likely " "a bug."); guac_protocol_send_ack(user->socket, stream, "SFTP: Upload disabled", GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); guac_socket_flush(user->socket); return 0; } /* Concatenate filename with path */ if (!guac_ssh_append_filename(fullpath, filesystem->upload_path, filename)) { guac_user_log(user, GUAC_LOG_DEBUG, "Filename \"%s\" is invalid or resulting path is too long", filename); /* Abort transfer - invalid filename */ guac_protocol_send_ack(user->socket, stream, "SFTP: Illegal filename", GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST); guac_socket_flush(user->socket); return 0; } /* Open file via SFTP */ file = libssh2_sftp_open(filesystem->sftp_session, fullpath, LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC, S_IRUSR | S_IWUSR); /* Inform of status */ if (file != NULL) { guac_user_log(user, GUAC_LOG_DEBUG, "File \"%s\" opened", fullpath); guac_protocol_send_ack(user->socket, stream, "SFTP: File opened", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(user->socket); } else { guac_user_log(user, GUAC_LOG_INFO, "Unable to open file \"%s\"", fullpath); guac_protocol_send_ack(user->socket, stream, "SFTP: Open failed", guac_sftp_get_status(filesystem)); guac_socket_flush(user->socket); } /* Set handlers for file stream */ stream->blob_handler = guac_common_ssh_sftp_blob_handler; stream->end_handler = guac_common_ssh_sftp_end_handler; /* Store file within stream */ stream->data = file; return 0; } /** * Handler for ack messages which continue an outbound SFTP data transfer * (download), signaling the current status and requesting additional data. * The data associated with the given stream is expected to be a pointer to an * open LIBSSH2_SFTP_HANDLE for the file from which the data is to be read. * * @param user * The user receiving the ack message. * * @param stream * The Guacamole protocol stream associated with the received ack message. * * @param message * An arbitrary human-readable message describing the nature of the * success or failure denoted by the ack message. * * @param status * The status code associated with the ack message, which may indicate * success or an error. * * @return * Zero if the file is read from successfully, or non-zero on error. */ static int guac_common_ssh_sftp_ack_handler(guac_user* user, guac_stream* stream, char* message, guac_protocol_status status) { /* Pull file from stream */ LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data; /* If successful, read data */ if (status == GUAC_PROTOCOL_STATUS_SUCCESS) { /* Attempt read into buffer */ char buffer[4096]; int bytes_read = libssh2_sftp_read(file, buffer, sizeof(buffer)); /* If bytes read, send as blob */ if (bytes_read > 0) { guac_protocol_send_blob(user->socket, stream, buffer, bytes_read); guac_user_log(user, GUAC_LOG_DEBUG, "%i bytes sent to user", bytes_read); } /* If bytes could not be read, handle EOF or error condition */ else { /* If EOF, send end */ if (bytes_read == 0) { guac_user_log(user, GUAC_LOG_DEBUG, "File sent"); guac_protocol_send_end(user->socket, stream); guac_user_free_stream(user, stream); } /* Otherwise, fail stream */ else { guac_user_log(user, GUAC_LOG_INFO, "Error reading file"); guac_protocol_send_end(user->socket, stream); guac_user_free_stream(user, stream); } /* Close file */ if (libssh2_sftp_close(file) == 0) guac_user_log(user, GUAC_LOG_DEBUG, "File closed"); else guac_user_log(user, GUAC_LOG_INFO, "Unable to close file"); } guac_socket_flush(user->socket); } /* Otherwise, return stream to user */ else guac_user_free_stream(user, stream); return 0; } guac_stream* guac_common_ssh_sftp_download_file( guac_common_ssh_sftp_filesystem* filesystem, guac_user* user, char* filename) { guac_stream* stream; LIBSSH2_SFTP_HANDLE* file; /* Ignore download if downloads have been disabled */ if (filesystem->disable_download) { guac_user_log(user, GUAC_LOG_WARNING, "A download attempt has " "been blocked due to downloads being disabled, however it " "should have been blocked at a higher level. This is likely " "a bug."); return NULL; } /* Attempt to open file for reading */ file = libssh2_sftp_open(filesystem->sftp_session, filename, LIBSSH2_FXF_READ, 0); if (file == NULL) { guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"", filename); return NULL; } /* Allocate stream */ stream = guac_user_alloc_stream(user); stream->ack_handler = guac_common_ssh_sftp_ack_handler; stream->data = file; /* Send stream start, strip name */ filename = basename(filename); guac_protocol_send_file(user->socket, stream, "application/octet-stream", filename); guac_socket_flush(user->socket); guac_user_log(user, GUAC_LOG_DEBUG, "Sending file \"%s\"", filename); return stream; } void guac_common_ssh_sftp_set_upload_path( guac_common_ssh_sftp_filesystem* filesystem, const char* path) { guac_client* client = filesystem->ssh_session->client; /* Ignore requests which exceed maximum-allowed path */ int length = strnlen(path, GUAC_COMMON_SSH_SFTP_MAX_PATH)+1; if (length > GUAC_COMMON_SSH_SFTP_MAX_PATH) { guac_client_log(client, GUAC_LOG_ERROR, "Submitted path exceeds limit of %i bytes", GUAC_COMMON_SSH_SFTP_MAX_PATH); return; } /* Copy path */ memcpy(filesystem->upload_path, path, length); guac_client_log(client, GUAC_LOG_DEBUG, "Upload path set to \"%s\"", path); } /** * Handler for ack messages received due to receipt of a "body" or "blob" * instruction associated with a SFTP directory list operation. * * @param user * The user receiving the ack message. * * @param stream * The Guacamole protocol stream associated with the received ack message. * * @param message * An arbitrary human-readable message describing the nature of the * success or failure denoted by this ack message. * * @param status * The status code associated with this ack message, which may indicate * success or an error. * * @return * Zero on success, non-zero on error. */ static int guac_common_ssh_sftp_ls_ack_handler(guac_user* user, guac_stream* stream, char* message, guac_protocol_status status) { int bytes_read; char filename[GUAC_COMMON_SSH_SFTP_MAX_PATH]; LIBSSH2_SFTP_ATTRIBUTES attributes; guac_common_ssh_sftp_ls_state* list_state = (guac_common_ssh_sftp_ls_state*) stream->data; guac_common_ssh_sftp_filesystem* filesystem = list_state->filesystem; LIBSSH2_SFTP* sftp = filesystem->sftp_session; /* If unsuccessful, free stream and abort */ if (status != GUAC_PROTOCOL_STATUS_SUCCESS) { libssh2_sftp_closedir(list_state->directory); guac_user_free_stream(user, stream); free(list_state); return 0; } /* While directory entries remain */ while ((bytes_read = libssh2_sftp_readdir(list_state->directory, filename, sizeof(filename), &attributes)) > 0) { char absolute_path[GUAC_COMMON_SSH_SFTP_MAX_PATH]; /* Skip current and parent directory entries */ if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; /* Concatenate into absolute path - skip if invalid */ if (!guac_ssh_append_filename(absolute_path, list_state->directory_name, filename)) { guac_user_log(user, GUAC_LOG_DEBUG, "Skipping filename \"%s\" - filename is invalid or " "resulting path is too long", filename); continue; } /* Stat explicitly if symbolic link (might point to directory) */ if (LIBSSH2_SFTP_S_ISLNK(attributes.permissions)) libssh2_sftp_stat(sftp, absolute_path, &attributes); /* Determine mimetype */ const char* mimetype; if (LIBSSH2_SFTP_S_ISDIR(attributes.permissions)) mimetype = GUAC_USER_STREAM_INDEX_MIMETYPE; else mimetype = "application/octet-stream"; /* Write entry, waiting for next ack if a blob is written */ if (guac_common_json_write_property(user, stream, &list_state->json_state, absolute_path, mimetype)) break; } /* Complete JSON and cleanup at end of directory */ if (bytes_read <= 0) { /* Complete JSON object */ guac_common_json_end_object(user, stream, &list_state->json_state); guac_common_json_flush(user, stream, &list_state->json_state); /* Clean up resources */ libssh2_sftp_closedir(list_state->directory); free(list_state); /* Signal of stream */ guac_protocol_send_end(user->socket, stream); guac_user_free_stream(user, stream); } guac_socket_flush(user->socket); return 0; } /** * Translates a stream name for the given SFTP filesystem object into the * absolute path corresponding to the actual file it represents. * * @param fullpath * The buffer to populate with the translated path. This buffer MUST be at * least GUAC_COMMON_SSH_SFTP_MAX_PATH bytes in size. * * @param object * The Guacamole protocol object associated with the SFTP filesystem. * * @param name * The name of the stream (file) to translate into an absolute path. * * @return * Non-zero if translation succeeded, zero otherwise. */ static int guac_common_ssh_sftp_translate_name(char* fullpath, guac_object* object, char* name) { char normalized_name[GUAC_COMMON_SSH_SFTP_MAX_PATH]; guac_common_ssh_sftp_filesystem* filesystem = (guac_common_ssh_sftp_filesystem*) object->data; /* Normalize stream name into a path, and append to the root path */ return guac_common_ssh_sftp_normalize_path(normalized_name, name) && guac_ssh_append_path(fullpath, filesystem->root_path, normalized_name); } /** * Handler for get messages. In context of SFTP and the filesystem exposed via * the Guacamole protocol, get messages request the body of a file within the * filesystem. * * @param user * The user who sent the get message. * * @param object * The Guacamole protocol object associated with the get request itself. * * @param name * The name of the input stream (file) being requested. * * @return * Zero on success, non-zero on error. */ static int guac_common_ssh_sftp_get_handler(guac_user* user, guac_object* object, char* name) { char fullpath[GUAC_COMMON_SSH_SFTP_MAX_PATH]; guac_common_ssh_sftp_filesystem* filesystem = (guac_common_ssh_sftp_filesystem*) object->data; LIBSSH2_SFTP* sftp = filesystem->sftp_session; LIBSSH2_SFTP_ATTRIBUTES attributes; /* Translate stream name into filesystem path */ if (!guac_common_ssh_sftp_translate_name(fullpath, object, name)) { guac_user_log(user, GUAC_LOG_INFO, "Unable to generate real path " "for stream \"%s\"", name); return 0; } /* Attempt to read file information */ if (libssh2_sftp_stat(sftp, fullpath, &attributes)) { guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"", fullpath); return 0; } /* If directory, send contents of directory */ if (LIBSSH2_SFTP_S_ISDIR(attributes.permissions)) { /* Open as directory */ LIBSSH2_SFTP_HANDLE* dir = libssh2_sftp_opendir(sftp, fullpath); if (dir == NULL) { guac_user_log(user, GUAC_LOG_INFO, "Unable to read directory \"%s\"", fullpath); return 0; } /* Init directory listing state */ guac_common_ssh_sftp_ls_state* list_state = malloc(sizeof(guac_common_ssh_sftp_ls_state)); list_state->directory = dir; list_state->filesystem = filesystem; int length = guac_strlcpy(list_state->directory_name, name, sizeof(list_state->directory_name)); /* Bail out if directory name is too long to store */ if (length >= sizeof(list_state->directory_name)) { guac_user_log(user, GUAC_LOG_INFO, "Unable to read directory " "\"%s\": Path too long", fullpath); free(list_state); return 0; } /* Allocate stream for body */ guac_stream* stream = guac_user_alloc_stream(user); stream->ack_handler = guac_common_ssh_sftp_ls_ack_handler; stream->data = list_state; /* Init JSON object state */ guac_common_json_begin_object(user, stream, &list_state->json_state); /* Associate new stream with get request */ guac_protocol_send_body(user->socket, object, stream, GUAC_USER_STREAM_INDEX_MIMETYPE, name); } /* Otherwise, send file contents */ else { /* If downloads are disabled, log and return. */ if (filesystem->disable_download) { guac_user_log(user, GUAC_LOG_INFO, "Unable to download file \"%s\", " "file downloads have been disabled.", fullpath); return 0; } /* Open as normal file */ LIBSSH2_SFTP_HANDLE* file = libssh2_sftp_open(sftp, fullpath, LIBSSH2_FXF_READ, 0); if (file == NULL) { guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"", fullpath); return 0; } /* Allocate stream for body */ guac_stream* stream = guac_user_alloc_stream(user); stream->ack_handler = guac_common_ssh_sftp_ack_handler; stream->data = file; /* Associate new stream with get request */ guac_protocol_send_body(user->socket, object, stream, "application/octet-stream", name); } guac_socket_flush(user->socket); return 0; } /** * Handler for put messages. In context of SFTP and the filesystem exposed via * the Guacamole protocol, put messages request write access to a file within * the filesystem. * * @param user * The user who sent the put message. * * @param object * The Guacamole protocol object associated with the put request itself. * * @param stream * The Guacamole protocol stream along which the user will be sending * file data. * * @param mimetype * The mimetype of the data being send along the stream. * * @param name * The name of the input stream (file) being requested. * * @return * Zero on success, non-zero on error. */ static int guac_common_ssh_sftp_put_handler(guac_user* user, guac_object* object, guac_stream* stream, char* mimetype, char* name) { char fullpath[GUAC_COMMON_SSH_SFTP_MAX_PATH]; guac_common_ssh_sftp_filesystem* filesystem = (guac_common_ssh_sftp_filesystem*) object->data; /* Ignore upload if uploads have been disabled */ if (filesystem->disable_upload) { guac_user_log(user, GUAC_LOG_WARNING, "A upload attempt has " "been blocked due to uploads being disabled, however it " "should have been blocked at a higher level. This is likely " "a bug."); guac_protocol_send_ack(user->socket, stream, "SFTP: Upload disabled", GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); guac_socket_flush(user->socket); return 0; } LIBSSH2_SFTP* sftp = filesystem->sftp_session; /* Translate stream name into filesystem path */ if (!guac_common_ssh_sftp_translate_name(fullpath, object, name)) { guac_user_log(user, GUAC_LOG_INFO, "Unable to generate real path " "for stream \"%s\"", name); return 0; } /* Open file via SFTP */ LIBSSH2_SFTP_HANDLE* file = libssh2_sftp_open(sftp, fullpath, LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC, S_IRUSR | S_IWUSR); /* Acknowledge stream if successful */ if (file != NULL) { guac_user_log(user, GUAC_LOG_DEBUG, "File \"%s\" opened", fullpath); guac_protocol_send_ack(user->socket, stream, "SFTP: File opened", GUAC_PROTOCOL_STATUS_SUCCESS); } /* Abort on failure */ else { guac_user_log(user, GUAC_LOG_INFO, "Unable to open file \"%s\"", fullpath); guac_protocol_send_ack(user->socket, stream, "SFTP: Open failed", guac_sftp_get_status(filesystem)); } /* Set handlers for file stream */ stream->blob_handler = guac_common_ssh_sftp_blob_handler; stream->end_handler = guac_common_ssh_sftp_end_handler; /* Store file within stream */ stream->data = file; guac_socket_flush(user->socket); return 0; } void* guac_common_ssh_expose_sftp_filesystem(guac_user* user, void* data) { guac_common_ssh_sftp_filesystem* filesystem = (guac_common_ssh_sftp_filesystem*) data; /* No need to expose if there is no filesystem or the user has left */ if (user == NULL || filesystem == NULL) return NULL; /* Allocate and expose filesystem object for user */ return guac_common_ssh_alloc_sftp_filesystem_object(filesystem, user); } guac_object* guac_common_ssh_alloc_sftp_filesystem_object( guac_common_ssh_sftp_filesystem* filesystem, guac_user* user) { /* Init filesystem */ guac_object* fs_object = guac_user_alloc_object(user); fs_object->get_handler = guac_common_ssh_sftp_get_handler; /* Only handle uploads if not disabled. */ if (!filesystem->disable_upload) fs_object->put_handler = guac_common_ssh_sftp_put_handler; fs_object->data = filesystem; /* Send filesystem to user */ guac_protocol_send_filesystem(user->socket, fs_object, filesystem->name); guac_socket_flush(user->socket); return fs_object; } guac_common_ssh_sftp_filesystem* guac_common_ssh_create_sftp_filesystem( guac_common_ssh_session* session, const char* root_path, const char* name, int disable_download, int disable_upload) { /* Request SFTP */ LIBSSH2_SFTP* sftp_session = libssh2_sftp_init(session->session); if (sftp_session == NULL) return NULL; /* Allocate data for SFTP session */ guac_common_ssh_sftp_filesystem* filesystem = malloc(sizeof(guac_common_ssh_sftp_filesystem)); /* Associate SSH session with SFTP data and user */ filesystem->ssh_session = session; filesystem->sftp_session = sftp_session; /* Copy over disable flags */ filesystem->disable_download = disable_download; filesystem->disable_upload = disable_upload; /* Normalize and store the provided root path */ if (!guac_common_ssh_sftp_normalize_path(filesystem->root_path, root_path)) { guac_client_log(session->client, GUAC_LOG_WARNING, "Cannot create " "SFTP filesystem - \"%s\" is not a valid path.", root_path); free(filesystem); return NULL; } /* Generate filesystem name from root path if no name is provided */ if (name != NULL) filesystem->name = strdup(name); else filesystem->name = strdup(filesystem->root_path); /* Initially upload files to current directory */ strcpy(filesystem->upload_path, "."); /* Return allocated filesystem */ return filesystem; } void guac_common_ssh_destroy_sftp_filesystem( guac_common_ssh_sftp_filesystem* filesystem) { /* Shutdown SFTP session */ libssh2_sftp_shutdown(filesystem->sftp_session); /* Free associated memory */ free(filesystem->name); free(filesystem); } guacamole-server-1.3.0/src/common-ssh/ssh.c0000644000175100001440000004571513764613616015536 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common-ssh/key.h" #include "common-ssh/ssh.h" #include "common-ssh/user.h" #include #include #ifdef LIBSSH2_USES_GCRYPT #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifdef LIBSSH2_USES_GCRYPT GCRY_THREAD_OPTION_PTHREAD_IMPL; #endif #ifdef OPENSSL_REQUIRES_THREADING_CALLBACKS /** * Array of mutexes, used by OpenSSL. */ static pthread_mutex_t* guac_common_ssh_openssl_locks = NULL; /** * Called by OpenSSL when locking or unlocking the Nth mutex. * * @param mode * A bitmask denoting the action to be taken on the Nth lock, such as * CRYPTO_LOCK or CRYPTO_UNLOCK. * * @param n * The index of the lock to lock or unlock. * * @param file * The filename of the function setting the lock, for debugging purposes. * * @param line * The line number of the function setting the lock, for debugging * purposes. */ static void guac_common_ssh_openssl_locking_callback(int mode, int n, const char* file, int line){ /* Lock given mutex upon request */ if (mode & CRYPTO_LOCK) pthread_mutex_lock(&(guac_common_ssh_openssl_locks[n])); /* Unlock given mutex upon request */ else if (mode & CRYPTO_UNLOCK) pthread_mutex_unlock(&(guac_common_ssh_openssl_locks[n])); } /** * Called by OpenSSL when determining the current thread ID. * * @return * An ID which uniquely identifies the current thread. */ static unsigned long guac_common_ssh_openssl_id_callback() { return (unsigned long) pthread_self(); } /** * Creates the given number of mutexes, such that OpenSSL will have at least * this number of mutexes at its disposal. * * @param count * The number of mutexes (locks) to create. */ static void guac_common_ssh_openssl_init_locks(int count) { int i; /* Allocate required number of locks */ guac_common_ssh_openssl_locks = malloc(sizeof(pthread_mutex_t) * count); /* Initialize each lock */ for (i=0; i < count; i++) pthread_mutex_init(&(guac_common_ssh_openssl_locks[i]), NULL); } /** * Frees the given number of mutexes. * * @param count * The number of mutexes (locks) to free. */ static void guac_common_ssh_openssl_free_locks(int count) { int i; /* SSL lock array was not initialized */ if (guac_common_ssh_openssl_locks == NULL) return; /* Free all locks */ for (i=0; i < count; i++) pthread_mutex_destroy(&(guac_common_ssh_openssl_locks[i])); /* Free lock array */ free(guac_common_ssh_openssl_locks); } #endif int guac_common_ssh_init(guac_client* client) { #ifdef LIBSSH2_USES_GCRYPT /* Init threadsafety in libgcrypt */ gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); if (!gcry_check_version(GCRYPT_VERSION)) { guac_client_log(client, GUAC_LOG_ERROR, "libgcrypt version mismatch."); return 1; } #endif #ifdef OPENSSL_REQUIRES_THREADING_CALLBACKS /* Init threadsafety in OpenSSL */ guac_common_ssh_openssl_init_locks(CRYPTO_num_locks()); CRYPTO_set_id_callback(guac_common_ssh_openssl_id_callback); CRYPTO_set_locking_callback(guac_common_ssh_openssl_locking_callback); #endif /* Init OpenSSL */ SSL_library_init(); ERR_load_crypto_strings(); /* Init libssh2 */ libssh2_init(0); /* Success */ return 0; } void guac_common_ssh_uninit() { #ifdef OPENSSL_REQUIRES_THREADING_CALLBACKS guac_common_ssh_openssl_free_locks(CRYPTO_num_locks()); #endif } /** * Callback invoked by libssh2 when libssh2_userauth_publickkey() is invoked. * This callback must sign the given data, returning the signature as newly- * allocated buffer space. * * @param session * The SSH session for which the signature is being generated. * * @param sig * A pointer to the buffer space containing the signature. This callback * MUST allocate and assign this space. * * @param sig_len * The length of the signature within the allocated buffer space, in bytes. * This value must be set to the size of the signature after the signing * operation completes. * * @param data * The arbitrary data that must be signed. * * @param data_len * The length of the arbitrary data to be signed, in bytes. * * @param abstract * The value of the abstract parameter provided with the corresponding call * to libssh2_userauth_publickey(). * * @return * Zero on success, non-zero if the signing operation failed. */ static int guac_common_ssh_sign_callback(LIBSSH2_SESSION* session, unsigned char** sig, size_t* sig_len, const unsigned char* data, size_t data_len, void **abstract) { guac_common_ssh_key* key = (guac_common_ssh_key*) abstract; int length; /* Allocate space for signature */ *sig = malloc(4096); /* Sign with key */ length = guac_common_ssh_key_sign(key, (const char*) data, data_len, *sig); if (length < 0) return 1; *sig_len = length; return 0; } /** * Callback for the keyboard-interactive authentication method. Currently * supports just one prompt for the password. This callback is invoked as * needed to fullfill a call to libssh2_userauth_keyboard_interactive(). * * @param name * An arbitrary name which should be printed to the terminal for the * benefit of the user. This is currently ignored. * * @param name_len * The length of the name string, in bytes. * * @param instruction * Arbitrary instructions which should be printed to the terminal for the * benefit of the user. This is currently ignored. * * @param instruction_len * The length of the instruction string, in bytes. * * @param num_prompts * The number of keyboard-interactive prompts for which responses are * requested. This callback currently only supports one prompt, and assumes * that this prompt is requesting the password. * * @param prompts * An array of all keyboard-interactive prompts for which responses are * requested. * * @param responses * A parallel array into which all prompt responses should be stored. Each * entry within this array corresponds to the entry in the prompts array * with the same index. * * @param abstract * The value of the abstract parameter provided when the SSH session was * created with libssh2_session_init_ex(). */ static void guac_common_ssh_kbd_callback(const char *name, int name_len, const char *instruction, int instruction_len, int num_prompts, const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, void **abstract) { guac_common_ssh_session* common_session = (guac_common_ssh_session*) *abstract; guac_client* client = common_session->client; /* Send password if only one prompt */ if (num_prompts == 1) { char* password = common_session->user->password; responses[0].text = strdup(password); responses[0].length = strlen(password); } /* If more than one prompt, a single password is not enough */ else guac_client_log(client, GUAC_LOG_WARNING, "Unsupported number of keyboard-interactive prompts: %i", num_prompts); } /** * Authenticates the user associated with the given session over SSH. All * required credentials must already be present within the user object * associated with the given session. * * @param session * The session associated with the user to be authenticated. * * @return * Zero if authentication succeeds, or non-zero if authentication has * failed. */ static int guac_common_ssh_authenticate(guac_common_ssh_session* common_session) { guac_client* client = common_session->client; guac_common_ssh_user* user = common_session->user; LIBSSH2_SESSION* session = common_session->session; /* Get user credentials */ guac_common_ssh_key* key = user->private_key; /* Validate username provided */ if (user->username == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED, "SSH authentication requires a username."); return 1; } /* Get list of supported authentication methods */ char* user_authlist = libssh2_userauth_list(session, user->username, strlen(user->username)); /* If auth list is NULL, then authentication has succeeded with NONE */ if (user_authlist == NULL) { guac_client_log(client, GUAC_LOG_DEBUG, "SSH NONE authentication succeeded."); return 0; } guac_client_log(client, GUAC_LOG_DEBUG, "Supported authentication methods: %s", user_authlist); /* Authenticate with private key, if provided */ if (key != NULL) { /* Check if public key auth is supported on the server */ if (strstr(user_authlist, "publickey") == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED, "Public key authentication is not supported by " "the SSH server"); return 1; } /* Attempt public key auth */ if (libssh2_userauth_publickey(session, user->username, (unsigned char*) key->public_key, key->public_key_length, guac_common_ssh_sign_callback, (void**) key)) { /* Abort on failure */ char* error_message; libssh2_session_last_error(session, &error_message, NULL, 0); guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED, "Public key authentication failed: %s", error_message); return 1; } /* Private key authentication succeeded */ return 0; } /* Attempt authentication with username + password. */ if (user->password == NULL && common_session->credential_handler) user->password = common_session->credential_handler(client, "Password: "); /* Authenticate with password, if provided */ if (user->password != NULL) { /* Check if password auth is supported on the server */ if (strstr(user_authlist, "password") != NULL) { /* Attempt password authentication */ if (libssh2_userauth_password(session, user->username, user->password)) { /* Abort on failure */ char* error_message; libssh2_session_last_error(session, &error_message, NULL, 0); guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED, "Password authentication failed: %s", error_message); return 1; } /* Password authentication succeeded */ return 0; } /* Check if keyboard-interactive auth is supported on the server */ if (strstr(user_authlist, "keyboard-interactive") != NULL) { /* Attempt keyboard-interactive auth using provided password */ if (libssh2_userauth_keyboard_interactive(session, user->username, &guac_common_ssh_kbd_callback)) { /* Abort on failure */ char* error_message; libssh2_session_last_error(session, &error_message, NULL, 0); guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED, "Keyboard-interactive authentication failed: %s", error_message); return 1; } /* Keyboard-interactive authentication succeeded */ return 0; } /* No known authentication types available */ guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED, "Password and keyboard-interactive authentication are not " "supported by the SSH server"); return 1; } /* No credentials provided */ guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED, "SSH authentication requires either a private key or a password."); return 1; } guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client, const char* hostname, const char* port, guac_common_ssh_user* user, int keepalive, const char* host_key, guac_ssh_credential_handler* credential_handler) { int retval; int fd; struct addrinfo* addresses; struct addrinfo* current_address; char connected_address[1024]; char connected_port[64]; struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP }; /* Get addresses connection */ if ((retval = getaddrinfo(hostname, port, &hints, &addresses))) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error parsing given address or port: %s", gai_strerror(retval)); return NULL; } /* Attempt connection to each address until success */ current_address = addresses; while (current_address != NULL) { /* Resolve hostname */ if ((retval = getnameinfo(current_address->ai_addr, current_address->ai_addrlen, connected_address, sizeof(connected_address), connected_port, sizeof(connected_port), NI_NUMERICHOST | NI_NUMERICSERV))) guac_client_log(client, GUAC_LOG_DEBUG, "Unable to resolve host: %s", gai_strerror(retval)); /* Get socket */ fd = socket(current_address->ai_family, SOCK_STREAM, 0); if (fd < 0) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to create socket: %s", strerror(errno)); freeaddrinfo(addresses); return NULL; } /* Connect */ if (connect(fd, current_address->ai_addr, current_address->ai_addrlen) == 0) { guac_client_log(client, GUAC_LOG_DEBUG, "Successfully connected to host %s, port %s", connected_address, connected_port); /* Done if successful connect */ break; } /* Otherwise log information regarding bind failure */ guac_client_log(client, GUAC_LOG_DEBUG, "Unable to connect to " "host %s, port %s: %s", connected_address, connected_port, strerror(errno)); close(fd); current_address = current_address->ai_next; } /* Free addrinfo */ freeaddrinfo(addresses); /* If unable to connect to anything, fail */ if (current_address == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND, "Unable to connect to any addresses."); return NULL; } /* Allocate new session */ guac_common_ssh_session* common_session = malloc(sizeof(guac_common_ssh_session)); /* Open SSH session */ LIBSSH2_SESSION* session = libssh2_session_init_ex(NULL, NULL, NULL, common_session); if (session == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Session allocation failed."); free(common_session); close(fd); return NULL; } /* Perform handshake */ if (libssh2_session_handshake(session, fd)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "SSH handshake failed."); free(common_session); close(fd); return NULL; } /* Get host key of remote system we're connecting to */ size_t remote_hostkey_len; const char *remote_hostkey = libssh2_session_hostkey(session, &remote_hostkey_len, NULL); /* Failure to retrieve a host key means we should abort */ if (!remote_hostkey) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Failed to get host key for %s", hostname); free(common_session); close(fd); return NULL; } /* SSH known host key checking. */ int known_host_check = guac_common_ssh_verify_host_key(session, client, host_key, hostname, atoi(port), remote_hostkey, remote_hostkey_len); /* Abort on any error codes */ if (known_host_check != 0) { char* err_msg; libssh2_session_last_error(session, &err_msg, NULL, 0); if (known_host_check < 0) guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error occurred attempting to check host key: %s", err_msg); if (known_host_check > 0) guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Host key did not match any provided known host keys. %s", err_msg); free(common_session); close(fd); return NULL; } /* Store basic session data */ common_session->client = client; common_session->user = user; common_session->session = session; common_session->fd = fd; common_session->credential_handler = credential_handler; /* Attempt authentication */ if (guac_common_ssh_authenticate(common_session)) { free(common_session); close(fd); return NULL; } /* Warn if keepalive below minimum value */ if (keepalive < 0) { keepalive = 0; guac_client_log(client, GUAC_LOG_WARNING, "negative keepalive intervals " "are converted to 0, disabling keepalive."); } else if (keepalive == 1) { guac_client_log(client, GUAC_LOG_WARNING, "keepalive interval will " "be rounded up to minimum value of 2."); } /* Configure session keepalive */ libssh2_keepalive_config(common_session->session, 1, keepalive); /* Return created session */ return common_session; } void guac_common_ssh_destroy_session(guac_common_ssh_session* session) { /* Disconnect and clean up libssh2 */ libssh2_session_disconnect(session->session, "Bye"); libssh2_session_free(session->session); /* Free all other data */ free(session); } guacamole-server-1.3.0/src/common-ssh/Makefile.am0000644000175100001440000000403513764613616016617 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 noinst_LTLIBRARIES = libguac_common_ssh.la SUBDIRS = . tests libguac_common_ssh_la_SOURCES = \ buffer.c \ dsa-compat.c \ rsa-compat.c \ sftp.c \ ssh.c \ key.c \ user.c noinst_HEADERS = \ common-ssh/buffer.h \ common-ssh/dsa-compat.h \ common-ssh/rsa-compat.h \ common-ssh/key.h \ common-ssh/sftp.h \ common-ssh/ssh.h \ common-ssh/user.h libguac_common_ssh_la_CFLAGS = \ -Werror -Wall -pedantic \ @COMMON_INCLUDE@ \ @LIBGUAC_INCLUDE@ libguac_common_ssh_la_LIBADD = \ @LIBGUAC_LTLIB@ libguac_common_ssh_la_LDFLAGS = \ @PTHREAD_LIBS@ \ @SSH_LIBS@ \ @SSL_LIBS@ guacamole-server-1.3.0/src/common-ssh/buffer.c0000644000175100001440000000630713676721353016204 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include #include #include #include #include void guac_common_ssh_buffer_write_byte(char** buffer, uint8_t value) { uint8_t* data = (uint8_t*) *buffer; *data = value; (*buffer)++; } void guac_common_ssh_buffer_write_uint32(char** buffer, uint32_t value) { uint8_t* data = (uint8_t*) *buffer; data[0] = (value & 0xFF000000) >> 24; data[1] = (value & 0x00FF0000) >> 16; data[2] = (value & 0x0000FF00) >> 8; data[3] = value & 0x000000FF; *buffer += 4; } void guac_common_ssh_buffer_write_data(char** buffer, const char* data, int length) { memcpy(*buffer, data, length); *buffer += length; } void guac_common_ssh_buffer_write_bignum(char** buffer, const BIGNUM* value) { unsigned char* bn_buffer; int length; /* If zero, just write zero length */ if (BN_is_zero(value)) { guac_common_ssh_buffer_write_uint32(buffer, 0); return; } /* Allocate output buffer, add padding byte */ length = BN_num_bytes(value); bn_buffer = malloc(length); /* Convert BIGNUM */ BN_bn2bin(value, bn_buffer); /* If first byte has high bit set, write padding byte */ if (bn_buffer[0] & 0x80) { guac_common_ssh_buffer_write_uint32(buffer, length+1); guac_common_ssh_buffer_write_byte(buffer, 0); } else guac_common_ssh_buffer_write_uint32(buffer, length); /* Write data */ memcpy(*buffer, bn_buffer, length); *buffer += length; free(bn_buffer); } void guac_common_ssh_buffer_write_string(char** buffer, const char* string, int length) { guac_common_ssh_buffer_write_uint32(buffer, length); guac_common_ssh_buffer_write_data(buffer, string, length); } uint8_t guac_common_ssh_buffer_read_byte(char** buffer) { uint8_t* data = (uint8_t*) *buffer; uint8_t value = *data; (*buffer)++; return value; } uint32_t guac_common_ssh_buffer_read_uint32(char** buffer) { uint8_t* data = (uint8_t*) *buffer; uint32_t value = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; *buffer += 4; return value; } char* guac_common_ssh_buffer_read_string(char** buffer, int* length) { char* value; *length = guac_common_ssh_buffer_read_uint32(buffer); value = *buffer; *buffer += *length; return value; } guacamole-server-1.3.0/src/guaclog/0000755000175100001440000000000013772471157014200 500000000000000guacamole-server-1.3.0/src/guaclog/interpret.c0000644000175100001440000001075513702142276016276 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "instructions.h" #include "log.h" #include "state.h" #include #include #include #include #include #include #include #include #include #include #include /** * Reads and handles all Guacamole instructions from the given guac_socket * until end-of-stream is reached. * * @param state * The current state of the Guacamole input log interpreter. * * @param path * The name of the file being parsed (for logging purposes). This file * must already be open and available through the given socket. * * @param socket * The guac_socket through which instructions should be read. * * @return * Zero on success, non-zero if parsing of Guacamole protocol data through * the given socket fails. */ static int guaclog_read_instructions(guaclog_state* state, const char* path, guac_socket* socket) { /* Obtain Guacamole protocol parser */ guac_parser* parser = guac_parser_alloc(); if (parser == NULL) return 1; /* Continuously read and handle all instructions */ while (!guac_parser_read(parser, socket, -1)) { guaclog_handle_instruction(state, parser->opcode, parser->argc, parser->argv); } /* Fail on read/parse error */ if (guac_error != GUAC_STATUS_CLOSED) { guaclog_log(GUAC_LOG_ERROR, "%s: %s", path, guac_status_string(guac_error)); guac_parser_free(parser); return 1; } /* Parse complete */ guac_parser_free(parser); return 0; } int guaclog_interpret(const char* path, const char* out_path, bool force) { /* Open input file */ int fd = open(path, O_RDONLY); if (fd < 0) { guaclog_log(GUAC_LOG_ERROR, "%s: %s", path, strerror(errno)); return 1; } /* Lock entire input file for reading by the current process */ struct flock file_lock = { .l_type = F_RDLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0, .l_pid = getpid() }; /* Abort if file cannot be locked for reading */ if (!force && fcntl(fd, F_SETLK, &file_lock) == -1) { /* Warn if lock cannot be acquired */ if (errno == EACCES || errno == EAGAIN) guaclog_log(GUAC_LOG_WARNING, "Refusing to interpret log of " "in-progress session \"%s\" (specify the -f option to " "override this behavior).", path); /* Log an error if locking fails in an unexpected way */ else guaclog_log(GUAC_LOG_ERROR, "Cannot lock \"%s\" for reading: %s", path, strerror(errno)); close(fd); return 1; } /* Allocate input state for interpreting process */ guaclog_state* state = guaclog_state_alloc(out_path); if (state == NULL) { close(fd); return 1; } /* Obtain guac_socket wrapping file descriptor */ guac_socket* socket = guac_socket_open(fd); if (socket == NULL) { guaclog_log(GUAC_LOG_ERROR, "%s: %s", path, guac_status_string(guac_error)); close(fd); guaclog_state_free(state); return 1; } guaclog_log(GUAC_LOG_INFO, "Writing input events from \"%s\" " "to \"%s\" ...", path, out_path); /* Attempt to read all instructions in the file */ if (guaclog_read_instructions(state, path, socket)) { guac_socket_free(socket); guaclog_state_free(state); return 1; } /* Close input and finish interpreting process */ guac_socket_free(socket); return guaclog_state_free(state); } guacamole-server-1.3.0/src/guaclog/guaclog.h0000644000175100001440000000174713702142276015711 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACLOG_H #define GUACLOG_H #include "config.h" /** * The default log level below which no messages should be logged. */ #define GUACLOG_DEFAULT_LOG_LEVEL GUAC_LOG_INFO #endif guacamole-server-1.3.0/src/guaclog/instructions.h0000644000175100001440000000650213702142276017026 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACLOG_INSTRUCTIONS_H #define GUACLOG_INSTRUCTIONS_H #include "config.h" #include "state.h" /** * A callback function which, when invoked, handles a particular Guacamole * instruction. The opcode of the instruction is implied (as it is expected * that there will be a 1:1 mapping of opcode to callback function), while the * arguments for that instruction are included in the parameters given to the * callback. * * @param state * The current state of the Guacamole input log interpreter. * * @param argc * The number of arguments (excluding opcode) passed to the instruction * being handled by the callback. * * @param argv * All arguments (excluding opcode) associated with the instruction being * handled by the callback. * * @return * Zero if the instruction was handled successfully, non-zero if an error * occurs. */ typedef int guaclog_instruction_handler(guaclog_state* state, int argc, char** argv); /** * Mapping of instruction opcode to corresponding handler function. */ typedef struct guaclog_instruction_handler_mapping { /** * The opcode of the instruction that the associated handler function * should be invoked for. */ const char* opcode; /** * The handler function to invoke whenever an instruction having the * associated opcode is parsed. */ guaclog_instruction_handler* handler; } guaclog_instruction_handler_mapping; /** * Array of all opcode/handler mappings for all supported opcodes, terminated * by an entry with a NULL opcode. All opcodes not listed here can be safely * ignored. */ extern guaclog_instruction_handler_mapping guaclog_instruction_handler_map[]; /** * Handles the instruction having the given opcode and arguments, updating * the state of the interpreter accordingly. * * @param state * The current state of the Guacamole input log interpreter. * * @param opcode * The opcode of the instruction being handled. * * @param argc * The number of arguments (excluding opcode) passed to the instruction * being handled by the callback. * * @param argv * All arguments (excluding opcode) associated with the instruction being * handled by the callback. * * @return * Zero if the instruction was handled successfully, non-zero if an error * occurs. */ int guaclog_handle_instruction(guaclog_state* state, const char* opcode, int argc, char** argv); /** * Handler for the Guacamole "key" instruction. */ guaclog_instruction_handler guaclog_handle_key; #endif guacamole-server-1.3.0/src/guaclog/state.h0000644000175100001440000000663413702142276015410 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACLOG_STATE_H #define GUACLOG_STATE_H #include "config.h" #include "keydef.h" #include #include /** * The maximum number of keys which may be tracked at any one time before * newly-pressed keys are ignored. */ #define GUACLOG_MAX_KEYS 256 /** * The current state of a single key. */ typedef struct guaclog_key_state { /** * The definition of the key. */ guaclog_keydef* keydef; /** * Whether the key is currently pressed (true) or released (false). */ bool pressed; } guaclog_key_state; /** * The current state of the Guacamole input log interpreter. */ typedef struct guaclog_state { /** * Output file stream. */ FILE* output; /** * The number of keys currently being tracked within the key_states array. */ int active_keys; /** * Array of all keys currently being tracked. A key is added to the array * when it is pressed for the first time. Released keys at the end of the * array are automatically removed from tracking. */ guaclog_key_state key_states[GUACLOG_MAX_KEYS]; } guaclog_state; /** * Allocates a new state structure for the Guacamole input log interpreter. * This structure serves as the representation of interpreter state as * input-related instructions are read and handled. * * @param path * The full path to the file in which interpreted, human-readable should be * written. * * @return * The newly-allocated Guacamole input log interpreter state, or NULL if * the state could not be allocated. */ guaclog_state* guaclog_state_alloc(const char* path); /** * Frees all memory associated with the given Guacamole input log interpreter * state, and finishes any remaining interpreting process. If the given state * is NULL, this function has no effect. * * @param state * The Guacamole input log interpreter state to free, which may be NULL. * * @return * Zero if the interpreting process completed successfully, non-zero * otherwise. */ int guaclog_state_free(guaclog_state* state); /** * Updates the given Guacamole input log interpreter state, marking the given * key as pressed or released. * * @param state * The Guacamole input log interpreter state being updated. * * @param keysym * The X11 keysym of the key being pressed or released. * * @param pressed * true if the key is being pressed, false if the key is being released. * * @return * Zero if the interpreter state was updated successfully, non-zero * otherwise. */ int guaclog_state_update_key(guaclog_state* state, int keysym, bool pressed); #endif guacamole-server-1.3.0/src/guaclog/log.h0000644000175100001440000000372313702142276015045 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACLOG_LOG_H #define GUACLOG_LOG_H #include "config.h" #include #include /** * The maximum level at which to log messages. All other messages will be * dropped. */ extern int guaclog_log_level; /** * The string to prepend to all log messages. */ #define GUACLOG_LOG_NAME "guaclog" /** * Writes a message to guaclog's logs. This function takes a format and * va_list, similar to vprintf. * * @param level * The level at which to log this message. * * @param format * A printf-style format string to log. * * @param args * The va_list containing the arguments to be used when filling the format * string for printing. */ void vguaclog_log(guac_client_log_level level, const char* format, va_list args); /** * Writes a message to guaclog's logs. This function accepts parameters * identically to printf. * * @param level * The level at which to log this message. * * @param format * A printf-style format string to log. * * @param ... * Arguments to use when filling the format string for printing. */ void guaclog_log(guac_client_log_level level, const char* format, ...); #endif guacamole-server-1.3.0/src/guaclog/instruction-key.c0000644000175100001440000000247513702142276017431 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "log.h" #include "state.h" #include #include int guaclog_handle_key(guaclog_state* state, int argc, char** argv) { /* Verify argument count */ if (argc < 2) { guaclog_log(GUAC_LOG_WARNING, "\"key\" instruction incomplete"); return 1; } /* Parse arguments */ int keysym = atoi(argv[0]); bool pressed = (atoi(argv[1]) != 0); /* Update interpreter state accordingly */ return guaclog_state_update_key(state, keysym, pressed); } guacamole-server-1.3.0/src/guaclog/interpret.h0000644000175100001440000000332013702142276016271 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACLOG_INTERPRET_H #define GUACLOG_INTERPRET_H #include "config.h" #include /** * Interprets all input events within the given Guacamole protocol dump, * producing a human-readable log of those input events. A read lock will be * acquired on the input file to ensure that in-progress logs are not * interpreted. This behavior can be overridden by specifying true for the * force parameter. * * @param path * The path to the file containing the raw Guacamole protocol dump. * * @param out_path * The full path to the file in which interpreted log should be written. * * @param force * Interpret even if the input file appears to be an in-progress log (has * an associated lock). * * @return * Zero on success, non-zero if an error prevented successful * interpretation of the log. */ int guaclog_interpret(const char* path, const char* out_path, bool force); #endif guacamole-server-1.3.0/src/guaclog/state.c0000644000175100001440000001661513702142276015403 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "keydef.h" #include "log.h" #include "state.h" #include #include #include #include #include #include #include #include guaclog_state* guaclog_state_alloc(const char* path) { /* Open output file */ int fd = open(path, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); if (fd == -1) { guaclog_log(GUAC_LOG_ERROR, "Failed to open output file \"%s\": %s", path, strerror(errno)); goto fail_output_fd; } /* Create stream for output file */ FILE* output = fdopen(fd, "wb"); if (output == NULL) { guaclog_log(GUAC_LOG_ERROR, "Failed to allocate stream for output " "file \"%s\": %s", path, strerror(errno)); goto fail_output_file; } /* Allocate state */ guaclog_state* state = (guaclog_state*) calloc(1, sizeof(guaclog_state)); if (state == NULL) { goto fail_state; } /* Associate state with output file */ state->output = output; /* No keys are initially tracked */ state->active_keys = 0; return state; /* Free all allocated data in case of failure */ fail_state: fclose(output); fail_output_file: close(fd); fail_output_fd: return NULL; } int guaclog_state_free(guaclog_state* state) { int i; /* Ignore NULL state */ if (state == NULL) return 0; /* Free keydefs of all tracked keys */ for (i = 0; i < state->active_keys; i++) guaclog_keydef_free(state->key_states[i].keydef); /* Close output file */ fclose(state->output); free(state); return 0; } /** * Adds the given key state to the array of tracked keys. If the key is already * being tracked, its corresponding entry within the array of tracked keys is * updated, and the number of tracked keys remains the same. If the key is not * already being tracked, it is added to the end of the array of tracked keys * providing there is space available, and the number of tracked keys is * updated. Failures to add keys will be automatically logged. * * @param state * The Guacamole input log interpreter state being updated. * * @param keydef * The guaclog_keydef of the key being pressed or released. This * guaclog_keydef will automatically be freed along with the guaclog_state * if the key state was successfully added, and must be manually freed * otherwise. * * @param pressed * true if the key is being pressed, false if the key is being released. * * @return * Zero if the key state was successfully added, non-zero otherwise. */ static int guaclog_state_add_key(guaclog_state* state, guaclog_keydef* keydef, bool pressed) { int i; /* Update existing key, if already tracked */ for (i = 0; i < state->active_keys; i++) { guaclog_key_state* key = &state->key_states[i]; if (key->keydef->keysym == keydef->keysym) { guaclog_keydef_free(key->keydef); key->keydef = keydef; key->pressed = pressed; return 0; } } /* If not already tracked, we need space to add it */ if (state->active_keys == GUACLOG_MAX_KEYS) { guaclog_log(GUAC_LOG_WARNING, "Unable to log key 0x%X: Too many " "active keys.", keydef->keysym); return 1; } /* Add key to state */ guaclog_key_state* key = &state->key_states[state->active_keys++]; key->keydef = keydef; key->pressed = pressed; return 0; } /** * Removes released keys from the end of the array of tracked keys, such that * the last key in the array is a pressed key. This function should be invoked * after changes have been made to the interpreter state, to ensure that the * array of tracked keys does not grow longer than necessary. * * @param state * The Guacamole input log interpreter state to trim. */ static void guaclog_state_trim_keys(guaclog_state* state) { int i; /* Reset active_keys to contain only up to the last pressed key */ for (i = state->active_keys - 1; i >= 0; i--) { guaclog_key_state* key = &state->key_states[i]; if (key->pressed) { state->active_keys = i + 1; return; } /* Free all trimmed states */ guaclog_keydef_free(key->keydef); } /* No keys are active */ state->active_keys = 0; } /** * Returns whether the current tracked key state represents an in-progress * keyboard shortcut. * * @param state * The Guacamole input log interpreter state to test. * * @return * true if the given state represents an in-progress keyboard shortcut, * false otherwise. */ static bool guaclog_state_is_shortcut(guaclog_state* state) { int i; /* We are in a shortcut if at least one key is non-printable */ for (i = 0; i < state->active_keys; i++) { guaclog_key_state* key = &state->key_states[i]; if (key->keydef->value == NULL) return true; } /* All keys are printable - no shortcut */ return false; } int guaclog_state_update_key(guaclog_state* state, int keysym, bool pressed) { int i; /* Determine nature of key */ guaclog_keydef* keydef = guaclog_keydef_alloc(keysym); if (keydef == NULL) return 0; /* Update tracked key state for modifiers */ if (keydef->modifier) { /* Keydef will be automatically freed if successfully added to state */ if (guaclog_state_add_key(state, keydef, pressed)) guaclog_keydef_free(keydef); else guaclog_state_trim_keys(state); return 0; } /* Output key states only for printable keys */ if (pressed) { if (guaclog_state_is_shortcut(state)) { fprintf(state->output, "<"); /* Compose log entry by inspecting the state of each tracked key */ for (i = 0; i < state->active_keys; i++) { /* Translate keysym into human-readable name */ guaclog_key_state* key = &state->key_states[i]; /* Print name of key */ if (i == 0) fprintf(state->output, "%s", key->keydef->name); else fprintf(state->output, "+%s", key->keydef->name); } fprintf(state->output, "%s>", keydef->value); } /* Print the key itself */ else { if (keydef->value != NULL) fprintf(state->output, "%s", keydef->value); else fprintf(state->output, "<%s>", keydef->name); } } guaclog_keydef_free(keydef); return 0; } guacamole-server-1.3.0/src/guaclog/guaclog.c0000644000175100001440000000633213702142276015677 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guaclog.h" #include "interpret.h" #include "log.h" #include #include #include int main(int argc, char* argv[]) { int i; /* Load defaults */ bool force = false; /* Parse arguments */ int opt; while ((opt = getopt(argc, argv, "s:r:f")) != -1) { /* -f: Force */ if (opt == 'f') force = true; /* Invalid option */ else { goto invalid_options; } } /* Log start */ guaclog_log(GUAC_LOG_INFO, "Guacamole input log interpreter (guaclog) " "version " VERSION); /* Track number of overall failures */ int total_files = argc - optind; int failures = 0; /* Abort if no files given */ if (total_files <= 0) { guaclog_log(GUAC_LOG_INFO, "No input files specified. Nothing to do."); return 0; } guaclog_log(GUAC_LOG_INFO, "%i input file(s) provided.", total_files); /* Interpret all input files */ for (i = optind; i < argc; i++) { /* Get current filename */ const char* path = argv[i]; /* Generate output filename */ char out_path[4096]; int len = snprintf(out_path, sizeof(out_path), "%s.txt", path); /* Do not write if filename exceeds maximum length */ if (len >= sizeof(out_path)) { guaclog_log(GUAC_LOG_ERROR, "Cannot write output file for \"%s\": " "Name too long", path); continue; } /* Attempt interpreting, log granular success/failure at debug level */ if (guaclog_interpret(path, out_path, force)) { failures++; guaclog_log(GUAC_LOG_DEBUG, "%s was NOT successfully interpreted.", path); } else guaclog_log(GUAC_LOG_DEBUG, "%s was successfully " "interpreted.", path); } /* Warn if at least one file failed */ if (failures != 0) guaclog_log(GUAC_LOG_WARNING, "Interpreting failed for %i of %i " "file(s).", failures, total_files); /* Notify of success */ else guaclog_log(GUAC_LOG_INFO, "All files interpreted successfully."); /* Interpreting complete */ return 0; /* Display usage and exit with error if options are invalid */ invalid_options: fprintf(stderr, "USAGE: %s" " [-f]" " [FILE]...\n", argv[0]); return 1; } guacamole-server-1.3.0/src/guaclog/man/0000755000175100001440000000000013772471154014750 500000000000000guacamole-server-1.3.0/src/guaclog/man/guaclog.1.in0000644000175100001440000000771113702142276016777 00000000000000.\" .\" Licensed to the Apache Software Foundation (ASF) under one .\" or more contributor license agreements. See the NOTICE file .\" distributed with this work for additional information .\" regarding copyright ownership. The ASF licenses this file .\" to you under the Apache License, Version 2.0 (the .\" "License"); you may not use this file except in compliance .\" with the License. You may obtain a copy of the License at .\" .\" http://www.apache.org/licenses/LICENSE-2.0 .\" .\" Unless required by applicable law or agreed to in writing, .\" software distributed under the License is distributed on an .\" "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY .\" KIND, either express or implied. See the License for the .\" specific language governing permissions and limitations .\" under the License. .\" .TH guaclog 1 "26 Jan 2018" "version @PACKAGE_VERSION@" "Apache Guacamole" . .SH NAME guaclog \- Guacamole input log interpreter . .SH SYNOPSIS .B guaclog [\fB-f\fR] [\fIFILE\fR]... . .SH DESCRIPTION .B guaclog is an interpreter which accepts Guacamole protocol dumps, such as those saved when input logging is enabled for a Guacamole session recording, writing human-readable text logs as output. .B guaclog is essentially an implementation of a Guacamole client which accepts its input from files instead of a network connection, however unlike .B guacenc it only handles instructions related to user input. .P Each \fIFILE\fR specified will be translated into a new human-readable text file named \fIFILE\fR.txt. Existing files will not be overwritten; the interpreting process for any input file will be aborted if it would result in overwriting an existing file. .P Guacamole acquires a write lock on recordings as they are being written. By default, .B guaclog will check whether the each input file is locked and will refuse to read and interpret an input file if it appears to be an in-progress recording. This behavior can be overridden by specifying the \fB-f\fR option. Interpreting an in-progress recording will still work; the resulting human-readable text file will simply cover the user's session only up to the current point in time. . .SH OPTIONS .TP \fB-f\fR Overrides the default behavior of .B guaclog such that input files will be interpreted even if they appear to be recordings of in-progress Guacamole sessions. . .SH OUTPUT FORMAT The output format of .B guaclog is meant to match what the user would have typed within a typical text editor as closely as possible, while also representing non-printable characters and keyboard shortcuts in a human-readable way. .P All output is on one line, with new lines started only as a result of the user pressing enter/return. Keys which produce printable characters are translated into their corresponding Unicode codepoints and encoded as UTF-8, while non-printable characters are enclosed within angle brackets and represented with their human-readable names. Keyboard shortcuts which are made up of more than one key are enclosed within angle brackets, with each key within the shortcut separated by plus signs. .P Spaces and newlines are included as their Unicode character, except when represented within a keyboard shortcut, in which case their human-readable names are used instead. As the output of pressing tab can be easily mistaken for spaces, and as pressing tab frequently has special meaning within applications, tab is always represented by its human-readable name. .P Modifiers are output as part of keyboard shortcuts only. Simple pressing and releasing of a modifier will be ignored, as are presses of shift or AltGr while typing. .P For example, if the user typed "Hello WORLD!", selected everything by pressing Ctrl+a, copied the selected text by pressing Ctrl+c, switched to another application by pressing Alt+Shift+Tab, and then pasted the previously-copied text by pressing Ctrl+v, the resulting log from .B guaclog would look like: .PP .RS 0 Hello WORLD! . .SH SEE ALSO .BR guacenc (1) guacamole-server-1.3.0/src/guaclog/keydef.c0000644000175100001440000002166413702142276015532 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "keydef.h" #include "log.h" #include #include #include #include #include /** * All known keys. */ const guaclog_keydef known_keys[] = { { 0xFE03, "AltGr", "", true }, { 0xFF08, "Backspace" }, { 0xFF09, "Tab" }, { 0xFF0B, "Clear" }, { 0xFF0D, "Return", "\n" }, { 0xFF13, "Pause" }, { 0xFF14, "Scroll" }, { 0xFF15, "SysReq" }, { 0xFF1B, "Escape" }, { 0xFF50, "Home" }, { 0xFF51, "Left" }, { 0xFF52, "Up" }, { 0xFF53, "Right" }, { 0xFF54, "Down" }, { 0xFF55, "Page Up" }, { 0xFF56, "Page Down" }, { 0xFF57, "End" }, { 0xFF63, "Insert" }, { 0xFF65, "Undo" }, { 0xFF6A, "Help" }, { 0xFF7F, "Num" }, { 0xFF80, "Space", " " }, { 0xFF8D, "Enter", "\n" }, { 0xFF95, "Home" }, { 0xFF96, "Left" }, { 0xFF97, "Up" }, { 0xFF98, "Right" }, { 0xFF99, "Down" }, { 0xFF9A, "Page Up" }, { 0xFF9B, "Page Down" }, { 0xFF9C, "End" }, { 0xFF9E, "Insert" }, { 0xFFAA, "*", "*" }, { 0xFFAB, "+", "+" }, { 0xFFAD, "-", "-" }, { 0xFFAE, ".", "." }, { 0xFFAF, "/", "/" }, { 0xFFB0, "0", "0" }, { 0xFFB1, "1", "1" }, { 0xFFB2, "2", "2" }, { 0xFFB3, "3", "3" }, { 0xFFB4, "4", "4" }, { 0xFFB5, "5", "5" }, { 0xFFB6, "6", "6" }, { 0xFFB7, "7", "7" }, { 0xFFB8, "8", "8" }, { 0xFFB9, "9", "9" }, { 0xFFBE, "F1" }, { 0xFFBF, "F2" }, { 0xFFC0, "F3" }, { 0xFFC1, "F4" }, { 0xFFC2, "F5" }, { 0xFFC3, "F6" }, { 0xFFC4, "F7" }, { 0xFFC5, "F8" }, { 0xFFC6, "F9" }, { 0xFFC7, "F10" }, { 0xFFC8, "F11" }, { 0xFFC9, "F12" }, { 0xFFCA, "F13" }, { 0xFFCB, "F14" }, { 0xFFCC, "F15" }, { 0xFFCD, "F16" }, { 0xFFCE, "F17" }, { 0xFFCF, "F18" }, { 0xFFD0, "F19" }, { 0xFFD1, "F20" }, { 0xFFD2, "F21" }, { 0xFFD3, "F22" }, { 0xFFD4, "F23" }, { 0xFFD5, "F24" }, { 0xFFE1, "Shift", "", true }, { 0xFFE2, "Shift", "", true }, { 0xFFE3, "Ctrl", NULL, true }, { 0xFFE4, "Ctrl", NULL, true }, { 0xFFE5, "Caps" }, { 0xFFE7, "Meta", NULL, true }, { 0xFFE8, "Meta", NULL, true }, { 0xFFE9, "Alt", NULL, true }, { 0xFFEA, "Alt", NULL, true }, { 0xFFEB, "Super", NULL, true }, { 0xFFEC, "Super", NULL, true }, { 0xFFED, "Hyper", NULL, true }, { 0xFFEE, "Hyper", NULL, true }, { 0xFFFF, "Delete" } }; /** * Comparator for the standard bsearch() function which compares an integer * keysym against the keysym associated with a guaclog_keydef. * * @param key * The key value being compared against the member. This MUST be the * keysym value, passed through typecasting to an intptr_t (NOT a pointer * to the int itself). * * @param member * The member within the known_keys array being compared against the given * key. * * @return * Zero if the given keysym is equal to that of the given member, a * positive value if the given keysym is greater than that of the given * member, or a negative value if the given keysym is less than that of the * given member. */ static int guaclog_keydef_bsearch_compare(const void* key, const void* member) { int keysym = (int) ((intptr_t) key); guaclog_keydef* current = (guaclog_keydef*) member; /* Compare given keysym to keysym of current member */ return keysym - current->keysym; } /** * Searches through the known_keys array of known keys for the name of the key * having the given keysym, returning a pointer to the static guaclog_keydef * within the array if found. * * @param keysym * The X11 keysym of the key. * * @return * A pointer to the static guaclog_keydef associated with the given keysym, * or NULL if the key could not be found. */ static guaclog_keydef* guaclog_get_known_key(int keysym) { /* Search through known keys for given keysym */ return bsearch((void*) ((intptr_t) keysym), known_keys, sizeof(known_keys) / sizeof(known_keys[0]), sizeof(known_keys[0]), guaclog_keydef_bsearch_compare); } /** * Returns a statically-allocated guaclog_keydef representing an unknown key, * deriving the name of the key from the hexadecimal value of the keysym. * * @param keysym * The X11 keysym of the key. * * @return * A statically-allocated guaclog_keydef representing the key associated * with the given keysym. */ static guaclog_keydef* guaclog_get_unknown_key(int keysym) { static char unknown_keydef_name[64]; static guaclog_keydef unknown_keydef; /* Write keysym as hex */ int size = snprintf(unknown_keydef_name, sizeof(unknown_keydef_name), "0x%X", keysym); /* Hex string is guaranteed to fit within the provided 64 bytes */ assert(size < sizeof(unknown_keydef_name)); /* Return static key definition */ unknown_keydef.keysym = keysym; unknown_keydef.name = unknown_keydef_name; return &unknown_keydef; } /** * Returns a statically-allocated guaclog_keydef representing the key * associated with the given keysym, deriving the name and value of the key * using its corresponding Unicode character. * * @param keysym * The X11 keysym of the key. * * @return * A statically-allocated guaclog_keydef representing the key associated * with the given keysym, or NULL if the given keysym has no corresponding * Unicode character. */ static guaclog_keydef* guaclog_get_unicode_key(int keysym) { static char unicode_keydef_name[8]; static guaclog_keydef unicode_keydef; int i; int mask, bytes; /* Translate only if keysym maps to Unicode */ if (keysym < 0x00 || (keysym > 0xFF && (keysym | 0xFFFF) != 0x0100FFFF)) return NULL; int codepoint = keysym & 0xFFFF; /* Determine size and initial byte mask */ if (codepoint <= 0x007F) { mask = 0x00; bytes = 1; } else if (codepoint <= 0x7FF) { mask = 0xC0; bytes = 2; } else { assert(codepoint <= 0xFFFF); mask = 0xE0; bytes = 3; } /* Offset buffer by size */ char* key_name = unicode_keydef_name + bytes; /* Add null terminator */ *(key_name--) = '\0'; /* Add trailing bytes, if any */ for (i=1; i>= 6; } /* Set initial byte */ *key_name = mask | codepoint; /* Return static key definition */ unicode_keydef.keysym = keysym; unicode_keydef.name = unicode_keydef.value = unicode_keydef_name; unicode_keydef.modifier = false; return &unicode_keydef; } /** * Copies the given guaclog_keydef into a newly-allocated guaclog_keydef * structure. The resulting guaclog_keydef must eventually be freed through a * call to guaclog_keydef_free(). * * @param keydef * The guaclog_keydef to copy. * * @return * A newly-allocated guaclog_keydef structure copied from the given * guaclog_keydef. */ static guaclog_keydef* guaclog_copy_key(guaclog_keydef* keydef) { guaclog_keydef* copy = malloc(sizeof(guaclog_keydef)); /* Always copy keysym and name */ copy->keysym = keydef->keysym; copy->name = strdup(keydef->name); copy->modifier = keydef->modifier; /* Copy value only if defined */ if (keydef->value != NULL) copy->value = strdup(keydef->value); else copy->value = NULL; return copy; } guaclog_keydef* guaclog_keydef_alloc(int keysym) { guaclog_keydef* keydef; /* Check list of known keys first */ keydef = guaclog_get_known_key(keysym); if (keydef != NULL) return guaclog_copy_key(keydef); /* Failing that, attempt to translate straight into a Unicode character */ keydef = guaclog_get_unicode_key(keysym); if (keydef != NULL) return guaclog_copy_key(keydef); /* Key not known */ guaclog_log(GUAC_LOG_DEBUG, "Definition not found for key 0x%X.", keysym); return guaclog_copy_key(guaclog_get_unknown_key(keysym)); } void guaclog_keydef_free(guaclog_keydef* keydef) { /* Ignore NULL keydef */ if (keydef == NULL) return; free(keydef->name); free(keydef->value); free(keydef); } guacamole-server-1.3.0/src/guaclog/log.c0000644000175100001440000000442713702142276015042 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guaclog.h" #include "log.h" #include #include #include #include int guaclog_log_level = GUACLOG_DEFAULT_LOG_LEVEL; void vguaclog_log(guac_client_log_level level, const char* format, va_list args) { const char* priority_name; char message[2048]; /* Don't bother if the log level is too high */ if (level > guaclog_log_level) return; /* Copy log message into buffer */ vsnprintf(message, sizeof(message), format, args); /* Convert log level to human-readable name */ switch (level) { /* Error log level */ case GUAC_LOG_ERROR: priority_name = "ERROR"; break; /* Warning log level */ case GUAC_LOG_WARNING: priority_name = "WARNING"; break; /* Informational log level */ case GUAC_LOG_INFO: priority_name = "INFO"; break; /* Debug log level */ case GUAC_LOG_DEBUG: priority_name = "DEBUG"; break; /* Any unknown/undefined log level */ default: priority_name = "UNKNOWN"; break; } /* Log to STDERR */ fprintf(stderr, GUACLOG_LOG_NAME ": %s: %s\n", priority_name, message); } void guaclog_log(guac_client_log_level level, const char* format, ...) { va_list args; va_start(args, format); vguaclog_log(level, format, args); va_end(args); } guacamole-server-1.3.0/src/guaclog/Makefile.in0000644000175100001440000011663413772471102016166 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = guaclog$(EXEEXT) subdir = src/guaclog ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" PROGRAMS = $(bin_PROGRAMS) am_guaclog_OBJECTS = guaclog-guaclog.$(OBJEXT) \ guaclog-instructions.$(OBJEXT) \ guaclog-instruction-key.$(OBJEXT) guaclog-interpret.$(OBJEXT) \ guaclog-keydef.$(OBJEXT) guaclog-log.$(OBJEXT) \ guaclog-state.$(OBJEXT) guaclog_OBJECTS = $(am_guaclog_OBJECTS) guaclog_DEPENDENCIES = AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = guaclog_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(guaclog_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/guaclog-guaclog.Po \ ./$(DEPDIR)/guaclog-instruction-key.Po \ ./$(DEPDIR)/guaclog-instructions.Po \ ./$(DEPDIR)/guaclog-interpret.Po ./$(DEPDIR)/guaclog-keydef.Po \ ./$(DEPDIR)/guaclog-log.Po ./$(DEPDIR)/guaclog-state.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(guaclog_SOURCES) DIST_SOURCES = $(guaclog_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 NROFF = nroff MANS = $(man_MANS) HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign man_MANS = \ man/guaclog.1 noinst_HEADERS = \ guaclog.h \ instructions.h \ interpret.h \ keydef.h \ log.h \ state.h guaclog_SOURCES = \ guaclog.c \ instructions.c \ instruction-key.c \ interpret.c \ keydef.c \ log.c \ state.c guaclog_CFLAGS = \ -Werror -Wall \ @LIBGUAC_INCLUDE@ guaclog_LDADD = \ @LIBGUAC_LTLIB@ EXTRA_DIST = \ man/guaclog.1.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/guaclog/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/guaclog/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list guaclog$(EXEEXT): $(guaclog_OBJECTS) $(guaclog_DEPENDENCIES) $(EXTRA_guaclog_DEPENDENCIES) @rm -f guaclog$(EXEEXT) $(AM_V_CCLD)$(guaclog_LINK) $(guaclog_OBJECTS) $(guaclog_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guaclog-guaclog.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guaclog-instruction-key.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guaclog-instructions.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guaclog-interpret.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guaclog-keydef.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guaclog-log.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guaclog-state.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< guaclog-guaclog.o: guaclog.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-guaclog.o -MD -MP -MF $(DEPDIR)/guaclog-guaclog.Tpo -c -o guaclog-guaclog.o `test -f 'guaclog.c' || echo '$(srcdir)/'`guaclog.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-guaclog.Tpo $(DEPDIR)/guaclog-guaclog.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='guaclog.c' object='guaclog-guaclog.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-guaclog.o `test -f 'guaclog.c' || echo '$(srcdir)/'`guaclog.c guaclog-guaclog.obj: guaclog.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-guaclog.obj -MD -MP -MF $(DEPDIR)/guaclog-guaclog.Tpo -c -o guaclog-guaclog.obj `if test -f 'guaclog.c'; then $(CYGPATH_W) 'guaclog.c'; else $(CYGPATH_W) '$(srcdir)/guaclog.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-guaclog.Tpo $(DEPDIR)/guaclog-guaclog.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='guaclog.c' object='guaclog-guaclog.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-guaclog.obj `if test -f 'guaclog.c'; then $(CYGPATH_W) 'guaclog.c'; else $(CYGPATH_W) '$(srcdir)/guaclog.c'; fi` guaclog-instructions.o: instructions.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-instructions.o -MD -MP -MF $(DEPDIR)/guaclog-instructions.Tpo -c -o guaclog-instructions.o `test -f 'instructions.c' || echo '$(srcdir)/'`instructions.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-instructions.Tpo $(DEPDIR)/guaclog-instructions.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instructions.c' object='guaclog-instructions.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-instructions.o `test -f 'instructions.c' || echo '$(srcdir)/'`instructions.c guaclog-instructions.obj: instructions.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-instructions.obj -MD -MP -MF $(DEPDIR)/guaclog-instructions.Tpo -c -o guaclog-instructions.obj `if test -f 'instructions.c'; then $(CYGPATH_W) 'instructions.c'; else $(CYGPATH_W) '$(srcdir)/instructions.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-instructions.Tpo $(DEPDIR)/guaclog-instructions.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instructions.c' object='guaclog-instructions.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-instructions.obj `if test -f 'instructions.c'; then $(CYGPATH_W) 'instructions.c'; else $(CYGPATH_W) '$(srcdir)/instructions.c'; fi` guaclog-instruction-key.o: instruction-key.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-instruction-key.o -MD -MP -MF $(DEPDIR)/guaclog-instruction-key.Tpo -c -o guaclog-instruction-key.o `test -f 'instruction-key.c' || echo '$(srcdir)/'`instruction-key.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-instruction-key.Tpo $(DEPDIR)/guaclog-instruction-key.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-key.c' object='guaclog-instruction-key.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-instruction-key.o `test -f 'instruction-key.c' || echo '$(srcdir)/'`instruction-key.c guaclog-instruction-key.obj: instruction-key.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-instruction-key.obj -MD -MP -MF $(DEPDIR)/guaclog-instruction-key.Tpo -c -o guaclog-instruction-key.obj `if test -f 'instruction-key.c'; then $(CYGPATH_W) 'instruction-key.c'; else $(CYGPATH_W) '$(srcdir)/instruction-key.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-instruction-key.Tpo $(DEPDIR)/guaclog-instruction-key.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-key.c' object='guaclog-instruction-key.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-instruction-key.obj `if test -f 'instruction-key.c'; then $(CYGPATH_W) 'instruction-key.c'; else $(CYGPATH_W) '$(srcdir)/instruction-key.c'; fi` guaclog-interpret.o: interpret.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-interpret.o -MD -MP -MF $(DEPDIR)/guaclog-interpret.Tpo -c -o guaclog-interpret.o `test -f 'interpret.c' || echo '$(srcdir)/'`interpret.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-interpret.Tpo $(DEPDIR)/guaclog-interpret.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='interpret.c' object='guaclog-interpret.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-interpret.o `test -f 'interpret.c' || echo '$(srcdir)/'`interpret.c guaclog-interpret.obj: interpret.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-interpret.obj -MD -MP -MF $(DEPDIR)/guaclog-interpret.Tpo -c -o guaclog-interpret.obj `if test -f 'interpret.c'; then $(CYGPATH_W) 'interpret.c'; else $(CYGPATH_W) '$(srcdir)/interpret.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-interpret.Tpo $(DEPDIR)/guaclog-interpret.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='interpret.c' object='guaclog-interpret.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-interpret.obj `if test -f 'interpret.c'; then $(CYGPATH_W) 'interpret.c'; else $(CYGPATH_W) '$(srcdir)/interpret.c'; fi` guaclog-keydef.o: keydef.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-keydef.o -MD -MP -MF $(DEPDIR)/guaclog-keydef.Tpo -c -o guaclog-keydef.o `test -f 'keydef.c' || echo '$(srcdir)/'`keydef.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-keydef.Tpo $(DEPDIR)/guaclog-keydef.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keydef.c' object='guaclog-keydef.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-keydef.o `test -f 'keydef.c' || echo '$(srcdir)/'`keydef.c guaclog-keydef.obj: keydef.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-keydef.obj -MD -MP -MF $(DEPDIR)/guaclog-keydef.Tpo -c -o guaclog-keydef.obj `if test -f 'keydef.c'; then $(CYGPATH_W) 'keydef.c'; else $(CYGPATH_W) '$(srcdir)/keydef.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-keydef.Tpo $(DEPDIR)/guaclog-keydef.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keydef.c' object='guaclog-keydef.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-keydef.obj `if test -f 'keydef.c'; then $(CYGPATH_W) 'keydef.c'; else $(CYGPATH_W) '$(srcdir)/keydef.c'; fi` guaclog-log.o: log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-log.o -MD -MP -MF $(DEPDIR)/guaclog-log.Tpo -c -o guaclog-log.o `test -f 'log.c' || echo '$(srcdir)/'`log.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-log.Tpo $(DEPDIR)/guaclog-log.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='log.c' object='guaclog-log.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-log.o `test -f 'log.c' || echo '$(srcdir)/'`log.c guaclog-log.obj: log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-log.obj -MD -MP -MF $(DEPDIR)/guaclog-log.Tpo -c -o guaclog-log.obj `if test -f 'log.c'; then $(CYGPATH_W) 'log.c'; else $(CYGPATH_W) '$(srcdir)/log.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-log.Tpo $(DEPDIR)/guaclog-log.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='log.c' object='guaclog-log.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-log.obj `if test -f 'log.c'; then $(CYGPATH_W) 'log.c'; else $(CYGPATH_W) '$(srcdir)/log.c'; fi` guaclog-state.o: state.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-state.o -MD -MP -MF $(DEPDIR)/guaclog-state.Tpo -c -o guaclog-state.o `test -f 'state.c' || echo '$(srcdir)/'`state.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-state.Tpo $(DEPDIR)/guaclog-state.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='state.c' object='guaclog-state.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-state.o `test -f 'state.c' || echo '$(srcdir)/'`state.c guaclog-state.obj: state.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -MT guaclog-state.obj -MD -MP -MF $(DEPDIR)/guaclog-state.Tpo -c -o guaclog-state.obj `if test -f 'state.c'; then $(CYGPATH_W) 'state.c'; else $(CYGPATH_W) '$(srcdir)/state.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guaclog-state.Tpo $(DEPDIR)/guaclog-state.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='state.c' object='guaclog-state.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guaclog_CFLAGS) $(CFLAGS) -c -o guaclog-state.obj `if test -f 'state.c'; then $(CYGPATH_W) 'state.c'; else $(CYGPATH_W) '$(srcdir)/state.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/guaclog-guaclog.Po -rm -f ./$(DEPDIR)/guaclog-instruction-key.Po -rm -f ./$(DEPDIR)/guaclog-instructions.Po -rm -f ./$(DEPDIR)/guaclog-interpret.Po -rm -f ./$(DEPDIR)/guaclog-keydef.Po -rm -f ./$(DEPDIR)/guaclog-log.Po -rm -f ./$(DEPDIR)/guaclog-state.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/guaclog-guaclog.Po -rm -f ./$(DEPDIR)/guaclog-instruction-key.Po -rm -f ./$(DEPDIR)/guaclog-instructions.Po -rm -f ./$(DEPDIR)/guaclog-interpret.Po -rm -f ./$(DEPDIR)/guaclog-keydef.Po -rm -f ./$(DEPDIR)/guaclog-log.Po -rm -f ./$(DEPDIR)/guaclog-state.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-man uninstall-man: uninstall-man1 .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-man1 \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-man uninstall-man1 .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/guaclog/instructions.c0000644000175100001440000000366713702142276017032 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "state.h" #include "instructions.h" #include "log.h" #include guaclog_instruction_handler_mapping guaclog_instruction_handler_map[] = { {"key", guaclog_handle_key}, {NULL, NULL} }; int guaclog_handle_instruction(guaclog_state* state, const char* opcode, int argc, char** argv) { /* Search through mapping for instruction handler having given opcode */ guaclog_instruction_handler_mapping* current = guaclog_instruction_handler_map; while (current->opcode != NULL) { /* Invoke handler if opcode matches (if defined) */ if (strcmp(current->opcode, opcode) == 0) { /* Invoke defined handler */ guaclog_instruction_handler* handler = current->handler; if (handler != NULL) return handler(state, argc, argv); /* Log defined but unimplemented instructions */ guaclog_log(GUAC_LOG_DEBUG, "\"%s\" not implemented", opcode); return 0; } /* Next candidate handler */ current++; } /* end opcode search */ /* Ignore any unknown instructions */ return 0; } guacamole-server-1.3.0/src/guaclog/Makefile.am0000644000175100001440000000333513702142276016146 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign bin_PROGRAMS = guaclog man_MANS = \ man/guaclog.1 noinst_HEADERS = \ guaclog.h \ instructions.h \ interpret.h \ keydef.h \ log.h \ state.h guaclog_SOURCES = \ guaclog.c \ instructions.c \ instruction-key.c \ interpret.c \ keydef.c \ log.c \ state.c guaclog_CFLAGS = \ -Werror -Wall \ @LIBGUAC_INCLUDE@ guaclog_LDADD = \ @LIBGUAC_LTLIB@ EXTRA_DIST = \ man/guaclog.1.in guacamole-server-1.3.0/src/guaclog/keydef.h0000644000175100001440000000442013702142276015526 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACLOG_KEYDEF_H #define GUACLOG_KEYDEF_H #include "config.h" #include /** * A mapping of X11 keysym to its corresponding human-readable name. */ typedef struct guaclog_keydef { /** * The X11 keysym of the key. */ int keysym; /** * A human-readable name for the key. */ char* name; /** * The value which would be typed in a typical text editor, if any. If the * key is not associated with any typable value, or if the typable value is * not generally useful in an auditing context, this will be NULL. */ char* value; /** * Whether this key is a modifier which may affect the interpretation of * other keys, and thus should be tracked as it is held down. */ bool modifier; } guaclog_keydef; /** * Creates a new guaclog_keydef which represents the key having the given * keysym. The resulting guaclog_keydef must eventually be freed through a * call to guaclog_keydef_free(). * * @param keysym * The X11 keysym of the key. * * @return * A new guaclog_keydef which represents the key having the given keysym, * or NULL if no such key is known. */ guaclog_keydef* guaclog_keydef_alloc(int keysym); /** * Frees all resources associated with the given guaclog_keydef. If the given * guaclog_keydef is NULL, this function has no effect. * * @param keydef * The guaclog_keydef to free, which may be NULL. */ void guaclog_keydef_free(guaclog_keydef* keydef); #endif guacamole-server-1.3.0/src/guacd/0000755000175100001440000000000013772471156013641 500000000000000guacamole-server-1.3.0/src/guacd/proc.c0000644000175100001440000003374513770536337014705 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "log.h" #include "move-fd.h" #include "proc.h" #include "proc-map.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** * Parameters for the user thread. */ typedef struct guacd_user_thread_params { /** * The process being joined. */ guacd_proc* proc; /** * The file descriptor of the joining user's socket. */ int fd; /** * Whether the joining user is the connection owner. */ int owner; } guacd_user_thread_params; /** * Handles a user's entire connection and socket lifecycle. * * @param data * A pointer to a guacd_user_thread_params structure describing the user's * associated file descriptor, whether that user is the connection owner * (the first person to join), as well as the process associated with the * connection being joined. * * @return * Always NULL. */ static void* guacd_user_thread(void* data) { guacd_user_thread_params* params = (guacd_user_thread_params*) data; guacd_proc* proc = params->proc; guac_client* client = proc->client; /* Get guac_socket for user's file descriptor */ guac_socket* socket = guac_socket_open(params->fd); if (socket == NULL) return NULL; /* Create skeleton user */ guac_user* user = guac_user_alloc(); user->socket = socket; user->client = client; user->owner = params->owner; /* Handle user connection from handshake until disconnect/completion */ guac_user_handle_connection(user, GUACD_USEC_TIMEOUT); /* Stop client and prevent future users if all users are disconnected */ if (client->connected_users == 0) { guacd_log(GUAC_LOG_INFO, "Last user of connection \"%s\" disconnected", client->connection_id); guacd_proc_stop(proc); } /* Clean up */ guac_socket_free(socket); guac_user_free(user); free(params); return NULL; } /** * Begins a new user connection under a given process, using the given file * descriptor. The connection will be managed by a separate and detached thread * which is started by this function. * * @param proc * The process that the user is being added to. * * @param fd * The file descriptor associated with the user's network connection to * guacd. * * @param owner * Non-zero if the user is the owner of the connection being joined (they * are the first user to join), or zero otherwise. */ static void guacd_proc_add_user(guacd_proc* proc, int fd, int owner) { guacd_user_thread_params* params = malloc(sizeof(guacd_user_thread_params)); params->proc = proc; params->fd = fd; params->owner = owner; /* Start user thread */ pthread_t user_thread; pthread_create(&user_thread, NULL, guacd_user_thread, params); pthread_detach(user_thread); } /** * Forcibly kills all processes within the current process group, including the * current process and all child processes. This function is only safe to call * if the process group ID has been correctly set. Calling this function within * a process which does not have a PGID separate from the main guacd process * can result in guacd itself being terminated. */ static void guacd_kill_current_proc_group() { /* Forcibly kill all children within process group */ if (kill(0, SIGKILL)) guacd_log(GUAC_LOG_WARNING, "Unable to forcibly terminate " "client process: %s ", strerror(errno)); } /** * The current status of a background attempt to free a guac_client instance. */ typedef struct guacd_client_free { /** * The guac_client instance being freed. */ guac_client* client; /** * The condition which is signalled whenever changes are made to the * completed flag. The completed flag only changes from zero (not yet * freed) to non-zero (successfully freed). */ pthread_cond_t completed_cond; /** * Mutex which must be acquired before any changes are made to the * completed flag. */ pthread_mutex_t completed_mutex; /** * Whether the guac_client has been successfully freed. Initially, this * will be zero, indicating that the free operation has not yet been * attempted. If the client is eventually successfully freed, this will be * set to a non-zero value. Changes to this flag are signalled through * the completed_cond condition. */ int completed; } guacd_client_free; /** * Thread which frees a given guac_client instance in the background. If the * free operation succeeds, a flag is set on the provided structure, and the * change in that flag is signalled with a pthread condition. * * At the time this function is provided to a pthread_create() call, the * completed flag of the associated guacd_client_free structure MUST be * initialized to zero, the pthread mutex and condition MUST both be * initialized, and the client pointer must point to the guac_client being * freed. * * @param data * A pointer to a guacd_client_free structure describing the free * operation. * * @return * Always NULL. */ static void* guacd_client_free_thread(void* data) { guacd_client_free* free_operation = (guacd_client_free*) data; /* Attempt to free client (this may never return if the client is * malfunctioning) */ guac_client_free(free_operation->client); /* Signal that the client was successfully freed */ pthread_mutex_lock(&free_operation->completed_mutex); free_operation->completed = 1; pthread_cond_broadcast(&free_operation->completed_cond); pthread_mutex_unlock(&free_operation->completed_mutex); return NULL; } /** * Attempts to free the given guac_client, restricting the time taken by the * free handler of the guac_client to a finite number of seconds. If the free * handler does not complete within the time alotted, this function returns * and the intended free operation is left in an undefined state. * * @param client * The guac_client instance to free. * * @param timeout * The maximum amount of time to wait for the guac_client to be freed, * in seconds. * * @return * Zero if the guac_client was successfully freed within the time alotted, * non-zero otherwise. */ static int guacd_timed_client_free(guac_client* client, int timeout) { pthread_t client_free_thread; guacd_client_free free_operation = { .client = client, .completed_cond = PTHREAD_COND_INITIALIZER, .completed_mutex = PTHREAD_MUTEX_INITIALIZER, .completed = 0 }; /* Get current time */ struct timeval current_time; if (gettimeofday(¤t_time, NULL)) return 1; /* Calculate exact time that the free operation MUST complete by */ struct timespec deadline = { .tv_sec = current_time.tv_sec + timeout, .tv_nsec = current_time.tv_usec * 1000 }; /* The mutex associated with the pthread conditional and flag MUST be * acquired before attempting to wait for the condition */ if (pthread_mutex_lock(&free_operation.completed_mutex)) return 1; /* Free the client in a separate thread, so we can time the free operation */ if (!pthread_create(&client_free_thread, NULL, guacd_client_free_thread, &free_operation)) { /* Wait a finite amount of time for the free operation to finish */ (void) pthread_cond_timedwait(&free_operation.completed_cond, &free_operation.completed_mutex, &deadline); } (void) pthread_mutex_unlock(&free_operation.completed_mutex); /* Return status of free operation */ return !free_operation.completed; } /** * Starts protocol-specific handling on the given process by loading the client * plugin for that protocol. This function does NOT return. It initializes the * process with protocol-specific handlers and then runs until the guacd_proc's * fd_socket is closed, adding any file descriptors received along fd_socket as * new users. * * @param proc * The process that any new users received along fd_socket should be added * to (after the process has been initialized for the given protocol). * * @param protocol * The protocol to initialize the given process for. */ static void guacd_exec_proc(guacd_proc* proc, const char* protocol) { int result = 1; /* Set process group ID to match PID */ if (setpgid(0, 0)) { guacd_log(GUAC_LOG_ERROR, "Cannot set PGID for connection process: %s", strerror(errno)); goto cleanup_process; } /* Init client for selected protocol */ guac_client* client = proc->client; if (guac_client_load_plugin(client, protocol)) { /* Log error */ if (guac_error == GUAC_STATUS_NOT_FOUND) guacd_log(GUAC_LOG_WARNING, "Support for protocol \"%s\" is not installed", protocol); else guacd_log_guac_error(GUAC_LOG_ERROR, "Unable to load client plugin"); goto cleanup_client; } /* The first file descriptor is the owner */ int owner = 1; /* Enable keep alive on the broadcast socket */ guac_socket_require_keep_alive(client->socket); /* Add each received file descriptor as a new user */ int received_fd; while ((received_fd = guacd_recv_fd(proc->fd_socket)) != -1) { guacd_proc_add_user(proc, received_fd, owner); /* Future file descriptors are not owners */ owner = 0; } cleanup_client: /* Request client to stop/disconnect */ guac_client_stop(client); /* Attempt to free client cleanly */ guacd_log(GUAC_LOG_DEBUG, "Requesting termination of client..."); result = guacd_timed_client_free(client, GUACD_CLIENT_FREE_TIMEOUT); /* If client was unable to be freed, warn and forcibly kill */ if (result) { guacd_log(GUAC_LOG_WARNING, "Client did not terminate in a timely " "manner. Forcibly terminating client and any child " "processes."); guacd_kill_current_proc_group(); } else guacd_log(GUAC_LOG_DEBUG, "Client terminated successfully."); /* Verify whether children were all properly reaped */ pid_t child_pid; while ((child_pid = waitpid(0, NULL, WNOHANG)) > 0) { guacd_log(GUAC_LOG_DEBUG, "Automatically reaped unreaped " "(zombie) child process with PID %i.", child_pid); } /* If running children remain, warn and forcibly kill */ if (child_pid == 0) { guacd_log(GUAC_LOG_WARNING, "Client reported successful termination, " "but child processes remain. Forcibly terminating client and " "child processes."); guacd_kill_current_proc_group(); } cleanup_process: /* Free up all internal resources outside the client */ close(proc->fd_socket); free(proc); exit(result); } guacd_proc* guacd_create_proc(const char* protocol) { int sockets[2]; /* Open UNIX socket pair */ if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) < 0) { guacd_log(GUAC_LOG_ERROR, "Error opening socket pair: %s", strerror(errno)); return NULL; } int parent_socket = sockets[0]; int child_socket = sockets[1]; /* Allocate process */ guacd_proc* proc = calloc(1, sizeof(guacd_proc)); if (proc == NULL) { close(parent_socket); close(child_socket); return NULL; } /* Associate new client */ proc->client = guac_client_alloc(); if (proc->client == NULL) { guacd_log_guac_error(GUAC_LOG_ERROR, "Unable to create client"); close(parent_socket); close(child_socket); free(proc); return NULL; } /* Init logging */ proc->client->log_handler = guacd_client_log; /* Fork */ proc->pid = fork(); if (proc->pid < 0) { guacd_log(GUAC_LOG_ERROR, "Cannot fork child process: %s", strerror(errno)); close(parent_socket); close(child_socket); guac_client_free(proc->client); free(proc); return NULL; } /* Child */ else if (proc->pid == 0) { /* Communicate with parent */ proc->fd_socket = parent_socket; close(child_socket); /* Start protocol-specific handling */ guacd_exec_proc(proc, protocol); } /* Parent */ else { /* Communicate with child */ proc->fd_socket = child_socket; close(parent_socket); } return proc; } void guacd_proc_stop(guacd_proc* proc) { /* Signal client to stop */ guac_client_stop(proc->client); /* Shutdown socket - in-progress recvmsg() will not fail otherwise */ if (shutdown(proc->fd_socket, SHUT_RDWR) == -1) guacd_log(GUAC_LOG_ERROR, "Unable to shutdown internal socket for " "connection %s. Corresponding process may remain running but " "inactive.", proc->client->connection_id); /* Clean up our end of the socket */ close(proc->fd_socket); } guacamole-server-1.3.0/src/guacd/proc-map.h0000644000175100001440000000676513676721354015467 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUACD_PROC_MAP_H #define _GUACD_PROC_MAP_H #include "config.h" #include "common/list.h" #include "proc.h" #include /** * The maximum number of concurrent connections to a single instance * of guacd. */ #define GUACD_CLIENT_MAX_CONNECTIONS 65536 /** * The number of hash buckets in each process map. */ #define GUACD_PROC_MAP_BUCKETS GUACD_CLIENT_MAX_CONNECTIONS*2 /** * Set of all active connections to guacd, indexed by connection ID. */ typedef struct guacd_proc_map { /** * Internal hash buckets. Each bucket is a linked list containing all * guac_client instances which hash to this bucket location. */ guac_common_list* __buckets[GUACD_PROC_MAP_BUCKETS]; } guacd_proc_map; /** * Allocates a new client process map. There is intended to be exactly one * process map instance, which persists for the life of guacd. * * @return * A newly-allocated client process map. */ guacd_proc_map* guacd_proc_map_alloc(); /** * Adds the given process to the client process map. On success, zero is * returned. If adding the client fails (due to lack of space, or duplicate * ID), a non-zero value is returned instead. The client process is stored by * the connection ID of the underlying guac_client. * * @param map * The map in which the given client process should be stored. * * @param proc * The client process to store in the given map. * * @return * Zero if the process was successfully stored in the map, or non-zero if * storing the process fails for any reason. */ int guacd_proc_map_add(guacd_proc_map* map, guacd_proc* proc); /** * Retrieves the client process having the client with the given ID, or NULL if * no such process is stored. * * @param map * The map from which to retrieve the process associated with the client * having the given ID. * * @param id * The ID of the client whose process should be retrieved. * * @return * The process associated with the client having the given ID, or NULL if * no such process exists. */ guacd_proc* guacd_proc_map_retrieve(guacd_proc_map* map, const char* id); /** * Removes the client process having the client with the given ID, returning * the corresponding process. If no such process exists, NULL is returned. * * @param map * The map from which to remove the process associated with the client * having the given ID. * * @param id * The ID of the client whose process should be removed. * * @return * The process associated with the client having the given ID which has now * been removed from the given map, or NULL if no such process exists. */ guacd_proc* guacd_proc_map_remove(guacd_proc_map* map, const char* id); #endif guacamole-server-1.3.0/src/guacd/conf-file.h0000644000175100001440000000253713702142276015572 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUACD_CONF_FILE_H #define _GUACD_CONF_FILE_H #include "config.h" #include "conf.h" /** * Reads the given file descriptor, parsing its contents into the guacd_config. * On success, zero is returned. If parsing fails, non-zero is returned, and an * error message is printed to stderr. */ int guacd_conf_parse_file(guacd_config* conf, int fd); /** * Loads the configuration from any of several default locations, if found. If * parsing fails, NULL is returned, and an error message is printed to stderr. */ guacd_config* guacd_conf_load(); #endif guacamole-server-1.3.0/src/guacd/conf-parse.c0000644000175100001440000003362413702142276015761 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "conf.h" #include "conf-parse.h" #include #include #include /* * Simple recursive descent parser for an INI-like conf file grammar. The * grammar is, roughly: * * ::= * ::= * ::= | | "" * ::= "[" "]" * ::= "=" * * Where: * is any number of tabs or spaces. * is a # character followed by any length of text without an EOL. * is an alpha-numeric string consisting of: [A-Za-z0-9_-]. * is any length of text without an EOL or # character, or a double-quoted string (backslash escapes legal). * is a carriage return or line feed character. */ /** * The current section. Note that this means the parser is NOT threadsafe. */ char __guacd_current_section[GUACD_CONF_MAX_NAME_LENGTH + 1] = ""; char* guacd_conf_parse_error = NULL; char* guacd_conf_parse_error_location = NULL; /** * Reads through all whitespace at the beginning of the buffer, returning the * number of characters read. This is in the grammar above. As * the whitespace is zero or more whitespace characters, this function cannot * fail, but it may read zero chars overall. */ static int guacd_parse_whitespace(char* buffer, int length) { int chars_read = 0; /* Read through all whitespace */ while (chars_read < length) { /* Read character */ char c = *buffer; /* Stop at non-whitespace */ if (c != ' ' && c != '\t') break; chars_read++; buffer++; } return chars_read; } /** * Parses the name of a parameter, section, etc. A section/parameter name can * consist only of alphanumeric characters and underscores. The resulting name * will be stored in the name string, which must have at least 256 bytes * available. */ static int guacd_parse_name(char* buffer, int length, char* name) { char* name_start = buffer; int chars_read = 0; /* Read through all valid name chars */ while (chars_read < length) { /* Read character */ char c = *buffer; /* Stop at non-name characters */ if (!isalnum(c) && c != '_') break; chars_read++; buffer++; /* Ensure name does not exceed maximum length */ if (chars_read > GUACD_CONF_MAX_NAME_LENGTH) { guacd_conf_parse_error = "Names can be no more than 255 characters long"; guacd_conf_parse_error_location = buffer; return -1; } } /* Names must contain at least one character */ if (chars_read == 0) return 0; /* Copy name from buffer */ memcpy(name, name_start, chars_read); name[chars_read] = '\0'; return chars_read; } /** * Parses the value of a parameter. A value can consist of any character except * '#', whitespace, or EOL. The resulting value will be stored in the value * string, which must have at least 256 bytes available. */ static int guacd_parse_value(char* buffer, int length, char* value) { char* value_start = buffer; int chars_read = 0; /* Read through all valid value chars */ while (chars_read < length) { /* Read character */ char c = *buffer; /* Stop at invalid character */ if (c == '#' || c == '"' || c == '\r' || c == '\n' || c == ' ' || c == '\t') break; chars_read++; buffer++; /* Ensure value does not exceed maximum length */ if (chars_read > GUACD_CONF_MAX_VALUE_LENGTH) { guacd_conf_parse_error = "Values can be no more than 8191 characters long"; guacd_conf_parse_error_location = buffer; return -1; } } /* Values must contain at least one character */ if (chars_read == 0) { guacd_conf_parse_error = "Unquoted values must contain at least one character"; guacd_conf_parse_error_location = buffer; return -1; } /* Copy value from buffer */ memcpy(value, value_start, chars_read); value[chars_read] = '\0'; return chars_read; } /** * Parses the quoted value of a parameter. Quoted values may contain any * character except double quotes or backslashes, which must be * backslash-escaped. */ static int guacd_parse_quoted_value(char* buffer, int length, char* value) { int escaped = 0; /* Assert first character is '"' */ if (length == 0 || *buffer != '"') return 0; int chars_read = 1; buffer++; length--; /* Read until end of quoted value */ while (chars_read < length) { /* Read character */ char c = *buffer; /* Handle special characters if not escaped */ if (!escaped) { /* Stop at quote or invalid character */ if (c == '"' || c == '\r' || c == '\n') break; /* Backslash escaping */ else if (c == '\\') escaped = 1; else *(value++) = c; } /* Reset escape flag */ else { escaped = 0; *(value++) = c; } chars_read++; buffer++; /* Ensure value does not exceed maximum length */ if (chars_read > GUACD_CONF_MAX_VALUE_LENGTH) { guacd_conf_parse_error = "Values can be no more than 8191 characters long"; guacd_conf_parse_error_location = buffer; return -1; } } /* Assert value ends with '"' */ if (length == 0 || *buffer != '"') { guacd_conf_parse_error = "'\"' expected"; guacd_conf_parse_error_location = buffer; return -1; } chars_read++; /* Terminate read value */ *value = '\0'; return chars_read; } /** * Reads a parameter/value pair, separated by an '=' character. If the * parameter/value pair is invalid for any reason, a negative value is * returned. */ static int guacd_parse_parameter(guacd_param_callback* callback, char* buffer, int length, void* data) { char param_name[GUACD_CONF_MAX_NAME_LENGTH + 1]; char param_value[GUACD_CONF_MAX_VALUE_LENGTH + 1]; int retval; int chars_read = 0; char* param_start = buffer; retval = guacd_parse_name(buffer, length, param_name); if (retval < 0) return -1; /* If no name found, no parameter/value pair */ if (retval == 0) return 0; /* Validate presence of section header */ if (__guacd_current_section[0] == '\0') { guacd_conf_parse_error = "Parameters must have a corresponding section"; guacd_conf_parse_error_location = buffer; return -1; } chars_read += retval; buffer += retval; length -= retval; /* Optional whitespace before '=' */ retval = guacd_parse_whitespace(buffer, length); chars_read += retval; buffer += retval; length -= retval; /* Required '=' */ if (length == 0 || *buffer != '=') { guacd_conf_parse_error = "'=' expected"; guacd_conf_parse_error_location = buffer; return -1; } chars_read++; buffer++; length--; /* Optional whitespace before value */ retval = guacd_parse_whitespace(buffer, length); chars_read += retval; buffer += retval; length -= retval; /* Quoted parameter value */ retval = guacd_parse_quoted_value(buffer, length, param_value); if (retval < 0) return -1; /* Non-quoted parameter value (required if no quoted value given) */ if (retval == 0) retval = guacd_parse_value(buffer, length, param_value); if (retval < 0) return -1; chars_read += retval; /* Call callback, handling error code */ if (callback(__guacd_current_section, param_name, param_value, data)) { guacd_conf_parse_error_location = param_start; return -1; } return chars_read; } /** * Reads a section name from the beginning of the given buffer. This section * name must conform to the grammar definition. If the section name does not * match, a negative value is returned. */ static int guacd_parse_section(char* buffer, int length) { int retval; /* Assert first character is '[' */ if (length == 0 || *buffer != '[') return 0; int chars_read = 1; buffer++; length--; retval = guacd_parse_name(buffer, length, __guacd_current_section); if (retval < 0) return -1; /* If no name found, invalid section */ if (retval == 0) { guacd_conf_parse_error = "Section names must contain at least one character"; guacd_conf_parse_error_location = buffer; return -1; } chars_read += retval; buffer += retval; length -= retval; /* Name must end with ']' */ if (length == 0 || *buffer != ']') { guacd_conf_parse_error = "']' expected"; guacd_conf_parse_error_location = buffer; return -1; } chars_read++; return chars_read; } /** * Parses a declaration, which may be either a section name or a * parameter/value pair. The empty string is acceptable, as well, as a * "null declaration". */ static int guacd_parse_declaration(guacd_param_callback* callback, char* buffer, int length, void* data) { int retval; /* Look for section name */ retval = guacd_parse_section(buffer, length); if (retval != 0) return retval; /* Lacking a section name, read parameter/value pair */ retval = guacd_parse_parameter(callback, buffer, length, data); if (retval != 0) return retval; /* Null declaration (default) */ return 0; } /** * Parses a comment, which must start with a '#' character, and terminate with * an end-of-line character. If no EOL is found, or the first character is not * a '#', a negative value is returned. Otherwise, the number of characters * parsed is returned. If no comment is present, zero is returned. */ static int guacd_parse_comment(char* buffer, int length) { /* Need at least one character */ if (length == 0) return 0; /* Assert first character is '#' */ if (*(buffer++) != '#') return 0; int chars_read = 1; /* Advance to first non-space character */ while (chars_read < length) { /* Read character */ char c = *buffer; /* End of comment found at end of line */ if (c == '\n' || c == '\r') return chars_read; chars_read++; buffer++; } /* No end of line in comment */ guacd_conf_parse_error = "expected end-of-line"; guacd_conf_parse_error_location = buffer; return -1; } /** * Parses the end of a line, which may contain a comment. If a parse error * occurs, a negative value is returned. Otherwise, the number of characters * parsed is returned. */ static int guacd_parse_line_end(char* buffer, int length) { int chars_read = 0; int retval; /* Initial optional whitespace */ retval = guacd_parse_whitespace(buffer, length); chars_read += retval; buffer += retval; length -= retval; /* Optional comment */ retval = guacd_parse_comment(buffer, length); if (retval < 0) return -1; chars_read += retval; buffer += retval; length -= retval; /* Assert EOL */ if (length == 0 || (*buffer != '\r' && *buffer != '\n')) { guacd_conf_parse_error = "expected end-of-line"; guacd_conf_parse_error_location = buffer; return -1; } chars_read++; /* Line is valid */ return chars_read; } /** * Parses an entire line - declaration, comment, and all. If a parse error * occurs, a negative value is returned. Otherwise, the number of characters * parsed is returned. */ static int guacd_parse_line(guacd_param_callback* callback, char* buffer, int length, void* data) { int chars_read = 0; int retval; /* Initial optional whitespace */ retval = guacd_parse_whitespace(buffer, length); chars_read += retval; buffer += retval; length -= retval; /* Declaration (which may be the empty string) */ retval = guacd_parse_declaration(callback, buffer, length, data); if (retval < 0) return retval; chars_read += retval; buffer += retval; length -= retval; /* End of line */ retval = guacd_parse_line_end(buffer, length); if (retval < 0) return retval; chars_read += retval; return chars_read; } int guacd_parse_conf(guacd_param_callback* callback, char* buffer, int length, void* data) { /* Empty buffers are valid */ if (length == 0) return 0; return guacd_parse_line(callback, buffer, length, data); } int guacd_parse_log_level(const char* name) { /* Translate log level name */ if (strcmp(name, "info") == 0) return GUAC_LOG_INFO; if (strcmp(name, "error") == 0) return GUAC_LOG_ERROR; if (strcmp(name, "warning") == 0) return GUAC_LOG_WARNING; if (strcmp(name, "debug") == 0) return GUAC_LOG_DEBUG; if (strcmp(name, "trace") == 0) return GUAC_LOG_TRACE; /* No such log level */ return -1; } guacamole-server-1.3.0/src/guacd/daemon.c0000644000175100001440000003461413770226763015200 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "conf.h" #include "conf-args.h" #include "conf-file.h" #include "connection.h" #include "log.h" #include "proc-map.h" #ifdef ENABLE_SSL #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define GUACD_DEV_NULL "/dev/null" #define GUACD_ROOT "/" /** * Redirects the given file descriptor to /dev/null. The given flags must match * the read/write flags of the file descriptor given (if the given file * descriptor was opened write-only, flags here must be O_WRONLY, etc.). * * @param fd * The file descriptor to redirect to /dev/null. * * @param flags * The flags to use when opening /dev/null as the target for redirection. * These flags must match the flags of the file descriptor given. * * @return * Zero on success, non-zero if redirecting the file descriptor fails. */ static int redirect_fd(int fd, int flags) { /* Attempt to open bit bucket */ int new_fd = open(GUACD_DEV_NULL, flags); if (new_fd < 0) return 1; /* If descriptor is different, redirect old to new and close new */ if (new_fd != fd) { dup2(new_fd, fd); close(new_fd); } return 0; } /** * Turns the current process into a daemon through a series of fork() calls. * The standard I/O file desriptors for STDIN, STDOUT, and STDERR will be * redirected to /dev/null, and the working directory is changed to root. * Execution within the caller of this function will terminate before this * function returns, while execution within the daemonized child process will * continue. * * @return * Zero if the daemonization process succeeded and we are now in the * daemonized child process, or non-zero if daemonization failed and we are * still the original caller. This function does not return for the original * caller if daemonization succeeds. */ static int daemonize() { pid_t pid; /* Fork once to ensure we aren't the process group leader */ pid = fork(); if (pid < 0) { guacd_log(GUAC_LOG_ERROR, "Could not fork() parent: %s", strerror(errno)); return 1; } /* Exit if we are the parent */ if (pid > 0) { guacd_log(GUAC_LOG_DEBUG, "Exiting and passing control to PID %i", pid); _exit(0); } /* Start a new session (if not already group leader) */ setsid(); /* Fork again so the session group leader exits */ pid = fork(); if (pid < 0) { guacd_log(GUAC_LOG_ERROR, "Could not fork() group leader: %s", strerror(errno)); return 1; } /* Exit if we are the parent */ if (pid > 0) { guacd_log(GUAC_LOG_DEBUG, "Exiting and passing control to PID %i", pid); _exit(0); } /* Change to root directory */ if (chdir(GUACD_ROOT) < 0) { guacd_log(GUAC_LOG_ERROR, "Unable to change working directory to " GUACD_ROOT); return 1; } /* Reopen the 3 stdxxx to /dev/null */ if (redirect_fd(STDIN_FILENO, O_RDONLY) || redirect_fd(STDOUT_FILENO, O_WRONLY) || redirect_fd(STDERR_FILENO, O_WRONLY)) { guacd_log(GUAC_LOG_ERROR, "Unable to redirect standard file descriptors to " GUACD_DEV_NULL); return 1; } /* Success */ return 0; } #ifdef ENABLE_SSL #ifdef OPENSSL_REQUIRES_THREADING_CALLBACKS /** * Array of mutexes, used by OpenSSL. */ static pthread_mutex_t* guacd_openssl_locks = NULL; /** * Called by OpenSSL when locking or unlocking the Nth mutex. * * @param mode * A bitmask denoting the action to be taken on the Nth lock, such as * CRYPTO_LOCK or CRYPTO_UNLOCK. * * @param n * The index of the lock to lock or unlock. * * @param file * The filename of the function setting the lock, for debugging purposes. * * @param line * The line number of the function setting the lock, for debugging * purposes. */ static void guacd_openssl_locking_callback(int mode, int n, const char* file, int line){ /* Lock given mutex upon request */ if (mode & CRYPTO_LOCK) pthread_mutex_lock(&(guacd_openssl_locks[n])); /* Unlock given mutex upon request */ else if (mode & CRYPTO_UNLOCK) pthread_mutex_unlock(&(guacd_openssl_locks[n])); } /** * Called by OpenSSL when determining the current thread ID. * * @return * An ID which uniquely identifies the current thread. */ static unsigned long guacd_openssl_id_callback() { return (unsigned long) pthread_self(); } /** * Creates the given number of mutexes, such that OpenSSL will have at least * this number of mutexes at its disposal. * * @param count * The number of mutexes (locks) to create. */ static void guacd_openssl_init_locks(int count) { int i; /* Allocate required number of locks */ guacd_openssl_locks = malloc(sizeof(pthread_mutex_t) * count); /* Initialize each lock */ for (i=0; i < count; i++) pthread_mutex_init(&(guacd_openssl_locks[i]), NULL); } /** * Frees the given number of mutexes. * * @param count * The number of mutexes (locks) to free. */ static void guacd_openssl_free_locks(int count) { int i; /* SSL lock array was not initialized */ if (guacd_openssl_locks == NULL) return; /* Free all locks */ for (i=0; i < count; i++) pthread_mutex_destroy(&(guacd_openssl_locks[i])); /* Free lock array */ free(guacd_openssl_locks); } #endif #endif int main(int argc, char* argv[]) { /* Server */ int socket_fd; struct addrinfo* addresses; struct addrinfo* current_address; char bound_address[1024]; char bound_port[64]; int opt_on = 1; struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP }; /* Client */ struct sockaddr_in client_addr; socklen_t client_addr_len; int connected_socket_fd; #ifdef ENABLE_SSL SSL_CTX* ssl_context = NULL; #endif guacd_proc_map* map = guacd_proc_map_alloc(); /* General */ int retval; /* Load configuration */ guacd_config* config = guacd_conf_load(); if (config == NULL || guacd_conf_parse_args(config, argc, argv)) exit(EXIT_FAILURE); /* If requested, simply print version and exit, without initializing the * logging system, etc. */ if (config->print_version) { printf("Guacamole proxy daemon (guacd) version " VERSION "\n"); exit(EXIT_SUCCESS); } /* Init logging as early as possible */ guacd_log_level = config->max_log_level; openlog(GUACD_LOG_NAME, LOG_PID, LOG_DAEMON); /* Log start */ guacd_log(GUAC_LOG_INFO, "Guacamole proxy daemon (guacd) version " VERSION " started"); /* Get addresses for binding */ if ((retval = getaddrinfo(config->bind_host, config->bind_port, &hints, &addresses))) { guacd_log(GUAC_LOG_ERROR, "Error parsing given address or port: %s", gai_strerror(retval)); exit(EXIT_FAILURE); } /* Get socket */ socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd < 0) { guacd_log(GUAC_LOG_ERROR, "Error opening socket: %s", strerror(errno)); exit(EXIT_FAILURE); } /* Allow socket reuse */ if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (void*) &opt_on, sizeof(opt_on))) { guacd_log(GUAC_LOG_WARNING, "Unable to set socket options for reuse: %s", strerror(errno)); } /* Attempt binding of each address until success */ current_address = addresses; while (current_address != NULL) { int retval; /* Resolve hostname */ if ((retval = getnameinfo(current_address->ai_addr, current_address->ai_addrlen, bound_address, sizeof(bound_address), bound_port, sizeof(bound_port), NI_NUMERICHOST | NI_NUMERICSERV))) guacd_log(GUAC_LOG_ERROR, "Unable to resolve host: %s", gai_strerror(retval)); /* Attempt to bind socket to address */ if (bind(socket_fd, current_address->ai_addr, current_address->ai_addrlen) == 0) { guacd_log(GUAC_LOG_DEBUG, "Successfully bound socket to " "host %s, port %s", bound_address, bound_port); /* Done if successful bind */ break; } /* Otherwise log information regarding bind failure */ else guacd_log(GUAC_LOG_DEBUG, "Unable to bind socket to " "host %s, port %s: %s", bound_address, bound_port, strerror(errno)); current_address = current_address->ai_next; } /* If unable to bind to anything, fail */ if (current_address == NULL) { guacd_log(GUAC_LOG_ERROR, "Unable to bind socket to any addresses."); exit(EXIT_FAILURE); } #ifdef ENABLE_SSL /* Init SSL if enabled */ if (config->key_file != NULL || config->cert_file != NULL) { guacd_log(GUAC_LOG_INFO, "Communication will require SSL/TLS."); #ifdef OPENSSL_REQUIRES_THREADING_CALLBACKS /* Init threadsafety in OpenSSL */ guacd_openssl_init_locks(CRYPTO_num_locks()); CRYPTO_set_id_callback(guacd_openssl_id_callback); CRYPTO_set_locking_callback(guacd_openssl_locking_callback); #endif /* Init SSL */ SSL_library_init(); SSL_load_error_strings(); ssl_context = SSL_CTX_new(SSLv23_server_method()); /* Load key */ if (config->key_file != NULL) { guacd_log(GUAC_LOG_INFO, "Using PEM keyfile %s", config->key_file); if (!SSL_CTX_use_PrivateKey_file(ssl_context, config->key_file, SSL_FILETYPE_PEM)) { guacd_log(GUAC_LOG_ERROR, "Unable to load keyfile."); exit(EXIT_FAILURE); } } else guacd_log(GUAC_LOG_WARNING, "No PEM keyfile given - SSL/TLS may not work."); /* Load cert file if specified */ if (config->cert_file != NULL) { guacd_log(GUAC_LOG_INFO, "Using certificate file %s", config->cert_file); if (!SSL_CTX_use_certificate_chain_file(ssl_context, config->cert_file)) { guacd_log(GUAC_LOG_ERROR, "Unable to load certificate."); exit(EXIT_FAILURE); } } else guacd_log(GUAC_LOG_WARNING, "No certificate file given - SSL/TLS may not work."); } #endif /* Daemonize if requested */ if (!config->foreground) { /* Attempt to daemonize process */ if (daemonize()) { guacd_log(GUAC_LOG_ERROR, "Could not become a daemon."); exit(EXIT_FAILURE); } } /* Write PID file if requested */ if (config->pidfile != NULL) { /* Attempt to open pidfile and write PID */ FILE* pidf = fopen(config->pidfile, "w"); if (pidf) { fprintf(pidf, "%d\n", getpid()); fclose(pidf); } /* Fail if could not write PID file*/ else { guacd_log(GUAC_LOG_ERROR, "Could not write PID file: %s", strerror(errno)); exit(EXIT_FAILURE); } } /* Ignore SIGPIPE */ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { guacd_log(GUAC_LOG_INFO, "Could not set handler for SIGPIPE to ignore. " "SIGPIPE may cause termination of the daemon."); } /* Ignore SIGCHLD (force automatic removal of children) */ if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { guacd_log(GUAC_LOG_INFO, "Could not set handler for SIGCHLD to ignore. " "Child processes may pile up in the process table."); } /* Log listening status */ guacd_log(GUAC_LOG_INFO, "Listening on host %s, port %s", bound_address, bound_port); /* Free addresses */ freeaddrinfo(addresses); /* Listen for connections */ if (listen(socket_fd, 5) < 0) { guacd_log(GUAC_LOG_ERROR, "Could not listen on socket: %s", strerror(errno)); return 3; } /* Daemon loop */ for (;;) { pthread_t child_thread; /* Accept connection */ client_addr_len = sizeof(client_addr); connected_socket_fd = accept(socket_fd, (struct sockaddr*) &client_addr, &client_addr_len); if (connected_socket_fd < 0) { guacd_log(GUAC_LOG_ERROR, "Could not accept client connection: %s", strerror(errno)); continue; } /* Create parameters for connection thread */ guacd_connection_thread_params* params = malloc(sizeof(guacd_connection_thread_params)); if (params == NULL) { guacd_log(GUAC_LOG_ERROR, "Could not create connection thread: %s", strerror(errno)); continue; } params->map = map; params->connected_socket_fd = connected_socket_fd; #ifdef ENABLE_SSL params->ssl_context = ssl_context; #endif /* Spawn thread to handle connection */ pthread_create(&child_thread, NULL, guacd_connection_thread, params); pthread_detach(child_thread); } /* Close socket */ if (close(socket_fd) < 0) { guacd_log(GUAC_LOG_ERROR, "Could not close socket: %s", strerror(errno)); return 3; } #ifdef ENABLE_SSL if (ssl_context != NULL) { #ifdef OPENSSL_REQUIRES_THREADING_CALLBACKS guacd_openssl_free_locks(CRYPTO_num_locks()); #endif SSL_CTX_free(ssl_context); } #endif return 0; } guacamole-server-1.3.0/src/guacd/conf-parse.h0000644000175100001440000000451713613156714015770 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUACD_CONF_PARSE_H #define _GUACD_CONF_PARSE_H /** * The maximum length of a name, in characters. */ #define GUACD_CONF_MAX_NAME_LENGTH 255 /** * The maximum length of a value, in characters. */ #define GUACD_CONF_MAX_VALUE_LENGTH 8191 /** * A callback function which is provided to guacd_parse_conf() and is called * for each parameter/value pair set. The current section is always given. This * function will not be called for parameters outside of sections, which are * illegal. */ typedef int guacd_param_callback(const char* section, const char* param, const char* value, void* data); /** * Parses an arbitrary buffer of configuration file data, calling the given * callback for each valid parameter/value pair. Upon success, the number of * characters parsed is returned. On failure, a negative value is returned, and * guacd_conf_parse_error and guacd_conf_parse_error_location are set. The * provided data will be passed to the callback for each invocation. */ int guacd_parse_conf(guacd_param_callback* callback, char* buffer, int length, void* data); /** * Parses the given level name, returning the corresponding log level, or -1 if * no such log level exists. */ int guacd_parse_log_level(const char* name); /** * Human-readable description of the current error, if any. */ extern char* guacd_conf_parse_error; /** * The location of the most recent parse error. This will be a pointer to the * location of the error within the buffer passed to guacd_parse_conf(). */ extern char* guacd_conf_parse_error_location; #endif guacamole-server-1.3.0/src/guacd/log.h0000644000175100001440000000415513613156714014512 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUACD_LOG_H #define __GUACD_LOG_H #include "config.h" #include /** * The maximum level at which to log messages. All other messages will be * dropped. */ extern int guacd_log_level; /** * The string to prepend to all log messages. */ #define GUACD_LOG_NAME "guacd" /** * Writes a message to guacd's logs. This function takes a format and va_list, * similar to vprintf. */ void vguacd_log(guac_client_log_level level, const char* format, va_list args); /** * Writes a message to guacd's logs. This function accepts parameters * identically to printf. */ void guacd_log(guac_client_log_level level, const char* format, ...); /** * Writes a message using the logging facilities of the given client. This * function accepts parameters identically to printf. */ void guacd_client_log(guac_client* client, guac_client_log_level level, const char* format, va_list args); /** * Prints an error message to guacd's logs, automatically including any * information present in guac_error. This function accepts parameters * identically to printf. */ void guacd_log_guac_error(guac_client_log_level level, const char* message); /** * Logs a reasonable explanatory message regarding handshake failure based on * the current value of guac_error. */ void guacd_log_handshake_failure(); #endif guacamole-server-1.3.0/src/guacd/conf-args.h0000644000175100001440000000216513702142276015604 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUACD_CONF_ARGS_H #define _GUACD_CONF_ARGS_H #include "config.h" #include "conf.h" /** * Parses the given arguments into the given configuration. Zero is returned on * success, and non-zero is returned if arguments cannot be parsed. */ int guacd_conf_parse_args(guacd_config* config, int argc, char** argv); #endif guacamole-server-1.3.0/src/guacd/init.d/0000755000175100001440000000000013772471156015026 500000000000000guacamole-server-1.3.0/src/guacd/init.d/guacd.in0000644000175100001440000000564013613156714016360 00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # guacd # # chkconfig: 2345 20 80 # description: Guacamole proxy daemon ### BEGIN INIT INFO # Provides: guacd # Required-Start: $network $syslog # Required-Stop: $network $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Guacamole proxy daemon # Description: The Guacamole proxy daemon, required to translate remote desktop protocols into the text-based Guacamole protocol used by the JavaScript application. ### END INIT INFO prog="guacd" exec="@sbindir@/$prog" pidfile="/var/run/$prog.pid" # Returns PID of currently running process, if any getpid() { if [ -f "$pidfile" ] then read PID < "$pidfile" # If pidfile contains PID and PID is valid if [ -n "$PID" ] && ps "$PID" > /dev/null 2>&1 then echo "$PID" return 0 fi fi # pidfile/pid not found, or process is dead return 1 } start() { [ -x $exec ] || exit 5 echo -n "Starting $prog: " getpid > /dev/null || $exec -p "$pidfile" retval=$? case "$retval" in 0) echo "SUCCESS" ;; *) echo "FAIL" ;; esac return $retval } stop() { echo -n "Stopping $prog: " PID=`getpid` retval=$? case "$retval" in 0) if kill $PID > /dev/null 2>&1 then echo "SUCCESS" return 0 fi echo "FAIL" return 1 ;; *) echo "SUCCESS (not running)" return 0 ;; esac } restart() { stop && start } force_reload() { restart } status() { PID=`getpid` retval=$? case "$retval" in 0) echo "$prog is running with PID=$PID." ;; *) echo "$prog is not running." ;; esac return $retval } case "$1" in start|stop|status|restart|force-reload) $1 ;; try-restart) status && restart ;; *) echo "Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac exit $? guacamole-server-1.3.0/src/guacd/man/0000755000175100001440000000000013772471154014412 500000000000000guacamole-server-1.3.0/src/guacd/man/guacd.conf.5.in0000644000175100001440000001226213676721354017042 00000000000000.\" .\" Licensed to the Apache Software Foundation (ASF) under one .\" or more contributor license agreements. See the NOTICE file .\" distributed with this work for additional information .\" regarding copyright ownership. The ASF licenses this file .\" to you under the Apache License, Version 2.0 (the .\" "License"); you may not use this file except in compliance .\" with the License. You may obtain a copy of the License at .\" .\" http://www.apache.org/licenses/LICENSE-2.0 .\" .\" Unless required by applicable law or agreed to in writing, .\" software distributed under the License is distributed on an .\" "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY .\" KIND, either express or implied. See the License for the .\" specific language governing permissions and limitations .\" under the License. .\" .TH guacd.conf 5 "1 Jun 2017" "version @PACKAGE_VERSION@" "Apache Guacamole" . .SH NAME /etc/guacamole/guacd.conf \- Configuration file for guacd . .SH DESCRIPTION .B /etc/guacamole/guacd.conf is the configuration file for the Guacamole proxy daemon used by the Guacamole web application and framework, .B guacd. Use of this file is entirely optional, and all of its options can be specified from the command line when running .B guacd. If you provide both the .B guacd.conf file and command line options, the command line options will take precedence. . .SH SYNTAX .B guacd.conf is made up of sections, where each section contains a set of parameter/value pairs. The parameters available are dictated by the section in use, and parameters may only be specified within a section. .P The beginning of each section is denoted with a section name in brackets, and each section ends implicitly with the beginning of a new section, or at the end of the file. .TP \fB[server]\fR Contains parameters which control how .B guacd behaves as a server, from a network perspective. .TP \fB[daemon]\fR Parameters which configure how .B guacd behaves as a daemon, such as what file should contain the PID, if any. .TP \fB[ssl]\fR Parameters which control the SSL support of .B guacd, such as the certificate and private key used for encryption of the Guacamole protocol. This section and its parameters are only valid if .B guacd was built with SSL support. .P Parameters within sections are written as a parameter name, followed by an equals sign, followed by the parameter value, all on one line. Comments may be placed anywhere, and consist of arbitrary text following a .B # symbol until end-of-line: .TP \fIname\fR \fB=\fR \fIvalue\fR \fB#\fR \fISome arbitrary comment text\fR .P Beware that it is the combination of the section name with the parameter name that makes up the fully qualified name of a parameter. Each parameter absolutely .I must be placed only within its proper section, or .B guacd.conf will fail to be parsed, and .B guacd will not start. .P If special characters need to be placed within a parameter value, such as whitespace, \fB#\fR, \fB"\fR, or \fB\\\fR, the entire value must be enclosed in double quotes, and each occurrence of \fB"\fR or \fB\\\fR within the value must be escaped with backslashes: .TP \fIname\fR \fB=\fR \fB"\fR\fIquoted # value \\\\ with \\" special characters\fR\fB"\fR . .SH SERVER PARAMETERS .TP \fBbind_host\fR \fB=\fR \fIHOSTNAME\fR Requires .B guacd to bind to a specific host when listening for connections. By default, .B guacd will bind to localhost only. .TP \fBbind_port\fR \fB=\fR \fIPORT\fR Requires .B guacd to bind to a specific port when listening for connections. By default, .B guacd will bind to port 4822. . .SH DAEMON PARAMETERS .TP \fBlog_level\fR \fB=\fR \fILEVEL\fR Sets the maximum level at which .B guacd will log messages to syslog and, if running in the foreground, the console. Legal values are .B trace, .B debug, .B info, .B warning, and .B error. The default value is .B info. .TP \fBpid_file\fR \fB=\fR \fIFILE\fR Causes .B guacd to write its PID to the specified file upon startup. Note that .B guacd must have sufficient privileges to create or write this file, or it will fail to start. This parameter is typically needed for startup scripts, such that the script can report on the status of .B guacd and kill it if necessary. . .SH SSL PARAMETERS If .B guacd was built with SSL support, then connections between the web application and .B guacd can be encrypted if an SSL certificate and key file are given. .P When using a chain of certificates, you must append the additional certificates to your server certificate. This can be done easily with the standard .B cat command. Beware that the certificate for .B guacd .I must be the first certificate in the file. .TP \fBserver_certificate\fR \fB=\fR \fICERTIFICATE FILE\fR Enables SSL/TLS using the given cerficiate file. Future connections to .B guacd will require SSL/TLS enabled in the client (the web application). .TP \fBserver_key\fR \fB=\fR \fIKEY FILE\fR Enables SSL/TLS using the given private key file. Future connections to .B guacd will require SSL/TLS enabled in the client (the web application). . .SH EXAMPLE .nf .RS # # guacd.conf example # [daemon] pid_file = /var/run/guacd.pid [server] bind_host = localhost bind_port = 4822 [ssl] server_certificate = /etc/ssl/certs/guacd.crt server_key = /etc/ssl/private/guacd.key .RE .fi guacamole-server-1.3.0/src/guacd/man/guacd.8.in0000644000175100001440000000662713702142276016117 00000000000000.\" .\" Licensed to the Apache Software Foundation (ASF) under one .\" or more contributor license agreements. See the NOTICE file .\" distributed with this work for additional information .\" regarding copyright ownership. The ASF licenses this file .\" to you under the Apache License, Version 2.0 (the .\" "License"); you may not use this file except in compliance .\" with the License. You may obtain a copy of the License at .\" .\" http://www.apache.org/licenses/LICENSE-2.0 .\" .\" Unless required by applicable law or agreed to in writing, .\" software distributed under the License is distributed on an .\" "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY .\" KIND, either express or implied. See the License for the .\" specific language governing permissions and limitations .\" under the License. .\" .TH guacd 8 "1 Jun 2017" "version @PACKAGE_VERSION@" "Apache Guacamole" . .SH NAME guacd \- Guacamole proxy daemon . .SH SYNOPSIS .B guacd [\fB-b\fR \fIHOST\fR] [\fB-l\fR \fIPORT\fR] [\fB-p\fR \fIPID FILE\fR] [\fB-L\fR \fILOG LEVEL\fR] [\fB-C\fR \fICERTIFICATE FILE\fR] [\fB-K\fR \fIKEY FILE\fR] [\fB-f\fR] [\fB-v\fR] . .SH DESCRIPTION .B guacd is the Guacamole proxy daemon used by the Guacamole web application and framework. As JavaScript cannot handle binary protocols (like VNC and remote desktop) efficiently, a new text-based protocol was developed which would contain a common superset of the operations needed for efficient remote desktop access, but would be easy for JavaScript programs to process. .B guacd is the proxy which translates between arbitrary protocols and the Guacamole protocol. . .SH OPTIONS .TP \fB\-b\fR \fIHOST\fR Changes the host or address that .B guacd listens on. .TP \fB\-l\fR \fIPORT\fR Changes the port that .B guacd listens on (the default is port 4822). .TP \fB\-p\fR \fIFILE\fR Causes .B guacd to write the PID of the daemon process to the specified file. This is useful for init scripts and is used by the provided init script. .TP \fB\-L\fR \fILEVEL\fR Sets the maximum level at which .B guacd will log messages to syslog and, if running in the foreground, the console. Legal values are .B trace, .B debug, .B info, .B warning, and .B error. The default value is .B info. .TP \fB\-f\fR Causes .B guacd to run in the foreground, rather than automatically forking into the background. .TP \fB\-v\fR Causes .B guacd to simply print its version information and exit. . .SH SSL/TLS OPTIONS If libssl was present at the time .B guacd was compiled, it will contain SSL/TLS support, and connections between the web application and .B guacd can be encrypted if a certificate file is given. .P When using a chain of certificates, you must append the additional certificates to your server certificate. This can be done easily with the standard .B cat command. Beware that the certificate for .B guacd .I must be the first certificate in the file. .TP \fB-C\fR \fICERTIFICATE FILE\fR Enables SSL/TLS using the given cerficiate file. Future connections to this instance of .B guacd will require SSL/TLS enabled in the client (the web application). If this option is not given, communication with guacd must be unencrypted. .TP \fB-K\fR \fIKEY FILE\fR Enables SSL/TLS using the given private key file. Future connections to this instance of .B guacd will require SSL/TLS enabled in the client (the web application). If this option is not given, communication with guacd must be unencrypted. . .SH SEE ALSO .BR guacd.conf (5) guacamole-server-1.3.0/src/guacd/log.c0000644000175100001440000001003113772470243014475 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "log.h" #include #include #include #include #include #include int guacd_log_level = GUAC_LOG_INFO; void vguacd_log(guac_client_log_level level, const char* format, va_list args) { const char* priority_name; int priority; char message[2048]; /* Don't bother if the log level is too high */ if (level > guacd_log_level) return; /* Copy log message into buffer */ vsnprintf(message, sizeof(message), format, args); /* Convert log level to syslog priority */ switch (level) { /* Error log level */ case GUAC_LOG_ERROR: priority = LOG_ERR; priority_name = "ERROR"; break; /* Warning log level */ case GUAC_LOG_WARNING: priority = LOG_WARNING; priority_name = "WARNING"; break; /* Informational log level */ case GUAC_LOG_INFO: priority = LOG_INFO; priority_name = "INFO"; break; /* Debug log level */ case GUAC_LOG_DEBUG: priority = LOG_DEBUG; priority_name = "DEBUG"; break; /* Trace log level */ case GUAC_LOG_TRACE: priority = LOG_DEBUG; priority_name = "TRACE"; break; /* Any unknown/undefined log level */ default: priority = LOG_INFO; priority_name = "UNKNOWN"; break; } /* Log to syslog */ syslog(priority, "%s", message); /* Log to STDERR */ fprintf(stderr, GUACD_LOG_NAME "[%i]: %s:\t%s\n", getpid(), priority_name, message); } void guacd_log(guac_client_log_level level, const char* format, ...) { va_list args; va_start(args, format); vguacd_log(level, format, args); va_end(args); } void guacd_client_log(guac_client* client, guac_client_log_level level, const char* format, va_list args) { vguacd_log(level, format, args); } void guacd_log_guac_error(guac_client_log_level level, const char* message) { if (guac_error != GUAC_STATUS_SUCCESS) { /* If error message provided, include in log */ if (guac_error_message != NULL) guacd_log(level, "%s: %s", message, guac_error_message); /* Otherwise just log with standard status string */ else guacd_log(level, "%s: %s", message, guac_status_string(guac_error)); } /* Just log message if no status code */ else guacd_log(level, "%s", message); } void guacd_log_handshake_failure() { if (guac_error == GUAC_STATUS_CLOSED) guacd_log(GUAC_LOG_DEBUG, "Guacamole connection closed during handshake"); else if (guac_error == GUAC_STATUS_PROTOCOL_ERROR) guacd_log(GUAC_LOG_ERROR, "Guacamole protocol violation. Perhaps the version of " "guacamole-client is incompatible with this version of " "guacd?"); else guacd_log(GUAC_LOG_WARNING, "Guacamole handshake failed: %s", guac_status_string(guac_error)); } guacamole-server-1.3.0/src/guacd/Makefile.in0000644000175100001440000013757213772471101015633 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ sbin_PROGRAMS = guacd$(EXEEXT) subdir = src/guacd ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(initdir)" \ "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" \ "$(DESTDIR)$(systemddir)" PROGRAMS = $(sbin_PROGRAMS) am_guacd_OBJECTS = guacd-conf-args.$(OBJEXT) guacd-conf-file.$(OBJEXT) \ guacd-conf-parse.$(OBJEXT) guacd-connection.$(OBJEXT) \ guacd-daemon.$(OBJEXT) guacd-log.$(OBJEXT) \ guacd-move-fd.$(OBJEXT) guacd-proc.$(OBJEXT) \ guacd-proc-map.$(OBJEXT) guacd_OBJECTS = $(am_guacd_OBJECTS) guacd_DEPENDENCIES = AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = guacd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(guacd_CFLAGS) $(CFLAGS) \ $(guacd_LDFLAGS) $(LDFLAGS) -o $@ am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } SCRIPTS = $(init_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/guacd-conf-args.Po \ ./$(DEPDIR)/guacd-conf-file.Po ./$(DEPDIR)/guacd-conf-parse.Po \ ./$(DEPDIR)/guacd-connection.Po ./$(DEPDIR)/guacd-daemon.Po \ ./$(DEPDIR)/guacd-log.Po ./$(DEPDIR)/guacd-move-fd.Po \ ./$(DEPDIR)/guacd-proc-map.Po ./$(DEPDIR)/guacd-proc.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(guacd_SOURCES) DIST_SOURCES = $(guacd_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac man5dir = $(mandir)/man5 man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) DATA = $(systemd_DATA) HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign man_MANS = \ man/guacd.8 \ man/guacd.conf.5 noinst_HEADERS = \ conf.h \ conf-args.h \ conf-file.h \ conf-parse.h \ connection.h \ log.h \ move-fd.h \ proc.h \ proc-map.h guacd_SOURCES = \ conf-args.c \ conf-file.c \ conf-parse.c \ connection.c \ daemon.c \ log.c \ move-fd.c \ proc.c \ proc-map.c guacd_CFLAGS = \ -Werror -Wall -pedantic \ @COMMON_INCLUDE@ \ @LIBGUAC_INCLUDE@ guacd_LDADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ guacd_LDFLAGS = \ @PTHREAD_LIBS@ \ @SSL_LIBS@ EXTRA_DIST = \ init.d/guacd.in \ systemd/guacd.service.in \ man/guacd.8.in \ man/guacd.conf.5.in CLEANFILES = $(init_SCRIPTS) $(systemd_UNITS) # Init script @ENABLE_INIT_TRUE@initdir = @init_dir@ @ENABLE_INIT_TRUE@init_SCRIPTS = init.d/guacd # Systemd service @ENABLE_SYSTEMD_TRUE@systemddir = @systemd_dir@ @ENABLE_SYSTEMD_TRUE@systemd_DATA = systemd/guacd.service all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/guacd/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/guacd/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list guacd$(EXEEXT): $(guacd_OBJECTS) $(guacd_DEPENDENCIES) $(EXTRA_guacd_DEPENDENCIES) @rm -f guacd$(EXEEXT) $(AM_V_CCLD)$(guacd_LINK) $(guacd_OBJECTS) $(guacd_LDADD) $(LIBS) install-initSCRIPTS: $(init_SCRIPTS) @$(NORMAL_INSTALL) @list='$(init_SCRIPTS)'; test -n "$(initdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(initdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(initdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(initdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(initdir)$$dir" || exit $$?; \ } \ ; done uninstall-initSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(init_SCRIPTS)'; test -n "$(initdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(initdir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacd-conf-args.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacd-conf-file.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacd-conf-parse.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacd-connection.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacd-daemon.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacd-log.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacd-move-fd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacd-proc-map.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacd-proc.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< guacd-conf-args.o: conf-args.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-conf-args.o -MD -MP -MF $(DEPDIR)/guacd-conf-args.Tpo -c -o guacd-conf-args.o `test -f 'conf-args.c' || echo '$(srcdir)/'`conf-args.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-conf-args.Tpo $(DEPDIR)/guacd-conf-args.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='conf-args.c' object='guacd-conf-args.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-conf-args.o `test -f 'conf-args.c' || echo '$(srcdir)/'`conf-args.c guacd-conf-args.obj: conf-args.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-conf-args.obj -MD -MP -MF $(DEPDIR)/guacd-conf-args.Tpo -c -o guacd-conf-args.obj `if test -f 'conf-args.c'; then $(CYGPATH_W) 'conf-args.c'; else $(CYGPATH_W) '$(srcdir)/conf-args.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-conf-args.Tpo $(DEPDIR)/guacd-conf-args.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='conf-args.c' object='guacd-conf-args.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-conf-args.obj `if test -f 'conf-args.c'; then $(CYGPATH_W) 'conf-args.c'; else $(CYGPATH_W) '$(srcdir)/conf-args.c'; fi` guacd-conf-file.o: conf-file.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-conf-file.o -MD -MP -MF $(DEPDIR)/guacd-conf-file.Tpo -c -o guacd-conf-file.o `test -f 'conf-file.c' || echo '$(srcdir)/'`conf-file.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-conf-file.Tpo $(DEPDIR)/guacd-conf-file.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='conf-file.c' object='guacd-conf-file.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-conf-file.o `test -f 'conf-file.c' || echo '$(srcdir)/'`conf-file.c guacd-conf-file.obj: conf-file.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-conf-file.obj -MD -MP -MF $(DEPDIR)/guacd-conf-file.Tpo -c -o guacd-conf-file.obj `if test -f 'conf-file.c'; then $(CYGPATH_W) 'conf-file.c'; else $(CYGPATH_W) '$(srcdir)/conf-file.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-conf-file.Tpo $(DEPDIR)/guacd-conf-file.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='conf-file.c' object='guacd-conf-file.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-conf-file.obj `if test -f 'conf-file.c'; then $(CYGPATH_W) 'conf-file.c'; else $(CYGPATH_W) '$(srcdir)/conf-file.c'; fi` guacd-conf-parse.o: conf-parse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-conf-parse.o -MD -MP -MF $(DEPDIR)/guacd-conf-parse.Tpo -c -o guacd-conf-parse.o `test -f 'conf-parse.c' || echo '$(srcdir)/'`conf-parse.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-conf-parse.Tpo $(DEPDIR)/guacd-conf-parse.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='conf-parse.c' object='guacd-conf-parse.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-conf-parse.o `test -f 'conf-parse.c' || echo '$(srcdir)/'`conf-parse.c guacd-conf-parse.obj: conf-parse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-conf-parse.obj -MD -MP -MF $(DEPDIR)/guacd-conf-parse.Tpo -c -o guacd-conf-parse.obj `if test -f 'conf-parse.c'; then $(CYGPATH_W) 'conf-parse.c'; else $(CYGPATH_W) '$(srcdir)/conf-parse.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-conf-parse.Tpo $(DEPDIR)/guacd-conf-parse.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='conf-parse.c' object='guacd-conf-parse.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-conf-parse.obj `if test -f 'conf-parse.c'; then $(CYGPATH_W) 'conf-parse.c'; else $(CYGPATH_W) '$(srcdir)/conf-parse.c'; fi` guacd-connection.o: connection.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-connection.o -MD -MP -MF $(DEPDIR)/guacd-connection.Tpo -c -o guacd-connection.o `test -f 'connection.c' || echo '$(srcdir)/'`connection.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-connection.Tpo $(DEPDIR)/guacd-connection.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='connection.c' object='guacd-connection.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-connection.o `test -f 'connection.c' || echo '$(srcdir)/'`connection.c guacd-connection.obj: connection.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-connection.obj -MD -MP -MF $(DEPDIR)/guacd-connection.Tpo -c -o guacd-connection.obj `if test -f 'connection.c'; then $(CYGPATH_W) 'connection.c'; else $(CYGPATH_W) '$(srcdir)/connection.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-connection.Tpo $(DEPDIR)/guacd-connection.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='connection.c' object='guacd-connection.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-connection.obj `if test -f 'connection.c'; then $(CYGPATH_W) 'connection.c'; else $(CYGPATH_W) '$(srcdir)/connection.c'; fi` guacd-daemon.o: daemon.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-daemon.o -MD -MP -MF $(DEPDIR)/guacd-daemon.Tpo -c -o guacd-daemon.o `test -f 'daemon.c' || echo '$(srcdir)/'`daemon.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-daemon.Tpo $(DEPDIR)/guacd-daemon.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='daemon.c' object='guacd-daemon.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-daemon.o `test -f 'daemon.c' || echo '$(srcdir)/'`daemon.c guacd-daemon.obj: daemon.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-daemon.obj -MD -MP -MF $(DEPDIR)/guacd-daemon.Tpo -c -o guacd-daemon.obj `if test -f 'daemon.c'; then $(CYGPATH_W) 'daemon.c'; else $(CYGPATH_W) '$(srcdir)/daemon.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-daemon.Tpo $(DEPDIR)/guacd-daemon.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='daemon.c' object='guacd-daemon.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-daemon.obj `if test -f 'daemon.c'; then $(CYGPATH_W) 'daemon.c'; else $(CYGPATH_W) '$(srcdir)/daemon.c'; fi` guacd-log.o: log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-log.o -MD -MP -MF $(DEPDIR)/guacd-log.Tpo -c -o guacd-log.o `test -f 'log.c' || echo '$(srcdir)/'`log.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-log.Tpo $(DEPDIR)/guacd-log.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='log.c' object='guacd-log.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-log.o `test -f 'log.c' || echo '$(srcdir)/'`log.c guacd-log.obj: log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-log.obj -MD -MP -MF $(DEPDIR)/guacd-log.Tpo -c -o guacd-log.obj `if test -f 'log.c'; then $(CYGPATH_W) 'log.c'; else $(CYGPATH_W) '$(srcdir)/log.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-log.Tpo $(DEPDIR)/guacd-log.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='log.c' object='guacd-log.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-log.obj `if test -f 'log.c'; then $(CYGPATH_W) 'log.c'; else $(CYGPATH_W) '$(srcdir)/log.c'; fi` guacd-move-fd.o: move-fd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-move-fd.o -MD -MP -MF $(DEPDIR)/guacd-move-fd.Tpo -c -o guacd-move-fd.o `test -f 'move-fd.c' || echo '$(srcdir)/'`move-fd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-move-fd.Tpo $(DEPDIR)/guacd-move-fd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='move-fd.c' object='guacd-move-fd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-move-fd.o `test -f 'move-fd.c' || echo '$(srcdir)/'`move-fd.c guacd-move-fd.obj: move-fd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-move-fd.obj -MD -MP -MF $(DEPDIR)/guacd-move-fd.Tpo -c -o guacd-move-fd.obj `if test -f 'move-fd.c'; then $(CYGPATH_W) 'move-fd.c'; else $(CYGPATH_W) '$(srcdir)/move-fd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-move-fd.Tpo $(DEPDIR)/guacd-move-fd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='move-fd.c' object='guacd-move-fd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-move-fd.obj `if test -f 'move-fd.c'; then $(CYGPATH_W) 'move-fd.c'; else $(CYGPATH_W) '$(srcdir)/move-fd.c'; fi` guacd-proc.o: proc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-proc.o -MD -MP -MF $(DEPDIR)/guacd-proc.Tpo -c -o guacd-proc.o `test -f 'proc.c' || echo '$(srcdir)/'`proc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-proc.Tpo $(DEPDIR)/guacd-proc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='proc.c' object='guacd-proc.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-proc.o `test -f 'proc.c' || echo '$(srcdir)/'`proc.c guacd-proc.obj: proc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-proc.obj -MD -MP -MF $(DEPDIR)/guacd-proc.Tpo -c -o guacd-proc.obj `if test -f 'proc.c'; then $(CYGPATH_W) 'proc.c'; else $(CYGPATH_W) '$(srcdir)/proc.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-proc.Tpo $(DEPDIR)/guacd-proc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='proc.c' object='guacd-proc.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-proc.obj `if test -f 'proc.c'; then $(CYGPATH_W) 'proc.c'; else $(CYGPATH_W) '$(srcdir)/proc.c'; fi` guacd-proc-map.o: proc-map.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-proc-map.o -MD -MP -MF $(DEPDIR)/guacd-proc-map.Tpo -c -o guacd-proc-map.o `test -f 'proc-map.c' || echo '$(srcdir)/'`proc-map.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-proc-map.Tpo $(DEPDIR)/guacd-proc-map.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='proc-map.c' object='guacd-proc-map.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-proc-map.o `test -f 'proc-map.c' || echo '$(srcdir)/'`proc-map.c guacd-proc-map.obj: proc-map.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -MT guacd-proc-map.obj -MD -MP -MF $(DEPDIR)/guacd-proc-map.Tpo -c -o guacd-proc-map.obj `if test -f 'proc-map.c'; then $(CYGPATH_W) 'proc-map.c'; else $(CYGPATH_W) '$(srcdir)/proc-map.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacd-proc-map.Tpo $(DEPDIR)/guacd-proc-map.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='proc-map.c' object='guacd-proc-map.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacd_CFLAGS) $(CFLAGS) -c -o guacd-proc-map.obj `if test -f 'proc-map.c'; then $(CYGPATH_W) 'proc-map.c'; else $(CYGPATH_W) '$(srcdir)/proc-map.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man5: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man5dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.5[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ done; } uninstall-man5: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man5dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.5[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) install-man8: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) install-systemdDATA: $(systemd_DATA) @$(NORMAL_INSTALL) @list='$(systemd_DATA)'; test -n "$(systemddir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(systemddir)'"; \ $(MKDIR_P) "$(DESTDIR)$(systemddir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(systemddir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(systemddir)" || exit $$?; \ done uninstall-systemdDATA: @$(NORMAL_UNINSTALL) @list='$(systemd_DATA)'; test -n "$(systemddir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(systemddir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(MANS) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(initdir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(systemddir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/guacd-conf-args.Po -rm -f ./$(DEPDIR)/guacd-conf-file.Po -rm -f ./$(DEPDIR)/guacd-conf-parse.Po -rm -f ./$(DEPDIR)/guacd-connection.Po -rm -f ./$(DEPDIR)/guacd-daemon.Po -rm -f ./$(DEPDIR)/guacd-log.Po -rm -f ./$(DEPDIR)/guacd-move-fd.Po -rm -f ./$(DEPDIR)/guacd-proc-map.Po -rm -f ./$(DEPDIR)/guacd-proc.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-initSCRIPTS install-man install-systemdDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man5 install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/guacd-conf-args.Po -rm -f ./$(DEPDIR)/guacd-conf-file.Po -rm -f ./$(DEPDIR)/guacd-conf-parse.Po -rm -f ./$(DEPDIR)/guacd-connection.Po -rm -f ./$(DEPDIR)/guacd-daemon.Po -rm -f ./$(DEPDIR)/guacd-log.Po -rm -f ./$(DEPDIR)/guacd-move-fd.Po -rm -f ./$(DEPDIR)/guacd-proc-map.Po -rm -f ./$(DEPDIR)/guacd-proc.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-initSCRIPTS uninstall-man \ uninstall-sbinPROGRAMS uninstall-systemdDATA uninstall-man: uninstall-man5 uninstall-man8 .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-sbinPROGRAMS cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-initSCRIPTS install-man install-man5 \ install-man8 install-pdf install-pdf-am install-ps \ install-ps-am install-sbinPROGRAMS install-strip \ install-systemdDATA installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-initSCRIPTS uninstall-man uninstall-man5 \ uninstall-man8 uninstall-sbinPROGRAMS uninstall-systemdDATA .PRECIOUS: Makefile @ENABLE_INIT_TRUE@init.d/guacd: init.d/guacd.in @ENABLE_INIT_TRUE@ sed -e 's,[@]sbindir[@],$(sbindir),g' < init.d/guacd.in > init.d/guacd @ENABLE_INIT_TRUE@ chmod +x init.d/guacd @ENABLE_SYSTEMD_TRUE@systemd/guacd.service: systemd/guacd.service.in @ENABLE_SYSTEMD_TRUE@ sed -e 's,[@]sbindir[@],$(sbindir),g' < systemd/guacd.service.in > systemd/guacd.service # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/guacd/conf-args.c0000644000175100001440000000653713702142276015606 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "conf.h" #include "conf-args.h" #include "conf-parse.h" #include #include #include #include int guacd_conf_parse_args(guacd_config* config, int argc, char** argv) { /* Parse arguments */ int opt; while ((opt = getopt(argc, argv, "l:b:p:L:C:K:fv")) != -1) { /* -l: Bind port */ if (opt == 'l') { free(config->bind_port); config->bind_port = strdup(optarg); } /* -b: Bind host */ else if (opt == 'b') { free(config->bind_host); config->bind_host = strdup(optarg); } /* -f: Run in foreground */ else if (opt == 'f') { config->foreground = 1; } /* -v: Print version and exit */ else if (opt == 'v') { config->print_version = 1; } /* -p: PID file */ else if (opt == 'p') { free(config->pidfile); config->pidfile = strdup(optarg); } /* -L: Log level */ else if (opt == 'L') { /* Validate and parse log level */ int level = guacd_parse_log_level(optarg); if (level == -1) { fprintf(stderr, "Invalid log level. Valid levels are: \"trace\", \"debug\", \"info\", \"warning\", and \"error\".\n"); return 1; } config->max_log_level = level; } #ifdef ENABLE_SSL /* -C SSL certificate */ else if (opt == 'C') { free(config->cert_file); config->cert_file = strdup(optarg); } /* -K SSL key */ else if (opt == 'K') { free(config->key_file); config->key_file = strdup(optarg); } #else else if (opt == 'C' || opt == 'K') { fprintf(stderr, "This guacd does not have SSL/TLS support compiled in.\n\n" "If you wish to enable support for the -%c option, please install libssl and\n" "recompile guacd.\n", opt); return 1; } #endif else { fprintf(stderr, "USAGE: %s" " [-l LISTENPORT]" " [-b LISTENADDRESS]" " [-p PIDFILE]" " [-L LEVEL]" #ifdef ENABLE_SSL " [-C CERTIFICATE_FILE]" " [-K PEM_FILE]" #endif " [-f]" " [-v]\n", argv[0]); return 1; } } /* Success */ return 0; } guacamole-server-1.3.0/src/guacd/conf.h0000644000175100001440000000324313702142276014650 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACD_CONF_H #define GUACD_CONF_H #include "config.h" #include /** * The contents of a guacd configuration file. */ typedef struct guacd_config { /** * The host to bind on. */ char* bind_host; /** * The port to bind on. */ char* bind_port; /** * The file to write the PID in, if any. */ char* pidfile; /** * Whether guacd should run in the foreground. */ int foreground; /** * Whether guacd should simply print its version information and exit. */ int print_version; #ifdef ENABLE_SSL /** * SSL certificate file. */ char* cert_file; /** * SSL private key file. */ char* key_file; #endif /** * The maximum log level to be logged by guacd. */ guac_client_log_level max_log_level; } guacd_config; #endif guacamole-server-1.3.0/src/guacd/conf-file.c0000644000175100001440000001264613702142276015567 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "conf.h" #include "conf-file.h" #include "conf-parse.h" #include #include #include #include #include #include #include #include #include /** * Updates the configuration with the given parameter/value pair, flagging * errors as necessary. */ static int guacd_conf_callback(const char* section, const char* param, const char* value, void* data) { guacd_config* config = (guacd_config*) data; /* Network server options */ if (strcmp(section, "server") == 0) { /* Bind host */ if (strcmp(param, "bind_host") == 0) { free(config->bind_host); config->bind_host = strdup(value); return 0; } /* Bind port */ else if (strcmp(param, "bind_port") == 0) { free(config->bind_port); config->bind_port = strdup(value); return 0; } } /* Options related to daemon startup */ else if (strcmp(section, "daemon") == 0) { /* PID file */ if (strcmp(param, "pid_file") == 0) { free(config->pidfile); config->pidfile = strdup(value); return 0; } /* Max log level */ else if (strcmp(param, "log_level") == 0) { int level = guacd_parse_log_level(value); /* Invalid log level */ if (level < 0) { guacd_conf_parse_error = "Invalid log level. Valid levels are: \"trace\", \"debug\", \"info\", \"warning\", and \"error\"."; return 1; } /* Valid log level */ config->max_log_level = level; return 0; } } /* SSL-specific options */ else if (strcmp(section, "ssl") == 0) { #ifdef ENABLE_SSL /* SSL certificate */ if (strcmp(param, "server_certificate") == 0) { free(config->cert_file); config->cert_file = strdup(value); return 0; } /* SSL key */ else if (strcmp(param, "server_key") == 0) { free(config->key_file); config->key_file = strdup(value); return 0; } #else guacd_conf_parse_error = "SSL support not compiled in"; return 1; #endif } /* If still unhandled, the parameter/section is invalid */ guacd_conf_parse_error = "Invalid parameter or section name"; return 1; } int guacd_conf_parse_file(guacd_config* conf, int fd) { int chars_read; char buffer[8192]; int length = 0; int line = 1; char* line_start = buffer; int parsed = 0; /* Attempt to fill remaining space in buffer */ while ((chars_read = read(fd, buffer + length, sizeof(buffer) - length)) > 0) { length += chars_read; line_start = buffer; /* Attempt to parse entire buffer */ while ((parsed = guacd_parse_conf(guacd_conf_callback, line_start, length, conf)) > 0) { line_start += parsed; length -= parsed; line++; } /* Shift contents to front */ memmove(buffer, line_start, length); } /* Handle parse errors */ if (parsed < 0) { int column = guacd_conf_parse_error_location - line_start + 1; fprintf(stderr, "Parse error at line %i, column %i: %s.\n", line, column, guacd_conf_parse_error); return 1; } /* Check for error conditions */ if (chars_read < 0) { fprintf(stderr, "Error reading configuration: %s\n", strerror(errno)); return 1; } /* Read successfully */ return 0; } guacd_config* guacd_conf_load() { guacd_config* conf = malloc(sizeof(guacd_config)); if (conf == NULL) return NULL; /* Load defaults */ conf->bind_host = NULL; conf->bind_port = strdup("4822"); conf->pidfile = NULL; conf->foreground = 0; conf->print_version = 0; conf->max_log_level = GUAC_LOG_INFO; #ifdef ENABLE_SSL conf->cert_file = NULL; conf->key_file = NULL; #endif /* Read configuration from file */ int fd = open(GUACD_CONF_FILE, O_RDONLY); if (fd > 0) { int retval = guacd_conf_parse_file(conf, fd); close(fd); if (retval != 0) { fprintf(stderr, "Unable to parse \"" GUACD_CONF_FILE "\".\n"); free(conf); return NULL; } } /* Notify of errors preventing reading */ else if (errno != ENOENT) { fprintf(stderr, "Unable to open \"" GUACD_CONF_FILE "\": %s\n", strerror(errno)); free(conf); return NULL; } return conf; } guacamole-server-1.3.0/src/guacd/move-fd.h0000644000175100001440000000402313613156714015260 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACD_MOVE_FD_H #define GUACD_MOVE_FD_H #include "config.h" /** * Sends the given file descriptor along the given socket, allowing the * receiving process to use that file descriptor normally. Returns non-zero on * success, zero on error, just as a normal call to sendmsg() would. If an * error does occur, errno will be set appropriately. * * @param sock * The file descriptor of an open UNIX domain socket along which the file * descriptor specified by fd should be sent. * * @param fd * The file descriptor to send along the given UNIX domain socket. * * @return * Non-zero if the send operation succeeded, zero on error. */ int guacd_send_fd(int sock, int fd); /** * Waits for a file descriptor on the given socket, returning the received file * descriptor. The file descriptor must have been sent via guacd_send_fd. If an * error occurs, -1 is returned, and errno will be set appropriately. * * @param sock * The file descriptor of an open UNIX domain socket along which the file * descriptor will be sent (by guacd_send_fd()). * * @return * The received file descriptor, or -1 if an error occurs preventing * receipt of the file descriptor. */ int guacd_recv_fd(int sock); #endif guacamole-server-1.3.0/src/guacd/connection.c0000644000175100001440000002670213676721354016074 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "connection.h" #include "log.h" #include "move-fd.h" #include "proc.h" #include "proc-map.h" #include #include #include #include #include #include #include #ifdef ENABLE_SSL #include #include #endif #include #include #include #include #include #include /** * Behaves exactly as write(), but writes as much as possible, returning * successfully only if the entire buffer was written. If the write fails for * any reason, a negative value is returned. * * @param fd * The file descriptor to write to. * * @param buffer * The buffer containing the data to be written. * * @param length * The number of bytes in the buffer to write. * * @return * The number of bytes written, or -1 if an error occurs. As this function * is guaranteed to write ALL bytes, this will always be the number of * bytes specified by length unless an error occurs. */ static int __write_all(int fd, char* buffer, int length) { /* Repeatedly write() until all data is written */ while (length > 0) { int written = write(fd, buffer, length); if (written < 0) return -1; length -= written; buffer += written; } return length; } /** * Continuously reads from a guac_socket, writing all data read to a file * descriptor. Any data already buffered from that guac_socket by a given * guac_parser is read first, prior to reading further data from the * guac_socket. The provided guac_parser will be freed once its buffers have * been emptied, but the guac_socket will not. * * This thread ultimately terminates when no further data can be read from the * guac_socket. * * @param data * A pointer to a guacd_connection_io_thread_params structure containing * the guac_socket to read from, the file descriptor to write the read data * to, and the guac_parser associated with the guac_socket which may have * unhandled data in its parsing buffers. * * @return * Always NULL. */ static void* guacd_connection_write_thread(void* data) { guacd_connection_io_thread_params* params = (guacd_connection_io_thread_params*) data; char buffer[8192]; int length; /* Read all buffered data from parser first */ while ((length = guac_parser_shift(params->parser, buffer, sizeof(buffer))) > 0) { if (__write_all(params->fd, buffer, length) < 0) break; } /* Parser is no longer needed */ guac_parser_free(params->parser); /* Transfer data from file descriptor to socket */ while ((length = guac_socket_read(params->socket, buffer, sizeof(buffer))) > 0) { if (__write_all(params->fd, buffer, length) < 0) break; } return NULL; } void* guacd_connection_io_thread(void* data) { guacd_connection_io_thread_params* params = (guacd_connection_io_thread_params*) data; char buffer[8192]; int length; pthread_t write_thread; pthread_create(&write_thread, NULL, guacd_connection_write_thread, params); /* Transfer data from file descriptor to socket */ while ((length = read(params->fd, buffer, sizeof(buffer))) > 0) { if (guac_socket_write(params->socket, buffer, length)) break; guac_socket_flush(params->socket); } /* Wait for write thread to die */ pthread_join(write_thread, NULL); /* Clean up */ guac_socket_free(params->socket); close(params->fd); free(params); return NULL; } /** * Adds the given socket as a new user to the given process, automatically * reading/writing from the socket via read/write threads. The given socket, * parser, and any associated resources will be freed unless the user is not * added successfully. * * If adding the user fails for any reason, non-zero is returned. Zero is * returned upon success. * * @param proc * The existing process to add the user to. * * @param parser * The parser associated with the given guac_socket (used to handle the * user's connection handshake thus far). * * @param socket * The socket associated with the user to be added to the existing * process. * * @return * Zero if the user was added successfully, non-zero if an error occurred. */ static int guacd_add_user(guacd_proc* proc, guac_parser* parser, guac_socket* socket) { int sockets[2]; /* Set up socket pair */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) { guacd_log(GUAC_LOG_ERROR, "Unable to allocate file descriptors for I/O transfer: %s", strerror(errno)); return 1; } int user_fd = sockets[0]; int proc_fd = sockets[1]; /* Send user file descriptor to process */ if (!guacd_send_fd(proc->fd_socket, proc_fd)) { guacd_log(GUAC_LOG_ERROR, "Unable to add user."); return 1; } /* Close our end of the process file descriptor */ close(proc_fd); guacd_connection_io_thread_params* params = malloc(sizeof(guacd_connection_io_thread_params)); params->parser = parser; params->socket = socket; params->fd = user_fd; /* Start I/O thread */ pthread_t io_thread; pthread_create(&io_thread, NULL, guacd_connection_io_thread, params); pthread_detach(io_thread); return 0; } /** * Routes the connection on the given socket according to the Guacamole * protocol, adding new users and creating new client processes as needed. If a * new process is created, this function blocks until that process terminates, * automatically deregistering the process at that point. * * The socket provided will be automatically freed when the connection * terminates unless routing fails, in which case non-zero is returned. * * @param map * The map of existing client processes. * * @param socket * The socket associated with the new connection that must be routed to * a new or existing process within the given map. * * @return * Zero if the connection was successfully routed, non-zero if routing has * failed. */ static int guacd_route_connection(guacd_proc_map* map, guac_socket* socket) { guac_parser* parser = guac_parser_alloc(); /* Reset guac_error */ guac_error = GUAC_STATUS_SUCCESS; guac_error_message = NULL; /* Get protocol from select instruction */ if (guac_parser_expect(parser, socket, GUACD_USEC_TIMEOUT, "select")) { /* Log error */ guacd_log_handshake_failure(); guacd_log_guac_error(GUAC_LOG_DEBUG, "Error reading \"select\""); guac_parser_free(parser); return 1; } /* Validate args to select */ if (parser->argc != 1) { /* Log error */ guacd_log_handshake_failure(); guacd_log(GUAC_LOG_ERROR, "Bad number of arguments to \"select\" (%i)", parser->argc); guac_parser_free(parser); return 1; } guacd_proc* proc; int new_process; const char* identifier = parser->argv[0]; /* If connection ID, retrieve existing process */ if (identifier[0] == GUAC_CLIENT_ID_PREFIX) { proc = guacd_proc_map_retrieve(map, identifier); new_process = 0; /* Warn if requested connection does not exist */ if (proc == NULL) guacd_log(GUAC_LOG_INFO, "Connection \"%s\" does not exist.", identifier); else guacd_log(GUAC_LOG_INFO, "Joining existing connection \"%s\"", identifier); } /* Otherwise, create new client */ else { guacd_log(GUAC_LOG_INFO, "Creating new client for protocol \"%s\"", identifier); /* Create new process */ proc = guacd_create_proc(identifier); new_process = 1; } /* Abort if no process exists for the requested connection */ if (proc == NULL) { guacd_log_guac_error(GUAC_LOG_INFO, "Connection did not succeed"); guac_parser_free(parser); return 1; } /* Add new user (in the case of a new process, this will be the owner */ int add_user_failed = guacd_add_user(proc, parser, socket); /* If new process was created, manage that process */ if (new_process) { /* The new process will only be active if the user was added */ if (!add_user_failed) { /* Log connection ID */ guacd_log(GUAC_LOG_INFO, "Connection ID is \"%s\"", proc->client->connection_id); /* Store process, allowing other users to join */ guacd_proc_map_add(map, proc); /* Wait for child to finish */ waitpid(proc->pid, NULL, 0); /* Remove client */ if (guacd_proc_map_remove(map, proc->client->connection_id) == NULL) guacd_log(GUAC_LOG_ERROR, "Internal failure removing " "client \"%s\". Client record will never be freed.", proc->client->connection_id); else guacd_log(GUAC_LOG_INFO, "Connection \"%s\" removed.", proc->client->connection_id); } /* Parser must be manually freed if the process did not start */ else guac_parser_free(parser); /* Force process to stop and clean up */ guacd_proc_stop(proc); /* Free skeleton client */ guac_client_free(proc->client); /* Clean up */ close(proc->fd_socket); free(proc); } /* Routing succeeded only if the user was added to a process */ return add_user_failed; } void* guacd_connection_thread(void* data) { guacd_connection_thread_params* params = (guacd_connection_thread_params*) data; guacd_proc_map* map = params->map; int connected_socket_fd = params->connected_socket_fd; guac_socket* socket; #ifdef ENABLE_SSL SSL_CTX* ssl_context = params->ssl_context; /* If SSL chosen, use it */ if (ssl_context != NULL) { socket = guac_socket_open_secure(ssl_context, connected_socket_fd); if (socket == NULL) { guacd_log_guac_error(GUAC_LOG_ERROR, "Unable to set up SSL/TLS"); close(connected_socket_fd); free(params); return NULL; } } else socket = guac_socket_open(connected_socket_fd); #else /* Open guac_socket */ socket = guac_socket_open(connected_socket_fd); #endif /* Route connection according to Guacamole, creating a new process if needed */ if (guacd_route_connection(map, socket)) guac_socket_free(socket); free(params); return NULL; } guacamole-server-1.3.0/src/guacd/connection.h0000644000175100001440000000736413613156714016075 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACD_CONNECTION_H #define GUACD_CONNECTION_H #include "config.h" #include "proc-map.h" #ifdef ENABLE_SSL #include #endif /** * Parameters required by each connection thread. */ typedef struct guacd_connection_thread_params { /** * The shared map of all connected clients. */ guacd_proc_map* map; #ifdef ENABLE_SSL /** * SSL context for encrypted connections to guacd. If SSL is not active, * this will be NULL. */ SSL_CTX* ssl_context; #endif /** * The file descriptor associated with the newly-accepted connection. */ int connected_socket_fd; } guacd_connection_thread_params; /** * Handles an inbound connection to guacd, allowing guacd to continue listening * for other connections. The file descriptor of the inbound connection will * either be given to a new process for a new remote desktop connection, or * will be passed to an existing process for joining an existing remote desktop * connection. It is expected that this thread will operate detached. The * creating process need not join on the resulting thread. * * @param data * A pointer to a guacd_connection_thread_params structure containing the * shared overall map of currently-connected processes, the file * descriptor associated with the newly-established connection that is to * be either (1) associated with a new process or (2) passed on to an * existing process, and the SSL context for the encryption surrounding * that connection (if any). * * @return * Always NULL. */ void* guacd_connection_thread(void* data); /** * Parameters required by the per-connection I/O transfer thread. */ typedef struct guacd_connection_io_thread_params { /** * The guac_parser which may contain buffered, but unparsed, data from the * original guac_socket which must be transferred to the * connection-specific process. */ guac_parser* parser; /** * The guac_socket which is directly handling I/O from a user's connection * to guacd. */ guac_socket* socket; /** * The file descriptor which is being handled by a guac_socket within the * connection-specific process. */ int fd; } guacd_connection_io_thread_params; /** * Transfers data back and forth between the guacd-side guac_socket and the * file descriptor used by the process-side guac_socket. Note that both the * provided guac_parser and the guac_socket will be freed once this thread * terminates, which will occur when no further data can be read from the * guac_socket. * * @param data * A pointer to a guacd_connection_io_thread_params structure containing * the guac_socket and file descriptor to transfer data between * (bidirectionally), as well as the guac_parser associated with the * guac_socket (which may have unhandled data in its parsing buffers). * * @return * Always NULL. */ void* guacd_connection_io_thread(void* data); #endif guacamole-server-1.3.0/src/guacd/systemd/0000755000175100001440000000000013772471156015331 500000000000000guacamole-server-1.3.0/src/guacd/systemd/guacd.service.in0000644000175100001440000000172413702142276020316 00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. [Unit] Description=Guacamole Server Documentation=man:guacd(8) After=network.target [Service] User=daemon ExecStart=@sbindir@/guacd -f Restart=on-abnormal [Install] WantedBy=multi-user.target guacamole-server-1.3.0/src/guacd/proc.h0000644000175100001440000000665313702142276014676 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACD_PROC_H #define GUACD_PROC_H #include "config.h" #include #include #include /** * The number of milliseconds to wait for messages in any phase before * timing out and closing the connection with an error. */ #define GUACD_TIMEOUT 15000 /** * The number of microseconds to wait for messages in any phase before * timing out and closing the conncetion with an error. This is always * equal to GUACD_TIMEOUT * 1000. */ #define GUACD_USEC_TIMEOUT (GUACD_TIMEOUT*1000) /** * The number of seconds to wait for any particular guac_client instance * to be freed following disconnect. If the free operation does not complete * within this period of time, the associated process will be forcibly * terminated. */ #define GUACD_CLIENT_FREE_TIMEOUT 5 /** * Process information of the internal remote desktop client. */ typedef struct guacd_proc { /** * The process ID of the client. This will only be available to the * parent process. The child process will see this as 0. */ pid_t pid; /** * The file descriptor of the UNIX domain socket to use for sending and * receiving file descriptors of new users. This parent will see this * as the file descriptor for communicating with the child and vice * versa. */ int fd_socket; /** * The actual client instance. This will be visible to both child and * parent process, but only the child will have a full guac_client * instance, containing handlers from the plugin, etc. * * The parent process will receive a skeleton guac_client, containing only * a proper connection_id and logging handlers. The actual * protocol-specific handling will be absent. */ guac_client* client; } guacd_proc; /** * Creates a new background process for handling the given protocol, returning * a structure allowing communication with and monitoring of the process * created. Within the child process, this function does not return - the * entire child process simply terminates instead. * * @param protocol * The protocol for which this process is client being created. * * @return * A newly-allocated process structure pointing to the file descriptor of * the background process specific to the specified protocol, or NULL of * the process could not be created. */ guacd_proc* guacd_create_proc(const char* protocol); /** * Signals the given process to stop accepting new users and clean up. This * will eventually cause the child process to exit. * * @param proc * The process to stop. */ void guacd_proc_stop(guacd_proc* proc); #endif guacamole-server-1.3.0/src/guacd/proc-map.c0000644000175100001440000001236213676721354015450 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/list.h" #include "proc.h" #include "proc-map.h" #include #include #include /** * Returns a hash code based on the given connection ID. * * @param str * The string containing the connection ID. * * @return * A reasonably well-distributed hash code for the given string. */ static unsigned int __guacd_client_hash(const char* str) { unsigned int hash_value = 0; int c; /* Apply each character in string to the hash code */ while ((c = *(str++))) hash_value = hash_value * 65599 + c; return hash_value; } /** * Locates the bucket corresponding to the hash code indicated by the given id, * where the hash code is dictated by __guacd_client_hash(). Each bucket is an * instance of guac_common_list. * * @param map * The map to retrieve the hash bucket from. * * @param id * The ID whose hash code determines the bucket being retrieved. * * @return * The bucket corresponding to the hash code for the given ID, represented * by a guac_common_list. */ static guac_common_list* __guacd_proc_find_bucket(guacd_proc_map* map, const char* id) { const int index = __guacd_client_hash(id) % GUACD_PROC_MAP_BUCKETS; return map->__buckets[index]; } /** * Given a bucket of guacd_proc instances, returns the guacd_proc having the * guac_client with the given ID, or NULL if no such client is stored. * * @param bucket * The bucket of guacd_proc instances to search, represented as a * guac_common_list. * * @param id * The ID of the guac_client whose corresponding guacd_proc instance should * be located within the bucket. * * @return * The guac_common_list_element containing the guacd_proc instance * corresponding to the guac_client having the given ID, or NULL of no such * element exists. */ static guac_common_list_element* __guacd_proc_find(guac_common_list* bucket, const char* id) { guac_common_list_element* current = bucket->head; /* Search for matching element within bucket */ while (current != NULL) { /* Check connection ID */ guacd_proc* proc = (guacd_proc*) current->data; if (strcmp(proc->client->connection_id, id) == 0) break; current = current->next; } return current; } guacd_proc_map* guacd_proc_map_alloc() { guacd_proc_map* map = malloc(sizeof(guacd_proc_map)); guac_common_list** current; int i; /* Init all buckets */ current = map->__buckets; for (i=0; iclient->connection_id; guac_common_list* bucket = __guacd_proc_find_bucket(map, identifier); guac_common_list_element* found; /* Retrieve corresponding element, if any */ guac_common_list_lock(bucket); found = __guacd_proc_find(bucket, identifier); /* If no such element, we can add the new client successfully */ if (found == NULL) { guac_common_list_add(bucket, proc); guac_common_list_unlock(bucket); return 0; } /* Otherwise, fail - already exists */ guac_common_list_unlock(bucket); return 1; } guacd_proc* guacd_proc_map_retrieve(guacd_proc_map* map, const char* id) { guacd_proc* proc; guac_common_list* bucket = __guacd_proc_find_bucket(map, id); guac_common_list_element* found; /* Retrieve corresponding element, if any */ guac_common_list_lock(bucket); found = __guacd_proc_find(bucket, id); /* If no such element, fail */ if (found == NULL) { guac_common_list_unlock(bucket); return NULL; } proc = (guacd_proc*) found->data; guac_common_list_unlock(bucket); return proc; } guacd_proc* guacd_proc_map_remove(guacd_proc_map* map, const char* id) { guacd_proc* proc; guac_common_list* bucket = __guacd_proc_find_bucket(map, id); guac_common_list_element* found; /* Retrieve corresponding element, if any */ guac_common_list_lock(bucket); found = __guacd_proc_find(bucket, id); /* If no such element, fail */ if (found == NULL) { guac_common_list_unlock(bucket); return NULL; } proc = (guacd_proc*) found->data; guac_common_list_remove(bucket, found); guac_common_list_unlock(bucket); return proc; } guacamole-server-1.3.0/src/guacd/move-fd.c0000644000175100001440000000627213676434704015272 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "move-fd.h" /* Required for CMSG_* macros on BSD */ #define __BSD_VISIBLE 1 #include #include #include #include #include #include #include int guacd_send_fd(int sock, int fd) { struct msghdr message = {0}; char message_data[] = {'G'}; /* Assign data buffer */ struct iovec io_vector[1]; io_vector[0].iov_base = message_data; io_vector[0].iov_len = sizeof(message_data); message.msg_iov = io_vector; message.msg_iovlen = 1; /* Assign ancillary data buffer */ char buffer[CMSG_SPACE(sizeof(fd))] = {0}; message.msg_control = buffer; message.msg_controllen = sizeof(buffer); /* Set fields of control message header */ struct cmsghdr* control = CMSG_FIRSTHDR(&message); control->cmsg_level = SOL_SOCKET; control->cmsg_type = SCM_RIGHTS; control->cmsg_len = CMSG_LEN(sizeof(fd)); /* Add file descriptor to message data */ memcpy(CMSG_DATA(control), &fd, sizeof(fd)); /* Send file descriptor */ return (sendmsg(sock, &message, 0) == sizeof(message_data)); } int guacd_recv_fd(int sock) { int fd; struct msghdr message = {0}; char message_data[1]; /* Assign data buffer */ struct iovec io_vector[1]; io_vector[0].iov_base = message_data; io_vector[0].iov_len = sizeof(message_data); message.msg_iov = io_vector; message.msg_iovlen = 1; /* Assign ancillary data buffer */ char buffer[CMSG_SPACE(sizeof(fd))]; message.msg_control = buffer; message.msg_controllen = sizeof(buffer); /* Receive file descriptor */ if (recvmsg(sock, &message, 0) == sizeof(message_data)) { /* Validate payload */ if (message_data[0] != 'G') { errno = EPROTO; return -1; } /* Iterate control headers, looking for the sent file descriptor */ struct cmsghdr* control; for (control = CMSG_FIRSTHDR(&message); control != NULL; control = CMSG_NXTHDR(&message, control)) { /* Pull file descriptor from data */ if (control->cmsg_level == SOL_SOCKET && control->cmsg_type == SCM_RIGHTS) { memcpy(&fd, CMSG_DATA(control), sizeof(fd)); return fd; } } } /* end if recvmsg() success */ /* Failed to receive file descriptor */ return -1; } guacamole-server-1.3.0/src/guacd/Makefile.am0000644000175100001440000000501713702142276015607 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign sbin_PROGRAMS = guacd man_MANS = \ man/guacd.8 \ man/guacd.conf.5 noinst_HEADERS = \ conf.h \ conf-args.h \ conf-file.h \ conf-parse.h \ connection.h \ log.h \ move-fd.h \ proc.h \ proc-map.h guacd_SOURCES = \ conf-args.c \ conf-file.c \ conf-parse.c \ connection.c \ daemon.c \ log.c \ move-fd.c \ proc.c \ proc-map.c guacd_CFLAGS = \ -Werror -Wall -pedantic \ @COMMON_INCLUDE@ \ @LIBGUAC_INCLUDE@ guacd_LDADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ guacd_LDFLAGS = \ @PTHREAD_LIBS@ \ @SSL_LIBS@ EXTRA_DIST = \ init.d/guacd.in \ systemd/guacd.service.in \ man/guacd.8.in \ man/guacd.conf.5.in CLEANFILES = $(init_SCRIPTS) $(systemd_UNITS) # Init script if ENABLE_INIT initdir = @init_dir@ init_SCRIPTS = init.d/guacd init.d/guacd: init.d/guacd.in sed -e 's,[@]sbindir[@],$(sbindir),g' < init.d/guacd.in > init.d/guacd chmod +x init.d/guacd endif # Systemd service if ENABLE_SYSTEMD systemddir = @systemd_dir@ systemd_DATA = systemd/guacd.service systemd/guacd.service: systemd/guacd.service.in sed -e 's,[@]sbindir[@],$(sbindir),g' < systemd/guacd.service.in > systemd/guacd.service endif guacamole-server-1.3.0/src/guacd-docker/0000755000175100001440000000000013676721354015107 500000000000000guacamole-server-1.3.0/src/guacd-docker/bin/0000755000175100001440000000000013771167437015661 500000000000000guacamole-server-1.3.0/src/guacd-docker/bin/link-freerdp-plugins.sh0000755000175100001440000000507313771167437022206 00000000000000#!/bin/sh -e # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # ## ## @fn link-freerdp-plugins.sh ## ## Automatically creates any required symbolic links for the proper loading of ## the given FreeRDP plugins. If a given plugin is already in the correct ## directory, no link is created for that plugin. ## ## @param ... ## The FreeRDP plugins to add links for. ## ## ## Given the full path to a FreeRDP plugin, locates the base directory of the ## associated FreeRDP installation (where the FreeRDP library .so files are ## located), printing the result to STDOUT. If the directory cannot be ## determined, an error is printed. ## ## @param PLUGIN_FILE ## The full path to the FreeRDP plugin to check. ## where_is_freerdp() { PLUGIN_FILE="$1" # Determine the location of all libfreerdp* libraries explicitly linked # to given file PATHS="$(ldd "$PLUGIN_FILE" \ | awk '/=>/{print $(NF-1)}' \ | grep 'libfreerdp' \ | xargs -r dirname \ | xargs -r realpath \ | sort -u)" # Verify that exactly one location was found if [ "$(echo "$PATHS" | wc -l)" != 1 ]; then echo "$1: Unable to locate FreeRDP install location." >&2 return 1 fi echo "$PATHS" } # # Create symbolic links as necessary to include all given plugins within the # search path of FreeRDP # while [ -n "$1" ]; do # Determine correct install location for FreeRDP plugins FREERDP_DIR="$(where_is_freerdp "$1")" FREERDP_PLUGIN_DIR="${FREERDP_DIR}/freerdp2" # Add symbolic link if necessary if [ ! -e "$FREERDP_PLUGIN_DIR/$(basename "$1")" ]; then mkdir -p "$FREERDP_PLUGIN_DIR" ln -s "$1" "$FREERDP_PLUGIN_DIR" else echo "$1: Already in correct directory." >&2 fi shift done guacamole-server-1.3.0/src/guacd-docker/bin/build-guacd.sh0000755000175100001440000000303013770546371020311 00000000000000#!/bin/sh -e # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # ## ## @fn build-guacd.sh ## ## Builds the source of guacamole-server, automatically creating any required ## symbolic links for the proper loading of FreeRDP plugins. ## ## @param BUILD_DIR ## The directory which currently contains the guacamole-server source and ## in which the build should be performed. ## ## @param PREFIX_DIR ## The directory prefix into which the build artifacts should be installed ## in which the build should be performed. This is passed to the --prefix ## option of `configure`. ## BUILD_DIR="$1" PREFIX_DIR="$2" # # Build guacamole-server # cd "$BUILD_DIR" autoreconf -fi ./configure --prefix="$PREFIX_DIR" --disable-guaclog --with-freerdp-plugin-dir="$PREFIX_DIR/lib/freerdp2" make make install ldconfig guacamole-server-1.3.0/src/guacd-docker/bin/list-dependencies.sh0000755000175100001440000000273213771167437021543 00000000000000#!/bin/sh -e # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # ## ## @fn list-dependencies.sh ## ## Lists the Debian/Ubuntu package names for all library dependencies of the ## given binaries. Each package is only listed once, even if multiple binaries ## provided by the same package are given. ## ## @param ... ## The full paths to all binaries being checked. ## while [ -n "$1" ]; do # For all non-Guacamole library dependencies ldd "$1" | grep -v 'libguac' | awk '/=>/{print $(NF-1)}' \ | while read LIBRARY; do # Determine the Debian package which is associated with that # library, if any dpkg-query -S "$LIBRARY" 2> /dev/null || true done # Next binary shift done | cut -f1 -d: | sort -u guacamole-server-1.3.0/src/guacd-docker/README.md0000644000175100001440000000336413676721354016314 00000000000000What is guacd? ============== [guacd](https://github.com/apache/guacamole-server/) is the native server-side proxy used by the [Apache Guacamole web application](http://guacamole.apache.org/). If you wish to deploy Guacamole, or an application using the [Guacamole core APIs](http://guacamole.apache.org/api-documentation), you will need a copy of guacd running. How to use this image ===================== Running guacd for use by the [Guacamole Docker image](https://registry.hub.docker.com/u/guacamole/guacamole/) ----------------------------------------------------- docker run --name some-guacd -d guacamole/guacd guacd will be listening on port 4822, but this port will only be available to Docker containers that have been explicitly linked to `some-guacd`. Running guacd for use services by outside Docker ------------------------------------------------ docker run --name some-guacd -d -p 4822:4822 guacamole/guacd guacd will be listening on port 4822, and Docker will expose this port on the same server hosting Docker. Other services, such as an instance of Tomcat running outside of Docker, will be able to connect to guacd. Beware of the security ramifications of doing this. There is no authentication within guacd, so allowing access from untrusted applications is dangerous. If you need to expose guacd, ensure that you only expose it as absolutely necessary, and that only specific trusted applications have access. Connecting to guacd from an application --------------------------------------- docker run --name some-app --link some-guacd:guacd -d application-that-uses-guacd Reporting issues ================ Please report any bugs encountered by opening a new issue in [our JIRA](https://issues.apache.org/jira/browse/GUACAMOLE/). guacamole-server-1.3.0/src/pulse/0000755000175100001440000000000013772471157013707 500000000000000guacamole-server-1.3.0/src/pulse/pulse/0000755000175100001440000000000013772471157015037 500000000000000guacamole-server-1.3.0/src/pulse/pulse/pulse.h0000644000175100001440000000626513613156714016262 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_PULSE_H #define GUAC_PULSE_H #include "config.h" #include #include #include #include /** * The number of bytes to request for the audio fragments received from * PulseAudio. */ #define GUAC_PULSE_AUDIO_FRAGMENT_SIZE 8192 /** * The minimum number of PCM bytes to wait for before flushing an audio * packet. The current value is 48K, which works out to be around 280ms. */ #define GUAC_PULSE_PCM_WRITE_RATE 49152 /** * Rate of audio to stream, in Hz. */ #define GUAC_PULSE_AUDIO_RATE 44100 /** * The number of channels to stream. */ #define GUAC_PULSE_AUDIO_CHANNELS 2 /** * The number of bits per sample. */ #define GUAC_PULSE_AUDIO_BPS 16 /** * An audio stream which connects to a PulseAudio server and streams the * received audio through a guac_client. */ typedef struct guac_pa_stream { /** * The client associated with the audio stream. */ guac_client* client; /** * Audio output stream. */ guac_audio_stream* audio; /** * PulseAudio event loop. */ pa_threaded_mainloop* pa_mainloop; } guac_pa_stream; /** * Allocates a new PulseAudio audio stream for the given Guacamole client and * begins streaming. * * @param client * The client to stream audio to. * * @param server_name * The hostname of the PulseAudio server to connect to, or NULL to connect * to the default (local) server. * * @return * A newly-allocated PulseAudio stream, or NULL if audio cannot be * streamed. */ guac_pa_stream* guac_pa_stream_alloc(guac_client* client, const char* server_name); /** * Notifies the given PulseAudio stream that a user has joined the connection. * The audio stream itself may need to be restarted. and the audio stream will * need to be created for the new user to ensure they can properly handle * future data received along the stream. * * @param stream * The guac_pa_stream associated with the Guacamole connection being * joined. * * @param user * The user that has joined the Guacamole connection. */ void guac_pa_stream_add_user(guac_pa_stream* stream, guac_user* user); /** * Stops streaming audio from the given PulseAudio stream, freeing all * associated resources. * * @param stream * The PulseAudio stream to free. */ void guac_pa_stream_free(guac_pa_stream* stream); #endif guacamole-server-1.3.0/src/pulse/pulse.c0000644000175100001440000002516213613156714015122 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "pulse/pulse.h" #include #include #include #include /** * Returns whether the given buffer contains only silence (only null bytes). * * @param buffer * The audio buffer to check. * * @param length * The length of the buffer to check. * * @return * Non-zero if the audio buffer contains silence, zero otherwise. */ static int guac_pa_is_silence(const void* buffer, size_t length) { int i; const unsigned char* current = (const unsigned char*) buffer; /* For each byte in buffer */ for (i = 0; i < length; i++) { /* If current value non-zero, then not silence */ if (*(current++)) return 0; } /* Otherwise, the buffer contains 100% silence */ return 1; } /** * Callback invoked by PulseAudio when PCM data is available for reading * from the given stream. The PCM data can be read using pa_stream_peek(). * * @param stream * The PulseAudio stream which has PCM data available. * * @param length * The number of bytes of PCM data available on the given stream. * * @param data * A pointer to the guac_pa_stream structure associated with the Guacamole * stream receiving audio data from PulseAudio. */ static void __stream_read_callback(pa_stream* stream, size_t length, void* data) { guac_pa_stream* guac_stream = (guac_pa_stream*) data; guac_audio_stream* audio = guac_stream->audio; const void* buffer; /* Read data */ pa_stream_peek(stream, &buffer, &length); /* Continuously write received PCM data */ if (!guac_pa_is_silence(buffer, length)) guac_audio_stream_write_pcm(audio, buffer, length); /* Flush upon silence */ else guac_audio_stream_flush(audio); /* Advance buffer */ pa_stream_drop(stream); } /** * Callback invoked by PulseAudio when the audio stream has changed state. The * new state can be retrieved using pa_stream_get_state(). * * @param stream * The PulseAudio stream which has changed state. * * @param data * A pointer to the guac_pa_stream structure associated with the Guacamole * stream receiving audio data from PulseAudio. */ static void __stream_state_callback(pa_stream* stream, void* data) { guac_pa_stream* guac_stream = (guac_pa_stream*) data; guac_client* client = guac_stream->client; switch (pa_stream_get_state(stream)) { case PA_STREAM_UNCONNECTED: guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream currently unconnected"); break; case PA_STREAM_CREATING: guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream being created..."); break; case PA_STREAM_READY: guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream now ready"); break; case PA_STREAM_FAILED: guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream connection failed"); break; case PA_STREAM_TERMINATED: guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream terminated"); break; default: guac_client_log(client, GUAC_LOG_INFO, "Unknown PulseAudio stream state: 0x%x", pa_stream_get_state(stream)); } } /** * Callback invoked by PulseAudio when the audio sink information has been * retrieved. The callback is invoked repeatedly, once for each available * sink, followed by one final invocation with the is_last flag set. The final * invocation (with is_last set) does not describe a sink; it serves as a * terminator only. * * @param context * The PulseAudio context which is providing the sink information. * * @param info * Information describing an available audio sink. * * @param is_last * Non-zero if this invocation is the final invocation of this callback for * all currently-available sinks (and this invocation does not describe a * sink), zero otherwise. * * @param data * A pointer to the guac_pa_stream structure associated with the Guacamole * stream receiving audio data from PulseAudio. */ static void __context_get_sink_info_callback(pa_context* context, const pa_sink_info* info, int is_last, void* data) { guac_pa_stream* guac_stream = (guac_pa_stream*) data; guac_client* client = guac_stream->client; pa_stream* stream; pa_sample_spec spec; pa_buffer_attr attr; /* Stop if end of list reached */ if (is_last) return; guac_client_log(client, GUAC_LOG_INFO, "Starting streaming from \"%s\"", info->description); /* Set format */ spec.format = PA_SAMPLE_S16LE; spec.rate = GUAC_PULSE_AUDIO_RATE; spec.channels = GUAC_PULSE_AUDIO_CHANNELS; attr.maxlength = -1; attr.fragsize = GUAC_PULSE_AUDIO_FRAGMENT_SIZE; /* Create stream */ stream = pa_stream_new(context, "Guacamole Audio", &spec, NULL); /* Set stream callbacks */ pa_stream_set_state_callback(stream, __stream_state_callback, guac_stream); pa_stream_set_read_callback(stream, __stream_read_callback, guac_stream); /* Start stream */ pa_stream_connect_record(stream, info->monitor_source_name, &attr, PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND | PA_STREAM_ADJUST_LATENCY); } /** * Callback invoked by PulseAudio when server information has been retrieved. * * @param context * The PulseAudio context which is providing the sink information. * * @param info * Information describing the PulseAudio server. * * @param data * A pointer to the guac_pa_stream structure associated with the Guacamole * stream receiving audio data from PulseAudio. */ static void __context_get_server_info_callback(pa_context* context, const pa_server_info* info, void* data) { guac_pa_stream* guac_stream = (guac_pa_stream*) data; guac_client* client = guac_stream->client; /* If no default sink, cannot continue */ if (info->default_sink_name == NULL) { guac_client_log(client, GUAC_LOG_ERROR, "No default sink. Cannot stream audio."); return; } guac_client_log(client, GUAC_LOG_INFO, "Will use default sink: \"%s\"", info->default_sink_name); /* Wait for default sink information */ pa_operation_unref( pa_context_get_sink_info_by_name(context, info->default_sink_name, __context_get_sink_info_callback, guac_stream)); } /** * Callback invoked by PulseAudio when the overall audio context has changed * state. The new state can be retrieved using pa_context_get_state(). * * @param context * The PulseAudio context which has changed state. * * @param data * A pointer to the guac_pa_stream structure associated with the Guacamole * stream receiving audio data from PulseAudio. */ static void __context_state_callback(pa_context* context, void* data) { guac_pa_stream* guac_stream = (guac_pa_stream*) data; guac_client* client = guac_stream->client; switch (pa_context_get_state(context)) { case PA_CONTEXT_UNCONNECTED: guac_client_log(client, GUAC_LOG_INFO, "PulseAudio reports it is unconnected"); break; case PA_CONTEXT_CONNECTING: guac_client_log(client, GUAC_LOG_INFO, "Connecting to PulseAudio..."); break; case PA_CONTEXT_AUTHORIZING: guac_client_log(client, GUAC_LOG_INFO, "Authorizing PulseAudio connection..."); break; case PA_CONTEXT_SETTING_NAME: guac_client_log(client, GUAC_LOG_INFO, "Sending client name..."); break; case PA_CONTEXT_READY: guac_client_log(client, GUAC_LOG_INFO, "PulseAudio now ready"); pa_operation_unref(pa_context_get_server_info(context, __context_get_server_info_callback, guac_stream)); break; case PA_CONTEXT_FAILED: guac_client_log(client, GUAC_LOG_INFO, "PulseAudio connection failed"); break; case PA_CONTEXT_TERMINATED: guac_client_log(client, GUAC_LOG_INFO, "PulseAudio connection terminated"); break; default: guac_client_log(client, GUAC_LOG_INFO, "Unknown PulseAudio context state: 0x%x", pa_context_get_state(context)); } } guac_pa_stream* guac_pa_stream_alloc(guac_client* client, const char* server_name) { guac_audio_stream* audio = guac_audio_stream_alloc(client, NULL, GUAC_PULSE_AUDIO_RATE, GUAC_PULSE_AUDIO_CHANNELS, GUAC_PULSE_AUDIO_BPS); /* Abort if audio stream cannot be created */ if (audio == NULL) return NULL; /* Init main loop */ guac_pa_stream* stream = malloc(sizeof(guac_pa_stream)); stream->client = client; stream->audio = audio; stream->pa_mainloop = pa_threaded_mainloop_new(); /* Create context */ pa_context* context = pa_context_new( pa_threaded_mainloop_get_api(stream->pa_mainloop), "Guacamole Audio"); /* Set up context */ pa_context_set_state_callback(context, __context_state_callback, stream); pa_context_connect(context, server_name, PA_CONTEXT_NOAUTOSPAWN, NULL); /* Start loop */ pa_threaded_mainloop_start(stream->pa_mainloop); return stream; } void guac_pa_stream_add_user(guac_pa_stream* stream, guac_user* user) { guac_audio_stream_add_user(stream->audio, user); } void guac_pa_stream_free(guac_pa_stream* stream) { /* Stop loop */ pa_threaded_mainloop_stop(stream->pa_mainloop); /* Free underlying audio stream */ guac_audio_stream_free(stream->audio); /* Stream now ended */ guac_client_log(stream->client, GUAC_LOG_INFO, "Audio stream finished"); free(stream); } guacamole-server-1.3.0/src/pulse/Makefile.in0000644000175100001440000005360313772471103015672 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/pulse ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libguac_pulse_la_DEPENDENCIES = am_libguac_pulse_la_OBJECTS = libguac_pulse_la-pulse.lo libguac_pulse_la_OBJECTS = $(am_libguac_pulse_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libguac_pulse_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libguac_pulse_la_CFLAGS) $(CFLAGS) \ $(libguac_pulse_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libguac_pulse_la-pulse.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libguac_pulse_la_SOURCES) DIST_SOURCES = $(libguac_pulse_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 noinst_LTLIBRARIES = libguac_pulse.la noinst_HEADERS = \ pulse/pulse.h libguac_pulse_la_SOURCES = \ pulse.c libguac_pulse_la_CFLAGS = \ -Werror -Wall -pedantic \ @LIBGUAC_INCLUDE@ libguac_pulse_la_LIBADD = \ @LIBGUAC_LTLIB@ libguac_pulse_la_LDFLAGS = \ @PULSE_LIBS@ all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/pulse/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/pulse/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libguac_pulse.la: $(libguac_pulse_la_OBJECTS) $(libguac_pulse_la_DEPENDENCIES) $(EXTRA_libguac_pulse_la_DEPENDENCIES) $(AM_V_CCLD)$(libguac_pulse_la_LINK) $(libguac_pulse_la_OBJECTS) $(libguac_pulse_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_pulse_la-pulse.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libguac_pulse_la-pulse.lo: pulse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_pulse_la_CFLAGS) $(CFLAGS) -MT libguac_pulse_la-pulse.lo -MD -MP -MF $(DEPDIR)/libguac_pulse_la-pulse.Tpo -c -o libguac_pulse_la-pulse.lo `test -f 'pulse.c' || echo '$(srcdir)/'`pulse.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_pulse_la-pulse.Tpo $(DEPDIR)/libguac_pulse_la-pulse.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pulse.c' object='libguac_pulse_la-pulse.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_pulse_la_CFLAGS) $(CFLAGS) -c -o libguac_pulse_la-pulse.lo `test -f 'pulse.c' || echo '$(srcdir)/'`pulse.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libguac_pulse_la-pulse.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libguac_pulse_la-pulse.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/pulse/Makefile.am0000644000175100001440000000301313702142276015646 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 noinst_LTLIBRARIES = libguac_pulse.la noinst_HEADERS = \ pulse/pulse.h libguac_pulse_la_SOURCES = \ pulse.c libguac_pulse_la_CFLAGS = \ -Werror -Wall -pedantic \ @LIBGUAC_INCLUDE@ libguac_pulse_la_LIBADD = \ @LIBGUAC_LTLIB@ libguac_pulse_la_LDFLAGS = \ @PULSE_LIBS@ guacamole-server-1.3.0/src/protocols/0000755000175100001440000000000013772471161014576 500000000000000guacamole-server-1.3.0/src/protocols/vnc/0000755000175100001440000000000013772471161015364 500000000000000guacamole-server-1.3.0/src/protocols/vnc/clipboard.c0000644000175100001440000001137313764613616017420 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "client.h" #include "clipboard.h" #include "common/clipboard.h" #include "common/iconv.h" #include "user.h" #include "vnc.h" #include #include #include #include #include int guac_vnc_set_clipboard_encoding(guac_client* client, const char* name) { guac_vnc_client* vnc_client = (guac_vnc_client*) client->data; /* Use ISO8859-1 if explicitly selected or NULL */ if (name == NULL || strcmp(name, "ISO8859-1") == 0) { vnc_client->clipboard_reader = GUAC_READ_ISO8859_1; vnc_client->clipboard_writer = GUAC_WRITE_ISO8859_1; return 0; } /* UTF-8 */ if (strcmp(name, "UTF-8") == 0) { vnc_client->clipboard_reader = GUAC_READ_UTF8; vnc_client->clipboard_writer = GUAC_WRITE_UTF8; return 1; } /* UTF-16 */ if (strcmp(name, "UTF-16") == 0) { vnc_client->clipboard_reader = GUAC_READ_UTF16; vnc_client->clipboard_writer = GUAC_WRITE_UTF16; return 1; } /* CP1252 */ if (strcmp(name, "CP1252") == 0) { vnc_client->clipboard_reader = GUAC_READ_CP1252; vnc_client->clipboard_writer = GUAC_WRITE_CP1252; return 1; } /* If encoding unrecognized, warn and default to ISO8859-1 */ guac_client_log(client, GUAC_LOG_WARNING, "Encoding '%s' is invalid. Defaulting to ISO8859-1.", name); vnc_client->clipboard_reader = GUAC_READ_ISO8859_1; vnc_client->clipboard_writer = GUAC_WRITE_ISO8859_1; return 0; } int guac_vnc_clipboard_handler(guac_user* user, guac_stream* stream, char* mimetype) { /* Clear clipboard and prepare for new data */ guac_vnc_client* vnc_client = (guac_vnc_client*) user->client->data; guac_common_clipboard_reset(vnc_client->clipboard, mimetype); /* Set handlers for clipboard stream */ stream->blob_handler = guac_vnc_clipboard_blob_handler; stream->end_handler = guac_vnc_clipboard_end_handler; return 0; } int guac_vnc_clipboard_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { /* Append new data */ guac_vnc_client* vnc_client = (guac_vnc_client*) user->client->data; guac_common_clipboard_append(vnc_client->clipboard, (char*) data, length); return 0; } int guac_vnc_clipboard_end_handler(guac_user* user, guac_stream* stream) { guac_vnc_client* vnc_client = (guac_vnc_client*) user->client->data; rfbClient* rfb_client = vnc_client->rfb_client; char output_data[GUAC_VNC_CLIPBOARD_MAX_LENGTH]; const char* input = vnc_client->clipboard->buffer; char* output = output_data; guac_iconv_write* writer = vnc_client->clipboard_writer; /* Convert clipboard contents */ guac_iconv(GUAC_READ_UTF8, &input, vnc_client->clipboard->length, writer, &output, sizeof(output_data)); /* Send via VNC only if finished connecting */ if (rfb_client != NULL) SendClientCutText(rfb_client, output_data, output - output_data); return 0; } void guac_vnc_cut_text(rfbClient* client, const char* text, int textlen) { guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY); guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data; /* Ignore received text if outbound clipboard transfer is disabled */ if (vnc_client->settings->disable_copy) return; char received_data[GUAC_VNC_CLIPBOARD_MAX_LENGTH]; const char* input = text; char* output = received_data; guac_iconv_read* reader = vnc_client->clipboard_reader; /* Convert clipboard contents */ guac_iconv(reader, &input, textlen, GUAC_WRITE_UTF8, &output, sizeof(received_data)); /* Send converted data */ guac_common_clipboard_reset(vnc_client->clipboard, "text/plain"); guac_common_clipboard_append(vnc_client->clipboard, received_data, output - received_data); guac_common_clipboard_send(vnc_client->clipboard, gc); } guacamole-server-1.3.0/src/protocols/vnc/cursor.h0000644000175100001440000000371413726006252016771 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_VNC_CURSOR_H #define GUAC_VNC_CURSOR_H #include "config.h" #include #include /** * Callback invoked by libVNCServer when it receives a new cursor image from * the VNC server. The cursor image itself will be split across * client->rcSource and client->rcMask, where rcSource is an image buffer of * the format natively used by the current VNC connection, and rcMask is an * array if bitmasks. Each bit within rcMask corresponds to a pixel within * rcSource, where a 0 denotes full transparency and a 1 denotes full opacity. * * @param client * The VNC client associated with the VNC session in which the new cursor * image was received. * * @param x * The X coordinate of the new cursor image's hotspot, in pixels. * * @param y * The Y coordinate of the new cursor image's hotspot, in pixels. * * @param w * The width of the cursor image, in pixels. * * @param h * The height of the cursor image, in pixels. * * @param bpp * The number of bytes in each pixel, which must be either 4, 2, or 1. */ void guac_vnc_cursor(rfbClient* client, int x, int y, int w, int h, int bpp); #endif guacamole-server-1.3.0/src/protocols/vnc/argv.c0000644000175100001440000000317513770536337016422 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "vnc.h" #include #include #include #include #include #include int guac_vnc_argv_callback(guac_user* user, const char* mimetype, const char* name, const char* value, void* data) { guac_client* client = user->client; guac_vnc_client* vnc_client = (guac_vnc_client*) client->data; guac_vnc_settings* settings = vnc_client->settings; /* Update username */ if (strcmp(name, GUAC_VNC_ARGV_USERNAME) == 0) { free(settings->username); settings->username = strdup(value); } /* Update password */ else if (strcmp(name, GUAC_VNC_ARGV_PASSWORD) == 0) { free(settings->password); settings->password = strdup(value); } return 0; }guacamole-server-1.3.0/src/protocols/vnc/input.h0000644000175100001440000000214513613156714016614 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_VNC_INPUT_H #define GUAC_VNC_INPUT_H #include "config.h" #include /** * Handler for Guacamole user mouse events. */ guac_user_mouse_handler guac_vnc_user_mouse_handler; /** * Handler for Guacamole user key events. */ guac_user_key_handler guac_vnc_user_key_handler; #endif guacamole-server-1.3.0/src/protocols/vnc/display.c0000644000175100001440000001471113726006252017113 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "client.h" #include "common/iconv.h" #include "common/surface.h" #include "vnc.h" #include #include #include #include #include #include #include /* Define cairo_format_stride_for_width() if missing */ #ifndef HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH #define cairo_format_stride_for_width(format, width) (width*4) #endif #include #include #include #include #include void guac_vnc_update(rfbClient* client, int x, int y, int w, int h) { guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY); guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data; int dx, dy; /* Cairo image buffer */ int stride; unsigned char* buffer; unsigned char* buffer_row_current; cairo_surface_t* surface; /* VNC framebuffer */ unsigned int bpp; unsigned int fb_stride; unsigned char* fb_row_current; /* Ignore extra update if already handled by copyrect */ if (vnc_client->copy_rect_used) { vnc_client->copy_rect_used = 0; return; } /* Init Cairo buffer */ stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w); buffer = malloc(h*stride); buffer_row_current = buffer; bpp = client->format.bitsPerPixel/8; fb_stride = bpp * client->width; fb_row_current = client->frameBuffer + (y * fb_stride) + (x * bpp); /* Copy image data from VNC client to PNG */ for (dy = y; dy> client->format.redShift) * 0x100 / (client->format.redMax + 1); green = (v >> client->format.greenShift) * 0x100 / (client->format.greenMax+ 1); blue = (v >> client->format.blueShift) * 0x100 / (client->format.blueMax + 1); /* Output RGB */ if (vnc_client->settings->swap_red_blue) *(buffer_current++) = (blue << 16) | (green << 8) | red; else *(buffer_current++) = (red << 16) | (green << 8) | blue; fb_current += bpp; } } /* Create surface from decoded buffer */ surface = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_RGB24, w, h, stride); /* Draw directly to default layer */ guac_common_surface_draw(vnc_client->display->default_surface, x, y, surface); /* Free surface */ cairo_surface_destroy(surface); free(buffer); } void guac_vnc_copyrect(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) { guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY); guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data; /* Copy specified rectangle within default layer */ guac_common_surface_copy(vnc_client->display->default_surface, src_x, src_y, w, h, vnc_client->display->default_surface, dest_x, dest_y); vnc_client->copy_rect_used = 1; } void guac_vnc_set_pixel_format(rfbClient* client, int color_depth) { client->format.trueColour = 1; switch(color_depth) { case 8: client->format.depth = 8; client->format.bitsPerPixel = 8; client->format.blueShift = 6; client->format.redShift = 0; client->format.greenShift = 3; client->format.blueMax = 3; client->format.redMax = 7; client->format.greenMax = 7; break; case 16: client->format.depth = 16; client->format.bitsPerPixel = 16; client->format.blueShift = 0; client->format.redShift = 11; client->format.greenShift = 5; client->format.blueMax = 0x1f; client->format.redMax = 0x1f; client->format.greenMax = 0x3f; break; case 24: case 32: default: client->format.depth = 24; client->format.bitsPerPixel = 32; client->format.blueShift = 0; client->format.redShift = 16; client->format.greenShift = 8; client->format.blueMax = 0xff; client->format.redMax = 0xff; client->format.greenMax = 0xff; } } rfbBool guac_vnc_malloc_framebuffer(rfbClient* rfb_client) { guac_client* gc = rfbClientGetClientData(rfb_client, GUAC_VNC_CLIENT_KEY); guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data; /* Resize surface */ if (vnc_client->display != NULL) guac_common_surface_resize(vnc_client->display->default_surface, rfb_client->width, rfb_client->height); /* Use original, wrapped proc */ return vnc_client->rfb_MallocFrameBuffer(rfb_client); } guacamole-server-1.3.0/src/protocols/vnc/user.h0000644000175100001440000000211213613156714016425 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_VNC_USER_H #define GUAC_VNC_USER_H #include "config.h" #include /** * Handler for joining users. */ guac_user_join_handler guac_vnc_user_join_handler; /** * Handler for leaving users. */ guac_user_leave_handler guac_vnc_user_leave_handler; #endif guacamole-server-1.3.0/src/protocols/vnc/log.h0000644000175100001440000000354613726006252016240 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_VNC_LOG_H #define GUAC_VNC_LOG_H #include "config.h" #include "client.h" #include "common/iconv.h" #include "common/surface.h" #include #include #include #include #include #include #include #include #include #include #include /** * Callback invoked by libVNCServer when an informational message needs to be * logged. * * @param format * A printf-style format string to log. * * @param ... * The values to use when filling the conversion specifiers within the * format string. */ void guac_vnc_client_log_info(const char* format, ...); /** * Callback invoked by libVNCServer when an error message needs to be logged. * * @param format * A printf-style format string to log. * * @param ... * The values to use when filling the conversion specifiers within the * format string. */ void guac_vnc_client_log_error(const char* format, ...); #endif guacamole-server-1.3.0/src/protocols/vnc/sftp.h0000644000175100001440000000213413613156714016427 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_VNC_SFTP_H #define GUAC_VNC_SFTP_H #include "config.h" #include /** * Handles an incoming stream from a Guacamole "file" instruction, saving the * contents of that stream to the file having the given name. */ guac_user_file_handler guac_vnc_sftp_file_handler; #endif guacamole-server-1.3.0/src/protocols/vnc/auth.h0000644000175100001440000000374313770226763016431 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_VNC_AUTH_H #define GUAC_VNC_AUTH_H #include "config.h" #include #include /** * Callback which is invoked by libVNCServer when it needs to read the user's * VNC password. As this user's password, if any, will be stored in the * connection settings, this function does nothing more than return that value. * * @param client * The rfbClient associated with the VNC connection requiring the password. * * @return * The password to provide to the VNC server. */ char* guac_vnc_get_password(rfbClient* client); /** * Callback which is invoked by libVNCServer when it needs to read the user's * VNC credentials. The credentials are stored in the connection settings, * so they will be retrieved from that. * * @param client * The rfbClient associated with the VNC connection requiring the * authentication. * * @param credentialType * The credential type being requested, as defined by the libVNCclient * code in the rfbclient.h header. * * @return * The rfbCredential object that contains the required credentials. */ rfbCredential* guac_vnc_get_credentials(rfbClient* client, int credentialType); #endif guacamole-server-1.3.0/src/protocols/vnc/auth.c0000644000175100001440000001016313770536337016417 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "auth.h" #include "vnc.h" #include #include #include #include #include #include #include #include #include char* guac_vnc_get_password(rfbClient* client) { guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY); guac_vnc_client* vnc_client = ((guac_vnc_client*) gc->data); guac_vnc_settings* settings = vnc_client->settings; /* If the client does not support the "required" instruction, just return the configuration data. */ if (!guac_client_owner_supports_required(gc)) return guac_strdup(settings->password); /* If password isn't around, prompt for it. */ if (settings->password == NULL) { guac_argv_register(GUAC_VNC_ARGV_PASSWORD, guac_vnc_argv_callback, NULL, 0); const char* params[] = {GUAC_VNC_ARGV_PASSWORD, NULL}; /* Send the request for password to the owner. */ guac_client_owner_send_required(gc, params); /* Wait for the arguments to be returned */ guac_argv_await(params); } return guac_strdup(settings->password); } rfbCredential* guac_vnc_get_credentials(rfbClient* client, int credentialType) { guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY); guac_vnc_client* vnc_client = ((guac_vnc_client*) gc->data); guac_vnc_settings* settings = vnc_client->settings; /* Handle request for Username/Password credentials */ if (credentialType == rfbCredentialTypeUser) { rfbCredential *creds = malloc(sizeof(rfbCredential)); /* If the client supports the "required" instruction, prompt for and update those. */ if (guac_client_owner_supports_required(gc)) { char* params[3] = {NULL}; int i = 0; /* Check if username is not provided. */ if (settings->username == NULL) { guac_argv_register(GUAC_VNC_ARGV_USERNAME, guac_vnc_argv_callback, NULL, 0); params[i] = GUAC_VNC_ARGV_USERNAME; i++; } /* Check if password is not provided. */ if (settings->password == NULL) { guac_argv_register(GUAC_VNC_ARGV_PASSWORD, guac_vnc_argv_callback, NULL, 0); params[i] = GUAC_VNC_ARGV_PASSWORD; i++; } params[i] = NULL; /* If we have empty parameters, request them and await response. */ if (i > 0) { guac_client_owner_send_required(gc, (const char**) params); guac_argv_await((const char**) params); } } /* Copy the values and return the credential set. */ creds->userCredential.username = guac_strdup(settings->username); creds->userCredential.password = guac_strdup(settings->password); return creds; } guac_client_abort(gc, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unsupported credential type requested."); guac_client_log(gc, GUAC_LOG_DEBUG, "Unable to provide requested type of credential: %d.", credentialType); return NULL; } guacamole-server-1.3.0/src/protocols/vnc/vnc.h0000644000175100001440000000772113764613616016256 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_VNC_VNC_H #define GUAC_VNC_VNC_H #include "config.h" #include "common/clipboard.h" #include "common/display.h" #include "common/iconv.h" #include "common/recording.h" #include "common/surface.h" #include "settings.h" #include #include #include #ifdef ENABLE_PULSE #include "pulse/pulse.h" #endif #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" #include "common-ssh/ssh.h" #include "common-ssh/user.h" #endif #include /** * VNC-specific client data. */ typedef struct guac_vnc_client { /** * The VNC client thread. */ pthread_t client_thread; #ifdef ENABLE_VNC_TLS_LOCKING /** * The TLS mutex lock for the client. */ pthread_mutex_t tls_lock; #endif /** * The underlying VNC client. */ rfbClient* rfb_client; /** * The original framebuffer malloc procedure provided by the initialized * rfbClient. */ MallocFrameBufferProc rfb_MallocFrameBuffer; /** * Whether copyrect was used to produce the latest update received * by the VNC server. */ int copy_rect_used; /** * Client settings, parsed from args. */ guac_vnc_settings* settings; /** * The current display state. */ guac_common_display* display; /** * Internal clipboard. */ guac_common_clipboard* clipboard; #ifdef ENABLE_PULSE /** * PulseAudio output, if any. */ guac_pa_stream* audio; #endif #ifdef ENABLE_COMMON_SSH /** * The user and credentials used to authenticate for SFTP. */ guac_common_ssh_user* sftp_user; /** * The SSH session used for SFTP. */ guac_common_ssh_session* sftp_session; /** * An SFTP-based filesystem. */ guac_common_ssh_sftp_filesystem* sftp_filesystem; #endif /** * The in-progress session recording, or NULL if no recording is in * progress. */ guac_common_recording* recording; /** * Clipboard encoding-specific reader. */ guac_iconv_read* clipboard_reader; /** * Clipboard encoding-specific writer. */ guac_iconv_write* clipboard_writer; } guac_vnc_client; /** * Allocates a new rfbClient instance given the parameters stored within the * client, returning NULL on failure. * * @param client * The guac_client associated with the settings of the desired VNC * connection. * * @return * A new rfbClient instance allocated and connected according to the * parameters stored within the given client, or NULL if connecting to the * VNC server fails. */ rfbClient* guac_vnc_get_client(guac_client* client); /** * VNC client thread. This thread initiates the VNC connection and ultimately * runs throughout the duration of the client, existing as a single instance, * shared by all users. * * @param data * The guac_client instance associated with the requested VNC connection. * * @return * Always NULL. */ void* guac_vnc_client_thread(void* data); /** * Key which can be used with the rfbClientGetClientData function to return * the associated guac_client. */ extern char* GUAC_VNC_CLIENT_KEY; #endif guacamole-server-1.3.0/src/protocols/vnc/log.c0000644000175100001440000000340713726006252016227 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "client.h" #include "common/iconv.h" #include "common/surface.h" #include #include #include #include #include #include #include #include #include #include #include void guac_vnc_client_log_info(const char* format, ...) { char message[2048]; /* Copy log message into buffer */ va_list args; va_start(args, format); vsnprintf(message, sizeof(message), format, args); va_end(args); /* Log to syslog */ syslog(LOG_INFO, "%s", message); } void guac_vnc_client_log_error(const char* format, ...) { char message[2048]; /* Copy log message into buffer */ va_list args; va_start(args, format); vsnprintf(message, sizeof(message), format, args); va_end(args); /* Log to syslog */ syslog(LOG_ERR, "%s", message); } guacamole-server-1.3.0/src/protocols/vnc/argv.h0000644000175100001440000000261713770536337016427 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef ARGV_H #define ARGV_H #include "config.h" #include #include /** * Handles a received argument value from a Guacamole "argv" instruction, * updating the given connection parameter. */ guac_argv_callback guac_vnc_argv_callback; /** * The name of the parameter Guacamole will use to specify/update the username * for the VNC connection. */ #define GUAC_VNC_ARGV_USERNAME "username" /** * The name of the parameter Guacamole will use to specify/update the password * for the VNC connection. */ #define GUAC_VNC_ARGV_PASSWORD "password" #endif /* ARGV_H */ guacamole-server-1.3.0/src/protocols/vnc/user.c0000644000175100001440000000762513770536337016445 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "clipboard.h" #include "input.h" #include "common/display.h" #include "common/dot_cursor.h" #include "common/pointer_cursor.h" #include "user.h" #include "sftp.h" #include "vnc.h" #ifdef ENABLE_PULSE #include "pulse/pulse.h" #endif #include #include #include #include #include #include #include #include int guac_vnc_user_join_handler(guac_user* user, int argc, char** argv) { guac_vnc_client* vnc_client = (guac_vnc_client*) user->client->data; /* Parse provided arguments */ guac_vnc_settings* settings = guac_vnc_parse_args(user, argc, (const char**) argv); /* Fail if settings cannot be parsed */ if (settings == NULL) { guac_user_log(user, GUAC_LOG_INFO, "Badly formatted client arguments."); return 1; } /* Store settings at user level */ user->data = settings; /* Connect via VNC if owner */ if (user->owner) { /* Store owner's settings at client level */ vnc_client->settings = settings; /* Start client thread */ if (pthread_create(&vnc_client->client_thread, NULL, guac_vnc_client_thread, user->client)) { guac_user_log(user, GUAC_LOG_ERROR, "Unable to start VNC client thread."); return 1; } } /* If not owner, synchronize with current state */ else { #ifdef ENABLE_PULSE /* Synchronize an audio stream */ if (vnc_client->audio) guac_pa_stream_add_user(vnc_client->audio, user); #endif /* Synchronize with current display */ guac_common_display_dup(vnc_client->display, user, user->socket); guac_socket_flush(user->socket); } /* Only handle events if not read-only */ if (!settings->read_only) { /* General mouse/keyboard events */ user->mouse_handler = guac_vnc_user_mouse_handler; user->key_handler = guac_vnc_user_key_handler; /* Inbound (client to server) clipboard transfer */ if (!settings->disable_paste) user->clipboard_handler = guac_vnc_clipboard_handler; /* Updates to connection parameters if we own the connection */ if (user->owner) user->argv_handler = guac_argv_handler; #ifdef ENABLE_COMMON_SSH /* Set generic (non-filesystem) file upload handler */ if (settings->enable_sftp && !settings->sftp_disable_upload) user->file_handler = guac_vnc_sftp_file_handler; #endif } return 0; } int guac_vnc_user_leave_handler(guac_user* user) { guac_vnc_client* vnc_client = (guac_vnc_client*) user->client->data; if (vnc_client->display) { /* Update shared cursor state */ guac_common_cursor_remove_user(vnc_client->display->cursor, user); } /* Free settings if not owner (owner settings will be freed with client) */ if (!user->owner) { guac_vnc_settings* settings = (guac_vnc_settings*) user->data; guac_vnc_settings_free(settings); } return 0; } guacamole-server-1.3.0/src/protocols/vnc/input.c0000644000175100001440000000422713726006252016606 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/cursor.h" #include "common/display.h" #include "common/recording.h" #include "vnc.h" #include #include int guac_vnc_user_mouse_handler(guac_user* user, int x, int y, int mask) { guac_client* client = user->client; guac_vnc_client* vnc_client = (guac_vnc_client*) client->data; rfbClient* rfb_client = vnc_client->rfb_client; /* Store current mouse location/state */ guac_common_cursor_update(vnc_client->display->cursor, user, x, y, mask); /* Report mouse position within recording */ if (vnc_client->recording != NULL) guac_common_recording_report_mouse(vnc_client->recording, x, y, mask); /* Send VNC event only if finished connecting */ if (rfb_client != NULL) SendPointerEvent(rfb_client, x, y, mask); return 0; } int guac_vnc_user_key_handler(guac_user* user, int keysym, int pressed) { guac_vnc_client* vnc_client = (guac_vnc_client*) user->client->data; rfbClient* rfb_client = vnc_client->rfb_client; /* Report key state within recording */ if (vnc_client->recording != NULL) guac_common_recording_report_key(vnc_client->recording, keysym, pressed); /* Send VNC event only if finished connecting */ if (rfb_client != NULL) SendKeyEvent(rfb_client, keysym, pressed); return 0; } guacamole-server-1.3.0/src/protocols/vnc/clipboard.h0000644000175100001440000000463013726006252017411 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_VNC_CLIPBOARD_H #define _GUAC_VNC_CLIPBOARD_H #include "config.h" #include #include #include /** * Sets the encoding of clipboard data exchanged with the VNC server to the * encoding having the given name. If the name is NULL, or is invalid, the * standard ISO8859-1 encoding will be used. * * @param client * The client to set the clipboard encoding of. * * @param name * The name of the encoding to use for all clipboard data. Valid values * are: "ISO8859-1", "UTF-8", "UTF-16", "CP1252", or NULL. * * @return * Zero if the chosen encoding is standard for VNC, or non-zero if the VNC * standard is being violated. */ int guac_vnc_set_clipboard_encoding(guac_client* client, const char* name); /** * Handler for inbound clipboard data from Guacamole users. */ guac_user_clipboard_handler guac_vnc_clipboard_handler; /** * Handler for stream data related to clipboard. */ guac_user_blob_handler guac_vnc_clipboard_blob_handler; /** * Handler for end-of-stream related to clipboard. */ guac_user_end_handler guac_vnc_clipboard_end_handler; /** * Handler for clipboard data received via VNC, invoked by libVNCServer * whenever text has been copied or cut within the VNC session. * * @param client * The VNC client associated with the session in which the user cut or * copied text. * * @param text * The string of cut/copied text. * * @param textlen * The number of bytes in the string of cut/copied text. */ void guac_vnc_cut_text(rfbClient* client, const char* text, int textlen); #endif guacamole-server-1.3.0/src/protocols/vnc/Makefile.in0000644000175100001440000012132713772471103017353 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ # Optional SFTP support @ENABLE_COMMON_SSH_TRUE@am__append_1 = sftp.c @ENABLE_COMMON_SSH_TRUE@am__append_2 = sftp.h @ENABLE_COMMON_SSH_TRUE@am__append_3 = @COMMON_SSH_LTLIB@ # Optional PulseAudio support @ENABLE_PULSE_TRUE@am__append_4 = @PULSE_LTLIB@ subdir = src/protocols/vnc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__noinst_HEADERS_DIST) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libguac_client_vnc_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am__libguac_client_vnc_la_SOURCES_DIST = argv.c auth.c client.c \ clipboard.c cursor.c display.c input.c log.c settings.c user.c \ vnc.c sftp.c @ENABLE_COMMON_SSH_TRUE@am__objects_1 = libguac_client_vnc_la-sftp.lo am_libguac_client_vnc_la_OBJECTS = libguac_client_vnc_la-argv.lo \ libguac_client_vnc_la-auth.lo libguac_client_vnc_la-client.lo \ libguac_client_vnc_la-clipboard.lo \ libguac_client_vnc_la-cursor.lo \ libguac_client_vnc_la-display.lo \ libguac_client_vnc_la-input.lo libguac_client_vnc_la-log.lo \ libguac_client_vnc_la-settings.lo \ libguac_client_vnc_la-user.lo libguac_client_vnc_la-vnc.lo \ $(am__objects_1) libguac_client_vnc_la_OBJECTS = $(am_libguac_client_vnc_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libguac_client_vnc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) \ $(libguac_client_vnc_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libguac_client_vnc_la-argv.Plo \ ./$(DEPDIR)/libguac_client_vnc_la-auth.Plo \ ./$(DEPDIR)/libguac_client_vnc_la-client.Plo \ ./$(DEPDIR)/libguac_client_vnc_la-clipboard.Plo \ ./$(DEPDIR)/libguac_client_vnc_la-cursor.Plo \ ./$(DEPDIR)/libguac_client_vnc_la-display.Plo \ ./$(DEPDIR)/libguac_client_vnc_la-input.Plo \ ./$(DEPDIR)/libguac_client_vnc_la-log.Plo \ ./$(DEPDIR)/libguac_client_vnc_la-settings.Plo \ ./$(DEPDIR)/libguac_client_vnc_la-sftp.Plo \ ./$(DEPDIR)/libguac_client_vnc_la-user.Plo \ ./$(DEPDIR)/libguac_client_vnc_la-vnc.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libguac_client_vnc_la_SOURCES) DIST_SOURCES = $(am__libguac_client_vnc_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__noinst_HEADERS_DIST = argv.h auth.h client.h clipboard.h cursor.h \ display.h input.h log.h settings.h user.h vnc.h sftp.h HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac-client-vnc.la libguac_client_vnc_la_SOURCES = argv.c auth.c client.c clipboard.c \ cursor.c display.c input.c log.c settings.c user.c vnc.c \ $(am__append_1) noinst_HEADERS = argv.h auth.h client.h clipboard.h cursor.h display.h \ input.h log.h settings.h user.h vnc.h $(am__append_2) libguac_client_vnc_la_CFLAGS = \ -Werror -Wall -pedantic -Iinclude \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ \ @PULSE_INCLUDE@ libguac_client_vnc_la_LDFLAGS = \ -version-info 0:0:0 \ @CAIRO_LIBS@ \ @VNC_LIBS@ libguac_client_vnc_la_LIBADD = @COMMON_LTLIB@ @LIBGUAC_LTLIB@ \ $(am__append_3) $(am__append_4) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/protocols/vnc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/protocols/vnc/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libguac-client-vnc.la: $(libguac_client_vnc_la_OBJECTS) $(libguac_client_vnc_la_DEPENDENCIES) $(EXTRA_libguac_client_vnc_la_DEPENDENCIES) $(AM_V_CCLD)$(libguac_client_vnc_la_LINK) -rpath $(libdir) $(libguac_client_vnc_la_OBJECTS) $(libguac_client_vnc_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_vnc_la-argv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_vnc_la-auth.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_vnc_la-client.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_vnc_la-clipboard.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_vnc_la-cursor.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_vnc_la-display.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_vnc_la-input.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_vnc_la-log.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_vnc_la-settings.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_vnc_la-sftp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_vnc_la-user.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_vnc_la-vnc.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libguac_client_vnc_la-argv.lo: argv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -MT libguac_client_vnc_la-argv.lo -MD -MP -MF $(DEPDIR)/libguac_client_vnc_la-argv.Tpo -c -o libguac_client_vnc_la-argv.lo `test -f 'argv.c' || echo '$(srcdir)/'`argv.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_vnc_la-argv.Tpo $(DEPDIR)/libguac_client_vnc_la-argv.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='argv.c' object='libguac_client_vnc_la-argv.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -c -o libguac_client_vnc_la-argv.lo `test -f 'argv.c' || echo '$(srcdir)/'`argv.c libguac_client_vnc_la-auth.lo: auth.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -MT libguac_client_vnc_la-auth.lo -MD -MP -MF $(DEPDIR)/libguac_client_vnc_la-auth.Tpo -c -o libguac_client_vnc_la-auth.lo `test -f 'auth.c' || echo '$(srcdir)/'`auth.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_vnc_la-auth.Tpo $(DEPDIR)/libguac_client_vnc_la-auth.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='auth.c' object='libguac_client_vnc_la-auth.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -c -o libguac_client_vnc_la-auth.lo `test -f 'auth.c' || echo '$(srcdir)/'`auth.c libguac_client_vnc_la-client.lo: client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -MT libguac_client_vnc_la-client.lo -MD -MP -MF $(DEPDIR)/libguac_client_vnc_la-client.Tpo -c -o libguac_client_vnc_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_vnc_la-client.Tpo $(DEPDIR)/libguac_client_vnc_la-client.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client.c' object='libguac_client_vnc_la-client.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -c -o libguac_client_vnc_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c libguac_client_vnc_la-clipboard.lo: clipboard.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -MT libguac_client_vnc_la-clipboard.lo -MD -MP -MF $(DEPDIR)/libguac_client_vnc_la-clipboard.Tpo -c -o libguac_client_vnc_la-clipboard.lo `test -f 'clipboard.c' || echo '$(srcdir)/'`clipboard.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_vnc_la-clipboard.Tpo $(DEPDIR)/libguac_client_vnc_la-clipboard.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='clipboard.c' object='libguac_client_vnc_la-clipboard.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -c -o libguac_client_vnc_la-clipboard.lo `test -f 'clipboard.c' || echo '$(srcdir)/'`clipboard.c libguac_client_vnc_la-cursor.lo: cursor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -MT libguac_client_vnc_la-cursor.lo -MD -MP -MF $(DEPDIR)/libguac_client_vnc_la-cursor.Tpo -c -o libguac_client_vnc_la-cursor.lo `test -f 'cursor.c' || echo '$(srcdir)/'`cursor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_vnc_la-cursor.Tpo $(DEPDIR)/libguac_client_vnc_la-cursor.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cursor.c' object='libguac_client_vnc_la-cursor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -c -o libguac_client_vnc_la-cursor.lo `test -f 'cursor.c' || echo '$(srcdir)/'`cursor.c libguac_client_vnc_la-display.lo: display.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -MT libguac_client_vnc_la-display.lo -MD -MP -MF $(DEPDIR)/libguac_client_vnc_la-display.Tpo -c -o libguac_client_vnc_la-display.lo `test -f 'display.c' || echo '$(srcdir)/'`display.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_vnc_la-display.Tpo $(DEPDIR)/libguac_client_vnc_la-display.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display.c' object='libguac_client_vnc_la-display.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -c -o libguac_client_vnc_la-display.lo `test -f 'display.c' || echo '$(srcdir)/'`display.c libguac_client_vnc_la-input.lo: input.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -MT libguac_client_vnc_la-input.lo -MD -MP -MF $(DEPDIR)/libguac_client_vnc_la-input.Tpo -c -o libguac_client_vnc_la-input.lo `test -f 'input.c' || echo '$(srcdir)/'`input.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_vnc_la-input.Tpo $(DEPDIR)/libguac_client_vnc_la-input.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='input.c' object='libguac_client_vnc_la-input.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -c -o libguac_client_vnc_la-input.lo `test -f 'input.c' || echo '$(srcdir)/'`input.c libguac_client_vnc_la-log.lo: log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -MT libguac_client_vnc_la-log.lo -MD -MP -MF $(DEPDIR)/libguac_client_vnc_la-log.Tpo -c -o libguac_client_vnc_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_vnc_la-log.Tpo $(DEPDIR)/libguac_client_vnc_la-log.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='log.c' object='libguac_client_vnc_la-log.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -c -o libguac_client_vnc_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c libguac_client_vnc_la-settings.lo: settings.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -MT libguac_client_vnc_la-settings.lo -MD -MP -MF $(DEPDIR)/libguac_client_vnc_la-settings.Tpo -c -o libguac_client_vnc_la-settings.lo `test -f 'settings.c' || echo '$(srcdir)/'`settings.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_vnc_la-settings.Tpo $(DEPDIR)/libguac_client_vnc_la-settings.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings.c' object='libguac_client_vnc_la-settings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -c -o libguac_client_vnc_la-settings.lo `test -f 'settings.c' || echo '$(srcdir)/'`settings.c libguac_client_vnc_la-user.lo: user.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -MT libguac_client_vnc_la-user.lo -MD -MP -MF $(DEPDIR)/libguac_client_vnc_la-user.Tpo -c -o libguac_client_vnc_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_vnc_la-user.Tpo $(DEPDIR)/libguac_client_vnc_la-user.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user.c' object='libguac_client_vnc_la-user.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -c -o libguac_client_vnc_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c libguac_client_vnc_la-vnc.lo: vnc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -MT libguac_client_vnc_la-vnc.lo -MD -MP -MF $(DEPDIR)/libguac_client_vnc_la-vnc.Tpo -c -o libguac_client_vnc_la-vnc.lo `test -f 'vnc.c' || echo '$(srcdir)/'`vnc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_vnc_la-vnc.Tpo $(DEPDIR)/libguac_client_vnc_la-vnc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vnc.c' object='libguac_client_vnc_la-vnc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -c -o libguac_client_vnc_la-vnc.lo `test -f 'vnc.c' || echo '$(srcdir)/'`vnc.c libguac_client_vnc_la-sftp.lo: sftp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -MT libguac_client_vnc_la-sftp.lo -MD -MP -MF $(DEPDIR)/libguac_client_vnc_la-sftp.Tpo -c -o libguac_client_vnc_la-sftp.lo `test -f 'sftp.c' || echo '$(srcdir)/'`sftp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_vnc_la-sftp.Tpo $(DEPDIR)/libguac_client_vnc_la-sftp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sftp.c' object='libguac_client_vnc_la-sftp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_vnc_la_CFLAGS) $(CFLAGS) -c -o libguac_client_vnc_la-sftp.lo `test -f 'sftp.c' || echo '$(srcdir)/'`sftp.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libguac_client_vnc_la-argv.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-auth.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-client.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-clipboard.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-cursor.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-display.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-input.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-log.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-settings.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-sftp.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-user.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-vnc.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libguac_client_vnc_la-argv.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-auth.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-client.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-clipboard.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-cursor.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-display.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-input.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-log.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-settings.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-sftp.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-user.Plo -rm -f ./$(DEPDIR)/libguac_client_vnc_la-vnc.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/protocols/vnc/cursor.c0000644000175100001440000000774213726006252016771 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "client.h" #include "common/cursor.h" #include "common/display.h" #include "common/surface.h" #include "vnc.h" #include #include #include #include #include #include #include /* Define cairo_format_stride_for_width() if missing */ #ifndef HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH #define cairo_format_stride_for_width(format, width) (width*4) #endif #include #include #include #include #include void guac_vnc_cursor(rfbClient* client, int x, int y, int w, int h, int bpp) { guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY); guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data; /* Cairo image buffer */ int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w); unsigned char* buffer = malloc(h*stride); unsigned char* buffer_row_current = buffer; /* VNC image buffer */ unsigned int fb_stride = bpp * w; unsigned char* fb_row_current = client->rcSource; unsigned char* fb_mask = client->rcMask; int dx, dy; /* Copy image data from VNC client to RGBA buffer */ for (dy = 0; dy> client->format.redShift) * 0x100 / (client->format.redMax + 1); green = (v >> client->format.greenShift) * 0x100 / (client->format.greenMax+ 1); blue = (v >> client->format.blueShift) * 0x100 / (client->format.blueMax + 1); /* Output ARGB */ if (vnc_client->settings->swap_red_blue) *(buffer_current++) = (alpha << 24) | (blue << 16) | (green << 8) | red; else *(buffer_current++) = (alpha << 24) | (red << 16) | (green << 8) | blue; /* Next VNC pixel */ fb_current += bpp; } } /* Update stored cursor information */ guac_common_cursor_set_argb(vnc_client->display->cursor, x, y, buffer, w, h, stride); /* Free surface */ free(buffer); /* libvncclient does not free rcMask as it does rcSource */ free(client->rcMask); } guacamole-server-1.3.0/src/protocols/vnc/settings.h0000644000175100001440000002212713764613616017325 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_VNC_SETTINGS_H #define __GUAC_VNC_SETTINGS_H #include "config.h" #include /** * The filename to use for the screen recording, if not specified. */ #define GUAC_VNC_DEFAULT_RECORDING_NAME "recording" /** * VNC-specific client data. */ typedef struct guac_vnc_settings { /** * The hostname of the VNC server (or repeater) to connect to. */ char* hostname; /** * The port of the VNC server (or repeater) to connect to. */ int port; /** * The username given in the arguments. */ char* username; /** * The password given in the arguments. */ char* password; /** * Space-separated list of encodings to use within the VNC session. */ char* encodings; /** * Whether the red and blue components of each color should be swapped. * This is mainly used for VNC servers that do not properly handle * colors. */ bool swap_red_blue; /** * The color depth to request, in bits. */ int color_depth; /** * Whether this connection is read-only, and user input should be dropped. */ bool read_only; #ifdef ENABLE_VNC_REPEATER /** * The VNC host to connect to, if using a repeater. */ char* dest_host; /** * The VNC port to connect to, if using a repeater. */ int dest_port; #endif #ifdef ENABLE_VNC_LISTEN /** * Whether not actually connecting to a VNC server, but rather listening * for a connection from the VNC server (reverse connection). */ bool reverse_connect; /** * The maximum amount of time to wait when listening for connections, in * milliseconds. */ int listen_timeout; #endif /** * Whether the cursor should be rendered on the server (remote) or on the * client (local). */ bool remote_cursor; #ifdef ENABLE_PULSE /** * Whether audio is enabled. */ bool audio_enabled; /** * The name of the PulseAudio server to connect to. */ char* pa_servername; #endif /** * The number of connection attempts to make before giving up. */ int retries; /** * The encoding to use for clipboard data sent to the VNC server, or NULL * to use the encoding required by the VNC standard. */ char* clipboard_encoding; /** * Whether outbound clipboard access should be blocked. If set, it will not * be possible to copy data from the remote desktop to the client using the * clipboard. */ bool disable_copy; /** * Whether inbound clipboard access should be blocked. If set, it will not * be possible to paste data from the client to the remote desktop using * the clipboard. */ bool disable_paste; #ifdef ENABLE_COMMON_SSH /** * Whether SFTP should be enabled for the VNC connection. */ bool enable_sftp; /** * The hostname of the SSH server to connect to for SFTP. */ char* sftp_hostname; /** * The public SSH host key. */ char* sftp_host_key; /** * The port of the SSH server to connect to for SFTP. */ char* sftp_port; /** * The username to provide when authenticating with the SSH server for * SFTP. */ char* sftp_username; /** * The password to provide when authenticating with the SSH server for * SFTP (if not using a private key). */ char* sftp_password; /** * The base64-encoded private key to use when authenticating with the SSH * server for SFTP (if not using a password). */ char* sftp_private_key; /** * The passphrase to use to decrypt the provided base64-encoded private * key. */ char* sftp_passphrase; /** * The default location for file uploads within the SSH server. This will * apply only to uploads which do not use the filesystem guac_object (where * the destination directory is otherwise ambiguous). */ char* sftp_directory; /** * The path of the directory within the SSH server to expose as a * filesystem guac_object. */ char* sftp_root_directory; /** * The interval at which SSH keepalive messages are sent to the server for * SFTP connections. The default is 0 (disabling keepalives), and a value * of 1 is automatically increased to 2 by libssh2 to avoid busy loop corner * cases. */ int sftp_server_alive_interval; /** * Whether file downloads over SFTP should be blocked. If set to "true", * the local client will not be able to download files from the SFTP server. * If set to "false" or not set, file downloads will be allowed. */ bool sftp_disable_download; /** * Whether file uploads over SFTP should be blocked. If set to "true", the * local client will not be able to upload files to the SFTP server. If set * to "false" or not set, file uploads will be allowed. */ bool sftp_disable_upload; #endif /** * The path in which the screen recording should be saved, if enabled. If * no screen recording should be saved, this will be NULL. */ char* recording_path; /** * The filename to use for the screen recording, if enabled. */ char* recording_name; /** * Whether the screen recording path should be automatically created if it * does not already exist. */ bool create_recording_path; /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output * is included by default, as it is necessary for any recording which must * later be viewable as video. */ bool recording_exclude_output; /** * Whether changes to mouse state, such as position and buttons pressed or * released, should NOT be included in the session recording. Mouse state * is included by default, as it is necessary for the mouse cursor to be * rendered in any resulting video. */ bool recording_exclude_mouse; /** * Whether keys pressed and released should be included in the session * recording. Key events are NOT included by default within the recording, * as doing so has privacy and security implications. Including key events * may be necessary in certain auditing contexts, but should only be done * with caution. Key events can easily contain sensitive information, such * as passwords, credit card numbers, etc. */ bool recording_include_keys; /** * Whether or not to send the magic Wake-on-LAN (WoL) packet prior to * trying to connect to the remote host. By default this will not be sent. * If this option is enabled but a MAC address is not provided a warning will * be logged and the packet will not be sent. */ bool wol_send_packet; /** * The MAC address to place in the magic WoL packet to wake the remote host. */ char* wol_mac_addr; /** * The broadcast address to which to send the magic WoL packet to wake * the remote host. */ char* wol_broadcast_addr; /** * The number of seconds after sending the magic WoL packet to wait before * attempting to connect to the remote host. */ int wol_wait_time; } guac_vnc_settings; /** * Parses all given args, storing them in a newly-allocated settings object. If * the args fail to parse, NULL is returned. * * @param user * The user who submitted the given arguments while joining the * connection. * * @param argc * The number of arguments within the argv array. * * @param argv * The values of all arguments provided by the user. * * @return * A newly-allocated settings object which must be freed with * guac_vnc_settings_free() when no longer needed. If the arguments fail * to parse, NULL is returned. */ guac_vnc_settings* guac_vnc_parse_args(guac_user* user, int argc, const char** argv); /** * Frees the given guac_vnc_settings object, having been previously allocated * via guac_vnc_parse_args(). * * @param settings * The settings object to free. */ void guac_vnc_settings_free(guac_vnc_settings* settings); /** * NULL-terminated array of accepted client args. */ extern const char* GUAC_VNC_CLIENT_ARGS[]; #endif guacamole-server-1.3.0/src/protocols/vnc/settings.c0000644000175100001440000004732713770536337017332 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "client.h" #include "common/defaults.h" #include "settings.h" #include #include #include #include #include #include /* Client plugin arguments */ const char* GUAC_VNC_CLIENT_ARGS[] = { "hostname", "port", "read-only", "encodings", GUAC_VNC_ARGV_USERNAME, GUAC_VNC_ARGV_PASSWORD, "swap-red-blue", "color-depth", "cursor", "autoretry", "clipboard-encoding", #ifdef ENABLE_VNC_REPEATER "dest-host", "dest-port", #endif #ifdef ENABLE_PULSE "enable-audio", "audio-servername", #endif #ifdef ENABLE_VNC_LISTEN "reverse-connect", "listen-timeout", #endif #ifdef ENABLE_COMMON_SSH "enable-sftp", "sftp-hostname", "sftp-host-key", "sftp-port", "sftp-username", "sftp-password", "sftp-private-key", "sftp-passphrase", "sftp-directory", "sftp-root-directory", "sftp-server-alive-interval", "sftp-disable-download", "sftp-disable-upload", #endif "recording-path", "recording-name", "recording-exclude-output", "recording-exclude-mouse", "recording-include-keys", "create-recording-path", "disable-copy", "disable-paste", "wol-send-packet", "wol-mac-addr", "wol-broadcast-addr", "wol-wait-time", NULL }; enum VNC_ARGS_IDX { /** * The hostname of the VNC server (or repeater) to connect to. */ IDX_HOSTNAME, /** * The port of the VNC server (or repeater) to connect to. */ IDX_PORT, /** * "true" if this connection should be read-only (user input should be * dropped), "false" or blank otherwise. */ IDX_READ_ONLY, /** * Space-separated list of encodings to use within the VNC session. If not * specified, this will be: * * "zrle ultra copyrect hextile zlib corre rre raw". */ IDX_ENCODINGS, /** * The username to send to the VNC server if authentication is requested. */ IDX_USERNAME, /** * The password to send to the VNC server if authentication is requested. */ IDX_PASSWORD, /** * "true" if the red and blue components of each color should be swapped, * "false" or blank otherwise. This is mainly used for VNC servers that do * not properly handle colors. */ IDX_SWAP_RED_BLUE, /** * The color depth to request, in bits. */ IDX_COLOR_DEPTH, /** * "remote" if the cursor should be rendered on the server instead of the * client. All other values will default to local rendering. */ IDX_CURSOR, /** * The number of connection attempts to make before giving up. By default, * this will be 0. */ IDX_AUTORETRY, /** * The encoding to use for clipboard data sent to the VNC server if we are * going to be deviating from the standard (which mandates ISO 8829-1). * Valid values are "ISO8829-1" (the only legal value with respect to the * VNC standard), "UTF-8", "UTF-16", and "CP2252". */ IDX_CLIPBOARD_ENCODING, #ifdef ENABLE_VNC_REPEATER /** * The VNC host to connect to, if using a repeater. */ IDX_DEST_HOST, /** * The VNC port to connect to, if using a repeater. */ IDX_DEST_PORT, #endif #ifdef ENABLE_PULSE /** * "true" if audio should be enabled, "false" or blank otherwise. */ IDX_ENABLE_AUDIO, /** * The name of the PulseAudio server to connect to. If left blank, the * default sink of the local machine will be used as the source for audio. */ IDX_AUDIO_SERVERNAME, #endif #ifdef ENABLE_VNC_LISTEN /** * "true" if not actually connecting to a VNC server, but rather listening * for a connection from the VNC server (reverse connection), "false" or * blank otherwise. */ IDX_REVERSE_CONNECT, /** * The maximum amount of time to wait when listening for connections, in * milliseconds. If unspecified, this will default to 5000. */ IDX_LISTEN_TIMEOUT, #endif #ifdef ENABLE_COMMON_SSH /** * "true" if SFTP should be enabled for the VNC connection, "false" or * blank otherwise. */ IDX_ENABLE_SFTP, /** * The hostname of the SSH server to connect to for SFTP. If blank, the * hostname of the VNC server will be used. */ IDX_SFTP_HOSTNAME, /** * The public SSH host key to identify the SFTP server. */ IDX_SFTP_HOST_KEY, /** * The port of the SSH server to connect to for SFTP. If blank, the default * SSH port of "22" will be used. */ IDX_SFTP_PORT, /** * The username to provide when authenticating with the SSH server for * SFTP. */ IDX_SFTP_USERNAME, /** * The password to provide when authenticating with the SSH server for * SFTP (if not using a private key). */ IDX_SFTP_PASSWORD, /** * The base64-encoded private key to use when authenticating with the SSH * server for SFTP (if not using a password). */ IDX_SFTP_PRIVATE_KEY, /** * The passphrase to use to decrypt the provided base64-encoded private * key. */ IDX_SFTP_PASSPHRASE, /** * The default location for file uploads within the SSH server. This will * apply only to uploads which do not use the filesystem guac_object (where * the destination directory is otherwise ambiguous). */ IDX_SFTP_DIRECTORY, /** * The path of the directory within the SSH server to expose as a * filesystem guac_object. If omitted, "/" will be used by default. */ IDX_SFTP_ROOT_DIRECTORY, /** * The interval at which SSH keepalive messages are sent to the server for * SFTP connections. The default is 0 (disabling keepalives), and a value * of 1 is automatically incremented to 2 by libssh2 to avoid busy loop corner * cases. */ IDX_SFTP_SERVER_ALIVE_INTERVAL, /** * If set to "true", file downloads over SFTP will be blocked. If set to * "false" or not set, file downloads will be allowed. */ IDX_SFTP_DISABLE_DOWNLOAD, /** * If set to "true", file uploads over SFTP will be blocked. If set to * "false" or not set, file uploads will be allowed. */ IDX_SFTP_DISABLE_UPLOAD, #endif /** * The full absolute path to the directory in which screen recordings * should be written. */ IDX_RECORDING_PATH, /** * The name that should be given to screen recordings which are written in * the given path. */ IDX_RECORDING_NAME, /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output * is included by default, as it is necessary for any recording which must * later be viewable as video. */ IDX_RECORDING_EXCLUDE_OUTPUT, /** * Whether changes to mouse state, such as position and buttons pressed or * released, should NOT be included in the session recording. Mouse state * is included by default, as it is necessary for the mouse cursor to be * rendered in any resulting video. */ IDX_RECORDING_EXCLUDE_MOUSE, /** * Whether keys pressed and released should be included in the session * recording. Key events are NOT included by default within the recording, * as doing so has privacy and security implications. Including key events * may be necessary in certain auditing contexts, but should only be done * with caution. Key events can easily contain sensitive information, such * as passwords, credit card numbers, etc. */ IDX_RECORDING_INCLUDE_KEYS, /** * Whether the specified screen recording path should automatically be * created if it does not yet exist. */ IDX_CREATE_RECORDING_PATH, /** * Whether outbound clipboard access should be blocked. If set to "true", * it will not be possible to copy data from the remote desktop to the * client using the clipboard. By default, clipboard access is not blocked. */ IDX_DISABLE_COPY, /** * Whether inbound clipboard access should be blocked. If set to "true", it * will not be possible to paste data from the client to the remote desktop * using the clipboard. By default, clipboard access is not blocked. */ IDX_DISABLE_PASTE, /** * Whether to send the magic Wake-on-LAN (WoL) packet to wake the remote * host prior to attempting to connect. If set to "true" the packet will * be sent. By default the packet will not be sent. */ IDX_WOL_SEND_PACKET, /** * The MAC address to place in the magic WoL packet to wake the remote host. * If WoL is requested but this is not provided a warning will be logged * and the WoL packet will not be sent. */ IDX_WOL_MAC_ADDR, /** * The broadcast packet to which to send the magic WoL packet. */ IDX_WOL_BROADCAST_ADDR, /** * The number of seconds to wait after sending the magic WoL packet before * attempting to connect to the remote host. The default is not to wait * at all (0 seconds). */ IDX_WOL_WAIT_TIME, VNC_ARGS_COUNT }; guac_vnc_settings* guac_vnc_parse_args(guac_user* user, int argc, const char** argv) { /* Validate arg count */ if (argc != VNC_ARGS_COUNT) { guac_user_log(user, GUAC_LOG_WARNING, "Incorrect number of connection " "parameters provided: expected %i, got %i.", VNC_ARGS_COUNT, argc); return NULL; } guac_vnc_settings* settings = calloc(1, sizeof(guac_vnc_settings)); settings->hostname = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_HOSTNAME, ""); settings->port = guac_user_parse_args_int(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_PORT, 0); settings->username = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_USERNAME, NULL); settings->password = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_PASSWORD, NULL); /* Remote cursor */ if (strcmp(argv[IDX_CURSOR], "remote") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Cursor rendering: remote"); settings->remote_cursor = true; } /* Local cursor */ else { guac_user_log(user, GUAC_LOG_INFO, "Cursor rendering: local"); settings->remote_cursor = false; } /* Swap red/blue (for buggy VNC servers) */ settings->swap_red_blue = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SWAP_RED_BLUE, false); /* Read-only mode */ settings->read_only = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_READ_ONLY, false); /* Parse color depth */ settings->color_depth = guac_user_parse_args_int(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_COLOR_DEPTH, 0); #ifdef ENABLE_VNC_REPEATER /* Set repeater parameters if specified */ settings->dest_host = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_DEST_HOST, NULL); /* VNC repeater port */ settings->dest_port = guac_user_parse_args_int(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_DEST_PORT, 0); #endif /* Set encodings if specified */ settings->encodings = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_ENCODINGS, "zrle ultra copyrect hextile zlib corre rre raw"); /* Parse autoretry */ settings->retries = guac_user_parse_args_int(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_AUTORETRY, 0); #ifdef ENABLE_VNC_LISTEN /* Set reverse-connection flag */ settings->reverse_connect = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_REVERSE_CONNECT, false); /* Parse listen timeout */ settings->listen_timeout = guac_user_parse_args_int(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_LISTEN_TIMEOUT, 5000); #endif #ifdef ENABLE_PULSE /* Audio enable/disable */ settings->audio_enabled = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_ENABLE_AUDIO, false); /* Load servername if specified and applicable */ if (settings->audio_enabled) settings->pa_servername = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_AUDIO_SERVERNAME, NULL); #endif /* Set clipboard encoding if specified */ settings->clipboard_encoding = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_CLIPBOARD_ENCODING, NULL); #ifdef ENABLE_COMMON_SSH /* SFTP enable/disable */ settings->enable_sftp = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_ENABLE_SFTP, false); /* Hostname for SFTP connection */ settings->sftp_hostname = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SFTP_HOSTNAME, settings->hostname); /* The public SSH host key. */ settings->sftp_host_key = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SFTP_HOST_KEY, NULL); /* Port for SFTP connection */ settings->sftp_port = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SFTP_PORT, "22"); /* Username for SSH/SFTP authentication */ settings->sftp_username = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SFTP_USERNAME, ""); /* Password for SFTP (if not using private key) */ settings->sftp_password = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SFTP_PASSWORD, ""); /* Private key for SFTP (if not using password) */ settings->sftp_private_key = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SFTP_PRIVATE_KEY, NULL); /* Passphrase for decrypting the SFTP private key (if applicable */ settings->sftp_passphrase = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SFTP_PASSPHRASE, ""); /* Default upload directory */ settings->sftp_directory = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SFTP_DIRECTORY, NULL); /* SFTP root directory */ settings->sftp_root_directory = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SFTP_ROOT_DIRECTORY, "/"); /* Default keepalive value */ settings->sftp_server_alive_interval = guac_user_parse_args_int(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SFTP_SERVER_ALIVE_INTERVAL, 0); settings->sftp_disable_download = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SFTP_DISABLE_DOWNLOAD, false); settings->sftp_disable_upload = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_SFTP_DISABLE_UPLOAD, false); #endif /* Read recording path */ settings->recording_path = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_RECORDING_PATH, NULL); /* Read recording name */ settings->recording_name = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_RECORDING_NAME, GUAC_VNC_DEFAULT_RECORDING_NAME); /* Parse output exclusion flag */ settings->recording_exclude_output = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_RECORDING_EXCLUDE_OUTPUT, false); /* Parse mouse exclusion flag */ settings->recording_exclude_mouse = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_RECORDING_EXCLUDE_MOUSE, false); /* Parse key event inclusion flag */ settings->recording_include_keys = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_RECORDING_INCLUDE_KEYS, false); /* Parse path creation flag */ settings->create_recording_path = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_CREATE_RECORDING_PATH, false); /* Parse clipboard copy disable flag */ settings->disable_copy = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_DISABLE_COPY, false); /* Parse clipboard paste disable flag */ settings->disable_paste = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_DISABLE_PASTE, false); /* Parse Wake-on-LAN (WoL) settings */ settings->wol_send_packet = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_WOL_SEND_PACKET, false); if (settings->wol_send_packet) { /* If WoL has been enabled but no MAC provided, log warning and disable. */ if(strcmp(argv[IDX_WOL_MAC_ADDR], "") == 0) { guac_user_log(user, GUAC_LOG_WARNING, "Wake on LAN was requested, ", "but no MAC address was specified. WoL will not be sent."); settings->wol_send_packet = false; } /* Parse the WoL MAC address. */ settings->wol_mac_addr = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_WOL_MAC_ADDR, NULL); /* Parse the WoL broadcast address. */ settings->wol_broadcast_addr = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_WOL_BROADCAST_ADDR, GUAC_WOL_LOCAL_IPV4_BROADCAST); /* Parse the WoL wait time. */ settings->wol_wait_time = guac_user_parse_args_int(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_WOL_WAIT_TIME, GUAC_WOL_DEFAULT_BOOT_WAIT_TIME); } return settings; } void guac_vnc_settings_free(guac_vnc_settings* settings) { /* Free settings strings */ free(settings->clipboard_encoding); free(settings->encodings); free(settings->hostname); free(settings->password); free(settings->recording_name); free(settings->recording_path); free(settings->username); #ifdef ENABLE_VNC_REPEATER /* Free VNC repeater settings */ free(settings->dest_host); #endif #ifdef ENABLE_COMMON_SSH /* Free SFTP settings */ free(settings->sftp_directory); free(settings->sftp_root_directory); free(settings->sftp_host_key); free(settings->sftp_hostname); free(settings->sftp_passphrase); free(settings->sftp_password); free(settings->sftp_port); free(settings->sftp_private_key); free(settings->sftp_username); #endif #ifdef ENABLE_PULSE /* Free PulseAudio settings */ free(settings->pa_servername); #endif /* Free settings structure */ free(settings); } guacamole-server-1.3.0/src/protocols/vnc/display.h0000644000175100001440000000764613726006252017131 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_VNC_DISPLAY_H #define GUAC_VNC_DISPLAY_H #include "config.h" #include #include /** * Callback invoked by libVNCServer when it receives a new binary image data. * the VNC server. The image itself will be stored in the designated sub- * rectangle of client->framebuffer. * * @param client * The VNC client associated with the VNC session in which the new image * was received. * * @param x * The X coordinate of the upper-left corner of the destination rectangle * in which the image should be drawn, in pixels. * * @param y * The Y coordinate of the upper-left corner of the destination rectangle * in which the image should be drawn, in pixels. * * @param w * The width of the image, in pixels. * * @param h * The height of the image, in pixels. */ void guac_vnc_update(rfbClient* client, int x, int y, int w, int h); /** * Callback invoked by libVNCServer when it receives a CopyRect message. * CopyRect specified a rectangle of source data within the display and a * set of X/Y coordinates to which that rectangle should be copied. * * @param client * The VNC client associated with the VNC session in which the CopyRect * was received. * * @param src_x * The X coordinate of the upper-left corner of the source rectangle * from which the image data should be copied, in pixels. * * @param src_y * The Y coordinate of the upper-left corner of the source rectangle * from which the image data should be copied, in pixels. * * @param w * The width of the source and destination rectangles, in pixels. * * @param h * The height of the source and destination rectangles, in pixels. * * @param dest_x * The X coordinate of the upper-left corner of the destination rectangle * in which the copied image data should be drawn, in pixels. * * @param dest_y * The Y coordinate of the upper-left corner of the destination rectangle * in which the copied image data should be drawn, in pixels. */ void guac_vnc_copyrect(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y); /** * Sets the pixel format to request of the VNC server. The request will be made * during the connection handshake with the VNC server using the values * specified by this function. Note that the VNC server is not required to * honor this request. * * @param client * The VNC client associated with the VNC session whose desired pixel * format should be set. * * @param color_depth * The desired new color depth, in bits per pixel. Valid values are 8, 16, * 24, and 32. */ void guac_vnc_set_pixel_format(rfbClient* client, int color_depth); /** * Overridden implementation of the rfb_MallocFrameBuffer function invoked by * libVNCServer when the display is being resized (or initially allocated). * * @param client * The VNC client associated with the VNC session whose display needs to be * allocated or reallocated. * * @return * The original value returned by rfb_MallocFrameBuffer(). */ rfbBool guac_vnc_malloc_framebuffer(rfbClient* rfb_client); #endif guacamole-server-1.3.0/src/protocols/vnc/client.h0000644000175100001440000000372013613156714016733 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_VNC_CLIENT_H #define __GUAC_VNC_CLIENT_H #include /** * The maximum duration of a frame in milliseconds. */ #define GUAC_VNC_FRAME_DURATION 40 /** * The amount of time to allow per message read within a frame, in * milliseconds. If the server is silent for at least this amount of time, the * frame will be considered finished. */ #define GUAC_VNC_FRAME_TIMEOUT 0 /** * The amount of time to wait for a new message from the VNC server when * beginning a new frame. This value must be kept reasonably small such that * a slow VNC server will not prevent external events from being handled (such * as the stop signal from guac_client_stop()), but large enough that the * message handling loop does not eat up CPU spinning. */ #define GUAC_VNC_FRAME_START_TIMEOUT 1000000 /** * The number of milliseconds to wait between connection attempts. */ #define GUAC_VNC_CONNECT_INTERVAL 1000 /** * The maximum number of bytes to allow within the clipboard. */ #define GUAC_VNC_CLIPBOARD_MAX_LENGTH 262144 /** * Handler which frees all data associated with the guac_client. */ guac_client_free_handler guac_vnc_client_free_handler; #endif guacamole-server-1.3.0/src/protocols/vnc/vnc.c0000644000175100001440000004025513770536337016251 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "auth.h" #include "client.h" #include "clipboard.h" #include "common/clipboard.h" #include "common/cursor.h" #include "common/display.h" #include "common/recording.h" #include "cursor.h" #include "display.h" #include "log.h" #include "settings.h" #include "vnc.h" #ifdef ENABLE_PULSE #include "pulse/pulse.h" #endif #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" #include "common-ssh/ssh.h" #include "sftp.h" #endif #include #include #include #include #include #include #include #include #include #include char* GUAC_VNC_CLIENT_KEY = "GUAC_VNC"; #ifdef ENABLE_VNC_TLS_LOCKING /** * A callback function that is called by the VNC library prior to writing * data to a TLS-encrypted socket. This returns the rfbBool FALSE value * if there's an error locking the mutex, or rfbBool TRUE otherwise. * * @param rfb_client * The rfbClient for which to lock the TLS mutex. * * @returns * rfbBool FALSE if an error occurs locking the mutex, otherwise * TRUE. */ static rfbBool guac_vnc_lock_write_to_tls(rfbClient* rfb_client) { /* Retrieve the Guacamole data structures */ guac_client* gc = rfbClientGetClientData(rfb_client, GUAC_VNC_CLIENT_KEY); guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data; /* Lock write access */ int retval = pthread_mutex_lock(&(vnc_client->tls_lock)); if (retval) { guac_client_log(gc, GUAC_LOG_ERROR, "Error locking TLS write mutex: %s", strerror(retval)); return FALSE; } return TRUE; } /** * A callback function for use by the VNC library that is called once * the client is finished writing to a TLS-encrypted socket. A rfbBool * FALSE value is returned if an error occurs unlocking the mutex, * otherwise TRUE is returned. * * @param rfb_client * The rfbClient for which to unlock the TLS mutex. * * @returns * rfbBool FALSE if an error occurs unlocking the mutex, otherwise * TRUE. */ static rfbBool guac_vnc_unlock_write_to_tls(rfbClient* rfb_client) { /* Retrieve the Guacamole data structures */ guac_client* gc = rfbClientGetClientData(rfb_client, GUAC_VNC_CLIENT_KEY); guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data; /* Unlock write access */ int retval = pthread_mutex_unlock(&(vnc_client->tls_lock)); if (retval) { guac_client_log(gc, GUAC_LOG_ERROR, "Error unlocking TLS write mutex: %s", strerror(retval)); return FALSE; } return TRUE; } #endif rfbClient* guac_vnc_get_client(guac_client* client) { rfbClient* rfb_client = rfbGetClient(8, 3, 4); /* 32-bpp client */ guac_vnc_client* vnc_client = (guac_vnc_client*) client->data; guac_vnc_settings* vnc_settings = vnc_client->settings; /* Store Guac client in rfb client */ rfbClientSetClientData(rfb_client, GUAC_VNC_CLIENT_KEY, client); /* Framebuffer update handler */ rfb_client->GotFrameBufferUpdate = guac_vnc_update; rfb_client->GotCopyRect = guac_vnc_copyrect; #ifdef ENABLE_VNC_TLS_LOCKING /* TLS Locking and Unlocking */ rfb_client->LockWriteToTLS = guac_vnc_lock_write_to_tls; rfb_client->UnlockWriteToTLS = guac_vnc_unlock_write_to_tls; #endif /* Do not handle clipboard and local cursor if read-only */ if (vnc_settings->read_only == 0) { /* Clipboard */ rfb_client->GotXCutText = guac_vnc_cut_text; /* Set remote cursor */ if (vnc_settings->remote_cursor) { rfb_client->appData.useRemoteCursor = FALSE; } else { /* Enable client-side cursor */ rfb_client->appData.useRemoteCursor = TRUE; rfb_client->GotCursorShape = guac_vnc_cursor; } } /* Authentication */ rfb_client->GetCredential = guac_vnc_get_credentials; /* Password */ rfb_client->GetPassword = guac_vnc_get_password; /* Depth */ guac_vnc_set_pixel_format(rfb_client, vnc_settings->color_depth); /* Hook into allocation so we can handle resize. */ vnc_client->rfb_MallocFrameBuffer = rfb_client->MallocFrameBuffer; rfb_client->MallocFrameBuffer = guac_vnc_malloc_framebuffer; rfb_client->canHandleNewFBSize = 1; /* Set hostname and port */ rfb_client->serverHost = strdup(vnc_settings->hostname); rfb_client->serverPort = vnc_settings->port; #ifdef ENABLE_VNC_REPEATER /* Set repeater parameters if specified */ if (vnc_settings->dest_host) { rfb_client->destHost = strdup(vnc_settings->dest_host); rfb_client->destPort = vnc_settings->dest_port; } #endif #ifdef ENABLE_VNC_LISTEN /* If reverse connection enabled, start listening */ if (vnc_settings->reverse_connect) { guac_client_log(client, GUAC_LOG_INFO, "Listening for connections on port %i", vnc_settings->port); /* Listen for connection from server */ rfb_client->listenPort = vnc_settings->port; if (listenForIncomingConnectionsNoFork(rfb_client, vnc_settings->listen_timeout*1000) <= 0) return NULL; } #endif /* Set encodings if provided */ if (vnc_settings->encodings) rfb_client->appData.encodingsString = strdup(vnc_settings->encodings); /* Connect */ if (rfbInitClient(rfb_client, NULL, NULL)) return rfb_client; /* If connection fails, return NULL */ return NULL; } /** * Waits until data is available to be read from the given rfbClient, and thus * a call to HandleRFBServerMessages() should not block. If the timeout elapses * before data is available, zero is returned. * * @param rfb_client * The rfbClient to wait for. * * @param timeout * The maximum amount of time to wait, in microseconds. * * @returns * A positive value if data is available, zero if the timeout elapses * before data becomes available, or a negative value on error. */ static int guac_vnc_wait_for_messages(rfbClient* rfb_client, int timeout) { /* Do not explicitly wait while data is on the buffer */ if (rfb_client->buffered) return 1; /* If no data on buffer, wait for data on socket */ return WaitForMessage(rfb_client, timeout); } void* guac_vnc_client_thread(void* data) { guac_client* client = (guac_client*) data; guac_vnc_client* vnc_client = (guac_vnc_client*) client->data; guac_vnc_settings* settings = vnc_client->settings; /* If Wake-on-LAN is enabled, attempt to wake. */ if (settings->wol_send_packet) { guac_client_log(client, GUAC_LOG_DEBUG, "Sending Wake-on-LAN packet, " "and pausing for %d seconds.", settings->wol_wait_time); /* Send the Wake-on-LAN request. */ if (guac_wol_wake(settings->wol_mac_addr, settings->wol_broadcast_addr)) return NULL; /* If wait time is specified, sleep for that amount of time. */ if (settings->wol_wait_time > 0) guac_timestamp_msleep(settings->wol_wait_time * 1000); } /* Configure clipboard encoding */ if (guac_vnc_set_clipboard_encoding(client, settings->clipboard_encoding)) { guac_client_log(client, GUAC_LOG_INFO, "Using non-standard VNC " "clipboard encoding: '%s'.", settings->clipboard_encoding); } /* Set up libvncclient logging */ rfbClientLog = guac_vnc_client_log_info; rfbClientErr = guac_vnc_client_log_error; /* Attempt connection */ rfbClient* rfb_client = guac_vnc_get_client(client); int retries_remaining = settings->retries; /* If unsuccessful, retry as many times as specified */ while (!rfb_client && retries_remaining > 0) { guac_client_log(client, GUAC_LOG_INFO, "Connect failed. Waiting %ims before retrying...", GUAC_VNC_CONNECT_INTERVAL); /* Wait for given interval then retry */ guac_timestamp_msleep(GUAC_VNC_CONNECT_INTERVAL); rfb_client = guac_vnc_get_client(client); retries_remaining--; } /* If the final connect attempt fails, return error */ if (!rfb_client) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND, "Unable to connect to VNC server."); return NULL; } #ifdef ENABLE_PULSE /* If audio is enabled, start streaming via PulseAudio */ if (settings->audio_enabled) vnc_client->audio = guac_pa_stream_alloc(client, settings->pa_servername); #endif #ifdef ENABLE_COMMON_SSH guac_common_ssh_init(client); /* Connect via SSH if SFTP is enabled */ if (settings->enable_sftp) { /* Abort if username is missing */ if (settings->sftp_username == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "SFTP username is required if SFTP is enabled."); return NULL; } guac_client_log(client, GUAC_LOG_DEBUG, "Connecting via SSH for SFTP filesystem access."); vnc_client->sftp_user = guac_common_ssh_create_user(settings->sftp_username); /* Import private key, if given */ if (settings->sftp_private_key != NULL) { guac_client_log(client, GUAC_LOG_DEBUG, "Authenticating with private key."); /* Abort if private key cannot be read */ if (guac_common_ssh_user_import_key(vnc_client->sftp_user, settings->sftp_private_key, settings->sftp_passphrase)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Private key unreadable."); return NULL; } } /* Otherwise, use specified password */ else { guac_client_log(client, GUAC_LOG_DEBUG, "Authenticating with password."); guac_common_ssh_user_set_password(vnc_client->sftp_user, settings->sftp_password); } /* Attempt SSH connection */ vnc_client->sftp_session = guac_common_ssh_create_session(client, settings->sftp_hostname, settings->sftp_port, vnc_client->sftp_user, settings->sftp_server_alive_interval, settings->sftp_host_key, NULL); /* Fail if SSH connection does not succeed */ if (vnc_client->sftp_session == NULL) { /* Already aborted within guac_common_ssh_create_session() */ return NULL; } /* Load filesystem */ vnc_client->sftp_filesystem = guac_common_ssh_create_sftp_filesystem(vnc_client->sftp_session, settings->sftp_root_directory, NULL, settings->sftp_disable_download, settings->sftp_disable_upload); /* Expose filesystem to connection owner */ guac_client_for_owner(client, guac_common_ssh_expose_sftp_filesystem, vnc_client->sftp_filesystem); /* Abort if SFTP connection fails */ if (vnc_client->sftp_filesystem == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "SFTP connection failed."); return NULL; } /* Configure destination for basic uploads, if specified */ if (settings->sftp_directory != NULL) guac_common_ssh_sftp_set_upload_path( vnc_client->sftp_filesystem, settings->sftp_directory); guac_client_log(client, GUAC_LOG_DEBUG, "SFTP connection succeeded."); } #endif /* Set remaining client data */ vnc_client->rfb_client = rfb_client; /* Set up screen recording, if requested */ if (settings->recording_path != NULL) { vnc_client->recording = guac_common_recording_create(client, settings->recording_path, settings->recording_name, settings->create_recording_path, !settings->recording_exclude_output, !settings->recording_exclude_mouse, settings->recording_include_keys); } /* Create display */ vnc_client->display = guac_common_display_alloc(client, rfb_client->width, rfb_client->height); /* If not read-only, set an appropriate cursor */ if (settings->read_only == 0) { if (settings->remote_cursor) guac_common_cursor_set_dot(vnc_client->display->cursor); else guac_common_cursor_set_pointer(vnc_client->display->cursor); } guac_socket_flush(client->socket); guac_timestamp last_frame_end = guac_timestamp_current(); /* Handle messages from VNC server while client is running */ while (client->state == GUAC_CLIENT_RUNNING) { /* Wait for start of frame */ int wait_result = guac_vnc_wait_for_messages(rfb_client, GUAC_VNC_FRAME_START_TIMEOUT); if (wait_result > 0) { int processing_lag = guac_client_get_processing_lag(client); guac_timestamp frame_start = guac_timestamp_current(); /* Read server messages until frame is built */ do { guac_timestamp frame_end; int frame_remaining; /* Handle any message received */ if (!HandleRFBServerMessage(rfb_client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Error handling message from VNC server."); break; } /* Calculate time remaining in frame */ frame_end = guac_timestamp_current(); frame_remaining = frame_start + GUAC_VNC_FRAME_DURATION - frame_end; /* Calculate time that client needs to catch up */ int time_elapsed = frame_end - last_frame_end; int required_wait = processing_lag - time_elapsed; /* Increase the duration of this frame if client is lagging */ if (required_wait > GUAC_VNC_FRAME_TIMEOUT) wait_result = guac_vnc_wait_for_messages(rfb_client, required_wait*1000); /* Wait again if frame remaining */ else if (frame_remaining > 0) wait_result = guac_vnc_wait_for_messages(rfb_client, GUAC_VNC_FRAME_TIMEOUT*1000); else break; } while (wait_result > 0); /* Record end of frame, excluding server-side rendering time (we * assume server-side rendering time will be consistent between any * two subsequent frames, and that this time should thus be * excluded from the required wait period of the next frame). */ last_frame_end = frame_start; } /* If an error occurs, log it and fail */ if (wait_result < 0) guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Connection closed."); /* Flush frame */ guac_common_surface_flush(vnc_client->display->default_surface); guac_client_end_frame(client); guac_socket_flush(client->socket); } /* Kill client and finish connection */ guac_client_stop(client); guac_client_log(client, GUAC_LOG_INFO, "Internal VNC client disconnected"); return NULL; } guacamole-server-1.3.0/src/protocols/vnc/sftp.c0000644000175100001440000000262213613156714016424 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common-ssh/sftp.h" #include "sftp.h" #include "vnc.h" #include #include #include int guac_vnc_sftp_file_handler(guac_user* user, guac_stream* stream, char* mimetype, char* filename) { guac_client* client = user->client; guac_vnc_client* vnc_client = (guac_vnc_client*) client->data; guac_common_ssh_sftp_filesystem* filesystem = vnc_client->sftp_filesystem; /* Handle file upload */ return guac_common_ssh_sftp_handle_file_stream(filesystem, user, stream, mimetype, filename); } guacamole-server-1.3.0/src/protocols/vnc/client.c0000644000175100001440000001016213770536337016733 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/recording.h" #include "client.h" #include "user.h" #include "vnc.h" #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" #include "common-ssh/ssh.h" #include "common-ssh/user.h" #endif #ifdef ENABLE_PULSE #include "pulse/pulse.h" #endif #include #include #include #include int guac_client_init(guac_client* client) { /* Set client args */ client->args = GUAC_VNC_CLIENT_ARGS; /* Alloc client data */ guac_vnc_client* vnc_client = calloc(1, sizeof(guac_vnc_client)); client->data = vnc_client; #ifdef ENABLE_VNC_TLS_LOCKING /* Initialize the TLS write lock */ pthread_mutex_init(&vnc_client->tls_lock, NULL); #endif /* Init clipboard */ vnc_client->clipboard = guac_common_clipboard_alloc(GUAC_VNC_CLIPBOARD_MAX_LENGTH); /* Set handlers */ client->join_handler = guac_vnc_user_join_handler; client->leave_handler = guac_vnc_user_leave_handler; client->free_handler = guac_vnc_client_free_handler; return 0; } int guac_vnc_client_free_handler(guac_client* client) { guac_vnc_client* vnc_client = (guac_vnc_client*) client->data; guac_vnc_settings* settings = vnc_client->settings; /* Clean up VNC client*/ rfbClient* rfb_client = vnc_client->rfb_client; if (rfb_client != NULL) { /* Wait for client thread to finish */ pthread_join(vnc_client->client_thread, NULL); /* Free memory not free'd by libvncclient's rfbClientCleanup() */ if (rfb_client->frameBuffer != NULL) free(rfb_client->frameBuffer); if (rfb_client->raw_buffer != NULL) free(rfb_client->raw_buffer); if (rfb_client->rcSource != NULL) free(rfb_client->rcSource); /* Free VNC rfbClientData linked list (not free'd by rfbClientCleanup()) */ while (rfb_client->clientData != NULL) { rfbClientData* next = rfb_client->clientData->next; free(rfb_client->clientData); rfb_client->clientData = next; } rfbClientCleanup(rfb_client); } #ifdef ENABLE_COMMON_SSH /* Free SFTP filesystem, if loaded */ if (vnc_client->sftp_filesystem) guac_common_ssh_destroy_sftp_filesystem(vnc_client->sftp_filesystem); /* Free SFTP session */ if (vnc_client->sftp_session) guac_common_ssh_destroy_session(vnc_client->sftp_session); /* Free SFTP user */ if (vnc_client->sftp_user) guac_common_ssh_destroy_user(vnc_client->sftp_user); guac_common_ssh_uninit(); #endif /* Clean up recording, if in progress */ if (vnc_client->recording != NULL) guac_common_recording_free(vnc_client->recording); /* Free clipboard */ if (vnc_client->clipboard != NULL) guac_common_clipboard_free(vnc_client->clipboard); /* Free display */ if (vnc_client->display != NULL) guac_common_display_free(vnc_client->display); #ifdef ENABLE_PULSE /* If audio enabled, stop streaming */ if (vnc_client->audio) guac_pa_stream_free(vnc_client->audio); #endif /* Free parsed settings */ if (settings != NULL) guac_vnc_settings_free(settings); #ifdef ENABLE_VNC_TLS_LOCKING /* Clean up TLS lock mutex. */ pthread_mutex_destroy(&(vnc_client->tls_lock)); #endif /* Free generic data struct */ free(client->data); return 0; } guacamole-server-1.3.0/src/protocols/vnc/Makefile.am0000644000175100001440000000513513770536337017351 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac-client-vnc.la libguac_client_vnc_la_SOURCES = \ argv.c \ auth.c \ client.c \ clipboard.c \ cursor.c \ display.c \ input.c \ log.c \ settings.c \ user.c \ vnc.c noinst_HEADERS = \ argv.h \ auth.h \ client.h \ clipboard.h \ cursor.h \ display.h \ input.h \ log.h \ settings.h \ user.h \ vnc.h libguac_client_vnc_la_CFLAGS = \ -Werror -Wall -pedantic -Iinclude \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ \ @PULSE_INCLUDE@ libguac_client_vnc_la_LDFLAGS = \ -version-info 0:0:0 \ @CAIRO_LIBS@ \ @VNC_LIBS@ libguac_client_vnc_la_LIBADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ # Optional SFTP support if ENABLE_COMMON_SSH libguac_client_vnc_la_SOURCES += sftp.c noinst_HEADERS += sftp.h libguac_client_vnc_la_LIBADD += @COMMON_SSH_LTLIB@ endif # Optional PulseAudio support if ENABLE_PULSE libguac_client_vnc_la_LIBADD += @PULSE_LTLIB@ endif guacamole-server-1.3.0/src/protocols/rdp/0000755000175100001440000000000013772471160015362 500000000000000guacamole-server-1.3.0/src/protocols/rdp/error.c0000644000175100001440000002525013770536337016611 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "error.h" #include #include #include #include #include /** * Translates the error code returned by freerdp_get_last_error() for the given * RDP instance into a Guacamole status code and human-readable message. If no * error was reported, a successful error code and message will be assigned. * * @param rdp_inst * The FreeRDP client instance handling the RDP connection that failed. * * @param status * Pointer to the variable that should receive the guac_protocol_status * value equivalent to the error returned by freerdp_get_last_error(). * * @param message * Pointer to the variable that should receive a static human-readable * message generally describing the error returned by * freerdp_get_last_error(). */ static void guac_rdp_translate_last_error(freerdp* rdp_inst, guac_protocol_status* status, const char** message) { UINT32 last_error = freerdp_get_last_error(rdp_inst->context); switch (last_error) { /* * Normal disconnect (no error at all) */ case FREERDP_ERROR_NONE: case FREERDP_ERROR_SUCCESS: *status = GUAC_PROTOCOL_STATUS_SUCCESS; *message = "Disconnected."; break; /* * General credentials expired (password has expired, password must be * reset before it can be used for the first time, etc.) */ #ifdef FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED case FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED: #endif #ifdef FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE case FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE: #endif case FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED: case FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED: case FREERDP_ERROR_SERVER_FRESH_CREDENTIALS_REQUIRED: *status = GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN; *message = "Credentials expired."; break; /* * Security negotiation failed (the server is refusing the connection * because the security negotiation process failed) */ case FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED: *status = GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED; *message = "Security negotiation failed (wrong security type?)"; break; /* * General access denied/revoked (regardless of any credentials * provided, the server is denying the requested access by this * account) */ #ifdef FREERDP_ERROR_CONNECT_ACCESS_DENIED case FREERDP_ERROR_CONNECT_ACCESS_DENIED: #endif #ifdef FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED case FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED: #endif #ifdef FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT case FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT: #endif #ifdef FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION case FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION: #endif #ifdef FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED case FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED: #endif case FREERDP_ERROR_CONNECT_CLIENT_REVOKED: case FREERDP_ERROR_INSUFFICIENT_PRIVILEGES: case FREERDP_ERROR_SERVER_DENIED_CONNECTION: case FREERDP_ERROR_SERVER_INSUFFICIENT_PRIVILEGES: *status = GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN; *message = "Access denied by server (account locked/disabled?)"; break; /* * General authentication failure (no credentials provided or wrong * credentials provided) */ #ifdef FREERDP_ERROR_CONNECT_NO_OR_MISSING_CREDENTIALS case FREERDP_ERROR_CONNECT_NO_OR_MISSING_CREDENTIALS: #endif #ifdef FREERDP_ERROR_CONNECT_LOGON_FAILURE case FREERDP_ERROR_CONNECT_LOGON_FAILURE: #endif #ifdef FREERDP_ERROR_CONNECT_WRONG_PASSWORD case FREERDP_ERROR_CONNECT_WRONG_PASSWORD: #endif case FREERDP_ERROR_AUTHENTICATION_FAILED: *status = GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED; *message = "Authentication failure (invalid credentials?)"; break; /* * SSL/TLS connection failed (the server's certificate is not trusted) */ case FREERDP_ERROR_TLS_CONNECT_FAILED: *status = GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND; *message = "SSL/TLS connection failed (untrusted/self-signed certificate?)"; break; /* * DNS lookup failed (hostname resolution failed or invalid IP address) */ case FREERDP_ERROR_DNS_ERROR: case FREERDP_ERROR_DNS_NAME_NOT_FOUND: *status = GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND; *message = "DNS lookup failed (incorrect hostname?)"; break; /* * Connection refused (the server is outright refusing to handle the * inbound connection, typically due to the client requesting a * security type that is not allowed) */ case FREERDP_ERROR_CONNECT_TRANSPORT_FAILED: *status = GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND; *message = "Server refused connection (wrong security type?)"; break; /* * Connection failed (the network connection to the server did not * succeed) */ case FREERDP_ERROR_CONNECT_CANCELLED: case FREERDP_ERROR_CONNECT_FAILED: case FREERDP_ERROR_CONNECT_KDC_UNREACHABLE: case FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR: *status = GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND; *message = "Connection failed (server unreachable?)"; break; /* * All other (unknown) errors */ default: *status = GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR; *message = "Upstream error."; } } void guac_rdp_client_abort(guac_client* client, freerdp* rdp_inst) { /* * NOTE: The RDP status codes translated here are documented within * [MS-RDPBCGR], section 2.2.5.1.1: "Set Error Info PDU Data", in the * description of the "errorInfo" field. * * https://msdn.microsoft.com/en-us/library/cc240544.aspx */ guac_protocol_status status; const char* message; /* Read disconnect reason code from connection */ int error_info = freerdp_error_info(rdp_inst); /* Translate reason code into Guacamole protocol status */ switch (error_info) { /* Possibly-normal disconnect, depending on freerdp_get_last_error() */ case 0x0: /* ERRINFO_SUCCESS */ guac_rdp_translate_last_error(rdp_inst, &status, &message); break; /* Forced disconnect (possibly by admin) */ case 0x1: /* ERRINFO_RPC_INITIATED_DISCONNECT */ status = GUAC_PROTOCOL_STATUS_SESSION_CLOSED; message = "Forcibly disconnected."; break; /* The user was logged off (possibly by admin) */ case 0x2: /* ERRINFO_RPC_INITIATED_LOGOFF */ status = GUAC_PROTOCOL_STATUS_SESSION_CLOSED; message = "Logged off."; break; /* The user was idle long enough that the RDP server disconnected */ case 0x3: /* ERRINFO_IDLE_TIMEOUT */ status = GUAC_PROTOCOL_STATUS_SESSION_TIMEOUT; message = "Idle session time limit exceeded."; break; /* The user's session has been active for too long */ case 0x4: /* ERRINFO_LOGON_TIMEOUT */ status = GUAC_PROTOCOL_STATUS_SESSION_CLOSED; message = "Active session time limit exceeded."; break; /* Another user logged on, disconnecting this user */ case 0x5: /* ERRINFO_DISCONNECTED_BY_OTHER_CONNECTION */ status = GUAC_PROTOCOL_STATUS_SESSION_CONFLICT; message = "Disconnected by other connection."; break; /* The RDP server is refusing to service the connection */ case 0x6: /* ERRINFO_OUT_OF_MEMORY */ case 0x7: /* ERRINFO_SERVER_DENIED_CONNECTION */ status = GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE; message = "Server refused connection."; break; /* The user does not have permission to connect */ case 0x9: /* ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES */ status = GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN; message = "Insufficient privileges."; break; /* The user's credentials have expired */ case 0xA: /* ERRINFO_SERVER_FRESH_CREDENTIALS_REQUIRED */ status = GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN; message = "Credentials expired."; break; /* The user manually disconnected using an administrative tool within * the session */ case 0xB: /* ERRINFO_RPC_INITIATED_DISCONNECT_BYUSER */ status = GUAC_PROTOCOL_STATUS_SUCCESS; message = "Manually disconnected."; break; /* The user manually logged off */ case 0xC: /* ERRINFO_LOGOFF_BY_USER */ status = GUAC_PROTOCOL_STATUS_SUCCESS; message = "Manually logged off."; break; /* Unimplemented/unknown disconnect reason code */ default: status = GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR; message = "Upstream error."; } /* Send error code if an error occurred */ if (status != GUAC_PROTOCOL_STATUS_SUCCESS) { guac_protocol_send_error(client->socket, message, status); guac_socket_flush(client->socket); } /* Log human-readable description of disconnect at info level */ guac_client_log(client, GUAC_LOG_INFO, "RDP server closed/refused " "connection: %s", message); /* Log internal disconnect reason code at debug level */ if (error_info) guac_client_log(client, GUAC_LOG_DEBUG, "Disconnect reason " "code: 0x%X.", error_info); /* Abort connection */ guac_client_stop(client); } guacamole-server-1.3.0/src/protocols/rdp/error.h0000644000175100001440000000265513770536337016622 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_ERROR_H #define GUAC_RDP_ERROR_H #include #include /** * Stops the current connection due to the RDP server disconnecting or the * connection attempt failing. If the RDP server or FreeRDP provided a reason * for for the failure/disconnect, that reason will be logged, and an * appropriate error code will be sent to the Guacamole client. * * @param client * The Guacamole client to disconnect. * * @param rdp_inst * The FreeRDP client instance handling the RDP connection that failed. */ void guac_rdp_client_abort(guac_client* client, freerdp* rdp_inst); #endif guacamole-server-1.3.0/src/protocols/rdp/bitmap.h0000644000175100001440000000745713764613616016751 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_BITMAP_H #define GUAC_RDP_BITMAP_H #include "config.h" #include "common/display.h" #include #include #include #include /** * Guacamole-specific rdpBitmap data. */ typedef struct guac_rdp_bitmap { /** * FreeRDP bitmap data - MUST GO FIRST. */ rdpBitmap bitmap; /** * Layer containing cached image data. */ guac_common_display_layer* layer; /** * The number of times a bitmap has been used. */ int used; } guac_rdp_bitmap; /** * Caches the given bitmap immediately, storing its data in a remote Guacamole * buffer. As RDP bitmaps are frequently created, used once, and immediately * destroyed, we defer actual remote-side caching of RDP bitmaps until they are * used at least once. * * @param context * The rdpContext associated with the current RDP session. * * @param bitmap * The bitmap to cache. */ void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap); /** * Initializes the given newly-created rdpBitmap. * * @param context * The rdpContext associated with the current RDP session. * * @param bitmap * The bitmap to initialize. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap); /** * Paints the given rdpBitmap on the primary display surface. Note that this * operation does NOT draw to the "current" surface set by calls to * guac_rdp_bitmap_setsurface(). * * @param context * The rdpContext associated with the current RDP session. * * @param bitmap * The bitmap to paint. This structure will also contain the specifics of * the paint operation to perform, including the destination X/Y * coordinates. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap); /** * Frees any Guacamole-specific data associated with the given rdpBitmap. * * @param context * The rdpContext associated with the current RDP session. * * @param bitmap * The bitmap whose Guacamole-specific data is to be freed. */ void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap); /** * Sets the given rdpBitmap as the drawing surface for future operations or, * if the primary flag is set, resets the current drawing surface to the * primary drawing surface of the remote display. * * @param context * The rdpContext associated with the current RDP session. * * @param bitmap * The rdpBitmap to set as the current drawing surface. This parameter is * only valid if the primary flag is FALSE. * * @param primary * TRUE if the bitmap parameter should be ignored, and the current drawing * surface should be reset to the primary drawing surface of the remote * display, FALSE otherwise. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary); #endif guacamole-server-1.3.0/src/protocols/rdp/download.c0000644000175100001440000001704513764613616017271 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/json.h" #include "download.h" #include "fs.h" #include "ls.h" #include "rdp.h" #include #include #include #include #include #include #include #include #include #include int guac_rdp_download_ack_handler(guac_user* user, guac_stream* stream, char* message, guac_protocol_status status) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_download_status* download_status = (guac_rdp_download_status*) stream->data; /* Get filesystem, return error if no filesystem */ guac_rdp_fs* fs = rdp_client->filesystem; if (fs == NULL) { guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(user->socket); return 0; } /* If successful, read data */ if (status == GUAC_PROTOCOL_STATUS_SUCCESS) { /* Attempt read into buffer */ char buffer[4096]; int bytes_read = guac_rdp_fs_read(fs, download_status->file_id, download_status->offset, buffer, sizeof(buffer)); /* If bytes read, send as blob */ if (bytes_read > 0) { download_status->offset += bytes_read; guac_protocol_send_blob(user->socket, stream, buffer, bytes_read); } /* If EOF, send end */ else if (bytes_read == 0) { guac_protocol_send_end(user->socket, stream); guac_user_free_stream(user, stream); free(download_status); } /* Otherwise, fail stream */ else { guac_user_log(user, GUAC_LOG_ERROR, "Error reading file for download"); guac_protocol_send_end(user->socket, stream); guac_user_free_stream(user, stream); free(download_status); } guac_socket_flush(user->socket); } /* Otherwise, return stream to user */ else guac_user_free_stream(user, stream); return 0; } int guac_rdp_download_get_handler(guac_user* user, guac_object* object, char* name) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Get filesystem, ignore request if no filesystem */ guac_rdp_fs* fs = rdp_client->filesystem; if (fs == NULL) return 0; /* Attempt to open file for reading */ int file_id = guac_rdp_fs_open(fs, name, GENERIC_READ, 0, FILE_OPEN, 0); if (file_id < 0) { guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"", name); return 0; } /* Get opened file */ guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id); if (file == NULL) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Successful open produced bad file_id: %i", __func__, file_id); return 0; } /* If directory, send contents of directory */ if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) { /* Create stream data */ guac_rdp_ls_status* ls_status = malloc(sizeof(guac_rdp_ls_status)); ls_status->fs = fs; ls_status->file_id = file_id; guac_strlcpy(ls_status->directory_name, name, sizeof(ls_status->directory_name)); /* Allocate stream for body */ guac_stream* stream = guac_user_alloc_stream(user); stream->ack_handler = guac_rdp_ls_ack_handler; stream->data = ls_status; /* Init JSON object state */ guac_common_json_begin_object(user, stream, &ls_status->json_state); /* Associate new stream with get request */ guac_protocol_send_body(user->socket, object, stream, GUAC_USER_STREAM_INDEX_MIMETYPE, name); } /* Otherwise, send file contents if downloads are allowed */ else if (!fs->disable_download) { /* Create stream data */ guac_rdp_download_status* download_status = malloc(sizeof(guac_rdp_download_status)); download_status->file_id = file_id; download_status->offset = 0; /* Allocate stream for body */ guac_stream* stream = guac_user_alloc_stream(user); stream->data = download_status; stream->ack_handler = guac_rdp_download_ack_handler; /* Associate new stream with get request */ guac_protocol_send_body(user->socket, object, stream, "application/octet-stream", name); } else guac_client_log(client, GUAC_LOG_INFO, "Unable to download file " "\"%s\", file downloads have been disabled.", name); guac_socket_flush(user->socket); return 0; } void* guac_rdp_download_to_user(guac_user* user, void* data) { /* Do not bother attempting the download if the user has left */ if (user == NULL) return NULL; guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_fs* filesystem = rdp_client->filesystem; /* Ignore download if filesystem has been unloaded */ if (filesystem == NULL) return NULL; /* Ignore download if downloads have been disabled */ if (filesystem->disable_download) { guac_client_log(client, GUAC_LOG_WARNING, "A download attempt has " "been blocked due to downloads being disabled, however it " "should have been blocked at a higher level. This is likely " "a bug."); return NULL; } /* Attempt to open requested file */ char* path = (char*) data; int file_id = guac_rdp_fs_open(filesystem, path, FILE_READ_DATA, 0, FILE_OPEN, 0); /* If file opened successfully, start stream */ if (file_id >= 0) { /* Associate stream with transfer status */ guac_stream* stream = guac_user_alloc_stream(user); guac_rdp_download_status* download_status = malloc(sizeof(guac_rdp_download_status)); stream->data = download_status; stream->ack_handler = guac_rdp_download_ack_handler; download_status->file_id = file_id; download_status->offset = 0; guac_user_log(user, GUAC_LOG_DEBUG, "%s: Initiating download " "of \"%s\"", __func__, path); /* Begin stream */ guac_protocol_send_file(user->socket, stream, "application/octet-stream", guac_rdp_fs_basename(path)); guac_socket_flush(user->socket); /* Download started successfully */ return stream; } /* Download failed */ guac_user_log(user, GUAC_LOG_ERROR, "Unable to download \"%s\"", path); return NULL; } guacamole-server-1.3.0/src/protocols/rdp/argv.c0000644000175100001440000000347013770536337016417 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "rdp.h" #include "settings.h" #include #include #include #include #include #include int guac_rdp_argv_callback(guac_user* user, const char* mimetype, const char* name, const char* value, void* data) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; /* Update username */ if (strcmp(name, GUAC_RDP_ARGV_USERNAME) == 0) { free(settings->username); settings->username = strdup(value); } /* Update password */ else if (strcmp(name, GUAC_RDP_ARGV_PASSWORD) == 0) { free(settings->password); settings->password = strdup(value); } /* Update domain */ else if (strcmp(name, GUAC_RDP_ARGV_DOMAIN) == 0) { free(settings->domain); settings->domain = strdup(value); } return 0; }guacamole-server-1.3.0/src/protocols/rdp/input.h0000644000175100001440000000226613613156714016617 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_INPUT_H #define GUAC_RDP_INPUT_H #include /** * Handler for Guacamole user mouse events. */ guac_user_mouse_handler guac_rdp_user_mouse_handler; /** * Handler for Guacamole user key events. */ guac_user_key_handler guac_rdp_user_key_handler; /** * Handler for Guacamole user size events. */ guac_user_size_handler guac_rdp_user_size_handler; #endif guacamole-server-1.3.0/src/protocols/rdp/beep.c0000644000175100001440000001217513764613616016374 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "beep.h" #include "rdp.h" #include "settings.h" #include #include #include #include #include #include #include /** * Fills the given buffer with signed 8-bit, single-channel PCM at the given * sample rate which will produce a beep of the given frequency. * * @param buffer * The buffer to fill with PCM data. * * @param frequency * The frequency of the beep to generate, in hertz. * * @param rate * The sample rate of the PCM to generate, in samples per second. * * @param buffer_size * The number of bytes of PCM data to write to the given buffer. */ static void guac_rdp_beep_fill_triangle_wave(unsigned char* buffer, int frequency, int rate, int buffer_size) { /* With the distance between each positive/negative peak and zero being the * amplitude, and with the "bounce" between those peaks occurring once * every two periods, the number of distinct states that the triangle wave * function goes through is twice the peak-to-peak amplitude, or four times * the overall amplitude */ const int wave_period = GUAC_RDP_BEEP_AMPLITUDE * 4; /* With the number of distinct states being the wave_period defined above, * the "bounce" point within that period is half the period */ const int wave_bounce_offset = wave_period / 2; for (int position = 0; position < buffer_size; position++) { /* Calculate relative position within the repeating portion of the wave * (the portion with wave_period unique states) */ int wave_position = (position * frequency * wave_period / rate) % wave_period; /* Calculate state of the triangle wave function at the calculated * offset, knowing in advance the relative location that the function * should "bounce" */ *(buffer++) = abs(wave_position - wave_bounce_offset) - GUAC_RDP_BEEP_AMPLITUDE; } } /** * Writes PCM data to the given guac_audio_stream which produces a beep of the * given frequency and duration. The provided guac_audio_stream may be * configured for any sample rate but MUST be configured for single-channel, * 8-bit PCM. * * @param audio * The guac_audio_stream which should receive the PCM data. * * @param frequency * The frequency of the beep, in hertz. * * @param duration * The duration of the beep, in milliseconds. */ static void guac_rdp_beep_write_pcm(guac_audio_stream* audio, int frequency, int duration) { int buffer_size = audio->rate * duration / 1000; unsigned char* buffer = malloc(buffer_size); /* Beep for given frequency/duration using a simple triangle wave */ guac_rdp_beep_fill_triangle_wave(buffer, frequency, audio->rate, buffer_size); guac_audio_stream_write_pcm(audio, buffer, buffer_size); free(buffer); } BOOL guac_rdp_beep_play_sound(rdpContext* context, const PLAY_SOUND_UPDATE* play_sound) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; /* Ignore if audio is not enabled */ if (!settings->audio_enabled) { guac_client_log(client, GUAC_LOG_DEBUG, "Ignoring request to beep " "for %" PRIu32 " millseconds at %" PRIu32 " Hz as audio is " "disabled.", play_sound->duration, play_sound->frequency); return TRUE; } /* Allocate audio stream which sends audio in a format supported by the * connected client(s) */ guac_audio_stream* beep = guac_audio_stream_alloc(client, NULL, GUAC_RDP_BEEP_SAMPLE_RATE, 1, 8); /* Stream availability is not guaranteed */ if (beep == NULL) { guac_client_log(client, GUAC_LOG_DEBUG, "Ignoring request to beep " "for %" PRIu32 " millseconds at %" PRIu32 " Hz as no audio " "stream could be allocated.", play_sound->duration, play_sound->frequency); return TRUE; } /* Limit maximum duration of each beep */ int duration = play_sound->duration; if (duration > GUAC_RDP_BEEP_MAX_DURATION) duration = GUAC_RDP_BEEP_MAX_DURATION; guac_rdp_beep_write_pcm(beep, play_sound->frequency, duration); guac_audio_stream_free(beep); return TRUE; } guacamole-server-1.3.0/src/protocols/rdp/keyboard.h0000644000175100001440000002553713764613616017274 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_KEYBOARD_H #define GUAC_RDP_KEYBOARD_H #include "keymap.h" #include #include /** * The maximum number of distinct keysyms that any particular keyboard may support. */ #define GUAC_RDP_KEYBOARD_MAX_KEYSYMS 1024 /** * The maximum number of unique modifier variations that any particular keysym * may define. For example, on a US English keyboard, an uppercase "A" may be * typed by pressing Shift+A with Caps Lock unset, or by pressing A with Caps * Lock set (two variations). */ #define GUAC_RDP_KEY_MAX_DEFINITIONS 4 /** * All possible sources of RDP key events tracked by guac_rdp_keyboard. */ typedef enum guac_rdp_key_source { /** * The key event was received directly from the Guacamole client via a * "key" instruction. */ GUAC_RDP_KEY_SOURCE_CLIENT = 0, /** * The key event is being synthesized internally within the RDP support. */ GUAC_RDP_KEY_SOURCE_SYNTHETIC = 1 } guac_rdp_key_source; /** * A representation of a single key within the overall local keyboard, * including the definition of that key within the RDP server's keymap and * whether the key is currently pressed locally. */ typedef struct guac_rdp_key { /** * All definitions of this key within the RDP server's keymap (keyboard * layout). Each definition describes which scancode corresponds to this * key from the perspective of the RDP server, as well as which other * scancodes must be pressed/released for this key to have the desired * meaning. */ const guac_rdp_keysym_desc* definitions[GUAC_RDP_KEY_MAX_DEFINITIONS]; /** * The number of definitions within the definitions array. If this key does * not exist within the RDP server's keymap, this will be 0. */ int num_definitions; /** * The definition of this key that is currently pressed. If this key is not * currently pressed, this will be NULL. */ const guac_rdp_keysym_desc* pressed; /** * Whether this key is currently pressed by the user, and is included among * the total tracked by user_pressed_keys within guac_rdp_keyboard. */ int user_pressed; } guac_rdp_key; /** * The current keyboard state of an RDP session. */ typedef struct guac_rdp_keyboard { /** * The guac_client associated with the RDP session whose keyboard state is * being managed by this guac_rdp_keyboard. */ guac_client* client; /** * The local state of all known lock keys, as a bitwise OR of all RDP lock * key flags. Legal flags are KBD_SYNC_SCROLL_LOCK, KBD_SYNC_NUM_LOCK, * KBD_SYNC_CAPS_LOCK, and KBD_SYNC_KANA_LOCK. */ UINT32 lock_flags; /** * Whether the states of remote lock keys (Caps lock, Num lock, etc.) have * been synchronized with local lock key states. */ int synchronized; /** * The number of keys stored within the keys array. */ unsigned int num_keys; /** * The local state of all keys, as well as the necessary information to * translate received keysyms into scancodes or sequences of scancodes for * RDP. The state of each key is updated based on received Guacamole key * events, while the information describing the behavior and scancode * mapping of each key is populated based on an associated keymap. * * Keys within this array are in arbitrary order. */ guac_rdp_key keys[GUAC_RDP_KEYBOARD_MAX_KEYSYMS]; /** * Lookup table into the overall keys array, locating the guac_rdp_key * associated with any particular keysym. If a keysym has no corresponding * guac_rdp_key within the keys array, its entry within this lookuptable * will be NULL. * * The index of the key for a given keysym is determined based on a * simple transformation of the keysym itself. Keysyms between 0x0000 and * 0xFFFF inclusive are mapped to 0x00000 through 0x0FFFF, while keysyms * between 0x1000000 and 0x100FFFF inclusive (keysyms which are derived * from Unicode) are mapped to 0x10000 through 0x1FFFF. */ guac_rdp_key* keys_by_keysym[0x20000]; /** * The total number of keys that the user of the connection is currently * holding down. This value indicates only the client-side keyboard state. * It DOES NOT indicate the number of keys currently pressed within the RDP * server. */ int user_pressed_keys; } guac_rdp_keyboard; /** * Allocates a new guac_rdp_keyboard which manages the keyboard state of the * RDP session associated with the given guac_client. Keyboard events will be * dynamically translated from keysym to RDP scancode according to the provided * keymap. The returned guac_rdp_keyboard must eventually be freed with * guac_rdp_keyboard_free(). * * @param client * The guac_client associated with the RDP session whose keyboard state is * to be managed by the newly-allocated guac_rdp_keyboard. * * @param keymap * The keymap which should be used to translate keyboard events. * * @return * A newly-allocated guac_rdp_keyboard which manages the keyboard state * for the RDP session associated given guac_client. */ guac_rdp_keyboard* guac_rdp_keyboard_alloc(guac_client* client, const guac_rdp_keymap* keymap); /** * Frees all memory allocated for the given guac_rdp_keyboard. The * guac_rdp_keyboard must have been previously allocated via * guac_rdp_keyboard_alloc(). * * @param keyboard * The guac_rdp_keyboard instance which should be freed. */ void guac_rdp_keyboard_free(guac_rdp_keyboard* keyboard); /** * Returns whether the given keysym is defined for the keyboard layout * associated with the given keyboard. * * @param keyboard * The guac_rdp_keyboard instance to check. * * @param keysym * The keysym of the key being checked against the keyboard layout of the * given keyboard. * * @return * Non-zero if the key is explicitly defined within the keyboard layout of * the given keyboard, zero otherwise. */ int guac_rdp_keyboard_is_defined(guac_rdp_keyboard* keyboard, int keysym); /** * Returns whether the key having the given keysym is currently pressed. * * @param keyboard * The guac_rdp_keyboard instance to check. * * @param keysym * The keysym of the key being checked. * * @return * Non-zero if the key is currently pressed, zero otherwise. */ int guac_rdp_keyboard_is_pressed(guac_rdp_keyboard* keyboard, int keysym); /** * Returns the local state of all known modifier keys, as a bitwise OR of the * modifier flags used by the keymaps. Alternative methods of producing the * effect of certain modifiers, such as holding Ctrl+Alt for AltGr when a * dedicated AltGr key is unavailable, are taken into account. * * @see GUAC_RDP_KEYMAP_MODIFIER_SHIFT * @see GUAC_RDP_KEYMAP_MODIFIER_ALTGR * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. * * @return * The local state of all known modifier keys. */ unsigned int guac_rdp_keyboard_get_modifier_flags(guac_rdp_keyboard* keyboard); /** * Updates the local state of the lock keys (such as Caps lock or Num lock), * synchronizing the remote state of those keys if it is expected to differ. * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. * * @param set_flags * The lock key flags which should be set. Legal flags are * KBD_SYNC_SCROLL_LOCK, KBD_SYNC_NUM_LOCK, KBD_SYNC_CAPS_LOCK, and * KBD_SYNC_KANA_LOCK. * * @param clear_flags * The lock key flags which should be cleared. Legal flags are * KBD_SYNC_SCROLL_LOCK, KBD_SYNC_NUM_LOCK, KBD_SYNC_CAPS_LOCK, and * KBD_SYNC_KANA_LOCK. */ void guac_rdp_keyboard_update_locks(guac_rdp_keyboard* keyboard, unsigned int set_flags, unsigned int clear_flags); /** * Updates the local state of the modifier keys (such as Shift or AltGr), * synchronizing the remote state of those keys if it is expected to differ. * Valid modifier flags are defined by keymap.h. * * @see GUAC_RDP_KEYMAP_MODIFIER_SHIFT * @see GUAC_RDP_KEYMAP_MODIFIER_ALTGR * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. * * @param set_flags * The modifier key flags which should be set. * * @param clear_flags * The modifier key flags which should be cleared. */ void guac_rdp_keyboard_update_modifiers(guac_rdp_keyboard* keyboard, unsigned int set_flags, unsigned int clear_flags); /** * Updates the local state of the given keysym, sending the key events required * to replicate that state remotely (on the RDP server). The key events sent * will depend on the current keymap. * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. * * @param keysym * The keysym being pressed or released. * * @param pressed * Zero if the keysym is being released, non-zero otherwise. * * @param source * The source of the key event represented by this call to * guac_rdp_keyboard_update_keysym(). * * @return * Zero if the keys were successfully sent, non-zero otherwise. */ int guac_rdp_keyboard_update_keysym(guac_rdp_keyboard* keyboard, int keysym, int pressed, guac_rdp_key_source source); /** * Releases all currently pressed keys, sending key release events to the RDP * server as necessary. Lock states (Caps Lock, etc.) are not affected. * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. */ void guac_rdp_keyboard_reset(guac_rdp_keyboard* keyboard); /** * Callback which is invoked by FreeRDP when the RDP server reports changes to * keyboard lock status using a Server Set Keyboard Indicators PDU. * * @param context * The rdpContext associated with the current RDP session. * * @param flags * The remote state of all lock keys, as a bitwise OR of all RDP lock key * flags. Legal flags are KBD_SYNC_SCROLL_LOCK, KBD_SYNC_NUM_LOCK, * KBD_SYNC_CAPS_LOCK, and KBD_SYNC_KANA_LOCK. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_keyboard_set_indicators(rdpContext* context, UINT16 flags); #endif guacamole-server-1.3.0/src/protocols/rdp/keymaps/0000755000175100001440000000000013772471160017033 500000000000000guacamole-server-1.3.0/src/protocols/rdp/keymaps/generate.pl0000755000175100001440000002073513764613616021121 00000000000000#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # generate.pl # # Parse .keymap files, producing corresponding .c files that can be included # into the RDP plugin source. # # We need at least Perl 5.8 for Unicode's sake use 5.008; sub keymap_symbol { my $name = shift; $name =~ s/-/_/g; return 'guac_rdp_keymap_' . $name; } # # _generated_keymaps.c # my @keymaps = (); open OUTPUT, ">", "_generated_keymaps.c"; print OUTPUT '#include "config.h"' . "\n" . '#include "keymap.h"' . "\n" . '#include ' . "\n" . '#include ' . "\n" . "\n" . '#include ' . "\n" . "\n"; for my $filename (@ARGV) { my $content = ""; my $parent = ""; my $layout_name = ""; my $freerdp = ""; # Parse file open INPUT, '<', "$filename"; binmode INPUT, ":encoding(utf8)"; while () { chomp; # Comments if (m/^\s*#/) {} # Name elsif ((my $name) = m/^\s*name\s+"(.*)"\s*(?:#.*)?$/) { $layout_name = $name; } # Parent map elsif ((my $name) = m/^\s*parent\s+"(.*)"\s*(?:#.*)?$/) { $parent = keymap_symbol($name); } # FreeRDP equiv elsif ((my $name) = m/^\s*freerdp\s+"(.*)"\s*(?:#.*)?$/) { $freerdp = $name; } # Map elsif ((my $range, my $onto) = m/^\s*map\s+([^~]*)\s+~\s+(".*"|0x[0-9A-Fa-f]+)\s*(?:#.*)?$/) { my @keysyms = (); my @scancodes = (); my $ext_flags = 0; my $set_shift = 0; my $set_altgr = 0; my $set_caps = 0; my $set_num = 0; my $clear_shift = 0; my $clear_altgr = 0; my $clear_caps = 0; my $clear_num = 0; # Parse ranges and options foreach $_ (split(/\s+/, $range)) { # Set option/modifier if ((my $opt) = m/^\+([a-z]+)$/) { if ($opt eq "shift") { $set_shift = 1; } elsif ($opt eq "altgr") { $set_altgr = 1; } elsif ($opt eq "caps") { $set_caps = 1; } elsif ($opt eq "num") { $set_num = 1; } elsif ($opt eq "ext") { $ext_flags = 1; } else { die "$filename: $.: ERROR: " . "Invalid set option\n"; } } # Clear option/modifier elsif ((my $opt) = m/^-([a-z]+)$/) { if ($opt eq "shift") { $clear_shift = 1; } elsif ($opt eq "altgr") { $clear_altgr = 1; } elsif ($opt eq "caps") { $clear_caps = 1; } elsif ($opt eq "num") { $clear_num = 1; } else { die "$filename: $.: ERROR: " . "Invalid clear option\n"; } } # Single scancode elsif ((my $scancode) = m/^(0x[0-9A-Fa-f]+)$/) { $scancodes[++$#scancodes] = hex($scancode); } # Range of scancodes elsif ((my $start, my $end) = m/^(0x[0-9A-Fa-f]+)\.\.(0x[0-9A-Fa-f]+)$/) { for (my $i=hex($start); $i<=hex($end); $i++) { $scancodes[++$#scancodes] = $i; } } # Invalid token else { die "$filename: $.: ERROR: " . "Invalid token\n"; } } # Parse onto if ($onto =~ m/^0x/) { $keysyms[0] = hex($onto); } else { foreach my $char (split('', substr($onto, 1, length($onto)-2))) { my $codepoint = ord($char); if ($codepoint >= 0x0100) { $keysyms[++$#keysyms] = 0x01000000 | $codepoint; } else { $keysyms[++$#keysyms] = $codepoint; } } } # Check mapping if ($#keysyms != $#scancodes) { die "$filename: $.: ERROR: " . "Keysym and scancode range lengths differ\n"; } # Write keysym/scancode pairs for (my $i=0; $i<=$#keysyms; $i++) { $content .= " {" . " .keysym = " . $keysyms[$i] . "," . " .scancode = " . $scancodes[$i]; # Modifiers that must be active $content .= ", .set_modifiers = 0"; $content .= " | GUAC_RDP_KEYMAP_MODIFIER_SHIFT" if $set_shift; $content .= " | GUAC_RDP_KEYMAP_MODIFIER_ALTGR" if $set_altgr; # Modifiers that must be inactive $content .= ", .clear_modifiers = 0"; $content .= " | GUAC_RDP_KEYMAP_MODIFIER_SHIFT" if $clear_shift; $content .= " | GUAC_RDP_KEYMAP_MODIFIER_ALTGR" if $clear_altgr; # Locks that must be set $content .= ", .set_locks = 0"; $content .= " | KBD_SYNC_NUM_LOCK" if $set_num; $content .= " | KBD_SYNC_CAPS_LOCK" if $set_caps; # Locks that must NOT be set $content .= ", .clear_locks = 0"; $content .= " | KBD_SYNC_NUM_LOCK" if $clear_num; $content .= " | KBD_SYNC_CAPS_LOCK" if $clear_caps; # Flags if ($ext_flags) { $content .= ", .flags = KBD_FLAGS_EXTENDED"; } $content .= " },\n"; } } # Invalid token elsif (m/\S/) { die "$filename: $.: ERROR: " . "Invalid token\n"; } } close INPUT; # Header my $sym = keymap_symbol($layout_name); print OUTPUT "\n" . '/* Autogenerated from ' . $filename . ' */' . "\n" . 'static guac_rdp_keysym_desc __' . $sym . '[] = {' . "\n" . $content . ' {0}' . "\n" . '};' . "\n"; # Desc header print OUTPUT "\n" . 'static const guac_rdp_keymap ' . $sym . ' = { ' . "\n"; # Layout name print OUTPUT " .name = \"$layout_name\",\n"; # Parent layout (if any) if ($parent) { print OUTPUT " .parent = &$parent,\n"; } # FreeRDP layout (if any) if ($freerdp) { print OUTPUT " .freerdp_keyboard_layout = $freerdp,\n"; } # Desc footer print OUTPUT ' .mapping = __' . $sym . "\n" . '};' . "\n"; $keymaps[++$#keymaps] = $sym; print STDERR "Added: $layout_name\n"; } print OUTPUT "\n" . 'const guac_rdp_keymap* GUAC_KEYMAPS[] = {' . "\n"; foreach my $keymap (@keymaps) { print OUTPUT " &$keymap,\n"; } print OUTPUT ' NULL' . "\n" . '};' . "\n"; close OUTPUT; guacamole-server-1.3.0/src/protocols/rdp/keymaps/fr_ch_qwertz.keymap0000644000175100001440000000451213764613616022667 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "fr-ch-qwertz" freerdp "KBD_SWISS_FRENCH" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0C ~ "§1234567890'" map -caps -altgr -shift 0x10..0x1A ~ "qwertzuiopè" map -caps -altgr -shift 0x1E..0x28 0x2B ~ "asdfghjkléà$" map -caps -altgr -shift 0x56 0x2C..0x35 ~ "YXCVBNM;:_" map +caps -altgr -shift 0x29 0x02..0x0C ~ "§1234567890'" map +caps -altgr -shift 0x10..0x1A ~ "QWERTZUIOPè" map +caps -altgr -shift 0x1E..0x28 0x2B ~ "ASDFGHJKLéà$" map +caps -altgr -shift 0x56 0x2C..0x35 ~ "yxcvbnm;:_" # # Keys requiring AltGr # map +altgr -shift 0x02..0x04 ~ "¦@#" map +altgr -shift 0x07..0x09 ~ "¬|¢" map +altgr -shift 0x1A 0x1B ~ "[]" map +altgr -shift 0x28 0x2B ~ "{}" map +altgr -shift 0x56 ~ "\" map +altgr -shift 0x12 ~ "€" # # Dead keys # map -altgr -shift 0x1B ~ 0xFE57 # Dead umlaut map +altgr -shift 0x0C ~ 0xFE51 # Dead acute map -altgr -shift 0x0D ~ 0xFE52 # Dead circumflex map -altgr +shift 0x0D ~ 0xFE50 # Dead grave map +altgr -shift 0x0D ~ 0xFE53 # Dead tilde guacamole-server-1.3.0/src/protocols/rdp/keymaps/en_gb_qwerty.keymap0000644000175100001440000000547213764613616022665 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "en-gb-qwerty" freerdp "KBD_UNITED_KINGDOM" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0D ~ "`1234567890-=" map -caps -altgr -shift 0x10..0x1B ~ "qwertyuiop[]" map -caps -altgr -shift 0x1E..0x28 0x2B ~ "asdfghjkl;'#" map -caps -altgr -shift 0x56 0x2C..0x35 ~ "\zxcvbnm,./" map -caps -altgr +shift 0x29 0x02..0x0D ~ "¬!"£$%^&*()_+" map -caps -altgr +shift 0x10..0x1B ~ "QWERTYUIOP{}" map -caps -altgr +shift 0x1E..0x28 0x2B ~ "ASDFGHJKL:@~" map -caps -altgr +shift 0x56 0x2C..0x35 ~ "|ZXCVBNM<>?" map +caps -altgr -shift 0x29 0x02..0x0D ~ "`1234567890-=" map +caps -altgr -shift 0x10..0x1B ~ "QWERTYUIOP[]" map +caps -altgr -shift 0x1E..0x28 0x2B ~ "ASDFGHJKL;'#" map +caps -altgr -shift 0x56 0x2C..0x35 ~ "\ZXCVBNM,./" map +caps -altgr +shift 0x29 0x02..0x0D ~ "¬!"£$%^&*()_+" map +caps -altgr +shift 0x10..0x1B ~ "qwertyuiop{}" map +caps -altgr +shift 0x1E..0x28 0x2B ~ "asdfghjkl:@~" map +caps -altgr +shift 0x56 0x2C..0x35 ~ "|zxcvbnm<>?" # # Keys requiring AltGr (some of which are affected by Caps Lock) # map +altgr -shift 0x29 ~ "¦" map +altgr -shift 0x05 ~ "€" map -caps +altgr -shift 0x12 ~ "é" map -caps +altgr +shift 0x12 ~ "É" map -caps +altgr -shift 0x16 ~ "ú" map -caps +altgr +shift 0x16 ~ "Ú" map -caps +altgr -shift 0x17 ~ "í" map -caps +altgr +shift 0x17 ~ "Í" map -caps +altgr -shift 0x18 ~ "ó" map -caps +altgr +shift 0x18 ~ "Ó" map -caps +altgr -shift 0x1E ~ "á" map -caps +altgr +shift 0x1E ~ "Á" map -caps +altgr -shift 0x2E ~ "ç" map -caps +altgr +shift 0x2E ~ "Ç" map +caps +altgr +shift 0x12 ~ "é" map +caps +altgr -shift 0x12 ~ "É" map +caps +altgr +shift 0x16 ~ "ú" map +caps +altgr -shift 0x16 ~ "Ú" map +caps +altgr +shift 0x17 ~ "í" map +caps +altgr -shift 0x17 ~ "Í" map +caps +altgr +shift 0x18 ~ "ó" map +caps +altgr -shift 0x18 ~ "Ó" map +caps +altgr +shift 0x1E ~ "á" map +caps +altgr -shift 0x1E ~ "Á" map +caps +altgr +shift 0x2E ~ "ç" map +caps +altgr -shift 0x2E ~ "Ç" guacamole-server-1.3.0/src/protocols/rdp/keymaps/failsafe.keymap0000644000175100001440000000151213613156714021733 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "failsafe" freerdp "KBD_US" guacamole-server-1.3.0/src/protocols/rdp/keymaps/es_es_qwerty.keymap0000644000175100001440000000440513764613616022704 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "es-es-qwerty" freerdp "KBD_SPANISH" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0D ~ "º1234567890'¡" map -caps -altgr -shift 0x10..0x19 0x1B ~ "qwertyuiop+" map -caps -altgr -shift 0x1E..0x27 0x2B ~ "asdfghjklñç" map -caps -altgr -shift 0x56 0x2C..0x35 ~ "ZXCVBNM;:_" map +caps -altgr -shift 0x29 0x02..0x0D ~ "º1234567890'¡" map +caps -altgr -shift 0x10..0x19 0x1B ~ "QWERTYUIOP+" map +caps -altgr -shift 0x1E..0x27 0x2B ~ "ASDFGHJKLÑÇ" map +caps -altgr -shift 0x56 0x2C..0x35 ~ "zxcvbnm;:_" # # Keys requiring AltGr # map +altgr -shift 0x29 0x02..0x04 0x07 ~ "\|@#¬" map +altgr -shift 0x12 0x1A 0x1B ~ "€[]" map +altgr -shift 0x28 0x2B ~ "{}" # # Dead keys # map -altgr -shift 0x1A ~ 0xFE50 # Dead grave map -altgr -shift 0x28 ~ 0xFE51 # Dead acute map -altgr +shift 0x1A ~ 0xFE52 # Dead circumflex map +altgr -shift 0x05 ~ 0xFE53 # Dead tilde map -altgr +shift 0x28 ~ 0xFE57 # Dead diaeresis (umlaut) guacamole-server-1.3.0/src/protocols/rdp/keymaps/de_ch_qwertz.keymap0000644000175100001440000000453013764613616022650 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "de-ch-qwertz" freerdp "KBD_SWISS_GERMAN" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0C ~ "§1234567890'" map -caps -altgr -shift 0x10..0x1A ~ "qwertzuiopü" map -caps -altgr -shift 0x1E..0x28 0x2B ~ "asdfghjklöä$" map -caps -altgr -shift 0x56 0x2C..0x35 ~ "YXCVBNM;:_" map +caps -altgr -shift 0x29 0x02..0x0C ~ "§1234567890'" map +caps -altgr -shift 0x10..0x1A ~ "QWERTZUIOPÜ" map +caps -altgr -shift 0x1E..0x28 0x2B ~ "ASDFGHJKLÖÄ$" map +caps -altgr -shift 0x56 0x2C..0x35 ~ "yxcvbnm;:_" # # Keys requiring AltGr # map +altgr -shift 0x02..0x04 ~ "¦@#" map +altgr -shift 0x07..0x09 ~ "¬|¢" map +altgr -shift 0x1A..0x1B ~ "[]" map +altgr -shift 0x28 ~ "{" map +altgr -shift 0x2B ~ "}" map +altgr -shift 0x56 ~ "\" map +altgr -shift 0x12 ~ "€" # # Dead keys # map +altgr -shift 0x0C ~ 0xFE51 # Dead acute map -altgr -shift 0x0D ~ 0xFE52 # Dead circumflex map -altgr +shift 0x0D ~ 0xFE50 # Dead grave map +altgr -shift 0x0D ~ 0xFE53 # Dead tilde map -altgr -shift 0x1B ~ 0xFE57 # Dead umlaut guacamole-server-1.3.0/src/protocols/rdp/keymaps/es_latam_qwerty.keymap0000644000175100001440000000426313764613616023375 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "es-latam-qwerty" freerdp "KBD_LATIN_AMERICAN" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0D ~ "|1234567890'¿" map -caps -altgr -shift 0x10..0x19 0x1B ~ "qwertyuiop+" map -caps -altgr -shift 0x1E..0x28 0x2B ~ "asdfghjklñ{}" map -caps -altgr -shift 0x56 0x2C..0x35 ~ "ZXCVBNM;:_" map +caps -altgr -shift 0x29 0x02..0x0D ~ "|1234567890'¿" map +caps -altgr -shift 0x10..0x19 0x1B ~ "QWERTYUIOP+" map +caps -altgr -shift 0x1E..0x28 0x2B ~ "ASDFGHJKLÑ{}" map +caps -altgr -shift 0x56 0x2C..0x35 ~ "zxcvbnm;:_" # # Keys requiring AltGr # map +altgr -shift 0x29 0x0C ~ "¬\" map +altgr -shift 0x10 ~ "€" map +altgr -shift 0x28 ~ "^" # # Dead keys # map +altgr -shift 0x2B ~ 0xFE50 # Dead grave map -altgr -shift 0x1A ~ 0xFE51 # Dead acute map -altgr +shift 0x1A ~ 0xFE57 # Dead diaeresis (umlaut) map +altgr -shift 0x1B ~ 0xFE53 # Dead tilde guacamole-server-1.3.0/src/protocols/rdp/keymaps/pt_br_qwerty.keymap0000644000175100001440000000457513764613616022724 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "pt-br-qwerty" freerdp "KBD_PORTUGUESE_BRAZILIAN_ABNT2" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0D ~ "'1234567890-=" map -caps -altgr -shift 0x10..0x19 0x1B ~ "qwertyuiop[" map -caps -altgr -shift 0x1E..0x27 0x2B ~ "asdfghjklç]" map -caps -altgr -shift 0x56 0x2C..0x36 ~ "\zxcvbnm,.;/" map -caps -altgr +shift 0x29 0x02..0x06 0x08..0x0D ~ ""!@#$%&*()_+" map -caps -altgr +shift 0x10..0x19 0x1B ~ "QWERTYUIOP{" map -caps -altgr +shift 0x1E..0x27 0x2B ~ "ASDFGHJKLÇ}" map -caps -altgr +shift 0x56 0x2C..0x36 ~ "|ZXCVBNM<>:?" map +caps -altgr -shift 0x29 0x02..0x0D ~ "'1234567890-=" map +caps -altgr -shift 0x10..0x19 0x1B ~ "QWERTYUIOP[" map +caps -altgr -shift 0x1E..0x27 0x2B ~ "ASDFGHJKLÇ]" map +caps -altgr -shift 0x56 0x2C..0x36 ~ "\ZXCVBNM,.;/" map +caps -altgr +shift 0x29 0x02..0x06 0x08..0x0D ~ ""!@#$%&*()_+" map +caps -altgr +shift 0x10..0x19 0x1B ~ "qwertyuiop{" map +caps -altgr +shift 0x1E..0x27 0x2B ~ "asdfghjklç}" map +caps -altgr +shift 0x56 0x2C..0x36 ~ "|zxcvbnm<>:?" # # Keys requiring AltGr # map +altgr -shift 0x02..0x07 0x0D ~ "¹²³£¢¬§" map +altgr -shift 0x10..0x11 ~ "/?" map +altgr -shift 0x12 ~ "°" map +altgr -shift 0x1B ~ "ª" map +altgr -shift 0x2B ~ "º" map +altgr -shift 0x2E ~ "₢" # # Dead keys # map -altgr +shift 0x07 ~ 0xFE57 # Dead diaeresis (umlaut) map -altgr +shift 0x1A ~ 0xFE50 # Dead grave map -altgr -shift 0x1A ~ 0xFE51 # Dead acute map -altgr +shift 0x28 ~ 0xFE52 # Dead circumflex map -altgr -shift 0x28 ~ 0xFE53 # Dead tilde guacamole-server-1.3.0/src/protocols/rdp/keymaps/en_us_qwerty.keymap0000644000175100001440000000327613764613616022724 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "en-us-qwerty" freerdp "KBD_US" map -caps -shift 0x29 0x02..0x0D ~ "`1234567890-=" map -caps -shift 0x10..0x1B 0x2B ~ "qwertyuiop[]\" map -caps -shift 0x1E..0x28 ~ "asdfghjkl;'" map -caps -shift 0x2C..0x35 ~ "zxcvbnm,./" map -caps +shift 0x29 0x02..0x0D ~ "~!@#$%^&*()_+" map -caps +shift 0x10..0x1B 0x2B ~ "QWERTYUIOP{}|" map -caps +shift 0x1E..0x28 ~ "ASDFGHJKL:"" map -caps +shift 0x2C..0x35 ~ "ZXCVBNM<>?" map +caps -shift 0x29 0x02..0x0D ~ "`1234567890-=" map +caps -shift 0x10..0x1B 0x2B ~ "QWERTYUIOP[]\" map +caps -shift 0x1E..0x28 ~ "ASDFGHJKL;'" map +caps -shift 0x2C..0x35 ~ "ZXCVBNM,./" map +caps +shift 0x29 0x02..0x0D ~ "~!@#$%^&*()_+" map +caps +shift 0x10..0x1B 0x2B ~ "qwertyuiop{}|" map +caps +shift 0x1E..0x28 ~ "asdfghjkl:"" map +caps +shift 0x2C..0x35 ~ "zxcvbnm<>?" guacamole-server-1.3.0/src/protocols/rdp/keymaps/sv_se_qwerty.keymap0000644000175100001440000000465613764613616022735 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "sv-se-qwerty" freerdp "KBD_SWEDISH" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0C ~ "§1234567890+" map -caps -altgr -shift 0x10..0x1A ~ "qwertyuiopå" map -caps -altgr -shift 0x1E..0x28 0x2B ~ "asdfghjklöä'" map -caps -altgr -shift 0x56 0x2C..0x35 ~ "ZXCVBNM;:_" map +caps -altgr -shift 0x29 0x02..0x0C ~ "§1234567890+" map +caps -altgr -shift 0x10..0x1A ~ "QWERTYUIOPÅ" map +caps -altgr -shift 0x1E..0x28 0x2B ~ "ASDFGHJKLÖÄ'" map +caps -altgr -shift 0x56 0x2C..0x35 ~ "zxcvbnm;:_" # # Keys requiring AltGr # map +altgr -shift 0x03 ~ "@" map +altgr -shift 0x04 ~ "£" map +altgr -shift 0x05 ~ "$" map +altgr -shift 0x08 ~ "{" map +altgr -shift 0x09 ~ "[" map +altgr -shift 0x0A ~ "]" map +altgr -shift 0x0B ~ "}" map +altgr -shift 0x0C ~ "\" map +altgr -shift 0x12 ~ "€" map +altgr -shift 0x56 ~ "|" map +altgr -shift 0x32 ~ "µ" # # Dead keys # map -altgr -shift 0x0D ~ 0xFE51 # Dead acute map -altgr +shift 0x0D ~ 0xFE50 # Dead grave map -altgr -shift 0x1B ~ 0xFE57 # Dead umlaut map -altgr +shift 0x1B ~ 0xFE52 # Dead circumflex map +altgr -shift 0x1B ~ 0xFE53 # Dead tilde guacamole-server-1.3.0/src/protocols/rdp/keymaps/fr_be_azerty.keymap0000644000175100001440000000510513764613616022644 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "fr-be-azerty" freerdp "KBD_BELGIAN_FRENCH" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0D ~ "²&é"'(§è!çà)_" map -caps -altgr -shift 0x10..0x19 0x1B ~ "azertyuiop$" map -caps -altgr -shift 0x1E..0x28 0x2B ~ "qsdfghjklmùµ" map -caps -altgr -shift 0x56 0x2C..0x35 ~ "WXCVBN?./+" map +caps -altgr -shift 0x29 0x02..0x0D ~ "²1234567890°-" map +caps -altgr -shift 0x10..0x19 0x1B ~ "AZERTYUIOP£" map +caps -altgr -shift 0x1E..0x28 0x2B ~ "QSDFGHJKLM%£" map +caps -altgr -shift 0x56 0x2C..0x35 ~ "wxcvbn,;:=" # # Keys requiring AltGr (unaffected by Caps Lock, but Shift must not be pressed) # map +altgr -shift 0x02..0x04 ~ "|@#" map +altgr -shift 0x0A..0x0B ~ "{}" map +altgr -shift 0x1A..0x1B ~ "[]" map +altgr -shift 0x12 ~ "€" map +altgr -shift 0x56 ~ "\" map +altgr -shift 0x07 ~ "^" # # Dead keys requiring AltGr (unaffected by Caps Lock or Shift) # map +altgr 0x35 ~ 0xFE53 # Dead tilde map +altgr 0x28 ~ 0xFE51 # Dead acute map +altgr 0x2B ~ 0xFE50 # Dead grave # # Dead keys (affected by Caps Lock and Shift) # map -caps -altgr -shift 0x1A ~ 0xFE52 # Dead circumflex map -caps -altgr +shift 0x1A ~ 0xFE57 # Dead umlaut map +caps -altgr -shift 0x1A ~ 0xFE57 # Dead umlaut map +caps -altgr +shift 0x1A ~ 0xFE52 # Dead circumflex guacamole-server-1.3.0/src/protocols/rdp/keymaps/base.keymap0000644000175100001440000000516113764613616021105 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # name "base" # Typeable characters map 0x39 ~ " " # Space map 0x0F ~ 0xff09 # Tab # Control characters map 0x0E ~ 0xff08 # BackSpace map 0x1C ~ 0xff0d # Return map 0x01 ~ 0xff1b # Escape map +ext 0x52 ~ 0xff63 # Insert map +ext 0x53 ~ 0xffff # Delete map +ext 0x47 ~ 0xff50 # Home map +ext 0x4F ~ 0xff57 # End map +ext 0x4B ~ 0xff51 # Left map +ext 0x48 ~ 0xff52 # Up map +ext 0x4D ~ 0xff53 # Right map +ext 0x50 ~ 0xff54 # Down map +ext 0x49 ~ 0xff55 # Page_Up map +ext 0x51 ~ 0xff56 # Page_Down map +ext 0x37 ~ 0xff61 # Print Screen # Locks map 0x45 ~ 0xff7f # Num_Lock map 0x46 ~ 0xff14 # Scroll_Lock map 0x3A ~ 0xffe5 # Caps_Lock # Keypad numerals map -shift +num 0x52 ~ 0xffb0 # KP_0 map -shift +num 0x4F ~ 0xffb1 # KP_1 map -shift +num 0x50 ~ 0xffb2 # KP_2 map -shift +num 0x51 ~ 0xffb3 # KP_3 map -shift +num 0x4B ~ 0xffb4 # KP_4 map -shift +num 0x4C ~ 0xffb5 # KP_5 map -shift +num 0x4D ~ 0xffb6 # KP_6 map -shift +num 0x47 ~ 0xffb7 # KP_7 map -shift +num 0x48 ~ 0xffb8 # KP_8 map -shift +num 0x49 ~ 0xffb9 # KP_9 # Keypad operators map 0x37 ~ 0xffaa # KP_multiply map 0x4e ~ 0xffab # KP_add map 0x4a ~ 0xffad # KP_subtract map 0x53 ~ 0xffae # KP_decimal map +ext 0x35 ~ 0xffaf # KP_divide # F keys map 0x3B ~ 0xffbe # F1 map 0x3C ~ 0xffbf # F2 map 0x3D ~ 0xffc0 # F3 map 0x3E ~ 0xffc1 # F4 map 0x3F ~ 0xffc2 # F5 map 0x40 ~ 0xffc3 # F6 map 0x41 ~ 0xffc4 # F7 map 0x42 ~ 0xffc5 # F8 map 0x43 ~ 0xffc6 # F9 map 0x44 ~ 0xffc7 # F10 map 0x57 ~ 0xffc8 # F11 map 0x58 ~ 0xffc9 # F12 # Modifiers map 0x2A ~ 0xffe1 # Shift_L map 0x36 ~ 0xffe2 # Shift_R map 0x1D ~ 0xffe3 # Control_L map +ext 0x1D ~ 0xffe4 # Control_R map 0x38 ~ 0xffe9 # Alt_L map +ext 0x38 ~ 0xffea # Alt_R map +ext 0x38 ~ 0xfe03 # AltGr map +ext 0x5B ~ 0xffeb # Super_L map +ext 0x5C ~ 0xffec # Super_R map +ext 0x5D ~ 0xff67 # Menu guacamole-server-1.3.0/src/protocols/rdp/keymaps/it_it_qwerty.keymap0000644000175100001440000000411013764613616022707 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "it-it-qwerty" freerdp "KBD_ITALIAN" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0D ~ "\1234567890'ì" map -caps -altgr -shift 0x10..0x1B ~ "qwertyuiopè+" map -caps -altgr -shift 0x1E..0x28 0x2B ~ "asdfghjklòàù" map -caps -altgr -shift 0x56 0x2C..0x35 ~ "ZXCVBNM;:_" map +caps -altgr -shift 0x29 0x02..0x0D ~ "\1234567890'ì" map +caps -altgr -shift 0x10..0x1B ~ "QWERTYUIOPè+" map +caps -altgr -shift 0x1E..0x28 0x2B ~ "ASDFGHJKLòàù" map +caps -altgr -shift 0x56 0x2C..0x35 ~ "zxcvbnm;:_" # # Keys requiring AltGr # map +altgr -shift 0x12 ~ "€" map +altgr -shift 0x1A ~ "[" map +altgr -shift 0x1B ~ "]" map +altgr -shift 0x27 ~ "@" map +altgr -shift 0x28 ~ "#" map +altgr +shift 0x1A ~ "{" map +altgr +shift 0x1B ~ "}" guacamole-server-1.3.0/src/protocols/rdp/keymaps/da_dk_qwerty.keymap0000644000175100001440000000465413764613616022656 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "da-dk-qwerty" freerdp "KBD_DANISH" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0C ~ "§1234567890+" map -caps -altgr -shift 0x10..0x1A ~ "qwertyuiopå" map -caps -altgr -shift 0x1E..0x28 0x2B ~ "asdfghjklæø'" map -caps -altgr -shift 0x56 0x2C..0x35 ~ "ZXCVBNM;:_" map +caps -altgr -shift 0x29 0x02..0x0C ~ "§1234567890+" map +caps -altgr -shift 0x10..0x1A ~ "QWERTYUIOPÅ" map +caps -altgr -shift 0x1E..0x28 0x2B ~ "ASDFGHJKLÆØ'" map +caps -altgr -shift 0x56 0x2C..0x35 ~ "zxcvbnm;:_" # # Keys requiring AltGr # map +altgr -shift 0x03 ~ "@" map +altgr -shift 0x04 ~ "£" map +altgr -shift 0x05 ~ "$" map +altgr -shift 0x08 ~ "{" map +altgr -shift 0x09 ~ "[" map +altgr -shift 0x0A ~ "]" map +altgr -shift 0x0B ~ "}" map +altgr -shift 0x56 ~ "\" map +altgr -shift 0x12 ~ "€" map +altgr -shift 0x0D ~ "|" map +altgr -shift 0x32 ~ "µ" # # Dead keys # map -altgr -shift 0x0D ~ 0xFE51 # Dead acute map -altgr +shift 0x0D ~ 0xFE50 # Dead grave map -altgr -shift 0x1B ~ 0xFE57 # Dead umlaut map -altgr +shift 0x1B ~ 0xFE52 # Dead circumflex map +altgr -shift 0x1B ~ 0xFE53 # Dead tilde guacamole-server-1.3.0/src/protocols/rdp/keymaps/fr_fr_azerty.keymap0000644000175100001440000000444413764613616022672 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "fr-fr-azerty" freerdp "KBD_FRENCH" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0D ~ "²&é"'(-è_çà)=" map -caps -altgr -shift 0x10..0x19 0x1B ~ "azertyuiop$" map -caps -altgr -shift 0x1E..0x28 0x2B ~ "qsdfghjklmù*" map -caps -altgr -shift 0x56 0x2C..0x35 ~ "WXCVBN?./§" map +caps -altgr -shift 0x29 0x02..0x0D ~ "²1234567890°+" map +caps -altgr -shift 0x10..0x19 0x1B ~ "AZERTYUIOP£" map +caps -altgr -shift 0x1E..0x28 0x2B ~ "QSDFGHJKLM%µ" map +caps -altgr -shift 0x56 0x2C..0x35 ~ "wxcvbn,;:!" # # Keys requiring AltGr (unaffected by Caps Lock, but Shift must not be pressed) # map +altgr -shift 0x03..0x0D ~ "~#{[|`\^@]}" map +altgr -shift 0x12 ~ "€" map +altgr -shift 0x1B ~ "¤" # # Dead keys (affected by Caps Lock and Shift) # map -caps -altgr -shift 0x1A ~ 0xFE52 # Dead circumflex map -caps -altgr +shift 0x1A ~ 0xFE57 # Dead umlaut map +caps -altgr -shift 0x1A ~ 0xFE57 # Dead umlaut map +caps -altgr +shift 0x1A ~ 0xFE52 # Dead circumflex guacamole-server-1.3.0/src/protocols/rdp/keymaps/tr_tr_qwerty.keymap0000644000175100001440000000551613764613616022744 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "tr-tr-qwerty" freerdp "KBD_TURKISH_Q" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0D ~ ""1234567890*-" map -caps -altgr -shift 0x10..0x1B ~ "qwertyuıopğü" map -caps -altgr -shift 0x1E..0x28 0x2B ~ "asdfghjklşi," map -caps -altgr -shift 0x56 0x2C..0x35 ~ "ZXCVBNMÖÇ:" map +caps -altgr -shift 0x29 0x02..0x0D ~ ""1234567890*-" map +caps -altgr -shift 0x10..0x1B ~ "QWERTYUIOPĞÜ" map +caps -altgr -shift 0x1E..0x28 0x2B ~ "ASDFGHJKLŞİ," map +caps -altgr -shift 0x56 0x2C..0x35 ~ "zxcvbnmöç:" # # Keys requiring AltGr # map +altgr -shift 0x29 0x02..0x06 ~ "<>£#$½" map +altgr -shift 0x08..0x0D ~ "{[]}\|" map +altgr -shift 0x10 ~ "@" map +altgr -shift 0x12 ~ "€" map +altgr -shift 0x14 ~ "₺" map +altgr -shift 0x1F ~ "ß" map +altgr -shift 0x56 ~ "|" # # Keys requiring AltGr and vary by Shift and Caps Lock # map -caps +altgr -shift 0x17 ~ "i" map -caps +altgr -shift 0x1E ~ "æ" map -caps +altgr +shift 0x17 ~ "İ" map -caps +altgr +shift 0x1E ~ "Æ" map +caps +altgr -shift 0x17 ~ "İ" map +caps +altgr -shift 0x1E ~ "Æ" map +caps +altgr +shift 0x1E ~ "æ" map +caps +altgr +shift 0x17 ~ "i" # # Dead keys # map -altgr +shift 0x04 ~ 0xFE52 # Dead circumflex map +altgr -shift 0x1A ~ 0xFE57 # Dead diaeresis (umlaut) map +altgr -shift 0x1B ~ 0xFE53 # Dead tilde map +altgr -shift 0x27 ~ 0xFE51 # Dead acute map +altgr -shift 0x2B ~ 0xFE50 # Dead grave # END guacamole-server-1.3.0/src/protocols/rdp/keymaps/hu_hu_qwertz.keymap0000644000175100001440000000647513764613616022730 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "hu-hu-qwertz" freerdp "KBD_HUNGARIAN" # # Basic keys # map -caps -altgr -shift 0x29 0x02..0x0D ~ "0123456789öüó" map -caps -altgr -shift 0x10..0x1B ~ "qwertzuıopőú" map -caps -altgr -shift 0x1E..0x28 0x2B ~ "asdfghjkléáű" map -caps -altgr -shift 0x56 0x2C..0x35 ~ "íyxcvbnm,.-" map -caps -altgr +shift 0x29 0x02..0x0D ~ "§'"+!%/=()ÖÜÓ" map -caps -altgr +shift 0x10..0x1B ~ "QWERTZUIOPŐÚ" map -caps -altgr +shift 0x1E..0x28 0x2B ~ "ASDFGHJKLÉÁŰ" map -caps -altgr +shift 0x56 0x2C..0x35 ~ "ÍYXCVBNM?:_" map +caps -altgr -shift 0x29 0x02..0x0D ~ "0123456789ÖÜÓ" map +caps -altgr -shift 0x10..0x1B ~ "QWERTZUIOPŐÚ" map +caps -altgr -shift 0x1E..0x28 0x2B ~ "ASDFGHJKLÉÁŰ" map +caps -altgr -shift 0x56 0x2C..0x35 ~ "ÍYXCVBNM,.-" map +caps -altgr +shift 0x29 0x02..0x0D ~ "§'"+!%/=()öüó" map +caps -altgr +shift 0x10..0x1B ~ "qwertzuiopőú" map +caps -altgr +shift 0x1E..0x28 0x2B ~ "asdfghjkléáű" map +caps -altgr +shift 0x56 0x2C..0x35 ~ "íyxcvbnm?:_" # # Keys requiring AltGr # map +altgr -shift 0x02 ~ "~" map +altgr -shift 0x08 ~ "`" map +altgr -shift 0x10 ~ "\" map +altgr -shift 0x11 ~ "|" map +altgr -shift 0x12 ~ "Ä" map +altgr -shift 0x16 ~ "€" map +altgr -shift 0x17 ~ "Í" map +altgr -shift 0x1A ~ "÷" map +altgr -shift 0x1B ~ "×" map +altgr -shift 0x1E ~ "ä" map +altgr -shift 0x1F ~ "đ" map +altgr -shift 0x20 ~ "Đ" map +altgr -shift 0x21 ~ "[" map +altgr -shift 0x22 ~ "]" map +altgr -shift 0x24 ~ "í" map +altgr -shift 0x25 ~ "ł" map +altgr -shift 0x26 ~ "Ł" map +altgr -shift 0x27 ~ "$" map +altgr -shift 0x28 ~ "ß" map +altgr -shift 0x2B ~ "¤" map +altgr -shift 0x56 ~ "<" map +altgr -shift 0x2C ~ ">" map +altgr -shift 0x2D ~ "#" map +altgr -shift 0x2E ~ "&" map +altgr -shift 0x2F ~ "@" map +altgr -shift 0x30 ~ "{" map +altgr -shift 0x31 ~ "}" map +altgr -shift 0x32 ~ "<" map +altgr -shift 0x33 ~ ";" map +altgr -shift 0x34 ~ ">" map +altgr -shift 0x35 ~ "*" # # Keys requiring AltGr & Shift # # # Dead keys # map +altgr -shift 0x03 ~ 0xFE5A # Dead caron map +altgr -shift 0x04 ~ 0xFE52 # Dead circumflex map +altgr -shift 0x05 ~ 0xFE55 # Dead breve map +altgr -shift 0x06 ~ 0xFE58 # Dead abovering map +altgr -shift 0x07 ~ 0xFE5C # Dead ogonek map +altgr -shift 0x09 ~ 0xFE56 # Dead abovedot map +altgr -shift 0x0A ~ 0xFE51 # Dead acute map +altgr -shift 0x0B ~ 0xFE59 # Dead doubleacute map +altgr -shift 0x0C ~ 0xFE57 # Dead diaeresis map +altgr -shift 0x0D ~ 0xFE5B # Dead cedilla # END guacamole-server-1.3.0/src/protocols/rdp/keymaps/ja_jp_qwerty.keymap0000644000175100001440000000254213613156714022663 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "ja-jp-qwerty" freerdp "KBD_JAPANESE" map -shift 0x02..0x0D 0x7D ~ "1234567890-^\" map -shift 0x10..0x1B ~ "qwertyuiop@[" map -shift 0x1E..0x28 0x2B ~ "asdfghjkl;:]" map -shift 0x2C..0x35 0x73 ~ "zxcvbnm,./\" map +shift 0x02..0x0A 0x0C 0x0D 0x7D ~ "!"#$%&'()=~|" map +shift 0x10..0x1B ~ "QWERTYUIOP`{" map +shift 0x1E..0x28 0x2B ~ "ASDFGHJKL+*}" map +shift 0x2C..0x35 0x73 ~ "ZXCVBNM<>?_" map -shift 0x29 ~ 0xFF28 map -shift 0x29 ~ 0xFF2A map +shift 0x29 ~ 0xFF29 guacamole-server-1.3.0/src/protocols/rdp/keymaps/de_de_qwertz.keymap0000644000175100001440000000463713764613616022656 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # parent "base" name "de-de-qwertz" freerdp "KBD_GERMAN" # # Basic keys # map -caps -altgr -shift 0x02..0x0C ~ "1234567890ß" map -caps -altgr -shift 0x10..0x1B ~ "qwertzuiopü+" map -caps -altgr -shift 0x1E..0x28 0x2B ~ "asdfghjklöä#" map -caps -altgr -shift 0x56 0x2C..0x35 ~ "YXCVBNM;:_" map +caps -altgr -shift 0x02..0x0C ~ "!"§$%&/()=?" map +caps -altgr -shift 0x10..0x1B ~ "QWERTZUIOPÜ*" map +caps -altgr -shift 0x1E..0x28 0x2B ~ "ASDFGHJKLÖÄ'" map +caps -altgr -shift 0x56 0x2C..0x35 ~ "yxcvbnm,._" # # Keys requiring AltGr # map +altgr -shift 0x03 ~ "²" map +altgr -shift 0x04 ~ "³" map +altgr -shift 0x08 ~ "{" map +altgr -shift 0x09 ~ "[" map +altgr -shift 0x0A ~ "]" map +altgr -shift 0x0B ~ "}" map +altgr -shift 0x0C ~ "\" map +altgr -shift 0x10 ~ "@" map +altgr -shift 0x12 ~ "€" map +altgr -shift 0x1B ~ "~" map +altgr -shift 0x56 ~ "|" map +altgr -shift 0x32 ~ "µ" # # Dead keys # map -altgr +shift 0x0D ~ 0xFE50 # Dead grave map -altgr -shift 0x0D ~ 0xFE51 # Dead acute map -altgr -shift 0x29 ~ 0xFE52 # Dead circumflex map +altgr -shift 0x0C ~ 0xFE53 # Dead tilde guacamole-server-1.3.0/src/protocols/rdp/unicode.h0000644000175100001440000000341613613156714017104 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_UNICODE_H #define GUAC_RDP_UNICODE_H /** * Convert the given number of UTF-16 characters to UTF-8 characters. * * @param utf16 * Arbitrary UTF-16 data. * * @param length * The length of the UTF-16 data, in characters. * * @param utf8 * Buffer to which the converted UTF-8 data will be written. * * @param size * The maximum number of bytes available in the UTF-8 buffer. */ void guac_rdp_utf16_to_utf8(const unsigned char* utf16, int length, char* utf8, int size); /** * Convert the given number of UTF-8 characters to UTF-16 characters. * * @param utf8 * Arbitrary UTF-8 data. * * @param length * The length of the UTF-8 data, in characters. * * @param utf16 * Buffer to which the converted UTF-16 data will be written. * * @param size * The maximum number of bytes available in the UTF-16 buffer. */ void guac_rdp_utf8_to_utf16(const unsigned char* utf8, int length, char* utf16, int size); #endif guacamole-server-1.3.0/src/protocols/rdp/keymap.c0000644000175100001440000000226613764613616016747 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "keymap.h" #include const guac_rdp_keymap* guac_rdp_keymap_find(const char* name) { /* For each keymap */ const guac_rdp_keymap** current = GUAC_KEYMAPS; while (*current != NULL) { /* If name matches, done */ if (strcmp((*current)->name, name) == 0) return *current; current++; } /* Failure */ return NULL; } guacamole-server-1.3.0/src/protocols/rdp/gdi.h0000644000175100001440000001377413764613616016237 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_GDI_H #define GUAC_RDP_GDI_H #include "config.h" #include #include /** * Translates a standard RDP ROP3 value into a guac_composite_mode. Valid * ROP3 operations indexes are listed in the RDP protocol specifications: * * http://msdn.microsoft.com/en-us/library/cc241583.aspx * * @param client * The guac_client associated with the current RDP session. * * @param rop3 * The ROP3 operation index to translate. * * @return * The guac_composite_mode that equates to, or most closely approximates, * the given ROP3 operation. */ guac_composite_mode guac_rdp_rop3_transfer_function(guac_client* client, int rop3); /** * Handler for the DstBlt Primary Drawing Order. A DstBlt Primary Drawing Order * paints a rectangle of image data using a raster operation which considers * the destination only. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/87ea30df-59d6-438e-a735-83f0225fbf91 * * @param context * The rdpContext associated with the current RDP session. * * @param dstblt * The DSTBLT update to handle. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt); /** * Handler for the PatBlt Primary Drawing Order. A PatBlt Primary Drawing Order * paints a rectangle of image data, a brush pattern, and a three-way raster * operation which considers the source data, the destination, AND the brush * pattern. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/bd4bf5e7-b988-45f9-8201-3b22cc9aeeb8 * * @param context * The rdpContext associated with the current RDP session. * * @param patblt * The PATBLT update to handle. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt); /** * Handler for the ScrBlt Primary Drawing Order. A ScrBlt Primary Drawing Order * paints a rectangle of image data using a raster operation which considers * the source and destination. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/a4e322b0-cd64-4dfc-8e1a-f24dc0edc99d * * @param context * The rdpContext associated with the current RDP session. * * @param scrblt * The SCRBLT update to handle. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt); /** * Handler for the MemBlt Primary Drawing Order. A MemBlt Primary Drawing Order * paints a rectangle of cached image data from a cached surface to the screen * using a raster operation which considers the source and destination. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/84c2ec2f-f776-405b-9b48-6894a28b1b14 * * @param context * The rdpContext associated with the current RDP session. * * @param memblt * The MEMBLT update to handle. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt); /** * Handler for the OpaqueRect Primary Drawing Order. An OpaqueRect Primary * Drawing Order draws an opaque rectangle of a single solid color. Note that * support for OpaqueRect cannot be claimed without also supporting PatBlt, as * both use the same negotiation order number. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/1eead7aa-ac63-411a-9f8c-b1b227526877 * * @param context * The rdpContext associated with the current RDP session. * * @param opaque_rect * The OPAQUE RECT update to handle. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_opaquerect(rdpContext* context, const OPAQUE_RECT_ORDER* opaque_rect); /** * Handler called prior to calling the handlers for specific updates when * those updates are clipped by a bounding rectangle. This is not a true RDP * update, but is called by FreeRDP before and after any update involving * clipping. * * @param context * The rdpContext associated with the current RDP session. * * @param bounds * The clipping rectangle to set, or NULL to remove any applied clipping * rectangle. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds); /** * Handler called when a paint operation is complete. We don't actually * use this, but FreeRDP requires it. Calling this function has no effect. * * @param context * The rdpContext associated with the current RDP session. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_end_paint(rdpContext* context); /** * Handler called when the desktop dimensions change, either from a * true desktop resize event received by the RDP client, or due to * a revised size given by the server during initial connection * negotiation. * * The new screen size will be made available within the settings associated * with the given context. * * @param context * The rdpContext associated with the current RDP session. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_desktop_resize(rdpContext* context); #endif guacamole-server-1.3.0/src/protocols/rdp/pointer.h0000644000175100001440000000573513764613616017152 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_POINTER_H #define GUAC_RDP_POINTER_H #include "common/display.h" #include #include #include /** * Guacamole-specific rdpPointer data. */ typedef struct guac_rdp_pointer { /** * FreeRDP pointer data - MUST GO FIRST. */ rdpPointer pointer; /** * The display layer containing cached image data. */ guac_common_display_layer* layer; } guac_rdp_pointer; /** * Caches a new pointer, which can later be set via guac_rdp_pointer_set() as * the current mouse pointer. * * @param context * The rdpContext associated with the current RDP session. * * @param pointer * The pointer to cache. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer); /** * Sets the given cached pointer as the current pointer. The given pointer must * have already been initialized through a call to guac_rdp_pointer_new(). * * @param context * The rdpContext associated with the current RDP session. * * @param pointer * The pointer to set as the current mouse pointer. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_pointer_set(rdpContext* context, const rdpPointer* pointer); /** * Frees all Guacamole-related data associated with the given pointer, allowing * FreeRDP to free the rest safely. * * @param context * The rdpContext associated with the current RDP session. * * @param pointer * The pointer to free. */ void guac_rdp_pointer_free(rdpContext* context, rdpPointer* pointer); /** * Hides the current mouse pointer. * * @param context * The rdpContext associated with the current RDP session. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_pointer_set_null(rdpContext* context); /** * Sets the system-dependent (as in dependent on the client system) default * pointer as the current pointer, rather than a cached pointer. * * @param context * The rdpContext associated with the current RDP session. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_pointer_set_default(rdpContext* context); #endif guacamole-server-1.3.0/src/protocols/rdp/plugins/0000755000175100001440000000000013772471160017043 500000000000000guacamole-server-1.3.0/src/protocols/rdp/plugins/generate-entry-wrappers.pl0000755000175100001440000000540213764613616024123 00000000000000#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # generate-entry-wrappers.pl # # Generates C source which defines wrapper functions for FreeRDP plugin entry # points, allowing multiple instances of the same plugin to be loaded despite # otherwise always having the same entry point. # # The resulting source is stored within "_generated_channel_entry_wrappers.c". # use strict; ## ## The maximum number of static channels supported by Guacamole's RDP support. ## my $GUAC_RDP_MAX_CHANNELS; # Extract value of GUAC_RDP_MAX_CHANNELS macro from provided source while (<>) { if ((my $value) = m/^\s*#define\s+GUAC_RDP_MAX_CHANNELS\s+(\d+)\s*$/) { $GUAC_RDP_MAX_CHANNELS = $value; } } open OUTPUT, ">", "_generated_channel_entry_wrappers.c"; # Generate required headers print OUTPUT <<"EOF"; #include "plugins/channels.h" #include #include EOF # Generate wrapper definitions for PVIRTUALCHANNELENTRYEX entry point variant print OUTPUT <<"EOF" for (1..$GUAC_RDP_MAX_CHANNELS); static BOOL guac_rdp_plugin_entry_ex_wrapper$_(PCHANNEL_ENTRY_POINTS_EX entry_points_ex, PVOID init_handle) { return guac_rdp_wrapped_entry_ex[$_ - 1](entry_points_ex, init_handle); } EOF # Generate wrapper definitions for PVIRTUALCHANNELENTRY entry point variant print OUTPUT <<"EOF" for (1..$GUAC_RDP_MAX_CHANNELS); static BOOL guac_rdp_plugin_entry_wrapper$_(PCHANNEL_ENTRY_POINTS entry_points) { return guac_rdp_wrapped_entry[$_ - 1](entry_points); } EOF # Populate lookup table of PVIRTUALCHANNELENTRYEX wrapper functions print OUTPUT "PVIRTUALCHANNELENTRYEX guac_rdp_entry_ex_wrappers[$GUAC_RDP_MAX_CHANNELS] = {\n"; print OUTPUT " guac_rdp_plugin_entry_ex_wrapper$_,\n" for (1..$GUAC_RDP_MAX_CHANNELS); print OUTPUT "};\n"; # Populate lookup table of PVIRTUALCHANNELENTRY wrapper functions print OUTPUT "PVIRTUALCHANNELENTRY guac_rdp_entry_wrappers[$GUAC_RDP_MAX_CHANNELS] = {\n"; print OUTPUT " guac_rdp_plugin_entry_wrapper$_,\n" for (1..$GUAC_RDP_MAX_CHANNELS); print OUTPUT "};\n"; guacamole-server-1.3.0/src/protocols/rdp/plugins/ptr-string.c0000644000175100001440000000216413764613616021250 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "plugins/ptr-string.h" #include void guac_rdp_ptr_to_string(void* data, char* str) { /* Convert pointer to string */ sprintf(str, "%p", data); } void* guac_rdp_string_to_ptr(const char* str) { void* data; /* Convert string to pointer */ sscanf(str, "%p", &data); return data; } guacamole-server-1.3.0/src/protocols/rdp/plugins/channels.c0000644000175100001440000001143713764613616020735 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "plugins/channels.h" #include "rdp.h" #include #include #include #include #include #include #include int guac_rdp_wrapped_entry_ex_count = 0; int guac_rdp_wrapped_entry_count = 0; PVIRTUALCHANNELENTRYEX guac_rdp_wrapped_entry_ex[GUAC_RDP_MAX_CHANNELS] = { NULL }; PVIRTUALCHANNELENTRY guac_rdp_wrapped_entry[GUAC_RDP_MAX_CHANNELS] = { NULL }; PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(guac_client* client, PVIRTUALCHANNELENTRYEX entry_ex) { /* Do not wrap if there is insufficient space to store the wrapped * function */ if (guac_rdp_wrapped_entry_ex_count == GUAC_RDP_MAX_CHANNELS) { guac_client_log(client, GUAC_LOG_WARNING, "Maximum number of static " "channels has been reached. Further FreeRDP plugins and " "channel support may fail to load."); return entry_ex; } /* Generate wrapped version of provided entry point */ PVIRTUALCHANNELENTRYEX wrapper = guac_rdp_entry_ex_wrappers[guac_rdp_wrapped_entry_ex_count]; guac_rdp_wrapped_entry_ex[guac_rdp_wrapped_entry_ex_count] = entry_ex; guac_rdp_wrapped_entry_ex_count++; return wrapper; } PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(guac_client* client, PVIRTUALCHANNELENTRY entry) { /* Do not wrap if there is insufficient space to store the wrapped * function */ if (guac_rdp_wrapped_entry_count == GUAC_RDP_MAX_CHANNELS) { guac_client_log(client, GUAC_LOG_WARNING, "Maximum number of static " "channels has been reached. Further FreeRDP plugins and " "channel support may fail to load."); return entry; } /* Generate wrapped version of provided entry point */ PVIRTUALCHANNELENTRY wrapper = guac_rdp_entry_wrappers[guac_rdp_wrapped_entry_count]; guac_rdp_wrapped_entry[guac_rdp_wrapped_entry_count] = entry; guac_rdp_wrapped_entry_count++; return wrapper; } int guac_freerdp_channels_load_plugin(rdpContext* context, const char* name, void* data) { guac_client* client = ((rdp_freerdp_context*) context)->client; /* Load plugin using "ex" version of the channel plugin entry point, if it exists */ PVIRTUALCHANNELENTRYEX entry_ex = (PVIRTUALCHANNELENTRYEX) (void*) freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC | FREERDP_ADDIN_CHANNEL_ENTRYEX); if (entry_ex != NULL) { entry_ex = guac_rdp_plugin_wrap_entry_ex(client, entry_ex); return freerdp_channels_client_load_ex(context->channels, context->settings, entry_ex, data); } /* Lacking the "ex" entry point, attempt to load using the non-ex version */ PVIRTUALCHANNELENTRY entry = freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC); if (entry != NULL) { entry = guac_rdp_plugin_wrap_entry(client, entry); return freerdp_channels_client_load(context->channels, context->settings, entry, data); } /* The plugin does not exist / cannot be loaded */ return 1; } void guac_freerdp_dynamic_channel_collection_add(rdpSettings* settings, const char* name, ...) { va_list args; ADDIN_ARGV* freerdp_args = malloc(sizeof(ADDIN_ARGV)); va_start(args, name); /* Count number of arguments (excluding terminating NULL) */ freerdp_args->argc = 1; while (va_arg(args, char*) != NULL) freerdp_args->argc++; /* Reset va_list */ va_end(args); va_start(args, name); /* Copy argument values into DVC entry */ freerdp_args->argv = malloc(sizeof(char*) * freerdp_args->argc); freerdp_args->argv[0] = strdup(name); int i; for (i = 1; i < freerdp_args->argc; i++) freerdp_args->argv[i] = strdup(va_arg(args, char*)); va_end(args); /* Register plugin with FreeRDP */ settings->SupportDynamicChannels = TRUE; freerdp_dynamic_channel_collection_add(settings, freerdp_args); } guacamole-server-1.3.0/src/protocols/rdp/plugins/channels.h0000644000175100001440000002062613764613616020742 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_PLUGINS_CHANNELS_H #define GUAC_RDP_PLUGINS_CHANNELS_H #include #include #include #include #include /** * The maximum number of static channels supported by Guacamole's RDP support. * This value should be given a value which is at least the value of FreeRDP's * CHANNEL_MAX_COUNT. * * NOTE: The value of this macro must be specified statically (not as a * reference to CHANNEL_MAX_COUNT), as its value is extracted and used by the * entry point wrapper code generator (generate-entry-wrappers.pl). */ #define GUAC_RDP_MAX_CHANNELS 64 /* Validate GUAC_RDP_MAX_CHANNELS is sane at compile time */ #if GUAC_RDP_MAX_CHANNELS < CHANNEL_MAX_COUNT #error "GUAC_RDP_MAX_CHANNELS must not be less than CHANNEL_MAX_COUNT" #endif /** Loads the FreeRDP plugin having the given name. With the exception that * this function requires the rdpContext rather than rdpChannels and * rdpSettings, this function is essentially a drop-in replacement for * freerdp_channels_load_plugin() which additionally loads plugins implementing * the PVIRTUALCHANNELENTRYEX version of the channel plugin entry point. The * freerdp_channels_load_plugin() function which is part of FreeRDP can load * only plugins which implement the PVIRTUALCHANNELENTRY version of the entry * point. * * This MUST be called within the PreConnect callback of the freerdp instance * for the referenced plugin to be loaded correctly. * * @param context * The rdpContext associated with the active RDP session. * * @param name * The name of the plugin to load. If the plugin is not statically built * into FreeRDP, this name will determine the filename of the library to be * loaded dynamically. For a plugin named "NAME", the library called * "libNAME-client" will be loaded from the "freerdp2" subdirectory of the * main directory containing the FreeRDP libraries. * * @param data * Arbitrary data to be passed to the plugin entry point. For most plugins * which are built into FreeRDP, this will be another reference to the * rdpSettings struct. The source of the relevant plugin must be consulted * to determine the proper value to pass here. * * @return * Zero if the plugin was loaded successfully, non-zero if the plugin could * not be loaded. */ int guac_freerdp_channels_load_plugin(rdpContext* context, const char* name, void* data); /** * Schedules loading of the FreeRDP dynamic virtual channel plugin having the * given name. This function is essentially a wrapper for * freerdp_dynamic_channel_collection_add() which additionally takes care of * housekeeping tasks which would otherwise need to be performed manually: * * - The ADDIN_ARGV structure used to pass arguments to dynamic virtual * channel plugins is automatically allocated and populated with any given * arguments. * - The SupportDynamicChannels member of the rdpSettings structure is * automatically set to TRUE. * * The "drdynvc" plugin must still eventually be loaded for this function to * have any effect, as it is the "drdynvc" plugin which processes the * collection this function manipulates. * * This MUST be called within the PreConnect callback of the freerdp instance * and the "drdynvc" plugin MUST be loaded at some point after this function is * called for the referenced dynamic channel plugin to be loaded correctly. * * @param settings * The rdpSettings structure associated with the FreeRDP instance, already * populated with any settings applicable to the plugin being loaded. * * @param name * The name of the plugin to load. If the plugin is not statically built * into FreeRDP, this name will determine the filename of the library to be * loaded dynamically. For a plugin named "NAME", the library called * "libNAME-client" will be loaded from the "freerdp2" subdirectory of the * main directory containing the FreeRDP libraries. * * @param ... * Arbitrary arguments to be passed to the plugin entry point. For most * plugins which are built into FreeRDP, this will be another reference to * the rdpSettings struct or NULL. The source of the relevant plugin must * be consulted to determine the proper value(s) to pass here. */ void guac_freerdp_dynamic_channel_collection_add(rdpSettings* settings, const char* name, ...); /** * The number of wrapped channel entry points currently stored within * guac_rdp_wrapped_entry_ex. */ extern int guac_rdp_wrapped_entry_ex_count; /** * All currently wrapped entry points that use the PVIRTUALCHANNELENTRYEX * variant. */ extern PVIRTUALCHANNELENTRYEX guac_rdp_wrapped_entry_ex[GUAC_RDP_MAX_CHANNELS]; /** * Lookup table of wrapper functions for PVIRTUALCHANNELENTRYEX entry points. * Each function within this array is generated at compile time by the entry * point wrapper code generator (generate-entry-wrappers.pl) and automatically * invokes the corresponding wrapped entry point stored within * guac_rdp_wrapped_entry_ex. */ extern PVIRTUALCHANNELENTRYEX guac_rdp_entry_ex_wrappers[GUAC_RDP_MAX_CHANNELS]; /** * Wraps the provided entry point function, returning a different entry point * which simply invokes the original. As long as this function is not invoked * more than GUAC_RDP_MAX_CHANNELS times, each returned entry point will be * unique, even if the provided entry point is not. As FreeRDP will refuse to * load a plugin if its entry point is already loaded, this allows a single * FreeRDP plugin to be loaded multiple times. * * @param client * The guac_client associated with the relevant RDP session. * * @param entry_ex * The entry point function to wrap. * * @return * A wrapped version of the provided entry point, or the unwrapped entry * point if there is insufficient space remaining within * guac_rdp_entry_ex_wrappers to wrap the entry point. */ PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(guac_client* client, PVIRTUALCHANNELENTRYEX entry_ex); /** * The number of wrapped channel entry points currently stored within * guac_rdp_wrapped_entry. */ extern int guac_rdp_wrapped_entry_count; /** * All currently wrapped entry points that use the PVIRTUALCHANNELENTRY * variant. */ extern PVIRTUALCHANNELENTRY guac_rdp_wrapped_entry[GUAC_RDP_MAX_CHANNELS]; /** * Lookup table of wrapper functions for PVIRTUALCHANNELENTRY entry points. * Each function within this array is generated at compile time by the entry * point wrapper code generator (generate-entry-wrappers.pl) and automatically * invokes the corresponding wrapped entry point stored within * guac_rdp_wrapped_entry. */ extern PVIRTUALCHANNELENTRY guac_rdp_entry_wrappers[GUAC_RDP_MAX_CHANNELS]; /** * Wraps the provided entry point function, returning a different entry point * which simply invokes the original. As long as this function is not invoked * more than GUAC_RDP_MAX_CHANNELS times, each returned entry point will be * unique, even if the provided entry point is not. As FreeRDP will refuse to * load a plugin if its entry point is already loaded, this allows a single * FreeRDP plugin to be loaded multiple times. * * @param client * The guac_client associated with the relevant RDP session. * * @param entry * The entry point function to wrap. * * @return * A wrapped version of the provided entry point, or the unwrapped entry * point if there is insufficient space remaining within * guac_rdp_entry_wrappers to wrap the entry point. */ PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(guac_client* client, PVIRTUALCHANNELENTRY entry); #endif guacamole-server-1.3.0/src/protocols/rdp/plugins/ptr-string.h0000644000175100001440000000410213764613616021247 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_PLUGINS_PTR_STRING_H #define GUAC_RDP_PLUGINS_PTR_STRING_H #include /** * The maximum number of bytes required to represent a pointer printed using * printf()'s "%p". This will be the size of the hex prefix ("0x"), null * terminator, plus two bytes for every byte required by a pointer. */ #define GUAC_RDP_PTR_STRING_LENGTH (sizeof("0x") + (sizeof(void*) * 2)) /** * Converts the given string back into a void pointer. The string MUST have * been produced via guac_rdp_ptr_to_string(). * * @param str * The string to convert back to a pointer. * * @return * The pointer value of the given string, as originally passed to * guac_rdp_ptr_to_string(). */ void* guac_rdp_string_to_ptr(const char* str); /** * Converts a void pointer into a string representation, safe for use with * parts of the FreeRDP API which provide only for passing arbitrary strings, * despite being within the same memory area. * * @param data * The void pointer to convert to a string. * * @param str * The buffer in which the string representation of the given void pointer * should be stored. This buffer must have at least * GUAC_RDP_PTR_STRING_LENGTH bytes available. */ void guac_rdp_ptr_to_string(void* data, char* str); #endif guacamole-server-1.3.0/src/protocols/rdp/plugins/guac-common-svc/0000755000175100001440000000000013772471160022041 500000000000000guacamole-server-1.3.0/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c0000644000175100001440000002770213770536337025141 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/common-svc.h" #include #include #include #include #include #include /** * Event handler for events which deal with data transmitted over an open SVC, * including receipt of inbound data and completion of outbound writes. * * The FreeRDP requirements for this function follow those of the * VirtualChannelOpenEventEx callback defined within Microsoft's RDP API: * * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514754%28v%3dmsdn.10%29 * * @param user_param * The pointer to arbitrary data originally passed via the first parameter * of the pVirtualChannelInitEx() function call when the associated channel * was initialized. The pVirtualChannelInitEx() function is exposed within * the channel entry points structure. * * @param open_handle * The handle which identifies the channel itself, typically referred to * within the FreeRDP source as OpenHandle. * * @param event * An integer representing the event that should be handled. This will be * either CHANNEL_EVENT_DATA_RECEIVED, CHANNEL_EVENT_WRITE_CANCELLED, or * CHANNEL_EVENT_WRITE_COMPLETE. * * @param data * The data received, for CHANNEL_EVENT_DATA_RECEIVED events, and the value * passed as user data to pVirtualChannelWriteEx() for * CHANNEL_EVENT_WRITE_* events (note that user data for * pVirtualChannelWriteEx() as implemented by FreeRDP MUST either be NULL * or a wStream containing the data written). * * @param data_length * The number of bytes of event-specific data. * * @param total_length * The total number of bytes expected to be received from the RDP server * due to this single write (from the server's perspective). Each write may * actually be split into multiple chunks, thus resulting in multiple * receive events for the same logical block of data. The relationship * between chunks is indicated with the CHANNEL_FLAG_FIRST and * CHANNEL_FLAG_LAST flags. * * @param data_flags * The result of a bitwise OR of the CHANNEL_FLAG_* flags which apply to * the data received. This value is relevant only to * CHANNEL_EVENT_DATA_RECEIVED events. Valid flags are CHANNEL_FLAG_FIRST, * CHANNEL_FLAG_LAST, and CHANNEL_FLAG_ONLY. The flag CHANNEL_FLAG_MIDDLE * is not itself a flag, but the absence of both CHANNEL_FLAG_FIRST and * CHANNEL_FLAG_LAST. */ static VOID guac_rdp_common_svc_handle_open_event(LPVOID user_param, DWORD open_handle, UINT event, LPVOID data, UINT32 data_length, UINT32 total_length, UINT32 data_flags) { #ifndef FREERDP_SVC_CORE_FREES_WSTREAM /* Free stream data after send is complete */ if ((event == CHANNEL_EVENT_WRITE_CANCELLED || event == CHANNEL_EVENT_WRITE_COMPLETE) && data != NULL) { Stream_Free((wStream*) data, TRUE); return; } #endif /* Ignore all events except for received data */ if (event != CHANNEL_EVENT_DATA_RECEIVED) return; guac_rdp_common_svc* svc = (guac_rdp_common_svc*) user_param; /* Validate relevant handle matches that of SVC */ if (open_handle != svc->_open_handle) { guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " "received from within the remote desktop session for SVC " "\"%s\" are being dropped because the relevant open handle " "(0x%X) does not match the open handle of the SVC (0x%X).", data_length, svc->name, open_handle, svc->_open_handle); return; } /* If receiving first chunk, allocate sufficient space for all remaining * chunks */ if (data_flags & CHANNEL_FLAG_FIRST) { /* Limit maximum received size */ if (total_length > GUAC_SVC_MAX_ASSEMBLED_LENGTH) { guac_client_log(svc->client, GUAC_LOG_WARNING, "RDP server has " "requested to send a sequence of %i bytes, but this " "exceeds the maximum buffer space of %i bytes. Received " "data may be truncated.", total_length, GUAC_SVC_MAX_ASSEMBLED_LENGTH); total_length = GUAC_SVC_MAX_ASSEMBLED_LENGTH; } svc->_input_stream = Stream_New(NULL, total_length); } /* leave if we don't have a stream. */ if (svc->_input_stream == NULL) return; /* Add chunk to buffer only if sufficient space remains */ if (Stream_EnsureRemainingCapacity(svc->_input_stream, data_length)) Stream_Write(svc->_input_stream, data, data_length); else guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " "received from within the remote desktop session for SVC " "\"%s\" are being dropped because the maximum available " "space for received data has been exceeded.", data_length, svc->name); /* Fire event once last chunk has been received */ if (data_flags & CHANNEL_FLAG_LAST) { Stream_SealLength(svc->_input_stream); Stream_SetPosition(svc->_input_stream, 0); /* Handle channel-specific data receipt tasks, if any */ if (svc->_receive_handler) svc->_receive_handler(svc, svc->_input_stream); Stream_Free(svc->_input_stream, TRUE); svc->_input_stream = NULL; } } /** * Processes a CHANNEL_EVENT_CONNECTED event, completing the * connection/initialization process of the channel. * * @param rdpsnd * The guac_rdp_common_svc structure representing the channel. */ static void guac_rdp_common_svc_process_connect(guac_rdp_common_svc* svc) { /* Open FreeRDP side of connected channel */ UINT32 open_status = svc->_entry_points.pVirtualChannelOpenEx(svc->_init_handle, &svc->_open_handle, svc->_channel_def.name, guac_rdp_common_svc_handle_open_event); /* Warn if the channel cannot be opened after all */ if (open_status != CHANNEL_RC_OK) { guac_client_log(svc->client, GUAC_LOG_WARNING, "SVC \"%s\" could not " "be opened: %s (error %i)", svc->name, WTSErrorToString(open_status), open_status); return; } /* Handle channel-specific connect tasks, if any */ if (svc->_connect_handler) svc->_connect_handler(svc); /* Channel is now ready */ guac_client_log(svc->client, GUAC_LOG_DEBUG, "SVC \"%s\" connected.", svc->name); } /** * Processes a CHANNEL_EVENT_TERMINATED event, freeing all resources associated * with the channel. * * @param svc * The guac_rdp_common_svc structure representing the channel. */ static void guac_rdp_common_svc_process_terminate(guac_rdp_common_svc* svc) { /* Handle channel-specific termination tasks, if any */ if (svc->_terminate_handler) svc->_terminate_handler(svc); guac_client_log(svc->client, GUAC_LOG_DEBUG, "SVC \"%s\" disconnected.", svc->name); free(svc); } /** * Event handler for events which deal with the overall lifecycle of an SVC. * This specific implementation of the event handler currently handles only * CHANNEL_EVENT_CONNECTED and CHANNEL_EVENT_TERMINATED events, delegating * actual handling of those events to guac_rdp_common_svc_process_connect() and * guac_rdp_common_svc_process_terminate() respectively. * * The FreeRDP requirements for this function follow those of the * VirtualChannelInitEventEx callback defined within Microsoft's RDP API: * * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514727%28v%3dmsdn.10%29 * * @param user_param * The pointer to arbitrary data originally passed via the first parameter * of the pVirtualChannelInitEx() function call when the associated channel * was initialized. The pVirtualChannelInitEx() function is exposed within * the channel entry points structure. * * @param init_handle * The handle which identifies the client connection, typically referred to * within the FreeRDP source as pInitHandle. * * @param event * An integer representing the event that should be handled. This will be * either CHANNEL_EVENT_CONNECTED, CHANNEL_EVENT_DISCONNECTED, * CHANNEL_EVENT_INITIALIZED, CHANNEL_EVENT_TERMINATED, or * CHANNEL_EVENT_V1_CONNECTED. * * @param data * NULL in all cases except the CHANNEL_EVENT_CONNECTED event, in which * case this is a null-terminated string containing the name of the server. * * @param data_length * The number of bytes of data, if any. */ static VOID guac_rdp_common_svc_handle_init_event(LPVOID user_param, LPVOID init_handle, UINT event, LPVOID data, UINT data_length) { guac_rdp_common_svc* svc = (guac_rdp_common_svc*) user_param; /* Validate relevant handle matches that of SVC */ if (init_handle != svc->_init_handle) { guac_client_log(svc->client, GUAC_LOG_WARNING, "An init event (#%i) " "for SVC \"%s\" has been dropped because the relevant init " "handle (0x%X) does not match the init handle of the SVC " "(0x%X).", event, svc->name, init_handle, svc->_init_handle); return; } switch (event) { /* The remote desktop side of the SVC has been connected */ case CHANNEL_EVENT_CONNECTED: guac_rdp_common_svc_process_connect(svc); break; /* The channel has disconnected and now must be cleaned up */ case CHANNEL_EVENT_TERMINATED: guac_rdp_common_svc_process_terminate(svc); break; } } /** * Entry point for FreeRDP plugins. This function is automatically invoked when * the plugin is loaded. * * @param entry_points * Functions and data specific to the FreeRDP side of the virtual channel * and plugin. This structure must be copied within implementation-specific * storage such that the functions it references can be invoked when * needed. * * @param init_handle * The handle which identifies the client connection, typically referred to * within the FreeRDP source as pInitHandle. This handle is also provided * to the channel init event handler. The handle must eventually be used * within the channel open event handler to obtain a handle to the channel * itself. * * @return * TRUE if the plugin has initialized successfully, FALSE otherwise. */ BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX entry_points, PVOID init_handle) { CHANNEL_ENTRY_POINTS_FREERDP_EX* entry_points_ex = (CHANNEL_ENTRY_POINTS_FREERDP_EX*) entry_points; /* Get structure representing the Guacamole side of the SVC from plugin * parameters */ guac_rdp_common_svc* svc = (guac_rdp_common_svc*) entry_points_ex->pExtendedData; /* Copy FreeRDP data into SVC structure for future reference */ svc->_entry_points = *entry_points_ex; svc->_init_handle = init_handle; /* Complete initialization */ if (svc->_entry_points.pVirtualChannelInitEx(svc, NULL, init_handle, &svc->_channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, guac_rdp_common_svc_handle_init_event) != CHANNEL_RC_OK) { return FALSE; } return TRUE; } guacamole-server-1.3.0/src/protocols/rdp/plugins/guacai/0000755000175100001440000000000013772471160020274 500000000000000guacamole-server-1.3.0/src/protocols/rdp/plugins/guacai/guacai.c0000644000175100001440000002400713764613616021621 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/audio-input/audio-buffer.h" #include "plugins/guacai/guacai.h" #include "plugins/guacai/guacai-messages.h" #include "plugins/ptr-string.h" #include "rdp.h" #include #include #include #include #include #include #include /** * Handles the given data received along the AUDIO_INPUT channel of the RDP * connection associated with the given guac_client. This handler is * API-independent and is invoked by API-dependent guac_rdp_ai_data callback * specific to the version of FreeRDP installed. * * @param client * The guac_client associated with RDP connection having the AUDIO_INPUT * connection along which the given data was received. * * @param channel * A reference to the IWTSVirtualChannel instance along which responses * should be sent. * * @param stream * The data received along the AUDIO_INPUT channel. */ static void guac_rdp_ai_handle_data(guac_client* client, IWTSVirtualChannel* channel, wStream* stream) { /* Verify we have at least 1 byte in the stream (UINT8) */ if (Stream_GetRemainingLength(stream) < 1) { guac_client_log(client, GUAC_LOG_WARNING, "Audio input PDU header does " "not contain the expected number of bytes. Audio input " "redirection may not work as expected."); return; } /* Read message ID from received PDU */ BYTE message_id; Stream_Read_UINT8(stream, message_id); /* Invoke appropriate message processor based on ID */ switch (message_id) { /* Version PDU */ case GUAC_RDP_MSG_SNDIN_VERSION: guac_rdp_ai_process_version(client, channel, stream); break; /* Sound Formats PDU */ case GUAC_RDP_MSG_SNDIN_FORMATS: guac_rdp_ai_process_formats(client, channel, stream); break; /* Open PDU */ case GUAC_RDP_MSG_SNDIN_OPEN: guac_rdp_ai_process_open(client, channel, stream); break; /* Format Change PDU */ case GUAC_RDP_MSG_SNDIN_FORMATCHANGE: guac_rdp_ai_process_formatchange(client, channel, stream); break; /* Log unknown message IDs */ default: guac_client_log(client, GUAC_LOG_DEBUG, "Unknown AUDIO_INPUT message ID: 0x%x", message_id); } } /** * Callback which is invoked when data is received along a connection to the * AUDIO_INPUT plugin. * * @param channel_callback * The IWTSVirtualChannelCallback structure to which this callback was * originally assigned. * * @param stream * The data received. * * @return * Always zero. */ static UINT guac_rdp_ai_data(IWTSVirtualChannelCallback* channel_callback, wStream* stream) { guac_rdp_ai_channel_callback* ai_channel_callback = (guac_rdp_ai_channel_callback*) channel_callback; IWTSVirtualChannel* channel = ai_channel_callback->channel; /* Invoke generalized (API-independent) data handler */ guac_rdp_ai_handle_data(ai_channel_callback->client, channel, stream); return CHANNEL_RC_OK; } /** * Callback which is invoked when a connection to the AUDIO_INPUT plugin is * closed. * * @param channel_callback * The IWTSVirtualChannelCallback structure to which this callback was * originally assigned. * * @return * Always zero. */ static UINT guac_rdp_ai_close(IWTSVirtualChannelCallback* channel_callback) { guac_rdp_ai_channel_callback* ai_channel_callback = (guac_rdp_ai_channel_callback*) channel_callback; guac_client* client = ai_channel_callback->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_audio_buffer* audio_buffer = rdp_client->audio_input; /* Log closure of AUDIO_INPUT channel */ guac_client_log(client, GUAC_LOG_DEBUG, "AUDIO_INPUT channel connection closed"); guac_rdp_audio_buffer_end(audio_buffer); free(ai_channel_callback); return CHANNEL_RC_OK; } /** * Callback which is invoked when a new connection is received by the * AUDIO_INPUT plugin. Additional callbacks required to handle received data * and closure of the connection must be installed at this point. * * @param listener_callback * The IWTSListenerCallback structure associated with the AUDIO_INPUT * plugin receiving the new connection. * * @param channel * A reference to the IWTSVirtualChannel instance along which data related * to the AUDIO_INPUT channel should be sent. * * @param data * Absolutely no idea. According to Microsoft's documentation for the * function prototype on which FreeRDP's API appears to be based: "This * parameter is not implemented and is reserved for future use." * * @param accept * Pointer to a flag which should be set to TRUE if the connection should * be accepted or FALSE otherwise. In the case of FreeRDP, this value * defaults to TRUE, and TRUE absolutely MUST be identically 1 or it will * be interpreted as FALSE. * * @param channel_callback * A pointer to the location that the new IWTSVirtualChannelCallback * structure containing the required callbacks should be assigned. * * @return * Always zero. */ static UINT guac_rdp_ai_new_connection( IWTSListenerCallback* listener_callback, IWTSVirtualChannel* channel, BYTE* data, int* accept, IWTSVirtualChannelCallback** channel_callback) { guac_rdp_ai_listener_callback* ai_listener_callback = (guac_rdp_ai_listener_callback*) listener_callback; /* Log new AUDIO_INPUT connection */ guac_client_log(ai_listener_callback->client, GUAC_LOG_DEBUG, "New AUDIO_INPUT channel connection"); /* Allocate new channel callback */ guac_rdp_ai_channel_callback* ai_channel_callback = calloc(1, sizeof(guac_rdp_ai_channel_callback)); /* Init listener callback with data from plugin */ ai_channel_callback->client = ai_listener_callback->client; ai_channel_callback->channel = channel; ai_channel_callback->parent.OnDataReceived = guac_rdp_ai_data; ai_channel_callback->parent.OnClose = guac_rdp_ai_close; /* Return callback through pointer */ *channel_callback = (IWTSVirtualChannelCallback*) ai_channel_callback; return CHANNEL_RC_OK; } /** * Callback which is invoked when the AUDIO_INPUT plugin has been loaded and * needs to be initialized with other callbacks and data. * * @param plugin * The AUDIO_INPUT plugin that needs to be initialied. * * @param manager * The IWTSVirtualChannelManager instance with which the AUDIO_INPUT plugin * must be registered. * * @return * Always zero. */ static UINT guac_rdp_ai_initialize(IWTSPlugin* plugin, IWTSVirtualChannelManager* manager) { /* Allocate new listener callback */ guac_rdp_ai_listener_callback* ai_listener_callback = calloc(1, sizeof(guac_rdp_ai_listener_callback)); /* Ensure listener callback is freed when plugin is terminated */ guac_rdp_ai_plugin* ai_plugin = (guac_rdp_ai_plugin*) plugin; ai_plugin->listener_callback = ai_listener_callback; /* Init listener callback with data from plugin */ ai_listener_callback->client = ai_plugin->client; ai_listener_callback->parent.OnNewChannelConnection = guac_rdp_ai_new_connection; /* Register listener for "AUDIO_INPUT" channel */ manager->CreateListener(manager, "AUDIO_INPUT", 0, (IWTSListenerCallback*) ai_listener_callback, NULL); return CHANNEL_RC_OK; } /** * Callback which is invoked when all connections to the AUDIO_INPUT plugin * have closed and the plugin is being unloaded. * * @param plugin * The AUDIO_INPUT plugin being unloaded. * * @return * Always zero. */ static UINT guac_rdp_ai_terminated(IWTSPlugin* plugin) { guac_rdp_ai_plugin* ai_plugin = (guac_rdp_ai_plugin*) plugin; guac_client* client = ai_plugin->client; /* Free all non-FreeRDP data */ free(ai_plugin->listener_callback); free(ai_plugin); guac_client_log(client, GUAC_LOG_DEBUG, "AUDIO_INPUT plugin unloaded."); return CHANNEL_RC_OK; } /** * Entry point for AUDIO_INPUT dynamic virtual channel. */ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { /* Pull guac_client from arguments */ ADDIN_ARGV* args = pEntryPoints->GetPluginData(pEntryPoints); guac_client* client = (guac_client*) guac_rdp_string_to_ptr(args->argv[1]); /* Pull previously-allocated plugin */ guac_rdp_ai_plugin* ai_plugin = (guac_rdp_ai_plugin*) pEntryPoints->GetPlugin(pEntryPoints, "guacai"); /* If no such plugin allocated, allocate and register it now */ if (ai_plugin == NULL) { /* Init plugin callbacks and data */ ai_plugin = calloc(1, sizeof(guac_rdp_ai_plugin)); ai_plugin->parent.Initialize = guac_rdp_ai_initialize; ai_plugin->parent.Terminated = guac_rdp_ai_terminated; ai_plugin->client = client; /* Register plugin as "guacai" for later retrieval */ pEntryPoints->RegisterPlugin(pEntryPoints, "guacai", (IWTSPlugin*) ai_plugin); guac_client_log(client, GUAC_LOG_DEBUG, "AUDIO_INPUT plugin loaded."); } return CHANNEL_RC_OK; } guacamole-server-1.3.0/src/protocols/rdp/plugins/guacai/guacai-messages.c0000644000175100001440000003141613764613616023430 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/audio-input/audio-buffer.h" #include "plugins/guacai/guacai-messages.h" #include "rdp.h" #include #include #include #include /** * Reads AUDIO_FORMAT data from the given stream into the given struct. * * @param stream * The stream to read AUDIO_FORMAT data from. * * @param format * The structure to populate with data from the stream. * * @return * Zero on success or non-zero if an error occurs processing the format. */ static int guac_rdp_ai_read_format(wStream* stream, guac_rdp_ai_format* format) { /* Check that we have at least 18 bytes (5 x UINT16, 2 x UINT32) */ if (Stream_GetRemainingLength(stream) < 18) return 1; /* Read audio format into structure */ Stream_Read_UINT16(stream, format->tag); /* wFormatTag */ Stream_Read_UINT16(stream, format->channels); /* nChannels */ Stream_Read_UINT32(stream, format->rate); /* nSamplesPerSec */ Stream_Read_UINT32(stream, format->bytes_per_sec); /* nAvgBytesPerSec */ Stream_Read_UINT16(stream, format->block_align); /* nBlockAlign */ Stream_Read_UINT16(stream, format->bps); /* wBitsPerSample */ Stream_Read_UINT16(stream, format->data_size); /* cbSize */ /* Read arbitrary data block (if applicable) and data is available. */ if (format->data_size != 0) { /* Check to make sure Stream contains expected bytes. */ if (Stream_GetRemainingLength(stream) < format->data_size) return 1; format->data = Stream_Pointer(stream); /* data */ Stream_Seek(stream, format->data_size); } return 0; } /** * Writes AUDIO_FORMAT data to the given stream from the given struct. * * @param stream * The stream to write AUDIO_FORMAT data to. * * @param format * The structure containing the data that should be written to the stream. */ static void guac_rdp_ai_write_format(wStream* stream, guac_rdp_ai_format* format) { /* Write audio format into structure */ Stream_Write_UINT16(stream, format->tag); /* wFormatTag */ Stream_Write_UINT16(stream, format->channels); /* nChannels */ Stream_Write_UINT32(stream, format->rate); /* nSamplesPerSec */ Stream_Write_UINT32(stream, format->bytes_per_sec); /* nAvgBytesPerSec */ Stream_Write_UINT16(stream, format->block_align); /* nBlockAlign */ Stream_Write_UINT16(stream, format->bps); /* wBitsPerSample */ Stream_Write_UINT16(stream, format->data_size); /* cbSize */ /* Write arbitrary data block (if applicable) */ if (format->data_size != 0) Stream_Write(stream, format->data, format->data_size); } /** * Sends a Data Incoming PDU along the given channel. A Data Incoming PDU is * used by the client to indicate to the server that format or audio data is * about to be sent. * * @param channel * The channel along which the PDU should be sent. */ static void guac_rdp_ai_send_incoming_data(IWTSVirtualChannel* channel) { /* Build data incoming PDU */ wStream* stream = Stream_New(NULL, 1); Stream_Write_UINT8(stream, GUAC_RDP_MSG_SNDIN_DATA_INCOMING); /* MessageId */ /* Send stream */ channel->Write(channel, (UINT32) Stream_GetPosition(stream), Stream_Buffer(stream), NULL); Stream_Free(stream, TRUE); } /** * Sends a Data PDU along the given channel. A Data PDU is used by the client * to send actual audio data following a Data Incoming PDU. * * @param channel * The channel along which the PDU should be sent. * * @param buffer * The audio data to send. * * @param length * The number of bytes of audio data to send. */ static void guac_rdp_ai_send_data(IWTSVirtualChannel* channel, char* buffer, int length) { /* Build data PDU */ wStream* stream = Stream_New(NULL, length + 1); Stream_Write_UINT8(stream, GUAC_RDP_MSG_SNDIN_DATA); /* MessageId */ Stream_Write(stream, buffer, length); /* Data */ /* Send stream */ channel->Write(channel, (UINT32) Stream_GetPosition(stream), Stream_Buffer(stream), NULL); Stream_Free(stream, TRUE); } /** * Sends a Sound Formats PDU along the given channel. A Sound Formats PDU is * used by the client to indicate to the server which formats of audio it * supports (in response to the server sending exactly the same type of PDU). * This PDU MUST be preceded by the Data Incoming PDU. * * @param channel * The channel along which the PDU should be sent. * * @param formats * An array of all supported formats. * * @param num_formats * The number of entries in the formats array. */ static void guac_rdp_ai_send_formats(IWTSVirtualChannel* channel, guac_rdp_ai_format* formats, int num_formats) { int index; int packet_size = 9; /* Calculate packet size */ for (index = 0; index < num_formats; index++) packet_size += 18 + formats[index].data_size; wStream* stream = Stream_New(NULL, packet_size); /* Write header */ Stream_Write_UINT8(stream, GUAC_RDP_MSG_SNDIN_FORMATS); /* MessageId */ Stream_Write_UINT32(stream, num_formats); /* NumFormats */ Stream_Write_UINT32(stream, packet_size); /* cbSizeFormatsPacket */ /* Write all formats */ for (index = 0; index < num_formats; index++) guac_rdp_ai_write_format(stream, &(formats[index])); /* Send PDU */ channel->Write(channel, (UINT32) Stream_GetPosition(stream), Stream_Buffer(stream), NULL); Stream_Free(stream, TRUE); } /** * Sends an Open Reply PDU along the given channel. An Open Reply PDU is * used by the client to acknowledge the successful opening of the AUDIO_INPUT * channel. * * @param channel * The channel along which the PDU should be sent. * * @param result * The HRESULT code to send to the server indicating success, failure, etc. */ static void guac_rdp_ai_send_open_reply(IWTSVirtualChannel* channel, UINT32 result) { /* Build open reply PDU */ wStream* stream = Stream_New(NULL, 5); Stream_Write_UINT8(stream, GUAC_RDP_MSG_SNDIN_OPEN_REPLY); /* MessageId */ Stream_Write_UINT32(stream, result); /* Result */ /* Send stream */ channel->Write(channel, (UINT32) Stream_GetPosition(stream), Stream_Buffer(stream), NULL); Stream_Free(stream, TRUE); } /** * Sends a Format Change PDU along the given channel. A Format Change PDU is * used by the client to acknowledge the format being used for data sent * along the AUDIO_INPUT channel. * * @param channel * The channel along which the PDU should be sent. * * @param format * The index of the format being acknowledged, which must be the index of * the format within the original Sound Formats PDU received from the * server. */ static void guac_rdp_ai_send_formatchange(IWTSVirtualChannel* channel, UINT32 format) { /* Build format change PDU */ wStream* stream = Stream_New(NULL, 5); Stream_Write_UINT8(stream, GUAC_RDP_MSG_SNDIN_FORMATCHANGE); /* MessageId */ Stream_Write_UINT32(stream, format); /* NewFormat */ /* Send stream */ channel->Write(channel, (UINT32) Stream_GetPosition(stream), Stream_Buffer(stream), NULL); Stream_Free(stream, TRUE); } void guac_rdp_ai_process_version(guac_client* client, IWTSVirtualChannel* channel, wStream* stream) { /* Verify we have at least 4 bytes available (UINT32) */ if (Stream_GetRemainingLength(stream) < 4) { guac_client_log(client, GUAC_LOG_WARNING, "Audio input Versoin PDU " "does not contain the expected number of bytes. Audio input " "redirection may not work as expected."); return; } UINT32 version; Stream_Read_UINT32(stream, version); /* Warn if server's version number is incorrect */ if (version != 1) guac_client_log(client, GUAC_LOG_WARNING, "Server reports AUDIO_INPUT version %i, not 1", version); /* Build response version PDU */ wStream* response = Stream_New(NULL, 5); Stream_Write_UINT8(response, GUAC_RDP_MSG_SNDIN_VERSION); /* MessageId */ Stream_Write_UINT32(response, 1); /* Version */ /* Send response */ channel->Write(channel, (UINT32) Stream_GetPosition(response), Stream_Buffer(response), NULL); Stream_Free(response, TRUE); } void guac_rdp_ai_process_formats(guac_client* client, IWTSVirtualChannel* channel, wStream* stream) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_audio_buffer* audio_buffer = rdp_client->audio_input; /* Verify we have at least 8 bytes available (2 x UINT32) */ if (Stream_GetRemainingLength(stream) < 8) { guac_client_log(client, GUAC_LOG_WARNING, "Audio input Sound Formats " "PDU does not contain the expected number of bytes. Audio " "input redirection may not work as expected."); return; } UINT32 num_formats; Stream_Read_UINT32(stream, num_formats); /* NumFormats */ Stream_Seek_UINT32(stream); /* cbSizeFormatsPacket (MUST BE IGNORED) */ UINT32 index; for (index = 0; index < num_formats; index++) { guac_rdp_ai_format format; if (guac_rdp_ai_read_format(stream, &format)) { guac_client_log(client, GUAC_LOG_WARNING, "Error occurred " "processing audio input formats. Audio input redirection " "may not work as expected."); return; } /* Ignore anything but WAVE_FORMAT_PCM */ if (format.tag != GUAC_RDP_WAVE_FORMAT_PCM) continue; /* Set output format of internal audio buffer to match RDP server */ guac_rdp_audio_buffer_set_output(audio_buffer, format.rate, format.channels, format.bps / 8); /* Accept single format */ guac_rdp_ai_send_incoming_data(channel); guac_rdp_ai_send_formats(channel, &format, 1); return; } /* No formats available */ guac_client_log(client, GUAC_LOG_WARNING, "AUDIO_INPUT: No WAVE format."); guac_rdp_ai_send_incoming_data(channel); guac_rdp_ai_send_formats(channel, NULL, 0); } void guac_rdp_ai_flush_packet(char* buffer, int length, void* data) { IWTSVirtualChannel* channel = (IWTSVirtualChannel*) data; /* Send data over channel */ guac_rdp_ai_send_incoming_data(channel); guac_rdp_ai_send_data(channel, buffer, length); } void guac_rdp_ai_process_open(guac_client* client, IWTSVirtualChannel* channel, wStream* stream) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_audio_buffer* audio_buffer = rdp_client->audio_input; /* Verify we have at least 8 bytes available (2 x UINT32) */ if (Stream_GetRemainingLength(stream) < 8) { guac_client_log(client, GUAC_LOG_WARNING, "Audio input Open PDU does " "not contain the expected number of bytes. Audio input " "redirection may not work as expected."); return; } UINT32 packet_frames; UINT32 initial_format; Stream_Read_UINT32(stream, packet_frames); /* FramesPerPacket */ Stream_Read_UINT32(stream, initial_format); /* InitialFormat */ guac_client_log(client, GUAC_LOG_DEBUG, "RDP server is accepting audio " "input as %i-channel, %i Hz PCM audio at %i bytes/sample.", audio_buffer->out_format.channels, audio_buffer->out_format.rate, audio_buffer->out_format.bps); /* Success */ guac_rdp_ai_send_formatchange(channel, initial_format); guac_rdp_ai_send_open_reply(channel, 0); /* Begin receiving audio data */ guac_rdp_audio_buffer_begin(audio_buffer, packet_frames, guac_rdp_ai_flush_packet, channel); } void guac_rdp_ai_process_formatchange(guac_client* client, IWTSVirtualChannel* channel, wStream* stream) { /* Should not be called as we only accept one format */ guac_client_log(client, GUAC_LOG_DEBUG, "RDP server requesting AUDIO_INPUT format change despite only one " "format available."); } guacamole-server-1.3.0/src/protocols/rdp/plugins/guacai/guacai-messages.h0000644000175100001440000001551313764613616023435 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_PLUGINS_GUACAI_MESSAGES_H #define GUAC_RDP_PLUGINS_GUACAI_MESSAGES_H #include "channels/audio-input/audio-buffer.h" #include #include #include #include /** * The format tag associated with raw wave audio (WAVE_FORMAT_PCM). This format * is required to be supported by all RDP servers. */ #define GUAC_RDP_WAVE_FORMAT_PCM 0x01 /** * The message ID associated with the AUDIO_INPUT Version PDU. The Version PDU * is sent by both the client and the server to indicate their version of the * AUDIO_INPUT channel protocol (which must always be 1). */ #define GUAC_RDP_MSG_SNDIN_VERSION 0x01 /** * The message ID associated with the AUDIO_INPUT Sound Formats PDU. The * Sound Formats PDU is sent by the client and the server to indicate the * formats of audio supported. */ #define GUAC_RDP_MSG_SNDIN_FORMATS 0x02 /** * The message ID associated with the AUDIO_INPUT Open PDU. The Open PDU is * sent by the server to inform the client that the AUDIO_INPUT channel is * now open. */ #define GUAC_RDP_MSG_SNDIN_OPEN 0x03 /** * The message ID associated with the AUDIO_INPUT Open Reply PDU. The Open * Reply PDU is sent by the client (after sending a Format Change PDU) to * acknowledge that the AUDIO_INPUT channel is open. */ #define GUAC_RDP_MSG_SNDIN_OPEN_REPLY 0x04 /** * The message ID associated with the AUDIO_INPUT Incoming Data PDU. The * Incoming Data PDU is sent by the client to inform the server of incoming * sound format or audio data. */ #define GUAC_RDP_MSG_SNDIN_DATA_INCOMING 0x05 /** * The message ID associated with the AUDIO_INPUT Data PDU. The Data PDU is * sent by the client and contains audio data read from the microphone. */ #define GUAC_RDP_MSG_SNDIN_DATA 0x06 /** * The message ID associated with the AUDIO_INPUT Format Change PDU. The Format * Change PDU is sent by the client to acknowledge the current sound format, or * by the server to request a different sound format. */ #define GUAC_RDP_MSG_SNDIN_FORMATCHANGE 0x07 /** * An AUDIO_INPUT format, analogous to the AUDIO_FORMAT structure defined * within Microsoft's RDP documentation. */ typedef struct guac_rdp_ai_format { /** * The "format tag" denoting the overall format of audio data received, * such as WAVE_FORMAT_PCM. */ UINT16 tag; /** * The number of audio channels. */ UINT16 channels; /** * The number of samples per second. */ UINT32 rate; /** * The average number of bytes required for one second of audio. */ UINT32 bytes_per_sec; /** * The absolute minimum number of bytes required to process audio in this * format. */ UINT16 block_align; /** * The number of bits per sample. */ UINT16 bps; /** * The size of the arbitrary data block, if any. The meaning of the data * within the arbitrary data block is determined by the format tag. * WAVE_FORMAT_PCM audio has no associated arbitrary data. */ UINT16 data_size; /** * Optional arbitrary data whose meaning is determined by the format tag. * WAVE_FORMAT_PCM audio has no associated arbitrary data. */ BYTE* data; } guac_rdp_ai_format; /** * Processes a Version PDU received from the RDP server. The Version PDU is * sent by the server to indicate its version of the AUDIO_INPUT channel * protocol (which must always be 1). * * @param client * The guac_client associated with the current RDP connection. * * @param channel * The IWTSVirtualChannel instance associated with the connected * AUDIO_INPUT channel. * * @param stream * The received PDU, with the read position just after the message ID field * common to all AUDIO_INPUT PDUs. */ void guac_rdp_ai_process_version(guac_client* client, IWTSVirtualChannel* channel, wStream* stream); /** * Processes a Sound Formats PDU received from the RDP server. The Sound * Formats PDU is sent by the server to indicate the formats of audio * supported. * * @param client * The guac_client associated with the current RDP connection. * * @param channel * The IWTSVirtualChannel instance associated with the connected * AUDIO_INPUT channel. * * @param stream * The received PDU, with the read position just after the message ID field * common to all AUDIO_INPUT PDUs. */ void guac_rdp_ai_process_formats(guac_client* client, IWTSVirtualChannel* channel, wStream* stream); /** * Processes a Open PDU received from the RDP server. The Open PDU is sent by * the server to inform the client that the AUDIO_INPUT channel is now open. * * @param client * The guac_client associated with the current RDP connection. * * @param channel * The IWTSVirtualChannel instance associated with the connected * AUDIO_INPUT channel. * * @param stream * The received PDU, with the read position just after the message ID field * common to all AUDIO_INPUT PDUs. */ void guac_rdp_ai_process_open(guac_client* client, IWTSVirtualChannel* channel, wStream* stream); /** * Processes a Format Change PDU received from the RDP server. The Format * Change PDU is sent by the server to request a different sound format. * * @param client * The guac_client associated with the current RDP connection. * * @param channel * The IWTSVirtualChannel instance associated with the connected * AUDIO_INPUT channel. * * @param stream * The received PDU, with the read position just after the message ID field * common to all AUDIO_INPUT PDUs. */ void guac_rdp_ai_process_formatchange(guac_client* client, IWTSVirtualChannel* channel, wStream* stream); /** * Audio buffer flush handler which sends audio data along the active audio * input channel using a Data Incoming PDU and Data PDU. The arbitrary data * provided to the handler by the audio buffer implementation is in this case * the IWTSVirtualChannel structure representing the active audio input * channel. */ guac_rdp_audio_buffer_flush_handler guac_rdp_ai_flush_packet; #endif guacamole-server-1.3.0/src/protocols/rdp/plugins/guacai/guacai.h0000644000175100001440000000626013764613616021627 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_PLUGINS_GUACAI_H #define GUAC_RDP_PLUGINS_GUACAI_H #include #include #include #include /** * Extended version of the IWTSListenerCallback structure, providing additional * access to Guacamole-specific data. The IWTSListenerCallback provides access * to callbacks related to the receipt of new connections to the AUDIO_INPUT * channel. */ typedef struct guac_rdp_ai_listener_callback { /** * The parent IWTSListenerCallback structure that this structure extends. * THIS MEMBER MUST BE FIRST! */ IWTSListenerCallback parent; /** * The guac_client instance associated with the RDP connection using the * AUDIO_INPUT plugin. */ guac_client* client; } guac_rdp_ai_listener_callback; /** * Extended version of the IWTSVirtualChannelCallback structure, providing * additional access to Guacamole-specific data. The IWTSVirtualChannelCallback * provides access to callbacks related to an active connection to the * AUDIO_INPUT channel, including receipt of data. */ typedef struct guac_rdp_ai_channel_callback { /** * The parent IWTSVirtualChannelCallback structure that this structure * extends. THIS MEMBER MUST BE FIRST! */ IWTSVirtualChannelCallback parent; /** * The actual virtual channel instance along which the AUDIO_INPUT plugin * should send any responses. */ IWTSVirtualChannel* channel; /** * The guac_client instance associated with the RDP connection using the * AUDIO_INPUT plugin. */ guac_client* client; } guac_rdp_ai_channel_callback; /** * All data associated with Guacamole's AUDIO_INPUT plugin for FreeRDP. */ typedef struct guac_rdp_ai_plugin { /** * The parent IWTSPlugin structure that this structure extends. THIS * MEMBER MUST BE FIRST! */ IWTSPlugin parent; /** * The listener callback structure allocated when the AUDIO_INPUT plugin * was loaded, if any. If the plugin did not fully load, this will be NULL. * If non-NULL, this callback structure must be freed when the plugin is * terminated. */ guac_rdp_ai_listener_callback* listener_callback; /** * The guac_client instance associated with the RDP connection using the * AUDIO_INPUT plugin. */ guac_client* client; } guac_rdp_ai_plugin; #endif guacamole-server-1.3.0/src/protocols/rdp/upload.c0000644000175100001440000002030013764613616016732 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "fs.h" #include "rdp.h" #include "upload.h" #include #include #include #include #include #include #include #include /** * Writes the given filename to the given upload path, sanitizing the filename * and translating the filename to the root directory. * * @param filename * The filename to sanitize and move to the root directory. * * @param path * A pointer to a buffer which should receive the sanitized path. The * buffer must have at least GUAC_RDP_FS_MAX_PATH bytes available. */ static void __generate_upload_path(const char* filename, char* path) { int i; /* Add initial backslash */ *(path++) = '\\'; for (i=1; iclient; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; int file_id; char file_path[GUAC_RDP_FS_MAX_PATH]; /* Get filesystem, return error if no filesystem */ guac_rdp_fs* fs = rdp_client->filesystem; if (fs == NULL) { guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(user->socket); return 0; } /* Ignore upload if uploads have been disabled */ if (fs->disable_upload) { guac_client_log(client, GUAC_LOG_WARNING, "A upload attempt has " "been blocked due to uploads being disabled, however it " "should have been blocked at a higher level. This is likely " "a bug."); guac_protocol_send_ack(user->socket, stream, "FAIL (UPLOAD DISABLED)", GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); guac_socket_flush(user->socket); return 0; } /* Translate name */ __generate_upload_path(filename, file_path); /* Open file */ file_id = guac_rdp_fs_open(fs, file_path, GENERIC_WRITE, 0, FILE_OVERWRITE_IF, 0); if (file_id < 0) { guac_protocol_send_ack(user->socket, stream, "FAIL (CANNOT OPEN)", GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); guac_socket_flush(user->socket); return 0; } /* Init upload status */ guac_rdp_upload_status* upload_status = malloc(sizeof(guac_rdp_upload_status)); upload_status->offset = 0; upload_status->file_id = file_id; stream->data = upload_status; stream->blob_handler = guac_rdp_upload_blob_handler; stream->end_handler = guac_rdp_upload_end_handler; guac_protocol_send_ack(user->socket, stream, "OK (STREAM BEGIN)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(user->socket); return 0; } int guac_rdp_upload_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { int bytes_written; guac_rdp_upload_status* upload_status = (guac_rdp_upload_status*) stream->data; /* Get filesystem, return error if no filesystem */ guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_fs* fs = rdp_client->filesystem; if (fs == NULL) { guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(user->socket); return 0; } /* Write entire block */ while (length > 0) { /* Attempt write */ bytes_written = guac_rdp_fs_write(fs, upload_status->file_id, upload_status->offset, data, length); /* On error, abort */ if (bytes_written < 0) { guac_protocol_send_ack(user->socket, stream, "FAIL (BAD WRITE)", GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); guac_socket_flush(user->socket); return 0; } /* Update counters */ upload_status->offset += bytes_written; data += bytes_written; length -= bytes_written; } guac_protocol_send_ack(user->socket, stream, "OK (DATA RECEIVED)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(user->socket); return 0; } int guac_rdp_upload_end_handler(guac_user* user, guac_stream* stream) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_upload_status* upload_status = (guac_rdp_upload_status*) stream->data; /* Get filesystem, return error if no filesystem */ guac_rdp_fs* fs = rdp_client->filesystem; if (fs == NULL) { guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(user->socket); return 0; } /* Close file */ guac_rdp_fs_close(fs, upload_status->file_id); /* Acknowledge stream end */ guac_protocol_send_ack(user->socket, stream, "OK (STREAM END)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(user->socket); free(upload_status); return 0; } int guac_rdp_upload_put_handler(guac_user* user, guac_object* object, guac_stream* stream, char* mimetype, char* name) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Get filesystem, return error if no filesystem */ guac_rdp_fs* fs = rdp_client->filesystem; if (fs == NULL) { guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(user->socket); return 0; } /* Ignore upload if uploads have been disabled */ if (fs->disable_upload) { guac_client_log(client, GUAC_LOG_WARNING, "A upload attempt has " "been blocked due to uploads being disabled, however it " "should have been blocked at a higher level. This is likely " "a bug."); guac_protocol_send_ack(user->socket, stream, "FAIL (UPLOAD DISABLED)", GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); guac_socket_flush(user->socket); return 0; } /* Open file */ int file_id = guac_rdp_fs_open(fs, name, GENERIC_WRITE, 0, FILE_OVERWRITE_IF, 0); /* Abort on failure */ if (file_id < 0) { guac_protocol_send_ack(user->socket, stream, "FAIL (CANNOT OPEN)", GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); guac_socket_flush(user->socket); return 0; } /* Init upload stream data */ guac_rdp_upload_status* upload_status = malloc(sizeof(guac_rdp_upload_status)); upload_status->offset = 0; upload_status->file_id = file_id; /* Allocate stream, init for file upload */ stream->data = upload_status; stream->blob_handler = guac_rdp_upload_blob_handler; stream->end_handler = guac_rdp_upload_end_handler; /* Acknowledge stream creation */ guac_protocol_send_ack(user->socket, stream, "OK (STREAM BEGIN)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(user->socket); return 0; } guacamole-server-1.3.0/src/protocols/rdp/user.h0000644000175100001440000000246413613156714016436 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_USER_H #define GUAC_RDP_USER_H #include /** * Handler for joining users. */ guac_user_join_handler guac_rdp_user_join_handler; /** * Handler for leaving users. */ guac_user_leave_handler guac_rdp_user_leave_handler; /** * Handler for received simple file uploads. This handler will automatically * select between RDPDR and SFTP depending on which is available and which has * priority given associated settings. */ guac_user_file_handler guac_rdp_user_file_handler; #endif guacamole-server-1.3.0/src/protocols/rdp/log.h0000644000175100001440000000221713764613616016243 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_LOG_H #define GUAC_RDP_LOG_H #include /** * Redirects the core FreeRDP logging facility, wLog, such that it logs all * messages at the debug level using guac_client_log(). * * @param client * The guac_client that should receive all log messages. */ void guac_rdp_redirect_wlog(guac_client* client); #endif guacamole-server-1.3.0/src/protocols/rdp/tests/0000755000175100001440000000000013772471160016524 500000000000000guacamole-server-1.3.0/src/protocols/rdp/tests/Makefile.in0000644000175100001440000012317213772471102020513 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ check_PROGRAMS = test_rdp$(EXEEXT) subdir = src/protocols/rdp/tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__dirstamp = $(am__leading_dot)dirstamp am_test_rdp_OBJECTS = fs/test_rdp-basename.$(OBJEXT) \ fs/test_rdp-normalize_path.$(OBJEXT) nodist_test_rdp_OBJECTS = test_rdp-_generated_runner.$(OBJEXT) test_rdp_OBJECTS = $(am_test_rdp_OBJECTS) $(nodist_test_rdp_OBJECTS) test_rdp_DEPENDENCIES = AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = test_rdp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_rdp_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/test_rdp-_generated_runner.Po \ fs/$(DEPDIR)/test_rdp-basename.Po \ fs/$(DEPDIR)/test_rdp-normalize_path.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(test_rdp_SOURCES) $(nodist_test_rdp_SOURCES) DIST_SOURCES = $(test_rdp_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp \ $(top_srcdir)/build-aux/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 TESTS = $(check_PROGRAMS) test_rdp_SOURCES = \ fs/basename.c \ fs/normalize_path.c test_rdp_CFLAGS = \ -Werror -Wall -pedantic \ @LIBGUAC_CLIENT_RDP_INCLUDE@ \ @LIBGUAC_INCLUDE@ test_rdp_LDADD = \ @CUNIT_LIBS@ \ @LIBGUAC_CLIENT_RDP_LTLIB@ # # Autogenerate test runner # GEN_RUNNER = $(top_srcdir)/util/generate-test-runner.pl CLEANFILES = _generated_runner.c nodist_test_rdp_SOURCES = \ _generated_runner.c # Use automake's TAP test driver for running any tests LOG_DRIVER = \ env AM_TAP_AWK='$(AWK)' \ $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/protocols/rdp/tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/protocols/rdp/tests/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list fs/$(am__dirstamp): @$(MKDIR_P) fs @: > fs/$(am__dirstamp) fs/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) fs/$(DEPDIR) @: > fs/$(DEPDIR)/$(am__dirstamp) fs/test_rdp-basename.$(OBJEXT): fs/$(am__dirstamp) \ fs/$(DEPDIR)/$(am__dirstamp) fs/test_rdp-normalize_path.$(OBJEXT): fs/$(am__dirstamp) \ fs/$(DEPDIR)/$(am__dirstamp) test_rdp$(EXEEXT): $(test_rdp_OBJECTS) $(test_rdp_DEPENDENCIES) $(EXTRA_test_rdp_DEPENDENCIES) @rm -f test_rdp$(EXEEXT) $(AM_V_CCLD)$(test_rdp_LINK) $(test_rdp_OBJECTS) $(test_rdp_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f fs/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_rdp-_generated_runner.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@fs/$(DEPDIR)/test_rdp-basename.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@fs/$(DEPDIR)/test_rdp-normalize_path.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< fs/test_rdp-basename.o: fs/basename.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_rdp_CFLAGS) $(CFLAGS) -MT fs/test_rdp-basename.o -MD -MP -MF fs/$(DEPDIR)/test_rdp-basename.Tpo -c -o fs/test_rdp-basename.o `test -f 'fs/basename.c' || echo '$(srcdir)/'`fs/basename.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) fs/$(DEPDIR)/test_rdp-basename.Tpo fs/$(DEPDIR)/test_rdp-basename.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs/basename.c' object='fs/test_rdp-basename.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_rdp_CFLAGS) $(CFLAGS) -c -o fs/test_rdp-basename.o `test -f 'fs/basename.c' || echo '$(srcdir)/'`fs/basename.c fs/test_rdp-basename.obj: fs/basename.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_rdp_CFLAGS) $(CFLAGS) -MT fs/test_rdp-basename.obj -MD -MP -MF fs/$(DEPDIR)/test_rdp-basename.Tpo -c -o fs/test_rdp-basename.obj `if test -f 'fs/basename.c'; then $(CYGPATH_W) 'fs/basename.c'; else $(CYGPATH_W) '$(srcdir)/fs/basename.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) fs/$(DEPDIR)/test_rdp-basename.Tpo fs/$(DEPDIR)/test_rdp-basename.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs/basename.c' object='fs/test_rdp-basename.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_rdp_CFLAGS) $(CFLAGS) -c -o fs/test_rdp-basename.obj `if test -f 'fs/basename.c'; then $(CYGPATH_W) 'fs/basename.c'; else $(CYGPATH_W) '$(srcdir)/fs/basename.c'; fi` fs/test_rdp-normalize_path.o: fs/normalize_path.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_rdp_CFLAGS) $(CFLAGS) -MT fs/test_rdp-normalize_path.o -MD -MP -MF fs/$(DEPDIR)/test_rdp-normalize_path.Tpo -c -o fs/test_rdp-normalize_path.o `test -f 'fs/normalize_path.c' || echo '$(srcdir)/'`fs/normalize_path.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) fs/$(DEPDIR)/test_rdp-normalize_path.Tpo fs/$(DEPDIR)/test_rdp-normalize_path.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs/normalize_path.c' object='fs/test_rdp-normalize_path.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_rdp_CFLAGS) $(CFLAGS) -c -o fs/test_rdp-normalize_path.o `test -f 'fs/normalize_path.c' || echo '$(srcdir)/'`fs/normalize_path.c fs/test_rdp-normalize_path.obj: fs/normalize_path.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_rdp_CFLAGS) $(CFLAGS) -MT fs/test_rdp-normalize_path.obj -MD -MP -MF fs/$(DEPDIR)/test_rdp-normalize_path.Tpo -c -o fs/test_rdp-normalize_path.obj `if test -f 'fs/normalize_path.c'; then $(CYGPATH_W) 'fs/normalize_path.c'; else $(CYGPATH_W) '$(srcdir)/fs/normalize_path.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) fs/$(DEPDIR)/test_rdp-normalize_path.Tpo fs/$(DEPDIR)/test_rdp-normalize_path.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs/normalize_path.c' object='fs/test_rdp-normalize_path.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_rdp_CFLAGS) $(CFLAGS) -c -o fs/test_rdp-normalize_path.obj `if test -f 'fs/normalize_path.c'; then $(CYGPATH_W) 'fs/normalize_path.c'; else $(CYGPATH_W) '$(srcdir)/fs/normalize_path.c'; fi` test_rdp-_generated_runner.o: _generated_runner.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_rdp_CFLAGS) $(CFLAGS) -MT test_rdp-_generated_runner.o -MD -MP -MF $(DEPDIR)/test_rdp-_generated_runner.Tpo -c -o test_rdp-_generated_runner.o `test -f '_generated_runner.c' || echo '$(srcdir)/'`_generated_runner.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_rdp-_generated_runner.Tpo $(DEPDIR)/test_rdp-_generated_runner.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='_generated_runner.c' object='test_rdp-_generated_runner.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_rdp_CFLAGS) $(CFLAGS) -c -o test_rdp-_generated_runner.o `test -f '_generated_runner.c' || echo '$(srcdir)/'`_generated_runner.c test_rdp-_generated_runner.obj: _generated_runner.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_rdp_CFLAGS) $(CFLAGS) -MT test_rdp-_generated_runner.obj -MD -MP -MF $(DEPDIR)/test_rdp-_generated_runner.Tpo -c -o test_rdp-_generated_runner.obj `if test -f '_generated_runner.c'; then $(CYGPATH_W) '_generated_runner.c'; else $(CYGPATH_W) '$(srcdir)/_generated_runner.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_rdp-_generated_runner.Tpo $(DEPDIR)/test_rdp-_generated_runner.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='_generated_runner.c' object='test_rdp-_generated_runner.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_rdp_CFLAGS) $(CFLAGS) -c -o test_rdp-_generated_runner.obj `if test -f '_generated_runner.c'; then $(CYGPATH_W) '_generated_runner.c'; else $(CYGPATH_W) '$(srcdir)/_generated_runner.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: $(check_PROGRAMS) @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_rdp.log: test_rdp$(EXEEXT) @p='test_rdp$(EXEEXT)'; \ b='test_rdp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f fs/$(DEPDIR)/$(am__dirstamp) -rm -f fs/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/test_rdp-_generated_runner.Po -rm -f fs/$(DEPDIR)/test_rdp-basename.Po -rm -f fs/$(DEPDIR)/test_rdp-normalize_path.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/test_rdp-_generated_runner.Po -rm -f fs/$(DEPDIR)/test_rdp-basename.Po -rm -f fs/$(DEPDIR)/test_rdp-normalize_path.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am .PRECIOUS: Makefile _generated_runner.c: $(test_rdp_SOURCES) $(AM_V_GEN) $(GEN_RUNNER) $(test_rdp_SOURCES) > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/protocols/rdp/tests/fs/0000755000175100001440000000000013772471160017134 500000000000000guacamole-server-1.3.0/src/protocols/rdp/tests/fs/basename.c0000644000175100001440000000464413764613616021010 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "fs.h" #include #include /** * Test which verifies basenames are correctly extracted from Windows-style * paths. */ void test_fs__basename_windows() { CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("\\foo\\bar\\baz"), "baz") CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("\\foo\\bar\\..\\baz\\"), "") CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("bar\\..\\..\\baz\\a\\..\\b"), "b") CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename(".\\bar\\potato"), "potato") CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("..\\..\\..\\..\\..\\..\\baz"), "baz") } /** * Test which verifies basenames are correctly extracted from UNIX-style paths. */ void test_fs__basename_unix() { CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("/foo/bar/baz"), "baz") CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("/foo/bar/../baz/"), "") CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("bar/../../baz/a/../b"), "b") CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("./bar/potato"), "potato") CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("../../../../../../baz"), "baz") } /** * Test which verifies basenames are correctly extracted from paths consisting * of mixed Windows and UNIX path separators. */ void test_fs__basename_mixed() { CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("\\foo/bar\\baz"), "baz") CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("/foo\\bar/..\\baz/"), "") CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("bar\\../../baz\\a\\..\\b"), "b") CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename(".\\bar/potato"), "potato") CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("../..\\..\\..\\../..\\baz"), "baz") } guacamole-server-1.3.0/src/protocols/rdp/tests/fs/normalize_path.c0000644000175100001440000002254613764613616022252 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "fs.h" #include #include /** * Test which verifies absolute Windows-style paths are correctly normalized to * absolute paths with Windows separators and no relative components. */ void test_fs__normalize_absolute_windows() { char normalized[GUAC_RDP_FS_MAX_PATH]; CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("\\", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("\\foo\\bar\\baz", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\foo\\bar\\baz", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("\\foo\\bar\\..\\baz\\", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\foo\\baz", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("\\foo\\bar\\..\\..\\baz\\a\\..\\b", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\baz\\b", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("\\foo\\.\\bar\\baz", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\foo\\bar\\baz", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("\\foo\\bar\\..\\..\\..\\..\\..\\..\\baz", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\baz", sizeof(normalized)); } /** * Test which verifies absolute UNIX-style paths are correctly normalized to * absolute paths with Windows separators and no relative components. */ void test_fs__normalize_absolute_unix() { char normalized[GUAC_RDP_FS_MAX_PATH]; CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("/", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("/foo/bar/baz", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\foo\\bar\\baz", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("/foo/bar/../baz/", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\foo\\baz", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("/foo/bar/../../baz/a/../b", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\baz\\b", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("/foo/./bar/baz", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\foo\\bar\\baz", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("/foo/bar/../../../../../../baz", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\baz", sizeof(normalized)); } /** * Test which verifies absolute paths consisting of mixed Windows and UNIX path * separators are correctly normalized to absolute paths with Windows * separators and no relative components. */ void test_fs__normalize_absolute_mixed() { char normalized[GUAC_RDP_FS_MAX_PATH]; CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("\\foo/bar\\baz", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\foo\\bar\\baz", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("/foo\\bar/..\\baz/", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\foo\\baz", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("\\foo/bar\\../../baz\\a\\..\\b", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\baz\\b", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("\\foo\\.\\bar/baz", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\foo\\bar\\baz", sizeof(normalized)); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path("\\foo/bar\\../..\\..\\..\\../..\\baz", normalized), 0) CU_ASSERT_NSTRING_EQUAL(normalized, "\\baz", sizeof(normalized)); } /** * Test which verifies relative Windows-style paths are always rejected. */ void test_fs__normalize_relative_windows() { char normalized[GUAC_RDP_FS_MAX_PATH]; CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path(".", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("..", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("foo", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path(".\\foo", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("..\\foo", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("foo\\bar\\baz", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path(".\\foo\\bar\\baz", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("..\\foo\\bar\\baz", normalized), 0) } /** * Test which verifies relative UNIX-style paths are always rejected. */ void test_fs__normalize_relative_unix() { char normalized[GUAC_RDP_FS_MAX_PATH]; CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path(".", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("..", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("foo", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("./foo", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("../foo", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("foo/bar/baz", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("./foo/bar/baz", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("../foo/bar/baz", normalized), 0) } /** * Test which verifies relative paths consisting of mixed Windows and UNIX path * separators are always rejected. */ void test_fs__normalize_relative_mixed() { char normalized[GUAC_RDP_FS_MAX_PATH]; CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("foo\\bar/baz", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path(".\\foo/bar/baz", normalized), 0) CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path("../foo\\bar\\baz", normalized), 0) } /** * Generates a dynamically-allocated path having the given number of bytes, not * counting the null-terminator. The path will contain only Windows-style path * separators. The returned path must eventually be freed with a call to * free(). * * @param length * The number of bytes to include in the generated path, not counting the * null-terminator. If -1, the length of the path will be automatically * determined from the provided max_depth. * * @param max_depth * The maximum number of path components to include within the generated * path. * * @return * A dynamically-allocated path containing the given number of bytes, not * counting the null-terminator. This path must eventually be freed with a * call to free(). */ static char* generate_path(int length, int max_depth) { /* If no length given, calculate space required from max_depth */ if (length == -1) length = max_depth * 2; int i; char* input = malloc(length + 1); /* Fill path with \x\x\x\x\x\x\x\x\x\x\...\xxxxxxxxx... */ for (i = 0; i < length; i++) { if (max_depth > 0 && i % 2 == 0) { input[i] = '\\'; max_depth--; } else input[i] = 'x'; } /* Add null terminator */ input[length] = '\0'; return input; } /** * Test which verifies that paths exceeding the maximum path length are * rejected. */ void test_fs__normalize_long() { char* input; char normalized[GUAC_RDP_FS_MAX_PATH]; /* Exceeds maximum length by a factor of 2 */ input = generate_path(GUAC_RDP_FS_MAX_PATH * 2, GUAC_RDP_MAX_PATH_DEPTH); CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path(input, normalized), 0); free(input); /* Exceeds maximum length by one byte */ input = generate_path(GUAC_RDP_FS_MAX_PATH, GUAC_RDP_MAX_PATH_DEPTH); CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path(input, normalized), 0); free(input); /* Exactly maximum length */ input = generate_path(GUAC_RDP_FS_MAX_PATH - 1, GUAC_RDP_MAX_PATH_DEPTH); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path(input, normalized), 0); free(input); } /** * Test which verifies that paths exceeding the maximum path depth are * rejected. */ void test_fs__normalize_deep() { char* input; char normalized[GUAC_RDP_FS_MAX_PATH]; /* Exceeds maximum depth by a factor of 2 */ input = generate_path(-1, GUAC_RDP_MAX_PATH_DEPTH * 2); CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path(input, normalized), 0); free(input); /* Exceeds maximum depth by one component */ input = generate_path(-1, GUAC_RDP_MAX_PATH_DEPTH + 1); CU_ASSERT_NOT_EQUAL(guac_rdp_fs_normalize_path(input, normalized), 0); free(input); /* Exactly maximum depth */ input = generate_path(-1, GUAC_RDP_MAX_PATH_DEPTH); CU_ASSERT_EQUAL(guac_rdp_fs_normalize_path(input, normalized), 0); free(input); } guacamole-server-1.3.0/src/protocols/rdp/tests/Makefile.am0000644000175100001440000000402113764613616020502 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 # # Unit tests for RDP support # check_PROGRAMS = test_rdp TESTS = $(check_PROGRAMS) test_rdp_SOURCES = \ fs/basename.c \ fs/normalize_path.c test_rdp_CFLAGS = \ -Werror -Wall -pedantic \ @LIBGUAC_CLIENT_RDP_INCLUDE@ \ @LIBGUAC_INCLUDE@ test_rdp_LDADD = \ @CUNIT_LIBS@ \ @LIBGUAC_CLIENT_RDP_LTLIB@ # # Autogenerate test runner # GEN_RUNNER = $(top_srcdir)/util/generate-test-runner.pl CLEANFILES = _generated_runner.c _generated_runner.c: $(test_rdp_SOURCES) $(AM_V_GEN) $(GEN_RUNNER) $(test_rdp_SOURCES) > $@ nodist_test_rdp_SOURCES = \ _generated_runner.c # Use automake's TAP test driver for running any tests LOG_DRIVER = \ env AM_TAP_AWK='$(AWK)' \ $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh guacamole-server-1.3.0/src/protocols/rdp/sftp.h0000644000175100001440000000305013764613616016432 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_SFTP_H #define GUAC_RDP_SFTP_H #include #include /** * Handles an incoming stream from a Guacamole "file" instruction, saving the * contents of that stream to the file having the given name. * * @param user * The user uploading the file. * * @param stream * The stream through which the uploaded file data will be received. * * @param mimetype * The mimetype of the data being received. * * @param filename * The filename of the file to write to. * * @return * Zero if the incoming stream has been handled successfully, non-zero on * failure. */ int guac_rdp_sftp_file_handler(guac_user* user, guac_stream* stream, char* mimetype, char* filename); #endif guacamole-server-1.3.0/src/protocols/rdp/fs.c0000644000175100001440000005607213764613616016075 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "fs.h" #include "download.h" #include "upload.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include guac_rdp_fs* guac_rdp_fs_alloc(guac_client* client, const char* drive_path, int create_drive_path, int disable_download, int disable_upload) { /* Create drive path if it does not exist */ if (create_drive_path) { guac_client_log(client, GUAC_LOG_DEBUG, "%s: Creating directory \"%s\" if necessary.", __func__, drive_path); /* Log error if directory creation fails */ if (mkdir(drive_path, S_IRWXU) && errno != EEXIST) { guac_client_log(client, GUAC_LOG_ERROR, "Unable to create directory \"%s\": %s", drive_path, strerror(errno)); } } guac_rdp_fs* fs = malloc(sizeof(guac_rdp_fs)); fs->client = client; fs->drive_path = strdup(drive_path); fs->file_id_pool = guac_pool_alloc(0); fs->open_files = 0; fs->disable_download = disable_download; fs->disable_upload = disable_upload; return fs; } void guac_rdp_fs_free(guac_rdp_fs* fs) { guac_pool_free(fs->file_id_pool); free(fs->drive_path); free(fs); } guac_object* guac_rdp_fs_alloc_object(guac_rdp_fs* fs, guac_user* user) { /* Init filesystem */ guac_object* fs_object = guac_user_alloc_object(user); fs_object->get_handler = guac_rdp_download_get_handler; /* Assign handler only if uploads are not disabled. */ if (!fs->disable_upload) fs_object->put_handler = guac_rdp_upload_put_handler; fs_object->data = fs; /* Send filesystem to user */ guac_protocol_send_filesystem(user->socket, fs_object, "Shared Drive"); guac_socket_flush(user->socket); return fs_object; } void* guac_rdp_fs_expose(guac_user* user, void* data) { guac_rdp_fs* fs = (guac_rdp_fs*) data; /* No need to expose if there is no filesystem or the user has left */ if (user == NULL || fs == NULL) return NULL; /* Allocate and expose filesystem object for user */ return guac_rdp_fs_alloc_object(fs, user); } /** * Translates an absolute Windows path to an absolute path which is within the * "drive path" specified in the connection settings. No checking is performed * on the path provided, which is assumed to have already been normalized and * validated as absolute. * * @param fs * The filesystem containing the file whose path is being translated. * * @param virtual_path * The absolute path to the file on the simulated filesystem, relative to * the simulated filesystem root. * * @param real_path * The buffer in which to store the absolute path to the real file on the * local filesystem. */ static void __guac_rdp_fs_translate_path(guac_rdp_fs* fs, const char* virtual_path, char* real_path) { /* Get drive path */ char* drive_path = fs->drive_path; int i; /* Start with path from settings */ for (i=0; iclient, GUAC_LOG_DEBUG, "%s: path=\"%s\", access=0x%x, file_attributes=0x%x, " "create_disposition=0x%x, create_options=0x%x", __func__, path, access, file_attributes, create_disposition, create_options); /* If no files available, return too many open */ if (fs->open_files >= GUAC_RDP_FS_MAX_FILES) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Too many open files.", __func__, path); return GUAC_RDP_FS_ENFILE; } /* If path empty, transform to root path */ if (path[0] == '\0') path = "\\"; /* If path is relative, the file does not exist */ else if (path[0] != '\\' && path[0] != '/') { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Access denied - supplied path \"%s\" is relative.", __func__, path); return GUAC_RDP_FS_ENOENT; } /* Translate access into flags */ if (access & GENERIC_ALL) flags = O_RDWR; else if ((access & ( GENERIC_WRITE | FILE_WRITE_DATA | FILE_APPEND_DATA)) && (access & (GENERIC_READ | FILE_READ_DATA))) flags = O_RDWR; else if (access & ( GENERIC_WRITE | FILE_WRITE_DATA | FILE_APPEND_DATA)) flags = O_WRONLY; else flags = O_RDONLY; /* Normalize path, return no-such-file if invalid */ if (guac_rdp_fs_normalize_path(path, normalized_path)) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Normalization of path \"%s\" failed.", __func__, path); return GUAC_RDP_FS_ENOENT; } guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Normalized path \"%s\" to \"%s\".", __func__, path, normalized_path); /* Translate normalized path to real path */ __guac_rdp_fs_translate_path(fs, normalized_path, real_path); guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Translated path \"%s\" to \"%s\".", __func__, normalized_path, real_path); switch (create_disposition) { /* Create if not exist, fail otherwise */ case FILE_CREATE: flags |= O_CREAT | O_EXCL; break; /* Open file if exists and do not overwrite, fail otherwise */ case FILE_OPEN: /* No flag necessary - default functionality of open */ break; /* Open if exists, create otherwise */ case FILE_OPEN_IF: flags |= O_CREAT; break; /* Overwrite if exists, fail otherwise */ case FILE_OVERWRITE: flags |= O_TRUNC; break; /* Overwrite if exists, create otherwise */ case FILE_OVERWRITE_IF: flags |= O_CREAT | O_TRUNC; break; /* Supersede (replace) if exists, otherwise create */ case FILE_SUPERSEDE: unlink(real_path); flags |= O_CREAT | O_TRUNC; break; /* Unrecognised disposition */ default: return GUAC_RDP_FS_ENOSYS; } /* Create directory first, if necessary */ if ((create_options & FILE_DIRECTORY_FILE) && (flags & O_CREAT)) { /* Create directory */ if (mkdir(real_path, S_IRWXU)) { if (errno != EEXIST || (flags & O_EXCL)) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: mkdir() failed: %s", __func__, strerror(errno)); return guac_rdp_fs_get_errorcode(errno); } } /* Unset O_CREAT and O_EXCL as directory must exist before open() */ flags &= ~(O_CREAT | O_EXCL); } guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: native open: real_path=\"%s\", flags=0x%x", __func__, real_path, flags); /* Open file */ fd = open(real_path, flags, S_IRUSR | S_IWUSR); /* If file open failed as we're trying to write a dir, retry as read-only */ if (fd == -1 && errno == EISDIR) { flags &= ~(O_WRONLY | O_RDWR); flags |= O_RDONLY; fd = open(real_path, flags, S_IRUSR | S_IWUSR); } if (fd == -1) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: open() failed: %s", __func__, strerror(errno)); return guac_rdp_fs_get_errorcode(errno); } /* Get file ID, init file */ file_id = guac_pool_next_int(fs->file_id_pool); file = &(fs->files[file_id]); file->id = file_id; file->fd = fd; file->dir = NULL; file->dir_pattern[0] = '\0'; file->absolute_path = strdup(normalized_path); file->real_path = strdup(real_path); file->bytes_written = 0; guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Opened \"%s\" as file_id=%i", __func__, normalized_path, file_id); /* Attempt to pull file information */ if (fstat(fd, &file_stat) == 0) { /* Load size and times */ file->size = file_stat.st_size; file->ctime = WINDOWS_TIME(file_stat.st_ctime); file->mtime = WINDOWS_TIME(file_stat.st_mtime); file->atime = WINDOWS_TIME(file_stat.st_atime); /* Set type */ if (S_ISDIR(file_stat.st_mode)) file->attributes = FILE_ATTRIBUTE_DIRECTORY; else file->attributes = FILE_ATTRIBUTE_NORMAL; } /* If information cannot be retrieved, fake it */ else { /* Init information to 0, lacking any alternative */ file->size = 0; file->ctime = 0; file->mtime = 0; file->atime = 0; file->attributes = FILE_ATTRIBUTE_NORMAL; } fs->open_files++; return file_id; } int guac_rdp_fs_read(guac_rdp_fs* fs, int file_id, uint64_t offset, void* buffer, int length) { int bytes_read; guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id); if (file == NULL) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Read from bad file_id: %i", __func__, file_id); return GUAC_RDP_FS_EINVAL; } /* Attempt read */ lseek(file->fd, offset, SEEK_SET); bytes_read = read(file->fd, buffer, length); /* Translate errno on error */ if (bytes_read < 0) return guac_rdp_fs_get_errorcode(errno); return bytes_read; } int guac_rdp_fs_write(guac_rdp_fs* fs, int file_id, uint64_t offset, void* buffer, int length) { int bytes_written; guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id); if (file == NULL) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Write to bad file_id: %i", __func__, file_id); return GUAC_RDP_FS_EINVAL; } /* Attempt write */ lseek(file->fd, offset, SEEK_SET); bytes_written = write(file->fd, buffer, length); /* Translate errno on error */ if (bytes_written < 0) return guac_rdp_fs_get_errorcode(errno); file->bytes_written += bytes_written; return bytes_written; } int guac_rdp_fs_rename(guac_rdp_fs* fs, int file_id, const char* new_path) { char real_path[GUAC_RDP_FS_MAX_PATH]; char normalized_path[GUAC_RDP_FS_MAX_PATH]; guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id); if (file == NULL) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Rename of bad file_id: %i", __func__, file_id); return GUAC_RDP_FS_EINVAL; } /* Normalize path, return no-such-file if invalid */ if (guac_rdp_fs_normalize_path(new_path, normalized_path)) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Normalization of path \"%s\" failed.", __func__, new_path); return GUAC_RDP_FS_ENOENT; } /* Translate normalized path to real path */ __guac_rdp_fs_translate_path(fs, normalized_path, real_path); guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Renaming \"%s\" -> \"%s\"", __func__, file->real_path, real_path); /* Perform rename */ if (rename(file->real_path, real_path)) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: rename() failed: \"%s\" -> \"%s\"", __func__, file->real_path, real_path); return guac_rdp_fs_get_errorcode(errno); } return 0; } int guac_rdp_fs_delete(guac_rdp_fs* fs, int file_id) { /* Get file */ guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id); if (file == NULL) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Delete of bad file_id: %i", __func__, file_id); return GUAC_RDP_FS_EINVAL; } /* If directory, attempt removal */ if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) { if (rmdir(file->real_path)) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: rmdir() failed: \"%s\"", __func__, file->real_path); return guac_rdp_fs_get_errorcode(errno); } } /* Otherwise, attempt deletion */ else if (unlink(file->real_path)) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: unlink() failed: \"%s\"", __func__, file->real_path); return guac_rdp_fs_get_errorcode(errno); } return 0; } int guac_rdp_fs_truncate(guac_rdp_fs* fs, int file_id, int length) { /* Get file */ guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id); if (file == NULL) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Delete of bad file_id: %i", __func__, file_id); return GUAC_RDP_FS_EINVAL; } /* Attempt truncate */ if (ftruncate(file->fd, length)) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: ftruncate() to %i bytes failed: \"%s\"", __func__, length, file->real_path); return guac_rdp_fs_get_errorcode(errno); } return 0; } void guac_rdp_fs_close(guac_rdp_fs* fs, int file_id) { guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id); if (file == NULL) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Ignoring close for bad file_id: %i", __func__, file_id); return; } file = &(fs->files[file_id]); guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Closed \"%s\" (file_id=%i)", __func__, file->absolute_path, file_id); /* Close directory, if open */ if (file->dir != NULL) closedir(file->dir); /* Close file */ close(file->fd); /* Free name */ free(file->absolute_path); free(file->real_path); /* Free ID back to pool */ guac_pool_free_int(fs->file_id_pool, file_id); fs->open_files--; } const char* guac_rdp_fs_read_dir(guac_rdp_fs* fs, int file_id) { guac_rdp_fs_file* file; struct dirent* result; /* Only read if file ID is valid */ if (file_id < 0 || file_id >= GUAC_RDP_FS_MAX_FILES) return NULL; file = &(fs->files[file_id]); /* Open directory if not yet open, stop if error */ if (file->dir == NULL) { file->dir = fdopendir(file->fd); if (file->dir == NULL) return NULL; } /* Read next entry, stop if error or no more entries */ if ((result = readdir(file->dir)) == NULL) return NULL; /* Return filename */ return result->d_name; } const char* guac_rdp_fs_basename(const char* path) { for (const char* c = path; *c != '\0'; c++) { /* Reset beginning of path if a path separator is found */ if (*c == '/' || *c == '\\') path = c + 1; } /* path now points to the first character after the last path separator */ return path; } int guac_rdp_fs_normalize_path(const char* path, char* abs_path) { int path_depth = 0; const char* path_components[GUAC_RDP_MAX_PATH_DEPTH]; /* If original path is not absolute, normalization fails */ if (path[0] != '\\' && path[0] != '/') return 1; /* Create scratch copy of path excluding leading slash (we will be * replacing path separators with null terminators and referencing those * substrings directly as path components) */ char path_scratch[GUAC_RDP_FS_MAX_PATH - 1]; int length = guac_strlcpy(path_scratch, path + 1, sizeof(path_scratch)); /* Fail if provided path is too long */ if (length >= sizeof(path_scratch)) return 1; /* Locate all path components within path */ const char* current_path_component = &(path_scratch[0]); for (int i = 0; i <= length; i++) { /* If current character is a path separator, parse as component */ char c = path_scratch[i]; if (c == '/' || c == '\\' || c == '\0') { /* Terminate current component */ path_scratch[i] = '\0'; /* If component refers to parent, just move up in depth */ if (strcmp(current_path_component, "..") == 0) { if (path_depth > 0) path_depth--; } /* Otherwise, if component not current directory, add to list */ else if (strcmp(current_path_component, ".") != 0 && strcmp(current_path_component, "") != 0) { /* Fail normalization if path is too deep */ if (path_depth >= GUAC_RDP_MAX_PATH_DEPTH) return 1; path_components[path_depth++] = current_path_component; } /* Update start of next component */ current_path_component = &(path_scratch[i+1]); } /* end if separator */ /* We do not currently support named streams */ else if (c == ':') return 1; } /* end for each character */ /* Add leading slash for resulting absolute path */ abs_path[0] = '\\'; /* Append normalized components to path, separated by slashes */ guac_strljoin(abs_path + 1, path_components, path_depth, "\\", GUAC_RDP_FS_MAX_PATH - 1); return 0; } int guac_rdp_fs_convert_path(const char* parent, const char* rel_path, char* abs_path) { int length; char combined_path[GUAC_RDP_FS_MAX_PATH]; /* Copy parent path */ length = guac_strlcpy(combined_path, parent, sizeof(combined_path)); /* Add trailing slash */ length += guac_strlcpy(combined_path + length, "\\", sizeof(combined_path) - length); /* Copy remaining path */ length += guac_strlcpy(combined_path + length, rel_path, sizeof(combined_path) - length); /* Normalize into provided buffer */ return guac_rdp_fs_normalize_path(combined_path, abs_path); } guac_rdp_fs_file* guac_rdp_fs_get_file(guac_rdp_fs* fs, int file_id) { /* Validate ID */ if (file_id < 0 || file_id >= GUAC_RDP_FS_MAX_FILES) return NULL; /* Return file at given ID */ return &(fs->files[file_id]); } int guac_rdp_fs_matches(const char* filename, const char* pattern) { return fnmatch(pattern, filename, FNM_NOESCAPE) != 0; } int guac_rdp_fs_get_info(guac_rdp_fs* fs, guac_rdp_fs_info* info) { /* Read FS information */ struct statvfs fs_stat; if (statvfs(fs->drive_path, &fs_stat)) return guac_rdp_fs_get_errorcode(errno); /* Assign to structure */ info->blocks_available = fs_stat.f_bfree; info->blocks_total = fs_stat.f_blocks; info->block_size = fs_stat.f_bsize; return 0; } int guac_rdp_fs_append_filename(char* fullpath, const char* path, const char* filename) { int i; /* Disallow "." as a filename */ if (strcmp(filename, ".") == 0) return 0; /* Disallow ".." as a filename */ if (strcmp(filename, "..") == 0) return 0; /* Copy path, append trailing slash */ for (i=0; i 0 && path[i-1] != '/' && path[i-1] != '\\') fullpath[i++] = '/'; break; } /* Copy character if not end of string */ fullpath[i] = c; } /* Append filename */ for (; i #include void guac_rdp_utf16_to_utf8(const unsigned char* utf16, int length, char* utf8, int size) { int i; const uint16_t* in_codepoint = (const uint16_t*) utf16; /* For each UTF-16 character */ for (i=0; i #include #include #include #include #include BOOL guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Allocate buffer */ guac_common_display_layer* buffer = guac_common_display_alloc_buffer( rdp_client->display, pointer->width, pointer->height); /* Allocate data for image */ unsigned char* data = _aligned_malloc(pointer->width * pointer->height * 4, 16); cairo_surface_t* surface; /* Convert to alpha cursor if mask data present */ if (pointer->andMaskData && pointer->xorMaskData) freerdp_image_copy_from_pointer_data(data, guac_rdp_get_native_pixel_format(TRUE), 0, 0, 0, pointer->width, pointer->height, pointer->xorMaskData, pointer->lengthXorMask, pointer->andMaskData, pointer->lengthAndMask, pointer->xorBpp, &context->gdi->palette); /* Create surface from image data */ surface = cairo_image_surface_create_for_data( data, CAIRO_FORMAT_ARGB32, pointer->width, pointer->height, 4*pointer->width); /* Send surface to buffer */ guac_common_surface_draw(buffer->surface, 0, 0, surface); /* Free surface */ cairo_surface_destroy(surface); _aligned_free(data); /* Remember buffer */ ((guac_rdp_pointer*) pointer)->layer = buffer; return TRUE; } BOOL guac_rdp_pointer_set(rdpContext* context, const rdpPointer* pointer) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Set cursor */ guac_common_cursor_set_surface(rdp_client->display->cursor, pointer->xPos, pointer->yPos, ((guac_rdp_pointer*) pointer)->layer->surface); return TRUE; } void guac_rdp_pointer_free(rdpContext* context, rdpPointer* pointer) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_common_display_layer* buffer = ((guac_rdp_pointer*) pointer)->layer; /* Free buffer */ guac_common_display_free_buffer(rdp_client->display, buffer); /* NOTE: FreeRDP-allocated memory for the rdpPointer will be automatically * released after this free handler is invoked */ } BOOL guac_rdp_pointer_set_null(rdpContext* context) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Set cursor to empty/blank graphic */ guac_common_cursor_set_blank(rdp_client->display->cursor); return TRUE; } BOOL guac_rdp_pointer_set_default(rdpContext* context) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Set cursor to embedded pointer */ guac_common_cursor_set_pointer(rdp_client->display->cursor); return TRUE; } guacamole-server-1.3.0/src/protocols/rdp/print-job.c0000644000175100001440000004556213770536337017374 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "print-job.h" #include #include #include #include #include #include #include #include #include #include /** * The command to run when filtering postscript to produce PDF. This must be * a NULL-terminated array of arguments, where the first argument is the name * of the file to run. */ char* const guac_rdp_pdf_filter_command[] = { "gs", "-q", "-dNOPAUSE", "-dBATCH", "-dSAFER", "-dPARANOIDSAFER", "-sDEVICE=pdfwrite", "-sOutputFile=-", "-c", ".setpdfwrite", "-sstdout=/dev/null", "-f", "-", NULL }; /** * Updates the state of the given print job. Any threads currently blocked by a * call to guac_rdp_print_job_wait_for_ack() will be unblocked. * * @param job * The print job whose state should be updated. * * @param state * The new state to assign to the given print job. */ static void guac_rdp_print_job_set_state(guac_rdp_print_job* job, guac_rdp_print_job_state state) { pthread_mutex_lock(&(job->state_lock)); /* Update stream state, signalling modification */ job->state = state; pthread_cond_signal(&(job->state_modified)); pthread_mutex_unlock(&(job->state_lock)); } /** * Suspends execution of the current thread until the state of the given print * job is not GUAC_RDP_PRINT_JOB_WAITING_FOR_ACK. If the state of the print * job is GUAC_RDP_PRINT_JOB_ACK_RECEIVED, the state is automatically reset * back to GUAC_RDP_PRINT_JOB_WAITING_FOR_ACK prior to returning. * * @param job * The print job to wait for. * * @return * Zero if the state of the print job is GUAC_RDP_PRINT_JOB_CLOSED, * non-zero if the state was GUAC_RDP_PRINT_JOB_ACK_RECEIVED and has been * automatically reset to GUAC_RDP_PRINT_JOB_WAITING_FOR_ACK. */ static int guac_rdp_print_job_wait_for_ack(guac_rdp_print_job* job) { /* Wait for ack if stream open and not yet received */ pthread_mutex_lock(&(job->state_lock)); if (job->state == GUAC_RDP_PRINT_JOB_WAITING_FOR_ACK) pthread_cond_wait(&job->state_modified, &job->state_lock); /* Reset state if ack received */ int got_ack = (job->state == GUAC_RDP_PRINT_JOB_ACK_RECEIVED); if (got_ack) job->state = GUAC_RDP_PRINT_JOB_WAITING_FOR_ACK; /* Return whether ack was successfully received */ pthread_mutex_unlock(&(job->state_lock)); return got_ack; } /** * Sends a "file" instruction to the given user describing the PDF file that * will be sent using the output of the given print job. If the given user no * longer exists, the print stream will be automatically terminated. * * @param user * The user receiving the "file" instruction. * * @param data * A pointer to the guac_rdp_print_job representing the print job being * streamed. * * @return * Always NULL. */ static void* guac_rdp_print_job_begin_stream(guac_user* user, void* data) { guac_rdp_print_job* job = (guac_rdp_print_job*) data; guac_client_log(job->client, GUAC_LOG_DEBUG, "Beginning print stream: %s", job->filename); /* Kill job and do nothing if user no longer exists */ if (user == NULL) { guac_rdp_print_job_kill(job); return NULL; } /* Send document as a PDF file stream */ guac_protocol_send_file(user->socket, job->stream, "application/pdf", job->filename); guac_socket_flush(user->socket); return NULL; } /** * Sends a "blob" instruction to the given user containing the provided data * along the stream associated with the provided print job. If the given user * no longer exists, the print stream will be automatically terminated. * * @param user * The user receiving the "blob" instruction. * * @param data * A pointer to an guac_rdp_print_blob structure containing the data to * be written, the number of bytes being written, and the print job being * streamed. * * @return * Always NULL. */ static void* guac_rdp_print_job_send_blob(guac_user* user, void* data) { guac_rdp_print_blob* blob = (guac_rdp_print_blob*) data; guac_rdp_print_job* job = blob->job; guac_client_log(job->client, GUAC_LOG_DEBUG, "Sending %i byte(s) " "of filtered output.", blob->length); /* Kill job and do nothing if user no longer exists */ if (user == NULL) { guac_rdp_print_job_kill(job); return NULL; } /* Send single blob of print data */ guac_protocol_send_blob(user->socket, job->stream, blob->buffer, blob->length); guac_socket_flush(user->socket); return NULL; } /** * Sends an "end" instruction to the given user, closing the stream associated * with the given print job. If the given user no longer exists, the print * stream will be automatically terminated. * * @param user * The user receiving the "end" instruction. * * @param data * A pointer to the guac_rdp_print_job representing the print job being * streamed. * * @return * Always NULL. */ static void* guac_rdp_print_job_end_stream(guac_user* user, void* data) { guac_rdp_print_job* job = (guac_rdp_print_job*) data; guac_client_log(job->client, GUAC_LOG_DEBUG, "End of print stream."); /* Kill job and do nothing if user no longer exists */ if (user == NULL) { guac_rdp_print_job_kill(job); return NULL; } /* Explicitly close down stream */ guac_protocol_send_end(user->socket, job->stream); guac_socket_flush(user->socket); /* Clean up our end of the stream */ guac_user_free_stream(job->user, job->stream); return NULL; } /** * Handler for "ack" messages received in response to printed data. Additional * data will be sent as a result or, if no data remains, the stream will be * terminated. It is required that the data pointer of the provided stream be * set to the file descriptor from which the printed data should be read. * * @param user * The user to whom the printed data is being sent. * * @param stream * The stream along which the printed data is to be sent. The data pointer * of this stream MUST be set to the file descriptor from which the data * being sent is to be read. * * @param message * An arbitrary, human-readable message describing the success/failure of * the operation being acknowledged (either stream creation or receipt of * a blob). * * @param status * The status code describing the success/failure of the operation being * acknowledged (either stream creation or receipt of a blob). * * @return * Always zero. */ static int guac_rdp_print_filter_ack_handler(guac_user* user, guac_stream* stream, char* message, guac_protocol_status status) { guac_rdp_print_job* job = (guac_rdp_print_job*) stream->data; /* Update state for successful acks */ if (status == GUAC_PROTOCOL_STATUS_SUCCESS) guac_rdp_print_job_set_state(job, GUAC_RDP_PRINT_JOB_ACK_RECEIVED); /* Terminate stream if ack signals an error */ else { /* Note that the stream was aborted by the user */ guac_client_log(job->client, GUAC_LOG_INFO, "User explicitly aborted " "print stream."); /* Kill job (the results will no longer be received) */ guac_rdp_print_job_kill(job); } return 0; } /** * Forks a new print filtering process which accepts PostScript input and * produces PDF output. File descriptors for writing input and reading output * will automatically be allocated and must be manually closed when processing * is complete. * * @param client * The guac_client associated with the print job for which this filter * process is being created. * * @param input_fd * A pointer to an int which should receive the input file descriptor of * the filter process. PostScript input for the filter process should be * written to this file descriptor. * * @param output_fd * A pointer to an int which should receive the output file descriptor of * the filter process. PDF output from the filter process must be * continuously read from this file descriptor or the pipeline may block. * * @return * The PID of the filter process, or -1 if the filter process could not be * created. If the filter process could not be created, the values assigned * through input_fd and output_fd are undefined. */ static pid_t guac_rdp_create_filter_process(guac_client* client, int* input_fd, int* output_fd) { int child_pid; int stdin_pipe[2]; int stdout_pipe[2]; /* Create STDIN pipe */ if (pipe(stdin_pipe)) { guac_client_log(client, GUAC_LOG_ERROR, "Unable to create STDIN " "pipe for PDF filter process: %s", strerror(errno)); return -1; } /* Create STDOUT pipe */ if (pipe(stdout_pipe)) { guac_client_log(client, GUAC_LOG_ERROR, "Unable to create STDOUT " "pipe for PDF filter process: %s", strerror(errno)); close(stdin_pipe[0]); close(stdin_pipe[1]); return -1; } /* Store parent side of stdin/stdout */ *input_fd = stdin_pipe[1]; *output_fd = stdout_pipe[0]; /* Fork child process */ child_pid = fork(); /* Log fork errors */ if (child_pid == -1) { guac_client_log(client, GUAC_LOG_ERROR, "Unable to fork PDF filter " "process: %s", strerror(errno)); close(stdin_pipe[0]); close(stdin_pipe[1]); close(stdout_pipe[0]); close(stdout_pipe[1]); return -1; } /* Child process */ if (child_pid == 0) { /* Close unneeded ends of pipe */ close(stdin_pipe[1]); close(stdout_pipe[0]); /* Reassign file descriptors as STDIN/STDOUT */ dup2(stdin_pipe[0], STDIN_FILENO); dup2(stdout_pipe[1], STDOUT_FILENO); /* Run PDF filter */ guac_client_log(client, GUAC_LOG_INFO, "Running %s", guac_rdp_pdf_filter_command[0]); if (execvp(guac_rdp_pdf_filter_command[0], guac_rdp_pdf_filter_command) < 0) guac_client_log(client, GUAC_LOG_ERROR, "Unable to execute PDF " "filter command: %s", strerror(errno)); else guac_client_log(client, GUAC_LOG_ERROR, "Unable to execute PDF " "filter command, but no error given"); /* Terminate child process */ exit(1); } /* Log fork success */ guac_client_log(client, GUAC_LOG_INFO, "Created PDF filter process " "PID=%i", child_pid); /* Close unneeded ends of pipe */ close(stdin_pipe[0]); close(stdout_pipe[1]); return child_pid; } /** * Thread which continuously reads from the output file descriptor associated * with the given print job, writing filtered PDF output to the associated * Guacamole stream, and terminating only after the print job has completed * processing or the associated Guacamole stream has closed. * * @param data * A pointer to the guac_rdp_print_job representing the print job that * should be read. * * @return * Always NULL. */ static void* guac_rdp_print_job_output_thread(void* data) { int length; char buffer[6048]; guac_rdp_print_job* job = (guac_rdp_print_job*) data; guac_client_log(job->client, GUAC_LOG_DEBUG, "Reading output from filter " "process..."); /* Read continuously while data remains */ while ((length = read(job->output_fd, buffer, sizeof(buffer))) > 0) { /* Wait for client to be ready for blob */ if (guac_rdp_print_job_wait_for_ack(job)) { guac_rdp_print_blob blob = { .job = job, .buffer = buffer, .length = length }; /* Write a single blob of output */ guac_client_for_user(job->client, job->user, guac_rdp_print_job_send_blob, &blob); } /* Abort if stream is closed */ else { guac_client_log(job->client, GUAC_LOG_DEBUG, "Print stream " "explicitly aborted."); break; } } /* Warn of read errors */ if (length < 0) guac_client_log(job->client, GUAC_LOG_ERROR, "Error reading from filter: %s", strerror(errno)); /* Terminate stream */ guac_client_for_user(job->client, job->user, guac_rdp_print_job_end_stream, job); /* Ensure all associated file descriptors are closed */ close(job->input_fd); close(job->output_fd); guac_client_log(job->client, GUAC_LOG_DEBUG, "Print job completed."); return NULL; } void* guac_rdp_print_job_alloc(guac_user* user, void* data) { /* Allocate nothing if user does not exist */ if (user == NULL) return NULL; /* Allocate stream for print job output */ guac_stream* stream = guac_user_alloc_stream(user); if (stream == NULL) return NULL; /* Bail early if allocation fails */ guac_rdp_print_job* job = malloc(sizeof(guac_rdp_print_job)); if (job == NULL) return NULL; /* Associate job with stream and dependent data */ job->client = user->client; job->user = user; job->stream = stream; job->bytes_received = 0; /* Set default filename for job */ strcpy(job->filename, GUAC_RDP_PRINT_JOB_DEFAULT_FILENAME); /* Prepare stream for receipt of acks */ stream->ack_handler = guac_rdp_print_filter_ack_handler; stream->data = job; /* Create print filter process */ job->filter_pid = guac_rdp_create_filter_process(job->client, &job->input_fd, &job->output_fd); /* Abort if print filter process cannot be created */ if (job->filter_pid == -1) { guac_user_free_stream(user, stream); free(job); return NULL; } /* Init stream state signal and lock */ job->state = GUAC_RDP_PRINT_JOB_WAITING_FOR_ACK; pthread_cond_init(&job->state_modified, NULL); pthread_mutex_init(&job->state_lock, NULL); /* Start output thread */ pthread_create(&job->output_thread, NULL, guac_rdp_print_job_output_thread, job); /* Print job allocated successfully */ return job; } /** * Attempts to parse the given PostScript "%%Title:" header, storing the * contents within the filename of the given print job. If the given buffer * does not immediately begin with the "%%Title:" header, this function has no * effect. * * @param job * The job whose filename should be set if the "%%Title:" header is * successfully parsed. * * @param buffer * The buffer to parse as the "%%Title:" header. * * @param length * The number of bytes within the buffer. * * @return * Non-zero if the given buffer began with the "%%Title:" header and this * header was successfully parsed, zero otherwise. */ static int guac_rdp_print_job_parse_title_header(guac_rdp_print_job* job, void* buffer, int length) { int i; char* current = buffer; char* filename = job->filename; /* Verify that the buffer begins with "%%Title: " */ if (strncmp(current, "%%Title: ", 9) != 0) return 0; /* Skip past "%%Title: " */ current += 9; length -= 9; /* Calculate space remaining in filename */ int remaining = sizeof(job->filename) - 5 /* ".pdf\0" */; /* Do not exceed bounds of provided buffer */ if (length < remaining) remaining = length; /* Copy as much of title as reasonable */ for (i = 0; i < remaining; i++) { /* Get character, stop at EOL */ char c = *(current++); if (c == '\r' || c == '\n') break; /* Copy to filename */ *(filename++) = c; } /* Append extension to filename */ strcpy(filename, ".pdf"); /* Title successfully parsed */ return 1; } /** * Searches through the given buffer for PostScript headers denoting the title * of the document, assigning the filename of the given print job using the * discovered title. If no title can be found within * GUAC_RDP_PRINT_JOB_TITLE_SEARCH_LENGTH bytes, this function has no effect. * * @param job * The job whose filename should be set if the document title can be found * within the given buffer. * * @param buffer * The buffer to search for the document title. * * @param length * The number of bytes within the buffer. */ static void guac_rdp_print_job_read_filename(guac_rdp_print_job* job, void* buffer, int length) { char* current = buffer; int i; /* Restrict search area */ if (length > GUAC_RDP_PRINT_JOB_TITLE_SEARCH_LENGTH) length = GUAC_RDP_PRINT_JOB_TITLE_SEARCH_LENGTH; /* Search for document title within buffer */ for (i = 0; i < length; i++) { /* If document title has been found, we're done */ if (guac_rdp_print_job_parse_title_header(job, current, length)) break; /* Advance to next character */ length--; current++; } } int guac_rdp_print_job_write(guac_rdp_print_job* job, void* buffer, int length) { /* Create print job, if not yet created */ if (job->bytes_received == 0) { /* Attempt to read document title from first buffer of data */ guac_rdp_print_job_read_filename(job, buffer, length); /* Begin print stream */ guac_client_for_user(job->client, job->user, guac_rdp_print_job_begin_stream, job); } /* Update counter of bytes received */ job->bytes_received += length; /* Write data to filter process */ return write(job->input_fd, buffer, length); } void guac_rdp_print_job_free(guac_rdp_print_job* job) { /* No more input will be provided */ close(job->input_fd); /* Wait for job to terminate */ pthread_join(job->output_thread, NULL); /* Destroy lock */ pthread_mutex_destroy(&(job->state_lock)); /* Free base structure */ free(job); } void guac_rdp_print_job_kill(guac_rdp_print_job* job) { /* Stop all handling of I/O */ close(job->input_fd); close(job->output_fd); /* Mark stream as closed */ guac_rdp_print_job_set_state(job, GUAC_RDP_PRINT_JOB_CLOSED); } guacamole-server-1.3.0/src/protocols/rdp/keyboard.c0000644000175100001440000006050013764613616017254 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "decompose.h" #include "keyboard.h" #include "keymap.h" #include "rdp.h" #include #include #include #include /** * Translates the given keysym into the corresponding lock flag, as would be * required by the RDP synchronize event. If the given keysym does not * represent a lock key, zero is returned. * * @param keysym * The keysym to translate into a RDP lock flag. * * @return * The RDP lock flag which corresponds to the given keysym, or zero if the * given keysym does not represent a lock key. */ static int guac_rdp_keyboard_lock_flag(int keysym) { /* Translate keysym into corresponding lock flag */ switch (keysym) { /* Scroll lock */ case GUAC_RDP_KEYSYM_SCROLL_LOCK: return KBD_SYNC_SCROLL_LOCK; /* Kana lock */ case GUAC_RDP_KEYSYM_KANA_LOCK: return KBD_SYNC_KANA_LOCK; /* Num lock */ case GUAC_RDP_KEYSYM_NUM_LOCK: return KBD_SYNC_NUM_LOCK; /* Caps lock */ case GUAC_RDP_KEYSYM_CAPS_LOCK: return KBD_SYNC_CAPS_LOCK; } /* Not a lock key */ return 0; } /** * Immediately sends an RDP key event having the given scancode and flags. * * @param rdp_client * The RDP client instance associated with the RDP session along which the * key event should be sent. * * @param scancode * The scancode of the key to press or release via the RDP key event. * * @param flags * Any RDP-specific flags required for the provided scancode to have the * intended meaning, such as KBD_FLAGS_EXTENDED. The possible flags and * their meanings are dictated by RDP. KBD_FLAGS_DOWN and KBD_FLAGS_UP * need not be specified here - they will automatically be added depending * on the value specified for the pressed parameter. * * @param pressed * Non-zero if the key is being pressed, zero if the key is being released. */ static void guac_rdp_send_key_event(guac_rdp_client* rdp_client, int scancode, int flags, int pressed) { /* Determine proper event flag for pressed state */ int pressed_flags; if (pressed) pressed_flags = KBD_FLAGS_DOWN; else pressed_flags = KBD_FLAGS_RELEASE; /* Skip if not yet connected */ freerdp* rdp_inst = rdp_client->rdp_inst; if (rdp_inst == NULL) return; /* Send actual key */ rdp_inst->input->KeyboardEvent(rdp_inst->input, flags | pressed_flags, scancode); } /** * Immediately sends an RDP Unicode event having the given Unicode codepoint. * Unlike key events, RDP Unicode events do have not a pressed or released * state. They represent strictly the input of a single character, and are * technically independent of the keyboard. * * @param rdp_client * The RDP client instance associated with the RDP session along which the * Unicode event should be sent. * * @param codepoint * The Unicode codepoint of the character being input via the Unicode * event. */ static void guac_rdp_send_unicode_event(guac_rdp_client* rdp_client, int codepoint) { /* Skip if not yet connected */ freerdp* rdp_inst = rdp_client->rdp_inst; if (rdp_inst == NULL) return; /* Send Unicode event */ rdp_inst->input->UnicodeKeyboardEvent( rdp_inst->input, 0, codepoint); } /** * Immediately sends an RDP synchonize event having the given flags. An RDP * synchronize event sets the state of remote lock keys absolutely, where a * lock key will be active only if its corresponding flag is set in the event. * * @param rdp_client * The RDP client instance associated with the RDP session along which the * synchronize event should be sent. * * @param flags * Bitwise OR of the flags representing the lock keys which should be set, * if any, as dictated by the RDP protocol. If no flags are set, then no * lock keys will be active. */ static void guac_rdp_send_synchronize_event(guac_rdp_client* rdp_client, UINT32 flags) { /* Skip if not yet connected */ freerdp* rdp_inst = rdp_client->rdp_inst; if (rdp_inst == NULL) return; /* Synchronize lock key states */ rdp_inst->input->SynchronizeEvent(rdp_inst->input, flags); } /** * Given a keyboard instance and X11 keysym, returns a pointer to the * keys_by_keysym entry that represents the key having that keysym within the * keyboard, regardless of whether the key is currently defined. If no such key * can exist (the keysym cannot be mapped or is out of range), NULL is * returned. * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. * * @param keysym * The keysym of the key to lookup within the given keyboard. * * @return * A pointer to the keys_by_keysym entry which represents or can represent * the key having the given keysym, or NULL if no such keysym can be * defined within a guac_rdp_keyboard structure. */ static guac_rdp_key** guac_rdp_keyboard_map_key(guac_rdp_keyboard* keyboard, int keysym) { int index; /* Map keysyms between 0x0000 and 0xFFFF directly */ if (keysym >= 0x0000 && keysym <= 0xFFFF) index = keysym; /* Map all Unicode keysyms from U+0000 to U+FFFF */ else if (keysym >= 0x1000000 && keysym <= 0x100FFFF) index = 0x10000 + (keysym & 0xFFFF); /* All other keysyms are unmapped */ else return NULL; /* Corresponding key mapping (defined or not) has been located */ return &(keyboard->keys_by_keysym[index]); } /** * Returns the number of bits that are set within the given integer (the number * of 1s in the binary expansion of the given integer). * * @param value * The integer to read. * * @return * The number of bits that are set within the given integer. */ static int guac_rdp_count_bits(unsigned int value) { int bits = 0; while (value) { bits += value & 1; value >>= 1; } return bits; } /** * Returns an estimated cost for sending the necessary RDP events to type the * key described by the given guac_rdp_keysym_desc, given the current lock and * modifier state of the keyboard. A higher cost value indicates that a greater * number of events are expected to be required. * * Lower-cost approaches should be preferred when multiple alternatives exist * for typing a particular key, as the lower cost implies fewer additional key * events required to produce the expected behavior. For example, if Caps Lock * is enabled, typing an uppercase "A" by pressing the "A" key has a lower cost * than disabling Caps Lock and pressing Shift+A. * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. * * @param def * The guac_rdp_keysym_desc that describes the key being pressed, as well * as any requirements that must be satisfied for the key to be interpreted * as expected. * * @return * An arbitrary integer value which indicates the overall estimated * complexity of typing the given key. */ static int guac_rdp_keyboard_get_cost(guac_rdp_keyboard* keyboard, const guac_rdp_keysym_desc* def) { unsigned int modifier_flags = guac_rdp_keyboard_get_modifier_flags(keyboard); /* Each change to any key requires one event, by definition */ int cost = 1; /* Each change to a lock requires roughly two key events */ unsigned int update_locks = (def->set_locks & ~keyboard->lock_flags) | (def->clear_locks & keyboard->lock_flags); cost += guac_rdp_count_bits(update_locks) * 2; /* Each change to a modifier requires one key event */ unsigned int update_modifiers = (def->clear_modifiers & modifier_flags) | (def->set_modifiers & ~modifier_flags); cost += guac_rdp_count_bits(update_modifiers); return cost; } /** * Returns a pointer to the guac_rdp_key structure representing the * definition(s) and state of the key having the given keysym. If no such key * is defined within the keyboard layout of the RDP server, NULL is returned. * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. * * @param keysym * The keysym of the key to lookup within the given keyboard. * * @return * A pointer to the guac_rdp_key structure representing the definition(s) * and state of the key having the given keysym, or NULL if no such key is * defined within the keyboard layout of the RDP server. */ static guac_rdp_key* guac_rdp_keyboard_get_key(guac_rdp_keyboard* keyboard, int keysym) { /* Verify that the key is actually defined */ guac_rdp_key** key_by_keysym = guac_rdp_keyboard_map_key(keyboard, keysym); if (key_by_keysym == NULL) return NULL; return *key_by_keysym; } /** * Given a key which may have multiple possible definitions, returns the * definition that currently has the lowest cost, taking into account the * current keyboard lock and modifier states. * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. * * @param key * The key whose lowest-cost possible definition should be retrieved. * * @return * A pointer to the guac_rdp_keysym_desc which defines the current * lowest-cost method of typing the given key. */ static const guac_rdp_keysym_desc* guac_rdp_keyboard_get_definition(guac_rdp_keyboard* keyboard, guac_rdp_key* key) { /* Consistently map the same entry so long as the key is held */ if (key->pressed != NULL) return key->pressed; /* Calculate cost of first definition of key (there must always be at least * one definition) */ const guac_rdp_keysym_desc* best_def = key->definitions[0]; int best_cost = guac_rdp_keyboard_get_cost(keyboard, best_def); /* If further definitions exist, choose the definition with the lowest * overall cost */ for (int i = 1; i < key->num_definitions; i++) { const guac_rdp_keysym_desc* def = key->definitions[i]; int cost = guac_rdp_keyboard_get_cost(keyboard, def); if (cost < best_cost) { best_def = def; best_cost = cost; } } return best_def; } /** * Adds the keysym/scancode mapping described by the given guac_rdp_keysym_desc * to the internal mapping of the keyboard. If insufficient space remains for * additional keysyms, or the given keysym has already reached the maximum * number of possible definitions, the mapping is ignored and the failure is * logged. * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. * * @param mapping * The keysym/scancode mapping that should be added to the given keyboard. */ static void guac_rdp_keyboard_add_mapping(guac_rdp_keyboard* keyboard, const guac_rdp_keysym_desc* mapping) { /* Locate corresponding keysym-to-key translation entry within keyboard * structure */ guac_rdp_key** key_by_keysym = guac_rdp_keyboard_map_key(keyboard, mapping->keysym); if (key_by_keysym == NULL) { guac_client_log(keyboard->client, GUAC_LOG_DEBUG, "Ignoring unmappable keysym 0x%X", mapping->keysym); return; } /* If not yet pointing to a key, point keysym-to-key translation entry at * next available storage */ if (*key_by_keysym == NULL) { if (keyboard->num_keys == GUAC_RDP_KEYBOARD_MAX_KEYSYMS) { guac_client_log(keyboard->client, GUAC_LOG_DEBUG, "Key definition " "for keysym 0x%X dropped: Keymap exceeds maximum " "supported number of keysyms", mapping->keysym); return; } *key_by_keysym = &keyboard->keys[keyboard->num_keys++]; } guac_rdp_key* key = *key_by_keysym; /* Add new definition only if sufficient space remains */ if (key->num_definitions == GUAC_RDP_KEY_MAX_DEFINITIONS) { guac_client_log(keyboard->client, GUAC_LOG_DEBUG, "Key definition " "for keysym 0x%X dropped: Maximum number of possible " "definitions has been reached for this keysym", mapping->keysym); return; } /* Store new possible definition of key */ key->definitions[key->num_definitions++] = mapping; } /** * Loads all keysym/scancode mappings declared within the given keymap and its * parent keymap, if any. These mappings are stored within the given * guac_rdp_keyboard structure for future use in translating keysyms to the * scancodes required by RDP key events. * * @param keyboard * The guac_rdp_keyboard which should be initialized with the * keysym/scancode mapping defined in the given keymap. * * @param keymap * The keymap to use to populate the given client's keysym/scancode * mapping. */ static void guac_rdp_keyboard_load_keymap(guac_rdp_keyboard* keyboard, const guac_rdp_keymap* keymap) { /* If parent exists, load parent first */ if (keymap->parent != NULL) guac_rdp_keyboard_load_keymap(keyboard, keymap->parent); /* Log load */ guac_client_log(keyboard->client, GUAC_LOG_INFO, "Loading keymap \"%s\"", keymap->name); /* Copy mapping into keymap */ const guac_rdp_keysym_desc* mapping = keymap->mapping; while (mapping->keysym != 0) { guac_rdp_keyboard_add_mapping(keyboard, mapping++); } } guac_rdp_keyboard* guac_rdp_keyboard_alloc(guac_client* client, const guac_rdp_keymap* keymap) { guac_rdp_keyboard* keyboard = calloc(1, sizeof(guac_rdp_keyboard)); keyboard->client = client; /* Load keymap into keyboard */ guac_rdp_keyboard_load_keymap(keyboard, keymap); return keyboard; } void guac_rdp_keyboard_free(guac_rdp_keyboard* keyboard) { free(keyboard); } int guac_rdp_keyboard_is_defined(guac_rdp_keyboard* keyboard, int keysym) { /* Return whether the mapping actually exists */ return guac_rdp_keyboard_get_key(keyboard, keysym) != NULL; } int guac_rdp_keyboard_is_pressed(guac_rdp_keyboard* keyboard, int keysym) { guac_rdp_key* key = guac_rdp_keyboard_get_key(keyboard, keysym); return key != NULL && key->pressed != NULL; } unsigned int guac_rdp_keyboard_get_modifier_flags(guac_rdp_keyboard* keyboard) { unsigned int modifier_flags = 0; /* Shift */ if (guac_rdp_keyboard_is_pressed(keyboard, GUAC_RDP_KEYSYM_LSHIFT) || guac_rdp_keyboard_is_pressed(keyboard, GUAC_RDP_KEYSYM_RSHIFT)) modifier_flags |= GUAC_RDP_KEYMAP_MODIFIER_SHIFT; /* Dedicated AltGr key */ if (guac_rdp_keyboard_is_pressed(keyboard, GUAC_RDP_KEYSYM_RALT) || guac_rdp_keyboard_is_pressed(keyboard, GUAC_RDP_KEYSYM_ALTGR)) modifier_flags |= GUAC_RDP_KEYMAP_MODIFIER_ALTGR; /* AltGr via Ctrl+Alt */ if (guac_rdp_keyboard_is_pressed(keyboard, GUAC_RDP_KEYSYM_LALT) && (guac_rdp_keyboard_is_pressed(keyboard, GUAC_RDP_KEYSYM_RCTRL) || guac_rdp_keyboard_is_pressed(keyboard, GUAC_RDP_KEYSYM_LCTRL))) modifier_flags |= GUAC_RDP_KEYMAP_MODIFIER_ALTGR; return modifier_flags; } /** * Presses/releases the requested key by sending one or more RDP key events, as * defined within the keymap defining that key. * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. * * @param key * The guac_rdp_keysym_desc of the key being pressed or released, as * retrieved from the relevant keymap. * * @param pressed * Zero if the key is being released, non-zero otherwise. * * @return * Zero if the key was successfully pressed/released, non-zero if the key * cannot be sent using RDP key events. */ static const guac_rdp_keysym_desc* guac_rdp_keyboard_send_defined_key(guac_rdp_keyboard* keyboard, guac_rdp_key* key, int pressed) { guac_client* client = keyboard->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; const guac_rdp_keysym_desc* keysym_desc = guac_rdp_keyboard_get_definition(keyboard, key); if (keysym_desc->scancode == 0) return NULL; /* Update state of required locks and modifiers only when key is just * now being pressed */ if (pressed) { guac_rdp_keyboard_update_locks(keyboard, keysym_desc->set_locks, keysym_desc->clear_locks); guac_rdp_keyboard_update_modifiers(keyboard, keysym_desc->set_modifiers, keysym_desc->clear_modifiers); } /* Fire actual key event for target key */ guac_rdp_send_key_event(rdp_client, keysym_desc->scancode, keysym_desc->flags, pressed); return keysym_desc; } /** * Presses and releases the requested key by sending one or more RDP events, * without relying on a keymap for that key. This will typically involve either * sending the key using a Unicode event or decomposing the key into a series * of keypresses involving deadkeys. * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. * * @param keysym * The keysym of the key to press and release. */ static void guac_rdp_keyboard_send_missing_key(guac_rdp_keyboard* keyboard, int keysym) { guac_client* client = keyboard->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Attempt to type using dead keys */ if (!guac_rdp_decompose_keysym(keyboard, keysym)) return; guac_client_log(client, GUAC_LOG_DEBUG, "Sending keysym 0x%x as " "Unicode", keysym); /* Translate keysym into codepoint */ int codepoint; if (keysym <= 0xFF) codepoint = keysym; else if (keysym >= 0x1000000) codepoint = keysym & 0xFFFFFF; else { guac_client_log(client, GUAC_LOG_DEBUG, "Unmapped keysym has no " "equivalent unicode value: 0x%x", keysym); return; } /* Send as Unicode event */ guac_rdp_send_unicode_event(rdp_client, codepoint); } void guac_rdp_keyboard_update_locks(guac_rdp_keyboard* keyboard, unsigned int set_flags, unsigned int clear_flags) { guac_client* client = keyboard->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Calculate updated lock flags */ unsigned int lock_flags = (keyboard->lock_flags | set_flags) & ~clear_flags; /* Synchronize remote side only if lock flags have changed */ if (lock_flags != keyboard->lock_flags) { guac_rdp_send_synchronize_event(rdp_client, lock_flags); keyboard->lock_flags = lock_flags; } } void guac_rdp_keyboard_update_modifiers(guac_rdp_keyboard* keyboard, unsigned int set_flags, unsigned int clear_flags) { unsigned int modifier_flags = guac_rdp_keyboard_get_modifier_flags(keyboard); /* Only clear modifiers that are set */ clear_flags &= modifier_flags; /* Only set modifiers that are currently cleared */ set_flags &= ~modifier_flags; /* Press/release Shift as needed */ if (set_flags & GUAC_RDP_KEYMAP_MODIFIER_SHIFT) { guac_rdp_keyboard_update_keysym(keyboard, GUAC_RDP_KEYSYM_LSHIFT, 1, GUAC_RDP_KEY_SOURCE_SYNTHETIC); } else if (clear_flags & GUAC_RDP_KEYMAP_MODIFIER_SHIFT) { guac_rdp_keyboard_update_keysym(keyboard, GUAC_RDP_KEYSYM_LSHIFT, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC); guac_rdp_keyboard_update_keysym(keyboard, GUAC_RDP_KEYSYM_RSHIFT, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC); } /* Press/release AltGr as needed */ if (set_flags & GUAC_RDP_KEYMAP_MODIFIER_ALTGR) { guac_rdp_keyboard_update_keysym(keyboard, GUAC_RDP_KEYSYM_ALTGR, 1, GUAC_RDP_KEY_SOURCE_SYNTHETIC); } else if (clear_flags & GUAC_RDP_KEYMAP_MODIFIER_ALTGR) { guac_rdp_keyboard_update_keysym(keyboard, GUAC_RDP_KEYSYM_ALTGR, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC); guac_rdp_keyboard_update_keysym(keyboard, GUAC_RDP_KEYSYM_LALT, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC); guac_rdp_keyboard_update_keysym(keyboard, GUAC_RDP_KEYSYM_RALT, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC); guac_rdp_keyboard_update_keysym(keyboard, GUAC_RDP_KEYSYM_LCTRL, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC); guac_rdp_keyboard_update_keysym(keyboard, GUAC_RDP_KEYSYM_RCTRL, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC); } } int guac_rdp_keyboard_update_keysym(guac_rdp_keyboard* keyboard, int keysym, int pressed, guac_rdp_key_source source) { /* Synchronize lock keys states, if this has not yet been done */ if (!keyboard->synchronized) { guac_client* client = keyboard->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Synchronize remote lock key states with local state */ guac_rdp_send_synchronize_event(rdp_client, keyboard->lock_flags); keyboard->synchronized = 1; } guac_rdp_key* key = guac_rdp_keyboard_get_key(keyboard, keysym); /* Update tracking of client-side keyboard state but only for keys which * are tracked server-side, as well (to ensure that the key count remains * correct, even if a user sends extra unbalanced or excessive press and * release events) */ if (source == GUAC_RDP_KEY_SOURCE_CLIENT && key != NULL) { if (pressed && !key->user_pressed) { keyboard->user_pressed_keys++; key->user_pressed = 1; } else if (!pressed && key->user_pressed) { keyboard->user_pressed_keys--; key->user_pressed = 0; } } /* Send events and update server-side lock state only if server-side key * state is changing (or if server-side state of this key is untracked) */ if (key == NULL || (pressed && key->pressed == NULL) || (!pressed && key->pressed != NULL)) { /* Toggle locks on keydown */ if (pressed) keyboard->lock_flags ^= guac_rdp_keyboard_lock_flag(keysym); /* If key is known, update state and attempt to send using normal RDP key * events */ const guac_rdp_keysym_desc* definition = NULL; if (key != NULL) { definition = guac_rdp_keyboard_send_defined_key(keyboard, key, pressed); key->pressed = pressed ? definition : NULL; } /* Fall back to dead keys or Unicode events if otherwise undefined inside * current keymap (note that we only handle "pressed" here, as neither * Unicode events nor dead keys can have a pressed/released state) */ if (definition == NULL && pressed) { guac_rdp_keyboard_send_missing_key(keyboard, keysym); } } /* Reset RDP server keyboard state (releasing any automatically * pressed keys) once all keys have been released on the client * side */ if (source == GUAC_RDP_KEY_SOURCE_CLIENT && keyboard->user_pressed_keys == 0) guac_rdp_keyboard_reset(keyboard); return 0; } void guac_rdp_keyboard_reset(guac_rdp_keyboard* keyboard) { /* Release all pressed keys */ for (int i = 0; i < keyboard->num_keys; i++) { guac_rdp_key* key = &keyboard->keys[i]; if (key->pressed != NULL) guac_rdp_keyboard_update_keysym(keyboard, key->pressed->keysym, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC); } } BOOL guac_rdp_keyboard_set_indicators(rdpContext* context, UINT16 flags) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; pthread_rwlock_rdlock(&(rdp_client->lock)); /* Skip if keyboard not yet ready */ guac_rdp_keyboard* keyboard = rdp_client->keyboard; if (keyboard == NULL) goto complete; /* Update with received locks */ guac_client_log(client, GUAC_LOG_DEBUG, "Received updated keyboard lock flags from RDP server: 0x%X", flags); keyboard->lock_flags = flags; complete: pthread_rwlock_unlock(&(rdp_client->lock)); return TRUE; } guacamole-server-1.3.0/src/protocols/rdp/color.c0000644000175100001440000000475113764613616016600 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "settings.h" #include #include #include #include #include #include UINT32 guac_rdp_get_native_pixel_format(BOOL alpha) { uint32_t int_value; uint8_t raw_bytes[4] = { 0x0A, 0x0B, 0x0C, 0x0D }; memcpy(&int_value, raw_bytes, sizeof(raw_bytes)); /* Local platform stores bytes in decreasing order of significance * (big-endian) */ if (int_value == 0x0A0B0C0D) return alpha ? PIXEL_FORMAT_ARGB32 : PIXEL_FORMAT_XRGB32; /* Local platform stores bytes in increasing order of significance * (little-endian) */ else return alpha ? PIXEL_FORMAT_BGRA32 : PIXEL_FORMAT_BGRX32; } UINT32 guac_rdp_convert_color(rdpContext* context, UINT32 color) { int depth = guac_rdp_get_depth(context->instance); int src_format = gdi_get_pixel_format(depth); int dst_format = guac_rdp_get_native_pixel_format(TRUE); rdpGdi* gdi = context->gdi; /* Convert provided color into the intermediate representation expected by * FreeRDPConvertColor() */ UINT32 intermed = ReadColor((BYTE*) &color, src_format); /* Convert color from RDP source format to the native format used by Cairo, * still maintaining intermediate representation */ #ifdef HAVE_FREERDPCONVERTCOLOR intermed = FreeRDPConvertColor(intermed, src_format, dst_format, &gdi->palette); #else intermed = ConvertColor(intermed, src_format, dst_format, &gdi->palette); #endif /* Convert color from intermediate representation to the actual desired * format */ WriteColor((BYTE*) &color, dst_format, intermed); return color; } guacamole-server-1.3.0/src/protocols/rdp/resolution.h0000644000175100001440000000326113613156714017657 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_RESOLUTION_H #define GUAC_RDP_RESOLUTION_H #include /** * Returns whether the given resolution is reasonable for the given user, * based on arbitrary criteria for reasonability. * * @param user * The guac_user to test the given resolution against. * * @param resolution * The resolution to test, in DPI. * * @return * Non-zero if the resolution is reasonable, zero otherwise. */ int guac_rdp_resolution_reasonable(guac_user* user, int resolution); /** * Returns a reasonable resolution for the remote display, given the size and * resolution of a guac_user. * * @param user * The guac_user whose size and resolution shall be used to determine an * appropriate remote display resolution. * * @return * A reasonable resolution for the remote display, in DPI. */ int guac_rdp_suggest_resolution(guac_user* user); #endif guacamole-server-1.3.0/src/protocols/rdp/log.c0000644000175100001440000000443113764613616016236 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include /** * The guac_client that should be used within this process for FreeRDP log * messages. As all Guacamole connections are isolated at the process level, * this will only ever be set to the guac_client of the current process' * connection. */ static guac_client* current_client = NULL; /** * Logs the text data within the given message to the logging facilities of the * guac_client currently stored under current_client (the guac_client of the * current process). * * @param message * The message to log. * * @return * TRUE if the message was successfully logged, FALSE otherwise. */ static BOOL guac_rdp_wlog_text_message(const wLogMessage* message) { /* Fail if log not yet redirected */ if (current_client == NULL) return FALSE; /* Log all received messages at the debug level */ guac_client_log(current_client, GUAC_LOG_DEBUG, "%s", message->TextString); return TRUE; } void guac_rdp_redirect_wlog(guac_client* client) { wLogCallbacks callbacks = { .message = guac_rdp_wlog_text_message }; current_client = client; /* Reconfigure root logger to use callback appender */ wLog* root = WLog_GetRoot(); WLog_SetLogAppenderType(root, WLOG_APPENDER_CALLBACK); /* Set appender callbacks to our own */ wLogAppender* appender = WLog_GetLogAppender(root); WLog_ConfigureAppender(appender, "callbacks", &callbacks); } guacamole-server-1.3.0/src/protocols/rdp/channels/0000755000175100001440000000000013772471160017155 500000000000000guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/0000755000175100001440000000000013772471160020270 500000000000000guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c0000644000175100001440000001766213764613616023171 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/rdpdr/rdpdr-printer.h" #include "channels/rdpdr/rdpdr.h" #include "print-job.h" #include "rdp.h" #include "unicode.h" #include #include #include #include #include #include #include void guac_rdpdr_process_print_job_create(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { guac_client* client = svc->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Log creation of print job */ guac_client_log(client, GUAC_LOG_INFO, "Print job created"); /* Create print job */ rdp_client->active_job = guac_client_for_owner(client, guac_rdp_print_job_alloc, NULL); /* Respond with success */ wStream* output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, 0); /* fileId */ guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_process_print_job_write(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { guac_client* client = svc->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_print_job* job = (guac_rdp_print_job*) rdp_client->active_job; unsigned char* buffer; int length; int status; /* Verify that Stream contains at least 32 bytes (UINT32 + 8 + 20) */ if (Stream_GetRemainingLength(input_stream) < 32) { guac_client_log(client, GUAC_LOG_WARNING, "Print job write stream does " "not contain the expected number of bytes. Printer redirection " "may not work as expected."); return; } /* Read buffer of print data */ Stream_Read_UINT32(input_stream, length); Stream_Seek(input_stream, 8); /* Offset */ Stream_Seek(input_stream, 20); /* Padding */ buffer = Stream_Pointer(input_stream); /* Verify the stream has at least length number of bytes remaining. */ if (Stream_GetRemainingLength(input_stream) < length) { guac_client_log(client, GUAC_LOG_WARNING, "Print job write stream does " "not contain the expected number of bytes. Printer redirection " "may not work as expected."); return; } /* Write data only if job exists, translating status for RDP */ if (job != NULL && (length = guac_rdp_print_job_write(job, buffer, length)) >= 0) { status = STATUS_SUCCESS; } /* Report device offline if write fails */ else { status = STATUS_DEVICE_OFF_LINE; length = 0; } wStream* output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, status, 5); Stream_Write_UINT32(output_stream, length); Stream_Write_UINT8(output_stream, 0); /* Padding */ guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_process_print_job_close(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { guac_client* client = svc->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_print_job* job = (guac_rdp_print_job*) rdp_client->active_job; /* End print job */ if (job != NULL) { guac_rdp_print_job_free(job); rdp_client->active_job = NULL; } wStream* output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, 0); /* Padding */ guac_rdp_common_svc_write(svc, output_stream); /* Log end of print job */ guac_client_log(client, GUAC_LOG_INFO, "Print job closed"); } void guac_rdpdr_device_printer_iorequest_handler(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { switch (iorequest->major_func) { /* Print job create */ case IRP_MJ_CREATE: guac_rdpdr_process_print_job_create(svc, device, iorequest, input_stream); break; /* Printer job write */ case IRP_MJ_WRITE: guac_rdpdr_process_print_job_write(svc, device, iorequest, input_stream); break; /* Printer job close */ case IRP_MJ_CLOSE: guac_rdpdr_process_print_job_close(svc, device, iorequest, input_stream); break; /* Log unknown */ default: guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown printer " "I/O request function: 0x%x/0x%x", iorequest->major_func, iorequest->minor_func); } } void guac_rdpdr_device_printer_free_handler(guac_rdp_common_svc* svc, guac_rdpdr_device* device) { Stream_Free(device->device_announce, 1); } void guac_rdpdr_register_printer(guac_rdp_common_svc* svc, char* printer_name) { guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; int id = rdpdr->devices_registered++; /* Get new device */ guac_rdpdr_device* device = &(rdpdr->devices[id]); /* Init device */ device->device_id = id; device->device_name = printer_name; int device_name_len = guac_utf8_strlen(device->device_name); device->device_type = RDPDR_DTYP_PRINT; device->dos_name = "PRN1\0\0\0\0"; /* Set up device announce stream */ int prt_name_len = (device_name_len + 1) * 2; device->device_announce_len = 44 + prt_name_len + GUAC_PRINTER_DRIVER_LENGTH; device->device_announce = Stream_New(NULL, device->device_announce_len); /* Write common information. */ Stream_Write_UINT32(device->device_announce, device->device_type); Stream_Write_UINT32(device->device_announce, device->device_id); Stream_Write(device->device_announce, device->dos_name, 8); /* DeviceDataLength */ Stream_Write_UINT32(device->device_announce, 24 + prt_name_len + GUAC_PRINTER_DRIVER_LENGTH); /* Begin printer-specific information */ Stream_Write_UINT32(device->device_announce, RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER | RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER); /* Printer flags */ Stream_Write_UINT32(device->device_announce, 0); /* Reserved - must be 0. */ Stream_Write_UINT32(device->device_announce, 0); /* PnPName Length - ignored. */ Stream_Write_UINT32(device->device_announce, GUAC_PRINTER_DRIVER_LENGTH); Stream_Write_UINT32(device->device_announce, prt_name_len); Stream_Write_UINT32(device->device_announce, 0); /* CachedFields length. */ Stream_Write(device->device_announce, GUAC_PRINTER_DRIVER, GUAC_PRINTER_DRIVER_LENGTH); guac_rdp_utf8_to_utf16((const unsigned char*) device->device_name, device_name_len + 1, (char*) Stream_Pointer(device->device_announce), prt_name_len); Stream_Seek(device->device_announce, prt_name_len); /* Set handlers */ device->iorequest_handler = guac_rdpdr_device_printer_iorequest_handler; device->free_handler = guac_rdpdr_device_printer_free_handler; } guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h0000644000175100001440000001075413764613616025571 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_FILE_INFO_H #define GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_FILE_INFO_H /** * Handlers for file queries received over the RDPDR channel via the * IRP_MJ_QUERY_INFORMATION major function. * * @file rdpdr-fs-messages-file-info.h */ #include "channels/common-svc.h" #include "channels/rdpdr/rdpdr.h" #include /** * Handler for Device I/O Requests which set/update file information. * * @param svc * The guac_rdp_common_svc representing the static virtual channel being * used for RDPDR. * * @param device * The guac_rdpdr_device of the relevant device, as dictated by the * deviceId field of the common RDPDR header within the received PDU. * Within the guac_rdpdr_iorequest structure, the deviceId field is stored * within device_id. * * @param iorequest * The contents of the common RDPDR Device I/O Request header shared by all * RDPDR devices. * * @param length * The length of the SetBuffer field of the I/O request, in bytes. Whether * the SetBuffer field is applicable to a particular request, as well as * the specific contents of that field, depend on the type of request. * * @param input_stream * The remaining data within the received PDU, following the common RDPDR * Device I/O Request header and length field. If the SetBuffer field is * used for this request, the first byte of SetBuffer will be the first * byte read from this stream. */ typedef void guac_rdpdr_set_information_request_handler(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, int length, wStream* input_stream); /** * Processes a query for FileBasicInformation. From the documentation, this is * "used to query a file for the times of creation, last access, last write, * and change, in addition to file attribute information." */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_basic_info; /** * Processes a query for FileStandardInformation. From the documentation, this * is "used to query for file information such as allocation size, end-of-file * position, and number of links." */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_standard_info; /** * Processes a query for FileAttributeTagInformation. From the documentation * this is "used to query for file attribute and reparse tag information." */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_attribute_tag_info; /** * Process a set operation for FileRenameInformation. From the documentation, * this operation is used to rename a file. */ guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_rename_info; /** * Process a set operation for FileAllocationInformation. From the * documentation, this operation is used to set a file's allocation size. */ guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_allocation_info; /** * Process a set operation for FileDispositionInformation. From the * documentation, this operation is used to mark a file for deletion. */ guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_disposition_info; /** * Process a set operation for FileEndOfFileInformation. From the * documentation, this operation is used "to set end-of-file information for * a file." */ guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_end_of_file_info; /** * Process a set operation for FileBasicInformation. From the documentation, * this is "used to set file information such as the times of creation, last * access, last write, and change, in addition to file attributes." */ guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_basic_info; #endif guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c0000644000175100001440000002643113764613616025563 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/rdpdr/rdpdr-fs-messages-file-info.h" #include "channels/rdpdr/rdpdr.h" #include "download.h" #include "fs.h" #include "unicode.h" #include #include #include #include #include #include #include void guac_rdpdr_fs_process_query_basic_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { wStream* output_stream; guac_rdp_fs_file* file; /* Get file */ file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id); if (file == NULL) return; guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, iorequest->file_id); output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 40); Stream_Write_UINT32(output_stream, 36); Stream_Write_UINT64(output_stream, file->ctime); /* CreationTime */ Stream_Write_UINT64(output_stream, file->atime); /* LastAccessTime */ Stream_Write_UINT64(output_stream, file->mtime); /* LastWriteTime */ Stream_Write_UINT64(output_stream, file->mtime); /* ChangeTime */ Stream_Write_UINT32(output_stream, file->attributes); /* FileAttributes */ /* Reserved field must not be sent */ guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_query_standard_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { wStream* output_stream; guac_rdp_fs_file* file; BOOL is_directory = FALSE; /* Get file */ file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id); if (file == NULL) return; guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, iorequest->file_id); if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = TRUE; output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 26); Stream_Write_UINT32(output_stream, 22); Stream_Write_UINT64(output_stream, file->size); /* AllocationSize */ Stream_Write_UINT64(output_stream, file->size); /* EndOfFile */ Stream_Write_UINT32(output_stream, 1); /* NumberOfLinks */ Stream_Write_UINT8(output_stream, 0); /* DeletePending */ Stream_Write_UINT8(output_stream, is_directory); /* Directory */ /* Reserved field must not be sent */ guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { wStream* output_stream; guac_rdp_fs_file* file; /* Get file */ file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id); if (file == NULL) return; guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, iorequest->file_id); output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 12); Stream_Write_UINT32(output_stream, 8); Stream_Write_UINT32(output_stream, file->attributes); /* FileAttributes */ Stream_Write_UINT32(output_stream, 0); /* ReparseTag */ /* Reserved field must not be sent */ guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, int length, wStream* input_stream) { int result; int filename_length; wStream* output_stream; char destination_path[GUAC_RDP_FS_MAX_PATH]; /* Check stream size prior to reading. */ if (Stream_GetRemainingLength(input_stream) < 6) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set " "Information Request (FileRenameInformation) PDU does not " "contain the expected number of bytes. File redirection " "may not work as expected."); return; } /* Read structure */ Stream_Seek_UINT8(input_stream); /* ReplaceIfExists */ Stream_Seek_UINT8(input_stream); /* RootDirectory */ Stream_Read_UINT32(input_stream, filename_length); /* FileNameLength */ if (Stream_GetRemainingLength(input_stream) < filename_length) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set " "Information Request (FileRenameInformation) PDU does not " "contain the expected number of bytes. File redirection " "may not work as expected."); return; } /* Convert name to UTF-8 */ guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), filename_length/2, destination_path, sizeof(destination_path)); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]" "destination_path=\"%s\"", __func__, iorequest->file_id, destination_path); /* If file moving to \Download folder, start stream, do not move */ if (strncmp(destination_path, "\\Download\\", 10) == 0 && !((guac_rdp_fs*) device->data)->disable_download) { guac_rdp_fs_file* file; /* Get file */ file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id); if (file == NULL) return; /* Initiate download, pretend move succeeded */ guac_client_for_owner(svc->client, guac_rdp_download_to_user, file->absolute_path); output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4); } /* Otherwise, rename as requested */ else { result = guac_rdp_fs_rename((guac_rdp_fs*) device->data, iorequest->file_id, destination_path); if (result < 0) output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, guac_rdp_fs_get_status(result), 4); else output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4); } Stream_Write_UINT32(output_stream, length); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, int length, wStream* input_stream) { int result; UINT64 size; wStream* output_stream; /* Check to make sure the stream has at least 8 bytes (UINT64) */ if (Stream_GetRemainingLength(input_stream) < 8) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set " "Information Request (FileAllocationInformation) PDU does not " "contain the expected number of bytes. File redirection " "may not work as expected."); return; } /* Read new size */ Stream_Read_UINT64(input_stream, size); /* AllocationSize */ guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] " "size=%" PRIu64, __func__, iorequest->file_id, (uint64_t) size); /* Truncate file */ result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, iorequest->file_id, size); if (result < 0) output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, guac_rdp_fs_get_status(result), 4); else output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, length); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_set_disposition_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, int length, wStream* input_stream) { wStream* output_stream; /* Delete file */ int result = guac_rdp_fs_delete((guac_rdp_fs*) device->data, iorequest->file_id); if (result < 0) output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, guac_rdp_fs_get_status(result), 4); else output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, iorequest->file_id); Stream_Write_UINT32(output_stream, length); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, int length, wStream* input_stream) { int result; UINT64 size; wStream* output_stream; /* Check to make sure stream contains at least 8 bytes (UINT64) */ if (Stream_GetRemainingLength(input_stream) < 8) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set " "Information Request (FileEndOfFileInformation) PDU does not " "contain the expected number of bytes. File redirection " "may not work as expected."); return; } /* Read new size */ Stream_Read_UINT64(input_stream, size); /* AllocationSize */ guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] " "size=%" PRIu64, __func__, iorequest->file_id, (uint64_t) size); /* Truncate file */ result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, iorequest->file_id, size); if (result < 0) output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, guac_rdp_fs_get_status(result), 4); else output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, length); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_set_basic_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, int length, wStream* input_stream) { wStream* output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4); /* Currently do nothing, just respond */ Stream_Write_UINT32(output_stream, length); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] IGNORED", __func__, iorequest->file_id); guac_rdp_common_svc_write(svc, output_stream); } guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c0000644000175100001440000001331313764613616025437 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/common-svc.h" #include "channels/rdpdr/rdpdr-fs-messages-vol-info.h" #include "channels/rdpdr/rdpdr-fs.h" #include "channels/rdpdr/rdpdr.h" #include "fs.h" #include #include #include #include #include #include #include void guac_rdpdr_fs_process_query_volume_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { wStream* output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 21 + GUAC_FILESYSTEM_LABEL_LENGTH); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, iorequest->file_id); Stream_Write_UINT32(output_stream, 17 + GUAC_FILESYSTEM_LABEL_LENGTH); Stream_Write_UINT64(output_stream, 0); /* VolumeCreationTime */ Stream_Write_UINT32(output_stream, 0); /* VolumeSerialNumber */ Stream_Write_UINT32(output_stream, GUAC_FILESYSTEM_LABEL_LENGTH); Stream_Write_UINT8(output_stream, FALSE); /* SupportsObjects */ /* Reserved field must not be sent */ Stream_Write(output_stream, GUAC_FILESYSTEM_LABEL, GUAC_FILESYSTEM_LABEL_LENGTH); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_query_size_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { guac_rdp_fs_info info = {0}; guac_rdp_fs_get_info((guac_rdp_fs*) device->data, &info); wStream* output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 28); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, iorequest->file_id); Stream_Write_UINT32(output_stream, 24); Stream_Write_UINT64(output_stream, info.blocks_total); /* TotalAllocationUnits */ Stream_Write_UINT64(output_stream, info.blocks_available); /* AvailableAllocationUnits */ Stream_Write_UINT32(output_stream, 1); /* SectorsPerAllocationUnit */ Stream_Write_UINT32(output_stream, info.block_size); /* BytesPerSector */ guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_query_device_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { wStream* output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 12); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, iorequest->file_id); Stream_Write_UINT32(output_stream, 8); Stream_Write_UINT32(output_stream, FILE_DEVICE_DISK); /* DeviceType */ Stream_Write_UINT32(output_stream, 0); /* Characteristics */ guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_query_attribute_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { int name_len = guac_utf8_strlen(device->device_name); wStream* output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 16 + name_len); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, iorequest->file_id); Stream_Write_UINT32(output_stream, 12 + name_len); Stream_Write_UINT32(output_stream, FILE_UNICODE_ON_DISK | FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES); /* FileSystemAttributes */ Stream_Write_UINT32(output_stream, GUAC_RDP_FS_MAX_PATH ); /* MaximumComponentNameLength */ Stream_Write_UINT32(output_stream, name_len); Stream_Write(output_stream, device->device_name, name_len); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_query_full_size_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { guac_rdp_fs_info info = {0}; guac_rdp_fs_get_info((guac_rdp_fs*) device->data, &info); wStream* output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 36); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, iorequest->file_id); Stream_Write_UINT32(output_stream, 32); Stream_Write_UINT64(output_stream, info.blocks_total); /* TotalAllocationUnits */ Stream_Write_UINT64(output_stream, info.blocks_available); /* CallerAvailableAllocationUnits */ Stream_Write_UINT64(output_stream, info.blocks_available); /* ActualAvailableAllocationUnits */ Stream_Write_UINT32(output_stream, 1); /* SectorsPerAllocationUnit */ Stream_Write_UINT32(output_stream, info.block_size); /* BytesPerSector */ guac_rdp_common_svc_write(svc, output_stream); } guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h0000644000175100001440000000730513764613616023721 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_H #define GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_H /** * Handlers for core drive I/O requests. Requests handled here may be simple * messages handled directly, or more complex multi-type messages handled * elsewhere. * * @file rdpdr-fs-messages.h */ #include "channels/rdpdr/rdpdr.h" #include /** * Handles a Server Create Drive Request. Despite its name, this request opens * a file. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_create; /** * Handles a Server Close Drive Request. This request closes an open file. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_close; /** * Handles a Server Drive Read Request. This request reads from a file. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_read; /** * Handles a Server Drive Write Request. This request writes to a file. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_write; /** * Handles a Server Drive Control Request. This request handles one of any * number of Windows FSCTL_* control functions. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_device_control; /** * Handles a Server Drive Query Volume Information Request. This request * queries information about the redirected volume (drive). This request * has several query types which have their own handlers defined in a * separate file. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_volume_info; /** * Handles a Server Drive Set Volume Information Request. Currently, this * RDPDR implementation does not support setting of volume information. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_set_volume_info; /** * Handles a Server Drive Query Information Request. This request queries * information about a specific file. This request has several query types * which have their own handlers defined in a separate file. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_file_info; /** * Handles a Server Drive Set Information Request. This request sets * information about a specific file. Currently, this RDPDR implementation does * not support setting of file information. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_set_file_info; /** * Handles a Server Drive Query Directory Request. This request queries * information about a specific directory. This request has several query types * which have their own handlers defined in a separate file. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_directory; /** * Handles a Server Drive NotifyChange Directory Request. This request requests * directory change notification. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_notify_change_directory; /** * Handles a Server Drive Lock Control Request. This request locks or unlocks * portions of a file. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_lock_control; #endif guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr.c0000644000175100001440000001377213764613616021506 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/rdpdr/rdpdr.h" #include "channels/rdpdr/rdpdr-fs.h" #include "channels/rdpdr/rdpdr-messages.h" #include "channels/rdpdr/rdpdr-printer.h" #include "rdp.h" #include "settings.h" #include #include #include #include #include #include void guac_rdpdr_process_receive(guac_rdp_common_svc* svc, wStream* input_stream) { int component; int packet_id; /* * Check that device redirection stream contains at least 4 bytes * (UINT16 + UINT16). */ if (Stream_GetRemainingLength(input_stream) < 4) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Device redirection " "channel PDU header does not contain the expected number of " "bytes. Device redirection may not function as expected."); return; } /* Read header */ Stream_Read_UINT16(input_stream, component); Stream_Read_UINT16(input_stream, packet_id); /* Core component */ if (component == RDPDR_CTYP_CORE) { /* Dispatch handlers based on packet ID */ switch (packet_id) { case PAKID_CORE_SERVER_ANNOUNCE: guac_rdpdr_process_server_announce(svc, input_stream); break; case PAKID_CORE_CLIENTID_CONFIRM: guac_rdpdr_process_clientid_confirm(svc, input_stream); break; case PAKID_CORE_DEVICE_REPLY: guac_rdpdr_process_device_reply(svc, input_stream); break; case PAKID_CORE_DEVICE_IOREQUEST: guac_rdpdr_process_device_iorequest(svc, input_stream); break; case PAKID_CORE_SERVER_CAPABILITY: guac_rdpdr_process_server_capability(svc, input_stream); break; case PAKID_CORE_USER_LOGGEDON: guac_rdpdr_process_user_loggedon(svc, input_stream); break; default: guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring " "RDPDR core packet with unexpected ID: 0x%04x", packet_id); } } /* end if core */ /* Printer component */ else if (component == RDPDR_CTYP_PRN) { /* Dispatch handlers based on packet ID */ switch (packet_id) { case PAKID_PRN_CACHE_DATA: guac_rdpdr_process_prn_cache_data(svc, input_stream); break; case PAKID_PRN_USING_XPS: guac_rdpdr_process_prn_using_xps(svc, input_stream); break; default: guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring RDPDR " "printer packet with unexpected ID: 0x%04x", packet_id); } } /* end if printer */ else guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring packet for " "unknown RDPDR component: 0x%04x", component); } wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device, int completion_id, int status, int size) { wStream* output_stream = Stream_New(NULL, 16+size); /* Write header */ Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE); Stream_Write_UINT16(output_stream, PAKID_CORE_DEVICE_IOCOMPLETION); /* Write content */ Stream_Write_UINT32(output_stream, device->device_id); Stream_Write_UINT32(output_stream, completion_id); Stream_Write_UINT32(output_stream, status); return output_stream; } void guac_rdpdr_process_connect(guac_rdp_common_svc* svc) { /* Get data from client */ guac_client* client = svc->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdpdr* rdpdr = (guac_rdpdr*) calloc(1, sizeof(guac_rdpdr)); svc->data = rdpdr; /* Register printer if enabled */ if (rdp_client->settings->printing_enabled) guac_rdpdr_register_printer(svc, rdp_client->settings->printer_name); /* Register drive if enabled */ if (rdp_client->settings->drive_enabled) guac_rdpdr_register_fs(svc, rdp_client->settings->drive_name); } void guac_rdpdr_process_terminate(guac_rdp_common_svc* svc) { guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; if (rdpdr == NULL) return; int i; for (i=0; idevices_registered; i++) { guac_rdpdr_device* device = &(rdpdr->devices[i]); guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unloading device %i " "(%s)", device->device_id, device->device_name); device->free_handler(svc, device); } free(rdpdr); } void guac_rdpdr_load_plugin(rdpContext* context) { guac_client* client = ((rdp_freerdp_context*) context)->client; /* Load support for RDPDR */ if (guac_rdp_common_svc_load_plugin(context, "rdpdr", CHANNEL_OPTION_COMPRESS_RDP, guac_rdpdr_process_connect, guac_rdpdr_process_receive, guac_rdpdr_process_terminate)) { guac_client_log(client, GUAC_LOG_WARNING, "Support for the RDPDR " "channel (device redirection) could not be loaded. Drive " "redirection and printing will not work. Sound MAY not work."); } } guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h0000644000175100001440000000374613764613616022121 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_RDPDR_FS_H #define GUAC_RDP_RDPDR_FS_H /** * Functions and macros specific to filesystem handling and initialization * independent of RDP. The functions here may deal with the RDPDR device * directly, but their semantics must not deal with RDP protocol messaging. * Functions here represent a virtual Windows-style filesystem on top of UNIX * system calls and structures, using the guac_rdpdr_device structure as a home * for common data. * * @file rdpdr-fs.h */ #include "channels/common-svc.h" #include "channels/rdpdr/rdpdr.h" #include /** * The UTF-16 string that should be sent as the label of the filesystem. */ #define GUAC_FILESYSTEM_LABEL "G\0U\0A\0C\0F\0I\0L\0E\0" /** * The size of GUAC_FILESYSTEM_LABEL in bytes. */ #define GUAC_FILESYSTEM_LABEL_LENGTH 16 /** * Registers a new filesystem device within the RDPDR plugin. This must be done * before RDPDR connection finishes. * * @param svc * The static virtual channel instance being used for RDPDR. * * @param drive_name * The name of the redirected drive to display in the RDP connection. */ void guac_rdpdr_register_fs(guac_rdp_common_svc* svc, char* drive_name); #endif guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h0000644000175100001440000000401013764613616025436 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_VOL_INFO_H #define GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_VOL_INFO_H /** * Handlers for directory queries received over the RDPDR channel via the * IRP_MJ_DIRECTORY_CONTROL major function and the IRP_MN_QUERY_DIRECTORY minor * function. * * @file rdpdr-fs-messages-vol-info.h */ #include "channels/rdpdr/rdpdr.h" #include /** * Processes a query request for FileFsVolumeInformation. According to the * documentation, this is "used to query information for a volume on which a * file system is mounted." */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_volume_info; /** * Processes a query request for FileFsSizeInformation. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_size_info; /** * Processes a query request for FileFsAttributeInformation. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_attribute_info; /** * Processes a query request for FileFsFullSizeInformation. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_full_size_info; /** * Processes a query request for FileFsDeviceInformation. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_device_info; #endif guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c0000644000175100001440000003511513764613616023306 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/rdpdr/rdpdr-messages.h" #include "channels/rdpdr/rdpdr.h" #include "rdp.h" #include "settings.h" #include #include #include #include #include /** * Sends a Client Announce Reply message. The Client Announce Reply message is * required to be sent in response to the Server Announce Request message. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/d6fe6d1b-c145-4a6f-99aa-4fe3cdcea398 * * @param svc * The guac_rdp_common_svc representing the static virtual channel being * used for RDPDR. * * @param major * The major version of the RDPDR protocol in use. This value must always * be 1. * * @param minor * The minor version of the RDPDR protocol in use. This value must be * either 2, 5, 10, 12, or 13. * * @param client_id * The client ID received in the Server Announce Request, or a randomly * generated ID. */ static void guac_rdpdr_send_client_announce_reply(guac_rdp_common_svc* svc, unsigned int major, unsigned int minor, unsigned int client_id) { wStream* output_stream = Stream_New(NULL, 12); /* Write header */ Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE); Stream_Write_UINT16(output_stream, PAKID_CORE_CLIENTID_CONFIRM); /* Write content */ Stream_Write_UINT16(output_stream, major); Stream_Write_UINT16(output_stream, minor); Stream_Write_UINT32(output_stream, client_id); guac_rdp_common_svc_write(svc, output_stream); } /** * Sends a Client Name Request message. The Client Name Request message is used * by the client to announce its own name. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/902497f1-3b1c-4aee-95f8-1668f9b7b7d2 * * @param svc * The guac_rdp_common_svc representing the static virtual channel being * used for RDPDR. * * @param name * The name that should be used for the client. */ static void guac_rdpdr_send_client_name_request(guac_rdp_common_svc* svc, const char* name) { int name_bytes = strlen(name) + 1; wStream* output_stream = Stream_New(NULL, 16 + name_bytes); /* Write header */ Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE); Stream_Write_UINT16(output_stream, PAKID_CORE_CLIENT_NAME); /* Write content */ Stream_Write_UINT32(output_stream, 0); /* ASCII */ Stream_Write_UINT32(output_stream, 0); /* 0 required by RDPDR spec */ Stream_Write_UINT32(output_stream, name_bytes); Stream_Write(output_stream, name, name_bytes); guac_rdp_common_svc_write(svc, output_stream); } /** * Sends a Client Core Capability Response message. The Client Core Capability * Response message is used to announce the client's capabilities, in response * to receiving the server's capabilities via a Server Core Capability Request. * See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/f513bf87-cca0-488a-ac5c-18cf18f4a7e1 * * @param svc * The guac_rdp_common_svc representing the static virtual channel being * used for RDPDR. */ static void guac_rdpdr_send_client_capability(guac_rdp_common_svc* svc) { wStream* output_stream = Stream_New(NULL, 256); guac_client_log(svc->client, GUAC_LOG_DEBUG, "Sending capabilities..."); /* Write header */ Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE); Stream_Write_UINT16(output_stream, PAKID_CORE_CLIENT_CAPABILITY); /* Capability count + padding */ Stream_Write_UINT16(output_stream, 3); Stream_Write_UINT16(output_stream, 0); /* Padding */ /* General capability header */ Stream_Write_UINT16(output_stream, CAP_GENERAL_TYPE); Stream_Write_UINT16(output_stream, 44); Stream_Write_UINT32(output_stream, GENERAL_CAPABILITY_VERSION_02); /* General capability data */ Stream_Write_UINT32(output_stream, GUAC_OS_TYPE); /* osType - required to be ignored */ Stream_Write_UINT32(output_stream, 0); /* osVersion */ Stream_Write_UINT16(output_stream, 1); /* protocolMajor - must be set to 1 */ Stream_Write_UINT16(output_stream, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinor */ Stream_Write_UINT32(output_stream, 0xFFFF); /* ioCode1 */ Stream_Write_UINT32(output_stream, 0); /* ioCode2 */ Stream_Write_UINT32(output_stream, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */ Stream_Write_UINT32(output_stream, 0); /* extraFlags1 */ Stream_Write_UINT32(output_stream, 0); /* extraFlags2 */ Stream_Write_UINT32(output_stream, 0); /* SpecialTypeDeviceCap */ /* Printer support header */ Stream_Write_UINT16(output_stream, CAP_PRINTER_TYPE); Stream_Write_UINT16(output_stream, 8); Stream_Write_UINT32(output_stream, PRINT_CAPABILITY_VERSION_01); /* Drive support header */ Stream_Write_UINT16(output_stream, CAP_DRIVE_TYPE); Stream_Write_UINT16(output_stream, 8); Stream_Write_UINT32(output_stream, DRIVE_CAPABILITY_VERSION_02); guac_rdp_common_svc_write(svc, output_stream); guac_client_log(svc->client, GUAC_LOG_DEBUG, "Capabilities sent."); } /** * Sends a Client Device List Announce Request message. The Client Device List * Announce Request message is used by the client to enumerate all devices * which should be made available within the RDP session via RDPDR. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/10ef9ada-cba2-4384-ab60-7b6290ed4a9a * * @param svc * The guac_rdp_common_svc representing the static virtual channel being * used for RDPDR. */ static void guac_rdpdr_send_client_device_list_announce_request(guac_rdp_common_svc* svc) { guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; /* Calculate number of bytes needed for the stream */ int streamBytes = 16; for (int i=0; i < rdpdr->devices_registered; i++) streamBytes += rdpdr->devices[i].device_announce_len; /* Allocate the stream */ wStream* output_stream = Stream_New(NULL, streamBytes); /* Write header */ Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE); Stream_Write_UINT16(output_stream, PAKID_CORE_DEVICELIST_ANNOUNCE); /* Get the stream for each of the devices. */ Stream_Write_UINT32(output_stream, rdpdr->devices_registered); for (int i=0; idevices_registered; i++) { Stream_Write(output_stream, Stream_Buffer(rdpdr->devices[i].device_announce), rdpdr->devices[i].device_announce_len); guac_client_log(svc->client, GUAC_LOG_DEBUG, "Registered device %i (%s)", rdpdr->devices[i].device_id, rdpdr->devices[i].device_name); } guac_rdp_common_svc_write(svc, output_stream); guac_client_log(svc->client, GUAC_LOG_DEBUG, "All supported devices sent."); } void guac_rdpdr_process_server_announce(guac_rdp_common_svc* svc, wStream* input_stream) { unsigned int major, minor, client_id; /* Stream should contain at least 8 bytes (UINT16 + UINT16 + UINT32) */ if (Stream_GetRemainingLength(input_stream) < 8) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Announce " "Request PDU does not contain the expected number of bytes. " "Device redirection may not work as expected."); return; } Stream_Read_UINT16(input_stream, major); Stream_Read_UINT16(input_stream, minor); Stream_Read_UINT32(input_stream, client_id); /* Must choose own client ID if minor not >= 12 */ if (minor < 12) client_id = random() & 0xFFFF; guac_client_log(svc->client, GUAC_LOG_INFO, "Connected to RDPDR %u.%u as client 0x%04x", major, minor, client_id); /* Respond to announce */ guac_rdpdr_send_client_announce_reply(svc, major, minor, client_id); /* Name request */ guac_rdpdr_send_client_name_request(svc, ((guac_rdp_client*) svc->client->data)->settings->client_name); } void guac_rdpdr_process_clientid_confirm(guac_rdp_common_svc* svc, wStream* input_stream) { guac_client_log(svc->client, GUAC_LOG_DEBUG, "Client ID confirmed"); } void guac_rdpdr_process_device_reply(guac_rdp_common_svc* svc, wStream* input_stream) { guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; unsigned int device_id, ntstatus; int severity, c, n, facility, code; /* Stream should contain at least 8 bytes (UINT32 + UINT32 ) */ if (Stream_GetRemainingLength(input_stream) < 8) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Device Announce" "Response PDU does not contain the expected number of bytes." "Device redirection may not work as expected."); return; } Stream_Read_UINT32(input_stream, device_id); Stream_Read_UINT32(input_stream, ntstatus); severity = (ntstatus & 0xC0000000) >> 30; c = (ntstatus & 0x20000000) >> 29; n = (ntstatus & 0x10000000) >> 28; facility = (ntstatus & 0x0FFF0000) >> 16; code = ntstatus & 0x0000FFFF; /* Log error / information */ if (device_id < rdpdr->devices_registered) { if (severity == 0x0) guac_client_log(svc->client, GUAC_LOG_DEBUG, "Device %i (%s) connected successfully", device_id, rdpdr->devices[device_id].device_name); else guac_client_log(svc->client, GUAC_LOG_ERROR, "Problem connecting device %i (%s): " "severity=0x%x, c=0x%x, n=0x%x, facility=0x%x, code=0x%x", device_id, rdpdr->devices[device_id].device_name, severity, c, n, facility, code); } else guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown device ID: 0x%08x", device_id); } void guac_rdpdr_process_device_iorequest(guac_rdp_common_svc* svc, wStream* input_stream) { guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; guac_rdpdr_iorequest iorequest; /* Check to make sure the Stream contains at least 20 bytes (5 x UINT32 ). */ if (Stream_GetRemainingLength(input_stream) < 20) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Device I/O Request PDU " "does not contain the expected number of bytes. Device " "redirection may not work as expected."); return; } /* Read header */ Stream_Read_UINT32(input_stream, iorequest.device_id); Stream_Read_UINT32(input_stream, iorequest.file_id); Stream_Read_UINT32(input_stream, iorequest.completion_id); Stream_Read_UINT32(input_stream, iorequest.major_func); Stream_Read_UINT32(input_stream, iorequest.minor_func); /* If printer, run printer handlers */ if (iorequest.device_id >= 0 && iorequest.device_id < rdpdr->devices_registered) { /* Call handler on device */ guac_rdpdr_device* device = &(rdpdr->devices[iorequest.device_id]); device->iorequest_handler(svc, device, &iorequest, input_stream); } else guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown device ID: " "0x%08x", iorequest.device_id); } void guac_rdpdr_process_server_capability(guac_rdp_common_svc* svc, wStream* input_stream) { int count; int i; /* Check to make sure the Stream has at least 4 bytes (UINT16 + 2) */ if (Stream_GetRemainingLength(input_stream) < 4) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Core Capability " "Request PDU does not contain the expected number of bytes." "Device redirection may not work as expected."); return; } /* Read header */ Stream_Read_UINT16(input_stream, count); Stream_Seek(input_stream, 2); /* Parse capabilities */ for (i=0; iclient, GUAC_LOG_WARNING, "Server Core " "Capability Request PDU does not contain the expected " "number of bytes. Device redirection may not work as " "expected."); break; } Stream_Read_UINT16(input_stream, type); Stream_Read_UINT16(input_stream, length); /* Make sure Stream has required length remaining for Seek below. */ if (Stream_GetRemainingLength(input_stream) < (length - 4)) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Core " "Capability Request PDU does not contain the expected " "number of bytes. Device redirection may not work as " "expected."); break; } /* Ignore all for now */ guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring server capability set type=0x%04x, length=%i", type, length); Stream_Seek(input_stream, length - 4); } /* Send own capabilities */ guac_rdpdr_send_client_capability(svc); } void guac_rdpdr_process_user_loggedon(guac_rdp_common_svc* svc, wStream* input_stream) { guac_client_log(svc->client, GUAC_LOG_INFO, "RDPDR user logged on"); guac_rdpdr_send_client_device_list_announce_request(svc); } void guac_rdpdr_process_prn_cache_data(guac_rdp_common_svc* svc, wStream* input_stream) { guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring printer cached configuration data"); } void guac_rdpdr_process_prn_using_xps(guac_rdp_common_svc* svc, wStream* input_stream) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Printer unexpectedly switched to XPS mode"); } guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h0000644000175100001440000000626613764613616025433 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_DIR_INFO_H #define GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_DIR_INFO_H /** * Handlers for directory queries received over the RDPDR channel via the * IRP_MJ_DIRECTORY_CONTROL major function and the IRP_MN_QUERY_DIRECTORY minor * function. * * @file rdpdr-fs-messages-dir-info.h */ #include "channels/common-svc.h" #include "channels/rdpdr/rdpdr.h" #include /** * Handler for Device I/O Requests which query information about the files * within a directory. * * @param svc * The guac_rdp_common_svc representing the static virtual channel being * used for RDPDR. * * @param device * The guac_rdpdr_device of the relevant device, as dictated by the * deviceId field of the common RDPDR header within the received PDU. * Within the guac_rdpdr_iorequest structure, the deviceId field is stored * within device_id. * * @param iorequest * The contents of the common RDPDR Device I/O Request header shared by all * RDPDR devices. * * @param entry_name * The filename of the file being queried. * * @param entry_file_id * The ID of the file being queried. */ typedef void guac_rdpdr_directory_query_handler(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, const char* entry_name, int entry_file_id); /** * Processes a query request for FileDirectoryInformation. From the * documentation this is "defined as the file's name, time stamp, and size, or its * attributes." */ guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_directory_info; /** * Processes a query request for FileFullDirectoryInformation. From the * documentation, this is "defined as all the basic information, plus extended * attribute size." */ guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_full_directory_info; /** * Processes a query request for FileBothDirectoryInformation. From the * documentation, this absurdly-named request is "basic information plus * extended attribute size and short name about a file or directory." */ guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_both_directory_info; /** * Processes a query request for FileNamesInformation. From the documentation, * this is "detailed information on the names of files in a directory." */ guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_names_info; #endif guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h0000644000175100001440000001252113764613616023307 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_RDPDR_MESSAGES_H #define GUAC_RDP_CHANNELS_RDPDR_MESSAGES_H #include "channels/common-svc.h" #include "channels/rdpdr/rdpdr.h" #include #include /** * A 32-bit arbitrary value for the osType field of certain requests. As this * value is defined as completely arbitrary and required to be ignored by the * server, we send "GUAC" as an integer. */ #define GUAC_OS_TYPE (*((uint32_t*) "GUAC")) /** * Handler which processes a message specific to the RDPDR channel. * * @param svc * The guac_rdp_common_svc representing the static virtual channel being * used for RDPDR. * * @param input_stream * A wStream containing the entire received message. */ typedef void guac_rdpdr_message_handler(guac_rdp_common_svc* svc, wStream* input_stream); /** * Handler which processes a received Server Announce Request message. The * Server Announce Request message begins the RDPDR exchange and provides a * client ID which the RDPDR client may use. The client may also supply its * own, randomly-generated ID, and is required to do so for older versions of * RDPDR. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/046047aa-62d8-49f9-bf16-7fe41880aaf4 */ guac_rdpdr_message_handler guac_rdpdr_process_server_announce; /** * Handler which processes a received Server Client ID Confirm message. The * Server Client ID Confirm message is sent by the server to confirm the client * ID requested by the client (in its response to the Server Announce Request) * has been accepted. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/bbbb9666-6994-4cf6-8e65-0d46eb319c6e */ guac_rdpdr_message_handler guac_rdpdr_process_clientid_confirm; /** * Handler which processes a received Server Device Announce Response message. * The Server Device Announce Response message is sent in response to a Client * Device List Announce message to communicate the success/failure status of * device creation. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a4c0b619-6e87-4721-bdc4-5d2db7f485f3 */ guac_rdpdr_message_handler guac_rdpdr_process_device_reply; /** * Handler which processes a received Device I/O Request message. The Device * I/O Request message makes up the majority of traffic once RDPDR is * established. Each I/O request consists of a device-specific major/minor * function number pair, as well as several parameters. Device-specific * handling of I/O requests within Guacamole is delegated to device- and * function-specific implementations of yet another function type: * guac_rdpdr_device_iorequest_handler. * * See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a087ffa8-d0d5-4874-ac7b-0494f63e2d5d */ guac_rdpdr_message_handler guac_rdpdr_process_device_iorequest; /** * Handler which processes a received Server Core Capability Request message. * The Server Core Capability Request message is sent by the server to * communicate its capabilities and to request that the client communicate the * same. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/702789c3-b924-4bc2-9280-3221bc7d6797 */ guac_rdpdr_message_handler guac_rdpdr_process_server_capability; /** * Handler which processes a received Server User Logged On message. The Server * User Logged On message is sent by the server to notify that the user has * logged on to the session. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/dfc0e8ed-a242-4d00-bb88-e779e08f2f61 */ guac_rdpdr_message_handler guac_rdpdr_process_user_loggedon; /** * Handler which processes any one of several RDPDR messages specific to cached * printer configuration data, each of these messages having the same * PAKID_PRN_CACHE_DATA packet ID. The Guacamole RDPDR implementation ignores * all PAKID_PRN_CACHE_DATA messages. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpepc/7fccae60-f077-433b-9dee-9bad4238bf40 */ guac_rdpdr_message_handler guac_rdpdr_process_prn_cache_data; /** * Handler which processes a received Server Printer Set XPS Mode message. The * Server Printer Set XPS Mode message is specific to printers and requests * that the client printer be set to XPS mode. The Guacamole RDPDR * implementation ignores any request to set the printer to XPS mode. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpepc/f1789a66-bcd0-4df3-bfc2-6e7330d63145 */ guac_rdpdr_message_handler guac_rdpdr_process_prn_using_xps; #endif guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c0000644000175100001440000005242113764613616023713 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/common-svc.h" #include "channels/rdpdr/rdpdr-fs-messages-dir-info.h" #include "channels/rdpdr/rdpdr-fs-messages-file-info.h" #include "channels/rdpdr/rdpdr-fs-messages-vol-info.h" #include "channels/rdpdr/rdpdr-fs-messages.h" #include "channels/rdpdr/rdpdr.h" #include "download.h" #include "fs.h" #include "unicode.h" #include #include #include #include #include #include #include #include void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { wStream* output_stream; int file_id; int desired_access, file_attributes; int create_disposition, create_options, path_length; char path[GUAC_RDP_FS_MAX_PATH]; /* Check remaining stream data prior to reading. */ if (Stream_GetRemainingLength(input_stream) < 32) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Create Drive " "Request PDU does not contain the expected number of bytes. " "Drive redirection may not work as expected."); return; } /* Read "create" information */ Stream_Read_UINT32(input_stream, desired_access); Stream_Seek_UINT64(input_stream); /* allocation size */ Stream_Read_UINT32(input_stream, file_attributes); Stream_Seek_UINT32(input_stream); /* shared access */ Stream_Read_UINT32(input_stream, create_disposition); Stream_Read_UINT32(input_stream, create_options); Stream_Read_UINT32(input_stream, path_length); /* Check to make sure the stream contains path_length bytes. */ if(Stream_GetRemainingLength(input_stream) < path_length) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Create Drive " "Request PDU does not contain the expected number of bytes. " "Drive redirection may not work as expected."); return; } /* Convert path to UTF-8 */ guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path_length/2 - 1, path, sizeof(path)); /* Open file */ file_id = guac_rdp_fs_open((guac_rdp_fs*) device->data, path, desired_access, file_attributes, create_disposition, create_options); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] " "desired_access=0x%x, file_attributes=0x%x, " "create_disposition=0x%x, create_options=0x%x, path=\"%s\"", __func__, file_id, desired_access, file_attributes, create_disposition, create_options, path); /* If an error occurred, notify server */ if (file_id < 0) { guac_client_log(svc->client, GUAC_LOG_ERROR, "File open refused (%i): \"%s\"", file_id, path); output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, guac_rdp_fs_get_status(file_id), 5); Stream_Write_UINT32(output_stream, 0); /* fileId */ Stream_Write_UINT8(output_stream, 0); /* information */ } /* Otherwise, open succeeded */ else { guac_rdp_fs_file* file; output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 5); Stream_Write_UINT32(output_stream, file_id); /* fileId */ Stream_Write_UINT8(output_stream, 0); /* information */ /* Create \Download if it doesn't exist */ file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id); if (file != NULL && strcmp(file->absolute_path, "\\") == 0) { /* Only create Download folder if downloads are enabled. */ if (!((guac_rdp_fs*) device->data)->disable_download) { int download_id = guac_rdp_fs_open((guac_rdp_fs*) device->data, "\\Download", GENERIC_READ, 0, FILE_OPEN_IF, FILE_DIRECTORY_FILE); if (download_id >= 0) guac_rdp_fs_close((guac_rdp_fs*) device->data, download_id); } } } guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { UINT32 length; UINT64 offset; char* buffer; int bytes_read; wStream* output_stream; /* Check remaining bytes before reading stream. */ if (Stream_GetRemainingLength(input_stream) < 12) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Read " "Request PDU does not contain the expected number of bytes. " "Drive redirection may not work as expected."); return; } /* Read packet */ Stream_Read_UINT32(input_stream, length); Stream_Read_UINT64(input_stream, offset); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] length=%i, offset=%" PRIu64, __func__, iorequest->file_id, length, (uint64_t) offset); /* Ensure buffer size does not exceed a safe maximum */ if (length > GUAC_RDP_MAX_READ_BUFFER) length = GUAC_RDP_MAX_READ_BUFFER; /* Allocate buffer */ buffer = malloc(length); /* Attempt read */ bytes_read = guac_rdp_fs_read((guac_rdp_fs*) device->data, iorequest->file_id, offset, buffer, length); /* If error, return invalid parameter */ if (bytes_read < 0) { output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, guac_rdp_fs_get_status(bytes_read), 4); Stream_Write_UINT32(output_stream, 0); /* Length */ } /* Otherwise, send bytes read */ else { output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4+bytes_read); Stream_Write_UINT32(output_stream, bytes_read); /* Length */ Stream_Write(output_stream, buffer, bytes_read); /* ReadData */ } guac_rdp_common_svc_write(svc, output_stream); free(buffer); } void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { UINT32 length; UINT64 offset; int bytes_written; wStream* output_stream; /* Check remaining length. */ if (Stream_GetRemainingLength(input_stream) < 32) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Write " "Request PDU does not contain the expected number of bytes. " "Drive redirection may not work as expected."); return; } /* Read packet */ Stream_Read_UINT32(input_stream, length); Stream_Read_UINT64(input_stream, offset); Stream_Seek(input_stream, 20); /* Padding */ guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] length=%i, offset=%" PRIu64, __func__, iorequest->file_id, length, (uint64_t) offset); /* Check to make sure stream contains at least length bytes */ if (Stream_GetRemainingLength(input_stream) < length) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Write " "Request PDU does not contain the expected number of bytes. " "Drive redirection may not work as expected."); return; } /* Attempt write */ bytes_written = guac_rdp_fs_write((guac_rdp_fs*) device->data, iorequest->file_id, offset, Stream_Pointer(input_stream), length); /* If error, return invalid parameter */ if (bytes_written < 0) { output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, guac_rdp_fs_get_status(bytes_written), 5); Stream_Write_UINT32(output_stream, 0); /* Length */ Stream_Write_UINT8(output_stream, 0); /* Padding */ } /* Otherwise, send success */ else { output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 5); Stream_Write_UINT32(output_stream, bytes_written); /* Length */ Stream_Write_UINT8(output_stream, 0); /* Padding */ } guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { wStream* output_stream; guac_rdp_fs_file* file; guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, iorequest->file_id); /* Get file */ file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id); if (file == NULL) return; /* If file was written to, and it's in the \Download folder, start stream */ if (file->bytes_written > 0 && strncmp(file->absolute_path, "\\Download\\", 10) == 0 && !((guac_rdp_fs*) device->data)->disable_download) { guac_client_for_owner(svc->client, guac_rdp_download_to_user, file->absolute_path); guac_rdp_fs_delete((guac_rdp_fs*) device->data, iorequest->file_id); } /* Close file */ guac_rdp_fs_close((guac_rdp_fs*) device->data, iorequest->file_id); output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4); Stream_Write(output_stream, "\0\0\0\0", 4); /* Padding */ guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { int fs_information_class; /* Check remaining length */ if (Stream_GetRemainingLength(input_stream) < 4) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query " "Volume Information PDU does not contain the expected number " "of bytes. Drive redirection may not work as expected."); return; } Stream_Read_UINT32(input_stream, fs_information_class); /* Dispatch to appropriate class-specific handler */ switch (fs_information_class) { case FileFsVolumeInformation: guac_rdpdr_fs_process_query_volume_info(svc, device, iorequest, input_stream); break; case FileFsSizeInformation: guac_rdpdr_fs_process_query_size_info(svc, device, iorequest, input_stream); break; case FileFsDeviceInformation: guac_rdpdr_fs_process_query_device_info(svc, device, iorequest, input_stream); break; case FileFsAttributeInformation: guac_rdpdr_fs_process_query_attribute_info(svc, device, iorequest, input_stream); break; case FileFsFullSizeInformation: guac_rdpdr_fs_process_query_full_size_info(svc, device, iorequest, input_stream); break; default: guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unknown volume information class: 0x%x", fs_information_class); } } void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { int fs_information_class; /* Check remaining length */ if (Stream_GetRemainingLength(input_stream) < 4) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query " "Information PDU does not contain the expected number of " "bytes. Drive redirection may not work as expected."); return; } Stream_Read_UINT32(input_stream, fs_information_class); /* Dispatch to appropriate class-specific handler */ switch (fs_information_class) { case FileBasicInformation: guac_rdpdr_fs_process_query_basic_info(svc, device, iorequest, input_stream); break; case FileStandardInformation: guac_rdpdr_fs_process_query_standard_info(svc, device, iorequest, input_stream); break; case FileAttributeTagInformation: guac_rdpdr_fs_process_query_attribute_tag_info(svc, device, iorequest, input_stream); break; default: guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unknown file information class: 0x%x", fs_information_class); } } void guac_rdpdr_fs_process_set_volume_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { wStream* output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_NOT_SUPPORTED, 0); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] Set volume info not supported", __func__, iorequest->file_id); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { int fs_information_class; int length; /* Check remaining length */ if (Stream_GetRemainingLength(input_stream) < 32) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set " "Information PDU does not contain the expected number of " "bytes. Drive redirection may not work as expected."); return; } Stream_Read_UINT32(input_stream, fs_information_class); Stream_Read_UINT32(input_stream, length); /* Length */ Stream_Seek(input_stream, 24); /* Padding */ /* Dispatch to appropriate class-specific handler */ switch (fs_information_class) { case FileBasicInformation: guac_rdpdr_fs_process_set_basic_info(svc, device, iorequest, length, input_stream); break; case FileEndOfFileInformation: guac_rdpdr_fs_process_set_end_of_file_info(svc, device, iorequest, length, input_stream); break; case FileDispositionInformation: guac_rdpdr_fs_process_set_disposition_info(svc, device, iorequest, length, input_stream); break; case FileRenameInformation: guac_rdpdr_fs_process_set_rename_info(svc, device, iorequest, length, input_stream); break; case FileAllocationInformation: guac_rdpdr_fs_process_set_allocation_info(svc, device, iorequest, length, input_stream); break; default: guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unknown file information class: 0x%x", fs_information_class); } } void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { wStream* output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_INVALID_PARAMETER, 4); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] IGNORED", __func__, iorequest->file_id); /* No content for now */ Stream_Write_UINT32(output_stream, 0); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_notify_change_directory(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] Not " "implemented", __func__, iorequest->file_id); } void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { wStream* output_stream; guac_rdp_fs_file* file; int fs_information_class, initial_query; int path_length; const char* entry_name; /* Get file */ file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id); if (file == NULL) return; if (Stream_GetRemainingLength(input_stream) < 9) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query " "Directory PDU does not contain the expected number of bytes. " "Drive redirection may not work as expected."); return; } /* Read main header */ Stream_Read_UINT32(input_stream, fs_information_class); Stream_Read_UINT8(input_stream, initial_query); Stream_Read_UINT32(input_stream, path_length); /* If this is the first query, the path is included after padding */ if (initial_query) { /* * Check to make sure Stream has at least the 23 padding bytes in it * prior to seeking. */ if (Stream_GetRemainingLength(input_stream) < (23 + path_length)) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query " "Directory PDU does not contain the expected number of " "bytes. Drive redirection may not work as expected."); return; } Stream_Seek(input_stream, 23); /* Padding */ /* Convert path to UTF-8 */ guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path_length/2 - 1, file->dir_pattern, sizeof(file->dir_pattern)); } guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] " "initial_query=%i, dir_pattern=\"%s\"", __func__, iorequest->file_id, initial_query, file->dir_pattern); /* Find first matching entry in directory */ while ((entry_name = guac_rdp_fs_read_dir((guac_rdp_fs*) device->data, iorequest->file_id)) != NULL) { /* Convert to absolute path */ char entry_path[GUAC_RDP_FS_MAX_PATH]; if (guac_rdp_fs_convert_path(file->absolute_path, entry_name, entry_path) == 0) { int entry_file_id; /* Pattern defined and match fails, continue with next file */ if (guac_rdp_fs_matches(entry_path, file->dir_pattern)) continue; /* Open directory entry */ entry_file_id = guac_rdp_fs_open((guac_rdp_fs*) device->data, entry_path, FILE_READ_DATA, 0, FILE_OPEN, 0); if (entry_file_id >= 0) { /* Dispatch to appropriate class-specific handler */ switch (fs_information_class) { case FileDirectoryInformation: guac_rdpdr_fs_process_query_directory_info(svc, device, iorequest, entry_name, entry_file_id); break; case FileFullDirectoryInformation: guac_rdpdr_fs_process_query_full_directory_info(svc, device, iorequest, entry_name, entry_file_id); break; case FileBothDirectoryInformation: guac_rdpdr_fs_process_query_both_directory_info(svc, device, iorequest, entry_name, entry_file_id); break; case FileNamesInformation: guac_rdpdr_fs_process_query_names_info(svc, device, iorequest, entry_name, entry_file_id); break; default: guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unknown dir information class: 0x%x", fs_information_class); } guac_rdp_fs_close((guac_rdp_fs*) device->data, entry_file_id); return; } /* end if file exists */ } /* end if path valid */ } /* end if entry exists */ /* * Handle errors as a lack of files. */ output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_NO_MORE_FILES, 5); Stream_Write_UINT32(output_stream, 0); /* Length */ Stream_Write_UINT8(output_stream, 0); /* Padding */ guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_lock_control(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { wStream* output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_NOT_SUPPORTED, 5); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] Lock not supported", __func__, iorequest->file_id); Stream_Zero(output_stream, 5); /* Padding */ guac_rdp_common_svc_write(svc, output_stream); } guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr.h0000644000175100001440000001616513764613616021512 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_RDPDR_H #define GUAC_RDP_CHANNELS_RDPDR_H #include "channels/common-svc.h" #include #include #include #include /** * The maximum number of bytes to allow for a device read. */ #define GUAC_RDP_MAX_READ_BUFFER 4194304 /** * Arbitrary device forwarded over the RDPDR channel. */ typedef struct guac_rdpdr_device guac_rdpdr_device; /** * The contents of the header common to all RDPDR Device I/O Requests. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a087ffa8-d0d5-4874-ac7b-0494f63e2d5d */ typedef struct guac_rdpdr_iorequest { /** * The unique ID assigned to the device receiving this I/O request. */ int device_id; /** * The unique ID which identifies the relevant file, as returned when the * file was opened. This field may not be relevant to all requests. */ int file_id; /** * The unique ID that should be used to refer to this I/O request in future * responses. */ int completion_id; /** * Integer ID which identifies the function being requested, such as * IRP_MJ_CREATE (open a file within a shared drive) or IRP_MJ_WRITE (write * data to an open file). */ int major_func; /** * Integer ID which identifies a variant of the function denoted by * major_func. This value is only valid for IRP_MJ_DIRECTORY_CONTROL. */ int minor_func; } guac_rdpdr_iorequest; /** * Handler for Device I/O Requests. RDPDR devices must provide an * implementation of this function to be able to handle inbound I/O requests. * * @param svc * The guac_rdp_common_svc representing the static virtual channel being * used for RDPDR. * * @param device * The guac_rdpdr_device of the relevant device, as dictated by the * deviceId field of the common RDPDR header within the received PDU. * Within the guac_rdpdr_iorequest structure, the deviceId field is stored * within device_id. * * @param iorequest * The contents of the common RDPDR Device I/O Request header shared by all * RDPDR devices. * * @param input_stream * The remaining data within the received PDU, following the common RDPDR * Device I/O Request header. */ typedef void guac_rdpdr_device_iorequest_handler(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream); /** * Handler for cleaning up the dynamically-allocated portions of a device. * * @param svc * The guac_rdp_common_svc representing the static virtual channel being * used for RDPDR. * * @param device * The guac_rdpdr_device of the device being freed. */ typedef void guac_rdpdr_device_free_handler(guac_rdp_common_svc* svc, guac_rdpdr_device* device); struct guac_rdpdr_device { /** * The ID assigned to this device by the RDPDR plugin. */ int device_id; /** * Device name, used for logging and for passthrough to the * server. */ const char* device_name; /** * The type of RDPDR device that this represents. */ uint32_t device_type; /** * The DOS name of the device. Max 8 bytes, including terminator. */ const char *dos_name; /** * The stream that stores the RDPDR device announcement for this device. */ wStream* device_announce; /** * The length of the device_announce wStream. */ int device_announce_len; /** * Handler which should be called for every I/O request received. */ guac_rdpdr_device_iorequest_handler* iorequest_handler; /** * Handler which should be called when the device is being freed. */ guac_rdpdr_device_free_handler* free_handler; /** * Arbitrary data, used internally by the handlers for this device. */ void* data; }; /** * Structure representing the current state of the Guacamole RDPDR plugin for * FreeRDP. */ typedef struct guac_rdpdr { /** * The number of devices registered within the devices array. */ int devices_registered; /** * Array of registered devices. */ guac_rdpdr_device devices[8]; } guac_rdpdr; /** * Creates a new stream which contains the common DR_DEVICE_IOCOMPLETION header * used for virtually all responses. Depending on the specific I/O completion * being sent, additional space may be reserved within the resulting stream for * additional fields. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/10ef9ada-cba2-4384-ab60-7b6290ed4a9a * * @param device * The device that completed the operation requested by a prior I/O * request. * * @param completion_id * The completion ID of the I/O request that requested the operation. * * @param status * An NTSTATUS code describing the success/failure of the operation that * was completed. * * @param size * The number of additional bytes to reserve at the end of the resulting * stream for additional fields to be appended. * * @return * A new wStream containing an I/O completion header, followed by the * requested additional free space. */ wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device, int completion_id, int status, int size); /** * Initializes device redirection support (file transfer, printing, etc.) for * RDP and handling of the RDPDR channel. If failures occur, messages noting * the specifics of those failures will be logged, and the RDP side of * device redirection support will not be functional. * * This MUST be called within the PreConnect callback of the freerdp instance * for RDPDR support to be loaded. * * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. */ void guac_rdpdr_load_plugin(rdpContext* context); /** * Handler which is invoked when the RDPDR channel is connected to the RDP * server. */ guac_rdp_common_svc_connect_handler guac_rdpdr_process_connect; /** * Handler which is invoked when the RDPDR channel has received data from the * RDP server. */ guac_rdp_common_svc_receive_handler guac_rdpdr_process_receive; /** * Handler which is invoked when the RDPDR channel has disconnected and is * about to be freed. */ guac_rdp_common_svc_terminate_handler guac_rdpdr_process_terminate; #endif guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c0000644000175100001440000001240313764613616022102 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/rdpdr/rdpdr-fs.h" #include "channels/rdpdr/rdpdr-fs-messages.h" #include "channels/rdpdr/rdpdr.h" #include "rdp.h" #include #include #include #include #include #include void guac_rdpdr_device_fs_iorequest_handler(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { switch (iorequest->major_func) { /* File open */ case IRP_MJ_CREATE: guac_rdpdr_fs_process_create(svc, device, iorequest, input_stream); break; /* File close */ case IRP_MJ_CLOSE: guac_rdpdr_fs_process_close(svc, device, iorequest, input_stream); break; /* File read */ case IRP_MJ_READ: guac_rdpdr_fs_process_read(svc, device, iorequest, input_stream); break; /* File write */ case IRP_MJ_WRITE: guac_rdpdr_fs_process_write(svc, device, iorequest, input_stream); break; /* Device control request (Windows FSCTL_ control codes) */ case IRP_MJ_DEVICE_CONTROL: guac_rdpdr_fs_process_device_control(svc, device, iorequest, input_stream); break; /* Query volume (drive) information */ case IRP_MJ_QUERY_VOLUME_INFORMATION: guac_rdpdr_fs_process_volume_info(svc, device, iorequest, input_stream); break; /* Set volume (drive) information */ case IRP_MJ_SET_VOLUME_INFORMATION: guac_rdpdr_fs_process_set_volume_info(svc, device, iorequest, input_stream); break; /* Query file information */ case IRP_MJ_QUERY_INFORMATION: guac_rdpdr_fs_process_file_info(svc, device, iorequest, input_stream); break; /* Set file information */ case IRP_MJ_SET_INFORMATION: guac_rdpdr_fs_process_set_file_info(svc, device, iorequest, input_stream); break; case IRP_MJ_DIRECTORY_CONTROL: /* Enumerate directory contents */ if (iorequest->minor_func == IRP_MN_QUERY_DIRECTORY) guac_rdpdr_fs_process_query_directory(svc, device, iorequest, input_stream); /* Request notification of changes to directory */ else if (iorequest->minor_func == IRP_MN_NOTIFY_CHANGE_DIRECTORY) guac_rdpdr_fs_process_notify_change_directory(svc, device, iorequest, input_stream); break; /* Lock/unlock portions of a file */ case IRP_MJ_LOCK_CONTROL: guac_rdpdr_fs_process_lock_control(svc, device, iorequest, input_stream); break; default: guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unknown filesystem I/O request function: 0x%x/0x%x", iorequest->major_func, iorequest->minor_func); } } void guac_rdpdr_device_fs_free_handler(guac_rdp_common_svc* svc, guac_rdpdr_device* device) { Stream_Free(device->device_announce, 1); } void guac_rdpdr_register_fs(guac_rdp_common_svc* svc, char* drive_name) { guac_client* client = svc->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; int id = rdpdr->devices_registered++; /* Get new device */ guac_rdpdr_device* device = &(rdpdr->devices[id]); /* Init device */ device->device_id = id; device->device_name = drive_name; int device_name_len = guac_utf8_strlen(device->device_name); device->device_type = RDPDR_DTYP_FILESYSTEM; device->dos_name = "GUACFS\0\0"; /* Set up the device announcement */ device->device_announce_len = 20 + device_name_len; device->device_announce = Stream_New(NULL, device->device_announce_len); Stream_Write_UINT32(device->device_announce, device->device_type); Stream_Write_UINT32(device->device_announce, device->device_id); Stream_Write(device->device_announce, device->dos_name, 8); Stream_Write_UINT32(device->device_announce, device_name_len); Stream_Write(device->device_announce, device->device_name, device_name_len); /* Set handlers */ device->iorequest_handler = guac_rdpdr_device_fs_iorequest_handler; device->free_handler = guac_rdpdr_device_fs_free_handler; /* Init data */ device->data = rdp_client->filesystem; } guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c0000644000175100001440000002064713764613616025425 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/rdpdr/rdpdr-fs-messages-dir-info.h" #include "channels/rdpdr/rdpdr.h" #include "fs.h" #include "unicode.h" #include #include #include #include #include #include void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, const char* entry_name, int entry_file_id) { guac_rdp_fs_file* file; wStream* output_stream; int length = guac_utf8_strlen(entry_name); int utf16_length = length*2; unsigned char utf16_entry_name[256]; guac_rdp_utf8_to_utf16((const unsigned char*) entry_name, length, (char*) utf16_entry_name, sizeof(utf16_entry_name)); /* Get file */ file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, entry_file_id); if (file == NULL) return; guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i (entry_name=\"%s\")]", __func__, entry_file_id, entry_name); output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4 + 64 + utf16_length + 2); Stream_Write_UINT32(output_stream, 64 + utf16_length + 2); /* Length */ Stream_Write_UINT32(output_stream, 0); /* NextEntryOffset */ Stream_Write_UINT32(output_stream, 0); /* FileIndex */ Stream_Write_UINT64(output_stream, file->ctime); /* CreationTime */ Stream_Write_UINT64(output_stream, file->atime); /* LastAccessTime */ Stream_Write_UINT64(output_stream, file->mtime); /* LastWriteTime */ Stream_Write_UINT64(output_stream, file->mtime); /* ChangeTime */ Stream_Write_UINT64(output_stream, file->size); /* EndOfFile */ Stream_Write_UINT64(output_stream, file->size); /* AllocationSize */ Stream_Write_UINT32(output_stream, file->attributes); /* FileAttributes */ Stream_Write_UINT32(output_stream, utf16_length+2); /* FileNameLength*/ Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */ Stream_Write(output_stream, "\0\0", 2); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, const char* entry_name, int entry_file_id) { guac_rdp_fs_file* file; wStream* output_stream; int length = guac_utf8_strlen(entry_name); int utf16_length = length*2; unsigned char utf16_entry_name[256]; guac_rdp_utf8_to_utf16((const unsigned char*) entry_name, length, (char*) utf16_entry_name, sizeof(utf16_entry_name)); /* Get file */ file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, entry_file_id); if (file == NULL) return; guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i (entry_name=\"%s\")]", __func__, entry_file_id, entry_name); output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4 + 68 + utf16_length + 2); Stream_Write_UINT32(output_stream, 68 + utf16_length + 2); /* Length */ Stream_Write_UINT32(output_stream, 0); /* NextEntryOffset */ Stream_Write_UINT32(output_stream, 0); /* FileIndex */ Stream_Write_UINT64(output_stream, file->ctime); /* CreationTime */ Stream_Write_UINT64(output_stream, file->atime); /* LastAccessTime */ Stream_Write_UINT64(output_stream, file->mtime); /* LastWriteTime */ Stream_Write_UINT64(output_stream, file->mtime); /* ChangeTime */ Stream_Write_UINT64(output_stream, file->size); /* EndOfFile */ Stream_Write_UINT64(output_stream, file->size); /* AllocationSize */ Stream_Write_UINT32(output_stream, file->attributes); /* FileAttributes */ Stream_Write_UINT32(output_stream, utf16_length+2); /* FileNameLength*/ Stream_Write_UINT32(output_stream, 0); /* EaSize */ Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */ Stream_Write(output_stream, "\0\0", 2); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, const char* entry_name, int entry_file_id) { guac_rdp_fs_file* file; wStream* output_stream; int length = guac_utf8_strlen(entry_name); int utf16_length = length*2; unsigned char utf16_entry_name[256]; guac_rdp_utf8_to_utf16((const unsigned char*) entry_name, length, (char*) utf16_entry_name, sizeof(utf16_entry_name)); /* Get file */ file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, entry_file_id); if (file == NULL) return; guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i (entry_name=\"%s\")]", __func__, entry_file_id, entry_name); output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4 + 69 + 24 + utf16_length + 2); Stream_Write_UINT32(output_stream, 69 + 24 + utf16_length + 2); /* Length */ Stream_Write_UINT32(output_stream, 0); /* NextEntryOffset */ Stream_Write_UINT32(output_stream, 0); /* FileIndex */ Stream_Write_UINT64(output_stream, file->ctime); /* CreationTime */ Stream_Write_UINT64(output_stream, file->atime); /* LastAccessTime */ Stream_Write_UINT64(output_stream, file->mtime); /* LastWriteTime */ Stream_Write_UINT64(output_stream, file->mtime); /* ChangeTime */ Stream_Write_UINT64(output_stream, file->size); /* EndOfFile */ Stream_Write_UINT64(output_stream, file->size); /* AllocationSize */ Stream_Write_UINT32(output_stream, file->attributes); /* FileAttributes */ Stream_Write_UINT32(output_stream, utf16_length+2); /* FileNameLength*/ Stream_Write_UINT32(output_stream, 0); /* EaSize */ Stream_Write_UINT8(output_stream, 0); /* ShortNameLength */ /* Apparently, the reserved byte here must be skipped ... */ Stream_Zero(output_stream, 24); /* FileName */ Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */ Stream_Write(output_stream, "\0\0", 2); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_query_names_info(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, const char* entry_name, int entry_file_id) { guac_rdp_fs_file* file; wStream* output_stream; int length = guac_utf8_strlen(entry_name); int utf16_length = length*2; unsigned char utf16_entry_name[256]; guac_rdp_utf8_to_utf16((const unsigned char*) entry_name, length, (char*) utf16_entry_name, sizeof(utf16_entry_name)); /* Get file */ file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, entry_file_id); if (file == NULL) return; guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i (entry_name=\"%s\")]", __func__, entry_file_id, entry_name); output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4 + 12 + utf16_length + 2); Stream_Write_UINT32(output_stream, 12 + utf16_length + 2); /* Length */ Stream_Write_UINT32(output_stream, 0); /* NextEntryOffset */ Stream_Write_UINT32(output_stream, 0); /* FileIndex */ Stream_Write_UINT32(output_stream, utf16_length+2); /* FileNameLength*/ Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */ Stream_Write(output_stream, "\0\0", 2); guac_rdp_common_svc_write(svc, output_stream); } guacamole-server-1.3.0/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h0000644000175100001440000000506513764613616023170 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_RDPDR_PRINTER_H #define GUAC_RDP_CHANNELS_RDPDR_PRINTER_H #include "channels/common-svc.h" #include "channels/rdpdr/rdpdr.h" #include /** * Name of the printer driver that should be used on the server. */ #define GUAC_PRINTER_DRIVER "M\0S\0 \0P\0u\0b\0l\0i\0s\0h\0e\0r\0 \0I\0m\0a\0g\0e\0s\0e\0t\0t\0e\0r\0\0\0" /** * The size of GUAC_PRINTER_DRIVER in bytes. */ #define GUAC_PRINTER_DRIVER_LENGTH 50 /** * Registers a new printer device within the RDPDR plugin. This must be done * before RDPDR connection finishes. * * @param svc * The static virtual channel instance being used for RDPDR. * * @param printer_name * The name of the printer that will be registered with the RDP * connection and passed through to the server. */ void guac_rdpdr_register_printer(guac_rdp_common_svc* svc, char* printer_name); /** * I/O request handler which processes a print job creation request. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_process_print_job_create; /** * I/O request handler which processes a request to write data to an existing * print job. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_process_print_job_write; /** * I/O request handler which processes a request to close an existing print * job. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_process_print_job_close; /** * Handler for RDPDR Device I/O Requests which processes received messages on * behalf of a printer device, in this case a simulated printer which produces * PDF output. */ guac_rdpdr_device_iorequest_handler guac_rdpdr_device_printer_iorequest_handler; /** * Free handler which frees all data specific to the simulated printer device. */ guac_rdpdr_device_free_handler guac_rdpdr_device_printer_free_handler; #endif guacamole-server-1.3.0/src/protocols/rdp/channels/pipe-svc.h0000644000175100001440000001457313764613616021013 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_PIPE_SVC_H #define GUAC_RDP_CHANNELS_PIPE_SVC_H #include "channels/common-svc.h" #include #include #include #include #include #include #include /** * The maximum number of bytes to allow within each channel name, including * null terminator. */ #define GUAC_RDP_SVC_MAX_LENGTH 8 /** * Structure describing a static virtual channel and a corresponding Guacamole * pipe stream; */ typedef struct guac_rdp_pipe_svc { /** * The output pipe, opened when the RDP server receives a connection to * the static channel. */ guac_stream* output_pipe; /** * The underlying static channel. Data written to this SVC by the RDP * server will be forwarded along the pipe stream to the Guacamole client, * and data written to the pipe stream by the Guacamole client will be * forwarded along the SVC to the RDP server. */ guac_rdp_common_svc* svc; } guac_rdp_pipe_svc; /** * Initializes arbitrary static virtual channel (SVC) support for RDP, handling * communication for the SVC having the given name. Data sent from within the * RDP session using this channel will be sent along an identically-named pipe * stream to the Guacamole client, and data sent along a pipe stream having the * same name will be written to the SVC and received within the RDP session. If * failures occur while loading the plugin, messages noting the specifics of * those failures will be logged, and support for the given channel will not be * functional. * * This MUST be called within the PreConnect callback of the freerdp instance * for static virtual channel support to be loaded. * * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. * * @param name * The name of the SVC which should be handled. */ void guac_rdp_pipe_svc_load_plugin(rdpContext* context, char* name); /** * Sends the "pipe" instruction describing the given static virtual channel * along the given socket. This pipe instruction will relate the SVC's * underlying output stream with the SVC's name and the mimetype * "application/octet-stream". * * @param socket * The socket along which the "pipe" instruction should be sent. * * @param svc * The static virtual channel that the "pipe" instruction should describe. */ void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* svc); /** * Sends the "pipe" instructions describing all static virtual channels * available to the given user along that user's socket. Each pipe instruction * will relate the associated SVC's underlying output stream with the SVC's * name and the mimetype "application/octet-stream". * * @param user * The user to send the "pipe" instructions to. */ void guac_rdp_pipe_svc_send_pipes(guac_user* user); /** * Add the given SVC to the list of all available SVCs. This function must be * invoked after the SVC is connected for inbound pipe streams having that * SVC's name to result in received data being sent into the RDP session. * * @param client * The guac_client associated with the current RDP session. * * @param svc * The static virtual channel to add to the list of all such channels * available. */ void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* svc); /** * Retrieve the SVC with the given name from the list stored in the client. The * requested SVC must previously have been added using guac_rdp_pipe_svc_add(). * * @param client * The guac_client associated with the current RDP session. * * @param name * The name of the static virtual channel to retrieve. * * @return * The static virtual channel with the given name, or NULL if no such * virtual channel exists. */ guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name); /** * Removes the SVC with the given name from the list stored in the client. * Inbound pipe streams having the given name will no longer be routed to the * associated SVC. * * @param client * The guac_client associated with the current RDP session. * * @param name * The name of the static virtual channel to remove. * * @return * The static virtual channel that was removed, or NULL if no such virtual * channel exists. */ guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name); /** * Handler for "blob" instructions which writes received data to the associated * SVC using guac_rdp_pipe_svc_write(). */ guac_user_blob_handler guac_rdp_pipe_svc_blob_handler; /** * Handler for "pipe" instructions which prepares received pipe streams to * write received blobs to the SVC having the same name as the pipe stream. * Received pipe streams are associated with the relevant guac_rdp_pipe_svc * instance and the SVC-specific "blob" instruction handler * (guac_rdp_pipe_svc_blob_handler). */ guac_user_pipe_handler guac_rdp_pipe_svc_pipe_handler; /** * Handler which is invoked when an SVC associated with a Guacamole pipe stream * is connected to the RDP server. */ guac_rdp_common_svc_connect_handler guac_rdp_pipe_svc_process_connect; /** * Handler which is invoked when an SVC associated with a Guacamole pipe stream * received data from the RDP server. */ guac_rdp_common_svc_receive_handler guac_rdp_pipe_svc_process_receive; /** * Handler which is invoked when an SVC associated with a Guacamole pipe stream * has disconnected and is about to be freed. */ guac_rdp_common_svc_terminate_handler guac_rdp_pipe_svc_process_terminate; #endif guacamole-server-1.3.0/src/protocols/rdp/channels/rail.h0000644000175100001440000000257013764613616020206 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_RAIL_H #define GUAC_RDP_CHANNELS_RAIL_H #include /** * Initializes RemoteApp support for RDP and handling of the RAIL channel. If * failures occur, messages noting the specifics of those failures will be * logged, and RemoteApp support will not be functional. * * This MUST be called within the PreConnect callback of the freerdp instance * for RAIL support to be loaded. * * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. */ void guac_rdp_rail_load_plugin(rdpContext* context); #endif guacamole-server-1.3.0/src/protocols/rdp/channels/cliprdr.h0000644000175100001440000001250513764613616020715 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_CLIPRDR_H #define GUAC_RDP_CHANNELS_CLIPRDR_H #include "common/clipboard.h" #include #include #include #include #include #include /** * RDP clipboard, leveraging the "CLIPRDR" channel. */ typedef struct guac_rdp_clipboard { /** * The guac_client associated with the RDP connection. The broadcast * socket of this client will receive any clipboard data received from the * RDP server. */ guac_client* client; /** * CLIPRDR control interface. */ CliprdrClientContext* cliprdr; /** * The current clipboard contents. */ guac_common_clipboard* clipboard; /** * The format of the clipboard which was requested. Data received from * the RDP server should conform to this format. This will be one of * several legal clipboard format values defined within FreeRDP's WinPR * library, such as CF_TEXT. */ UINT requested_format; } guac_rdp_clipboard; /** * Allocates a new guac_rdp_clipboard which has been initialized for processing * of Guacamole clipboard data. Support for the RDP side of the clipboard (the * CLIPRDR channel) must be loaded separately during FreeRDP's PreConnect event * using guac_rdp_clipboard_load_plugin(). * * @param client * The guac_client associated with the Guacamole side of the RDP * connection. * * @return * A newly-allocated instance of guac_rdp_clipboard which has been * initialized for processing Guacamole clipboard data. */ guac_rdp_clipboard* guac_rdp_clipboard_alloc(guac_client* client); /** * Initializes clipboard support for RDP and handling of the CLIPRDR channel. * If failures occur, messages noting the specifics of those failures will be * logged, and the RDP side of clipboard support will not be functional. * * This MUST be called within the PreConnect callback of the freerdp instance * for CLIPRDR support to be loaded. * * @param clipboard * The guac_rdp_clipboard instance which has been allocated for the current * RDP connection. * * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. */ void guac_rdp_clipboard_load_plugin(guac_rdp_clipboard* clipboard, rdpContext* context); /** * Frees the resources associated with clipboard support for RDP and handling * of the CLIPRDR channel. Only resources specific to Guacamole are freed. * Resources specific to FreeRDP's handling of the CLIPRDR channel will be * freed by FreeRDP. If the provided guac_rdp_clipboard is NULL, this function * has no effect. * * @param clipboard * The guac_rdp_clipboard instance which was been allocated for the current * RDP connection. */ void guac_rdp_clipboard_free(guac_rdp_clipboard* clipboard); /** * Handler for inbound clipboard data, received via the stream created by an * inbound "clipboard" instruction. This handler will assign the * stream-specific handlers for processing "blob" and "end" instructions which * will eventually be received as clipboard data is sent. This specific handler * is expected to be assigned to the guac_user object of any user that may send * clipboard data. The guac_rdp_clipboard instance which will receive this data * MUST already be stored on the guac_rdp_client structure associated with the * current RDP connection. */ guac_user_clipboard_handler guac_rdp_clipboard_handler; /** * Handler for stream data related to clipboard, received via "blob" * instructions for a stream which has already been created with an inbound * "clipboard" instruction. This specific handler is assigned to the * guac_stream structure associated with that clipboard stream by * guac_rdp_clipboard_handler(). The guac_rdp_clipboard instance which will * receive this data MUST already be stored on the guac_rdp_client structure * associated with the current RDP connection. */ guac_user_blob_handler guac_rdp_clipboard_blob_handler; /** * Handler for end-of-stream related to clipboard, indicated via an "end" * instruction for a stream which has already been created with an inbound * "clipboard" instruction. This specific handler is assigned to the * guac_stream structure associated with that clipboard stream by * guac_rdp_clipboard_handler(). The guac_rdp_clipboard instance which will * receive this data MUST already be stored on the guac_rdp_client structure * associated with the current RDP connection. */ guac_user_end_handler guac_rdp_clipboard_end_handler; #endif guacamole-server-1.3.0/src/protocols/rdp/channels/common-svc.c0000644000175100001440000000735613770536337021343 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/common-svc.h" #include "plugins/channels.h" #include "rdp.h" #include #include #include #include #include #include #include int guac_rdp_common_svc_load_plugin(rdpContext* context, char* name, ULONG channel_options, guac_rdp_common_svc_connect_handler* connect_handler, guac_rdp_common_svc_receive_handler* receive_handler, guac_rdp_common_svc_terminate_handler* terminate_handler) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_common_svc* svc = calloc(1, sizeof(guac_rdp_common_svc)); svc->client = client; svc->name = svc->_channel_def.name; svc->_connect_handler = connect_handler; svc->_receive_handler = receive_handler; svc->_terminate_handler = terminate_handler; /* Init FreeRDP channel definition */ int name_length = guac_strlcpy(svc->_channel_def.name, name, GUAC_RDP_SVC_MAX_LENGTH); svc->_channel_def.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | channel_options; /* Warn about name length */ if (name_length >= GUAC_RDP_SVC_MAX_LENGTH) guac_client_log(client, GUAC_LOG_WARNING, "Static channel name \"%s\" exceeds maximum length of %i " "characters and will be truncated to \"%s\".", name, GUAC_RDP_SVC_MAX_LENGTH - 1, svc->name); /* Attempt to load the common SVC plugin for new static channel */ int result = guac_freerdp_channels_load_plugin(context, "guac-common-svc", svc); if (result) { guac_client_log(client, GUAC_LOG_WARNING, "Cannot create static " "channel \"%s\": failed to load \"guac-common-svc\" plugin " "for FreeRDP.", svc->name); free(svc); } /* Store and log on success (SVC structure will be freed on channel termination) */ else guac_client_log(client, GUAC_LOG_DEBUG, "Support for static channel " "\"%s\" loaded.", svc->name); return result; } void guac_rdp_common_svc_write(guac_rdp_common_svc* svc, wStream* output_stream) { /* Do not write if plugin not associated */ if (!svc->_open_handle) { guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " "written to SVC \"%s\" are being dropped because the remote " "desktop side of that SVC is not yet connected.", Stream_Length(output_stream), svc->name); return; } /* NOTE: The wStream sent via pVirtualChannelWriteEx will automatically be * freed later with a call to Stream_Free() when handling the * corresponding write cancel/completion event. */ svc->_entry_points.pVirtualChannelWriteEx(svc->_init_handle, svc->_open_handle, Stream_Buffer(output_stream), Stream_GetPosition(output_stream), output_stream); } guacamole-server-1.3.0/src/protocols/rdp/channels/cliprdr.c0000644000175100001440000005560413770536337020720 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/cliprdr.h" #include "client.h" #include "common/clipboard.h" #include "common/iconv.h" #include "config.h" #include "plugins/channels.h" #include "rdp.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef FREERDP_CLIPRDR_CALLBACKS_REQUIRE_CONST /** * FreeRDP 2.0.0-rc4 and newer requires the final argument for all CLIPRDR * callbacks to be const. */ #define CLIPRDR_CONST const #else /** * FreeRDP 2.0.0-rc3 and older requires the final argument for all CLIPRDR * callbacks to NOT be const. */ #define CLIPRDR_CONST #endif /** * Sends a Format List PDU to the RDP server containing the formats of * clipboard data supported. This PDU is used both to indicate the general * clipboard formats supported at the begining of an RDP session and to inform * the RDP server that new clipboard data is available within the listed * formats. * * @param cliprdr * The CliprdrClientContext structure used by FreeRDP to handle the * CLIPRDR channel for the current RDP session. * * @return * CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an * error code (non-zero) otherwise. */ static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) { /* This function is only invoked within FreeRDP-specific handlers for * CLIPRDR, which are not assigned, and thus not callable, until after the * relevant guac_rdp_clipboard structure is allocated and associated with * the CliprdrClientContext */ guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; assert(clipboard != NULL); /* We support CP-1252 and UTF-16 text */ CLIPRDR_FORMAT_LIST format_list = { .msgType = CB_FORMAT_LIST, .formats = (CLIPRDR_FORMAT[]) { { .formatId = CF_TEXT }, { .formatId = CF_UNICODETEXT } }, .numFormats = 2 }; guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending " "format list"); return cliprdr->ClientFormatList(cliprdr, &format_list); } /** * Sends a Clipboard Capabilities PDU to the RDP server describing the features * of the CLIPRDR channel that are supported by the client. * * @param cliprdr * The CliprdrClientContext structure used by FreeRDP to handle the * CLIPRDR channel for the current RDP session. * * @return * CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent * successfully, an error code (non-zero) otherwise. */ static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) { CLIPRDR_GENERAL_CAPABILITY_SET cap_set = { .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */ .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */ .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */ .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */ }; CLIPRDR_CAPABILITIES caps = { .cCapabilitiesSets = 1, .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set }; return cliprdr->ClientCapabilities(cliprdr, &caps); } /** * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready * PDUs. The Monitor Ready PDU is sent by the RDP server only during * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel * handshake and indicates that the RDP server's handling of clipboard * redirection is ready to proceed. * * @param cliprdr * The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR * channel for the current RDP session. * * @param monitor_ready * The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU * that was received. * * @return * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code * (non-zero) otherwise. */ static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, CLIPRDR_CONST CLIPRDR_MONITOR_READY* monitor_ready) { /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not * callable, until after the relevant guac_rdp_clipboard structure is * allocated and associated with the CliprdrClientContext */ guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; assert(clipboard != NULL); guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received " "monitor ready."); /* Respond with capabilities ... */ int status = guac_rdp_cliprdr_send_capabilities(cliprdr); if (status != CHANNEL_RC_OK) return status; /* ... and supported format list */ return guac_rdp_cliprdr_send_format_list(cliprdr); } /** * Sends a Format Data Request PDU to the RDP server, requesting that available * clipboard data be sent to the client in the specified format. This PDU is * sent when the server indicates that clipboard data is available via a Format * List PDU. * * @param client * The guac_client associated with the current RDP session. * * @param format * The clipboard format to request. This format must be one of the * documented values used by the CLIPRDR channel for clipboard format IDs. * * @return * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code * (non-zero) otherwise. */ static UINT guac_rdp_cliprdr_send_format_data_request( CliprdrClientContext* cliprdr, UINT32 format) { /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not * callable, until after the relevant guac_rdp_clipboard structure is * allocated and associated with the CliprdrClientContext */ guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; assert(clipboard != NULL); /* Create new data request */ CLIPRDR_FORMAT_DATA_REQUEST data_request = { .requestedFormatId = format }; /* Note the format we've requested for reference later when the requested * data is received via a Format Data Response PDU */ clipboard->requested_format = format; guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending " "format data request."); /* Send request */ return cliprdr->ClientFormatDataRequest(cliprdr, &data_request); } /** * Returns whether the given Format List PDU indicates support for the given * clipboard format. * * @param format_list * The CLIPRDR_FORMAT_LIST structure representing the Format List PDU * being tested. * * @param format_id * The ID of the clipboard format to test, such as CF_TEXT or * CF_UNICODETEXT. * * @return * Non-zero if the given Format List PDU indicates support for the given * clipboard format, zero otherwise. */ static int guac_rdp_cliprdr_format_supported(const CLIPRDR_FORMAT_LIST* format_list, UINT format_id) { /* Search format list for matching ID */ for (int i = 0; i < format_list->numFormats; i++) { if (format_list->formats[i].formatId == format_id) return 1; } /* If no matching ID, format is not supported */ return 0; } /** * Callback invoked by the FreeRDP CLIPRDR plugin for received Format List * PDUs. The Format List PDU is sent by the RDP server to indicate that new * clipboard data has been copied and is available for retrieval in the formats * listed. A client wishing to retrieve that data responds with a Format Data * Request PDU. * * @param cliprdr * The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR * channel for the current RDP session. * * @param format_list * The CLIPRDR_FORMAT_LIST structure representing the Format List PDU that * was received. * * @return * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code * (non-zero) otherwise. */ static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr, CLIPRDR_CONST CLIPRDR_FORMAT_LIST* format_list) { /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not * callable, until after the relevant guac_rdp_clipboard structure is * allocated and associated with the CliprdrClientContext */ guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; assert(clipboard != NULL); guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received " "format list."); CLIPRDR_FORMAT_LIST_RESPONSE format_list_response = { .msgFlags = CB_RESPONSE_OK }; /* Report successful processing of format list */ cliprdr->ClientFormatListResponse(cliprdr, &format_list_response); /* Prefer Unicode (in this case, UTF-16) */ if (guac_rdp_cliprdr_format_supported(format_list, CF_UNICODETEXT)) return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_UNICODETEXT); /* Use Windows' CP-1252 if Unicode unavailable */ if (guac_rdp_cliprdr_format_supported(format_list, CF_TEXT)) return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_TEXT); /* Ignore any unsupported data */ guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Ignoring unsupported " "clipboard data. Only Unicode and text clipboard formats are " "currently supported."); return CHANNEL_RC_OK; } /** * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data * Request PDUs. The Format Data Request PDU is sent by the RDP server when * requesting that clipboard data be sent, in response to a received Format * List PDU. The client is required to respond with a Format Data Response PDU * containing the requested data. * * @param cliprdr * The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR * channel for the current RDP session. * * @param format_data_request * The CLIPRDR_FORMAT_DATA_REQUEST structure representing the Format Data * Request PDU that was received. * * @return * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code * (non-zero) otherwise. */ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr, CLIPRDR_CONST CLIPRDR_FORMAT_DATA_REQUEST* format_data_request) { /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not * callable, until after the relevant guac_rdp_clipboard structure is * allocated and associated with the CliprdrClientContext */ guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; assert(clipboard != NULL); guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received " "format data request."); guac_iconv_write* writer; const char* input = clipboard->clipboard->buffer; char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH); /* Map requested clipboard format to a guac_iconv writer */ switch (format_data_request->requestedFormatId) { case CF_TEXT: writer = GUAC_WRITE_CP1252; break; case CF_UNICODETEXT: writer = GUAC_WRITE_UTF16; break; /* Warn if clipboard data cannot be sent as intended due to a violation * of the CLIPRDR spec */ default: guac_client_log(clipboard->client, GUAC_LOG_WARNING, "Received " "clipboard data cannot be sent to the RDP server because " "the RDP server has requested a clipboard format which " "was not declared as available. This violates the " "specification for the CLIPRDR channel."); free(output); return CHANNEL_RC_OK; } /* Send received clipboard data to the RDP server in the format * requested */ BYTE* start = (BYTE*) output; guac_iconv(GUAC_READ_UTF8, &input, clipboard->clipboard->length, writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH); CLIPRDR_FORMAT_DATA_RESPONSE data_response = { .requestedFormatData = (BYTE*) start, .dataLen = ((BYTE*) output) - start, .msgFlags = CB_RESPONSE_OK }; guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending " "format data response."); UINT result = cliprdr->ClientFormatDataResponse(cliprdr, &data_response); free(start); return result; } /** * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data * Response PDUs. The Format Data Response PDU is sent by the RDP server when * fullfilling a request for clipboard data received via a Format Data Request * PDU. * * @param cliprdr * The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR * channel for the current RDP session. * * @param format_data_response * The CLIPRDR_FORMAT_DATA_RESPONSE structure representing the Format Data * Response PDU that was received. * * @return * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code * (non-zero) otherwise. */ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr, CLIPRDR_CONST CLIPRDR_FORMAT_DATA_RESPONSE* format_data_response) { /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not * callable, until after the relevant guac_rdp_clipboard structure is * allocated and associated with the CliprdrClientContext */ guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; assert(clipboard != NULL); guac_client* client = clipboard->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; guac_client_log(client, GUAC_LOG_TRACE, "CLIPRDR: Received format data response."); /* Ignore received data if copy has been disabled */ if (settings->disable_copy) { guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Ignoring received " "clipboard data as copying from within the remote desktop has " "been explicitly disabled."); return CHANNEL_RC_OK; } char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH]; guac_iconv_read* reader; const char* input = (char*) format_data_response->requestedFormatData; char* output = received_data; /* Find correct source encoding */ switch (clipboard->requested_format) { /* Non-Unicode (Windows CP-1252) */ case CF_TEXT: reader = GUAC_READ_CP1252; break; /* Unicode (UTF-16) */ case CF_UNICODETEXT: reader = GUAC_READ_UTF16; break; /* If the format ID stored within the guac_rdp_clipboard structure is actually * not supported here, then something has been implemented incorrectly. * Either incorrect values are (somehow) being stored, or support for * the format indicated by that value is incomplete and must be added * here. The values which may be stored within requested_format are * completely within our control. */ default: guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Requested " "clipboard data in unsupported format (0x%X).", clipboard->requested_format); return CHANNEL_RC_OK; } /* Convert, store, and forward the clipboard data received from RDP * server */ if (guac_iconv(reader, &input, format_data_response->dataLen, GUAC_WRITE_UTF8, &output, sizeof(received_data))) { int length = strnlen(received_data, sizeof(received_data)); guac_common_clipboard_reset(clipboard->clipboard, "text/plain"); guac_common_clipboard_append(clipboard->clipboard, received_data, length); guac_common_clipboard_send(clipboard->clipboard, clipboard->client); } return CHANNEL_RC_OK; } /** * Callback which associates handlers specific to Guacamole with the * CliprdrClientContext instance allocated by FreeRDP to deal with received * CLIPRDR (clipboard redirection) messages. * * This function is called whenever a channel connects via the PubSub event * system within FreeRDP, but only has any effect if the connected channel is * the CLIPRDR channel. This specific callback is registered with the PubSub * system of the relevant rdpContext when guac_rdp_clipboard_load_plugin() is * called. * * @param context * The rdpContext associated with the active RDP session. * * @param e * Event-specific arguments, mainly the name of the channel, and a * reference to the associated plugin loaded for that channel by FreeRDP. */ static void guac_rdp_cliprdr_channel_connected(rdpContext* context, ChannelConnectedEventArgs* e) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_clipboard* clipboard = rdp_client->clipboard; /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not * callable, until after the relevant guac_rdp_clipboard structure is * allocated and associated with the guac_rdp_client */ assert(clipboard != NULL); /* Ignore connection event if it's not for the CLIPRDR channel */ if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) != 0) return; /* The structure pointed to by pInterface is guaranteed to be a * CliprdrClientContext if the channel is CLIPRDR */ CliprdrClientContext* cliprdr = (CliprdrClientContext*) e->pInterface; /* Associate FreeRDP CLIPRDR context and its Guacamole counterpart with * eachother */ cliprdr->custom = clipboard; clipboard->cliprdr = cliprdr; cliprdr->MonitorReady = guac_rdp_cliprdr_monitor_ready; cliprdr->ServerFormatList = guac_rdp_cliprdr_format_list; cliprdr->ServerFormatDataRequest = guac_rdp_cliprdr_format_data_request; cliprdr->ServerFormatDataResponse = guac_rdp_cliprdr_format_data_response; guac_client_log(client, GUAC_LOG_DEBUG, "CLIPRDR (clipboard redirection) " "channel connected."); } guac_rdp_clipboard* guac_rdp_clipboard_alloc(guac_client* client) { /* Allocate clipboard and underlying storage */ guac_rdp_clipboard* clipboard = calloc(1, sizeof(guac_rdp_clipboard)); clipboard->client = client; clipboard->clipboard = guac_common_clipboard_alloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH); clipboard->requested_format = CF_TEXT; return clipboard; } void guac_rdp_clipboard_load_plugin(guac_rdp_clipboard* clipboard, rdpContext* context) { /* Attempt to load FreeRDP support for the CLIPRDR channel */ if (guac_freerdp_channels_load_plugin(context, "cliprdr", NULL)) { guac_client_log(clipboard->client, GUAC_LOG_WARNING, "Support for the CLIPRDR channel (clipboard redirection) " "could not be loaded. This support normally takes the form of " "a plugin which is built into FreeRDP. Lacking this support, " "clipboard will not work."); return; } /* Complete RDP side of initialization when channel is connected */ PubSub_SubscribeChannelConnected(context->pubSub, (pChannelConnectedEventHandler) guac_rdp_cliprdr_channel_connected); guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Support for CLIPRDR " "(clipboard redirection) registered. Awaiting channel " "connection."); } void guac_rdp_clipboard_free(guac_rdp_clipboard* clipboard) { /* Do nothing if the clipboard is not actually allocated */ if (clipboard == NULL) return; /* Free clipboard and underlying storage */ guac_common_clipboard_free(clipboard->clipboard); free(clipboard); } int guac_rdp_clipboard_handler(guac_user* user, guac_stream* stream, char* mimetype) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Ignore stream creation if no clipboard structure is available to handle * received data */ guac_rdp_clipboard* clipboard = rdp_client->clipboard; if (clipboard == NULL) return 0; /* Handle any future "blob" and "end" instructions for this stream with * handlers that are aware of the RDP clipboard state */ stream->blob_handler = guac_rdp_clipboard_blob_handler; stream->end_handler = guac_rdp_clipboard_end_handler; /* Clear any current contents, assigning the mimetype the data which will * be received */ guac_common_clipboard_reset(clipboard->clipboard, mimetype); return 0; } int guac_rdp_clipboard_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Ignore received data if no clipboard structure is available to handle * that data */ guac_rdp_clipboard* clipboard = rdp_client->clipboard; if (clipboard == NULL) return 0; /* Append received data to current clipboard contents */ guac_common_clipboard_append(clipboard->clipboard, (char*) data, length); return 0; } int guac_rdp_clipboard_end_handler(guac_user* user, guac_stream* stream) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Ignore end of stream if no clipboard structure is available to handle * the data that was received */ guac_rdp_clipboard* clipboard = rdp_client->clipboard; if (clipboard == NULL) return 0; /* Terminate clipboard data with NULL */ guac_common_clipboard_append(clipboard->clipboard, "", 1); /* Notify RDP server of new data, if connected */ if (clipboard->cliprdr != NULL) { guac_client_log(client, GUAC_LOG_DEBUG, "Clipboard data received. " "Reporting availability of clipboard data to RDP server."); guac_rdp_cliprdr_send_format_list(clipboard->cliprdr); } else guac_client_log(client, GUAC_LOG_DEBUG, "Clipboard data has been " "received, but cannot be sent to the RDP server because the " "CLIPRDR channel is not yet connected."); return 0; } guacamole-server-1.3.0/src/protocols/rdp/channels/rdpsnd/0000755000175100001440000000000013772471160020447 500000000000000guacamole-server-1.3.0/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c0000644000175100001440000003145313764613616023645 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/rdpsnd/rdpsnd-messages.h" #include "channels/rdpsnd/rdpsnd.h" #include "rdp.h" #include #include #include #include #include #include #include void guac_rdpsnd_formats_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int server_format_count; int server_version; int i; wStream* output_stream; int output_body_size; unsigned char* output_stream_end; guac_client* client = svc->client; guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_audio_stream* audio = rdp_client->audio; /* Reset own format count */ rdpsnd->format_count = 0; /* * Check to make sure the stream has at least 20 bytes (14 byte seek, * 2 x UTF16 reads, and 2 x UTF8 seeks). */ if (Stream_GetRemainingLength(input_stream) < 20) { guac_client_log(client, GUAC_LOG_WARNING, "Server Audio Formats and " "Version PDU does not contain the expected number of bytes. " "Audio redirection may not work as expected."); return; } /* Format header */ Stream_Seek(input_stream, 14); Stream_Read_UINT16(input_stream, server_format_count); Stream_Seek_UINT8(input_stream); Stream_Read_UINT16(input_stream, server_version); Stream_Seek_UINT8(input_stream); /* Initialize Client Audio Formats and Version PDU */ output_stream = Stream_New(NULL, 24); Stream_Write_UINT8(output_stream, SNDC_FORMATS); Stream_Write_UINT8(output_stream, 0); /* Fill in body size later */ Stream_Seek_UINT16(output_stream); /* offset = 0x02 */ /* Flags, volume, and pitch */ Stream_Write_UINT32(output_stream, TSSNDCAPS_ALIVE); Stream_Write_UINT32(output_stream, 0); Stream_Write_UINT32(output_stream, 0); /* Datagram port (UDP) */ Stream_Write_UINT16(output_stream, 0); /* Fill in format count later */ Stream_Seek_UINT16(output_stream); /* offset = 0x12 */ /* Version and padding */ Stream_Write_UINT8(output_stream, 0); Stream_Write_UINT16(output_stream, 6); Stream_Write_UINT8(output_stream, 0); /* Check each server format, respond if supported and audio is enabled */ if (audio != NULL) { for (i=0; i < server_format_count; i++) { unsigned char* format_start; int format_tag; int channels; int rate; int bps; int body_size; /* Remember position in stream */ Stream_GetPointer(input_stream, format_start); /* Check to make sure Stream has at least 18 bytes. */ if (Stream_GetRemainingLength(input_stream) < 18) { guac_client_log(client, GUAC_LOG_WARNING, "Server Audio " "Formats and Version PDU does not contain the expected " "number of bytes. Audio redirection may not work as " "expected."); return; } /* Read format */ Stream_Read_UINT16(input_stream, format_tag); Stream_Read_UINT16(input_stream, channels); Stream_Read_UINT32(input_stream, rate); Stream_Seek_UINT32(input_stream); Stream_Seek_UINT16(input_stream); Stream_Read_UINT16(input_stream, bps); /* Skip past extra data */ Stream_Read_UINT16(input_stream, body_size); /* Check that Stream has at least body_size bytes remaining. */ if (Stream_GetRemainingLength(input_stream) < body_size) { guac_client_log(client, GUAC_LOG_WARNING, "Server Audio " "Formats and Version PDU does not contain the expected " "number of bytes. Audio redirection may not work as " "expected."); return; } Stream_Seek(input_stream, body_size); /* If PCM, accept */ if (format_tag == WAVE_FORMAT_PCM) { /* If can fit another format, accept it */ if (rdpsnd->format_count < GUAC_RDP_MAX_FORMATS) { /* Add channel */ int current = rdpsnd->format_count++; rdpsnd->formats[current].rate = rate; rdpsnd->formats[current].channels = channels; rdpsnd->formats[current].bps = bps; /* Log format */ guac_client_log(client, GUAC_LOG_INFO, "Accepted format: %i-bit PCM with %i channels at " "%i Hz", bps, channels, rate); /* Ensure audio stream is configured to use accepted * format */ guac_audio_stream_reset(audio, NULL, rate, channels, bps); /* Queue format for sending as accepted */ Stream_EnsureRemainingCapacity(output_stream, 18 + body_size); Stream_Write(output_stream, format_start, 18 + body_size); /* * BEWARE that using Stream_EnsureRemainingCapacity means * that any pointers returned via Stream_GetPointer on * output_stream are invalid. */ } /* Otherwise, log that we dropped one */ else guac_client_log(client, GUAC_LOG_INFO, "Dropped valid format: %i-bit PCM with %i " "channels at %i Hz", bps, channels, rate); } } } /* Otherwise, ignore all supported formats as we do not intend to actually * receive audio */ else guac_client_log(client, GUAC_LOG_DEBUG, "Audio explicitly disabled. Ignoring supported formats."); /* Calculate size of PDU */ output_body_size = Stream_GetPosition(output_stream) - 4; Stream_GetPointer(output_stream, output_stream_end); /* Set body size */ Stream_SetPosition(output_stream, 0x02); Stream_Write_UINT16(output_stream, output_body_size); /* Set format count */ Stream_SetPosition(output_stream, 0x12); Stream_Write_UINT16(output_stream, rdpsnd->format_count); /* Reposition cursor at end (necessary for message send) */ Stream_SetPointer(output_stream, output_stream_end); /* Send accepted formats */ guac_rdp_common_svc_write(svc, output_stream); /* If version greater than 6, must send Quality Mode PDU */ if (server_version >= 6) { /* Always send High Quality for now */ output_stream = Stream_New(NULL, 8); Stream_Write_UINT8(output_stream, SNDC_QUALITYMODE); Stream_Write_UINT8(output_stream, 0); Stream_Write_UINT16(output_stream, 4); Stream_Write_UINT16(output_stream, HIGH_QUALITY); Stream_Write_UINT16(output_stream, 0); guac_rdp_common_svc_write(svc, output_stream); } } /* server is getting a feel of the round trip time */ void guac_rdpsnd_training_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int data_size; wStream* output_stream; guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; /* Check to make sure audio stream contains a minimum number of bytes. */ if (Stream_GetRemainingLength(input_stream) < 4) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Audio Training PDU " "does not contain the expected number of bytes. Audio " "redirection may not work as expected."); return; } /* Read timestamp and data size */ Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp); Stream_Read_UINT16(input_stream, data_size); /* Send training response */ output_stream = Stream_New(NULL, 8); Stream_Write_UINT8(output_stream, SNDC_TRAINING); Stream_Write_UINT8(output_stream, 0); Stream_Write_UINT16(output_stream, 4); Stream_Write_UINT16(output_stream, rdpsnd->server_timestamp); Stream_Write_UINT16(output_stream, data_size); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpsnd_wave_info_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int format; guac_client* client = svc->client; guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_audio_stream* audio = rdp_client->audio; /* Check to make sure audio stream contains a minimum number of bytes. */ if (Stream_GetRemainingLength(input_stream) < 12) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Audio WaveInfo PDU " "does not contain the expected number of bytes. Sound may not " "work as expected."); return; } /* Read wave information */ Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp); Stream_Read_UINT16(input_stream, format); Stream_Read_UINT8(input_stream, rdpsnd->waveinfo_block_number); Stream_Seek(input_stream, 3); Stream_Read(input_stream, rdpsnd->initial_wave_data, 4); /* * Size of incoming wave data is equal to the body size field of this * header, less the size of a WaveInfo PDU (not including the header), * thus body_size - 12. */ rdpsnd->incoming_wave_size = header->body_size - 12; /* Read wave in next iteration */ rdpsnd->next_pdu_is_wave = TRUE; /* Reset audio stream if format has changed */ if (audio != NULL) { if (format < GUAC_RDP_MAX_FORMATS) guac_audio_stream_reset(audio, NULL, rdpsnd->formats[format].rate, rdpsnd->formats[format].channels, rdpsnd->formats[format].bps); else guac_client_log(svc->client, GUAC_LOG_WARNING, "RDP server " "attempted to specify an invalid audio format. Sound may " "not work as expected."); } } void guac_rdpsnd_wave_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header) { guac_client* client = svc->client; guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_audio_stream* audio = rdp_client->audio; /* Verify that the stream has bytes to cover the wave size plus header. */ if (Stream_Length(input_stream) < (rdpsnd->incoming_wave_size + 4)) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Audio Wave PDU does " "not contain the expected number of bytes. Sound may not work " "as expected."); return; } /* Wave Confirmation PDU */ wStream* output_stream = Stream_New(NULL, 8); /* Get wave data */ unsigned char* buffer = Stream_Buffer(input_stream); /* Copy over first four bytes */ memcpy(buffer, rdpsnd->initial_wave_data, 4); /* Write rest of audio packet */ if (audio != NULL) { guac_audio_stream_write_pcm(audio, buffer, rdpsnd->incoming_wave_size + 4); guac_audio_stream_flush(audio); } /* Write Wave Confirmation PDU */ Stream_Write_UINT8(output_stream, SNDC_WAVECONFIRM); Stream_Write_UINT8(output_stream, 0); Stream_Write_UINT16(output_stream, 4); Stream_Write_UINT16(output_stream, rdpsnd->server_timestamp); Stream_Write_UINT8(output_stream, rdpsnd->waveinfo_block_number); Stream_Write_UINT8(output_stream, 0); /* Send Wave Confirmation PDU */ guac_rdp_common_svc_write(svc, output_stream); /* We no longer expect to receive wave data */ rdpsnd->next_pdu_is_wave = FALSE; } void guac_rdpsnd_close_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header) { /* Do nothing */ } guacamole-server-1.3.0/src/protocols/rdp/channels/rdpsnd/rdpsnd.h0000644000175100001440000000767213764613616022053 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_RDPSND_H #define GUAC_RDP_CHANNELS_RDPSND_H #include "channels/common-svc.h" #include #include /** * The maximum number of PCM formats to accept during the initial RDPSND * handshake with the RDP server. */ #define GUAC_RDP_MAX_FORMATS 16 /** * Abstract representation of a PCM format, including the sample rate, number * of channels, and bits per sample. */ typedef struct guac_rdpsnd_pcm_format { /** * The sample rate of this PCM format. */ int rate; /** * The number off channels used by this PCM format. This will typically * be 1 or 2. */ int channels; /** * The number of bits per sample within this PCM format. This should be * either 8 or 16. */ int bps; } guac_rdpsnd_pcm_format; /** * Structure representing the current state of the Guacamole RDPSND plugin for * FreeRDP. */ typedef struct guac_rdpsnd { /** * The block number of the last SNDC_WAVE (WaveInfo) PDU received. */ int waveinfo_block_number; /** * Whether the next PDU coming is a SNDWAVE (Wave) PDU. Wave PDUs do not * have headers, and are indicated by the receipt of a WaveInfo PDU. */ int next_pdu_is_wave; /** * The wave data received within the last SNDC_WAVE (WaveInfo) PDU. */ unsigned char initial_wave_data[4]; /** * The size, in bytes, of the wave data in the coming Wave PDU, if any. * This does not include the initial wave data received within the last * SNDC_WAVE (WaveInfo) PDU, which is always the first four bytes of the * actual wave data block. */ int incoming_wave_size; /** * The last received server timestamp. */ int server_timestamp; /** * All formats agreed upon by server and client during the initial format * exchange. All of these formats will be PCM, which is the only format * guaranteed to be supported (based on the official RDP documentation). */ guac_rdpsnd_pcm_format formats[GUAC_RDP_MAX_FORMATS]; /** * The total number of formats. */ int format_count; } guac_rdpsnd; /** * Initializes audio output support for RDP and handling of the RDPSND channel. * If failures occur, messages noting the specifics of those failures will be * logged, and the RDP side of audio output support will not be functional. * * This MUST be called within the PreConnect callback of the freerdp instance * for RDPSND support to be loaded. * * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. */ void guac_rdpsnd_load_plugin(rdpContext* context); /** * Handler which is invoked when the RDPSND channel is connected to the RDP * server. */ guac_rdp_common_svc_connect_handler guac_rdpsnd_process_connect; /** * Handler which is invoked when the RDPSND channel has received data from the * RDP server. */ guac_rdp_common_svc_receive_handler guac_rdpsnd_process_receive; /** * Handler which is invoked when the RDPSND channel has disconnected and is * about to be freed. */ guac_rdp_common_svc_terminate_handler guac_rdpsnd_process_terminate; #endif guacamole-server-1.3.0/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.h0000644000175100001440000001155013764613616023646 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_RDPSND_MESSAGES_H #define GUAC_RDP_CHANNELS_RDPSND_MESSAGES_H #include "channels/common-svc.h" #include /** * The header common to all RDPSND PDUs. */ typedef struct guac_rdpsnd_pdu_header { /** * The type of message represented by this PDU (SNDC_WAVE, etc.) */ int message_type; /** * The size of the remainder of the message. */ int body_size; } guac_rdpsnd_pdu_header; /** * Handler for the SNDC_FORMATS (Server Audio Formats and Version) PDU. The * SNDC_FORMATS PDU describes all audio formats supported by the RDP server, as * well as the version of RDPSND implemented. * * @param svc * The RDPSND channel receiving the SNDC_FORMATS PDU. * * @param input_stream * The FreeRDP input stream containing the remaining raw bytes (after the * common header) of the SNDC_FORMATS PDU. * * @param header * The header content of the SNDC_FORMATS PDU. All RDPSND messages contain * the same header information. */ void guac_rdpsnd_formats_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** * Handler for the SNDC_TRAINING (Training) PDU. The SNDC_TRAINING PDU is used * to by RDP servers to test audio streaming latency, etc. without actually * sending audio data. See: * * https://msdn.microsoft.com/en-us/library/cc240961.aspx * * @param svc * The RDPSND channel receiving the SNDC_TRAINING PDU. * * @param input_stream * The FreeRDP input stream containing the remaining raw bytes (after the * common header) of the SNDC_TRAINING PDU. * * @param header * The header content of the SNDC_TRAINING PDU. All RDPSND messages contain * the same header information. */ void guac_rdpsnd_training_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** * Handler for the SNDC_WAVE (WaveInfo) PDU. The SNDC_WAVE immediately precedes * a SNDWAV PDU and describes the data about to be received. It also (very * strangely) contains exactly 4 bytes of audio data. The following SNDWAV PDU * then contains 4 bytes of padding prior to the audio data where it would make * perfect sense for this data to go. See: * * https://msdn.microsoft.com/en-us/library/cc240963.aspx * * @param svc * The RDPSND channel receiving the SNDC_WAVE PDU. * * @param input_stream * The FreeRDP input stream containing the remaining raw bytes (after the * common header) of the SNDC_WAVE PDU. * * @param header * The header content of the SNDC_WAVE PDU. All RDPSND messages contain * the same header information. */ void guac_rdpsnd_wave_info_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** * Handler for the SNDWAV (Wave) PDU which follows any WaveInfo PDU. The SNDWAV * PDU contains the actual audio data, less the four bytes of audio data * included in the SNDC_WAVE PDU. * * @param svc * The RDPSND channel receiving the SNDWAV PDU. * * @param input_stream * The FreeRDP input stream containing the remaining raw bytes (after the * common header) of the SNDWAV PDU. * * @param header * The header content of the SNDWAV PDU. All RDPSND messages contain * the same header information. */ void guac_rdpsnd_wave_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** * Handler for the SNDC_CLOSE (Close) PDU. This PDU is sent when audio * streaming has stopped. This PDU is currently ignored by Guacamole. See: * * https://msdn.microsoft.com/en-us/library/cc240970.aspx * * @param svc * The RDPSND channel receiving the SNDC_CLOSE PDU. * * @param input_stream * The FreeRDP input stream containing the remaining raw bytes (after the * common header) of the SNDC_CLOSE PDU. * * @param header * The header content of the SNDC_CLOSE PDU. All RDPSND messages contain * the same header information. */ void guac_rdpsnd_close_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header); #endif guacamole-server-1.3.0/src/protocols/rdp/channels/rdpsnd/rdpsnd.c0000644000175100001440000000706413764613616022041 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/common-svc.h" #include "channels/rdpsnd/rdpsnd.h" #include "channels/rdpsnd/rdpsnd-messages.h" #include "rdp.h" #include #include #include #include #include void guac_rdpsnd_process_receive(guac_rdp_common_svc* svc, wStream* input_stream) { guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; guac_rdpsnd_pdu_header header; /* Check that we have at least the 4 byte header (UINT8 + UINT8 + UINT16) */ if (Stream_GetRemainingLength(input_stream) < 4) { guac_client_log(svc->client, GUAC_LOG_WARNING, "Audio Stream does not " "contain the expected number of bytes. Audio redirection may " "not work as expected."); return; } /* Read RDPSND PDU header */ Stream_Read_UINT8(input_stream, header.message_type); Stream_Seek_UINT8(input_stream); Stream_Read_UINT16(input_stream, header.body_size); /* * If next PDU is SNDWAVE (due to receiving WaveInfo PDU previously), * ignore the header and parse as a Wave PDU. */ if (rdpsnd->next_pdu_is_wave) { guac_rdpsnd_wave_handler(svc, input_stream, &header); return; } /* Dispatch message to standard handlers */ switch (header.message_type) { /* Server Audio Formats and Version PDU */ case SNDC_FORMATS: guac_rdpsnd_formats_handler(svc, input_stream, &header); break; /* Training PDU */ case SNDC_TRAINING: guac_rdpsnd_training_handler(svc, input_stream, &header); break; /* WaveInfo PDU */ case SNDC_WAVE: guac_rdpsnd_wave_info_handler(svc, input_stream, &header); break; /* Close PDU */ case SNDC_CLOSE: guac_rdpsnd_close_handler(svc, input_stream, &header); break; } } void guac_rdpsnd_process_connect(guac_rdp_common_svc* svc) { guac_rdpsnd* rdpsnd = (guac_rdpsnd*) calloc(1, sizeof(guac_rdpsnd)); svc->data = rdpsnd; } void guac_rdpsnd_process_terminate(guac_rdp_common_svc* svc) { guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; free(rdpsnd); } void guac_rdpsnd_load_plugin(rdpContext* context) { guac_client* client = ((rdp_freerdp_context*) context)->client; /* Load support for RDPSND */ if (guac_rdp_common_svc_load_plugin(context, "rdpsnd", 0, guac_rdpsnd_process_connect, guac_rdpsnd_process_receive, guac_rdpsnd_process_terminate)) { guac_client_log(client, GUAC_LOG_WARNING, "Support for the RDPSND " "channel (audio output) could not be loaded. Sound will not " "work. Drive redirection and printing MAY not work."); } } guacamole-server-1.3.0/src/protocols/rdp/channels/pipe-svc.c0000644000175100001440000001630313764613616020777 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/common-svc.h" #include "channels/pipe-svc.h" #include "common/list.h" #include "rdp.h" #include #include #include #include #include #include #include #include #include void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* pipe_svc) { /* Send pipe instruction for the SVC's output stream */ guac_protocol_send_pipe(socket, pipe_svc->output_pipe, "application/octet-stream", pipe_svc->svc->name); } void guac_rdp_pipe_svc_send_pipes(guac_user* user) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_common_list_lock(rdp_client->available_svc); /* Send pipe for each allocated SVC's output stream */ guac_common_list_element* current = rdp_client->available_svc->head; while (current != NULL) { guac_rdp_pipe_svc_send_pipe(user->socket, (guac_rdp_pipe_svc*) current->data); current = current->next; } guac_common_list_unlock(rdp_client->available_svc); } void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* pipe_svc) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Add to list of available SVC */ guac_common_list_lock(rdp_client->available_svc); guac_common_list_add(rdp_client->available_svc, pipe_svc); guac_common_list_unlock(rdp_client->available_svc); } guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_common_list_element* current; guac_rdp_pipe_svc* found = NULL; /* For each available SVC */ guac_common_list_lock(rdp_client->available_svc); current = rdp_client->available_svc->head; while (current != NULL) { /* If name matches, found */ guac_rdp_pipe_svc* current_svc = (guac_rdp_pipe_svc*) current->data; if (strcmp(current_svc->svc->name, name) == 0) { found = current_svc; break; } current = current->next; } guac_common_list_unlock(rdp_client->available_svc); return found; } guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_common_list_element* current; guac_rdp_pipe_svc* found = NULL; /* For each available SVC */ guac_common_list_lock(rdp_client->available_svc); current = rdp_client->available_svc->head; while (current != NULL) { /* If name matches, remove entry */ guac_rdp_pipe_svc* current_svc = (guac_rdp_pipe_svc*) current->data; if (strcmp(current_svc->svc->name, name) == 0) { guac_common_list_remove(rdp_client->available_svc, current); found = current_svc; break; } current = current->next; } guac_common_list_unlock(rdp_client->available_svc); /* Return removed entry, if any */ return found; } int guac_rdp_pipe_svc_pipe_handler(guac_user* user, guac_stream* stream, char* mimetype, char* name) { guac_rdp_pipe_svc* pipe_svc = guac_rdp_pipe_svc_get(user->client, name); /* Fail if no such SVC */ if (pipe_svc == NULL) { guac_user_log(user, GUAC_LOG_WARNING, "User requested non-existent " "pipe (no such SVC configured): \"%s\"", name); guac_protocol_send_ack(user->socket, stream, "FAIL (NO SUCH PIPE)", GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST); guac_socket_flush(user->socket); return 0; } else guac_user_log(user, GUAC_LOG_DEBUG, "Inbound half of channel \"%s\" " "connected.", name); /* Init stream data */ stream->data = pipe_svc; stream->blob_handler = guac_rdp_pipe_svc_blob_handler; return 0; } int guac_rdp_pipe_svc_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { guac_rdp_pipe_svc* pipe_svc = (guac_rdp_pipe_svc*) stream->data; /* Write blob data to SVC directly */ wStream* output_stream = Stream_New(NULL, length); Stream_Write(output_stream, data, length); guac_rdp_common_svc_write(pipe_svc->svc, output_stream); guac_protocol_send_ack(user->socket, stream, "OK (DATA RECEIVED)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(user->socket); return 0; } void guac_rdp_pipe_svc_process_connect(guac_rdp_common_svc* svc) { /* Associate SVC with new Guacamole pipe */ guac_rdp_pipe_svc* pipe_svc = malloc(sizeof(guac_rdp_pipe_svc)); pipe_svc->svc = svc; pipe_svc->output_pipe = guac_client_alloc_stream(svc->client); svc->data = pipe_svc; /* SVC may now receive data from client */ guac_rdp_pipe_svc_add(svc->client, pipe_svc); /* Notify of pipe's existence */ guac_rdp_pipe_svc_send_pipe(svc->client->socket, pipe_svc); } void guac_rdp_pipe_svc_process_receive(guac_rdp_common_svc* svc, wStream* input_stream) { guac_rdp_pipe_svc* pipe_svc = (guac_rdp_pipe_svc*) svc->data; /* Fail if output not created */ if (pipe_svc->output_pipe == NULL) { guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " "received from within the remote desktop session for SVC " "\"%s\" are being dropped because the outbound pipe stream " "for that SVC is not yet open. This should NOT happen.", Stream_Length(input_stream), svc->name); return; } /* Send received data as blob */ guac_protocol_send_blob(svc->client->socket, pipe_svc->output_pipe, Stream_Buffer(input_stream), Stream_Length(input_stream)); guac_socket_flush(svc->client->socket); } void guac_rdp_pipe_svc_process_terminate(guac_rdp_common_svc* svc) { guac_rdp_pipe_svc* pipe_svc = (guac_rdp_pipe_svc*) svc->data; if (pipe_svc == NULL) return; /* Remove and free SVC */ guac_rdp_pipe_svc_remove(svc->client, svc->name); free(pipe_svc); } void guac_rdp_pipe_svc_load_plugin(rdpContext* context, char* name) { /* Attempt to load support for static channel */ guac_rdp_common_svc_load_plugin(context, name, CHANNEL_OPTION_COMPRESS_RDP, guac_rdp_pipe_svc_process_connect, guac_rdp_pipe_svc_process_receive, guac_rdp_pipe_svc_process_terminate); } guacamole-server-1.3.0/src/protocols/rdp/channels/disp.c0000644000175100001440000001631113764613616020207 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/disp.h" #include "plugins/channels.h" #include "rdp.h" #include "settings.h" #include #include #include #include #include #include #include guac_rdp_disp* guac_rdp_disp_alloc() { guac_rdp_disp* disp = malloc(sizeof(guac_rdp_disp)); /* Not yet connected */ disp->disp = NULL; /* No requests have been made */ disp->last_request = guac_timestamp_current(); disp->requested_width = 0; disp->requested_height = 0; disp->reconnect_needed = 0; return disp; } void guac_rdp_disp_free(guac_rdp_disp* disp) { free(disp); } /** * Callback which associates handlers specific to Guacamole with the * DispClientContext instance allocated by FreeRDP to deal with received * Display Update (client-initiated dynamic display resizing) messages. * * This function is called whenever a channel connects via the PubSub event * system within FreeRDP, but only has any effect if the connected channel is * the Display Update channel. This specific callback is registered with the * PubSub system of the relevant rdpContext when guac_rdp_disp_load_plugin() is * called. * * @param context * The rdpContext associated with the active RDP session. * * @param e * Event-specific arguments, mainly the name of the channel, and a * reference to the associated plugin loaded for that channel by FreeRDP. */ static void guac_rdp_disp_channel_connected(rdpContext* context, ChannelConnectedEventArgs* e) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_disp* guac_disp = rdp_client->disp; /* Ignore connection event if it's not for the Display Update channel */ if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) != 0) return; /* Init module with current display size */ guac_rdp_disp_set_size(guac_disp, rdp_client->settings, context->instance, guac_rdp_get_width(context->instance), guac_rdp_get_height(context->instance)); /* Store reference to the display update plugin once it's connected */ DispClientContext* disp = (DispClientContext*) e->pInterface; guac_disp->disp = disp; guac_client_log(client, GUAC_LOG_DEBUG, "Display update channel " "will be used for display size changes."); } void guac_rdp_disp_load_plugin(rdpContext* context) { /* Subscribe to and handle channel connected events */ PubSub_SubscribeChannelConnected(context->pubSub, (pChannelConnectedEventHandler) guac_rdp_disp_channel_connected); /* Add "disp" channel */ guac_freerdp_dynamic_channel_collection_add(context->settings, "disp", NULL); } /** * Fits a given dimension within the allowed bounds for Display Update * messages, adjusting the other dimension such that aspect ratio is * maintained. * * @param a The dimension to fit within allowed bounds. * * @param b * The other dimension to adjust if and only if necessary to preserve * aspect ratio. */ static void guac_rdp_disp_fit(int* a, int* b) { int a_value = *a; int b_value = *b; /* Ensure first dimension is within allowed range */ if (a_value < GUAC_RDP_DISP_MIN_SIZE) { /* Adjust other dimension to maintain aspect ratio */ int adjusted_b = b_value * GUAC_RDP_DISP_MIN_SIZE / a_value; if (adjusted_b > GUAC_RDP_DISP_MAX_SIZE) adjusted_b = GUAC_RDP_DISP_MAX_SIZE; *a = GUAC_RDP_DISP_MIN_SIZE; *b = adjusted_b; } else if (a_value > GUAC_RDP_DISP_MAX_SIZE) { /* Adjust other dimension to maintain aspect ratio */ int adjusted_b = b_value * GUAC_RDP_DISP_MAX_SIZE / a_value; if (adjusted_b < GUAC_RDP_DISP_MIN_SIZE) adjusted_b = GUAC_RDP_DISP_MIN_SIZE; *a = GUAC_RDP_DISP_MAX_SIZE; *b = adjusted_b; } } void guac_rdp_disp_set_size(guac_rdp_disp* disp, guac_rdp_settings* settings, freerdp* rdp_inst, int width, int height) { /* Fit width within bounds, adjusting height to maintain aspect ratio */ guac_rdp_disp_fit(&width, &height); /* Fit height within bounds, adjusting width to maintain aspect ratio */ guac_rdp_disp_fit(&height, &width); /* Width must be even */ if (width % 2 == 1) width -= 1; /* Store deferred size */ disp->requested_width = width; disp->requested_height = height; /* Send display update notification if possible */ guac_rdp_disp_update_size(disp, settings, rdp_inst); } void guac_rdp_disp_update_size(guac_rdp_disp* disp, guac_rdp_settings* settings, freerdp* rdp_inst) { int width = disp->requested_width; int height = disp->requested_height; /* Do not update size if no requests have been received */ if (width == 0 || height == 0) return; guac_timestamp now = guac_timestamp_current(); /* Limit display update frequency */ if (now - disp->last_request <= GUAC_RDP_DISP_UPDATE_INTERVAL) return; /* Do NOT send requests unless the size will change */ if (rdp_inst != NULL && width == guac_rdp_get_width(rdp_inst) && height == guac_rdp_get_height(rdp_inst)) return; disp->last_request = now; if (settings->resize_method == GUAC_RESIZE_RECONNECT) { /* Update settings with new dimensions */ settings->width = width; settings->height = height; /* Signal reconnect */ disp->reconnect_needed = 1; } else if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) { DISPLAY_CONTROL_MONITOR_LAYOUT monitors[1] = {{ .Flags = 0x1, /* DISPLAYCONTROL_MONITOR_PRIMARY */ .Left = 0, .Top = 0, .Width = width, .Height = height, .PhysicalWidth = 0, .PhysicalHeight = 0, .Orientation = 0, .DesktopScaleFactor = 0, .DeviceScaleFactor = 0 }}; /* Send display update notification if display channel is connected */ if (disp->disp != NULL) disp->disp->SendMonitorLayout(disp->disp, 1, monitors); } } int guac_rdp_disp_reconnect_needed(guac_rdp_disp* disp) { return disp->reconnect_needed; } void guac_rdp_disp_reconnect_complete(guac_rdp_disp* disp) { disp->reconnect_needed = 0; disp->last_request = guac_timestamp_current(); } guacamole-server-1.3.0/src/protocols/rdp/channels/common-svc.h0000644000175100001440000001765413764613616021351 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_COMMON_SVC_H #define GUAC_RDP_CHANNELS_COMMON_SVC_H #include #include #include #include #include #include #include /** * The maximum number of bytes to allow within each channel name, including * null terminator. */ #define GUAC_RDP_SVC_MAX_LENGTH 8 /** * The maximum number of bytes that the RDP server will be allowed to send * within any single write operation, regardless of the number of chunks that * write is split into. Bytes beyond this limit may be dropped. */ #define GUAC_SVC_MAX_ASSEMBLED_LENGTH 1048576 /** * Structure describing a static virtual channel, and the corresponding * Guacamole pipes and FreeRDP resources. */ typedef struct guac_rdp_common_svc guac_rdp_common_svc; /** * Handler which is invoked when a CHANNEL_EVENT_CONNECTED event has been * processed and the connection/initialization process of the SVC is now * complete. * * @param svc * The guac_rdp_common_svc structure representing the SVC that is now * connected. */ typedef void guac_rdp_common_svc_connect_handler(guac_rdp_common_svc* svc); /** * Handler which is invoked when a logical block of data has been received * along an SVC, having been reassembled from a series of * CHANNEL_EVENT_DATA_RECEIVED events. * * @param svc * The guac_rdp_common_svc structure representing the SVC that received the * data. * * @param input_stream * The reassembled block of data that was received. */ typedef void guac_rdp_common_svc_receive_handler(guac_rdp_common_svc* svc, wStream* input_stream); /** * Handler which is invoked when a CHANNEL_EVENT_TERMINATED event has been * processed and all resources associated with the SVC must now be freed. * * @param svc * The guac_rdp_common_svc structure representing the SVC that has been * terminated. */ typedef void guac_rdp_common_svc_terminate_handler(guac_rdp_common_svc* svc); struct guac_rdp_common_svc { /** * Reference to the client owning this static channel. */ guac_client* client; /** * The name of the static virtual channel, as specified to * guac_rdp_common_svc_load_plugin(). This value is stored and defined * internally by the CHANNEL_DEF. */ const char* name; /** * Arbitrary channel-specific data which may be assigned and referenced by * channel implementations leveraging the "guac-common-svc" plugin. */ void* data; /** * Handler which is invoked when handling a CHANNEL_EVENT_CONNECTED event. */ guac_rdp_common_svc_connect_handler* _connect_handler; /** * Handler which is invoked when all chunks of data for a single logical * block have been received via CHANNEL_EVENT_DATA_RECEIVED events and * reassembled. */ guac_rdp_common_svc_receive_handler* _receive_handler; /** * Handler which is invokved when the SVC has been disconnected and is * about to be freed. */ guac_rdp_common_svc_terminate_handler* _terminate_handler; /** * The definition of this static virtual channel, including its name. */ CHANNEL_DEF _channel_def; /** * Functions and data specific to the FreeRDP side of the virtual channel * and plugin. */ CHANNEL_ENTRY_POINTS_FREERDP_EX _entry_points; /** * Handle which identifies the client connection, typically referred to * within the FreeRDP source as pInitHandle. This handle is provided to the * channel entry point and the channel init event handler. The handle must * eventually be used within the channel open event handler to obtain a * handle to the channel itself. */ PVOID _init_handle; /** * Handle which identifies the channel itself, typically referred to within * the FreeRDP source as OpenHandle. This handle is obtained through a call * to entry_points.pVirtualChannelOpenEx() in response to receiving a * CHANNEL_EVENT_CONNECTED event via the init event handler. * * Data is received in CHANNEL_EVENT_DATA_RECEIVED events via the open * event handler, and data is written through calls to * entry_points.pVirtualChannelWriteEx(). */ DWORD _open_handle; /** * All data that has been received thus far from the current RDP server * write operation. Data received along virtual channels is sent in chunks * (typically 1600 bytes), and thus must be gradually reassembled as it is * received. */ wStream* _input_stream; }; /** * Initializes arbitrary static virtual channel (SVC) support for RDP, loading * a new instance of Guacamole's arbitrary SVC plugin for FreeRDP ("guacsvc") * supporting the channel having the given name. Data sent from within the RDP * session using this channel will be sent along an identically-named pipe * stream to the Guacamole client, and data sent along a pipe stream having the * same name will be written to the SVC and received within the RDP session. If * failures occur while loading the plugin, messages noting the specifics of * those failures will be logged, and support for the given channel will not be * functional. * * This MUST be called within the PreConnect callback of the freerdp instance * for static virtual channel support to be loaded. * * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. * * @param name * The name of the SVC which should be handled by the new instance of the * plugin. * * @param channel_options * Bitwise OR of any of the several CHANNEL_OPTION_* flags. Regardless of * whether specified here, the CHANNEL_OPTION_INTIALIZED and * CHANNEL_OPTION_ENCRYPT_RDP flags will automatically be set. * * @param connect_handler * The function to invoke when the SVC has been connected. * * @param receive_handler * The function to invoke when the SVC has received a logical block of * data, reassembled from perhaps several smaller chunks of data. * * @param terminate_handler * The function to invoke when the SVC has been disconnected and is about * to be freed. * * @return * Zero if the plugin was loaded successfully, non-zero if the plugin could * not be loaded. */ int guac_rdp_common_svc_load_plugin(rdpContext* context, char* name, ULONG channel_options, guac_rdp_common_svc_connect_handler* connect_handler, guac_rdp_common_svc_receive_handler* receive_handler, guac_rdp_common_svc_terminate_handler* terminate_handler); /** * Writes the given data to the virtual channel such that it can be received * within the RDP session. The given data MUST be dynamically allocated, as the * write operation may be queued and the actual write may not occur until * later. The provided wStream and the buffer it points to will be * automatically freed after the write occurs. * * @param svc * The static virtual channel to write data to. * * @param output_stream * The data to write, which MUST be dynamically allocated. */ void guac_rdp_common_svc_write(guac_rdp_common_svc* svc, wStream* output_stream); #endif guacamole-server-1.3.0/src/protocols/rdp/channels/rail.c0000644000175100001440000002252313764613616020201 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/rail.h" #include "plugins/channels.h" #include "rdp.h" #include "settings.h" #include #include #include #include #include #include #include #include #include #ifdef FREERDP_RAIL_CALLBACKS_REQUIRE_CONST /** * FreeRDP 2.0.0-rc4 and newer requires the final argument for all RAIL * callbacks to be const. */ #define RAIL_CONST const #else /** * FreeRDP 2.0.0-rc3 and older requires the final argument for all RAIL * callbacks to NOT be const. */ #define RAIL_CONST #endif /** * Completes initialization of the RemoteApp session, responding to the server * handshake, sending client status and system parameters, and executing the * desired RemoteApp command. This is accomplished using the Handshake PDU, * Client Information PDU, one or more Client System Parameters Update PDUs, * and the Client Execute PDU respectively. These PDUs MUST be sent for the * desired RemoteApp to run, and MUST NOT be sent until after a Handshake or * HandshakeEx PDU has been received. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/cec4eb83-b304-43c9-8378-b5b8f5e7082a (Handshake PDU) * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/743e782d-f59b-40b5-a0f3-adc74e68a2ff (Client Information PDU) * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/60344497-883f-4711-8b9a-828d1c580195 (System Parameters Update PDU) * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/98a6e3c3-c2a9-42cc-ad91-0d9a6c211138 (Client Execute PDU) * * @param rail * The RailClientContext structure used by FreeRDP to handle the RAIL * channel for the current RDP session. * * @return * CHANNEL_RC_OK (zero) if the PDUs were sent successfully, an error code * (non-zero) otherwise. */ static UINT guac_rdp_rail_complete_handshake(RailClientContext* rail) { UINT status; guac_client* client = (guac_client*) rail->custom; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; RAIL_HANDSHAKE_ORDER handshake = { /* Build number 7600 (0x1DB0) apparently represents Windows 7 and * compatibility with RDP 7.0. As of this writing, this is the same * build number sent for RAIL connections by xfreerdp. */ .buildNumber = 7600 }; /* Send client handshake response */ status = rail->ClientHandshake(rail, &handshake); if (status != CHANNEL_RC_OK) return status; RAIL_CLIENT_STATUS_ORDER client_status = { .flags = 0x00 }; /* Send client status */ status = rail->ClientInformation(rail, &client_status); if (status != CHANNEL_RC_OK) return status; RAIL_SYSPARAM_ORDER sysparam = { .dragFullWindows = FALSE, .highContrast = { .flags = HCF_AVAILABLE | HCF_CONFIRMHOTKEY | HCF_HOTKEYACTIVE | HCF_HOTKEYAVAILABLE | HCF_HOTKEYSOUND | HCF_INDICATOR, .colorScheme = { .string = NULL, .length = 0 } }, .keyboardCues = FALSE, .keyboardPref = FALSE, .mouseButtonSwap = FALSE, .workArea = { .left = 0, .top = 0, .right = rdp_client->settings->width, .bottom = rdp_client->settings->height }, .params = SPI_MASK_SET_DRAG_FULL_WINDOWS | SPI_MASK_SET_HIGH_CONTRAST | SPI_MASK_SET_KEYBOARD_CUES | SPI_MASK_SET_KEYBOARD_PREF | SPI_MASK_SET_MOUSE_BUTTON_SWAP | SPI_MASK_SET_WORK_AREA }; /* Send client system parameters */ status = rail->ClientSystemParam(rail, &sysparam); if (status != CHANNEL_RC_OK) return status; RAIL_EXEC_ORDER exec = { .flags = RAIL_EXEC_FLAG_EXPAND_ARGUMENTS, .RemoteApplicationProgram = rdp_client->settings->remote_app, .RemoteApplicationWorkingDir = rdp_client->settings->remote_app_dir, .RemoteApplicationArguments = rdp_client->settings->remote_app_args, }; /* Execute desired RemoteApp command */ return rail->ClientExecute(rail, &exec); } /** * Callback which is invoked when a Handshake PDU is received from the RDP * server. No communication for RemoteApp may occur until the Handshake PDU * (or, alternatively, the HandshakeEx PDU) is received. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/cec4eb83-b304-43c9-8378-b5b8f5e7082a * * @param rail * The RailClientContext structure used by FreeRDP to handle the RAIL * channel for the current RDP session. * * @param handshake * The RAIL_HANDSHAKE_ORDER structure representing the Handshake PDU that * was received. * * @return * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code * (non-zero) otherwise. */ static UINT guac_rdp_rail_handshake(RailClientContext* rail, RAIL_CONST RAIL_HANDSHAKE_ORDER* handshake) { return guac_rdp_rail_complete_handshake(rail); } /** * Callback which is invoked when a HandshakeEx PDU is received from the RDP * server. No communication for RemoteApp may occur until the HandshakeEx PDU * (or, alternatively, the Handshake PDU) is received. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/5cec5414-27de-442e-8d4a-c8f8b41f3899 * * @param rail * The RailClientContext structure used by FreeRDP to handle the RAIL * channel for the current RDP session. * * @param handshake_ex * The RAIL_HANDSHAKE_EX_ORDER structure representing the HandshakeEx PDU * that was received. * * @return * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code * (non-zero) otherwise. */ static UINT guac_rdp_rail_handshake_ex(RailClientContext* rail, RAIL_CONST RAIL_HANDSHAKE_EX_ORDER* handshake_ex) { return guac_rdp_rail_complete_handshake(rail); } /** * Callback which associates handlers specific to Guacamole with the * RailClientContext instance allocated by FreeRDP to deal with received * RAIL (RemoteApp) messages. * * This function is called whenever a channel connects via the PubSub event * system within FreeRDP, but only has any effect if the connected channel is * the RAIL channel. This specific callback is registered with the PubSub * system of the relevant rdpContext when guac_rdp_rail_load_plugin() is * called. * * @param context * The rdpContext associated with the active RDP session. * * @param e * Event-specific arguments, mainly the name of the channel, and a * reference to the associated plugin loaded for that channel by FreeRDP. */ static void guac_rdp_rail_channel_connected(rdpContext* context, ChannelConnectedEventArgs* e) { guac_client* client = ((rdp_freerdp_context*) context)->client; /* Ignore connection event if it's not for the RAIL channel */ if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) != 0) return; /* The structure pointed to by pInterface is guaranteed to be a * RailClientContext if the channel is RAIL */ RailClientContext* rail = (RailClientContext*) e->pInterface; /* Init FreeRDP RAIL context, ensuring the guac_client can be accessed from * within any RAIL-specific callbacks */ rail->custom = client; rail->ServerHandshake = guac_rdp_rail_handshake; rail->ServerHandshakeEx = guac_rdp_rail_handshake_ex; guac_client_log(client, GUAC_LOG_DEBUG, "RAIL (RemoteApp) channel " "connected."); } void guac_rdp_rail_load_plugin(rdpContext* context) { guac_client* client = ((rdp_freerdp_context*) context)->client; /* Attempt to load FreeRDP support for the RAIL channel */ if (guac_freerdp_channels_load_plugin(context, "rail", context->settings)) { guac_client_log(client, GUAC_LOG_WARNING, "Support for the RAIL channel (RemoteApp) could not be " "loaded. This support normally takes the form of a plugin " "which is built into FreeRDP. Lacking this support, " "RemoteApp will not work."); return; } /* Complete RDP side of initialization when channel is connected */ PubSub_SubscribeChannelConnected(context->pubSub, (pChannelConnectedEventHandler) guac_rdp_rail_channel_connected); guac_client_log(client, GUAC_LOG_DEBUG, "Support for RAIL (RemoteApp) " "registered. Awaiting channel connection."); } guacamole-server-1.3.0/src/protocols/rdp/channels/disp.h0000644000175100001440000001462713764613616020224 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_DISP_H #define GUAC_RDP_CHANNELS_DISP_H #include "settings.h" #include #include #include #include /** * The minimum value for width or height, in pixels. */ #define GUAC_RDP_DISP_MIN_SIZE 200 /** * The maximum value for width or height, in pixels. */ #define GUAC_RDP_DISP_MAX_SIZE 8192 /** * The minimum amount of time that must elapse between display size updates, * in milliseconds. */ #define GUAC_RDP_DISP_UPDATE_INTERVAL 500 /** * Display size update module. */ typedef struct guac_rdp_disp { /** * Display control interface. */ DispClientContext* disp; /** * The timestamp of the last display update request, or 0 if no request * has been sent yet. */ guac_timestamp last_request; /** * The last requested screen width, in pixels. */ int requested_width; /** * The last requested screen height, in pixels. */ int requested_height; /** * Whether the size has changed and the RDP connection must be closed and * reestablished. */ int reconnect_needed; } guac_rdp_disp; /** * Allocates a new display update module, which will ultimately control the * display update channel once connected. * * @return * A newly-allocated display update module. */ guac_rdp_disp* guac_rdp_disp_alloc(); /** * Frees the resources associated with support for the RDP Display Update * channel. Only resources specific to Guacamole are freed. Resources specific * to FreeRDP's handling of the Display Update channel will be freed by * FreeRDP. If no resources are currently allocated for Display Update support, * this function has no effect. * * @param disp * The display update module to free. */ void guac_rdp_disp_free(guac_rdp_disp* disp); /** * Adds FreeRDP's "disp" plugin to the list of dynamic virtual channel plugins * to be loaded by FreeRDP's "drdynvc" plugin. The context of the plugin will * automatically be assicated with the guac_rdp_disp instance pointed to by the * current guac_rdp_client. The plugin will only be loaded once the "drdynvc" * plugin is loaded. The "disp" plugin ultimately adds support for the Display * Update channel. * * If failures occur, messages noting the specifics of those failures will be * logged, and the RDP side of Display Update support will not be functional. * * This MUST be called within the PreConnect callback of the freerdp instance * for Display Update support to be loaded. * * @param context * The rdpContext associated with the active RDP session. */ void guac_rdp_disp_load_plugin(rdpContext* context); /** * Requests a display size update, which may then be sent immediately to the * RDP server. If an update was recently sent, this update may be delayed until * the RDP server has had time to settle. The width/height values provided may * be automatically altered to comply with the restrictions imposed by the * display update channel. * * @param disp * The display update module which should maintain the requested size, * sending the corresponding display update request when appropriate. * * @param settings * The RDP client settings associated with the current or pending RDP * session. These settings will be automatically adjusted to match the new * screen size. * * @param rdp_inst * The FreeRDP instance associated with the current or pending RDP session, * if any. If no RDP session is active, this should be NULL. * * @param width * The desired display width, in pixels. Due to the restrictions of the RDP * display update channel, this will be contrained to the range of 200 * through 8192 inclusive, and rounded down to the nearest even number. * * @param height * The desired display height, in pixels. Due to the restrictions of the * RDP display update channel, this will be contrained to the range of 200 * through 8192 inclusive. */ void guac_rdp_disp_set_size(guac_rdp_disp* disp, guac_rdp_settings* settings, freerdp* rdp_inst, int width, int height); /** * Sends an actual display update request to the RDP server based on previous * calls to guac_rdp_disp_set_size(). If an update was recently sent, the * update may be delayed until a future call to this function. If the RDP * session has not yet been established, the request will be delayed until the * session exists. * * @param disp * The display update module which should track the update request. * * @param settings * The RDP client settings associated with the current or pending RDP * session. These settings will be automatically adjusted to match the new * screen size. * * @param rdp_inst * The FreeRDP instance associated with the current or pending RDP session, * if any. If no RDP session is active, this should be NULL. */ void guac_rdp_disp_update_size(guac_rdp_disp* disp, guac_rdp_settings* settings, freerdp* rdp_inst); /** * Signals the given display update module that the requested reconnect has * been performed. * * @param disp * The display update module that should be signaled regarding the state * of reconnection. */ void guac_rdp_disp_reconnect_complete(guac_rdp_disp* disp); /** * Returns whether a full RDP reconnect is required for display update changes * to take effect. * * @param disp * The display update module that should be checked to determine whether a * reconnect is required. * * @return * Non-zero if a reconnect is needed, zero otherwise. */ int guac_rdp_disp_reconnect_needed(guac_rdp_disp* disp); #endif guacamole-server-1.3.0/src/protocols/rdp/channels/audio-input/0000755000175100001440000000000013772471160021413 500000000000000guacamole-server-1.3.0/src/protocols/rdp/channels/audio-input/audio-input.c0000644000175100001440000001322413770226763023744 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/audio-input/audio-buffer.h" #include "channels/audio-input/audio-input.h" #include "plugins/channels.h" #include "plugins/ptr-string.h" #include "rdp.h" #include #include #include #include #include #include #include #include #include #include /** * Parses the given raw audio mimetype, producing the corresponding rate, * number of channels, and bytes per sample. * * @param mimetype * The raw auduio mimetype to parse. * * @param rate * A pointer to an int where the sample rate for the PCM format described * by the given mimetype should be stored. * * @param channels * A pointer to an int where the number of channels used by the PCM format * described by the given mimetype should be stored. * * @param bps * A pointer to an int where the number of bytes used the PCM format for * each sample (independent of number of channels) described by the given * mimetype should be stored. * * @return * Zero if the given mimetype is a raw audio mimetype and has been parsed * successfully, non-zero otherwise. */ static int guac_rdp_audio_parse_mimetype(const char* mimetype, int* rate, int* channels, int* bps) { int parsed_rate = -1; int parsed_channels = 1; int parsed_bps; /* PCM audio with one byte per sample */ if (strncmp(mimetype, "audio/L8;", 9) == 0) { mimetype += 8; /* Advance to semicolon ONLY */ parsed_bps = 1; } /* PCM audio with two bytes per sample */ else if (strncmp(mimetype, "audio/L16;", 10) == 0) { mimetype += 9; /* Advance to semicolon ONLY */ parsed_bps = 2; } /* Unsupported mimetype */ else return 1; /* Parse each parameter name/value pair within the mimetype */ do { /* Advance to first character of parameter (current is either a * semicolon or a comma) */ mimetype++; /* Parse number of channels */ if (strncmp(mimetype, "channels=", 9) == 0) { mimetype += 9; parsed_channels = strtol(mimetype, (char**) &mimetype, 10); /* Fail if value invalid / out of range */ if (errno == EINVAL || errno == ERANGE) return 1; } /* Parse number of rate */ else if (strncmp(mimetype, "rate=", 5) == 0) { mimetype += 5; parsed_rate = strtol(mimetype, (char**) &mimetype, 10); /* Fail if value invalid / out of range */ if (errno == EINVAL || errno == ERANGE) return 1; } /* Advance to next parameter */ mimetype = strchr(mimetype, ','); } while (mimetype != NULL); /* Mimetype is invalid if rate was not specified */ if (parsed_rate == -1) return 1; /* Parse success */ *rate = parsed_rate; *channels = parsed_channels; *bps = parsed_bps; return 0; } int guac_rdp_audio_handler(guac_user* user, guac_stream* stream, char* mimetype) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; int rate; int channels; int bps; /* Parse mimetype, abort on parse error */ if (guac_rdp_audio_parse_mimetype(mimetype, &rate, &channels, &bps)) { guac_user_log(user, GUAC_LOG_WARNING, "Denying user audio stream with " "unsupported mimetype: \"%s\"", mimetype); guac_protocol_send_ack(user->socket, stream, "Unsupported audio " "mimetype", GUAC_PROTOCOL_STATUS_CLIENT_BAD_TYPE); return 0; } /* Init stream data */ stream->blob_handler = guac_rdp_audio_blob_handler; stream->end_handler = guac_rdp_audio_end_handler; /* Associate stream with audio buffer */ guac_rdp_audio_buffer_set_stream(rdp_client->audio_input, user, stream, rate, channels, bps); return 0; } int guac_rdp_audio_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Write blob to audio stream, buffering if necessary */ guac_rdp_audio_buffer_write(rdp_client->audio_input, data, length); return 0; } int guac_rdp_audio_end_handler(guac_user* user, guac_stream* stream) { /* Ignore - the AUDIO_INPUT channel will simply not receive anything */ return 0; } void guac_rdp_audio_load_plugin(rdpContext* context) { guac_client* client = ((rdp_freerdp_context*) context)->client; char client_ref[GUAC_RDP_PTR_STRING_LENGTH]; /* Add "AUDIO_INPUT" channel */ guac_rdp_ptr_to_string(client, client_ref); guac_freerdp_dynamic_channel_collection_add(context->settings, "guacai", client_ref, NULL); } guacamole-server-1.3.0/src/protocols/rdp/channels/audio-input/audio-buffer.h0000644000175100001440000002122213764613616024060 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_AUDIO_INPUT_AUDIO_BUFFER_H #define GUAC_RDP_CHANNELS_AUDIO_INPUT_AUDIO_BUFFER_H #include #include #include /** * Handler which is invoked when a guac_rdp_audio_buffer's internal packet * buffer has reached capacity and must be flushed. * * @param buffer * The buffer which needs to be flushed as an audio packet. * * @param length * The number of bytes stored within the buffer. This is guaranteed to be * identical to the packet_size value specified when the audio buffer was * initialized. * * @param data * The arbitrary data pointer provided when the audio buffer was * initialized. */ typedef void guac_rdp_audio_buffer_flush_handler(char* buffer, int length, void* data); /** * A description of an arbitrary PCM audio format. */ typedef struct guac_rdp_audio_format { /** * The rate of the audio data in samples per second. */ int rate; /** * The number of channels included in the audio data. This will be 1 for * monaural audio and 2 for stereo. */ int channels; /** * The size of each sample within the audio data, in bytes. */ int bps; } guac_rdp_audio_format; /** * A buffer of arbitrary audio data. Received audio data can be written to this * buffer, and will automatically be flushed via a given handler once the * internal buffer reaches capacity. */ typedef struct guac_rdp_audio_buffer { /** * Lock which is acquired/released to ensure accesses to the audio buffer * are atomic. */ pthread_mutex_t lock; /** * The user from which this audio buffer will receive data. If no user has * yet opened an associated audio stream, this will be NULL. */ guac_user* user; /** * The stream from which this audio buffer will receive data. If no user * has yet opened an associated audio stream, this will be NULL. */ guac_stream* stream; /** * The PCM format of the audio stream being received from the user, if any. * If no stream is yet associated, the values stored within this format are * undefined. */ guac_rdp_audio_format in_format; /** * The PCM format of the audio stream expected by RDP, if any. If no audio * stream has yet been requested by the RDP server, the values stored * within this format are undefined. */ guac_rdp_audio_format out_format; /** * The size that each audio packet must be, in bytes. The packet buffer * within this structure will be at least this size. */ int packet_size; /** * The number of bytes currently stored within the packet buffer. */ int bytes_written; /** * The total number of bytes having ever been received by the Guacamole * server for the current audio stream. */ int total_bytes_received; /** * The total number of bytes having ever been sent to the RDP server for * the current audio stream. */ int total_bytes_sent; /** * All audio data being prepared for sending to the AUDIO_INPUT channel. */ char* packet; /** * Handler function which will be invoked when a full audio packet is * ready to be flushed to the AUDIO_INPUT channel, if defined. If NULL, * audio packets will simply be ignored. */ guac_rdp_audio_buffer_flush_handler* flush_handler; /** * Arbitrary data assigned by the AUDIO_INPUT plugin implementation. */ void* data; } guac_rdp_audio_buffer; /** * Allocates a new audio buffer. The new audio buffer will ignore any received * data until guac_rdp_audio_buffer_begin() is invoked, and will resume * ignoring received data once guac_rdp_audio_buffer_end() is invoked. * * @return * A newly-allocated audio buffer. */ guac_rdp_audio_buffer* guac_rdp_audio_buffer_alloc(); /** * Associates the given audio buffer with the underlying audio stream which * has been received from the given Guacamole user. Once both the Guacamole * audio stream and the RDP audio stream are ready, an appropriate "ack" * message will be sent. * * @param audio_buffer * The audio buffer associated with the audio stream just received. * * @param user * The Guacamole user that created the audio stream. * * @param stream * The guac_stream object representing the audio stream. * * @param rate * The rate of the audio stream being received from the user, if any, in * samples per second. * * @param channels * The number of channels included in the audio stream being received from * the user, if any. * * @param bps * The size of each sample within the audio stream being received from the * user, if any, in bytes. */ void guac_rdp_audio_buffer_set_stream(guac_rdp_audio_buffer* audio_buffer, guac_user* user, guac_stream* stream, int rate, int channels, int bps); /** * Defines the output format that should be used by the audio buffer when * flushing packets of audio data received via guac_rdp_audio_buffer_write(). * As this format determines how the underlying packet buffer will be * allocated, this function MUST be called prior to the call to * guac_rdp_audio_buffer_begin(). * * @param audio_buffer * The audio buffer to set the output format of. * * @param rate * The rate of the audio stream expected by RDP, in samples per second. * * @param channels * The number of channels included in the audio stream expected by RDP. * * @param bps * The size of each sample within the audio stream expected by RDP, in * bytes. */ void guac_rdp_audio_buffer_set_output(guac_rdp_audio_buffer* audio_buffer, int rate, int channels, int bps); /** * Begins handling of audio data received via guac_rdp_audio_buffer_write() and * allocates the necessary underlying packet buffer. Audio packets having * exactly packet_frames frames will be flushed as available using the provided * flush_handler. An audio frame is a set of single samples, one sample per * channel. The guac_rdp_audio_buffer_set_output() function MUST have * been invoked first. * * @param audio_buffer * The audio buffer to begin. * * @param packet_frames * The exact number of frames (a set of samples, one for each channel) * which MUST be included in all audio packets provided to the * given flush_handler. * * @param flush_handler * The function to invoke when an audio packet must be flushed. * * @param data * Arbitrary data to provide to the flush_handler when an audio packet * needs to be flushed. */ void guac_rdp_audio_buffer_begin(guac_rdp_audio_buffer* audio_buffer, int packet_frames, guac_rdp_audio_buffer_flush_handler* flush_handler, void* data); /** * Writes the given buffer of audio data to the given audio buffer. A new * packet will be flushed using the associated flush handler once sufficient * bytes have been accumulated. * * @param audio_buffer * The audio buffer to which the given audio data should be written. * * @param buffer * The buffer of audio data to write to the given audio buffer. * * @param length * The number of bytes to write. */ void guac_rdp_audio_buffer_write(guac_rdp_audio_buffer* audio_buffer, char* buffer, int length); /** * Stops handling of audio data received via guac_rdp_audio_buffer_write() and * frees the underlying packet buffer. Further audio data will be ignored until * guac_rdp_audio_buffer_begin() is invoked again. * * @param audio_buffer * The audio buffer to end. */ void guac_rdp_audio_buffer_end(guac_rdp_audio_buffer* audio_buffer); /** * Frees the given audio buffer. If guac_rdp_audio_buffer_end() has not yet * been called, its associated packet buffer will also be freed. * * @param audio_buffer * The audio buffer to free. */ void guac_rdp_audio_buffer_free(guac_rdp_audio_buffer* audio_buffer); #endif guacamole-server-1.3.0/src/protocols/rdp/channels/audio-input/audio-input.h0000644000175100001440000000327713764613616023760 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CHANNELS_AUDIO_INPUT_H #define GUAC_RDP_CHANNELS_AUDIO_INPUT_H #include #include /** * Handler for inbound audio data (audio input). */ guac_user_audio_handler guac_rdp_audio_handler; /** * Handler for stream data related to audio input. */ guac_user_blob_handler guac_rdp_audio_blob_handler; /** * Handler for end-of-stream related to audio input. */ guac_user_end_handler guac_rdp_audio_end_handler; /** * Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel * plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only * be loaded once the "drdynvc" plugin is loaded. The "guacai" plugin * ultimately adds support for the "AUDIO_INPUT" dynamic virtual channel. * * @param context * The rdpContext associated with the active RDP session. */ void guac_rdp_audio_load_plugin(rdpContext* context); #endif guacamole-server-1.3.0/src/protocols/rdp/channels/audio-input/audio-buffer.c0000644000175100001440000002540113764613616024056 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/audio-input/audio-buffer.h" #include "rdp.h" #include #include #include #include #include #include #include #include #include guac_rdp_audio_buffer* guac_rdp_audio_buffer_alloc() { guac_rdp_audio_buffer* buffer = calloc(1, sizeof(guac_rdp_audio_buffer)); pthread_mutex_init(&(buffer->lock), NULL); return buffer; } /** * Sends an "ack" instruction over the socket associated with the Guacamole * stream over which audio data is being received. The "ack" instruction will * only be sent if the Guacamole audio stream has been established (through * receipt of an "audio" instruction), is still open (has not received an "end" * instruction nor been associated with an "ack" having an error code), and is * associated with an active RDP AUDIO_INPUT channel. * * @param audio_buffer * The audio buffer associated with the guac_stream for which the "ack" * instruction should be sent, if any. If there is no associated * guac_stream, this function has no effect. * * @param message * An arbitrary human-readable message to send along with the "ack". * * @param status * The Guacamole protocol status code to send with the "ack". This should * be GUAC_PROTOCOL_STATUS_SUCCESS if the audio stream has been set up * successfully or GUAC_PROTOCOL_STATUS_RESOURCE_CLOSED if the audio stream * has been closed (but may usable again if reopened). */ static void guac_rdp_audio_buffer_ack(guac_rdp_audio_buffer* audio_buffer, const char* message, guac_protocol_status status) { guac_user* user = audio_buffer->user; guac_stream* stream = audio_buffer->stream; /* Do not send ack unless both sides of the audio stream are ready */ if (user == NULL || stream == NULL || audio_buffer->packet == NULL) return; /* Send ack instruction */ guac_protocol_send_ack(user->socket, stream, message, status); guac_socket_flush(user->socket); } void guac_rdp_audio_buffer_set_stream(guac_rdp_audio_buffer* audio_buffer, guac_user* user, guac_stream* stream, int rate, int channels, int bps) { pthread_mutex_lock(&(audio_buffer->lock)); /* Associate received stream */ audio_buffer->user = user; audio_buffer->stream = stream; audio_buffer->in_format.rate = rate; audio_buffer->in_format.channels = channels; audio_buffer->in_format.bps = bps; /* Acknowledge stream creation (if buffer is ready to receive) */ guac_rdp_audio_buffer_ack(audio_buffer, "OK", GUAC_PROTOCOL_STATUS_SUCCESS); guac_user_log(user, GUAC_LOG_DEBUG, "User is requesting to provide audio " "input as %i-channel, %i Hz PCM audio at %i bytes/sample.", audio_buffer->in_format.channels, audio_buffer->in_format.rate, audio_buffer->in_format.bps); pthread_mutex_unlock(&(audio_buffer->lock)); } void guac_rdp_audio_buffer_set_output(guac_rdp_audio_buffer* audio_buffer, int rate, int channels, int bps) { pthread_mutex_lock(&(audio_buffer->lock)); /* Set output format */ audio_buffer->out_format.rate = rate; audio_buffer->out_format.channels = channels; audio_buffer->out_format.bps = bps; pthread_mutex_unlock(&(audio_buffer->lock)); } void guac_rdp_audio_buffer_begin(guac_rdp_audio_buffer* audio_buffer, int packet_frames, guac_rdp_audio_buffer_flush_handler* flush_handler, void* data) { pthread_mutex_lock(&(audio_buffer->lock)); /* Reset buffer state to provided values */ audio_buffer->bytes_written = 0; audio_buffer->flush_handler = flush_handler; audio_buffer->data = data; /* Calculate size of each packet in bytes */ audio_buffer->packet_size = packet_frames * audio_buffer->out_format.channels * audio_buffer->out_format.bps; /* Allocate new buffer */ free(audio_buffer->packet); audio_buffer->packet = malloc(audio_buffer->packet_size); /* Acknowledge stream creation (if stream is ready to receive) */ guac_rdp_audio_buffer_ack(audio_buffer, "OK", GUAC_PROTOCOL_STATUS_SUCCESS); pthread_mutex_unlock(&(audio_buffer->lock)); } /** * Reads a single sample from the given buffer of data, using the input * format defined within the given audio buffer. Each read sample is * translated to a signed 16-bit value, even if the input format is 8-bit. * The offset into the given buffer will be determined according to the * input and output formats, the number of bytes sent thus far, and the * number of bytes received (excluding the contents of the buffer). * * @param audio_buffer * The audio buffer dictating the format of the given data buffer, as * well as the offset from which the sample should be read. * * @param buffer * The buffer of raw PCM audio data from which the sample should be read. * This buffer MUST NOT contain data already taken into account by the * audio buffer's total_bytes_received counter. * * @param length * The number of bytes within the given buffer of PCM data. * * @param sample * A pointer to the int16_t in which the read sample should be stored. If * the input format is 8-bit, the sample will be shifted left by 8 bits * to produce a 16-bit sample. * * @return * Non-zero if a sample was successfully read, zero if no data remains * within the given buffer that has not already been mapped to an * output sample. */ static int guac_rdp_audio_buffer_read_sample( guac_rdp_audio_buffer* audio_buffer, const char* buffer, int length, int16_t* sample) { int in_bps = audio_buffer->in_format.bps; int in_rate = audio_buffer->in_format.rate; int in_channels = audio_buffer->in_format.channels; int out_bps = audio_buffer->out_format.bps; int out_rate = audio_buffer->out_format.rate; int out_channels = audio_buffer->out_format.channels; /* Calculate position within audio output */ int current_sample = audio_buffer->total_bytes_sent / out_bps; int current_frame = current_sample / out_channels; int current_channel = current_sample % out_channels; /* Map output channel to input channel */ if (current_channel >= in_channels) current_channel = in_channels - 1; /* Transform output position to input position */ current_frame = (int) current_frame * ((double) in_rate / out_rate); current_sample = current_frame * in_channels + current_channel; /* Calculate offset within given buffer from absolute input position */ int offset = current_sample * in_bps - audio_buffer->total_bytes_received; /* It should be impossible for the offset to ever go negative */ assert(offset >= 0); /* Apply offset to buffer */ buffer += offset; length -= offset; /* Read only if sufficient data is present in the given buffer */ if (length < in_bps) return 0; /* Simply read sample directly if input is 16-bit */ if (in_bps == 2) { *sample = *((int16_t*) buffer); return 1; } /* Translate to 16-bit if input is 8-bit */ if (in_bps == 1) { *sample = *buffer << 8; return 1; } /* Accepted audio formats are required to be 8- or 16-bit */ return 0; } void guac_rdp_audio_buffer_write(guac_rdp_audio_buffer* audio_buffer, char* buffer, int length) { int16_t sample; pthread_mutex_lock(&(audio_buffer->lock)); /* Ignore packet if there is no buffer */ if (audio_buffer->packet_size == 0 || audio_buffer->packet == NULL) { pthread_mutex_unlock(&(audio_buffer->lock)); return; } int out_bps = audio_buffer->out_format.bps; /* Continuously write packets until no data remains */ while (guac_rdp_audio_buffer_read_sample(audio_buffer, buffer, length, &sample) > 0) { char* current = audio_buffer->packet + audio_buffer->bytes_written; /* Store as 16-bit or 8-bit, depending on output format */ if (out_bps == 2) *((int16_t*) current) = sample; else if (out_bps == 1) *current = sample >> 8; /* Accepted audio formats are required to be 8- or 16-bit */ else assert(0); /* Update byte counters */ audio_buffer->bytes_written += out_bps; audio_buffer->total_bytes_sent += out_bps; /* Invoke flush handler if full */ if (audio_buffer->bytes_written == audio_buffer->packet_size) { /* Only actually invoke if defined */ if (audio_buffer->flush_handler) audio_buffer->flush_handler(audio_buffer->packet, audio_buffer->bytes_written, audio_buffer->data); /* Reset buffer in all cases */ audio_buffer->bytes_written = 0; } } /* end packet write loop */ /* Track current position in audio stream */ audio_buffer->total_bytes_received += length; pthread_mutex_unlock(&(audio_buffer->lock)); } void guac_rdp_audio_buffer_end(guac_rdp_audio_buffer* audio_buffer) { pthread_mutex_lock(&(audio_buffer->lock)); /* The stream is now closed */ guac_rdp_audio_buffer_ack(audio_buffer, "CLOSED", GUAC_PROTOCOL_STATUS_RESOURCE_CLOSED); /* Unset user and stream */ audio_buffer->user = NULL; audio_buffer->stream = NULL; /* Reset buffer state */ audio_buffer->bytes_written = 0; audio_buffer->packet_size = 0; audio_buffer->flush_handler = NULL; /* Reset I/O counters */ audio_buffer->total_bytes_sent = 0; audio_buffer->total_bytes_received = 0; /* Free packet (if any) */ free(audio_buffer->packet); audio_buffer->packet = NULL; pthread_mutex_unlock(&(audio_buffer->lock)); } void guac_rdp_audio_buffer_free(guac_rdp_audio_buffer* audio_buffer) { pthread_mutex_destroy(&(audio_buffer->lock)); free(audio_buffer->packet); free(audio_buffer); } guacamole-server-1.3.0/src/protocols/rdp/argv.h0000644000175100001440000000316013770536337016420 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_ARGV_H #define GUAC_RDP_ARGV_H #include "config.h" #include #include /** * Handles a received argument value from a Guacamole "argv" instruction, * updating the given connection parameter. */ guac_argv_callback guac_rdp_argv_callback; /** * The name of the parameter that specifies/updates the username that will be * sent to the RDP server during authentication. */ #define GUAC_RDP_ARGV_USERNAME "username" /** * The name of the parameter that specifies/updates the password that will be * sent to the RDP server during authentication. */ #define GUAC_RDP_ARGV_PASSWORD "password" /** * The name of the parameter that specifies/updates the domain name that will be * sent to the RDP server during authentication. */ #define GUAC_RDP_ARGV_DOMAIN "domain" #endif guacamole-server-1.3.0/src/protocols/rdp/user.c0000644000175100001440000001271513770536337016440 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/audio-input/audio-input.h" #include "channels/cliprdr.h" #include "channels/pipe-svc.h" #include "common/cursor.h" #include "common/display.h" #include "config.h" #include "input.h" #include "rdp.h" #include "settings.h" #include "upload.h" #include "user.h" #ifdef ENABLE_COMMON_SSH #include "sftp.h" #endif #include #include #include #include #include #include #include #include #include int guac_rdp_user_join_handler(guac_user* user, int argc, char** argv) { guac_rdp_client* rdp_client = (guac_rdp_client*) user->client->data; /* Parse provided arguments */ guac_rdp_settings* settings = guac_rdp_parse_args(user, argc, (const char**) argv); /* Fail if settings cannot be parsed */ if (settings == NULL) { guac_user_log(user, GUAC_LOG_INFO, "Badly formatted client arguments."); return 1; } /* Store settings at user level */ user->data = settings; /* Connect via RDP if owner */ if (user->owner) { /* Store owner's settings at client level */ rdp_client->settings = settings; /* Start client thread */ if (pthread_create(&rdp_client->client_thread, NULL, guac_rdp_client_thread, user->client)) { guac_user_log(user, GUAC_LOG_ERROR, "Unable to start RDP client thread."); return 1; } /* Handle inbound audio streams if audio input is enabled */ if (settings->enable_audio_input) user->audio_handler = guac_rdp_audio_handler; } /* If not owner, synchronize with current state */ else { /* Synchronize any audio stream */ if (rdp_client->audio) guac_audio_stream_add_user(rdp_client->audio, user); /* Bring user up to date with any registered static channels */ guac_rdp_pipe_svc_send_pipes(user); /* Synchronize with current display */ guac_common_display_dup(rdp_client->display, user, user->socket); guac_socket_flush(user->socket); } /* Only handle events if not read-only */ if (!settings->read_only) { /* General mouse/keyboard events */ user->mouse_handler = guac_rdp_user_mouse_handler; user->key_handler = guac_rdp_user_key_handler; /* Inbound (client to server) clipboard transfer */ if (!settings->disable_paste) user->clipboard_handler = guac_rdp_clipboard_handler; /* Display size change events */ user->size_handler = guac_rdp_user_size_handler; /* Set generic (non-filesystem) file upload handler */ user->file_handler = guac_rdp_user_file_handler; /* Inbound arbitrary named pipes */ user->pipe_handler = guac_rdp_pipe_svc_pipe_handler; /* If we own it, register handler for updating parameters during connection. */ if (user->owner) user->argv_handler = guac_argv_handler; } return 0; } int guac_rdp_user_file_handler(guac_user* user, guac_stream* stream, char* mimetype, char* filename) { guac_rdp_client* rdp_client = (guac_rdp_client*) user->client->data; guac_rdp_settings* settings = rdp_client->settings; #ifdef ENABLE_COMMON_SSH /* If SFTP is enabled and SFTP uploads have not been disabled, it should be * used for default uploads only if RDPDR is not enabled or its upload * directory has been set */ if (rdp_client->sftp_filesystem != NULL && !settings->sftp_disable_upload) { if (!settings->drive_enabled || settings->sftp_directory != NULL) return guac_rdp_sftp_file_handler(user, stream, mimetype, filename); } #endif /* Default to using RDPDR uploads (if enabled) */ if (rdp_client->filesystem != NULL && !settings->disable_upload) return guac_rdp_upload_file_handler(user, stream, mimetype, filename); /* File transfer not enabled */ guac_protocol_send_ack(user->socket, stream, "File transfer disabled", GUAC_PROTOCOL_STATUS_UNSUPPORTED); guac_socket_flush(user->socket); return 0; } int guac_rdp_user_leave_handler(guac_user* user) { guac_rdp_client* rdp_client = (guac_rdp_client*) user->client->data; /* Update shared cursor state */ guac_common_cursor_remove_user(rdp_client->display->cursor, user); /* Free settings if not owner (owner settings will be freed with client) */ if (!user->owner) { guac_rdp_settings* settings = (guac_rdp_settings*) user->data; guac_rdp_settings_free(settings); } return 0; } guacamole-server-1.3.0/src/protocols/rdp/resolution.c0000644000175100001440000000365313613156714017657 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "client.h" #include "resolution.h" #include int guac_rdp_resolution_reasonable(guac_user* user, int resolution) { int width = user->info.optimal_width; int height = user->info.optimal_height; /* Convert user pixels to remote pixels */ width = width * resolution / user->info.optimal_resolution; height = height * resolution / user->info.optimal_resolution; /* * Resolution is reasonable if the same as the user optimal resolution * OR if the resulting display area is reasonable */ return user->info.optimal_resolution == resolution || width*height >= GUAC_RDP_REASONABLE_AREA; } int guac_rdp_suggest_resolution(guac_user* user) { /* Prefer RDP's native resolution */ if (guac_rdp_resolution_reasonable(user, GUAC_RDP_NATIVE_RESOLUTION)) return GUAC_RDP_NATIVE_RESOLUTION; /* If native resolution is too tiny, try higher resolution */ if (guac_rdp_resolution_reasonable(user, GUAC_RDP_HIGH_RESOLUTION)) return GUAC_RDP_HIGH_RESOLUTION; /* Fallback to user-suggested resolution */ return user->info.optimal_resolution; } guacamole-server-1.3.0/src/protocols/rdp/keymap.h0000644000175100001440000001237213764613616016753 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_KEYMAP_H #define GUAC_RDP_KEYMAP_H #include /** * The X11 keysym for Num Lock. */ #define GUAC_RDP_KEYSYM_NUM_LOCK 0xFF7F /** * The X11 keysym for Scroll Lock. */ #define GUAC_RDP_KEYSYM_SCROLL_LOCK 0xFF14 /** * The X11 keysym for Caps Lock. */ #define GUAC_RDP_KEYSYM_CAPS_LOCK 0xFFE5 /** * The X11 keysym for Kana Lock. */ #define GUAC_RDP_KEYSYM_KANA_LOCK 0xFF2D /** * The X11 keysym for Left Shift. */ #define GUAC_RDP_KEYSYM_LSHIFT 0xFFE1 /** * The X11 keysym for Right Shift. */ #define GUAC_RDP_KEYSYM_RSHIFT 0xFFE2 /** * The X11 keysym for Left Ctrl. */ #define GUAC_RDP_KEYSYM_LCTRL 0xFFE3 /** * The X11 keysym for Right Ctrl. */ #define GUAC_RDP_KEYSYM_RCTRL 0xFFE4 /** * The X11 keysym for Left Alt. */ #define GUAC_RDP_KEYSYM_LALT 0xFFE9 /** * The X11 keysym for Right Alt. */ #define GUAC_RDP_KEYSYM_RALT 0xFFEA /** * The X11 keysym for AltGr. */ #define GUAC_RDP_KEYSYM_ALTGR 0xFE03 /** * Bitwise flag value representing the Shift modifier. */ #define GUAC_RDP_KEYMAP_MODIFIER_SHIFT 1 /** * Bitwise flag value representing the AltGr modifier. */ #define GUAC_RDP_KEYMAP_MODIFIER_ALTGR 2 /** * Represents a keysym-to-scancode mapping for RDP, with extra information * about the state of prerequisite keysyms. */ typedef struct guac_rdp_keysym_desc { /** * The keysym being mapped. */ int keysym; /** * The scancode this keysym maps to. */ int scancode; /** * Required RDP-specific flags that must be sent along with the scancode. */ int flags; /** * Bitwise-OR of the flags of any modifiers that must be active for the * associated scancode to be interpreted as this keysym. * * If the associated keysym is pressed, and any of these modifiers are not * currently active, Guacamole's RDP support must send additional events to * activate these modifiers prior to sending the scancode for this keysym. * * @see GUAC_RDP_KEYMAP_MODIFIER_SHIFT * @see GUAC_RDP_KEYMAP_MODIFIER_ALTGR */ const unsigned int set_modifiers; /** * Bitwise-OR of the flags of any modifiers that must NOT be active for the * associated scancode to be interpreted as this keysym. * * If the associated keysym is pressed, and any of these modifiers are * currently active, Guacamole's RDP support must send additional events to * deactivate these modifiers prior to sending the scancode for this * keysym. * * @see GUAC_RDP_KEYMAP_MODIFIER_SHIFT * @see GUAC_RDP_KEYMAP_MODIFIER_ALTGR */ const unsigned int clear_modifiers; /** * Bitwise OR of the flags of all lock keys (ie: Caps lock, Num lock, etc.) * which must be active for this keysym to be properly typed. Legal flags * are KBD_SYNC_SCROLL_LOCK, KBD_SYNC_NUM_LOCK, KBD_SYNC_CAPS_LOCK, and * KBD_SYNC_KANA_LOCK. */ const unsigned int set_locks; /** * Bitwise OR of the flags of all lock keys (ie: Caps lock, Num lock, etc.) * which must be inactive for this keysym to be properly typed. Legal flags * are KBD_SYNC_SCROLL_LOCK, KBD_SYNC_NUM_LOCK, KBD_SYNC_CAPS_LOCK, and * KBD_SYNC_KANA_LOCK. */ const unsigned int clear_locks; } guac_rdp_keysym_desc; /** * Hierarchical keysym mapping */ typedef struct guac_rdp_keymap guac_rdp_keymap; struct guac_rdp_keymap { /** * The parent mapping this map will inherit its initial mapping from. * Any other mapping information will add to or override the mapping * inherited from the parent. */ const guac_rdp_keymap* parent; /** * Descriptive name of this keymap */ const char* name; /** * Null-terminated array of scancode mappings. */ const guac_rdp_keysym_desc* mapping; /** * FreeRDP keyboard layout associated with this * keymap. If this keymap is selected, this layout * will be requested from the server. */ const UINT32 freerdp_keyboard_layout; }; /** * The name of the default keymap, which MUST exist. */ #define GUAC_DEFAULT_KEYMAP "en-us-qwerty" /** * NULL-terminated array of all keymaps. */ extern const guac_rdp_keymap* GUAC_KEYMAPS[]; /** * Return the keymap having the given name, if any, or NULL otherwise. * * @param name * The name of the keymap to find. * * @return * The keymap having the given name, or NULL if no such keymap exists. */ const guac_rdp_keymap* guac_rdp_keymap_find(const char* name); #endif guacamole-server-1.3.0/src/protocols/rdp/input.c0000644000175100001440000001242513764613616016616 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "channels/disp.h" #include "common/cursor.h" #include "common/display.h" #include "common/recording.h" #include "input.h" #include "keyboard.h" #include "rdp.h" #include "settings.h" #include #include #include #include #include int guac_rdp_user_mouse_handler(guac_user* user, int x, int y, int mask) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; pthread_rwlock_rdlock(&(rdp_client->lock)); /* Skip if not yet connected */ freerdp* rdp_inst = rdp_client->rdp_inst; if (rdp_inst == NULL) goto complete; /* Store current mouse location/state */ guac_common_cursor_update(rdp_client->display->cursor, user, x, y, mask); /* Report mouse position within recording */ if (rdp_client->recording != NULL) guac_common_recording_report_mouse(rdp_client->recording, x, y, mask); /* If button mask unchanged, just send move event */ if (mask == rdp_client->mouse_button_mask) rdp_inst->input->MouseEvent(rdp_inst->input, PTR_FLAGS_MOVE, x, y); /* Otherwise, send events describing button change */ else { /* Mouse buttons which have JUST become released */ int released_mask = rdp_client->mouse_button_mask & ~mask; /* Mouse buttons which have JUST become pressed */ int pressed_mask = ~rdp_client->mouse_button_mask & mask; /* Release event */ if (released_mask & 0x07) { /* Calculate flags */ int flags = 0; if (released_mask & 0x01) flags |= PTR_FLAGS_BUTTON1; if (released_mask & 0x02) flags |= PTR_FLAGS_BUTTON3; if (released_mask & 0x04) flags |= PTR_FLAGS_BUTTON2; rdp_inst->input->MouseEvent(rdp_inst->input, flags, x, y); } /* Press event */ if (pressed_mask & 0x07) { /* Calculate flags */ int flags = PTR_FLAGS_DOWN; if (pressed_mask & 0x01) flags |= PTR_FLAGS_BUTTON1; if (pressed_mask & 0x02) flags |= PTR_FLAGS_BUTTON3; if (pressed_mask & 0x04) flags |= PTR_FLAGS_BUTTON2; if (pressed_mask & 0x08) flags |= PTR_FLAGS_WHEEL | 0x78; if (pressed_mask & 0x10) flags |= PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x88; /* Send event */ rdp_inst->input->MouseEvent(rdp_inst->input, flags, x, y); } /* Scroll event */ if (pressed_mask & 0x18) { /* Down */ if (pressed_mask & 0x08) rdp_inst->input->MouseEvent( rdp_inst->input, PTR_FLAGS_WHEEL | 0x78, x, y); /* Up */ if (pressed_mask & 0x10) rdp_inst->input->MouseEvent( rdp_inst->input, PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x88, x, y); } rdp_client->mouse_button_mask = mask; } complete: pthread_rwlock_unlock(&(rdp_client->lock)); return 0; } int guac_rdp_user_key_handler(guac_user* user, int keysym, int pressed) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; int retval = 0; pthread_rwlock_rdlock(&(rdp_client->lock)); /* Report key state within recording */ if (rdp_client->recording != NULL) guac_common_recording_report_key(rdp_client->recording, keysym, pressed); /* Skip if keyboard not yet ready */ if (rdp_client->keyboard == NULL) goto complete; /* Update keysym state */ retval = guac_rdp_keyboard_update_keysym(rdp_client->keyboard, keysym, pressed, GUAC_RDP_KEY_SOURCE_CLIENT); complete: pthread_rwlock_unlock(&(rdp_client->lock)); return retval; } int guac_rdp_user_size_handler(guac_user* user, int width, int height) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; freerdp* rdp_inst = rdp_client->rdp_inst; /* Convert client pixels to remote pixels */ width = width * settings->resolution / user->info.optimal_resolution; height = height * settings->resolution / user->info.optimal_resolution; /* Send display update */ guac_rdp_disp_set_size(rdp_client->disp, settings, rdp_inst, width, height); return 0; } guacamole-server-1.3.0/src/protocols/rdp/Makefile.in0000644000175100001440000036747413772471102017370 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ # # Optional SFTP support # @ENABLE_COMMON_SSH_TRUE@am__append_1 = sftp.c @ENABLE_COMMON_SSH_TRUE@am__append_2 = sftp.h @ENABLE_COMMON_SSH_TRUE@am__append_3 = @COMMON_SSH_LTLIB@ subdir = src/protocols/rdp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__noinst_HEADERS_DIST) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(freerdpdir)" "$(DESTDIR)$(libdir)" LTLIBRARIES = $(freerdp_LTLIBRARIES) $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libguac_client_rdp_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am__libguac_client_rdp_la_SOURCES_DIST = argv.c beep.c bitmap.c \ channels/audio-input/audio-buffer.c \ channels/audio-input/audio-input.c channels/cliprdr.c \ channels/common-svc.c channels/disp.c channels/pipe-svc.c \ channels/rail.c channels/rdpdr/rdpdr-fs-messages-dir-info.c \ channels/rdpdr/rdpdr-fs-messages-file-info.c \ channels/rdpdr/rdpdr-fs-messages-vol-info.c \ channels/rdpdr/rdpdr-fs-messages.c channels/rdpdr/rdpdr-fs.c \ channels/rdpdr/rdpdr-messages.c channels/rdpdr/rdpdr-printer.c \ channels/rdpdr/rdpdr.c channels/rdpsnd/rdpsnd-messages.c \ channels/rdpsnd/rdpsnd.c client.c color.c decompose.c \ download.c error.c fs.c gdi.c glyph.c input.c keyboard.c \ keymap.c log.c ls.c plugins/channels.c plugins/ptr-string.c \ pointer.c print-job.c rdp.c resolution.c settings.c unicode.c \ upload.c user.c sftp.c am__dirstamp = $(am__leading_dot)dirstamp @ENABLE_COMMON_SSH_TRUE@am__objects_1 = libguac_client_rdp_la-sftp.lo am_libguac_client_rdp_la_OBJECTS = libguac_client_rdp_la-argv.lo \ libguac_client_rdp_la-beep.lo libguac_client_rdp_la-bitmap.lo \ channels/audio-input/libguac_client_rdp_la-audio-buffer.lo \ channels/audio-input/libguac_client_rdp_la-audio-input.lo \ channels/libguac_client_rdp_la-cliprdr.lo \ channels/libguac_client_rdp_la-common-svc.lo \ channels/libguac_client_rdp_la-disp.lo \ channels/libguac_client_rdp_la-pipe-svc.lo \ channels/libguac_client_rdp_la-rail.lo \ channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.lo \ channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-file-info.lo \ channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.lo \ channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages.lo \ channels/rdpdr/libguac_client_rdp_la-rdpdr-fs.lo \ channels/rdpdr/libguac_client_rdp_la-rdpdr-messages.lo \ channels/rdpdr/libguac_client_rdp_la-rdpdr-printer.lo \ channels/rdpdr/libguac_client_rdp_la-rdpdr.lo \ channels/rdpsnd/libguac_client_rdp_la-rdpsnd-messages.lo \ channels/rdpsnd/libguac_client_rdp_la-rdpsnd.lo \ libguac_client_rdp_la-client.lo libguac_client_rdp_la-color.lo \ libguac_client_rdp_la-decompose.lo \ libguac_client_rdp_la-download.lo \ libguac_client_rdp_la-error.lo libguac_client_rdp_la-fs.lo \ libguac_client_rdp_la-gdi.lo libguac_client_rdp_la-glyph.lo \ libguac_client_rdp_la-input.lo \ libguac_client_rdp_la-keyboard.lo \ libguac_client_rdp_la-keymap.lo libguac_client_rdp_la-log.lo \ libguac_client_rdp_la-ls.lo \ plugins/libguac_client_rdp_la-channels.lo \ plugins/libguac_client_rdp_la-ptr-string.lo \ libguac_client_rdp_la-pointer.lo \ libguac_client_rdp_la-print-job.lo \ libguac_client_rdp_la-rdp.lo \ libguac_client_rdp_la-resolution.lo \ libguac_client_rdp_la-settings.lo \ libguac_client_rdp_la-unicode.lo \ libguac_client_rdp_la-upload.lo libguac_client_rdp_la-user.lo \ $(am__objects_1) nodist_libguac_client_rdp_la_OBJECTS = \ libguac_client_rdp_la-_generated_channel_entry_wrappers.lo \ libguac_client_rdp_la-_generated_keymaps.lo libguac_client_rdp_la_OBJECTS = $(am_libguac_client_rdp_la_OBJECTS) \ $(nodist_libguac_client_rdp_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libguac_client_rdp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) \ $(libguac_client_rdp_la_LDFLAGS) $(LDFLAGS) -o $@ libguac_common_svc_client_la_DEPENDENCIES = am_libguac_common_svc_client_la_OBJECTS = plugins/guac-common-svc/libguac_common_svc_client_la-guac-common-svc.lo libguac_common_svc_client_la_OBJECTS = \ $(am_libguac_common_svc_client_la_OBJECTS) libguac_common_svc_client_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libguac_common_svc_client_la_CFLAGS) $(CFLAGS) \ $(libguac_common_svc_client_la_LDFLAGS) $(LDFLAGS) -o $@ libguacai_client_la_DEPENDENCIES = am_libguacai_client_la_OBJECTS = \ channels/audio-input/libguacai_client_la-audio-buffer.lo \ plugins/guacai/libguacai_client_la-guacai-messages.lo \ plugins/guacai/libguacai_client_la-guacai.lo \ plugins/libguacai_client_la-ptr-string.lo libguacai_client_la_OBJECTS = $(am_libguacai_client_la_OBJECTS) libguacai_client_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libguacai_client_la_CFLAGS) $(CFLAGS) \ $(libguacai_client_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libguac_client_rdp_la-_generated_channel_entry_wrappers.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-_generated_keymaps.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-argv.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-beep.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-bitmap.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-client.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-color.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-decompose.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-download.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-error.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-fs.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-gdi.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-glyph.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-input.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-keyboard.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-keymap.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-log.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-ls.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-pointer.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-print-job.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-rdp.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-resolution.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-settings.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-sftp.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-unicode.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-upload.Plo \ ./$(DEPDIR)/libguac_client_rdp_la-user.Plo \ channels/$(DEPDIR)/libguac_client_rdp_la-cliprdr.Plo \ channels/$(DEPDIR)/libguac_client_rdp_la-common-svc.Plo \ channels/$(DEPDIR)/libguac_client_rdp_la-disp.Plo \ channels/$(DEPDIR)/libguac_client_rdp_la-pipe-svc.Plo \ channels/$(DEPDIR)/libguac_client_rdp_la-rail.Plo \ channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-buffer.Plo \ channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-input.Plo \ channels/audio-input/$(DEPDIR)/libguacai_client_la-audio-buffer.Plo \ channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.Plo \ channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-file-info.Plo \ channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.Plo \ channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages.Plo \ channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs.Plo \ channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-messages.Plo \ channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-printer.Plo \ channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr.Plo \ channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd-messages.Plo \ channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd.Plo \ plugins/$(DEPDIR)/libguac_client_rdp_la-channels.Plo \ plugins/$(DEPDIR)/libguac_client_rdp_la-ptr-string.Plo \ plugins/$(DEPDIR)/libguacai_client_la-ptr-string.Plo \ plugins/guac-common-svc/$(DEPDIR)/libguac_common_svc_client_la-guac-common-svc.Plo \ plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai-messages.Plo \ plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libguac_client_rdp_la_SOURCES) \ $(nodist_libguac_client_rdp_la_SOURCES) \ $(libguac_common_svc_client_la_SOURCES) \ $(libguacai_client_la_SOURCES) DIST_SOURCES = $(am__libguac_client_rdp_la_SOURCES_DIST) \ $(libguac_common_svc_client_la_SOURCES) \ $(libguacai_client_la_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__noinst_HEADERS_DIST = argv.h beep.h bitmap.h \ channels/audio-input/audio-buffer.h \ channels/audio-input/audio-input.h channels/cliprdr.h \ channels/common-svc.h channels/disp.h channels/pipe-svc.h \ channels/rail.h channels/rdpdr/rdpdr-fs-messages-dir-info.h \ channels/rdpdr/rdpdr-fs-messages-file-info.h \ channels/rdpdr/rdpdr-fs-messages-vol-info.h \ channels/rdpdr/rdpdr-fs-messages.h channels/rdpdr/rdpdr-fs.h \ channels/rdpdr/rdpdr-messages.h channels/rdpdr/rdpdr-printer.h \ channels/rdpdr/rdpdr.h channels/rdpsnd/rdpsnd-messages.h \ channels/rdpsnd/rdpsnd.h client.h color.h decompose.h \ download.h error.h fs.h gdi.h glyph.h input.h keyboard.h \ keymap.h log.h ls.h plugins/channels.h \ plugins/guacai/guacai-messages.h plugins/guacai/guacai.h \ plugins/ptr-string.h pointer.h print-job.h rdp.h resolution.h \ settings.h unicode.h upload.h user.h sftp.h HEADERS = $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir distdir-am am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac-client-rdp.la SUBDIRS = . tests # # Main RDP client library # nodist_libguac_client_rdp_la_SOURCES = \ _generated_channel_entry_wrappers.c \ _generated_keymaps.c libguac_client_rdp_la_SOURCES = argv.c beep.c bitmap.c \ channels/audio-input/audio-buffer.c \ channels/audio-input/audio-input.c channels/cliprdr.c \ channels/common-svc.c channels/disp.c channels/pipe-svc.c \ channels/rail.c channels/rdpdr/rdpdr-fs-messages-dir-info.c \ channels/rdpdr/rdpdr-fs-messages-file-info.c \ channels/rdpdr/rdpdr-fs-messages-vol-info.c \ channels/rdpdr/rdpdr-fs-messages.c channels/rdpdr/rdpdr-fs.c \ channels/rdpdr/rdpdr-messages.c channels/rdpdr/rdpdr-printer.c \ channels/rdpdr/rdpdr.c channels/rdpsnd/rdpsnd-messages.c \ channels/rdpsnd/rdpsnd.c client.c color.c decompose.c \ download.c error.c fs.c gdi.c glyph.c input.c keyboard.c \ keymap.c log.c ls.c plugins/channels.c plugins/ptr-string.c \ pointer.c print-job.c rdp.c resolution.c settings.c unicode.c \ upload.c user.c $(am__append_1) noinst_HEADERS = argv.h beep.h bitmap.h \ channels/audio-input/audio-buffer.h \ channels/audio-input/audio-input.h channels/cliprdr.h \ channels/common-svc.h channels/disp.h channels/pipe-svc.h \ channels/rail.h channels/rdpdr/rdpdr-fs-messages-dir-info.h \ channels/rdpdr/rdpdr-fs-messages-file-info.h \ channels/rdpdr/rdpdr-fs-messages-vol-info.h \ channels/rdpdr/rdpdr-fs-messages.h channels/rdpdr/rdpdr-fs.h \ channels/rdpdr/rdpdr-messages.h channels/rdpdr/rdpdr-printer.h \ channels/rdpdr/rdpdr.h channels/rdpsnd/rdpsnd-messages.h \ channels/rdpsnd/rdpsnd.h client.h color.h decompose.h \ download.h error.h fs.h gdi.h glyph.h input.h keyboard.h \ keymap.h log.h ls.h plugins/channels.h \ plugins/guacai/guacai-messages.h plugins/guacai/guacai.h \ plugins/ptr-string.h pointer.h print-job.h rdp.h resolution.h \ settings.h unicode.h upload.h user.h $(am__append_2) libguac_client_rdp_la_CFLAGS = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ \ @RDP_CFLAGS@ libguac_client_rdp_la_LDFLAGS = \ -version-info 0:0:0 \ @CAIRO_LIBS@ \ @PTHREAD_LIBS@ \ @RDP_LIBS@ libguac_client_rdp_la_LIBADD = @COMMON_LTLIB@ @LIBGUAC_LTLIB@ \ $(am__append_3) # # Plugins for FreeRDP # freerdp_LTLIBRARIES = \ libguac-common-svc-client.la \ libguacai-client.la freerdpdir = @FREERDP2_PLUGIN_DIR@ # # Common SVC plugin (shared by RDPDR, RDPSND, etc.) # libguac_common_svc_client_la_SOURCES = \ plugins/guac-common-svc/guac-common-svc.c libguac_common_svc_client_la_CFLAGS = \ -Werror -Wall -Iinclude \ @LIBGUAC_INCLUDE@ \ @RDP_CFLAGS@ libguac_common_svc_client_la_LDFLAGS = \ -module -avoid-version -shared \ @RDP_LIBS@ libguac_common_svc_client_la_LIBADD = \ @LIBGUAC_LTLIB@ # # Audio Input # libguacai_client_la_SOURCES = \ channels/audio-input/audio-buffer.c \ plugins/guacai/guacai-messages.c \ plugins/guacai/guacai.c \ plugins/ptr-string.c libguacai_client_la_CFLAGS = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ \ @RDP_CFLAGS@ libguacai_client_la_LDFLAGS = \ -module -avoid-version -shared \ @PTHREAD_LIBS@ \ @RDP_LIBS@ libguacai_client_la_LIBADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ # # Autogenerated keymaps and channel wrapper functions # CLEANFILES = \ _generated_channel_entry_wrappers.c \ _generated_keymaps.c BUILT_SOURCES = \ _generated_channel_entry_wrappers.c \ _generated_keymaps.c rdp_keymaps = \ $(srcdir)/keymaps/base.keymap \ $(srcdir)/keymaps/failsafe.keymap \ $(srcdir)/keymaps/de_de_qwertz.keymap \ $(srcdir)/keymaps/de_ch_qwertz.keymap \ $(srcdir)/keymaps/en_gb_qwerty.keymap \ $(srcdir)/keymaps/en_us_qwerty.keymap \ $(srcdir)/keymaps/es_es_qwerty.keymap \ $(srcdir)/keymaps/es_latam_qwerty.keymap \ $(srcdir)/keymaps/fr_be_azerty.keymap \ $(srcdir)/keymaps/fr_ch_qwertz.keymap \ $(srcdir)/keymaps/fr_fr_azerty.keymap \ $(srcdir)/keymaps/hu_hu_qwertz.keymap \ $(srcdir)/keymaps/it_it_qwerty.keymap \ $(srcdir)/keymaps/ja_jp_qwerty.keymap \ $(srcdir)/keymaps/pt_br_qwerty.keymap \ $(srcdir)/keymaps/sv_se_qwerty.keymap \ $(srcdir)/keymaps/da_dk_qwerty.keymap \ $(srcdir)/keymaps/tr_tr_qwerty.keymap EXTRA_DIST = \ $(rdp_keymaps) \ keymaps/generate.pl \ plugins/generate-entry-wrappers.pl all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/protocols/rdp/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/protocols/rdp/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-freerdpLTLIBRARIES: $(freerdp_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(freerdp_LTLIBRARIES)'; test -n "$(freerdpdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(freerdpdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(freerdpdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(freerdpdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(freerdpdir)"; \ } uninstall-freerdpLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(freerdp_LTLIBRARIES)'; test -n "$(freerdpdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(freerdpdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(freerdpdir)/$$f"; \ done clean-freerdpLTLIBRARIES: -test -z "$(freerdp_LTLIBRARIES)" || rm -f $(freerdp_LTLIBRARIES) @list='$(freerdp_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } channels/audio-input/$(am__dirstamp): @$(MKDIR_P) channels/audio-input @: > channels/audio-input/$(am__dirstamp) channels/audio-input/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) channels/audio-input/$(DEPDIR) @: > channels/audio-input/$(DEPDIR)/$(am__dirstamp) channels/audio-input/libguac_client_rdp_la-audio-buffer.lo: \ channels/audio-input/$(am__dirstamp) \ channels/audio-input/$(DEPDIR)/$(am__dirstamp) channels/audio-input/libguac_client_rdp_la-audio-input.lo: \ channels/audio-input/$(am__dirstamp) \ channels/audio-input/$(DEPDIR)/$(am__dirstamp) channels/$(am__dirstamp): @$(MKDIR_P) channels @: > channels/$(am__dirstamp) channels/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) channels/$(DEPDIR) @: > channels/$(DEPDIR)/$(am__dirstamp) channels/libguac_client_rdp_la-cliprdr.lo: channels/$(am__dirstamp) \ channels/$(DEPDIR)/$(am__dirstamp) channels/libguac_client_rdp_la-common-svc.lo: \ channels/$(am__dirstamp) channels/$(DEPDIR)/$(am__dirstamp) channels/libguac_client_rdp_la-disp.lo: channels/$(am__dirstamp) \ channels/$(DEPDIR)/$(am__dirstamp) channels/libguac_client_rdp_la-pipe-svc.lo: channels/$(am__dirstamp) \ channels/$(DEPDIR)/$(am__dirstamp) channels/libguac_client_rdp_la-rail.lo: channels/$(am__dirstamp) \ channels/$(DEPDIR)/$(am__dirstamp) channels/rdpdr/$(am__dirstamp): @$(MKDIR_P) channels/rdpdr @: > channels/rdpdr/$(am__dirstamp) channels/rdpdr/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) channels/rdpdr/$(DEPDIR) @: > channels/rdpdr/$(DEPDIR)/$(am__dirstamp) channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.lo: \ channels/rdpdr/$(am__dirstamp) \ channels/rdpdr/$(DEPDIR)/$(am__dirstamp) channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-file-info.lo: \ channels/rdpdr/$(am__dirstamp) \ channels/rdpdr/$(DEPDIR)/$(am__dirstamp) channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.lo: \ channels/rdpdr/$(am__dirstamp) \ channels/rdpdr/$(DEPDIR)/$(am__dirstamp) channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages.lo: \ channels/rdpdr/$(am__dirstamp) \ channels/rdpdr/$(DEPDIR)/$(am__dirstamp) channels/rdpdr/libguac_client_rdp_la-rdpdr-fs.lo: \ channels/rdpdr/$(am__dirstamp) \ channels/rdpdr/$(DEPDIR)/$(am__dirstamp) channels/rdpdr/libguac_client_rdp_la-rdpdr-messages.lo: \ channels/rdpdr/$(am__dirstamp) \ channels/rdpdr/$(DEPDIR)/$(am__dirstamp) channels/rdpdr/libguac_client_rdp_la-rdpdr-printer.lo: \ channels/rdpdr/$(am__dirstamp) \ channels/rdpdr/$(DEPDIR)/$(am__dirstamp) channels/rdpdr/libguac_client_rdp_la-rdpdr.lo: \ channels/rdpdr/$(am__dirstamp) \ channels/rdpdr/$(DEPDIR)/$(am__dirstamp) channels/rdpsnd/$(am__dirstamp): @$(MKDIR_P) channels/rdpsnd @: > channels/rdpsnd/$(am__dirstamp) channels/rdpsnd/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) channels/rdpsnd/$(DEPDIR) @: > channels/rdpsnd/$(DEPDIR)/$(am__dirstamp) channels/rdpsnd/libguac_client_rdp_la-rdpsnd-messages.lo: \ channels/rdpsnd/$(am__dirstamp) \ channels/rdpsnd/$(DEPDIR)/$(am__dirstamp) channels/rdpsnd/libguac_client_rdp_la-rdpsnd.lo: \ channels/rdpsnd/$(am__dirstamp) \ channels/rdpsnd/$(DEPDIR)/$(am__dirstamp) plugins/$(am__dirstamp): @$(MKDIR_P) plugins @: > plugins/$(am__dirstamp) plugins/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/$(DEPDIR) @: > plugins/$(DEPDIR)/$(am__dirstamp) plugins/libguac_client_rdp_la-channels.lo: plugins/$(am__dirstamp) \ plugins/$(DEPDIR)/$(am__dirstamp) plugins/libguac_client_rdp_la-ptr-string.lo: plugins/$(am__dirstamp) \ plugins/$(DEPDIR)/$(am__dirstamp) libguac-client-rdp.la: $(libguac_client_rdp_la_OBJECTS) $(libguac_client_rdp_la_DEPENDENCIES) $(EXTRA_libguac_client_rdp_la_DEPENDENCIES) $(AM_V_CCLD)$(libguac_client_rdp_la_LINK) -rpath $(libdir) $(libguac_client_rdp_la_OBJECTS) $(libguac_client_rdp_la_LIBADD) $(LIBS) plugins/guac-common-svc/$(am__dirstamp): @$(MKDIR_P) plugins/guac-common-svc @: > plugins/guac-common-svc/$(am__dirstamp) plugins/guac-common-svc/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/guac-common-svc/$(DEPDIR) @: > plugins/guac-common-svc/$(DEPDIR)/$(am__dirstamp) plugins/guac-common-svc/libguac_common_svc_client_la-guac-common-svc.lo: \ plugins/guac-common-svc/$(am__dirstamp) \ plugins/guac-common-svc/$(DEPDIR)/$(am__dirstamp) libguac-common-svc-client.la: $(libguac_common_svc_client_la_OBJECTS) $(libguac_common_svc_client_la_DEPENDENCIES) $(EXTRA_libguac_common_svc_client_la_DEPENDENCIES) $(AM_V_CCLD)$(libguac_common_svc_client_la_LINK) -rpath $(freerdpdir) $(libguac_common_svc_client_la_OBJECTS) $(libguac_common_svc_client_la_LIBADD) $(LIBS) channels/audio-input/libguacai_client_la-audio-buffer.lo: \ channels/audio-input/$(am__dirstamp) \ channels/audio-input/$(DEPDIR)/$(am__dirstamp) plugins/guacai/$(am__dirstamp): @$(MKDIR_P) plugins/guacai @: > plugins/guacai/$(am__dirstamp) plugins/guacai/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/guacai/$(DEPDIR) @: > plugins/guacai/$(DEPDIR)/$(am__dirstamp) plugins/guacai/libguacai_client_la-guacai-messages.lo: \ plugins/guacai/$(am__dirstamp) \ plugins/guacai/$(DEPDIR)/$(am__dirstamp) plugins/guacai/libguacai_client_la-guacai.lo: \ plugins/guacai/$(am__dirstamp) \ plugins/guacai/$(DEPDIR)/$(am__dirstamp) plugins/libguacai_client_la-ptr-string.lo: plugins/$(am__dirstamp) \ plugins/$(DEPDIR)/$(am__dirstamp) libguacai-client.la: $(libguacai_client_la_OBJECTS) $(libguacai_client_la_DEPENDENCIES) $(EXTRA_libguacai_client_la_DEPENDENCIES) $(AM_V_CCLD)$(libguacai_client_la_LINK) -rpath $(freerdpdir) $(libguacai_client_la_OBJECTS) $(libguacai_client_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f channels/*.$(OBJEXT) -rm -f channels/*.lo -rm -f channels/audio-input/*.$(OBJEXT) -rm -f channels/audio-input/*.lo -rm -f channels/rdpdr/*.$(OBJEXT) -rm -f channels/rdpdr/*.lo -rm -f channels/rdpsnd/*.$(OBJEXT) -rm -f channels/rdpsnd/*.lo -rm -f plugins/*.$(OBJEXT) -rm -f plugins/*.lo -rm -f plugins/guac-common-svc/*.$(OBJEXT) -rm -f plugins/guac-common-svc/*.lo -rm -f plugins/guacai/*.$(OBJEXT) -rm -f plugins/guacai/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-_generated_channel_entry_wrappers.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-_generated_keymaps.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-argv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-beep.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-bitmap.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-client.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-color.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-decompose.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-download.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-error.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-fs.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-gdi.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-glyph.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-input.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-keyboard.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-keymap.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-log.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-ls.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-pointer.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-print-job.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-rdp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-resolution.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-settings.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-sftp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-unicode.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-upload.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_rdp_la-user.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/$(DEPDIR)/libguac_client_rdp_la-cliprdr.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/$(DEPDIR)/libguac_client_rdp_la-common-svc.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/$(DEPDIR)/libguac_client_rdp_la-disp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/$(DEPDIR)/libguac_client_rdp_la-pipe-svc.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/$(DEPDIR)/libguac_client_rdp_la-rail.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-buffer.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-input.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/audio-input/$(DEPDIR)/libguacai_client_la-audio-buffer.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-file-info.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-messages.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-printer.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd-messages.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/libguac_client_rdp_la-channels.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/libguac_client_rdp_la-ptr-string.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/libguacai_client_la-ptr-string.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@plugins/guac-common-svc/$(DEPDIR)/libguac_common_svc_client_la-guac-common-svc.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai-messages.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libguac_client_rdp_la-argv.lo: argv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-argv.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-argv.Tpo -c -o libguac_client_rdp_la-argv.lo `test -f 'argv.c' || echo '$(srcdir)/'`argv.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-argv.Tpo $(DEPDIR)/libguac_client_rdp_la-argv.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='argv.c' object='libguac_client_rdp_la-argv.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-argv.lo `test -f 'argv.c' || echo '$(srcdir)/'`argv.c libguac_client_rdp_la-beep.lo: beep.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-beep.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-beep.Tpo -c -o libguac_client_rdp_la-beep.lo `test -f 'beep.c' || echo '$(srcdir)/'`beep.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-beep.Tpo $(DEPDIR)/libguac_client_rdp_la-beep.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='beep.c' object='libguac_client_rdp_la-beep.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-beep.lo `test -f 'beep.c' || echo '$(srcdir)/'`beep.c libguac_client_rdp_la-bitmap.lo: bitmap.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-bitmap.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-bitmap.Tpo -c -o libguac_client_rdp_la-bitmap.lo `test -f 'bitmap.c' || echo '$(srcdir)/'`bitmap.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-bitmap.Tpo $(DEPDIR)/libguac_client_rdp_la-bitmap.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bitmap.c' object='libguac_client_rdp_la-bitmap.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-bitmap.lo `test -f 'bitmap.c' || echo '$(srcdir)/'`bitmap.c channels/audio-input/libguac_client_rdp_la-audio-buffer.lo: channels/audio-input/audio-buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/audio-input/libguac_client_rdp_la-audio-buffer.lo -MD -MP -MF channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-buffer.Tpo -c -o channels/audio-input/libguac_client_rdp_la-audio-buffer.lo `test -f 'channels/audio-input/audio-buffer.c' || echo '$(srcdir)/'`channels/audio-input/audio-buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-buffer.Tpo channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-buffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/audio-input/audio-buffer.c' object='channels/audio-input/libguac_client_rdp_la-audio-buffer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/audio-input/libguac_client_rdp_la-audio-buffer.lo `test -f 'channels/audio-input/audio-buffer.c' || echo '$(srcdir)/'`channels/audio-input/audio-buffer.c channels/audio-input/libguac_client_rdp_la-audio-input.lo: channels/audio-input/audio-input.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/audio-input/libguac_client_rdp_la-audio-input.lo -MD -MP -MF channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-input.Tpo -c -o channels/audio-input/libguac_client_rdp_la-audio-input.lo `test -f 'channels/audio-input/audio-input.c' || echo '$(srcdir)/'`channels/audio-input/audio-input.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-input.Tpo channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-input.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/audio-input/audio-input.c' object='channels/audio-input/libguac_client_rdp_la-audio-input.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/audio-input/libguac_client_rdp_la-audio-input.lo `test -f 'channels/audio-input/audio-input.c' || echo '$(srcdir)/'`channels/audio-input/audio-input.c channels/libguac_client_rdp_la-cliprdr.lo: channels/cliprdr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/libguac_client_rdp_la-cliprdr.lo -MD -MP -MF channels/$(DEPDIR)/libguac_client_rdp_la-cliprdr.Tpo -c -o channels/libguac_client_rdp_la-cliprdr.lo `test -f 'channels/cliprdr.c' || echo '$(srcdir)/'`channels/cliprdr.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/$(DEPDIR)/libguac_client_rdp_la-cliprdr.Tpo channels/$(DEPDIR)/libguac_client_rdp_la-cliprdr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/cliprdr.c' object='channels/libguac_client_rdp_la-cliprdr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/libguac_client_rdp_la-cliprdr.lo `test -f 'channels/cliprdr.c' || echo '$(srcdir)/'`channels/cliprdr.c channels/libguac_client_rdp_la-common-svc.lo: channels/common-svc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/libguac_client_rdp_la-common-svc.lo -MD -MP -MF channels/$(DEPDIR)/libguac_client_rdp_la-common-svc.Tpo -c -o channels/libguac_client_rdp_la-common-svc.lo `test -f 'channels/common-svc.c' || echo '$(srcdir)/'`channels/common-svc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/$(DEPDIR)/libguac_client_rdp_la-common-svc.Tpo channels/$(DEPDIR)/libguac_client_rdp_la-common-svc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/common-svc.c' object='channels/libguac_client_rdp_la-common-svc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/libguac_client_rdp_la-common-svc.lo `test -f 'channels/common-svc.c' || echo '$(srcdir)/'`channels/common-svc.c channels/libguac_client_rdp_la-disp.lo: channels/disp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/libguac_client_rdp_la-disp.lo -MD -MP -MF channels/$(DEPDIR)/libguac_client_rdp_la-disp.Tpo -c -o channels/libguac_client_rdp_la-disp.lo `test -f 'channels/disp.c' || echo '$(srcdir)/'`channels/disp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/$(DEPDIR)/libguac_client_rdp_la-disp.Tpo channels/$(DEPDIR)/libguac_client_rdp_la-disp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/disp.c' object='channels/libguac_client_rdp_la-disp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/libguac_client_rdp_la-disp.lo `test -f 'channels/disp.c' || echo '$(srcdir)/'`channels/disp.c channels/libguac_client_rdp_la-pipe-svc.lo: channels/pipe-svc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/libguac_client_rdp_la-pipe-svc.lo -MD -MP -MF channels/$(DEPDIR)/libguac_client_rdp_la-pipe-svc.Tpo -c -o channels/libguac_client_rdp_la-pipe-svc.lo `test -f 'channels/pipe-svc.c' || echo '$(srcdir)/'`channels/pipe-svc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/$(DEPDIR)/libguac_client_rdp_la-pipe-svc.Tpo channels/$(DEPDIR)/libguac_client_rdp_la-pipe-svc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/pipe-svc.c' object='channels/libguac_client_rdp_la-pipe-svc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/libguac_client_rdp_la-pipe-svc.lo `test -f 'channels/pipe-svc.c' || echo '$(srcdir)/'`channels/pipe-svc.c channels/libguac_client_rdp_la-rail.lo: channels/rail.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/libguac_client_rdp_la-rail.lo -MD -MP -MF channels/$(DEPDIR)/libguac_client_rdp_la-rail.Tpo -c -o channels/libguac_client_rdp_la-rail.lo `test -f 'channels/rail.c' || echo '$(srcdir)/'`channels/rail.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/$(DEPDIR)/libguac_client_rdp_la-rail.Tpo channels/$(DEPDIR)/libguac_client_rdp_la-rail.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/rail.c' object='channels/libguac_client_rdp_la-rail.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/libguac_client_rdp_la-rail.lo `test -f 'channels/rail.c' || echo '$(srcdir)/'`channels/rail.c channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.lo: channels/rdpdr/rdpdr-fs-messages-dir-info.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.lo -MD -MP -MF channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.Tpo -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.lo `test -f 'channels/rdpdr/rdpdr-fs-messages-dir-info.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-fs-messages-dir-info.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.Tpo channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/rdpdr/rdpdr-fs-messages-dir-info.c' object='channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.lo `test -f 'channels/rdpdr/rdpdr-fs-messages-dir-info.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-fs-messages-dir-info.c channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-file-info.lo: channels/rdpdr/rdpdr-fs-messages-file-info.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-file-info.lo -MD -MP -MF channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-file-info.Tpo -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-file-info.lo `test -f 'channels/rdpdr/rdpdr-fs-messages-file-info.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-fs-messages-file-info.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-file-info.Tpo channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-file-info.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/rdpdr/rdpdr-fs-messages-file-info.c' object='channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-file-info.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-file-info.lo `test -f 'channels/rdpdr/rdpdr-fs-messages-file-info.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-fs-messages-file-info.c channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.lo: channels/rdpdr/rdpdr-fs-messages-vol-info.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.lo -MD -MP -MF channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.Tpo -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.lo `test -f 'channels/rdpdr/rdpdr-fs-messages-vol-info.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-fs-messages-vol-info.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.Tpo channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/rdpdr/rdpdr-fs-messages-vol-info.c' object='channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.lo `test -f 'channels/rdpdr/rdpdr-fs-messages-vol-info.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-fs-messages-vol-info.c channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages.lo: channels/rdpdr/rdpdr-fs-messages.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages.lo -MD -MP -MF channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages.Tpo -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages.lo `test -f 'channels/rdpdr/rdpdr-fs-messages.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-fs-messages.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages.Tpo channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/rdpdr/rdpdr-fs-messages.c' object='channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-fs-messages.lo `test -f 'channels/rdpdr/rdpdr-fs-messages.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-fs-messages.c channels/rdpdr/libguac_client_rdp_la-rdpdr-fs.lo: channels/rdpdr/rdpdr-fs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/rdpdr/libguac_client_rdp_la-rdpdr-fs.lo -MD -MP -MF channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs.Tpo -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-fs.lo `test -f 'channels/rdpdr/rdpdr-fs.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-fs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs.Tpo channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/rdpdr/rdpdr-fs.c' object='channels/rdpdr/libguac_client_rdp_la-rdpdr-fs.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-fs.lo `test -f 'channels/rdpdr/rdpdr-fs.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-fs.c channels/rdpdr/libguac_client_rdp_la-rdpdr-messages.lo: channels/rdpdr/rdpdr-messages.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/rdpdr/libguac_client_rdp_la-rdpdr-messages.lo -MD -MP -MF channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-messages.Tpo -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-messages.lo `test -f 'channels/rdpdr/rdpdr-messages.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-messages.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-messages.Tpo channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-messages.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/rdpdr/rdpdr-messages.c' object='channels/rdpdr/libguac_client_rdp_la-rdpdr-messages.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-messages.lo `test -f 'channels/rdpdr/rdpdr-messages.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-messages.c channels/rdpdr/libguac_client_rdp_la-rdpdr-printer.lo: channels/rdpdr/rdpdr-printer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/rdpdr/libguac_client_rdp_la-rdpdr-printer.lo -MD -MP -MF channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-printer.Tpo -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-printer.lo `test -f 'channels/rdpdr/rdpdr-printer.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-printer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-printer.Tpo channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-printer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/rdpdr/rdpdr-printer.c' object='channels/rdpdr/libguac_client_rdp_la-rdpdr-printer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr-printer.lo `test -f 'channels/rdpdr/rdpdr-printer.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr-printer.c channels/rdpdr/libguac_client_rdp_la-rdpdr.lo: channels/rdpdr/rdpdr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/rdpdr/libguac_client_rdp_la-rdpdr.lo -MD -MP -MF channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr.Tpo -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr.lo `test -f 'channels/rdpdr/rdpdr.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr.Tpo channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/rdpdr/rdpdr.c' object='channels/rdpdr/libguac_client_rdp_la-rdpdr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/rdpdr/libguac_client_rdp_la-rdpdr.lo `test -f 'channels/rdpdr/rdpdr.c' || echo '$(srcdir)/'`channels/rdpdr/rdpdr.c channels/rdpsnd/libguac_client_rdp_la-rdpsnd-messages.lo: channels/rdpsnd/rdpsnd-messages.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/rdpsnd/libguac_client_rdp_la-rdpsnd-messages.lo -MD -MP -MF channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd-messages.Tpo -c -o channels/rdpsnd/libguac_client_rdp_la-rdpsnd-messages.lo `test -f 'channels/rdpsnd/rdpsnd-messages.c' || echo '$(srcdir)/'`channels/rdpsnd/rdpsnd-messages.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd-messages.Tpo channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd-messages.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/rdpsnd/rdpsnd-messages.c' object='channels/rdpsnd/libguac_client_rdp_la-rdpsnd-messages.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/rdpsnd/libguac_client_rdp_la-rdpsnd-messages.lo `test -f 'channels/rdpsnd/rdpsnd-messages.c' || echo '$(srcdir)/'`channels/rdpsnd/rdpsnd-messages.c channels/rdpsnd/libguac_client_rdp_la-rdpsnd.lo: channels/rdpsnd/rdpsnd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT channels/rdpsnd/libguac_client_rdp_la-rdpsnd.lo -MD -MP -MF channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd.Tpo -c -o channels/rdpsnd/libguac_client_rdp_la-rdpsnd.lo `test -f 'channels/rdpsnd/rdpsnd.c' || echo '$(srcdir)/'`channels/rdpsnd/rdpsnd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd.Tpo channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/rdpsnd/rdpsnd.c' object='channels/rdpsnd/libguac_client_rdp_la-rdpsnd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o channels/rdpsnd/libguac_client_rdp_la-rdpsnd.lo `test -f 'channels/rdpsnd/rdpsnd.c' || echo '$(srcdir)/'`channels/rdpsnd/rdpsnd.c libguac_client_rdp_la-client.lo: client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-client.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-client.Tpo -c -o libguac_client_rdp_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-client.Tpo $(DEPDIR)/libguac_client_rdp_la-client.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client.c' object='libguac_client_rdp_la-client.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c libguac_client_rdp_la-color.lo: color.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-color.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-color.Tpo -c -o libguac_client_rdp_la-color.lo `test -f 'color.c' || echo '$(srcdir)/'`color.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-color.Tpo $(DEPDIR)/libguac_client_rdp_la-color.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='color.c' object='libguac_client_rdp_la-color.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-color.lo `test -f 'color.c' || echo '$(srcdir)/'`color.c libguac_client_rdp_la-decompose.lo: decompose.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-decompose.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-decompose.Tpo -c -o libguac_client_rdp_la-decompose.lo `test -f 'decompose.c' || echo '$(srcdir)/'`decompose.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-decompose.Tpo $(DEPDIR)/libguac_client_rdp_la-decompose.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='decompose.c' object='libguac_client_rdp_la-decompose.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-decompose.lo `test -f 'decompose.c' || echo '$(srcdir)/'`decompose.c libguac_client_rdp_la-download.lo: download.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-download.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-download.Tpo -c -o libguac_client_rdp_la-download.lo `test -f 'download.c' || echo '$(srcdir)/'`download.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-download.Tpo $(DEPDIR)/libguac_client_rdp_la-download.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='download.c' object='libguac_client_rdp_la-download.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-download.lo `test -f 'download.c' || echo '$(srcdir)/'`download.c libguac_client_rdp_la-error.lo: error.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-error.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-error.Tpo -c -o libguac_client_rdp_la-error.lo `test -f 'error.c' || echo '$(srcdir)/'`error.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-error.Tpo $(DEPDIR)/libguac_client_rdp_la-error.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='error.c' object='libguac_client_rdp_la-error.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-error.lo `test -f 'error.c' || echo '$(srcdir)/'`error.c libguac_client_rdp_la-fs.lo: fs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-fs.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-fs.Tpo -c -o libguac_client_rdp_la-fs.lo `test -f 'fs.c' || echo '$(srcdir)/'`fs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-fs.Tpo $(DEPDIR)/libguac_client_rdp_la-fs.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs.c' object='libguac_client_rdp_la-fs.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-fs.lo `test -f 'fs.c' || echo '$(srcdir)/'`fs.c libguac_client_rdp_la-gdi.lo: gdi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-gdi.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-gdi.Tpo -c -o libguac_client_rdp_la-gdi.lo `test -f 'gdi.c' || echo '$(srcdir)/'`gdi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-gdi.Tpo $(DEPDIR)/libguac_client_rdp_la-gdi.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gdi.c' object='libguac_client_rdp_la-gdi.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-gdi.lo `test -f 'gdi.c' || echo '$(srcdir)/'`gdi.c libguac_client_rdp_la-glyph.lo: glyph.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-glyph.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-glyph.Tpo -c -o libguac_client_rdp_la-glyph.lo `test -f 'glyph.c' || echo '$(srcdir)/'`glyph.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-glyph.Tpo $(DEPDIR)/libguac_client_rdp_la-glyph.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='glyph.c' object='libguac_client_rdp_la-glyph.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-glyph.lo `test -f 'glyph.c' || echo '$(srcdir)/'`glyph.c libguac_client_rdp_la-input.lo: input.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-input.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-input.Tpo -c -o libguac_client_rdp_la-input.lo `test -f 'input.c' || echo '$(srcdir)/'`input.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-input.Tpo $(DEPDIR)/libguac_client_rdp_la-input.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='input.c' object='libguac_client_rdp_la-input.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-input.lo `test -f 'input.c' || echo '$(srcdir)/'`input.c libguac_client_rdp_la-keyboard.lo: keyboard.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-keyboard.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-keyboard.Tpo -c -o libguac_client_rdp_la-keyboard.lo `test -f 'keyboard.c' || echo '$(srcdir)/'`keyboard.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-keyboard.Tpo $(DEPDIR)/libguac_client_rdp_la-keyboard.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keyboard.c' object='libguac_client_rdp_la-keyboard.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-keyboard.lo `test -f 'keyboard.c' || echo '$(srcdir)/'`keyboard.c libguac_client_rdp_la-keymap.lo: keymap.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-keymap.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-keymap.Tpo -c -o libguac_client_rdp_la-keymap.lo `test -f 'keymap.c' || echo '$(srcdir)/'`keymap.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-keymap.Tpo $(DEPDIR)/libguac_client_rdp_la-keymap.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keymap.c' object='libguac_client_rdp_la-keymap.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-keymap.lo `test -f 'keymap.c' || echo '$(srcdir)/'`keymap.c libguac_client_rdp_la-log.lo: log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-log.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-log.Tpo -c -o libguac_client_rdp_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-log.Tpo $(DEPDIR)/libguac_client_rdp_la-log.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='log.c' object='libguac_client_rdp_la-log.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c libguac_client_rdp_la-ls.lo: ls.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-ls.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-ls.Tpo -c -o libguac_client_rdp_la-ls.lo `test -f 'ls.c' || echo '$(srcdir)/'`ls.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-ls.Tpo $(DEPDIR)/libguac_client_rdp_la-ls.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ls.c' object='libguac_client_rdp_la-ls.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-ls.lo `test -f 'ls.c' || echo '$(srcdir)/'`ls.c plugins/libguac_client_rdp_la-channels.lo: plugins/channels.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT plugins/libguac_client_rdp_la-channels.lo -MD -MP -MF plugins/$(DEPDIR)/libguac_client_rdp_la-channels.Tpo -c -o plugins/libguac_client_rdp_la-channels.lo `test -f 'plugins/channels.c' || echo '$(srcdir)/'`plugins/channels.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) plugins/$(DEPDIR)/libguac_client_rdp_la-channels.Tpo plugins/$(DEPDIR)/libguac_client_rdp_la-channels.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugins/channels.c' object='plugins/libguac_client_rdp_la-channels.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o plugins/libguac_client_rdp_la-channels.lo `test -f 'plugins/channels.c' || echo '$(srcdir)/'`plugins/channels.c plugins/libguac_client_rdp_la-ptr-string.lo: plugins/ptr-string.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT plugins/libguac_client_rdp_la-ptr-string.lo -MD -MP -MF plugins/$(DEPDIR)/libguac_client_rdp_la-ptr-string.Tpo -c -o plugins/libguac_client_rdp_la-ptr-string.lo `test -f 'plugins/ptr-string.c' || echo '$(srcdir)/'`plugins/ptr-string.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) plugins/$(DEPDIR)/libguac_client_rdp_la-ptr-string.Tpo plugins/$(DEPDIR)/libguac_client_rdp_la-ptr-string.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugins/ptr-string.c' object='plugins/libguac_client_rdp_la-ptr-string.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o plugins/libguac_client_rdp_la-ptr-string.lo `test -f 'plugins/ptr-string.c' || echo '$(srcdir)/'`plugins/ptr-string.c libguac_client_rdp_la-pointer.lo: pointer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-pointer.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-pointer.Tpo -c -o libguac_client_rdp_la-pointer.lo `test -f 'pointer.c' || echo '$(srcdir)/'`pointer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-pointer.Tpo $(DEPDIR)/libguac_client_rdp_la-pointer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pointer.c' object='libguac_client_rdp_la-pointer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-pointer.lo `test -f 'pointer.c' || echo '$(srcdir)/'`pointer.c libguac_client_rdp_la-print-job.lo: print-job.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-print-job.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-print-job.Tpo -c -o libguac_client_rdp_la-print-job.lo `test -f 'print-job.c' || echo '$(srcdir)/'`print-job.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-print-job.Tpo $(DEPDIR)/libguac_client_rdp_la-print-job.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='print-job.c' object='libguac_client_rdp_la-print-job.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-print-job.lo `test -f 'print-job.c' || echo '$(srcdir)/'`print-job.c libguac_client_rdp_la-rdp.lo: rdp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-rdp.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-rdp.Tpo -c -o libguac_client_rdp_la-rdp.lo `test -f 'rdp.c' || echo '$(srcdir)/'`rdp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-rdp.Tpo $(DEPDIR)/libguac_client_rdp_la-rdp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rdp.c' object='libguac_client_rdp_la-rdp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-rdp.lo `test -f 'rdp.c' || echo '$(srcdir)/'`rdp.c libguac_client_rdp_la-resolution.lo: resolution.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-resolution.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-resolution.Tpo -c -o libguac_client_rdp_la-resolution.lo `test -f 'resolution.c' || echo '$(srcdir)/'`resolution.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-resolution.Tpo $(DEPDIR)/libguac_client_rdp_la-resolution.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='resolution.c' object='libguac_client_rdp_la-resolution.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-resolution.lo `test -f 'resolution.c' || echo '$(srcdir)/'`resolution.c libguac_client_rdp_la-settings.lo: settings.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-settings.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-settings.Tpo -c -o libguac_client_rdp_la-settings.lo `test -f 'settings.c' || echo '$(srcdir)/'`settings.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-settings.Tpo $(DEPDIR)/libguac_client_rdp_la-settings.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings.c' object='libguac_client_rdp_la-settings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-settings.lo `test -f 'settings.c' || echo '$(srcdir)/'`settings.c libguac_client_rdp_la-unicode.lo: unicode.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-unicode.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-unicode.Tpo -c -o libguac_client_rdp_la-unicode.lo `test -f 'unicode.c' || echo '$(srcdir)/'`unicode.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-unicode.Tpo $(DEPDIR)/libguac_client_rdp_la-unicode.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unicode.c' object='libguac_client_rdp_la-unicode.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-unicode.lo `test -f 'unicode.c' || echo '$(srcdir)/'`unicode.c libguac_client_rdp_la-upload.lo: upload.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-upload.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-upload.Tpo -c -o libguac_client_rdp_la-upload.lo `test -f 'upload.c' || echo '$(srcdir)/'`upload.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-upload.Tpo $(DEPDIR)/libguac_client_rdp_la-upload.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='upload.c' object='libguac_client_rdp_la-upload.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-upload.lo `test -f 'upload.c' || echo '$(srcdir)/'`upload.c libguac_client_rdp_la-user.lo: user.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-user.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-user.Tpo -c -o libguac_client_rdp_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-user.Tpo $(DEPDIR)/libguac_client_rdp_la-user.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user.c' object='libguac_client_rdp_la-user.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c libguac_client_rdp_la-sftp.lo: sftp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-sftp.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-sftp.Tpo -c -o libguac_client_rdp_la-sftp.lo `test -f 'sftp.c' || echo '$(srcdir)/'`sftp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-sftp.Tpo $(DEPDIR)/libguac_client_rdp_la-sftp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sftp.c' object='libguac_client_rdp_la-sftp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-sftp.lo `test -f 'sftp.c' || echo '$(srcdir)/'`sftp.c libguac_client_rdp_la-_generated_channel_entry_wrappers.lo: _generated_channel_entry_wrappers.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-_generated_channel_entry_wrappers.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-_generated_channel_entry_wrappers.Tpo -c -o libguac_client_rdp_la-_generated_channel_entry_wrappers.lo `test -f '_generated_channel_entry_wrappers.c' || echo '$(srcdir)/'`_generated_channel_entry_wrappers.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-_generated_channel_entry_wrappers.Tpo $(DEPDIR)/libguac_client_rdp_la-_generated_channel_entry_wrappers.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='_generated_channel_entry_wrappers.c' object='libguac_client_rdp_la-_generated_channel_entry_wrappers.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-_generated_channel_entry_wrappers.lo `test -f '_generated_channel_entry_wrappers.c' || echo '$(srcdir)/'`_generated_channel_entry_wrappers.c libguac_client_rdp_la-_generated_keymaps.lo: _generated_keymaps.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -MT libguac_client_rdp_la-_generated_keymaps.lo -MD -MP -MF $(DEPDIR)/libguac_client_rdp_la-_generated_keymaps.Tpo -c -o libguac_client_rdp_la-_generated_keymaps.lo `test -f '_generated_keymaps.c' || echo '$(srcdir)/'`_generated_keymaps.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_rdp_la-_generated_keymaps.Tpo $(DEPDIR)/libguac_client_rdp_la-_generated_keymaps.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='_generated_keymaps.c' object='libguac_client_rdp_la-_generated_keymaps.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_rdp_la_CFLAGS) $(CFLAGS) -c -o libguac_client_rdp_la-_generated_keymaps.lo `test -f '_generated_keymaps.c' || echo '$(srcdir)/'`_generated_keymaps.c plugins/guac-common-svc/libguac_common_svc_client_la-guac-common-svc.lo: plugins/guac-common-svc/guac-common-svc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_svc_client_la_CFLAGS) $(CFLAGS) -MT plugins/guac-common-svc/libguac_common_svc_client_la-guac-common-svc.lo -MD -MP -MF plugins/guac-common-svc/$(DEPDIR)/libguac_common_svc_client_la-guac-common-svc.Tpo -c -o plugins/guac-common-svc/libguac_common_svc_client_la-guac-common-svc.lo `test -f 'plugins/guac-common-svc/guac-common-svc.c' || echo '$(srcdir)/'`plugins/guac-common-svc/guac-common-svc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) plugins/guac-common-svc/$(DEPDIR)/libguac_common_svc_client_la-guac-common-svc.Tpo plugins/guac-common-svc/$(DEPDIR)/libguac_common_svc_client_la-guac-common-svc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugins/guac-common-svc/guac-common-svc.c' object='plugins/guac-common-svc/libguac_common_svc_client_la-guac-common-svc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_svc_client_la_CFLAGS) $(CFLAGS) -c -o plugins/guac-common-svc/libguac_common_svc_client_la-guac-common-svc.lo `test -f 'plugins/guac-common-svc/guac-common-svc.c' || echo '$(srcdir)/'`plugins/guac-common-svc/guac-common-svc.c channels/audio-input/libguacai_client_la-audio-buffer.lo: channels/audio-input/audio-buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguacai_client_la_CFLAGS) $(CFLAGS) -MT channels/audio-input/libguacai_client_la-audio-buffer.lo -MD -MP -MF channels/audio-input/$(DEPDIR)/libguacai_client_la-audio-buffer.Tpo -c -o channels/audio-input/libguacai_client_la-audio-buffer.lo `test -f 'channels/audio-input/audio-buffer.c' || echo '$(srcdir)/'`channels/audio-input/audio-buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) channels/audio-input/$(DEPDIR)/libguacai_client_la-audio-buffer.Tpo channels/audio-input/$(DEPDIR)/libguacai_client_la-audio-buffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='channels/audio-input/audio-buffer.c' object='channels/audio-input/libguacai_client_la-audio-buffer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguacai_client_la_CFLAGS) $(CFLAGS) -c -o channels/audio-input/libguacai_client_la-audio-buffer.lo `test -f 'channels/audio-input/audio-buffer.c' || echo '$(srcdir)/'`channels/audio-input/audio-buffer.c plugins/guacai/libguacai_client_la-guacai-messages.lo: plugins/guacai/guacai-messages.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguacai_client_la_CFLAGS) $(CFLAGS) -MT plugins/guacai/libguacai_client_la-guacai-messages.lo -MD -MP -MF plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai-messages.Tpo -c -o plugins/guacai/libguacai_client_la-guacai-messages.lo `test -f 'plugins/guacai/guacai-messages.c' || echo '$(srcdir)/'`plugins/guacai/guacai-messages.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai-messages.Tpo plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai-messages.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugins/guacai/guacai-messages.c' object='plugins/guacai/libguacai_client_la-guacai-messages.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguacai_client_la_CFLAGS) $(CFLAGS) -c -o plugins/guacai/libguacai_client_la-guacai-messages.lo `test -f 'plugins/guacai/guacai-messages.c' || echo '$(srcdir)/'`plugins/guacai/guacai-messages.c plugins/guacai/libguacai_client_la-guacai.lo: plugins/guacai/guacai.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguacai_client_la_CFLAGS) $(CFLAGS) -MT plugins/guacai/libguacai_client_la-guacai.lo -MD -MP -MF plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai.Tpo -c -o plugins/guacai/libguacai_client_la-guacai.lo `test -f 'plugins/guacai/guacai.c' || echo '$(srcdir)/'`plugins/guacai/guacai.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai.Tpo plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugins/guacai/guacai.c' object='plugins/guacai/libguacai_client_la-guacai.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguacai_client_la_CFLAGS) $(CFLAGS) -c -o plugins/guacai/libguacai_client_la-guacai.lo `test -f 'plugins/guacai/guacai.c' || echo '$(srcdir)/'`plugins/guacai/guacai.c plugins/libguacai_client_la-ptr-string.lo: plugins/ptr-string.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguacai_client_la_CFLAGS) $(CFLAGS) -MT plugins/libguacai_client_la-ptr-string.lo -MD -MP -MF plugins/$(DEPDIR)/libguacai_client_la-ptr-string.Tpo -c -o plugins/libguacai_client_la-ptr-string.lo `test -f 'plugins/ptr-string.c' || echo '$(srcdir)/'`plugins/ptr-string.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) plugins/$(DEPDIR)/libguacai_client_la-ptr-string.Tpo plugins/$(DEPDIR)/libguacai_client_la-ptr-string.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugins/ptr-string.c' object='plugins/libguacai_client_la-ptr-string.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguacai_client_la_CFLAGS) $(CFLAGS) -c -o plugins/libguacai_client_la-ptr-string.lo `test -f 'plugins/ptr-string.c' || echo '$(srcdir)/'`plugins/ptr-string.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf channels/.libs channels/_libs -rm -rf channels/audio-input/.libs channels/audio-input/_libs -rm -rf channels/rdpdr/.libs channels/rdpdr/_libs -rm -rf channels/rdpsnd/.libs channels/rdpsnd/_libs -rm -rf plugins/.libs plugins/_libs -rm -rf plugins/guac-common-svc/.libs plugins/guac-common-svc/_libs -rm -rf plugins/guacai/.libs plugins/guacai/_libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-recursive all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(freerdpdir)" "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f channels/$(DEPDIR)/$(am__dirstamp) -rm -f channels/$(am__dirstamp) -rm -f channels/audio-input/$(DEPDIR)/$(am__dirstamp) -rm -f channels/audio-input/$(am__dirstamp) -rm -f channels/rdpdr/$(DEPDIR)/$(am__dirstamp) -rm -f channels/rdpdr/$(am__dirstamp) -rm -f channels/rdpsnd/$(DEPDIR)/$(am__dirstamp) -rm -f channels/rdpsnd/$(am__dirstamp) -rm -f plugins/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/$(am__dirstamp) -rm -f plugins/guac-common-svc/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/guac-common-svc/$(am__dirstamp) -rm -f plugins/guacai/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/guacai/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-recursive clean-am: clean-freerdpLTLIBRARIES clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f ./$(DEPDIR)/libguac_client_rdp_la-_generated_channel_entry_wrappers.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-_generated_keymaps.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-argv.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-beep.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-bitmap.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-client.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-color.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-decompose.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-download.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-error.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-fs.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-gdi.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-glyph.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-input.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-keyboard.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-keymap.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-log.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-ls.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-pointer.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-print-job.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-rdp.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-resolution.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-settings.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-sftp.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-unicode.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-upload.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-user.Plo -rm -f channels/$(DEPDIR)/libguac_client_rdp_la-cliprdr.Plo -rm -f channels/$(DEPDIR)/libguac_client_rdp_la-common-svc.Plo -rm -f channels/$(DEPDIR)/libguac_client_rdp_la-disp.Plo -rm -f channels/$(DEPDIR)/libguac_client_rdp_la-pipe-svc.Plo -rm -f channels/$(DEPDIR)/libguac_client_rdp_la-rail.Plo -rm -f channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-buffer.Plo -rm -f channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-input.Plo -rm -f channels/audio-input/$(DEPDIR)/libguacai_client_la-audio-buffer.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-file-info.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-messages.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-printer.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr.Plo -rm -f channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd-messages.Plo -rm -f channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd.Plo -rm -f plugins/$(DEPDIR)/libguac_client_rdp_la-channels.Plo -rm -f plugins/$(DEPDIR)/libguac_client_rdp_la-ptr-string.Plo -rm -f plugins/$(DEPDIR)/libguacai_client_la-ptr-string.Plo -rm -f plugins/guac-common-svc/$(DEPDIR)/libguac_common_svc_client_la-guac-common-svc.Plo -rm -f plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai-messages.Plo -rm -f plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-freerdpLTLIBRARIES install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/libguac_client_rdp_la-_generated_channel_entry_wrappers.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-_generated_keymaps.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-argv.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-beep.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-bitmap.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-client.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-color.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-decompose.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-download.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-error.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-fs.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-gdi.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-glyph.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-input.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-keyboard.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-keymap.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-log.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-ls.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-pointer.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-print-job.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-rdp.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-resolution.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-settings.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-sftp.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-unicode.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-upload.Plo -rm -f ./$(DEPDIR)/libguac_client_rdp_la-user.Plo -rm -f channels/$(DEPDIR)/libguac_client_rdp_la-cliprdr.Plo -rm -f channels/$(DEPDIR)/libguac_client_rdp_la-common-svc.Plo -rm -f channels/$(DEPDIR)/libguac_client_rdp_la-disp.Plo -rm -f channels/$(DEPDIR)/libguac_client_rdp_la-pipe-svc.Plo -rm -f channels/$(DEPDIR)/libguac_client_rdp_la-rail.Plo -rm -f channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-buffer.Plo -rm -f channels/audio-input/$(DEPDIR)/libguac_client_rdp_la-audio-input.Plo -rm -f channels/audio-input/$(DEPDIR)/libguacai_client_la-audio-buffer.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-dir-info.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-file-info.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages-vol-info.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs-messages.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-fs.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-messages.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr-printer.Plo -rm -f channels/rdpdr/$(DEPDIR)/libguac_client_rdp_la-rdpdr.Plo -rm -f channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd-messages.Plo -rm -f channels/rdpsnd/$(DEPDIR)/libguac_client_rdp_la-rdpsnd.Plo -rm -f plugins/$(DEPDIR)/libguac_client_rdp_la-channels.Plo -rm -f plugins/$(DEPDIR)/libguac_client_rdp_la-ptr-string.Plo -rm -f plugins/$(DEPDIR)/libguacai_client_la-ptr-string.Plo -rm -f plugins/guac-common-svc/$(DEPDIR)/libguac_common_svc_client_la-guac-common-svc.Plo -rm -f plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai-messages.Plo -rm -f plugins/guacai/$(DEPDIR)/libguacai_client_la-guacai.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-freerdpLTLIBRARIES uninstall-libLTLIBRARIES .MAKE: $(am__recursive_targets) all check install install-am \ install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--depfiles check check-am clean clean-freerdpLTLIBRARIES \ clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-freerdpLTLIBRARIES install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am \ uninstall-freerdpLTLIBRARIES uninstall-libLTLIBRARIES .PRECIOUS: Makefile _generated_keymaps.c: $(rdp_keymaps) $(srcdir)/keymaps/generate.pl $(AM_V_GEN) $(srcdir)/keymaps/generate.pl $(rdp_keymaps) _generated_channel_entry_wrappers.c: $(srcdir)/plugins/channels.h $(srcdir)/plugins/generate-entry-wrappers.pl $(AM_V_GEN) $(srcdir)/plugins/generate-entry-wrappers.pl $(srcdir)/plugins/channels.h # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/protocols/rdp/bitmap.c0000644000175100001440000001231513764613616016731 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "bitmap.h" #include "common/display.h" #include "common/surface.h" #include "config.h" #include "rdp.h" #include #include #include #include #include #include #include void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Allocate buffer */ guac_common_display_layer* buffer = guac_common_display_alloc_buffer( rdp_client->display, bitmap->width, bitmap->height); /* Cache image data if present */ if (bitmap->data != NULL) { /* Create surface from image data */ cairo_surface_t* image = cairo_image_surface_create_for_data( bitmap->data, CAIRO_FORMAT_RGB24, bitmap->width, bitmap->height, 4*bitmap->width); /* Send surface to buffer */ guac_common_surface_draw(buffer->surface, 0, 0, image); /* Free surface */ cairo_surface_destroy(image); } /* Store buffer reference in bitmap */ ((guac_rdp_bitmap*) bitmap)->layer = buffer; } BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { /* No corresponding surface yet - caching is deferred. */ ((guac_rdp_bitmap*) bitmap)->layer = NULL; /* Start at zero usage */ ((guac_rdp_bitmap*) bitmap)->used = 0; return TRUE; } BOOL guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_common_display_layer* buffer = ((guac_rdp_bitmap*) bitmap)->layer; int width = bitmap->right - bitmap->left + 1; int height = bitmap->bottom - bitmap->top + 1; /* If not cached, cache if necessary */ if (buffer == NULL && ((guac_rdp_bitmap*) bitmap)->used >= 1) guac_rdp_cache_bitmap(context, bitmap); /* If cached, retrieve from cache */ if (buffer != NULL) guac_common_surface_copy(buffer->surface, 0, 0, width, height, rdp_client->display->default_surface, bitmap->left, bitmap->top); /* Otherwise, draw with stored image data */ else if (bitmap->data != NULL) { /* Create surface from image data */ cairo_surface_t* image = cairo_image_surface_create_for_data( bitmap->data, CAIRO_FORMAT_RGB24, width, height, 4*bitmap->width); /* Draw image on default surface */ guac_common_surface_draw(rdp_client->display->default_surface, bitmap->left, bitmap->top, image); /* Free surface */ cairo_surface_destroy(image); } /* Increment usage counter */ ((guac_rdp_bitmap*) bitmap)->used++; return TRUE; } void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_common_display_layer* buffer = ((guac_rdp_bitmap*) bitmap)->layer; /* If cached, free buffer */ if (buffer != NULL) guac_common_display_free_buffer(rdp_client->display, buffer); #ifndef FREERDP_BITMAP_FREE_FREES_BITMAP /* NOTE: Except in FreeRDP 2.0.0-rc0 and earlier, FreeRDP-allocated memory * for the rdpBitmap will NOT be automatically released after this free * handler is invoked, thus we must do so manually here */ _aligned_free(bitmap->data); free(bitmap); #endif } BOOL guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; if (primary) rdp_client->current_surface = rdp_client->display->default_surface; else { /* Make sure that the recieved bitmap is not NULL before processing */ if (bitmap == NULL) { guac_client_log(client, GUAC_LOG_INFO, "NULL bitmap found in bitmap_setsurface instruction."); return TRUE; } /* If not available as a surface, make available. */ if (((guac_rdp_bitmap*) bitmap)->layer == NULL) guac_rdp_cache_bitmap(context, bitmap); rdp_client->current_surface = ((guac_rdp_bitmap*) bitmap)->layer->surface; } return TRUE; } guacamole-server-1.3.0/src/protocols/rdp/fs.h0000644000175100001440000004570413770536337016103 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_FS_H #define GUAC_RDP_FS_H /** * Functions and macros specific to filesystem handling and initialization * independent of RDP. The functions here may deal with the filesystem device * directly, but their semantics must not deal with RDP protocol messaging. * Functions here represent a virtual Windows-style filesystem on top of UNIX * system calls and structures, using the guac_rdp_fs structure as a home * for common data. * * @file fs.h */ #include #include #include #include #include #include /** * The maximum number of file IDs to provide. */ #define GUAC_RDP_FS_MAX_FILES 128 /** * The maximum number of bytes in a path string. */ #define GUAC_RDP_FS_MAX_PATH 4096 /** * The maximum number of directories a path may contain. */ #define GUAC_RDP_MAX_PATH_DEPTH 64 /** * Error code returned when no more file IDs can be allocated. */ #define GUAC_RDP_FS_ENFILE -1 /** * Error code returned when no such file exists. */ #define GUAC_RDP_FS_ENOENT -2 /** * Error code returned when the operation required a directory * but the file was not a directory. */ #define GUAC_RDP_FS_ENOTDIR -3 /** * Error code returned when insufficient space exists to complete * the operation. */ #define GUAC_RDP_FS_ENOSPC -4 /** * Error code returned when the operation requires a normal file but * a directory was given. */ #define GUAC_RDP_FS_EISDIR -5 /** * Error code returned when permission is denied. */ #define GUAC_RDP_FS_EACCES -6 /** * Error code returned when the operation cannot be completed because the * file already exists. */ #define GUAC_RDP_FS_EEXIST -7 /** * Error code returned when invalid parameters were given. */ #define GUAC_RDP_FS_EINVAL -8 /** * Error code returned when the operation is not implemented. */ #define GUAC_RDP_FS_ENOSYS -9 /** * Error code returned when the operation is not supported. */ #define GUAC_RDP_FS_ENOTSUP -10 /** * Converts a UNIX timestamp (seconds since Jan 1, 1970 UTC) to Windows * timestamp (100 nanosecond intervals since Jan 1, 1601 UTC). */ #define WINDOWS_TIME(t) ((t + ((uint64_t) 11644473600)) * 10000000) /** * An arbitrary file on the virtual filesystem of the Guacamole drive. */ typedef struct guac_rdp_fs_file { /** * The ID of this file. */ int id; /** * The absolute path, including filename, of this file. */ char* absolute_path; /** * The real path of this file on the local filesystem. */ char* real_path; /** * Associated local file descriptor. */ int fd; /** * Associated directory stream, if any. This field only applies * if the file is being used as a directory. */ DIR* dir; /** * The pattern the check directory contents against, if any. */ char dir_pattern[GUAC_RDP_FS_MAX_PATH]; /** * Bitwise OR of all associated Windows file attributes. */ int attributes; /** * The size of this file, in bytes. */ uint64_t size; /** * The time this file was created, as a Windows timestamp. */ uint64_t ctime; /** * The time this file was last modified, as a Windows timestamp. */ uint64_t mtime; /** * The time this file was last accessed, as a Windows timestamp. */ uint64_t atime; /** * The number of bytes written to the file. */ uint64_t bytes_written; } guac_rdp_fs_file; /** * A virtual filesystem implementing RDP-style operations. */ typedef struct guac_rdp_fs { /** * The Guacamole client associated with the RDP session. */ guac_client* client; /** * The root of the filesystem. */ char* drive_path; /** * The number of currently open files. */ int open_files; /** * Pool of file IDs. */ guac_pool* file_id_pool; /** * All available file structures. */ guac_rdp_fs_file files[GUAC_RDP_FS_MAX_FILES]; /** * If downloads from the remote server to the browser should be disabled. */ int disable_download; /** * If uploads from the browser to the remote server should be disabled. */ int disable_upload; } guac_rdp_fs; /** * Filesystem information structure. */ typedef struct guac_rdp_fs_info { /** * The number of free blocks available. */ int blocks_available; /** * The number of blocks in the filesystem. */ int blocks_total; /** * The number of bytes per block. */ int block_size; } guac_rdp_fs_info; /** * Allocates a new filesystem given a root path. This filesystem will behave * as if it were a network drive. * * @param client * The guac_client associated with the current RDP session. * * @param drive_path * The local directory to use as the root directory of the emulated * network drive. * * @param create_drive_path * Non-zero if the drive path specified should be automatically created if * it does not yet exist, zero otherwise. * * @param disable_download * Non-zero if downloads from the remote server to the local browser should * be disabled. * * @param disable_upload * Non-zero if uploads from the browser to the remote server should be * disabled. * * @return * The newly-allocated filesystem. */ guac_rdp_fs* guac_rdp_fs_alloc(guac_client* client, const char* drive_path, int create_drive_path, int disable_download, int disable_upload); /** * Frees the given filesystem. * * @param fs * The filesystem to free. */ void guac_rdp_fs_free(guac_rdp_fs* fs); /** * Creates and exposes a new filesystem guac_object to the given user, * providing access to the files within the given RDP filesystem. The * allocated guac_object must eventually be freed via guac_user_free_object(). * * @param fs * The RDP filesystem object to expose. * * @param user * The user that the RDP filesystem should be exposed to. * * @return * A new Guacamole filesystem object, configured to use RDP for uploading * and downloading files. */ guac_object* guac_rdp_fs_alloc_object(guac_rdp_fs* fs, guac_user* user); /** * Allocates a new filesystem guac_object for the given user, returning the * resulting guac_object. This function is provided for convenience, as it is * can be used as the callback for guac_client_foreach_user() or * guac_client_for_owner(). Note that this guac_object will be tracked * internally by libguac, will be provided to us in the parameters of handlers * related to that guac_object, and will automatically be freed when the * associated guac_user is freed, so the return value of this function can * safely be ignored. * * If either the given user or the given filesystem are NULL, then this * function has no effect. * * @param user * The use to expose the filesystem to, or NULL if nothing should be * exposed. * * @param data * A pointer to the guac_rdp_fs instance to expose to the given user, or * NULL if nothing should be exposed. * * @return * The guac_object allocated for the newly-exposed filesystem, or NULL if * no filesystem object could be allocated. */ void* guac_rdp_fs_expose(guac_user* user, void* data); /** * Converts the given relative path to an absolute path based on the given * parent path. If the path cannot be converted, non-zero is returned. * * @param parent * The parent directory of the relative path. * * @param rel_path * The relative path to convert. * * @return * Zero if the path was converted successfully, non-zero otherwise. */ int guac_rdp_fs_convert_path(const char* parent, const char* rel_path, char* abs_path); /** * Translates the given errno error code to a GUAC_RDP_FS error code. * * @param err * The error code, as returned within errno by a system call. * * @return * A GUAC_RDP_FS error code, such as GUAC_RDP_FS_ENFILE, * GUAC_RDP_FS_ENOENT, etc. */ int guac_rdp_fs_get_errorcode(int err); /** * Translates the given GUAC_RDP_FS error code to an RDPDR status code. * * @param err * A GUAC_RDP_FS error code, such as GUAC_RDP_FS_ENFILE, * GUAC_RDP_FS_ENOENT, etc. * * @return * A status code corresponding to the given error code that an * implementation of the RDPDR channel can understand. */ int guac_rdp_fs_get_status(int err); /** * Opens the given file, returning the a new file ID, or an error code less * than zero if an error occurs. The given path MUST be absolute, and will be * translated to be relative to the drive path of the simulated filesystem. * * @param fs * The filesystem to use when opening the file. * * @param path * The absolute path to the file within the simulated filesystem. * * @param access * A bitwise-OR of various RDPDR access flags, such as GENERIC_ALL or * GENERIC_WRITE. This value will ultimately be translated to a standard * O_RDWR, O_WRONLY, etc. value when opening the real file on the local * filesystem. * * @param file_attributes * The attributes to apply to the file, if created. This parameter is * currently ignored, and has no effect. * * @param create_disposition * Any one of several RDPDR file creation dispositions, such as * FILE_CREATE, FILE_OPEN_IF, etc. The creation disposition dictates * whether a new file should be created, whether the file can already * exist, whether existing contents should be truncated, etc. * * @param create_options * A bitwise-OR of various RDPDR options dictating how a file is to be * created. Currently only one option is implemented, FILE_DIRECTORY_FILE, * which specifies that the new file must be a directory. * * @return * A new file ID, which will always be a positive value, or an error code * if an error occurs. All error codes are negative values and correspond * to GUAC_RDP_FS constants, such as GUAC_RDP_FS_ENOENT. */ int guac_rdp_fs_open(guac_rdp_fs* fs, const char* path, int access, int file_attributes, int create_disposition, int create_options); /** * Reads up to the given length of bytes from the given offset within the * file having the given ID. Returns the number of bytes read, zero on EOF, * and an error code if an error occurs. * * @param fs * The filesystem containing the file from which data is to be read. * * @param file_id * The ID of the file to read data from, as returned by guac_rdp_fs_open(). * * @param offset * The byte offset within the file to start reading from. * * @param buffer * The buffer to fill with data from the file. * * @param length * The maximum number of bytes to read from the file. * * @return * The number of bytes actually read, zero on EOF, or an error code if an * error occurs. All error codes are negative values and correspond to * GUAC_RDP_FS constants, such as GUAC_RDP_FS_ENOENT. */ int guac_rdp_fs_read(guac_rdp_fs* fs, int file_id, uint64_t offset, void* buffer, int length); /** * Writes up to the given length of bytes from the given offset within the * file having the given ID. Returns the number of bytes written, and an * error code if an error occurs. * * @param fs * The filesystem containing the file to which data is to be written. * * @param file_id * The ID of the file to write data to, as returned by guac_rdp_fs_open(). * * @param offset * The byte offset within the file to start writinging at. * * @param buffer * The buffer containing the data to write. * * @param length * The maximum number of bytes to write to the file. * * @return * The number of bytes actually written, or an error code if an error * occurs. All error codes are negative values and correspond to * GUAC_RDP_FS constants, such as GUAC_RDP_FS_ENOENT. */ int guac_rdp_fs_write(guac_rdp_fs* fs, int file_id, uint64_t offset, void* buffer, int length); /** * Renames (moves) the file with the given ID to the new path specified. * Returns zero on success, or an error code if an error occurs. * * @param fs * The filesystem containing the file to rename. * * @param file_id * The ID of the file to rename, as returned by guac_rdp_fs_open(). * * @param new_path * The absolute path to move the file to. * * @return * Zero if the rename succeeded, or an error code if an error occurs. All * error codes are negative values and correspond to GUAC_RDP_FS constants, * such as GUAC_RDP_FS_ENOENT. */ int guac_rdp_fs_rename(guac_rdp_fs* fs, int file_id, const char* new_path); /** * Deletes the file with the given ID. * * @param fs * The filesystem containing the file to delete. * * @param file_id * The ID of the file to delete, as returned by guac_rdp_fs_open(). * * @return * Zero if deletion succeeded, or an error code if an error occurs. All * error codes are negative values and correspond to GUAC_RDP_FS constants, * such as GUAC_RDP_FS_ENOENT. */ int guac_rdp_fs_delete(guac_rdp_fs* fs, int file_id); /** * Truncates the file with the given ID to the given length (in bytes), which * may be larger. * * @param fs * The filesystem containing the file to truncate. * * @param file_id * The ID of the file to truncate, as returned by guac_rdp_fs_open(). * * @param length * The new length of the file, in bytes. Despite being named "truncate", * this new length may be larger. * * @return * Zero if truncation succeeded, or an error code if an error occurs. All * error codes are negative values and correspond to GUAC_RDP_FS constants, * such as GUAC_RDP_FS_ENOENT. */ int guac_rdp_fs_truncate(guac_rdp_fs* fs, int file_id, int length); /** * Frees the given file ID, allowing future open operations to reuse it. * * @param fs * The filesystem containing the file to close. * * @param file_id * The ID of the file to close, as returned by guac_rdp_fs_open(). */ void guac_rdp_fs_close(guac_rdp_fs* fs, int file_id); /** * Given an arbitrary path, returns a pointer to the first character following * the last path separator in the path (the basename of the path). For example, * given "/foo/bar/baz" or "\foo\bar\baz", this function would return a pointer * to "baz". * * @param path * The path to determine the basename of. * * @return * A pointer to the first character of the basename within the path. */ const char* guac_rdp_fs_basename(const char* path); /** * Given an arbitrary path, which may contain ".." and ".", creates an * absolute path which does NOT contain ".." or ".". The given path MUST * be absolute. * * @param path * The absolute path to normalize. * * @param abs_path * The buffer to populate with the normalized path. The normalized path * will not contain relative path components like ".." or ".". * * @return * Zero if normalization succeeded, non-zero otherwise. */ int guac_rdp_fs_normalize_path(const char* path, char* abs_path); /** * Given a parent path and a relative path, produces a normalized absolute * path. * * @param parent * The absolute path of the parent directory of the relative path. * * @param rel_path * The relative path to convert. * * @param abs_path * The buffer to populate with the absolute, normalized path. The * normalized path will not contain relative path components like ".." or * ".". * * @return * Zero if conversion succeeded, non-zero otherwise. */ int guac_rdp_fs_convert_path(const char* parent, const char* rel_path, char* abs_path); /** * Returns the next filename within the directory having the given file ID, * or NULL if no more files. * * @param fs * The filesystem containing the file to read directory entries from. * * @param file_id * The ID of the file to read directory entries from, as returned by * guac_rdp_fs_open(). * * @return * The name of the next filename within the directory, or NULL if the last * file in the directory has already been returned by a previous call. */ const char* guac_rdp_fs_read_dir(guac_rdp_fs* fs, int file_id); /** * Returns the file having the given ID, or NULL if no such file exists. * * @param fs * The filesystem containing the desired file. * * @param file_id * The ID of the desired, as returned by guac_rdp_fs_open(). * * @return * The file having the given ID, or NULL is no such file exists. */ guac_rdp_fs_file* guac_rdp_fs_get_file(guac_rdp_fs* fs, int file_id); /** * Returns whether the given filename matches the given pattern. The pattern * given is a shell wildcard pattern as accepted by the POSIX fnmatch() * function. Backslashes will be interpreted as literal backslashes, not * escape characters. * * @param filename * The filename to check * * @param pattern * The pattern to check the filename against. * * @return * Non-zero if the pattern matches, zero otherwise. */ int guac_rdp_fs_matches(const char* filename, const char* pattern); /** * Populates the given structure with information about the filesystem, * particularly the amount of space available. * * @param fs * The filesystem to obtain information from. * * @param info * The guac_rdp_fs_info structure to populate. * * @return * Zero if information retrieval succeeded, or an error code if an error * occurs. All error codes are negative values and correspond to * GUAC_RDP_FS constants, such as GUAC_RDP_FS_ENOENT. */ int guac_rdp_fs_get_info(guac_rdp_fs* fs, guac_rdp_fs_info* info); /** * Concatenates the given filename with the given path, separating the two * with a single forward slash. The full result must be no more than * GUAC_RDP_FS_MAX_PATH bytes long, counting null terminator. * * @param fullpath * The buffer to store the result within. This buffer must be at least * GUAC_RDP_FS_MAX_PATH bytes long. * * @param path * The path to append the filename to. * * @param filename * The filename to append to the path. * * @return * Non-zero if the filename is valid and was successfully appended to the * path, zero otherwise. */ int guac_rdp_fs_append_filename(char* fullpath, const char* path, const char* filename); #endif guacamole-server-1.3.0/src/protocols/rdp/settings.h0000644000175100001440000004262513770536337017332 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_SETTINGS_H #define GUAC_RDP_SETTINGS_H #include "config.h" #include "keymap.h" #include #include #include /** * The maximum number of bytes in the client hostname claimed during * connection. */ #define RDP_CLIENT_HOSTNAME_SIZE 32 /** * The default RDP port. */ #define RDP_DEFAULT_PORT 3389 /** * The default RDP port used by Hyper-V "VMConnect". */ #define RDP_DEFAULT_VMCONNECT_PORT 2179 /** * Default screen width, in pixels. */ #define RDP_DEFAULT_WIDTH 1024 /** * Default screen height, in pixels. */ #define RDP_DEFAULT_HEIGHT 768 /** * Default color depth, in bits. */ #define RDP_DEFAULT_DEPTH 16 /** * The filename to use for the screen recording, if not specified. */ #define GUAC_RDP_DEFAULT_RECORDING_NAME "recording" /** * The number of entries contained within the OrderSupport BYTE array * referenced by the rdpSettings structure. This value is defined by the RDP * negotiation process (there are 32 bytes available within the order * negotiation field sent during the connection handshake) and is hard-coded * within FreeRDP. There is no public constant for this value defined within * the FreeRDP headers. */ #define GUAC_RDP_ORDER_SUPPORT_LENGTH 32 /** * All supported combinations of security types. */ typedef enum guac_rdp_security { /** * Legacy RDP encryption. */ GUAC_SECURITY_RDP, /** * TLS encryption. */ GUAC_SECURITY_TLS, /** * Network level authentication. */ GUAC_SECURITY_NLA, /** * Extended network level authentication. */ GUAC_SECURITY_EXTENDED_NLA, /** * Negotiate security methods supported by Hyper-V's "VMConnect" feature. */ GUAC_SECURITY_VMCONNECT, /** * Negotiate a security method supported by both server and client. */ GUAC_SECURITY_ANY } guac_rdp_security; /** * All supported combinations screen resize methods. */ typedef enum guac_rdp_resize_method { /** * Dynamic resizing of the display will not be attempted. */ GUAC_RESIZE_NONE, /** * Dynamic resizing will be attempted through sending requests along the * Display Update channel. This will only work with recent versions of * Windows and relatively-recent versions of FreeRDP. */ GUAC_RESIZE_DISPLAY_UPDATE, /** * Guacamole will automatically disconnect and reconnect to the RDP server * whenever the screen size changes, requesting the new size during * reconnect. */ GUAC_RESIZE_RECONNECT } guac_rdp_resize_method; /** * All settings supported by the Guacamole RDP client. */ typedef struct guac_rdp_settings { /** * The hostname to connect to. */ char* hostname; /** * The port to connect to. */ int port; /** * The domain of the user logging in. */ char* domain; /** * The username of the user logging in. */ char* username; /** * The password of the user logging in. */ char* password; /** * Whether this connection is read-only, and user input should be dropped. */ int read_only; /** * The color depth of the display to request, in bits. */ int color_depth; /** * The width of the display to request, in pixels. */ int width; /** * The height of the display to request, in pixels. */ int height; /** * The DPI of the remote display to assume when converting between * client pixels and remote pixels. */ int resolution; /** * Whether audio is enabled. */ int audio_enabled; /** * Whether printing is enabled. */ int printing_enabled; /** * Name of the redirected printer. */ char* printer_name; /** * Whether the virtual drive is enabled. */ int drive_enabled; /** * The name of the virtual drive to pass through to the RDP connection. */ char* drive_name; /** * The local system path which will be used to persist the * virtual drive. */ char* drive_path; /** * Whether to automatically create the local system path if it does not * exist. */ int create_drive_path; /** * Whether or not to disable file download over RDP. */ int disable_download; /** * Wether or not to disable file upload over RDP. */ int disable_upload; /** * Whether this session is a console session. */ int console; /** * Whether to allow audio in the console session. */ int console_audio; /** * The keymap chosen as the layout of the server. */ const guac_rdp_keymap* server_layout; /** * The initial program to run, if any. */ char* initial_program; /** * The name of the client to submit to the RDP server upon connection, or * NULL if the name is not specified. */ char* client_name; /** * The type of security to use for the connection. */ guac_rdp_security security_mode; /** * Whether bad server certificates should be ignored. */ int ignore_certificate; /** * Whether authentication should be disabled. This is different from the * authentication that takes place when a user provides their username * and password. Authentication is required by definition for NLA. */ int disable_authentication; /** * The application to launch, if RemoteApp is in use. */ char* remote_app; /** * The working directory of the remote application, if RemoteApp is in use. */ char* remote_app_dir; /** * The arguments to pass to the remote application, if RemoteApp is in use. */ char* remote_app_args; /** * NULL-terminated list of all static virtual channel names, or NULL if * no channels whatsoever. */ char** svc_names; /** * Whether outbound clipboard access should be blocked. If set, it will not * be possible to copy data from the remote desktop to the client using the * clipboard. */ int disable_copy; /** * Whether inbound clipboard access should be blocked. If set, it will not * be possible to paste data from the client to the remote desktop using * the clipboard. */ int disable_paste; /** * Whether the desktop wallpaper should be visible. If unset, the desktop * wallpaper will be hidden, reducing the amount of bandwidth required. */ int wallpaper_enabled; /** * Whether desktop and window theming should be allowed. If unset, theming * is temporarily disabled on the desktop of the RDP server for the sake of * performance, reducing the amount of bandwidth required. */ int theming_enabled; /** * Whether glyphs should be smoothed with antialiasing (ClearType). If * unset, glyphs will be rendered with sharp edges and using single colors, * effectively 1-bit images, reducing the amount of bandwidth required. */ int font_smoothing_enabled; /** * Whether windows contents should be shown as they are moved. If unset, * only a window border will be shown during window move operations, * reducing the amount of bandwidth required. */ int full_window_drag_enabled; /** * Whether desktop composition (Aero) should be enabled during the session. * As desktop composition provides alpha blending and other special * effects, this increases the amount of bandwidth used. If unset, desktop * composition will be disabled. */ int desktop_composition_enabled; /** * Whether menu animations should be shown. If unset, menus will not be * animated, reducing the amount of bandwidth required. */ int menu_animations_enabled; /** * Whether bitmap caching should be disabled. By default it is * enabled - this allows users to explicitly disable it. */ int disable_bitmap_caching; /** * Whether offscreen caching should be disabled. By default it is * enabled - this allows users to explicitly disable it. */ int disable_offscreen_caching; /** * Whether glyph caching should be disabled. By default it is enabled * - this allows users to explicitly disable it. */ int disable_glyph_caching; /** * The preconnection ID to send within the preconnection PDU when * initiating an RDP connection, if any. If no preconnection ID is * specified, this will be -1. */ int preconnection_id; /** * The preconnection BLOB (PCB) to send to the RDP server prior to full RDP * connection negotiation. This value is used by Hyper-V to select the * destination VM. */ char* preconnection_blob; /** * The timezone to pass through to the RDP connection. */ char* timezone; #ifdef ENABLE_COMMON_SSH /** * Whether SFTP should be enabled for the RDP connection. */ int enable_sftp; /** * The hostname of the SSH server to connect to for SFTP. */ char* sftp_hostname; /** * The public SSH host key. */ char* sftp_host_key; /** * The port of the SSH server to connect to for SFTP. */ char* sftp_port; /** * The username to provide when authenticating with the SSH server for * SFTP. */ char* sftp_username; /** * The password to provide when authenticating with the SSH server for * SFTP (if not using a private key). */ char* sftp_password; /** * The base64-encoded private key to use when authenticating with the SSH * server for SFTP (if not using a password). */ char* sftp_private_key; /** * The passphrase to use to decrypt the provided base64-encoded private * key. */ char* sftp_passphrase; /** * The default location for file uploads within the SSH server. This will * apply only to uploads which do not use the filesystem guac_object (where * the destination directory is otherwise ambiguous). */ char* sftp_directory; /** * The path of the directory within the SSH server to expose as a * filesystem guac_object. */ char* sftp_root_directory; /** * The interval at which SSH keepalive messages are sent to the server for * SFTP connections. The default is 0 (disabling keepalives), and a value * of 1 is automatically increased to 2 by libssh2 to avoid busy loop corner * cases. */ int sftp_server_alive_interval; /** * Whether or not to disable file download over SFTP. */ int sftp_disable_download; /** * Whether or not to disable file upload over SFTP. */ int sftp_disable_upload; #endif /** * The path in which the screen recording should be saved, if enabled. If * no screen recording should be saved, this will be NULL. */ char* recording_path; /** * The filename to use for the screen recording, if enabled. */ char* recording_name; /** * Whether the screen recording path should be automatically created if it * does not already exist. */ int create_recording_path; /** * Non-zero if output which is broadcast to each connected client * (graphics, streams, etc.) should NOT be included in the session * recording, zero otherwise. Output is included by default, as it is * necessary for any recording which must later be viewable as video. */ int recording_exclude_output; /** * Non-zero if changes to mouse state, such as position and buttons pressed * or released, should NOT be included in the session recording, zero * otherwise. Mouse state is included by default, as it is necessary for * the mouse cursor to be rendered in any resulting video. */ int recording_exclude_mouse; /** * Non-zero if keys pressed and released should be included in the session * recording, zero otherwise. Key events are NOT included by default within * the recording, as doing so has privacy and security implications. * Including key events may be necessary in certain auditing contexts, but * should only be done with caution. Key events can easily contain * sensitive information, such as passwords, credit card numbers, etc. */ int recording_include_keys; /** * The method to apply when the user's display changes size. */ guac_rdp_resize_method resize_method; /** * Whether audio input (microphone) is enabled. */ int enable_audio_input; /** * The hostname of the remote desktop gateway that should be used as an * intermediary for the remote desktop connection. If no gateway should * be used, this will be NULL. */ char* gateway_hostname; /** * The port of the remote desktop gateway that should be used as an * intermediary for the remote desktop connection. NOTE: versions of * FreeRDP prior to 1.2 which have gateway support ignore this value, and * instead use a hard-coded value of 443. */ int gateway_port; /** * The domain of the user authenticating with the remote desktop gateway, * if a gateway is being used. This is not necessarily the same as the * user actually using the remote desktop connection. */ char* gateway_domain; /** * The username of the user authenticating with the remote desktop gateway, * if a gateway is being used. This is not necessarily the same as the * user actually using the remote desktop connection. */ char* gateway_username; /** * The password to provide when authenticating with the remote desktop * gateway, if a gateway is being used. */ char* gateway_password; /** * The load balancing information/cookie which should be provided to * the connection broker, if a connection broker is being used. */ char* load_balance_info; /** * Whether or not to send a magic WoL packet to wake up the host before * trying to connect. Zero will disable sending the packet, non-zero * values will trigger sending the packet. */ int wol_send_packet; /** * The mac address to put in the magic WoL packet. */ char* wol_mac_addr; /** * The broadcast address to send the magic WoL packet to. */ char* wol_broadcast_addr; /** * The amount of time to wait after sending the magic WoL packet before * continuing the connection. */ int wol_wait_time; } guac_rdp_settings; /** * Parses all given args, storing them in a newly-allocated settings object. If * the args fail to parse, NULL is returned. * * @param user * The user who submitted the given arguments while joining the * connection. * * @param argc * The number of arguments within the argv array. * * @param argv * The values of all arguments provided by the user. * * @return * A newly-allocated settings object which must be freed with * guac_rdp_settings_free() when no longer needed. If the arguments fail * to parse, NULL is returned. */ guac_rdp_settings* guac_rdp_parse_args(guac_user* user, int argc, const char** argv); /** * Frees the given guac_rdp_settings object, having been previously allocated * via guac_rdp_parse_args(). * * @param settings * The settings object to free. */ void guac_rdp_settings_free(guac_rdp_settings* settings); /** * NULL-terminated array of accepted client args. */ extern const char* GUAC_RDP_CLIENT_ARGS[]; /** * Save all given settings to the given freerdp instance. * * @param client * The guac_client object providing the settings. * * @param guac_settings * The guac_rdp_settings object to save. * * @param rdp * The RDP instance to save settings to. */ void guac_rdp_push_settings(guac_client* client, guac_rdp_settings* guac_settings, freerdp* rdp); /** * Returns the width of the RDP session display. * * @param rdp * The RDP instance to retrieve the width from. * * @return * The current width of the RDP display, in pixels. */ int guac_rdp_get_width(freerdp* rdp); /** * Returns the height of the RDP session display. * * @param rdp * The RDP instance to retrieve the height from. * * @return * The current height of the RDP display, in pixels. */ int guac_rdp_get_height(freerdp* rdp); /** * Returns the depth of the RDP session display. * * @param rdp * The RDP instance to retrieve the depth from. * * @return * The current depth of the RDP display, in bits per pixel. */ int guac_rdp_get_depth(freerdp* rdp); #endif guacamole-server-1.3.0/src/protocols/rdp/ls.c0000644000175100001440000000753513764613616016103 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "fs.h" #include "ls.h" #include #include #include #include #include #include #include #include #include int guac_rdp_ls_ack_handler(guac_user* user, guac_stream* stream, char* message, guac_protocol_status status) { int blob_written = 0; const char* filename; guac_rdp_ls_status* ls_status = (guac_rdp_ls_status*) stream->data; /* If unsuccessful, free stream and abort */ if (status != GUAC_PROTOCOL_STATUS_SUCCESS) { guac_rdp_fs_close(ls_status->fs, ls_status->file_id); guac_user_free_stream(user, stream); free(ls_status); return 0; } /* While directory entries remain */ while ((filename = guac_rdp_fs_read_dir(ls_status->fs, ls_status->file_id)) != NULL && !blob_written) { char absolute_path[GUAC_RDP_FS_MAX_PATH]; /* Skip current and parent directory entries */ if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; /* Concatenate into absolute path - skip if invalid */ if (!guac_rdp_fs_append_filename(absolute_path, ls_status->directory_name, filename)) { guac_user_log(user, GUAC_LOG_DEBUG, "Skipping filename \"%s\" - filename is invalid or " "resulting path is too long", filename); continue; } /* Attempt to open file to determine type */ int file_id = guac_rdp_fs_open(ls_status->fs, absolute_path, GENERIC_READ, 0, FILE_OPEN, 0); if (file_id < 0) continue; /* Get opened file */ guac_rdp_fs_file* file = guac_rdp_fs_get_file(ls_status->fs, file_id); if (file == NULL) { guac_user_log(user, GUAC_LOG_DEBUG, "%s: Successful open produced " "bad file_id: %i", __func__, file_id); return 0; } /* Determine mimetype */ const char* mimetype; if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) mimetype = GUAC_USER_STREAM_INDEX_MIMETYPE; else mimetype = "application/octet-stream"; /* Write entry */ blob_written |= guac_common_json_write_property(user, stream, &ls_status->json_state, absolute_path, mimetype); guac_rdp_fs_close(ls_status->fs, file_id); } /* Complete JSON and cleanup at end of directory */ if (filename == NULL) { /* Complete JSON object */ guac_common_json_end_object(user, stream, &ls_status->json_state); guac_common_json_flush(user, stream, &ls_status->json_state); /* Clean up resources */ guac_rdp_fs_close(ls_status->fs, ls_status->file_id); free(ls_status); /* Signal of stream */ guac_protocol_send_end(user->socket, stream); guac_user_free_stream(user, stream); } guac_socket_flush(user->socket); return 0; } guacamole-server-1.3.0/src/protocols/rdp/settings.c0000644000175100001440000013770013770536337017324 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "argv.h" #include "common/defaults.h" #include "common/string.h" #include "config.h" #include "resolution.h" #include "settings.h" #include #include #include #include #include #include #include #include #include #include #include #include #include /* Client plugin arguments */ const char* GUAC_RDP_CLIENT_ARGS[] = { "hostname", "port", GUAC_RDP_ARGV_DOMAIN, GUAC_RDP_ARGV_USERNAME, GUAC_RDP_ARGV_PASSWORD, "width", "height", "dpi", "initial-program", "color-depth", "disable-audio", "enable-printing", "printer-name", "enable-drive", "drive-name", "drive-path", "create-drive-path", "disable-download", "disable-upload", "console", "console-audio", "server-layout", "security", "ignore-cert", "disable-auth", "remote-app", "remote-app-dir", "remote-app-args", "static-channels", "client-name", "enable-wallpaper", "enable-theming", "enable-font-smoothing", "enable-full-window-drag", "enable-desktop-composition", "enable-menu-animations", "disable-bitmap-caching", "disable-offscreen-caching", "disable-glyph-caching", "preconnection-id", "preconnection-blob", "timezone", #ifdef ENABLE_COMMON_SSH "enable-sftp", "sftp-hostname", "sftp-host-key", "sftp-port", "sftp-username", "sftp-password", "sftp-private-key", "sftp-passphrase", "sftp-directory", "sftp-root-directory", "sftp-server-alive-interval", "sftp-disable-download", "sftp-disable-upload", #endif "recording-path", "recording-name", "recording-exclude-output", "recording-exclude-mouse", "recording-include-keys", "create-recording-path", "resize-method", "enable-audio-input", "read-only", "gateway-hostname", "gateway-port", "gateway-domain", "gateway-username", "gateway-password", "load-balance-info", "disable-copy", "disable-paste", "wol-send-packet", "wol-mac-addr", "wol-broadcast-addr", "wol-wait-time", NULL }; enum RDP_ARGS_IDX { /** * The hostname to connect to. */ IDX_HOSTNAME, /** * The port to connect to. If omitted, the default RDP port of 3389 will be * used. */ IDX_PORT, /** * The domain of the user logging in. */ IDX_DOMAIN, /** * The username of the user logging in. */ IDX_USERNAME, /** * The password of the user logging in. */ IDX_PASSWORD, /** * The width of the display to request, in pixels. If omitted, a reasonable * value will be calculated based on the user's own display size and * resolution. */ IDX_WIDTH, /** * The height of the display to request, in pixels. If omitted, a * reasonable value will be calculated based on the user's own display * size and resolution. */ IDX_HEIGHT, /** * The resolution of the display to request, in DPI. If omitted, a * reasonable value will be calculated based on the user's own display * size and resolution. */ IDX_DPI, /** * The initial program to run, if any. */ IDX_INITIAL_PROGRAM, /** * The color depth of the display to request, in bits. */ IDX_COLOR_DEPTH, /** * "true" if audio should be disabled, "false" or blank to leave audio * enabled. */ IDX_DISABLE_AUDIO, /** * "true" if printing should be enabled, "false" or blank otherwise. */ IDX_ENABLE_PRINTING, /** * The name of the printer that will be passed through to the RDP server. */ IDX_PRINTER_NAME, /** * "true" if the virtual drive should be enabled, "false" or blank * otherwise. */ IDX_ENABLE_DRIVE, /** * The name of the virtual driver that will be passed through to the * RDP connection. */ IDX_DRIVE_NAME, /** * The local system path which will be used to persist the * virtual drive. This must be specified if the virtual drive is enabled. */ IDX_DRIVE_PATH, /** * "true" to automatically create the local system path used by the virtual * drive if it does not yet exist, "false" or blank otherwise. */ IDX_CREATE_DRIVE_PATH, /** * "true" to disable the ability to download files from a remote server to * the local client over RDP, "false" or blank otherwise. */ IDX_DISABLE_DOWNLOAD, /** * "true" to disable the ability to upload files from the local client to * the remote server over RDP, "false" or blank otherwise. */ IDX_DISABLE_UPLOAD, /** * "true" if this session is a console session, "false" or blank otherwise. */ IDX_CONSOLE, /** * "true" if audio should be allowed in console sessions, "false" or blank * otherwise. */ IDX_CONSOLE_AUDIO, /** * The name of the keymap chosen as the layout of the server. Legal names * are defined within the *.keymap files in the "keymaps" directory of the * source for Guacamole's RDP support. */ IDX_SERVER_LAYOUT, /** * The type of security to use for the connection. Valid values are "rdp", * "tls", "nla", "nla-ext", "vmconnect", or "any". By default, the security * mode is negotiated ("any"). */ IDX_SECURITY, /** * "true" if validity of the RDP server's certificate should be ignored, * "false" or blank if invalid certificates should result in a failure to * connect. */ IDX_IGNORE_CERT, /** * "true" if authentication should be disabled, "false" or blank otherwise. * This is different from the authentication that takes place when a user * provides their username and password. Authentication is required by * definition for NLA. */ IDX_DISABLE_AUTH, /** * The application to launch, if RemoteApp is in use. */ IDX_REMOTE_APP, /** * The working directory of the remote application, if RemoteApp is in use. */ IDX_REMOTE_APP_DIR, /** * The arguments to pass to the remote application, if RemoteApp is in use. */ IDX_REMOTE_APP_ARGS, /** * Comma-separated list of the names of all static virtual channels that * should be connected to and exposed as Guacamole pipe streams, or blank * if no static virtual channels should be used. */ IDX_STATIC_CHANNELS, /** * The name of the client to submit to the RDP server upon connection. */ IDX_CLIENT_NAME, /** * "true" if the desktop wallpaper should be visible, "false" or blank if * the desktop wallpaper should be hidden. */ IDX_ENABLE_WALLPAPER, /** * "true" if desktop and window theming should be allowed, "false" or blank * if theming should be temporarily disabled on the desktop of the RDP * server for the sake of performance. */ IDX_ENABLE_THEMING, /** * "true" if glyphs should be smoothed with antialiasing (ClearType), * "false" or blank if glyphs should be rendered with sharp edges and using * single colors, effectively 1-bit images. */ IDX_ENABLE_FONT_SMOOTHING, /** * "true" if windows' contents should be shown as they are moved, "false" * or blank if only a window border should be shown during window move * operations. */ IDX_ENABLE_FULL_WINDOW_DRAG, /** * "true" if desktop composition (Aero) should be enabled during the * session, "false" or blank otherwise. As desktop composition provides * alpha blending and other special effects, this increases the amount of * bandwidth used. */ IDX_ENABLE_DESKTOP_COMPOSITION, /** * "true" if menu animations should be shown, "false" or blank menus should * not be animated. */ IDX_ENABLE_MENU_ANIMATIONS, /** * "true" if bitmap caching should be disabled, "false" if bitmap caching * should remain enabled. */ IDX_DISABLE_BITMAP_CACHING, /** * "true" if the offscreen caching should be disabled, false if offscren * caching should remain enabled. */ IDX_DISABLE_OFFSCREEN_CACHING, /** * "true" if glyph caching should be disabled, false if glyph caching should * remain enabled. */ IDX_DISABLE_GLYPH_CACHING, /** * The preconnection ID to send within the preconnection PDU when * initiating an RDP connection, if any. */ IDX_PRECONNECTION_ID, /** * The preconnection BLOB (PCB) to send to the RDP server prior to full RDP * connection negotiation. This value is used by Hyper-V to select the * destination VM. */ IDX_PRECONNECTION_BLOB, /** * The timezone to pass through to the RDP connection, in IANA format, which * will be translated into Windows formats. See the following page for * information and list of valid values: * https://en.wikipedia.org/wiki/List_of_tz_database_time_zones */ IDX_TIMEZONE, #ifdef ENABLE_COMMON_SSH /** * "true" if SFTP should be enabled for the RDP connection, "false" or * blank otherwise. */ IDX_ENABLE_SFTP, /** * The hostname of the SSH server to connect to for SFTP. If blank, the * hostname of the RDP server will be used. */ IDX_SFTP_HOSTNAME, /** * The public SSH host key of the SFTP server. Optional. */ IDX_SFTP_HOST_KEY, /** * The port of the SSH server to connect to for SFTP. If blank, the default * SSH port of "22" will be used. */ IDX_SFTP_PORT, /** * The username to provide when authenticating with the SSH server for * SFTP. If blank, the username provided for the RDP user will be used. */ IDX_SFTP_USERNAME, /** * The password to provide when authenticating with the SSH server for * SFTP (if not using a private key). */ IDX_SFTP_PASSWORD, /** * The base64-encoded private key to use when authenticating with the SSH * server for SFTP (if not using a password). */ IDX_SFTP_PRIVATE_KEY, /** * The passphrase to use to decrypt the provided base64-encoded private * key. */ IDX_SFTP_PASSPHRASE, /** * The default location for file uploads within the SSH server. This will * apply only to uploads which do not use the filesystem guac_object (where * the destination directory is otherwise ambiguous). */ IDX_SFTP_DIRECTORY, /** * The path of the directory within the SSH server to expose as a * filesystem guac_object. If omitted, "/" will be used by default. */ IDX_SFTP_ROOT_DIRECTORY, /** * The interval at which SSH keepalive messages are sent to the server for * SFTP connections. The default is 0 (disabling keepalives), and a value * of 1 is automatically increased to 2 by libssh2 to avoid busy loop corner * cases. */ IDX_SFTP_SERVER_ALIVE_INTERVAL, /** * "true" to disable file download from the SFTP server to the local client * over the SFTP connection, if SFTP is configured and enabled. "false" or * blank otherwise. */ IDX_SFTP_DISABLE_DOWNLOAD, /** * "true" to disable file upload from the SFTP server to the local client * over the SFTP connection, if SFTP is configured and enabled. "false" or * blank otherwise. */ IDX_SFTP_DISABLE_UPLOAD, #endif /** * The full absolute path to the directory in which screen recordings * should be written. */ IDX_RECORDING_PATH, /** * The name that should be given to screen recordings which are written in * the given path. */ IDX_RECORDING_NAME, /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output * is included by default, as it is necessary for any recording which must * later be viewable as video. */ IDX_RECORDING_EXCLUDE_OUTPUT, /** * Whether changes to mouse state, such as position and buttons pressed or * released, should NOT be included in the session recording. Mouse state * is included by default, as it is necessary for the mouse cursor to be * rendered in any resulting video. */ IDX_RECORDING_EXCLUDE_MOUSE, /** * Whether keys pressed and released should be included in the session * recording. Key events are NOT included by default within the recording, * as doing so has privacy and security implications. Including key events * may be necessary in certain auditing contexts, but should only be done * with caution. Key events can easily contain sensitive information, such * as passwords, credit card numbers, etc. */ IDX_RECORDING_INCLUDE_KEYS, /** * Whether the specified screen recording path should automatically be * created if it does not yet exist. */ IDX_CREATE_RECORDING_PATH, /** * The method to use to apply screen size changes requested by the user. * Valid values are blank, "display-update", and "reconnect". */ IDX_RESIZE_METHOD, /** * "true" if audio input (microphone) should be enabled for the RDP * connection, "false" or blank otherwise. */ IDX_ENABLE_AUDIO_INPUT, /** * "true" if this connection should be read-only (user input should be * dropped), "false" or blank otherwise. */ IDX_READ_ONLY, /** * The hostname of the remote desktop gateway that should be used as an * intermediary for the remote desktop connection. If omitted, a gateway * will not be used. */ IDX_GATEWAY_HOSTNAME, /** * The port of the remote desktop gateway that should be used as an * intermediary for the remote desktop connection. By default, this will be * 443. * * NOTE: If using a version of FreeRDP prior to 1.2, this setting has no * effect. FreeRDP instead uses a hard-coded value of 443. */ IDX_GATEWAY_PORT, /** * The domain of the user authenticating with the remote desktop gateway, * if a gateway is being used. This is not necessarily the same as the * user actually using the remote desktop connection. */ IDX_GATEWAY_DOMAIN, /** * The username of the user authenticating with the remote desktop gateway, * if a gateway is being used. This is not necessarily the same as the * user actually using the remote desktop connection. */ IDX_GATEWAY_USERNAME, /** * The password to provide when authenticating with the remote desktop * gateway, if a gateway is being used. */ IDX_GATEWAY_PASSWORD, /** * The load balancing information/cookie which should be provided to * the connection broker, if a connection broker is being used. */ IDX_LOAD_BALANCE_INFO, /** * Whether outbound clipboard access should be blocked. If set to "true", * it will not be possible to copy data from the remote desktop to the * client using the clipboard. By default, clipboard access is not blocked. */ IDX_DISABLE_COPY, /** * Whether inbound clipboard access should be blocked. If set to "true", it * will not be possible to paste data from the client to the remote desktop * using the clipboard. By default, clipboard access is not blocked. */ IDX_DISABLE_PASTE, /** * Whether or not to send the magic Wake-on-LAN (WoL) packet to the host * prior to attempting to connect. Non-zero values will enable sending * the WoL packet, while zero will disable this functionality. By default * the WoL packet is not sent. */ IDX_WOL_SEND_PACKET, /** * The MAC address to put in the magic WoL packet for the host that should * be woken up. */ IDX_WOL_MAC_ADDR, /** * The broadcast address to which to send the magic WoL packet to wake up * the remote host. */ IDX_WOL_BROADCAST_ADDR, /** * The amount of time, in seconds, to wait after sending the WoL packet * before attempting to connect to the host. This should be a reasonable * amount of time to allow the remote host to fully boot and respond to * network connection requests. The default is not to wait at all * (0 seconds). */ IDX_WOL_WAIT_TIME, RDP_ARGS_COUNT }; guac_rdp_settings* guac_rdp_parse_args(guac_user* user, int argc, const char** argv) { /* Validate arg count */ if (argc != RDP_ARGS_COUNT) { guac_user_log(user, GUAC_LOG_WARNING, "Incorrect number of connection " "parameters provided: expected %i, got %i.", RDP_ARGS_COUNT, argc); return NULL; } guac_rdp_settings* settings = calloc(1, sizeof(guac_rdp_settings)); /* Use console */ settings->console = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_CONSOLE, 0); /* Enable/disable console audio */ settings->console_audio = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_CONSOLE_AUDIO, 0); /* Ignore SSL/TLS certificate */ settings->ignore_certificate = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_IGNORE_CERT, 0); /* Disable authentication */ settings->disable_authentication = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DISABLE_AUTH, 0); /* NLA security */ if (strcmp(argv[IDX_SECURITY], "nla") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Security mode: NLA"); settings->security_mode = GUAC_SECURITY_NLA; } /* Extended NLA security */ else if (strcmp(argv[IDX_SECURITY], "nla-ext") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Security mode: Extended NLA"); settings->security_mode = GUAC_SECURITY_EXTENDED_NLA; } /* TLS security */ else if (strcmp(argv[IDX_SECURITY], "tls") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Security mode: TLS"); settings->security_mode = GUAC_SECURITY_TLS; } /* RDP security */ else if (strcmp(argv[IDX_SECURITY], "rdp") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Security mode: RDP"); settings->security_mode = GUAC_SECURITY_RDP; } /* Negotiate security supported by VMConnect */ else if (strcmp(argv[IDX_SECURITY], "vmconnect") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Security mode: Hyper-V / VMConnect"); settings->security_mode = GUAC_SECURITY_VMCONNECT; } /* Negotiate security (allow server to choose) */ else if (strcmp(argv[IDX_SECURITY], "any") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Security mode: Negotiate (ANY)"); settings->security_mode = GUAC_SECURITY_ANY; } /* If nothing given, default to RDP */ else { guac_user_log(user, GUAC_LOG_INFO, "No security mode specified. Defaulting to security mode negotiation with server."); settings->security_mode = GUAC_SECURITY_ANY; } /* Set hostname */ settings->hostname = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_HOSTNAME, ""); /* If port specified, use it, otherwise use an appropriate default */ settings->port = guac_user_parse_args_int(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_PORT, settings->security_mode == GUAC_SECURITY_VMCONNECT ? RDP_DEFAULT_VMCONNECT_PORT : RDP_DEFAULT_PORT); guac_user_log(user, GUAC_LOG_DEBUG, "User resolution is %ix%i at %i DPI", user->info.optimal_width, user->info.optimal_height, user->info.optimal_resolution); /* Use suggested resolution unless overridden */ settings->resolution = guac_user_parse_args_int(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DPI, guac_rdp_suggest_resolution(user)); /* Use optimal width unless overridden */ settings->width = user->info.optimal_width * settings->resolution / user->info.optimal_resolution; if (argv[IDX_WIDTH][0] != '\0') settings->width = atoi(argv[IDX_WIDTH]); /* Use default width if given width is invalid. */ if (settings->width <= 0) { settings->width = RDP_DEFAULT_WIDTH; guac_user_log(user, GUAC_LOG_ERROR, "Invalid width: \"%s\". Using default of %i.", argv[IDX_WIDTH], settings->width); } /* Round width down to nearest multiple of 4 */ settings->width = settings->width & ~0x3; /* Use optimal height unless overridden */ settings->height = user->info.optimal_height * settings->resolution / user->info.optimal_resolution; if (argv[IDX_HEIGHT][0] != '\0') settings->height = atoi(argv[IDX_HEIGHT]); /* Use default height if given height is invalid. */ if (settings->height <= 0) { settings->height = RDP_DEFAULT_HEIGHT; guac_user_log(user, GUAC_LOG_ERROR, "Invalid height: \"%s\". Using default of %i.", argv[IDX_WIDTH], settings->height); } guac_user_log(user, GUAC_LOG_DEBUG, "Using resolution of %ix%i at %i DPI", settings->width, settings->height, settings->resolution); /* Domain */ settings->domain = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DOMAIN, NULL); /* Username */ settings->username = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_USERNAME, NULL); /* Password */ settings->password = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_PASSWORD, NULL); /* Read-only mode */ settings->read_only = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_READ_ONLY, 0); /* Client name */ settings->client_name = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_CLIENT_NAME, "Guacamole RDP"); /* Initial program */ settings->initial_program = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_INITIAL_PROGRAM, NULL); /* RemoteApp program */ settings->remote_app = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_REMOTE_APP, NULL); /* RemoteApp working directory */ settings->remote_app_dir = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_REMOTE_APP_DIR, NULL); /* RemoteApp arguments */ settings->remote_app_args = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_REMOTE_APP_ARGS, NULL); /* Static virtual channels */ settings->svc_names = NULL; if (argv[IDX_STATIC_CHANNELS][0] != '\0') settings->svc_names = guac_split(argv[IDX_STATIC_CHANNELS], ','); /* * Performance flags */ settings->wallpaper_enabled = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_ENABLE_WALLPAPER, 0); settings->theming_enabled = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_ENABLE_THEMING, 0); settings->font_smoothing_enabled = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_ENABLE_FONT_SMOOTHING, 0); settings->full_window_drag_enabled = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_ENABLE_FULL_WINDOW_DRAG, 0); settings->desktop_composition_enabled = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_ENABLE_DESKTOP_COMPOSITION, 0); settings->menu_animations_enabled = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_ENABLE_MENU_ANIMATIONS, 0); settings->disable_bitmap_caching = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DISABLE_BITMAP_CACHING, 0); settings->disable_offscreen_caching = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DISABLE_OFFSCREEN_CACHING, 0); settings->disable_glyph_caching = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DISABLE_GLYPH_CACHING, 0); /* Session color depth */ settings->color_depth = guac_user_parse_args_int(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_COLOR_DEPTH, RDP_DEFAULT_DEPTH); /* Preconnection ID */ settings->preconnection_id = -1; if (argv[IDX_PRECONNECTION_ID][0] != '\0') { /* Parse preconnection ID, warn if invalid */ int preconnection_id = atoi(argv[IDX_PRECONNECTION_ID]); if (preconnection_id < 0) guac_user_log(user, GUAC_LOG_WARNING, "Ignoring invalid preconnection ID: %i", preconnection_id); /* Otherwise, assign specified ID */ else { settings->preconnection_id = preconnection_id; guac_user_log(user, GUAC_LOG_DEBUG, "Preconnection ID: %i", settings->preconnection_id); } } /* Preconnection BLOB */ settings->preconnection_blob = NULL; if (argv[IDX_PRECONNECTION_BLOB][0] != '\0') { settings->preconnection_blob = strdup(argv[IDX_PRECONNECTION_BLOB]); guac_user_log(user, GUAC_LOG_DEBUG, "Preconnection BLOB: \"%s\"", settings->preconnection_blob); } /* Audio enable/disable */ settings->audio_enabled = !guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DISABLE_AUDIO, 0); /* Printing enable/disable */ settings->printing_enabled = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_ENABLE_PRINTING, 0); /* Name of redirected printer */ settings->printer_name = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_PRINTER_NAME, "Guacamole Printer"); /* Drive enable/disable */ settings->drive_enabled = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_ENABLE_DRIVE, 0); /* Name of the drive being passed through */ settings->drive_name = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DRIVE_NAME, "Guacamole Filesystem"); /* The path on the server to connect the drive. */ settings->drive_path = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DRIVE_PATH, ""); /* If the server path should be created if it doesn't already exist. */ settings->create_drive_path = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_CREATE_DRIVE_PATH, 0); /* If file downloads over RDP should be disabled. */ settings->disable_download = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DISABLE_DOWNLOAD, 0); /* If file uploads over RDP should be disabled. */ settings->disable_upload = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DISABLE_UPLOAD, 0); /* Pick keymap based on argument */ settings->server_layout = NULL; if (argv[IDX_SERVER_LAYOUT][0] != '\0') settings->server_layout = guac_rdp_keymap_find(argv[IDX_SERVER_LAYOUT]); /* If no keymap requested, use default */ if (settings->server_layout == NULL) settings->server_layout = guac_rdp_keymap_find(GUAC_DEFAULT_KEYMAP); /* Timezone if provided by client, or use handshake version */ settings->timezone = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_TIMEZONE, user->info.timezone); #ifdef ENABLE_COMMON_SSH /* SFTP enable/disable */ settings->enable_sftp = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_ENABLE_SFTP, 0); /* Hostname for SFTP connection */ settings->sftp_hostname = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_SFTP_HOSTNAME, settings->hostname); /* The public SSH host key. */ settings->sftp_host_key = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_SFTP_HOST_KEY, NULL); /* Port for SFTP connection */ settings->sftp_port = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_SFTP_PORT, "22"); /* Username for SSH/SFTP authentication */ settings->sftp_username = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_SFTP_USERNAME, settings->username != NULL ? settings->username : ""); /* Password for SFTP (if not using private key) */ settings->sftp_password = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_SFTP_PASSWORD, ""); /* Private key for SFTP (if not using password) */ settings->sftp_private_key = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_SFTP_PRIVATE_KEY, NULL); /* Passphrase for decrypting the SFTP private key (if applicable */ settings->sftp_passphrase = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_SFTP_PASSPHRASE, ""); /* Default upload directory */ settings->sftp_directory = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_SFTP_DIRECTORY, NULL); /* SFTP root directory */ settings->sftp_root_directory = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_SFTP_ROOT_DIRECTORY, "/"); /* Default keepalive value */ settings->sftp_server_alive_interval = guac_user_parse_args_int(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_SFTP_SERVER_ALIVE_INTERVAL, 0); /* Whether or not to disable file download over SFTP. */ settings->sftp_disable_download = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_SFTP_DISABLE_DOWNLOAD, 0); /* Whether or not to disable file upload over SFTP. */ settings->sftp_disable_upload = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_SFTP_DISABLE_UPLOAD, 0); #endif /* Read recording path */ settings->recording_path = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_RECORDING_PATH, NULL); /* Read recording name */ settings->recording_name = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_RECORDING_NAME, GUAC_RDP_DEFAULT_RECORDING_NAME); /* Parse output exclusion flag */ settings->recording_exclude_output = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_RECORDING_EXCLUDE_OUTPUT, 0); /* Parse mouse exclusion flag */ settings->recording_exclude_mouse = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_RECORDING_EXCLUDE_MOUSE, 0); /* Parse key event inclusion flag */ settings->recording_include_keys = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_RECORDING_INCLUDE_KEYS, 0); /* Parse path creation flag */ settings->create_recording_path = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_CREATE_RECORDING_PATH, 0); /* No resize method */ if (strcmp(argv[IDX_RESIZE_METHOD], "") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Resize method: none"); settings->resize_method = GUAC_RESIZE_NONE; } /* Resize method: "reconnect" */ else if (strcmp(argv[IDX_RESIZE_METHOD], "reconnect") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Resize method: reconnect"); settings->resize_method = GUAC_RESIZE_RECONNECT; } /* Resize method: "display-update" */ else if (strcmp(argv[IDX_RESIZE_METHOD], "display-update") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Resize method: display-update"); settings->resize_method = GUAC_RESIZE_DISPLAY_UPDATE; } /* Default to no resize method if invalid */ else { guac_user_log(user, GUAC_LOG_INFO, "Resize method \"%s\" invalid. ", "Defaulting to no resize method.", argv[IDX_RESIZE_METHOD]); settings->resize_method = GUAC_RESIZE_NONE; } /* Audio input enable/disable */ settings->enable_audio_input = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_ENABLE_AUDIO_INPUT, 0); /* Set gateway hostname */ settings->gateway_hostname = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_GATEWAY_HOSTNAME, NULL); /* If gateway port specified, use it */ settings->gateway_port = guac_user_parse_args_int(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_GATEWAY_PORT, 443); /* Set gateway domain */ settings->gateway_domain = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_GATEWAY_DOMAIN, NULL); /* Set gateway username */ settings->gateway_username = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_GATEWAY_USERNAME, NULL); /* Set gateway password */ settings->gateway_password = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_GATEWAY_PASSWORD, NULL); /* Set load balance info */ settings->load_balance_info = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_LOAD_BALANCE_INFO, NULL); /* Parse clipboard copy disable flag */ settings->disable_copy = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DISABLE_COPY, 0); /* Parse clipboard paste disable flag */ settings->disable_paste = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_DISABLE_PASTE, 0); /* Parse Wake-on-LAN (WoL) settings */ settings->wol_send_packet = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_WOL_SEND_PACKET, 0); if (settings->wol_send_packet) { /* If WoL has been requested but no MAC address given, log a warning. */ if(strcmp(argv[IDX_WOL_MAC_ADDR], "") == 0) { guac_user_log(user, GUAC_LOG_WARNING, "WoL requested but no MAC ", "address specified. WoL will not be sent."); settings->wol_send_packet = 0; } /* Parse the WoL MAC address. */ settings->wol_mac_addr = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_WOL_MAC_ADDR, NULL); /* Parse the WoL broadcast address. */ settings->wol_broadcast_addr = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_WOL_BROADCAST_ADDR, GUAC_WOL_LOCAL_IPV4_BROADCAST); /* Parse the WoL wait time. */ settings->wol_wait_time = guac_user_parse_args_int(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_WOL_WAIT_TIME, GUAC_WOL_DEFAULT_BOOT_WAIT_TIME); } /* Success */ return settings; } void guac_rdp_settings_free(guac_rdp_settings* settings) { /* Free settings strings */ free(settings->client_name); free(settings->domain); free(settings->drive_name); free(settings->drive_path); free(settings->hostname); free(settings->initial_program); free(settings->password); free(settings->preconnection_blob); free(settings->recording_name); free(settings->recording_path); free(settings->remote_app); free(settings->remote_app_args); free(settings->remote_app_dir); free(settings->timezone); free(settings->username); free(settings->printer_name); /* Free channel name array */ if (settings->svc_names != NULL) { /* Free all elements of array */ char** current = &(settings->svc_names[0]); while (*current != NULL) { free(*current); current++; } /* Free array itself */ free(settings->svc_names); } #ifdef ENABLE_COMMON_SSH /* Free SFTP settings */ free(settings->sftp_directory); free(settings->sftp_root_directory); free(settings->sftp_host_key); free(settings->sftp_hostname); free(settings->sftp_passphrase); free(settings->sftp_password); free(settings->sftp_port); free(settings->sftp_private_key); free(settings->sftp_username); #endif /* Free RD gateway information */ free(settings->gateway_hostname); free(settings->gateway_domain); free(settings->gateway_username); free(settings->gateway_password); /* Free load balancer information string */ free(settings->load_balance_info); free(settings->wol_mac_addr); free(settings->wol_broadcast_addr); /* Free settings structure */ free(settings); } int guac_rdp_get_width(freerdp* rdp) { return rdp->settings->DesktopWidth; } int guac_rdp_get_height(freerdp* rdp) { return rdp->settings->DesktopHeight; } int guac_rdp_get_depth(freerdp* rdp) { return rdp->settings->ColorDepth; } /** * Given the settings structure of the Guacamole RDP client, calculates the * standard performance flag value to send to the RDP server. The value of * these flags is dictated by the RDP standard. * * @param guac_settings * The settings structure to read performance settings from. * * @returns * The standard RDP performance flag value representing the union of all * performance settings within the given settings structure. */ static int guac_rdp_get_performance_flags(guac_rdp_settings* guac_settings) { /* No performance flags initially */ int flags = PERF_FLAG_NONE; /* Desktop wallpaper */ if (!guac_settings->wallpaper_enabled) flags |= PERF_DISABLE_WALLPAPER; /* Theming of desktop/windows */ if (!guac_settings->theming_enabled) flags |= PERF_DISABLE_THEMING; /* Font smoothing (ClearType) */ if (guac_settings->font_smoothing_enabled) flags |= PERF_ENABLE_FONT_SMOOTHING; /* Full-window drag */ if (!guac_settings->full_window_drag_enabled) flags |= PERF_DISABLE_FULLWINDOWDRAG; /* Desktop composition (Aero) */ if (guac_settings->desktop_composition_enabled) flags |= PERF_ENABLE_DESKTOP_COMPOSITION; /* Menu animations */ if (!guac_settings->menu_animations_enabled) flags |= PERF_DISABLE_MENUANIMATIONS; return flags; } void guac_rdp_push_settings(guac_client* client, guac_rdp_settings* guac_settings, freerdp* rdp) { rdpSettings* rdp_settings = rdp->settings; /* Authentication */ rdp_settings->Domain = guac_strdup(guac_settings->domain); rdp_settings->Username = guac_strdup(guac_settings->username); rdp_settings->Password = guac_strdup(guac_settings->password); /* Connection */ rdp_settings->ServerHostname = guac_strdup(guac_settings->hostname); rdp_settings->ServerPort = guac_settings->port; /* Session */ rdp_settings->ColorDepth = guac_settings->color_depth; rdp_settings->DesktopWidth = guac_settings->width; rdp_settings->DesktopHeight = guac_settings->height; rdp_settings->AlternateShell = guac_strdup(guac_settings->initial_program); rdp_settings->KeyboardLayout = guac_settings->server_layout->freerdp_keyboard_layout; /* Performance flags */ /* Explicitly set flag value */ rdp_settings->PerformanceFlags = guac_rdp_get_performance_flags(guac_settings); /* Set individual flags - some FreeRDP versions overwrite the above */ rdp_settings->AllowFontSmoothing = guac_settings->font_smoothing_enabled; rdp_settings->DisableWallpaper = !guac_settings->wallpaper_enabled; rdp_settings->DisableFullWindowDrag = !guac_settings->full_window_drag_enabled; rdp_settings->DisableMenuAnims = !guac_settings->menu_animations_enabled; rdp_settings->DisableThemes = !guac_settings->theming_enabled; rdp_settings->AllowDesktopComposition = guac_settings->desktop_composition_enabled; /* Client name */ if (guac_settings->client_name != NULL) { guac_strlcpy(rdp_settings->ClientHostname, guac_settings->client_name, RDP_CLIENT_HOSTNAME_SIZE); } /* Console */ rdp_settings->ConsoleSession = guac_settings->console; rdp_settings->RemoteConsoleAudio = guac_settings->console_audio; /* Audio */ rdp_settings->AudioPlayback = guac_settings->audio_enabled; /* Audio capture */ rdp_settings->AudioCapture = guac_settings->enable_audio_input; /* Display Update channel */ rdp_settings->SupportDisplayControl = (guac_settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE); /* Timezone redirection */ if (guac_settings->timezone) { if (setenv("TZ", guac_settings->timezone, 1)) { guac_client_log(client, GUAC_LOG_WARNING, "Unable to forward timezone: TZ environment variable " "could not be set: %s", strerror(errno)); } } /* Device redirection */ rdp_settings->DeviceRedirection = guac_settings->audio_enabled || guac_settings->drive_enabled || guac_settings->printing_enabled; /* Security */ switch (guac_settings->security_mode) { /* Legacy RDP encryption */ case GUAC_SECURITY_RDP: rdp_settings->RdpSecurity = TRUE; rdp_settings->TlsSecurity = FALSE; rdp_settings->NlaSecurity = FALSE; rdp_settings->ExtSecurity = FALSE; rdp_settings->UseRdpSecurityLayer = TRUE; rdp_settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; rdp_settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; break; /* TLS encryption */ case GUAC_SECURITY_TLS: rdp_settings->RdpSecurity = FALSE; rdp_settings->TlsSecurity = TRUE; rdp_settings->NlaSecurity = FALSE; rdp_settings->ExtSecurity = FALSE; break; /* Network level authentication */ case GUAC_SECURITY_NLA: rdp_settings->RdpSecurity = FALSE; rdp_settings->TlsSecurity = FALSE; rdp_settings->NlaSecurity = TRUE; rdp_settings->ExtSecurity = FALSE; break; /* Extended network level authentication */ case GUAC_SECURITY_EXTENDED_NLA: rdp_settings->RdpSecurity = FALSE; rdp_settings->TlsSecurity = FALSE; rdp_settings->NlaSecurity = FALSE; rdp_settings->ExtSecurity = TRUE; break; /* Hyper-V "VMConnect" negotiation mode */ case GUAC_SECURITY_VMCONNECT: rdp_settings->RdpSecurity = FALSE; rdp_settings->TlsSecurity = TRUE; rdp_settings->NlaSecurity = TRUE; rdp_settings->ExtSecurity = FALSE; rdp_settings->VmConnectMode = TRUE; break; /* All security types */ case GUAC_SECURITY_ANY: rdp_settings->RdpSecurity = TRUE; rdp_settings->TlsSecurity = TRUE; rdp_settings->NlaSecurity = guac_settings->username && guac_settings->password; rdp_settings->ExtSecurity = FALSE; break; } /* Authentication */ rdp_settings->Authentication = !guac_settings->disable_authentication; rdp_settings->IgnoreCertificate = guac_settings->ignore_certificate; /* RemoteApp */ if (guac_settings->remote_app != NULL) { rdp_settings->Workarea = TRUE; rdp_settings->RemoteApplicationMode = TRUE; rdp_settings->RemoteAppLanguageBarSupported = TRUE; rdp_settings->RemoteApplicationProgram = guac_strdup(guac_settings->remote_app); rdp_settings->ShellWorkingDirectory = guac_strdup(guac_settings->remote_app_dir); rdp_settings->RemoteApplicationCmdLine = guac_strdup(guac_settings->remote_app_args); } /* Preconnection ID */ if (guac_settings->preconnection_id != -1) { rdp_settings->NegotiateSecurityLayer = FALSE; rdp_settings->SendPreconnectionPdu = TRUE; rdp_settings->PreconnectionId = guac_settings->preconnection_id; } /* Preconnection BLOB */ if (guac_settings->preconnection_blob != NULL) { rdp_settings->NegotiateSecurityLayer = FALSE; rdp_settings->SendPreconnectionPdu = TRUE; rdp_settings->PreconnectionBlob = guac_strdup(guac_settings->preconnection_blob); } /* Enable use of RD gateway if a gateway hostname is provided */ if (guac_settings->gateway_hostname != NULL) { /* Enable RD gateway */ rdp_settings->GatewayEnabled = TRUE; /* RD gateway connection details */ rdp_settings->GatewayHostname = guac_strdup(guac_settings->gateway_hostname); rdp_settings->GatewayPort = guac_settings->gateway_port; /* RD gateway credentials */ rdp_settings->GatewayUseSameCredentials = FALSE; rdp_settings->GatewayDomain = guac_strdup(guac_settings->gateway_domain); rdp_settings->GatewayUsername = guac_strdup(guac_settings->gateway_username); rdp_settings->GatewayPassword = guac_strdup(guac_settings->gateway_password); } /* Store load balance info (and calculate length) if provided */ if (guac_settings->load_balance_info != NULL) { rdp_settings->LoadBalanceInfo = (BYTE*) guac_strdup(guac_settings->load_balance_info); rdp_settings->LoadBalanceInfoLength = strlen(guac_settings->load_balance_info); } rdp_settings->BitmapCacheEnabled = !guac_settings->disable_bitmap_caching; rdp_settings->OffscreenSupportLevel = !guac_settings->disable_offscreen_caching; rdp_settings->GlyphSupportLevel = !guac_settings->disable_glyph_caching ? GLYPH_SUPPORT_FULL : GLYPH_SUPPORT_NONE; rdp_settings->OsMajorType = OSMAJORTYPE_UNSPECIFIED; rdp_settings->OsMinorType = OSMINORTYPE_UNSPECIFIED; rdp_settings->DesktopResize = TRUE; /* Claim support only for specific updates, independent of FreeRDP defaults */ ZeroMemory(rdp_settings->OrderSupport, GUAC_RDP_ORDER_SUPPORT_LENGTH); rdp_settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE; rdp_settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; rdp_settings->OrderSupport[NEG_MEMBLT_INDEX] = !guac_settings->disable_bitmap_caching; rdp_settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = !guac_settings->disable_bitmap_caching; rdp_settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = !guac_settings->disable_glyph_caching; rdp_settings->OrderSupport[NEG_FAST_INDEX_INDEX] = !guac_settings->disable_glyph_caching; rdp_settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = !guac_settings->disable_glyph_caching; #ifdef HAVE_RDPSETTINGS_ALLOWUNANOUNCEDORDERSFROMSERVER /* Do not consider server use of unannounced orders to be a fatal error */ rdp_settings->AllowUnanouncedOrdersFromServer = TRUE; #endif } guacamole-server-1.3.0/src/protocols/rdp/client.h0000644000175100001440000000620013764613616016734 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_CLIENT_H #define GUAC_RDP_CLIENT_H #include /** * The maximum duration of a frame in milliseconds. */ #define GUAC_RDP_FRAME_DURATION 60 /** * The amount of time to allow per message read within a frame, in * milliseconds. If the server is silent for at least this amount of time, the * frame will be considered finished. */ #define GUAC_RDP_FRAME_TIMEOUT 0 /** * The amount of time to wait for a new message from the RDP server when * beginning a new frame, in milliseconds. This value must be kept reasonably * small such that a slow RDP server will not prevent external events from * being handled (such as the stop signal from guac_client_stop()), but large * enough that the message handling loop does not eat up CPU spinning. */ #define GUAC_RDP_FRAME_START_TIMEOUT 250 /** * The native resolution of most RDP connections. As Windows and other systems * rely heavily on forced 96 DPI, we must assume 96 DPI. */ #define GUAC_RDP_NATIVE_RESOLUTION 96 /** * The resolution of an RDP connection that would be considered high, but is * tolerable in the case that the client display would be unreasonably small * otherwise. */ #define GUAC_RDP_HIGH_RESOLUTION 120 /** * The smallest area, in pixels^2, that would be considered reasonable large * screen DPI needs to be adjusted. */ #define GUAC_RDP_REASONABLE_AREA (800*600) /** * The maximum number of bytes to allow within the clipboard. */ #define GUAC_RDP_CLIPBOARD_MAX_LENGTH 262144 /** * Initial rate of audio to stream, in Hz. If the RDP server uses a different * value, the Guacamole audio stream will simply be reset appropriately. */ #define GUAC_RDP_AUDIO_RATE 44100 /** * The number of channels to stream for audio. If the RDP server uses a * different value, the Guacamole audio stream will simply be reset * appropriately. */ #define GUAC_RDP_AUDIO_CHANNELS 2 /** * The number of bits per sample within the audio stream. If the RDP server * uses a different value, the Guacamole audio stream will simply be reset * appropriately. */ #define GUAC_RDP_AUDIO_BPS 16 /** * The maximum number of file descriptors which can be associated with an RDP * connection. */ #define GUAC_RDP_MAX_FILE_DESCRIPTORS 32 /** * Handler which frees all data associated with the guac_client. */ guac_client_free_handler guac_rdp_client_free_handler; #endif guacamole-server-1.3.0/src/protocols/rdp/decompose.c0000644000175100001440000001537113764613616017440 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "keyboard.h" /** * The X11 keysym for the dead key which types a grave (`). */ #define DEAD_GRAVE 0xFE50 /** * The X11 keysym for the dead key which types an acute (´). Note that this is * NOT equivalent to an apostrophe or single quote. */ #define DEAD_ACUTE 0xFE51 /** * The X11 keysym for the dead key which types a circumflex/caret (^). */ #define DEAD_CIRCUMFLEX 0xFE52 /** * The X11 keysym for the dead key which types a tilde (~). */ #define DEAD_TILDE 0xFE53 /** * The X11 keysym for the dead key which types a dieresis/umlaut (¨). */ #define DEAD_DIERESIS 0xFE57 /** * The X11 keysym for the dead key which types an abovering (˚). Note that this * is NOT equivalent to the degree symbol. */ #define DEAD_ABOVERING 0xFE58 /** * The decomposed form of a key that can be typed using two keypresses: a dead * key followed by a base key. For example, on a keyboard which lacks a single * dedicated key for doing the same, "ó" would be typed using the dead acute * key followed by the "o" key. The dead key and base key are pressed and * released in sequence; they are not held down. */ typedef struct guac_rdp_decomposed_key { /** * The keysym of the dead key which must first be pressed and released to * begin typing the desired character. The dead key defines the diacritic * which will be applied to the character typed by the base key. */ int dead_keysym; /** * The keysym of the base key which must be pressed and released to finish * typing the desired character. The base key defines the normal form of * the character (the form which lacks any diacritic) to which the * diacritic defined by the previously-pressed dead key will be applied. */ int base_keysym; } guac_rdp_decomposed_key; /** * A lookup table of all known decomposed forms of various keysyms. Keysyms map * directly to entries within this table. A keysym which has no entry within * this table does not have a defined decomposed form (or at least does not * have a decomposed form relevant to RDP). */ guac_rdp_decomposed_key guac_rdp_decomposed_keys[256] = { /* ^ */ [0x005E] = { DEAD_CIRCUMFLEX, ' ' }, /* ` */ [0x0060] = { DEAD_GRAVE, ' ' }, /* ~ */ [0x007E] = { DEAD_TILDE, ' ' }, /* ¨ */ [0x00A8] = { DEAD_DIERESIS, ' ' }, /* ´ */ [0x00B4] = { DEAD_ACUTE, ' ' }, /* À */ [0x00C0] = { DEAD_GRAVE, 'A' }, /* Á */ [0x00C1] = { DEAD_ACUTE, 'A' }, /*  */ [0x00C2] = { DEAD_CIRCUMFLEX, 'A' }, /* à */ [0x00C3] = { DEAD_TILDE, 'A' }, /* Ä */ [0x00C4] = { DEAD_DIERESIS, 'A' }, /* Å */ [0x00C5] = { DEAD_ABOVERING, 'A' }, /* È */ [0x00C8] = { DEAD_GRAVE, 'E' }, /* É */ [0x00C9] = { DEAD_ACUTE, 'E' }, /* Ê */ [0x00CA] = { DEAD_CIRCUMFLEX, 'E' }, /* Ë */ [0x00CB] = { DEAD_DIERESIS, 'E' }, /* Ì */ [0x00CC] = { DEAD_GRAVE, 'I' }, /* Í */ [0x00CD] = { DEAD_ACUTE, 'I' }, /* Î */ [0x00CE] = { DEAD_CIRCUMFLEX, 'I' }, /* Ï */ [0x00CF] = { DEAD_DIERESIS, 'I' }, /* Ñ */ [0x00D1] = { DEAD_TILDE, 'N' }, /* Ò */ [0x00D2] = { DEAD_GRAVE, 'O' }, /* Ó */ [0x00D3] = { DEAD_ACUTE, 'O' }, /* Ô */ [0x00D4] = { DEAD_CIRCUMFLEX, 'O' }, /* Õ */ [0x00D5] = { DEAD_TILDE, 'O' }, /* Ö */ [0x00D6] = { DEAD_DIERESIS, 'O' }, /* Ù */ [0x00D9] = { DEAD_GRAVE, 'U' }, /* Ú */ [0x00DA] = { DEAD_ACUTE, 'U' }, /* Û */ [0x00DB] = { DEAD_CIRCUMFLEX, 'U' }, /* Ü */ [0x00DC] = { DEAD_DIERESIS, 'U' }, /* Ý */ [0x00DD] = { DEAD_ACUTE, 'Y' }, /* à */ [0x00E0] = { DEAD_GRAVE, 'a' }, /* á */ [0x00E1] = { DEAD_ACUTE, 'a' }, /* â */ [0x00E2] = { DEAD_CIRCUMFLEX, 'a' }, /* ã */ [0x00E3] = { DEAD_TILDE, 'a' }, /* ä */ [0x00E4] = { DEAD_DIERESIS, 'a' }, /* å */ [0x00E5] = { DEAD_ABOVERING, 'a' }, /* è */ [0x00E8] = { DEAD_GRAVE, 'e' }, /* é */ [0x00E9] = { DEAD_ACUTE, 'e' }, /* ê */ [0x00EA] = { DEAD_CIRCUMFLEX, 'e' }, /* ë */ [0x00EB] = { DEAD_DIERESIS, 'e' }, /* ì */ [0x00EC] = { DEAD_GRAVE, 'i' }, /* í */ [0x00ED] = { DEAD_ACUTE, 'i' }, /* î */ [0x00EE] = { DEAD_CIRCUMFLEX, 'i' }, /* ï */ [0x00EF] = { DEAD_DIERESIS, 'i' }, /* ñ */ [0x00F1] = { DEAD_TILDE, 'n' }, /* ò */ [0x00F2] = { DEAD_GRAVE, 'o' }, /* ó */ [0x00F3] = { DEAD_ACUTE, 'o' }, /* ô */ [0x00F4] = { DEAD_CIRCUMFLEX, 'o' }, /* õ */ [0x00F5] = { DEAD_TILDE, 'o' }, /* ö */ [0x00F6] = { DEAD_DIERESIS, 'o' }, /* ù */ [0x00F9] = { DEAD_GRAVE, 'u' }, /* ú */ [0x00FA] = { DEAD_ACUTE, 'u' }, /* û */ [0x00FB] = { DEAD_CIRCUMFLEX, 'u' }, /* ü */ [0x00FC] = { DEAD_DIERESIS, 'u' }, /* ý */ [0x00FD] = { DEAD_ACUTE, 'y' }, /* ÿ */ [0x00FF] = { DEAD_DIERESIS, 'y' } }; int guac_rdp_decompose_keysym(guac_rdp_keyboard* keyboard, int keysym) { /* Verify keysym is within range of lookup table */ if (keysym < 0x00 || keysym > 0xFF) return 1; /* Verify keysym is actually defined within lookup table */ guac_rdp_decomposed_key* key = &guac_rdp_decomposed_keys[keysym]; if (!key->dead_keysym) return 1; /* Cannot type using decomposed keys if those keys are not defined within * the current layout */ if (!guac_rdp_keyboard_is_defined(keyboard, key->dead_keysym) || !guac_rdp_keyboard_is_defined(keyboard, key->base_keysym)) return 1; /* Press dead key */ guac_rdp_keyboard_update_keysym(keyboard, key->dead_keysym, 1, GUAC_RDP_KEY_SOURCE_SYNTHETIC); guac_rdp_keyboard_update_keysym(keyboard, key->dead_keysym, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC); /* Press base key */ guac_rdp_keyboard_update_keysym(keyboard, key->base_keysym, 1, GUAC_RDP_KEY_SOURCE_SYNTHETIC); guac_rdp_keyboard_update_keysym(keyboard, key->base_keysym, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC); /* Decomposed key successfully typed */ return 0; } guacamole-server-1.3.0/src/protocols/rdp/glyph.h0000644000175100001440000001542713764613616016614 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_GLYPH_H #define GUAC_RDP_GLYPH_H #include "config.h" #include #include #include #include #ifdef FREERDP_GLYPH_CALLBACKS_ACCEPT_INT32 /** * FreeRDP 2.0.0-rc4 and newer requires INT32 for all integer arguments of * glyph callbacks. */ #define GLYPH_CALLBACK_INT32 INT32 #else /** * FreeRDP 2.0.0-rc3 and older requires UINT32 for all integer arguments of * glyph callbacks. */ #define GLYPH_CALLBACK_INT32 UINT32 #endif /** * Guacamole-specific rdpGlyph data. */ typedef struct guac_rdp_glyph { /** * FreeRDP glyph data - MUST GO FIRST. */ rdpGlyph glyph; /** * Cairo surface layer containing cached image data. */ cairo_surface_t* surface; } guac_rdp_glyph; /** * Caches the given glyph. Note that this caching currently only occurs server- * side, as it is more efficient to transmit the text as PNG. * * @param context * The rdpContext associated with the current RDP session. * * @param glyph * The glyph to cache. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_glyph_new(rdpContext* context, const rdpGlyph* glyph); /** * Draws a previously-cached glyph at the given coordinates within the current * drawing surface. * * @param context * The rdpContext associated with the current RDP session. * * @param glyph * The cached glyph to draw. * * @param x * The destination X coordinate of the upper-left corner of the glyph. * * @param y * The destination Y coordinate of the upper-left corner of the glyph. * * @param w * The width of the glyph being drawn. * * @param h * The height of the glyph being drawn. * * @param sx * The X coordinare of the upper-left corner of the glyph within the source * cache surface containing the glyph. * * @param sy * The Y coordinare of the upper-left corner of the glyph within the source * cache surface containing the glyph. * * @param redundant * Whether the background rectangle specified is redundant (transparent). * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_glyph_draw(rdpContext* context, const rdpGlyph* glyph, GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, GLYPH_CALLBACK_INT32 w, GLYPH_CALLBACK_INT32 h, GLYPH_CALLBACK_INT32 sx, GLYPH_CALLBACK_INT32 sy, BOOL redundant); /** * Frees any Guacamole-specific data associated with the given glyph, such that * it can be safely freed by FreeRDP. * * @param context * The rdpContext associated with the current RDP session. * * @param glyph * The cached glyph to free. */ void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph); /** * Called just prior to rendering a series of glyphs. After this function is * called, the glyphs will be individually rendered by calls to * guac_rdp_glyph_draw(). * * @param context * The rdpContext associated with the current RDP session. * * @param x * The X coordinate of the upper-left corner of the background rectangle of * the drawing operation, or 0 if the background is transparent. * * @param y * The Y coordinate of the upper-left corner of the background rectangle of * the drawing operation, or 0 if the background is transparent. * * @param width * The width of the background rectangle of the drawing operation, or 0 if * the background is transparent. * * @param height * The height of the background rectangle of the drawing operation, or 0 if * the background is transparent. * * @param fgcolor * The foreground color of each glyph. This color will be in the colorspace * of the RDP session, and may even be a palette index, and must be * translated via guac_rdp_convert_color(). * * @param bgcolor * The background color of the drawing area. This color will be in the * colorspace of the RDP session, and may even be a palette index, and must * be translated via guac_rdp_convert_color(). If the background is * transparent, this value is undefined. * * @param redundant * Whether the background rectangle specified is redundant (transparent). * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_glyph_begindraw(rdpContext* context, GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, GLYPH_CALLBACK_INT32 width, GLYPH_CALLBACK_INT32 height, UINT32 fgcolor, UINT32 bgcolor, BOOL redundant); /** * Called immediately after rendering a series of glyphs. Unlike * guac_rdp_glyph_begindraw(), there is no way to detect through any invocation * of this function whether the background color is opaque or transparent. We * currently do NOT implement this function. * * @param context * The rdpContext associated with the current RDP session. * * @param x * The X coordinate of the upper-left corner of the background rectangle of * the drawing operation. * * @param y * The Y coordinate of the upper-left corner of the background rectangle of * the drawing operation. * * @param width * The width of the background rectangle of the drawing operation. * * @param height * The height of the background rectangle of the drawing operation. * * @param fgcolor * The foreground color of each glyph. This color will be in the colorspace * of the RDP session, and may even be a palette index, and must be * translated via guac_rdp_convert_color(). * * @param bgcolor * The background color of the drawing area. This color will be in the * colorspace of the RDP session, and may even be a palette index, and must * be translated via guac_rdp_convert_color(). If the background is * transparent, this value is undefined. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_glyph_enddraw(rdpContext* context, GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, GLYPH_CALLBACK_INT32 width, GLYPH_CALLBACK_INT32 height, UINT32 fgcolor, UINT32 bgcolor); #endif guacamole-server-1.3.0/src/protocols/rdp/rdp.h0000644000175100001440000001172313764613616016251 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_H #define GUAC_RDP_H #include "channels/audio-input/audio-buffer.h" #include "channels/cliprdr.h" #include "channels/disp.h" #include "common/clipboard.h" #include "common/display.h" #include "common/list.h" #include "common/recording.h" #include "common/surface.h" #include "config.h" #include "fs.h" #include "keyboard.h" #include "print-job.h" #include "settings.h" #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" #include "common-ssh/ssh.h" #include "common-ssh/user.h" #endif #include #include #include #include #include #include #include /** * RDP-specific client data. */ typedef struct guac_rdp_client { /** * The RDP client thread. */ pthread_t client_thread; /** * Pointer to the FreeRDP client instance handling the current connection. */ freerdp* rdp_inst; /** * All settings associated with the current or pending RDP connection. */ guac_rdp_settings* settings; /** * Button mask containing the OR'd value of all currently pressed buttons. */ int mouse_button_mask; /** * Foreground color for any future glyphs. */ uint32_t glyph_color; /** * The display. */ guac_common_display* display; /** * The surface that GDI operations should draw to. RDP messages exist which * change this surface to allow drawing to occur off-screen. */ guac_common_surface* current_surface; /** * The current state of the keyboard with respect to the RDP session. */ guac_rdp_keyboard* keyboard; /** * The current state of the clipboard and the CLIPRDR channel. */ guac_rdp_clipboard* clipboard; /** * Audio output, if any. */ guac_audio_stream* audio; /** * Audio input buffer, if audio input is enabled. */ guac_rdp_audio_buffer* audio_input; /** * The filesystem being shared, if any. */ guac_rdp_fs* filesystem; /** * The currently-active print job, or NULL if no print job is active. */ guac_rdp_print_job* active_job; #ifdef ENABLE_COMMON_SSH /** * The user and credentials used to authenticate for SFTP. */ guac_common_ssh_user* sftp_user; /** * The SSH session used for SFTP. */ guac_common_ssh_session* sftp_session; /** * An SFTP-based filesystem. */ guac_common_ssh_sftp_filesystem* sftp_filesystem; #endif /** * The in-progress session recording, or NULL if no recording is in * progress. */ guac_common_recording* recording; /** * Display size update module. */ guac_rdp_disp* disp; /** * List of all available static virtual channels. */ guac_common_list* available_svc; /** * Common attributes for locks. */ pthread_mutexattr_t attributes; /** * Lock which is used to synchronizes access to RDP data structures * between user input and client threads. It prevents input handlers * from running when RDP data structures are allocated or freed * by the client thread. */ pthread_rwlock_t lock; } guac_rdp_client; /** * Client data that will remain accessible through the RDP context. * This should generally include data commonly used by FreeRDP handlers. */ typedef struct rdp_freerdp_context { /** * The parent context. THIS MUST BE THE FIRST ELEMENT. */ rdpContext _p; /** * Pointer to the guac_client instance handling the RDP connection with * this context. */ guac_client* client; /** * The current color palette, as received from the RDP server. */ UINT32 palette[256]; } rdp_freerdp_context; /** * RDP client thread. This thread runs throughout the duration of the client, * existing as a single instance, shared by all users. * * @param data * The guac_client to associate with an RDP session, once the RDP * connection succeeds. * * @return * NULL in all cases. The return value of this thread is expected to be * ignored. */ void* guac_rdp_client_thread(void* data); #endif guacamole-server-1.3.0/src/protocols/rdp/rdp.c0000644000175100001440000006303113770536337016244 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "argv.h" #include "beep.h" #include "bitmap.h" #include "channels/audio-input/audio-buffer.h" #include "channels/audio-input/audio-input.h" #include "channels/cliprdr.h" #include "channels/disp.h" #include "channels/pipe-svc.h" #include "channels/rail.h" #include "channels/rdpdr/rdpdr.h" #include "channels/rdpsnd/rdpsnd.h" #include "client.h" #include "color.h" #include "common/cursor.h" #include "common/display.h" #include "common/recording.h" #include "config.h" #include "error.h" #include "fs.h" #include "gdi.h" #include "glyph.h" #include "keyboard.h" #include "plugins/channels.h" #include "pointer.h" #include "print-job.h" #include "rdp.h" #include "settings.h" #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" #include "common-ssh/ssh.h" #include "common-ssh/user.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include BOOL rdp_freerdp_pre_connect(freerdp* instance) { rdpContext* context = instance->context; rdpGraphics* graphics = context->graphics; guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; /* Push desired settings to FreeRDP */ guac_rdp_push_settings(client, settings, instance); /* Init FreeRDP add-in provider */ freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); /* Load "disp" plugin for display update */ if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) guac_rdp_disp_load_plugin(context); /* Load "AUDIO_INPUT" plugin for audio input*/ if (settings->enable_audio_input) { rdp_client->audio_input = guac_rdp_audio_buffer_alloc(); guac_rdp_audio_load_plugin(instance->context); } /* Load "cliprdr" service if not disabled */ if (!(settings->disable_copy && settings->disable_paste)) guac_rdp_clipboard_load_plugin(rdp_client->clipboard, context); /* If RDPSND/RDPDR required, load them */ if (settings->printing_enabled || settings->drive_enabled || settings->audio_enabled) { guac_rdpdr_load_plugin(context); guac_rdpsnd_load_plugin(context); } /* Load RAIL plugin if RemoteApp in use */ if (settings->remote_app != NULL) guac_rdp_rail_load_plugin(context); /* Load SVC plugin instances for all static channels */ if (settings->svc_names != NULL) { char** current = settings->svc_names; do { guac_rdp_pipe_svc_load_plugin(context, *current); } while (*(++current) != NULL); } /* Load plugin providing Dynamic Virtual Channel support, if required */ if (instance->settings->SupportDynamicChannels && guac_freerdp_channels_load_plugin(context, "drdynvc", instance->settings)) { guac_client_log(client, GUAC_LOG_WARNING, "Failed to load drdynvc plugin. Display update and audio " "input support will be disabled."); } /* Init FreeRDP internal GDI implementation */ if (!gdi_init(instance, guac_rdp_get_native_pixel_format(FALSE))) return FALSE; /* Set up bitmap handling */ rdpBitmap bitmap = *graphics->Bitmap_Prototype; bitmap.size = sizeof(guac_rdp_bitmap); bitmap.New = guac_rdp_bitmap_new; bitmap.Free = guac_rdp_bitmap_free; bitmap.Paint = guac_rdp_bitmap_paint; bitmap.SetSurface = guac_rdp_bitmap_setsurface; graphics_register_bitmap(graphics, &bitmap); /* Set up glyph handling */ rdpGlyph glyph = *graphics->Glyph_Prototype; glyph.size = sizeof(guac_rdp_glyph); glyph.New = guac_rdp_glyph_new; glyph.Free = guac_rdp_glyph_free; glyph.Draw = guac_rdp_glyph_draw; glyph.BeginDraw = guac_rdp_glyph_begindraw; glyph.EndDraw = guac_rdp_glyph_enddraw; graphics_register_glyph(graphics, &glyph); /* Set up pointer handling */ rdpPointer pointer = *graphics->Pointer_Prototype; pointer.size = sizeof(guac_rdp_pointer); pointer.New = guac_rdp_pointer_new; pointer.Free = guac_rdp_pointer_free; pointer.Set = guac_rdp_pointer_set; pointer.SetNull = guac_rdp_pointer_set_null; pointer.SetDefault = guac_rdp_pointer_set_default; graphics_register_pointer(graphics, &pointer); /* Beep on receipt of Play Sound PDU */ instance->update->PlaySound = guac_rdp_beep_play_sound; /* Automatically synchronize keyboard locks when changed server-side */ instance->update->SetKeyboardIndicators = guac_rdp_keyboard_set_indicators; /* Set up GDI */ instance->update->DesktopResize = guac_rdp_gdi_desktop_resize; instance->update->EndPaint = guac_rdp_gdi_end_paint; instance->update->SetBounds = guac_rdp_gdi_set_bounds; rdpPrimaryUpdate* primary = instance->update->primary; primary->DstBlt = guac_rdp_gdi_dstblt; primary->PatBlt = guac_rdp_gdi_patblt; primary->ScrBlt = guac_rdp_gdi_scrblt; primary->MemBlt = guac_rdp_gdi_memblt; primary->OpaqueRect = guac_rdp_gdi_opaquerect; pointer_cache_register_callbacks(instance->update); glyph_cache_register_callbacks(instance->update); brush_cache_register_callbacks(instance->update); bitmap_cache_register_callbacks(instance->update); offscreen_cache_register_callbacks(instance->update); palette_cache_register_callbacks(instance->update); return TRUE; } /** * Callback invoked by FreeRDP when authentication is required but the required * parameters have not been provided. In the case of Guacamole clients that * support the "required" instruction, this function will send any of the three * unpopulated RDP authentication parameters back to the client so that the * connection owner can provide the required information. If the values have * been provided in the original connection parameters the user will not be * prompted for updated parameters. If the version of Guacamole Client in use * by the connection owner does not support the "required" instruction then the * connection will fail. This function always returns true. * * @param instance * The FreeRDP instance associated with the RDP session requesting * credentials. * * @param username * Pointer to a string which will receive the user's username. * * @param password * Pointer to a string which will receive the user's password. * * @param domain * Pointer to a string which will receive the domain associated with the * user's account. * * @return * Always TRUE. */ static BOOL rdp_freerdp_authenticate(freerdp* instance, char** username, char** password, char** domain) { rdpContext* context = instance->context; guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; char* params[4] = {NULL}; int i = 0; /* If the client does not support the "required" instruction, warn and * quit. */ if (!guac_client_owner_supports_required(client)) { guac_client_log(client, GUAC_LOG_WARNING, "Client does not support the " "\"required\" instruction. No authentication parameters will " "be requested."); return TRUE; } /* If the username is undefined, add it to the requested parameters. */ if (settings->username == NULL) { guac_argv_register(GUAC_RDP_ARGV_USERNAME, guac_rdp_argv_callback, NULL, 0); params[i] = GUAC_RDP_ARGV_USERNAME; i++; /* If username is undefined and domain is also undefined, request domain. */ if (settings->domain == NULL) { guac_argv_register(GUAC_RDP_ARGV_DOMAIN, guac_rdp_argv_callback, NULL, 0); params[i] = GUAC_RDP_ARGV_DOMAIN; i++; } } /* If the password is undefined, add it to the requested parameters. */ if (settings->password == NULL) { guac_argv_register(GUAC_RDP_ARGV_PASSWORD, guac_rdp_argv_callback, NULL, 0); params[i] = GUAC_RDP_ARGV_PASSWORD; i++; } /* NULL-terminate the array. */ params[i] = NULL; if (i > 0) { /* Send required parameters to the owner and wait for the response. */ guac_client_owner_send_required(client, (const char**) params); guac_argv_await((const char**) params); /* Free old values and get new values from settings. */ free(*username); free(*password); free(*domain); *username = guac_strdup(settings->username); *password = guac_strdup(settings->password); *domain = guac_strdup(settings->domain); } /* Always return TRUE allowing connection to retry. */ return TRUE; } /** * Callback invoked by FreeRDP when the SSL/TLS certificate of the RDP server * needs to be verified. If this ever happens, this function implementation * will always fail unless the connection has been configured to ignore * certificate validity. * * @param instance * The FreeRDP instance associated with the RDP session whose SSL/TLS * certificate needs to be verified. * * @param subject * The subject to whom the certificate was issued. * * @param issuer * The authority that issued the certificate, * * @param fingerprint * The cryptographic fingerprint of the certificate. * * @return * TRUE if the certificate passes verification, FALSE otherwise. */ static DWORD rdp_freerdp_verify_certificate(freerdp* instance, const char* common_name, const char* subject, const char* issuer, const char* fingerprint, BOOL host_mismatch) { rdpContext* context = instance->context; guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Bypass validation if ignore_certificate given */ if (rdp_client->settings->ignore_certificate) { guac_client_log(client, GUAC_LOG_INFO, "Certificate validation bypassed"); return 2; /* Accept only for this session */ } guac_client_log(client, GUAC_LOG_INFO, "Certificate validation failed"); return 0; /* Reject certificate */ } /** * Waits for messages from the RDP server for the given number of milliseconds. * * @param client * The client associated with the current RDP session. * * @param timeout_msecs * The maximum amount of time to wait, in milliseconds. * * @return * A positive value if messages are ready, zero if the specified timeout * period elapsed, or a negative value if an error occurs. */ static int rdp_guac_client_wait_for_messages(guac_client* client, int timeout_msecs) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; freerdp* rdp_inst = rdp_client->rdp_inst; HANDLE handles[GUAC_RDP_MAX_FILE_DESCRIPTORS]; int num_handles = freerdp_get_event_handles(rdp_inst->context, handles, GUAC_RDP_MAX_FILE_DESCRIPTORS); /* Wait for data and construct a reasonable frame */ int result = WaitForMultipleObjects(num_handles, handles, FALSE, timeout_msecs); /* Translate WaitForMultipleObjects() return values */ switch (result) { /* Timeout elapsed before wait could complete */ case WAIT_TIMEOUT: return 0; /* Attempt to wait failed due to an error */ case WAIT_FAILED: return -1; } /* Wait was successful */ return 1; } /** * Connects to an RDP server as described by the guac_rdp_settings structure * associated with the given client, allocating and freeing all objects * directly related to the RDP connection. It is expected that all objects * which are independent of FreeRDP's state (the clipboard, display update * management, etc.) will already be allocated and associated with the * guac_rdp_client associated with the given guac_client. This function blocks * for the duration of the RDP session, returning only after the session has * completely disconnected. * * @param client * The guac_client associated with the RDP settings describing the * connection that should be established. * * @return * Zero if the connection successfully terminated and a reconnect is * desired, non-zero if an error occurs or the connection was disconnected * and a reconnect is NOT desired. */ static int guac_rdp_handle_connection(guac_client* client) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; /* Init random number generator */ srandom(time(NULL)); pthread_rwlock_wrlock(&(rdp_client->lock)); /* Set up screen recording, if requested */ if (settings->recording_path != NULL) { rdp_client->recording = guac_common_recording_create(client, settings->recording_path, settings->recording_name, settings->create_recording_path, !settings->recording_exclude_output, !settings->recording_exclude_mouse, settings->recording_include_keys); } /* Create display */ rdp_client->display = guac_common_display_alloc(client, rdp_client->settings->width, rdp_client->settings->height); rdp_client->current_surface = rdp_client->display->default_surface; rdp_client->available_svc = guac_common_list_alloc(); /* Init client */ freerdp* rdp_inst = freerdp_new(); rdp_inst->PreConnect = rdp_freerdp_pre_connect; rdp_inst->Authenticate = rdp_freerdp_authenticate; rdp_inst->VerifyCertificate = rdp_freerdp_verify_certificate; /* Allocate FreeRDP context */ rdp_inst->ContextSize = sizeof(rdp_freerdp_context); if (!freerdp_context_new(rdp_inst)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "FreeRDP initialization failed before connecting. Please " "check for errors earlier in the logs and/or enable " "debug-level logging for guacd."); goto fail; } ((rdp_freerdp_context*) rdp_inst->context)->client = client; /* Load keymap into client */ rdp_client->keyboard = guac_rdp_keyboard_alloc(client, settings->server_layout); /* Set default pointer */ guac_common_cursor_set_pointer(rdp_client->display->cursor); /* Connect to RDP server */ if (!freerdp_connect(rdp_inst)) { guac_rdp_client_abort(client, rdp_inst); goto fail; } /* Connection complete */ rdp_client->rdp_inst = rdp_inst; guac_timestamp last_frame_end = guac_timestamp_current(); /* Signal that reconnect has been completed */ guac_rdp_disp_reconnect_complete(rdp_client->disp); pthread_rwlock_unlock(&(rdp_client->lock)); /* Handle messages from RDP server while client is running */ while (client->state == GUAC_CLIENT_RUNNING && !guac_rdp_disp_reconnect_needed(rdp_client->disp)) { /* Update remote display size */ guac_rdp_disp_update_size(rdp_client->disp, settings, rdp_inst); /* Wait for data and construct a reasonable frame */ int wait_result = rdp_guac_client_wait_for_messages(client, GUAC_RDP_FRAME_START_TIMEOUT); if (wait_result > 0) { int processing_lag = guac_client_get_processing_lag(client); guac_timestamp frame_start = guac_timestamp_current(); /* Read server messages until frame is built */ do { guac_timestamp frame_end; int frame_remaining; /* Check the libfreerdp fds */ if (!freerdp_check_event_handles(rdp_inst->context)) { /* Flag connection failure */ wait_result = -1; break; } /* Calculate time remaining in frame */ frame_end = guac_timestamp_current(); frame_remaining = frame_start + GUAC_RDP_FRAME_DURATION - frame_end; /* Calculate time that client needs to catch up */ int time_elapsed = frame_end - last_frame_end; int required_wait = processing_lag - time_elapsed; /* Increase the duration of this frame if client is lagging */ if (required_wait > GUAC_RDP_FRAME_TIMEOUT) wait_result = rdp_guac_client_wait_for_messages(client, required_wait); /* Wait again if frame remaining */ else if (frame_remaining > 0) wait_result = rdp_guac_client_wait_for_messages(client, GUAC_RDP_FRAME_TIMEOUT); else break; } while (wait_result > 0); /* Record end of frame, excluding server-side rendering time (we * assume server-side rendering time will be consistent between any * two subsequent frames, and that this time should thus be * excluded from the required wait period of the next frame). */ last_frame_end = frame_start; } /* Test whether the RDP server is closing the connection */ int connection_closing = freerdp_shall_disconnect(rdp_inst); /* Close connection cleanly if server is disconnecting */ if (connection_closing) guac_rdp_client_abort(client, rdp_inst); /* If a low-level connection error occurred, fail */ else if (wait_result < 0) guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE, "Connection closed."); /* Flush frame only if successful */ else { guac_common_display_flush(rdp_client->display); guac_client_end_frame(client); guac_socket_flush(client->socket); } } pthread_rwlock_wrlock(&(rdp_client->lock)); /* Clean up print job, if active */ if (rdp_client->active_job != NULL) { guac_rdp_print_job_kill(rdp_client->active_job); guac_rdp_print_job_free(rdp_client->active_job); } /* Disconnect client and channels */ freerdp_disconnect(rdp_inst); /* Clean up FreeRDP internal GDI implementation */ gdi_free(rdp_inst); /* Clean up RDP client context */ freerdp_context_free(rdp_inst); /* Clean up RDP client */ freerdp_free(rdp_inst); rdp_client->rdp_inst = NULL; /* Free SVC list */ guac_common_list_free(rdp_client->available_svc); rdp_client->available_svc = NULL; /* Free RDP keyboard state */ guac_rdp_keyboard_free(rdp_client->keyboard); rdp_client->keyboard = NULL; /* Free display */ guac_common_display_free(rdp_client->display); rdp_client->display = NULL; pthread_rwlock_unlock(&(rdp_client->lock)); /* Client is now disconnected */ guac_client_log(client, GUAC_LOG_INFO, "Internal RDP client disconnected"); return 0; fail: pthread_rwlock_unlock(&(rdp_client->lock)); return 1; } void* guac_rdp_client_thread(void* data) { guac_client* client = (guac_client*) data; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; /* If Wake-on-LAN is enabled, try to wake. */ if (settings->wol_send_packet) { guac_client_log(client, GUAC_LOG_DEBUG, "Sending Wake-on-LAN packet, " "and pausing for %d seconds.", settings->wol_wait_time); /* Send the Wake-on-LAN request. */ if (guac_wol_wake(settings->wol_mac_addr, settings->wol_broadcast_addr)) return NULL; /* If wait time is specified, sleep for that amount of time. */ if (settings->wol_wait_time > 0) guac_timestamp_msleep(settings->wol_wait_time * 1000); } /* If audio enabled, choose an encoder */ if (settings->audio_enabled) { rdp_client->audio = guac_audio_stream_alloc(client, NULL, GUAC_RDP_AUDIO_RATE, GUAC_RDP_AUDIO_CHANNELS, GUAC_RDP_AUDIO_BPS); /* Warn if no audio encoding is available */ if (rdp_client->audio == NULL) guac_client_log(client, GUAC_LOG_INFO, "No available audio encoding. Sound disabled."); } /* end if audio enabled */ /* Load filesystem if drive enabled */ if (settings->drive_enabled) { /* Allocate actual emulated filesystem */ rdp_client->filesystem = guac_rdp_fs_alloc(client, settings->drive_path, settings->create_drive_path, settings->disable_download, settings->disable_upload); /* Expose filesystem to owner */ guac_client_for_owner(client, guac_rdp_fs_expose, rdp_client->filesystem); } #ifdef ENABLE_COMMON_SSH /* Connect via SSH if SFTP is enabled */ if (settings->enable_sftp) { /* Abort if username is missing */ if (settings->sftp_username == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "A username or SFTP-specific username is required if " "SFTP is enabled."); return NULL; } guac_client_log(client, GUAC_LOG_DEBUG, "Connecting via SSH for SFTP filesystem access."); rdp_client->sftp_user = guac_common_ssh_create_user(settings->sftp_username); /* Import private key, if given */ if (settings->sftp_private_key != NULL) { guac_client_log(client, GUAC_LOG_DEBUG, "Authenticating with private key."); /* Abort if private key cannot be read */ if (guac_common_ssh_user_import_key(rdp_client->sftp_user, settings->sftp_private_key, settings->sftp_passphrase)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Private key unreadable."); return NULL; } } /* Otherwise, use specified password */ else { guac_client_log(client, GUAC_LOG_DEBUG, "Authenticating with password."); guac_common_ssh_user_set_password(rdp_client->sftp_user, settings->sftp_password); } /* Attempt SSH connection */ rdp_client->sftp_session = guac_common_ssh_create_session(client, settings->sftp_hostname, settings->sftp_port, rdp_client->sftp_user, settings->sftp_server_alive_interval, settings->sftp_host_key, NULL); /* Fail if SSH connection does not succeed */ if (rdp_client->sftp_session == NULL) { /* Already aborted within guac_common_ssh_create_session() */ return NULL; } /* Load and expose filesystem */ rdp_client->sftp_filesystem = guac_common_ssh_create_sftp_filesystem(rdp_client->sftp_session, settings->sftp_root_directory, NULL, settings->sftp_disable_download, settings->sftp_disable_upload); /* Expose filesystem to connection owner */ guac_client_for_owner(client, guac_common_ssh_expose_sftp_filesystem, rdp_client->sftp_filesystem); /* Abort if SFTP connection fails */ if (rdp_client->sftp_filesystem == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE, "SFTP connection failed."); return NULL; } /* Configure destination for basic uploads, if specified */ if (settings->sftp_directory != NULL) guac_common_ssh_sftp_set_upload_path( rdp_client->sftp_filesystem, settings->sftp_directory); guac_client_log(client, GUAC_LOG_DEBUG, "SFTP connection succeeded."); } #endif /* Continue handling connections until error or client disconnect */ while (client->state == GUAC_CLIENT_RUNNING) { if (guac_rdp_handle_connection(client)) break; } return NULL; } guacamole-server-1.3.0/src/protocols/rdp/print-job.h0000644000175100001440000001515213764613616017370 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_PRINT_JOB_H #define GUAC_RDP_PRINT_JOB_H #include #include #include #include #include /** * The maximum number of bytes in the filename of an RDP print job sent as a * file over the Guacamole protocol, including NULL terminator. */ #define GUAC_RDP_PRINT_JOB_FILENAME_MAX_LENGTH 1024 /** * The default filename to use for the PDF output of an RDP print job if no * document title can be found within the printed data. */ #define GUAC_RDP_PRINT_JOB_DEFAULT_FILENAME "guacamole-print.pdf" /** * The maximum number of bytes to search through at the beginning of a * PostScript document when locating the document title. */ #define GUAC_RDP_PRINT_JOB_TITLE_SEARCH_LENGTH 2048 /** * The current state of an RDP print job. */ typedef enum guac_rdp_print_job_state { /** * The print stream has been opened with the Guacamole client, but the * client has not yet confirmed that it is ready to receive data. */ GUAC_RDP_PRINT_JOB_WAITING_FOR_ACK, /** * The print stream has been opened with the Guacamole client, and the * client has responded with an "ack", confirming that it is ready to * receive data (or that data has been received and it is ready to receive * more). */ GUAC_RDP_PRINT_JOB_ACK_RECEIVED, /** * The print stream has been closed or the printer is terminating, and no * further data should be sent to the client. */ GUAC_RDP_PRINT_JOB_CLOSED } guac_rdp_print_job_state; /** * Data specific to an instance of the printer device. */ typedef struct guac_rdp_print_job { /** * The Guacamole client associated with the RDP session. */ guac_client* client; /** * The user receiving the output from the print job. */ guac_user* user; /** * The stream along which the print job output should be sent. */ guac_stream* stream; /** * The PID of the print filter process converting PostScript data into PDF. */ pid_t filter_pid; /** * The filename that should be used when the converted PDF output is * streamed to the Guacamole user. This value will be automatically * determined based on the contents of the printed document. */ char filename[GUAC_RDP_PRINT_JOB_FILENAME_MAX_LENGTH]; /** * File descriptor that should be written to when sending documents to the * printer. */ int input_fd; /** * File descriptor that should be read from when receiving output from the * printer. */ int output_fd; /** * The current state of the print stream, dependent on whether the client * has acknowledged creation of the stream, whether the client has * acknowledged receipt of data along the steam, and whether the print * stream itself has closed. */ guac_rdp_print_job_state state; /** * Lock which is acquired prior to modifying the state property or waiting * on the state_modified conditional. */ pthread_mutex_t state_lock; /** * Conditional which signals modification to the state property of this * structure. */ pthread_cond_t state_modified; /** * Thread which transfers data from the printer to the Guacamole client. */ pthread_t output_thread; /** * The number of bytes received in the current print job. */ int bytes_received; } guac_rdp_print_job; /** * A blob of print data being sent to the Guacamole user. */ typedef struct guac_rdp_print_blob { /** * The print job which generated the data being sent. */ guac_rdp_print_job* job; /** * The data being sent. */ void* buffer; /** * The number of bytes of data being sent. */ int length; } guac_rdp_print_blob; /** * Allocates a new print job for the given user. It is expected that this * function will be invoked via a call to guac_client_for_user() or * guac_client_for_owner(). * * @param user * The user that should receive the output from the print job. * * @param data * An arbitrary data parameter required by guac_client_for_user() and * guac_client_for_owner() but ignored by this function. This should * always be NULL. * * @return * A pointer to a newly-allocated guac_rdp_print_job, or NULL if the * print job could not be created. */ void* guac_rdp_print_job_alloc(guac_user* user, void* data); /** * Writes PostScript print data to the given active print job. The print job * will automatically convert this data to PDF, streaming the result to the * Guacamole user associated with the print job. This function may block if * the print job is not yet ready for more data. * * @param job * The print job to write to. * * @param buffer * The PostScript print data to write to the given print job. * * @param length * The number of bytes of PostScript print data to write. * * @return * The number of bytes written, or -1 if an error occurs which prevents * further writes. */ int guac_rdp_print_job_write(guac_rdp_print_job* job, void* buffer, int length); /** * Frees the memory associated with the given print job, closing all underlying * file descriptors, and ending the file transfer to the associated Guacamole * user. This function may block if the print filter process has not yet * finished processing the received data. * * @param job * The print job to free. */ void guac_rdp_print_job_free(guac_rdp_print_job* job); /** * Forcibly kills the given print job, stopping all associated processing and * streaming. The memory associated with the print job will still need to be * reclaimed via guac_rdp_print_job_free(). * * @param job * The print job to kill. */ void guac_rdp_print_job_kill(guac_rdp_print_job* job); #endif guacamole-server-1.3.0/src/protocols/rdp/sftp.c0000644000175100001440000000253713764613616016436 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common-ssh/sftp.h" #include "rdp.h" #include "sftp.h" #include #include int guac_rdp_sftp_file_handler(guac_user* user, guac_stream* stream, char* mimetype, char* filename) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_common_ssh_sftp_filesystem* filesystem = rdp_client->sftp_filesystem; /* Handle file upload */ return guac_common_ssh_sftp_handle_file_stream(filesystem, user, stream, mimetype, filename); } guacamole-server-1.3.0/src/protocols/rdp/gdi.c0000644000175100001440000002761713764613616016233 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "bitmap.h" #include "color.h" #include "common/display.h" #include "common/surface.h" #include "rdp.h" #include "settings.h" #include #include #include #include #include #include #include #include #include guac_transfer_function guac_rdp_rop3_transfer_function(guac_client* client, int rop3) { /* Translate supported ROP3 opcodes into composite modes */ switch (rop3) { /* "DSon" !(src | dest) */ case 0x11: return GUAC_TRANSFER_BINARY_NOR; /* "DSna" !src & dest */ case 0x22: return GUAC_TRANSFER_BINARY_NSRC_AND; /* "Sn" !src */ case 0x33: return GUAC_TRANSFER_BINARY_NSRC; /* "SDna" (src & !dest) */ case 0x44: return GUAC_TRANSFER_BINARY_NDEST_AND; /* "Dn" !dest */ case 0x55: return GUAC_TRANSFER_BINARY_NDEST; /* "SRCINVERT" (src ^ dest) */ case 0x66: return GUAC_TRANSFER_BINARY_XOR; /* "DSan" !(src & dest) */ case 0x77: return GUAC_TRANSFER_BINARY_NAND; /* "SRCAND" (src & dest) */ case 0x88: return GUAC_TRANSFER_BINARY_AND; /* "DSxn" !(src ^ dest) */ case 0x99: return GUAC_TRANSFER_BINARY_XNOR; /* "MERGEPAINT" (!src | dest)*/ case 0xBB: return GUAC_TRANSFER_BINARY_NSRC_OR; /* "SDno" (src | !dest) */ case 0xDD: return GUAC_TRANSFER_BINARY_NDEST_OR; /* "SRCPAINT" (src | dest) */ case 0xEE: return GUAC_TRANSFER_BINARY_OR; /* 0x00 = "BLACKNESS" (0) */ /* 0xAA = "NOP" (dest) */ /* 0xCC = "SRCCOPY" (src) */ /* 0xFF = "WHITENESS" (1) */ } /* Log warning if ROP3 opcode not supported */ guac_client_log(client, GUAC_LOG_INFO, "guac_rdp_rop3_transfer_function: " "UNSUPPORTED opcode = 0x%02X", rop3); /* Default to BINARY_SRC */ return GUAC_TRANSFER_BINARY_SRC; } BOOL guac_rdp_gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_common_surface* current_surface = ((guac_rdp_client*) client->data)->current_surface; int x = dstblt->nLeftRect; int y = dstblt->nTopRect; int w = dstblt->nWidth; int h = dstblt->nHeight; switch (dstblt->bRop) { /* Blackness */ case 0: /* Send black rectangle */ guac_common_surface_set(current_surface, x, y, w, h, 0x00, 0x00, 0x00, 0xFF); break; /* DSTINVERT */ case 0x55: guac_common_surface_transfer(current_surface, x, y, w, h, GUAC_TRANSFER_BINARY_NDEST, current_surface, x, y); break; /* NOP */ case 0xAA: break; /* Whiteness */ case 0xFF: guac_common_surface_set(current_surface, x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF); break; /* Unsupported ROP3 */ default: guac_client_log(client, GUAC_LOG_INFO, "guac_rdp_gdi_dstblt(rop3=0x%x)", dstblt->bRop); } return TRUE; } BOOL guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { /* * Note that this is not a full implementation of PATBLT. This is a * fallback implementation which only renders a solid block of background * color using the specified ROP3 operation, ignoring whatever brush * was actually specified. * * As libguac-client-rdp explicitly tells the server not to send PATBLT, * well-behaved RDP servers will not use this operation at all, while * others will at least have a fallback. */ /* Get client and current layer */ guac_client* client = ((rdp_freerdp_context*) context)->client; guac_common_surface* current_surface = ((guac_rdp_client*) client->data)->current_surface; int x = patblt->nLeftRect; int y = patblt->nTopRect; int w = patblt->nWidth; int h = patblt->nHeight; /* * Warn that rendering is a fallback, as the server should not be sending * this order. */ guac_client_log(client, GUAC_LOG_INFO, "Using fallback PATBLT (server is ignoring " "negotiated client capabilities)"); /* Render rectangle based on ROP */ switch (patblt->bRop) { /* If blackness, send black rectangle */ case 0x00: guac_common_surface_set(current_surface, x, y, w, h, 0x00, 0x00, 0x00, 0xFF); break; /* If NOP, do nothing */ case 0xAA: break; /* If operation is just a copy, send foreground only */ case 0xCC: case 0xF0: guac_common_surface_set(current_surface, x, y, w, h, (patblt->foreColor >> 16) & 0xFF, (patblt->foreColor >> 8 ) & 0xFF, (patblt->foreColor ) & 0xFF, 0xFF); break; /* If whiteness, send white rectangle */ case 0xFF: guac_common_surface_set(current_surface, x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF); break; /* Otherwise, invert entire rect */ default: guac_common_surface_transfer(current_surface, x, y, w, h, GUAC_TRANSFER_BINARY_NDEST, current_surface, x, y); } return TRUE; } BOOL guac_rdp_gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_common_surface* current_surface = ((guac_rdp_client*) client->data)->current_surface; int x = scrblt->nLeftRect; int y = scrblt->nTopRect; int w = scrblt->nWidth; int h = scrblt->nHeight; int x_src = scrblt->nXSrc; int y_src = scrblt->nYSrc; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Copy screen rect to current surface */ guac_common_surface_copy(rdp_client->display->default_surface, x_src, y_src, w, h, current_surface, x, y); return TRUE; } BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_common_surface* current_surface = ((guac_rdp_client*) client->data)->current_surface; guac_rdp_bitmap* bitmap = (guac_rdp_bitmap*) memblt->bitmap; int x = memblt->nLeftRect; int y = memblt->nTopRect; int w = memblt->nWidth; int h = memblt->nHeight; int x_src = memblt->nXSrc; int y_src = memblt->nYSrc; /* Make sure that the recieved bitmap is not NULL before processing */ if (bitmap == NULL) { guac_client_log(client, GUAC_LOG_INFO, "NULL bitmap found in memblt instruction."); return TRUE; } switch (memblt->bRop) { /* If blackness, send black rectangle */ case 0x00: guac_common_surface_set(current_surface, x, y, w, h, 0x00, 0x00, 0x00, 0xFF); break; /* If NOP, do nothing */ case 0xAA: break; /* If operation is just SRC, simply copy */ case 0xCC: /* If not cached, cache if necessary */ if (bitmap->layer == NULL && bitmap->used >= 1) guac_rdp_cache_bitmap(context, memblt->bitmap); /* If not cached, send as PNG */ if (bitmap->layer == NULL) { if (memblt->bitmap->data != NULL) { /* Create surface from image data */ cairo_surface_t* surface = cairo_image_surface_create_for_data( memblt->bitmap->data + 4*(x_src + y_src*memblt->bitmap->width), CAIRO_FORMAT_RGB24, w, h, 4*memblt->bitmap->width); /* Send surface to buffer */ guac_common_surface_draw(current_surface, x, y, surface); /* Free surface */ cairo_surface_destroy(surface); } } /* Otherwise, copy */ else guac_common_surface_copy(bitmap->layer->surface, x_src, y_src, w, h, current_surface, x, y); /* Increment usage counter */ ((guac_rdp_bitmap*) bitmap)->used++; break; /* If whiteness, send white rectangle */ case 0xFF: guac_common_surface_set(current_surface, x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF); break; /* Otherwise, use transfer */ default: /* If not available as a surface, make available. */ if (bitmap->layer == NULL) guac_rdp_cache_bitmap(context, memblt->bitmap); guac_common_surface_transfer(bitmap->layer->surface, x_src, y_src, w, h, guac_rdp_rop3_transfer_function(client, memblt->bRop), current_surface, x, y); /* Increment usage counter */ ((guac_rdp_bitmap*) bitmap)->used++; } return TRUE; } BOOL guac_rdp_gdi_opaquerect(rdpContext* context, const OPAQUE_RECT_ORDER* opaque_rect) { /* Get client data */ guac_client* client = ((rdp_freerdp_context*) context)->client; UINT32 color = guac_rdp_convert_color(context, opaque_rect->color); guac_common_surface* current_surface = ((guac_rdp_client*) client->data)->current_surface; int x = opaque_rect->nLeftRect; int y = opaque_rect->nTopRect; int w = opaque_rect->nWidth; int h = opaque_rect->nHeight; guac_common_surface_set(current_surface, x, y, w, h, (color >> 16) & 0xFF, (color >> 8 ) & 0xFF, (color ) & 0xFF, 0xFF); return TRUE; } BOOL guac_rdp_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* If no bounds given, clear bounding rect */ if (bounds == NULL) guac_common_surface_reset_clip(rdp_client->display->default_surface); /* Otherwise, set bounding rectangle */ else guac_common_surface_clip(rdp_client->display->default_surface, bounds->left, bounds->top, bounds->right - bounds->left + 1, bounds->bottom - bounds->top + 1); return TRUE; } BOOL guac_rdp_gdi_end_paint(rdpContext* context) { /* IGNORE */ return TRUE; } BOOL guac_rdp_gdi_desktop_resize(rdpContext* context) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_common_surface_resize(rdp_client->display->default_surface, guac_rdp_get_width(context->instance), guac_rdp_get_height(context->instance)); guac_common_surface_reset_clip(rdp_client->display->default_surface); guac_client_log(client, GUAC_LOG_DEBUG, "Server resized display to %ix%i", guac_rdp_get_width(context->instance), guac_rdp_get_height(context->instance)); return TRUE; } guacamole-server-1.3.0/src/protocols/rdp/color.h0000644000175100001440000000455713764613616016611 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_COLOR_H #define GUAC_RDP_COLOR_H #include #include /** * Returns the FreeRDP pixel format ID corresponding to the 32-bit RGB format * used by the Cairo library's image surfaces. Cairo handles colors in terms of * integers in native endianness, with CAIRO_FORMAT_ARGB32 representing a color * format where the alpha channel is stored in the most significant byte, * followed by red, green, and blue. FreeRDP handles colors in terms of * absolute byte order, with PIXEL_FORMAT_ARGB32 representing a color format * where the alpha channel is in byte 0, followed by red at byte 1, etc. * * @param alpha * TRUE if the returned FreeRDP pixel format should correspond to Cairo's * CAIRO_FORMAT_ARGB32, FALSE if the returned format should correspond to * Cairo's CAIRO_FORMAT_RGB24. * * @return * The FreeRDP pixel format ID that corresponds to the 32-bit RGB format * used by the Cairo library. */ UINT32 guac_rdp_get_native_pixel_format(BOOL alpha); /** * Converts the given color to ARGB32. The color given may be an index * referring to the palette, a 16-bit or 32-bit color, etc. all depending on * the current color depth of the RDP session. * * @param context * The rdpContext associated with the current RDP session. * * @param color * A color value in the format of the current RDP session. * * @return * A 32-bit ARGB color, where the low 8 bits are the blue component and * the high 8 bits are alpha. */ UINT32 guac_rdp_convert_color(rdpContext* context, UINT32 color); #endif guacamole-server-1.3.0/src/protocols/rdp/decompose.h0000644000175100001440000000341713702142276017432 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_DECOMPOSE_H #define GUAC_RDP_DECOMPOSE_H #include "config.h" #include "keyboard.h" /** * Attempts to type the given keysym by decomposing the associated character * into the dead key and base key pair which would be used to type that * character on a keyboard which lacks the necessary dedicated key. The key * events for the dead key and base key are sent only if the keyboard layout of * the given keyboard defines those keys. * * For example, the keysym for "ò" (0x00F2) would decompose into a dead grave * (`) and the base key "o". May it rest in peace. * * @param keyboard * The guac_rdp_keyboard associated with the current RDP session. * * @param keysym * The keysym being pressed. * * @return * Zero if the keysym was successfully decomposed and sent to the RDP * server as a pair of key events (the dead key and base key), non-zero * otherwise. */ int guac_rdp_decompose_keysym(guac_rdp_keyboard* keyboard, int keysym); #endif guacamole-server-1.3.0/src/protocols/rdp/client.c0000644000175100001440000001702013764613616016731 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "client.h" #include "channels/audio-input/audio-buffer.h" #include "channels/cliprdr.h" #include "channels/disp.h" #include "common/recording.h" #include "config.h" #include "fs.h" #include "log.h" #include "rdp.h" #include "settings.h" #include "user.h" #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" #include "common-ssh/ssh.h" #include "common-ssh/user.h" #endif #include #include #include #include #include #include #include #include #include #include #include /** * Tests whether the given path refers to a directory which the current user * can write to. If the given path is not a directory, is not writable, or is * not a link pointing to a writable directory, this test will fail, and * errno will be set appropriately. * * @param path * The path to test. * * @return * Non-zero if the given path is (or points to) a writable directory, zero * otherwise. */ static int is_writable_directory(const char* path) { /* Verify path is writable */ if (faccessat(AT_FDCWD, path, W_OK, 0)) return 0; /* If writable, verify path is actually a directory */ DIR* dir = opendir(path); if (!dir) return 0; /* Path is both writable and a directory */ closedir(dir); return 1; } int guac_client_init(guac_client* client, int argc, char** argv) { /* Automatically set HOME environment variable if unset (FreeRDP's * initialization process will fail within freerdp_settings_new() if this * is unset) */ const char* current_home = getenv("HOME"); if (current_home == NULL) { /* Warn if the correct home directory cannot be determined */ struct passwd* passwd = getpwuid(getuid()); if (passwd == NULL) guac_client_log(client, GUAC_LOG_WARNING, "FreeRDP initialization " "may fail: The \"HOME\" environment variable is unset and " "its correct value could not be automatically determined: " "%s", strerror(errno)); /* Warn if the correct home directory could be determined but can't be * assigned */ else if (setenv("HOME", passwd->pw_dir, 1)) guac_client_log(client, GUAC_LOG_WARNING, "FreeRDP initialization " "may fail: The \"HOME\" environment variable is unset " "and its correct value (detected as \"%s\") could not be " "assigned: %s", passwd->pw_dir, strerror(errno)); /* HOME has been successfully set */ else { guac_client_log(client, GUAC_LOG_DEBUG, "\"HOME\" " "environment variable was unset and has been " "automatically set to \"%s\"", passwd->pw_dir); current_home = passwd->pw_dir; } } /* Verify that detected home directory is actually writable and actually a * directory, as FreeRDP initialization will mysteriously fail otherwise */ if (current_home != NULL && !is_writable_directory(current_home)) { if (errno == EACCES) guac_client_log(client, GUAC_LOG_WARNING, "FreeRDP initialization " "may fail: The current user's home directory (\"%s\") is " "not writable, but FreeRDP generally requires a writable " "home directory for storage of configuration files and " "certificates.", current_home); else if (errno == ENOTDIR) guac_client_log(client, GUAC_LOG_WARNING, "FreeRDP initialization " "may fail: The current user's home directory (\"%s\") is " "not actually a directory, but FreeRDP generally requires " "a writable home directory for storage of configuration " "files and certificates.", current_home); else guac_client_log(client, GUAC_LOG_WARNING, "FreeRDP initialization " "may fail: Writability of the current user's home " "directory (\"%s\") could not be determined: %s", current_home, strerror(errno)); } /* Set client args */ client->args = GUAC_RDP_CLIENT_ARGS; /* Alloc client data */ guac_rdp_client* rdp_client = calloc(1, sizeof(guac_rdp_client)); client->data = rdp_client; /* Init clipboard */ rdp_client->clipboard = guac_rdp_clipboard_alloc(client); /* Init display update module */ rdp_client->disp = guac_rdp_disp_alloc(); /* Redirect FreeRDP log messages to guac_client_log() */ guac_rdp_redirect_wlog(client); /* Recursive attribute for locks */ pthread_mutexattr_init(&(rdp_client->attributes)); pthread_mutexattr_settype(&(rdp_client->attributes), PTHREAD_MUTEX_RECURSIVE); /* Initalize the lock */ pthread_rwlock_init(&(rdp_client->lock), NULL); /* Set handlers */ client->join_handler = guac_rdp_user_join_handler; client->free_handler = guac_rdp_client_free_handler; #ifdef ENABLE_COMMON_SSH guac_common_ssh_init(client); #endif return 0; } int guac_rdp_client_free_handler(guac_client* client) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Wait for client thread */ pthread_join(rdp_client->client_thread, NULL); /* Free parsed settings */ if (rdp_client->settings != NULL) guac_rdp_settings_free(rdp_client->settings); /* Clean up clipboard */ guac_rdp_clipboard_free(rdp_client->clipboard); /* Free display update module */ guac_rdp_disp_free(rdp_client->disp); /* Clean up filesystem, if allocated */ if (rdp_client->filesystem != NULL) guac_rdp_fs_free(rdp_client->filesystem); #ifdef ENABLE_COMMON_SSH /* Free SFTP filesystem, if loaded */ if (rdp_client->sftp_filesystem) guac_common_ssh_destroy_sftp_filesystem(rdp_client->sftp_filesystem); /* Free SFTP session */ if (rdp_client->sftp_session) guac_common_ssh_destroy_session(rdp_client->sftp_session); /* Free SFTP user */ if (rdp_client->sftp_user) guac_common_ssh_destroy_user(rdp_client->sftp_user); guac_common_ssh_uninit(); #endif /* Clean up recording, if in progress */ if (rdp_client->recording != NULL) guac_common_recording_free(rdp_client->recording); /* Clean up audio stream, if allocated */ if (rdp_client->audio != NULL) guac_audio_stream_free(rdp_client->audio); /* Clean up audio input buffer, if allocated */ if (rdp_client->audio_input != NULL) guac_rdp_audio_buffer_free(rdp_client->audio_input); pthread_rwlock_destroy(&(rdp_client->lock)); /* Free client data */ free(rdp_client); return 0; } guacamole-server-1.3.0/src/protocols/rdp/upload.h0000644000175100001440000000360613764613616016751 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_UPLOAD_H #define GUAC_RDP_UPLOAD_H #include "common/json.h" #include #include #include #include /** * Structure which represents the current state of an upload. */ typedef struct guac_rdp_upload_status { /** * The overall offset within the file that the next write should * occur at. */ int offset; /** * The ID of the file being written to. */ int file_id; } guac_rdp_upload_status; /** * Handler for inbound files related to file uploads. */ guac_user_file_handler guac_rdp_upload_file_handler; /** * Handler for stream data related to file uploads. */ guac_user_blob_handler guac_rdp_upload_blob_handler; /** * Handler for end-of-stream related to file uploads. */ guac_user_end_handler guac_rdp_upload_end_handler; /** * Handler for put messages. In context of uploads and the filesystem exposed * via the Guacamole protocol, put messages request write access to a file * within the filesystem. */ guac_user_put_handler guac_rdp_upload_put_handler; #endif guacamole-server-1.3.0/src/protocols/rdp/ls.h0000644000175100001440000000334113764613616016077 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_LS_H #define GUAC_RDP_LS_H #include "common/json.h" #include "fs.h" #include #include #include #include /** * The current state of a directory listing operation. */ typedef struct guac_rdp_ls_status { /** * The filesystem associated with the directory being listed. */ guac_rdp_fs* fs; /** * The file ID of the directory being listed. */ int file_id; /** * The absolute path of the directory being listed. */ char directory_name[GUAC_RDP_FS_MAX_PATH]; /** * The current state of the JSON directory object being written. */ guac_common_json_state json_state; } guac_rdp_ls_status; /** * Handler for ack messages received due to receipt of a "body" or "blob" * instruction associated with a directory list operation. */ guac_user_ack_handler guac_rdp_ls_ack_handler; #endif guacamole-server-1.3.0/src/protocols/rdp/glyph.c0000644000175100001440000001215013764613616016575 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "color.h" #include "common/surface.h" #include "config.h" #include "glyph.h" #include "rdp.h" #include #include #include #include #include /* Define cairo_format_stride_for_width() if missing */ #ifndef HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH #define cairo_format_stride_for_width(format, width) (width*4) #endif BOOL guac_rdp_glyph_new(rdpContext* context, const rdpGlyph* glyph) { int x, y, i; int stride; unsigned char* image_buffer; unsigned char* image_buffer_row; unsigned char* data = glyph->aj; int width = glyph->cx; int height = glyph->cy; /* Init Cairo buffer */ stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); image_buffer = malloc(height*stride); image_buffer_row = image_buffer; /* Copy image data from image data to buffer */ for (y = 0; ysurface = cairo_image_surface_create_for_data( image_buffer, CAIRO_FORMAT_ARGB32, width, height, stride); return TRUE; } BOOL guac_rdp_glyph_draw(rdpContext* context, const rdpGlyph* glyph, GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, GLYPH_CALLBACK_INT32 w, GLYPH_CALLBACK_INT32 h, GLYPH_CALLBACK_INT32 sx, GLYPH_CALLBACK_INT32 sy, BOOL redundant) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_common_surface* current_surface = rdp_client->current_surface; uint32_t fgcolor = rdp_client->glyph_color; /* Paint with glyph as mask */ guac_common_surface_paint(current_surface, x, y, ((guac_rdp_glyph*) glyph)->surface, (fgcolor & 0xFF0000) >> 16, (fgcolor & 0x00FF00) >> 8, fgcolor & 0x0000FF); return TRUE; } void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph) { unsigned char* image_buffer = cairo_image_surface_get_data( ((guac_rdp_glyph*) glyph)->surface); /* Free surface */ cairo_surface_destroy(((guac_rdp_glyph*) glyph)->surface); free(image_buffer); /* NOTE: FreeRDP-allocated memory for the rdpGlyph will NOT be * automatically released after this free handler is invoked, thus we must * do so manually here */ free(glyph->aj); free(glyph); } BOOL guac_rdp_glyph_begindraw(rdpContext* context, GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, GLYPH_CALLBACK_INT32 width, GLYPH_CALLBACK_INT32 height, UINT32 fgcolor, UINT32 bgcolor, BOOL redundant) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Fill background with color if specified */ if (width != 0 && height != 0 && !redundant) { /* Convert background color */ bgcolor = guac_rdp_convert_color(context, bgcolor); guac_common_surface_set(rdp_client->current_surface, x, y, width, height, (bgcolor & 0xFF0000) >> 16, (bgcolor & 0x00FF00) >> 8, (bgcolor & 0x0000FF), 0xFF); } /* Convert foreground color */ rdp_client->glyph_color = guac_rdp_convert_color(context, fgcolor); return TRUE; } BOOL guac_rdp_glyph_enddraw(rdpContext* context, GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, GLYPH_CALLBACK_INT32 width, GLYPH_CALLBACK_INT32 height, UINT32 fgcolor, UINT32 bgcolor) { /* IGNORE */ return TRUE; } guacamole-server-1.3.0/src/protocols/rdp/download.h0000644000175100001440000000375013764613616017274 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_DOWNLOAD_H #define GUAC_RDP_DOWNLOAD_H #include "common/json.h" #include #include #include #include /** * The transfer status of a file being downloaded. */ typedef struct guac_rdp_download_status { /** * The file ID of the file being downloaded. */ int file_id; /** * The current position within the file. */ uint64_t offset; } guac_rdp_download_status; /** * Handler for acknowledgements of receipt of data related to file downloads. */ guac_user_ack_handler guac_rdp_download_ack_handler; /** * Handler for get messages. In context of downloads and the filesystem exposed * via the Guacamole protocol, get messages request the body of a file within * the filesystem. */ guac_user_get_handler guac_rdp_download_get_handler; /** * Callback for guac_client_for_user() and similar functions which initiates a * file download to a specific user if that user is still connected. The path * for the file to be downloaded must be passed as the arbitrary data parameter * for the function invoking this callback. */ guac_user_callback guac_rdp_download_to_user; #endif guacamole-server-1.3.0/src/protocols/rdp/beep.h0000644000175100001440000000414413764613616016376 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RDP_BEEP_H #define GUAC_RDP_BEEP_H #include #include /** * The sample rate of the each generated beep, in samples per second. */ #define GUAC_RDP_BEEP_SAMPLE_RATE 8000 /** * The amplitude (volume) of each beep. As the beep is generated as 8-bit * signed PCM, this should be kept between 0 and 127 inclusive. */ #define GUAC_RDP_BEEP_AMPLITUDE 64 /** * The maximum duration of each beep, in milliseconds. This value should be * kept relatively small to ensure the amount of data sent for each beep is * minimal. */ #define GUAC_RDP_BEEP_MAX_DURATION 500 /** * Processes a Play Sound PDU received from the RDP server, beeping for the * requested duration and at the requested frequency. If audio has been * disabled for the connection, the Play Sound PDU will be silently ignored, * and this function has no effect. Beeps in excess of the maximum specified * by GUAC_RDP_BEEP_MAX_DURATION will be truncated. * * @param context * The rdpContext associated with the current RDP session. * * @param play_sound * The PLAY_SOUND_UPDATE structure representing the received Play Sound * PDU. * * @return * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_beep_play_sound(rdpContext* context, const PLAY_SOUND_UPDATE* play_sound); #endif guacamole-server-1.3.0/src/protocols/rdp/Makefile.am0000644000175100001440000002231413770536337017346 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac-client-rdp.la SUBDIRS = . tests # # Main RDP client library # nodist_libguac_client_rdp_la_SOURCES = \ _generated_channel_entry_wrappers.c \ _generated_keymaps.c libguac_client_rdp_la_SOURCES = \ argv.c \ beep.c \ bitmap.c \ channels/audio-input/audio-buffer.c \ channels/audio-input/audio-input.c \ channels/cliprdr.c \ channels/common-svc.c \ channels/disp.c \ channels/pipe-svc.c \ channels/rail.c \ channels/rdpdr/rdpdr-fs-messages-dir-info.c \ channels/rdpdr/rdpdr-fs-messages-file-info.c \ channels/rdpdr/rdpdr-fs-messages-vol-info.c \ channels/rdpdr/rdpdr-fs-messages.c \ channels/rdpdr/rdpdr-fs.c \ channels/rdpdr/rdpdr-messages.c \ channels/rdpdr/rdpdr-printer.c \ channels/rdpdr/rdpdr.c \ channels/rdpsnd/rdpsnd-messages.c \ channels/rdpsnd/rdpsnd.c \ client.c \ color.c \ decompose.c \ download.c \ error.c \ fs.c \ gdi.c \ glyph.c \ input.c \ keyboard.c \ keymap.c \ log.c \ ls.c \ plugins/channels.c \ plugins/ptr-string.c \ pointer.c \ print-job.c \ rdp.c \ resolution.c \ settings.c \ unicode.c \ upload.c \ user.c noinst_HEADERS = \ argv.h \ beep.h \ bitmap.h \ channels/audio-input/audio-buffer.h \ channels/audio-input/audio-input.h \ channels/cliprdr.h \ channels/common-svc.h \ channels/disp.h \ channels/pipe-svc.h \ channels/rail.h \ channels/rdpdr/rdpdr-fs-messages-dir-info.h \ channels/rdpdr/rdpdr-fs-messages-file-info.h \ channels/rdpdr/rdpdr-fs-messages-vol-info.h \ channels/rdpdr/rdpdr-fs-messages.h \ channels/rdpdr/rdpdr-fs.h \ channels/rdpdr/rdpdr-messages.h \ channels/rdpdr/rdpdr-printer.h \ channels/rdpdr/rdpdr.h \ channels/rdpsnd/rdpsnd-messages.h \ channels/rdpsnd/rdpsnd.h \ client.h \ color.h \ decompose.h \ download.h \ error.h \ fs.h \ gdi.h \ glyph.h \ input.h \ keyboard.h \ keymap.h \ log.h \ ls.h \ plugins/channels.h \ plugins/guacai/guacai-messages.h \ plugins/guacai/guacai.h \ plugins/ptr-string.h \ pointer.h \ print-job.h \ rdp.h \ resolution.h \ settings.h \ unicode.h \ upload.h \ user.h libguac_client_rdp_la_CFLAGS = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ \ @RDP_CFLAGS@ libguac_client_rdp_la_LDFLAGS = \ -version-info 0:0:0 \ @CAIRO_LIBS@ \ @PTHREAD_LIBS@ \ @RDP_LIBS@ libguac_client_rdp_la_LIBADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ # # Plugins for FreeRDP # freerdp_LTLIBRARIES = \ libguac-common-svc-client.la \ libguacai-client.la freerdpdir = @FREERDP2_PLUGIN_DIR@ # # Common SVC plugin (shared by RDPDR, RDPSND, etc.) # libguac_common_svc_client_la_SOURCES = \ plugins/guac-common-svc/guac-common-svc.c libguac_common_svc_client_la_CFLAGS = \ -Werror -Wall -Iinclude \ @LIBGUAC_INCLUDE@ \ @RDP_CFLAGS@ libguac_common_svc_client_la_LDFLAGS = \ -module -avoid-version -shared \ @RDP_LIBS@ libguac_common_svc_client_la_LIBADD = \ @LIBGUAC_LTLIB@ # # Audio Input # libguacai_client_la_SOURCES = \ channels/audio-input/audio-buffer.c \ plugins/guacai/guacai-messages.c \ plugins/guacai/guacai.c \ plugins/ptr-string.c libguacai_client_la_CFLAGS = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ \ @RDP_CFLAGS@ libguacai_client_la_LDFLAGS = \ -module -avoid-version -shared \ @PTHREAD_LIBS@ \ @RDP_LIBS@ libguacai_client_la_LIBADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ # # Optional SFTP support # if ENABLE_COMMON_SSH libguac_client_rdp_la_SOURCES += sftp.c noinst_HEADERS += sftp.h libguac_client_rdp_la_LIBADD += @COMMON_SSH_LTLIB@ endif # # Autogenerated keymaps and channel wrapper functions # CLEANFILES = \ _generated_channel_entry_wrappers.c \ _generated_keymaps.c BUILT_SOURCES = \ _generated_channel_entry_wrappers.c \ _generated_keymaps.c rdp_keymaps = \ $(srcdir)/keymaps/base.keymap \ $(srcdir)/keymaps/failsafe.keymap \ $(srcdir)/keymaps/de_de_qwertz.keymap \ $(srcdir)/keymaps/de_ch_qwertz.keymap \ $(srcdir)/keymaps/en_gb_qwerty.keymap \ $(srcdir)/keymaps/en_us_qwerty.keymap \ $(srcdir)/keymaps/es_es_qwerty.keymap \ $(srcdir)/keymaps/es_latam_qwerty.keymap \ $(srcdir)/keymaps/fr_be_azerty.keymap \ $(srcdir)/keymaps/fr_ch_qwertz.keymap \ $(srcdir)/keymaps/fr_fr_azerty.keymap \ $(srcdir)/keymaps/hu_hu_qwertz.keymap \ $(srcdir)/keymaps/it_it_qwerty.keymap \ $(srcdir)/keymaps/ja_jp_qwerty.keymap \ $(srcdir)/keymaps/pt_br_qwerty.keymap \ $(srcdir)/keymaps/sv_se_qwerty.keymap \ $(srcdir)/keymaps/da_dk_qwerty.keymap \ $(srcdir)/keymaps/tr_tr_qwerty.keymap _generated_keymaps.c: $(rdp_keymaps) $(srcdir)/keymaps/generate.pl $(AM_V_GEN) $(srcdir)/keymaps/generate.pl $(rdp_keymaps) _generated_channel_entry_wrappers.c: $(srcdir)/plugins/channels.h $(srcdir)/plugins/generate-entry-wrappers.pl $(AM_V_GEN) $(srcdir)/plugins/generate-entry-wrappers.pl $(srcdir)/plugins/channels.h EXTRA_DIST = \ $(rdp_keymaps) \ keymaps/generate.pl \ plugins/generate-entry-wrappers.pl guacamole-server-1.3.0/src/protocols/ssh/0000755000175100001440000000000013772471161015373 500000000000000guacamole-server-1.3.0/src/protocols/ssh/clipboard.c0000644000175100001440000000373313702142276017417 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "clipboard.h" #include "common/clipboard.h" #include "ssh.h" #include "terminal/terminal.h" #include #include #include int guac_ssh_clipboard_handler(guac_user* user, guac_stream* stream, char* mimetype) { /* Clear clipboard and prepare for new data */ guac_client* client = user->client; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; guac_common_clipboard_reset(ssh_client->clipboard, mimetype); /* Set handlers for clipboard stream */ stream->blob_handler = guac_ssh_clipboard_blob_handler; stream->end_handler = guac_ssh_clipboard_end_handler; return 0; } int guac_ssh_clipboard_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { /* Append new data */ guac_client* client = user->client; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; guac_common_clipboard_append(ssh_client->clipboard, data, length); return 0; } int guac_ssh_clipboard_end_handler(guac_user* user, guac_stream* stream) { /* Nothing to do - clipboard is implemented within client */ return 0; } guacamole-server-1.3.0/src/protocols/ssh/argv.c0000644000175100001440000000565613770536337016437 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "ssh.h" #include "terminal/terminal.h" #include #include #include #include #include #include int guac_ssh_argv_callback(guac_user* user, const char* mimetype, const char* name, const char* value, void* data) { guac_client* client = user->client; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; guac_terminal* terminal = ssh_client->term; /* Update color scheme */ if (strcmp(name, GUAC_SSH_ARGV_COLOR_SCHEME) == 0) guac_terminal_apply_color_scheme(terminal, value); /* Update font name */ else if (strcmp(name, GUAC_SSH_ARGV_FONT_NAME) == 0) guac_terminal_apply_font(terminal, value, -1, 0); /* Update only if font size is sane */ else if (strcmp(name, GUAC_SSH_ARGV_FONT_SIZE) == 0) { int size = atoi(value); if (size > 0) guac_terminal_apply_font(terminal, NULL, size, ssh_client->settings->resolution); } /* Update SSH pty size if connected */ if (ssh_client->term_channel != NULL) { pthread_mutex_lock(&(ssh_client->term_channel_lock)); libssh2_channel_request_pty_size(ssh_client->term_channel, terminal->term_width, terminal->term_height); pthread_mutex_unlock(&(ssh_client->term_channel_lock)); } return 0; } void* guac_ssh_send_current_argv(guac_user* user, void* data) { guac_ssh_client* ssh_client = (guac_ssh_client*) data; guac_terminal* terminal = ssh_client->term; /* Send current color scheme */ guac_user_stream_argv(user, user->socket, "text/plain", GUAC_SSH_ARGV_COLOR_SCHEME, terminal->color_scheme); /* Send current font name */ guac_user_stream_argv(user, user->socket, "text/plain", GUAC_SSH_ARGV_FONT_NAME, terminal->font_name); /* Send current font size */ char font_size[64]; sprintf(font_size, "%i", terminal->font_size); guac_user_stream_argv(user, user->socket, "text/plain", GUAC_SSH_ARGV_FONT_SIZE, font_size); return NULL; } guacamole-server-1.3.0/src/protocols/ssh/input.h0000644000175100001440000000231313613156714016620 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_SSH_INPUT_H #define GUAC_SSH_INPUT_H #include "config.h" #include /** * Handler for Guacamole user mouse events. */ guac_user_mouse_handler guac_ssh_user_mouse_handler; /** * Handler for Guacamole user key events. */ guac_user_key_handler guac_ssh_user_key_handler; /** * Handler for Guacamole user size events. */ guac_user_size_handler guac_ssh_user_size_handler; #endif guacamole-server-1.3.0/src/protocols/ssh/pipe.c0000644000175100001440000000316613702142276016415 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "pipe.h" #include "ssh.h" #include "terminal/terminal.h" #include #include #include #include int guac_ssh_pipe_handler(guac_user* user, guac_stream* stream, char* mimetype, char* name) { guac_client* client = user->client; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; /* Redirect STDIN if pipe has required name */ if (strcmp(name, GUAC_SSH_STDIN_PIPE_NAME) == 0) { guac_terminal_send_stream(ssh_client->term, user, stream); return 0; } /* No other inbound pipe streams are supported */ guac_protocol_send_ack(user->socket, stream, "No such input stream.", GUAC_PROTOCOL_STATUS_RESOURCE_NOT_FOUND); guac_socket_flush(user->socket); return 0; } guacamole-server-1.3.0/src/protocols/ssh/user.h0000644000175100001440000000211213613156714016434 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_SSH_USER_H #define GUAC_SSH_USER_H #include "config.h" #include /** * Handler for joining users. */ guac_user_join_handler guac_ssh_user_join_handler; /** * Handler for leaving users. */ guac_user_leave_handler guac_ssh_user_leave_handler; #endif guacamole-server-1.3.0/src/protocols/ssh/ssh_agent.h0000644000175100001440000000560013613156714017436 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_SSH_AGENT_H #define _GUAC_SSH_AGENT_H #include "config.h" #include "ssh_key.h" /** * Packet type of an agent identity request. */ #define SSH2_AGENT_REQUEST_IDENTITIES 0x0B /** * Packet type of an agent identity response. */ #define SSH2_AGENT_IDENTITIES_ANSWER 0x0C /** * Packet type of an agent sign request. */ #define SSH2_AGENT_SIGN_REQUEST 0x0D /** * Packet type of an agent sign response. */ #define SSH2_AGENT_SIGN_RESPONSE 0x0E /** * The comment to associate with public keys when listed. */ #define SSH_AGENT_COMMENT "Guacamole SSH Agent" /** * The packet sent by the SSH agent when an operation is not supported. */ #define UNSUPPORTED "\x00\x00\x00\x0C\x05Unsupported" /** * Data representing an SSH auth agent. */ typedef struct ssh_auth_agent { /** * The SSH channel being used for SSH agent protocol. */ LIBSSH2_CHANNEL* channel; /** * The single private key to use for authentication. */ ssh_key* identity; /** * Data read from the agent channel. */ char buffer[4096]; /** * The number of bytes of data currently stored in the buffer. */ int buffer_length; } ssh_auth_agent; /** * Handler for an agent sign request. */ void ssh_auth_agent_sign(ssh_auth_agent* auth_agent, char* data, int data_length); /** * Handler for an agent identity request. */ void ssh_auth_agent_list_identities(ssh_auth_agent* auth_agent); /** * Generic handler for all packets received over the auth agent channel. */ void ssh_auth_agent_handle_packet(ssh_auth_agent* auth_agent, uint8_t type, char* data, int data_length); /** * Reads and handles a single packet from the SSH agent channel associated * with the given ssh_auth_agent, returning the size of that packet, the size * of the partial packet read, or a negative value if an error occurs. */ int ssh_auth_agent_read(ssh_auth_agent* auth_agent); /** * Libssh2 callback, invoked when the auth agent channel is opened. */ void ssh_auth_agent_callback(LIBSSH2_SESSION *session, LIBSSH2_CHANNEL *channel, void **abstract); #endif guacamole-server-1.3.0/src/protocols/ssh/sftp.h0000644000175100001440000000446113613156714016443 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _SSH_GUAC_SFTP_H #define _SSH_GUAC_SFTP_H #include "config.h" #include #include #include /** * Handles an incoming stream from a Guacamole "file" instruction, saving the * contents of that stream to the file having the given name within the * upload directory set by guac_sftp_set_upload_path(). */ guac_user_file_handler guac_sftp_file_handler; /** * Initiates an SFTP file download to the user via the Guacamole "file" * instruction. The download will be automatically monitored and continued * after this function terminates in response to "ack" instructions received by * the client. * * @param client * The client associated with the terminal emulator receiving the file. * * @param filename * The filename of the file to download, relative to the given filesystem. * * @return * The file stream created for the file download, already configured to * properly handle "ack" responses, etc. from the client. */ guac_stream* guac_sftp_download_file(guac_client* client, char* filename); /** * Sets the destination directory for future uploads submitted via Guacamole * "file" instruction. This function has no bearing on the destination * directories of files uploaded with "put" instructions. * * @param client * The client setting the upload path. * * @param path * The path to use for future uploads submitted via "file" instruction. */ void guac_sftp_set_upload_path(guac_client* client, char* path); #endif guacamole-server-1.3.0/src/protocols/ssh/argv.h0000644000175100001440000000441713770536337016436 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_SSH_ARGV_H #define GUAC_SSH_ARGV_H #include "config.h" #include #include /** * The name of the parameter that specifies/updates the color scheme used by * the terminal emulator. */ #define GUAC_SSH_ARGV_COLOR_SCHEME "color-scheme" /** * The name of the parameter that specifies/updates the name of the font used * by the terminal emulator. */ #define GUAC_SSH_ARGV_FONT_NAME "font-name" /** * The name of the parameter that specifies/updates the font size used by the * terminal emulator. */ #define GUAC_SSH_ARGV_FONT_SIZE "font-size" /** * Handles a received argument value from a Guacamole "argv" instruction, * updating the given connection parameter. */ guac_argv_callback guac_ssh_argv_callback; /** * Sends the current values of all non-sensitive parameters which may be set * while the connection is running to the given user. Note that the user * receiving these values will not necessarily be able to set new values * themselves if their connection is read-only. This function can be used as * the callback for guac_client_foreach_user() and guac_client_for_owner() * * @param user * The user that should receive the values of all non-sensitive parameters * which may be set while the connection is running. * * @param data * The guac_ssh_client instance associated with the current connection. * * @return * Always NULL. */ void* guac_ssh_send_current_argv(guac_user* user, void* data); #endif guacamole-server-1.3.0/src/protocols/ssh/user.c0000644000175100001440000000737413770536337016455 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "clipboard.h" #include "common/display.h" #include "input.h" #include "user.h" #include "pipe.h" #include "sftp.h" #include "ssh.h" #include "settings.h" #include #include #include #include #include #include int guac_ssh_user_join_handler(guac_user* user, int argc, char** argv) { guac_client* client = user->client; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; /* Parse provided arguments */ guac_ssh_settings* settings = guac_ssh_parse_args(user, argc, (const char**) argv); /* Fail if settings cannot be parsed */ if (settings == NULL) { guac_user_log(user, GUAC_LOG_INFO, "Badly formatted client arguments."); return 1; } /* Store settings at user level */ user->data = settings; /* Connect via SSH if owner */ if (user->owner) { /* Store owner's settings at client level */ ssh_client->settings = settings; /* Start client thread */ if (pthread_create(&(ssh_client->client_thread), NULL, ssh_client_thread, (void*) client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start SSH client thread"); return 1; } } /* If not owner, synchronize with current display */ else { guac_terminal_dup(ssh_client->term, user, user->socket); guac_ssh_send_current_argv(user, ssh_client); guac_socket_flush(user->socket); } /* Only handle events if not read-only */ if (!settings->read_only) { /* General mouse/keyboard events */ user->key_handler = guac_ssh_user_key_handler; user->mouse_handler = guac_ssh_user_mouse_handler; /* Inbound (client to server) clipboard transfer */ if (!settings->disable_paste) user->clipboard_handler = guac_ssh_clipboard_handler; /* STDIN redirection */ user->pipe_handler = guac_ssh_pipe_handler; /* Updates to connection parameters */ user->argv_handler = guac_argv_handler; /* Display size change events */ user->size_handler = guac_ssh_user_size_handler; /* Set generic (non-filesystem) file upload handler */ if (settings->enable_sftp && !settings->sftp_disable_upload) user->file_handler = guac_sftp_file_handler; } return 0; } int guac_ssh_user_leave_handler(guac_user* user) { guac_ssh_client* ssh_client = (guac_ssh_client*) user->client->data; /* Update shared cursor state */ guac_common_cursor_remove_user(ssh_client->term->cursor, user); /* Free settings if not owner (owner settings will be freed with client) */ if (!user->owner) { guac_ssh_settings* settings = (guac_ssh_settings*) user->data; guac_ssh_settings_free(settings); } return 0; } guacamole-server-1.3.0/src/protocols/ssh/input.c0000644000175100001440000000567313702142276016624 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/cursor.h" #include "common/display.h" #include "common/recording.h" #include "ssh.h" #include "terminal/terminal.h" #include #include #include #include int guac_ssh_user_mouse_handler(guac_user* user, int x, int y, int mask) { guac_client* client = user->client; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; guac_terminal* term = ssh_client->term; /* Skip if terminal not yet ready */ if (term == NULL) return 0; /* Report mouse position within recording */ if (ssh_client->recording != NULL) guac_common_recording_report_mouse(ssh_client->recording, x, y, mask); /* Send mouse event */ guac_terminal_send_mouse(term, user, x, y, mask); return 0; } int guac_ssh_user_key_handler(guac_user* user, int keysym, int pressed) { guac_client* client = user->client; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; guac_terminal* term = ssh_client->term; /* Report key state within recording */ if (ssh_client->recording != NULL) guac_common_recording_report_key(ssh_client->recording, keysym, pressed); /* Skip if terminal not yet ready */ if (term == NULL) return 0; /* Send key */ guac_terminal_send_key(term, keysym, pressed); return 0; } int guac_ssh_user_size_handler(guac_user* user, int width, int height) { /* Get terminal */ guac_client* client = user->client; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; guac_terminal* terminal = ssh_client->term; /* Skip if terminal not yet ready */ if (terminal == NULL) return 0; /* Resize terminal */ guac_terminal_resize(terminal, width, height); /* Update SSH pty size if connected */ if (ssh_client->term_channel != NULL) { pthread_mutex_lock(&(ssh_client->term_channel_lock)); libssh2_channel_request_pty_size(ssh_client->term_channel, terminal->term_width, terminal->term_height); pthread_mutex_unlock(&(ssh_client->term_channel_lock)); } return 0; } guacamole-server-1.3.0/src/protocols/ssh/clipboard.h0000644000175100001440000000242413613156714017423 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_SSH_CLIPBOARD_H #define _GUAC_SSH_CLIPBOARD_H #include "config.h" #include #include /** * Handler for inbound clipboard streams. */ guac_user_clipboard_handler guac_ssh_clipboard_handler; /** * Handler for data received along clipboard streams. */ guac_user_blob_handler guac_ssh_clipboard_blob_handler; /** * Handler for end-of-stream related to clipboard. */ guac_user_end_handler guac_ssh_clipboard_end_handler; #endif guacamole-server-1.3.0/src/protocols/ssh/Makefile.in0000644000175100001440000011643113772471102017361 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ # Add agent sources if enabled @ENABLE_SSH_AGENT_TRUE@am__append_1 = ssh_agent.c @ENABLE_SSH_AGENT_TRUE@am__append_2 = ssh_agent.h subdir = src/protocols/ssh ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__noinst_HEADERS_DIST) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) libguac_client_ssh_la_DEPENDENCIES = am__libguac_client_ssh_la_SOURCES_DIST = argv.c client.c clipboard.c \ input.c pipe.c settings.c sftp.c ssh.c ttymode.c user.c \ ssh_agent.c @ENABLE_SSH_AGENT_TRUE@am__objects_1 = \ @ENABLE_SSH_AGENT_TRUE@ libguac_client_ssh_la-ssh_agent.lo am_libguac_client_ssh_la_OBJECTS = libguac_client_ssh_la-argv.lo \ libguac_client_ssh_la-client.lo \ libguac_client_ssh_la-clipboard.lo \ libguac_client_ssh_la-input.lo libguac_client_ssh_la-pipe.lo \ libguac_client_ssh_la-settings.lo \ libguac_client_ssh_la-sftp.lo libguac_client_ssh_la-ssh.lo \ libguac_client_ssh_la-ttymode.lo libguac_client_ssh_la-user.lo \ $(am__objects_1) libguac_client_ssh_la_OBJECTS = $(am_libguac_client_ssh_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libguac_client_ssh_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) \ $(libguac_client_ssh_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libguac_client_ssh_la-argv.Plo \ ./$(DEPDIR)/libguac_client_ssh_la-client.Plo \ ./$(DEPDIR)/libguac_client_ssh_la-clipboard.Plo \ ./$(DEPDIR)/libguac_client_ssh_la-input.Plo \ ./$(DEPDIR)/libguac_client_ssh_la-pipe.Plo \ ./$(DEPDIR)/libguac_client_ssh_la-settings.Plo \ ./$(DEPDIR)/libguac_client_ssh_la-sftp.Plo \ ./$(DEPDIR)/libguac_client_ssh_la-ssh.Plo \ ./$(DEPDIR)/libguac_client_ssh_la-ssh_agent.Plo \ ./$(DEPDIR)/libguac_client_ssh_la-ttymode.Plo \ ./$(DEPDIR)/libguac_client_ssh_la-user.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libguac_client_ssh_la_SOURCES) DIST_SOURCES = $(am__libguac_client_ssh_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__noinst_HEADERS_DIST = argv.h client.h clipboard.h input.h pipe.h \ settings.h sftp.h ssh.h ttymode.h user.h ssh_agent.h HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac-client-ssh.la libguac_client_ssh_la_SOURCES = argv.c client.c clipboard.c input.c \ pipe.c settings.c sftp.c ssh.c ttymode.c user.c \ $(am__append_1) noinst_HEADERS = argv.h client.h clipboard.h input.h pipe.h settings.h \ sftp.h ssh.h ttymode.h user.h $(am__append_2) libguac_client_ssh_la_CFLAGS = \ -Werror -Wall -Iinclude \ @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ \ @TERMINAL_INCLUDE@ libguac_client_ssh_la_LIBADD = \ @COMMON_LTLIB@ \ @COMMON_SSH_LTLIB@ \ @LIBGUAC_LTLIB@ \ @TERMINAL_LTLIB@ libguac_client_ssh_la_LDFLAGS = \ -version-info 0:0:0 \ @PTHREAD_LIBS@ \ @SSH_LIBS@ \ @SSL_LIBS@ all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/protocols/ssh/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/protocols/ssh/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libguac-client-ssh.la: $(libguac_client_ssh_la_OBJECTS) $(libguac_client_ssh_la_DEPENDENCIES) $(EXTRA_libguac_client_ssh_la_DEPENDENCIES) $(AM_V_CCLD)$(libguac_client_ssh_la_LINK) -rpath $(libdir) $(libguac_client_ssh_la_OBJECTS) $(libguac_client_ssh_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_ssh_la-argv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_ssh_la-client.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_ssh_la-clipboard.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_ssh_la-input.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_ssh_la-pipe.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_ssh_la-settings.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_ssh_la-sftp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_ssh_la-ssh.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_ssh_la-ssh_agent.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_ssh_la-ttymode.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_ssh_la-user.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libguac_client_ssh_la-argv.lo: argv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_client_ssh_la-argv.lo -MD -MP -MF $(DEPDIR)/libguac_client_ssh_la-argv.Tpo -c -o libguac_client_ssh_la-argv.lo `test -f 'argv.c' || echo '$(srcdir)/'`argv.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_ssh_la-argv.Tpo $(DEPDIR)/libguac_client_ssh_la-argv.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='argv.c' object='libguac_client_ssh_la-argv.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_client_ssh_la-argv.lo `test -f 'argv.c' || echo '$(srcdir)/'`argv.c libguac_client_ssh_la-client.lo: client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_client_ssh_la-client.lo -MD -MP -MF $(DEPDIR)/libguac_client_ssh_la-client.Tpo -c -o libguac_client_ssh_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_ssh_la-client.Tpo $(DEPDIR)/libguac_client_ssh_la-client.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client.c' object='libguac_client_ssh_la-client.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_client_ssh_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c libguac_client_ssh_la-clipboard.lo: clipboard.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_client_ssh_la-clipboard.lo -MD -MP -MF $(DEPDIR)/libguac_client_ssh_la-clipboard.Tpo -c -o libguac_client_ssh_la-clipboard.lo `test -f 'clipboard.c' || echo '$(srcdir)/'`clipboard.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_ssh_la-clipboard.Tpo $(DEPDIR)/libguac_client_ssh_la-clipboard.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='clipboard.c' object='libguac_client_ssh_la-clipboard.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_client_ssh_la-clipboard.lo `test -f 'clipboard.c' || echo '$(srcdir)/'`clipboard.c libguac_client_ssh_la-input.lo: input.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_client_ssh_la-input.lo -MD -MP -MF $(DEPDIR)/libguac_client_ssh_la-input.Tpo -c -o libguac_client_ssh_la-input.lo `test -f 'input.c' || echo '$(srcdir)/'`input.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_ssh_la-input.Tpo $(DEPDIR)/libguac_client_ssh_la-input.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='input.c' object='libguac_client_ssh_la-input.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_client_ssh_la-input.lo `test -f 'input.c' || echo '$(srcdir)/'`input.c libguac_client_ssh_la-pipe.lo: pipe.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_client_ssh_la-pipe.lo -MD -MP -MF $(DEPDIR)/libguac_client_ssh_la-pipe.Tpo -c -o libguac_client_ssh_la-pipe.lo `test -f 'pipe.c' || echo '$(srcdir)/'`pipe.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_ssh_la-pipe.Tpo $(DEPDIR)/libguac_client_ssh_la-pipe.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pipe.c' object='libguac_client_ssh_la-pipe.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_client_ssh_la-pipe.lo `test -f 'pipe.c' || echo '$(srcdir)/'`pipe.c libguac_client_ssh_la-settings.lo: settings.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_client_ssh_la-settings.lo -MD -MP -MF $(DEPDIR)/libguac_client_ssh_la-settings.Tpo -c -o libguac_client_ssh_la-settings.lo `test -f 'settings.c' || echo '$(srcdir)/'`settings.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_ssh_la-settings.Tpo $(DEPDIR)/libguac_client_ssh_la-settings.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings.c' object='libguac_client_ssh_la-settings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_client_ssh_la-settings.lo `test -f 'settings.c' || echo '$(srcdir)/'`settings.c libguac_client_ssh_la-sftp.lo: sftp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_client_ssh_la-sftp.lo -MD -MP -MF $(DEPDIR)/libguac_client_ssh_la-sftp.Tpo -c -o libguac_client_ssh_la-sftp.lo `test -f 'sftp.c' || echo '$(srcdir)/'`sftp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_ssh_la-sftp.Tpo $(DEPDIR)/libguac_client_ssh_la-sftp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sftp.c' object='libguac_client_ssh_la-sftp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_client_ssh_la-sftp.lo `test -f 'sftp.c' || echo '$(srcdir)/'`sftp.c libguac_client_ssh_la-ssh.lo: ssh.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_client_ssh_la-ssh.lo -MD -MP -MF $(DEPDIR)/libguac_client_ssh_la-ssh.Tpo -c -o libguac_client_ssh_la-ssh.lo `test -f 'ssh.c' || echo '$(srcdir)/'`ssh.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_ssh_la-ssh.Tpo $(DEPDIR)/libguac_client_ssh_la-ssh.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ssh.c' object='libguac_client_ssh_la-ssh.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_client_ssh_la-ssh.lo `test -f 'ssh.c' || echo '$(srcdir)/'`ssh.c libguac_client_ssh_la-ttymode.lo: ttymode.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_client_ssh_la-ttymode.lo -MD -MP -MF $(DEPDIR)/libguac_client_ssh_la-ttymode.Tpo -c -o libguac_client_ssh_la-ttymode.lo `test -f 'ttymode.c' || echo '$(srcdir)/'`ttymode.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_ssh_la-ttymode.Tpo $(DEPDIR)/libguac_client_ssh_la-ttymode.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ttymode.c' object='libguac_client_ssh_la-ttymode.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_client_ssh_la-ttymode.lo `test -f 'ttymode.c' || echo '$(srcdir)/'`ttymode.c libguac_client_ssh_la-user.lo: user.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_client_ssh_la-user.lo -MD -MP -MF $(DEPDIR)/libguac_client_ssh_la-user.Tpo -c -o libguac_client_ssh_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_ssh_la-user.Tpo $(DEPDIR)/libguac_client_ssh_la-user.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user.c' object='libguac_client_ssh_la-user.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_client_ssh_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c libguac_client_ssh_la-ssh_agent.lo: ssh_agent.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -MT libguac_client_ssh_la-ssh_agent.lo -MD -MP -MF $(DEPDIR)/libguac_client_ssh_la-ssh_agent.Tpo -c -o libguac_client_ssh_la-ssh_agent.lo `test -f 'ssh_agent.c' || echo '$(srcdir)/'`ssh_agent.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_ssh_la-ssh_agent.Tpo $(DEPDIR)/libguac_client_ssh_la-ssh_agent.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ssh_agent.c' object='libguac_client_ssh_la-ssh_agent.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_ssh_la_CFLAGS) $(CFLAGS) -c -o libguac_client_ssh_la-ssh_agent.lo `test -f 'ssh_agent.c' || echo '$(srcdir)/'`ssh_agent.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libguac_client_ssh_la-argv.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-client.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-clipboard.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-input.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-pipe.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-settings.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-sftp.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-ssh.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-ssh_agent.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-ttymode.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-user.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libguac_client_ssh_la-argv.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-client.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-clipboard.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-input.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-pipe.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-settings.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-sftp.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-ssh.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-ssh_agent.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-ttymode.Plo -rm -f ./$(DEPDIR)/libguac_client_ssh_la-user.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/protocols/ssh/settings.h0000644000175100001440000002170313764613616017333 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_SSH_SETTINGS_H #define GUAC_SSH_SETTINGS_H #include "config.h" #include #include /** * The name of the font to use for the terminal if no name is specified. */ #define GUAC_SSH_DEFAULT_FONT_NAME "monospace" /** * The size of the font to use for the terminal if no font size is specified, * in points. */ #define GUAC_SSH_DEFAULT_FONT_SIZE 12 /** * The port to connect to when initiating any SSH connection, if no other port * is specified. */ #define GUAC_SSH_DEFAULT_PORT "22" /** * The filename to use for the typescript, if not specified. */ #define GUAC_SSH_DEFAULT_TYPESCRIPT_NAME "typescript" /** * The filename to use for the screen recording, if not specified. */ #define GUAC_SSH_DEFAULT_RECORDING_NAME "recording" /** * The default polling timeout for SSH activity in milliseconds. */ #define GUAC_SSH_DEFAULT_POLL_TIMEOUT 1000 /** * The default maximum scrollback size in rows. */ #define GUAC_SSH_DEFAULT_MAX_SCROLLBACK 1000 /** * Settings for the SSH connection. The values for this structure are parsed * from the arguments given during the Guacamole protocol handshake using the * guac_ssh_parse_args() function. */ typedef struct guac_ssh_settings { /** * The hostname of the SSH server to connect to. */ char* hostname; /** * The public SSH host key. */ char* host_key; /** * The port of the SSH server to connect to. */ char* port; /** * The name of the user to login as, if any. If no username is specified, * this will be NULL. */ char* username; /** * The password to give when authenticating, if any. If no password is * specified, this will be NULL. */ char* password; /** * The private key, encoded as base64, if any. If no private key is * specified, this will be NULL. */ char* key_base64; /** * The passphrase to use to decrypt the given private key, if any. If no * passphrase is specified, this will be NULL. */ char* key_passphrase; /** * Whether this connection is read-only, and user input should be dropped. */ bool read_only; /** * The command to run instead of the default shell. If a normal shell * session is desired, this will be NULL. */ char* command; /** * The maximum size of the scrollback buffer in rows. */ int max_scrollback; /** * The name of the font to use for display rendering. */ char* font_name; /** * The size of the font to use, in points. */ int font_size; /** * The name of the color scheme to use. */ char* color_scheme; /** * The desired width of the terminal display, in pixels. */ int width; /** * The desired height of the terminal display, in pixels. */ int height; /** * The desired screen resolution, in DPI. */ int resolution; /** * Whether outbound clipboard access should be blocked. If set, it will not * be possible to copy data from the terminal to the client using the * clipboard. */ bool disable_copy; /** * Whether inbound clipboard access should be blocked. If set, it will not * be possible to paste data from the client to the terminal using the * clipboard. */ bool disable_paste; /** * Whether SFTP is enabled. */ bool enable_sftp; /** * The path of the directory within the SSH server to expose as a * filesystem guac_object. */ char* sftp_root_directory; /** * Whether file download over SFTP should be disabled. If set to true, file * downloads will not be allowed over SFTP. If not set or set to false, file * downloads will be allowed. */ bool sftp_disable_download; /** * Whether file uploads over SFTP should be disabled. If set to true, file * uploads will not be allowed over SFTP. If not set or set to false, file * uploads will be allowed. */ bool sftp_disable_upload; #ifdef ENABLE_SSH_AGENT /** * Whether the SSH agent is enabled. */ bool enable_agent; #endif /** * The path in which the typescript should be saved, if enabled. If no * typescript should be saved, this will be NULL. */ char* typescript_path; /** * The filename to use for the typescript, if enabled. */ char* typescript_name; /** * Whether the typescript path should be automatically created if it does * not already exist. */ bool create_typescript_path; /** * The path in which the screen recording should be saved, if enabled. If * no screen recording should be saved, this will be NULL. */ char* recording_path; /** * The filename to use for the screen recording, if enabled. */ char* recording_name; /** * Whether the screen recording path should be automatically created if it * does not already exist. */ bool create_recording_path; /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output * is included by default, as it is necessary for any recording which must * later be viewable as video. */ bool recording_exclude_output; /** * Whether changes to mouse state, such as position and buttons pressed or * released, should NOT be included in the session recording. Mouse state * is included by default, as it is necessary for the mouse cursor to be * rendered in any resulting video. */ bool recording_exclude_mouse; /** * Whether keys pressed and released should be included in the session * recording. Key events are NOT included by default within the recording, * as doing so has privacy and security implications. Including key events * may be necessary in certain auditing contexts, but should only be done * with caution. Key events can easily contain sensitive information, such * as passwords, credit card numbers, etc. */ bool recording_include_keys; /** * The number of seconds between sending server alive messages. */ int server_alive_interval; /** * The integer ASCII code of the command to send for backspace. */ int backspace; /** * The terminal emulator type that is passed to the remote system. */ char* terminal_type; /** * The locale that should be forwarded to the remote system via the LANG * environment variable. */ char* locale; /** * The client timezone to pass to the remote system. */ char* timezone; /** * Whether or not to send the Wake-on-LAN magic packet. */ bool wol_send_packet; /** * The MAC address to put in the magic WoL packet for the host to wake. */ char* wol_mac_addr; /** * The broadcast address to which to send the magic WoL packet. */ char* wol_broadcast_addr; /** * The amount of time to wait for the system to wake after sending the packet. */ int wol_wait_time; } guac_ssh_settings; /** * Parses all given args, storing them in a newly-allocated settings object. If * the args fail to parse, NULL is returned. * * @param user * The user who submitted the given arguments while joining the * connection. * * @param argc * The number of arguments within the argv array. * * @param argv * The values of all arguments provided by the user. * * @return * A newly-allocated settings object which must be freed with * guac_ssh_settings_free() when no longer needed. If the arguments fail * to parse, NULL is returned. */ guac_ssh_settings* guac_ssh_parse_args(guac_user* user, int argc, const char** argv); /** * Frees the given guac_ssh_settings object, having been previously allocated * via guac_ssh_parse_args(). * * @param settings * The settings object to free. */ void guac_ssh_settings_free(guac_ssh_settings* settings); /** * NULL-terminated array of accepted client args. */ extern const char* GUAC_SSH_CLIENT_ARGS[]; #endif guacamole-server-1.3.0/src/protocols/ssh/settings.c0000644000175100001440000004407413770536337017335 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "client.h" #include "common/defaults.h" #include "settings.h" #include #include #include #include #include /* Client plugin arguments */ const char* GUAC_SSH_CLIENT_ARGS[] = { "hostname", "host-key", "port", "username", "password", GUAC_SSH_ARGV_FONT_NAME, GUAC_SSH_ARGV_FONT_SIZE, "enable-sftp", "sftp-root-directory", "sftp-disable-download", "sftp-disable-upload", "private-key", "passphrase", #ifdef ENABLE_SSH_AGENT "enable-agent", #endif GUAC_SSH_ARGV_COLOR_SCHEME, "command", "typescript-path", "typescript-name", "create-typescript-path", "recording-path", "recording-name", "recording-exclude-output", "recording-exclude-mouse", "recording-include-keys", "create-recording-path", "read-only", "server-alive-interval", "backspace", "terminal-type", "scrollback", "locale", "timezone", "disable-copy", "disable-paste", "wol-send-packet", "wol-mac-addr", "wol-broadcast-addr", "wol-wait-time", NULL }; enum SSH_ARGS_IDX { /** * The hostname to connect to. Required. */ IDX_HOSTNAME, /** * The Base64-encoded public SSH host key. Optional. */ IDX_HOST_KEY, /** * The port to connect to. Optional. */ IDX_PORT, /** * The name of the user to login as. Optional. */ IDX_USERNAME, /** * The password to use when logging in. Optional. */ IDX_PASSWORD, /** * The name of the font to use within the terminal. */ IDX_FONT_NAME, /** * The size of the font to use within the terminal, in points. */ IDX_FONT_SIZE, /** * Whether SFTP should be enabled. */ IDX_ENABLE_SFTP, /** * The path of the directory within the SSH server to expose as a * filesystem guac_object. If omitted, "/" will be used by default. */ IDX_SFTP_ROOT_DIRECTORY, /** * "true" if file downloads over SFTP should be blocked. "false" or blank * if file downloads should be allowed. */ IDX_SFTP_DISABLE_DOWNLOAD, /** * "true" if file uploads over SFTP should be blocked. "false" or blank if * file uploads should be allowed. */ IDX_SFTP_DISABLE_UPLOAD, /** * The private key to use for authentication, if any. */ IDX_PRIVATE_KEY, /** * The passphrase required to decrypt the private key, if any. */ IDX_PASSPHRASE, #ifdef ENABLE_SSH_AGENT /** * Whether SSH agent forwarding support should be enabled. */ IDX_ENABLE_AGENT, #endif /** * The color scheme to use, as a series of semicolon-separated color-value * pairs: "background: ", "foreground: ", or * "color: ", where is a number from 0 to 255, and is * "color" or an X11 color code (e.g. "aqua" or "rgb:12/34/56"). * The color scheme can also be one of the special values: "black-white", * "white-black", "gray-black", or "green-black". */ IDX_COLOR_SCHEME, /** * The command to run instead if the default shell. If omitted, a normal * shell session will be created. */ IDX_COMMAND, /** * The full absolute path to the directory in which typescripts should be * written. */ IDX_TYPESCRIPT_PATH, /** * The name that should be given to typescripts which are written in the * given path. Each typescript will consist of two files: "NAME" and * "NAME.timing". */ IDX_TYPESCRIPT_NAME, /** * Whether the specified typescript path should automatically be created * if it does not yet exist. */ IDX_CREATE_TYPESCRIPT_PATH, /** * The full absolute path to the directory in which screen recordings * should be written. */ IDX_RECORDING_PATH, /** * The name that should be given to screen recordings which are written in * the given path. */ IDX_RECORDING_NAME, /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output * is included by default, as it is necessary for any recording which must * later be viewable as video. */ IDX_RECORDING_EXCLUDE_OUTPUT, /** * Whether changes to mouse state, such as position and buttons pressed or * released, should NOT be included in the session recording. Mouse state * is included by default, as it is necessary for the mouse cursor to be * rendered in any resulting video. */ IDX_RECORDING_EXCLUDE_MOUSE, /** * Whether keys pressed and released should be included in the session * recording. Key events are NOT included by default within the recording, * as doing so has privacy and security implications. Including key events * may be necessary in certain auditing contexts, but should only be done * with caution. Key events can easily contain sensitive information, such * as passwords, credit card numbers, etc. */ IDX_RECORDING_INCLUDE_KEYS, /** * Whether the specified screen recording path should automatically be * created if it does not yet exist. */ IDX_CREATE_RECORDING_PATH, /** * "true" if this connection should be read-only (user input should be * dropped), "false" or blank otherwise. */ IDX_READ_ONLY, /** * Number of seconds between sending alive packets. A default of 0 * tells SSH not to send these packets. A value of 1 is automatically * changed by libssh2 to 2 to avoid busy-loop corner cases. */ IDX_SERVER_ALIVE_INTERVAL, /** * The ASCII code, as an integer, to send for the backspace key, as configured * by the SSH connection from the client. By default this will be 127, * the ASCII DELETE code. */ IDX_BACKSPACE, /** * The terminal emulator type that is passed to the remote system (e.g. * "xterm" or "xterm-256color"). "linux" is used if unspecified. */ IDX_TERMINAL_TYPE, /** * The maximum size of the scrollback buffer in rows. */ IDX_SCROLLBACK, /** * The locale that should be forwarded to the remote system via the LANG * environment variable. By default, no locale is forwarded. This setting * will only have an effect if the SSH server allows the LANG environment * variable to be set. */ IDX_LOCALE, /** * The timezone that is to be passed to the remote system, via the * TZ environment variable. By default, no timezone is forwarded * and the timezone of the remote system will be used. This * setting will only work if the SSH server allows the TZ variable * to be set. Timezones should be in standard IANA format, see: * https://en.wikipedia.org/wiki/List_of_tz_database_time_zones */ IDX_TIMEZONE, /** * Whether outbound clipboard access should be blocked. If set to "true", * it will not be possible to copy data from the terminal to the client * using the clipboard. By default, clipboard access is not blocked. */ IDX_DISABLE_COPY, /** * Whether inbound clipboard access should be blocked. If set to "true", it * will not be possible to paste data from the client to the terminal using * the clipboard. By default, clipboard access is not blocked. */ IDX_DISABLE_PASTE, /** * Whether the magic WoL packet should be sent prior to starting the * connection. If set to "true", the system will attempt to send the WoL * packet and wait for the host to wake up. By default the WoL packet * is not sent. */ IDX_WOL_SEND_PACKET, /** * The MAC address to put in the magic WoL packet to wake the remote system. * By default no MAC address is specified. If WoL is enabled by a MAC * address is not provided a warning will be logged and the WoL packet will * not be sent. */ IDX_WOL_MAC_ADDR, /** * The broadcast address to which to send the magic WoL packet to wake the * remote system. */ IDX_WOL_BROADCAST_ADDR, /** * The amount of time to wait after sending the magic WoL packet prior to * continuing the connection attempt. The default is no wait time * (0 seconds). */ IDX_WOL_WAIT_TIME, SSH_ARGS_COUNT }; guac_ssh_settings* guac_ssh_parse_args(guac_user* user, int argc, const char** argv) { /* Validate arg count */ if (argc != SSH_ARGS_COUNT) { guac_user_log(user, GUAC_LOG_WARNING, "Incorrect number of connection " "parameters provided: expected %i, got %i.", SSH_ARGS_COUNT, argc); return NULL; } guac_ssh_settings* settings = calloc(1, sizeof(guac_ssh_settings)); /* Read parameters */ settings->hostname = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_HOSTNAME, ""); settings->host_key = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_HOST_KEY, NULL); settings->username = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_USERNAME, NULL); settings->password = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_PASSWORD, NULL); /* Init public key auth information */ settings->key_base64 = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_PRIVATE_KEY, NULL); settings->key_passphrase = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_PASSPHRASE, NULL); /* Read maximum scrollback size */ settings->max_scrollback = guac_user_parse_args_int(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_SCROLLBACK, GUAC_SSH_DEFAULT_MAX_SCROLLBACK); /* Read font name */ settings->font_name = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_FONT_NAME, GUAC_SSH_DEFAULT_FONT_NAME); /* Read font size */ settings->font_size = guac_user_parse_args_int(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_FONT_SIZE, GUAC_SSH_DEFAULT_FONT_SIZE); /* Copy requested color scheme */ settings->color_scheme = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_COLOR_SCHEME, ""); /* Pull width/height/resolution directly from user */ settings->width = user->info.optimal_width; settings->height = user->info.optimal_height; settings->resolution = user->info.optimal_resolution; /* Parse SFTP enable */ settings->enable_sftp = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_ENABLE_SFTP, false); /* SFTP root directory */ settings->sftp_root_directory = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_SFTP_ROOT_DIRECTORY, "/"); /* Disable file downloads. */ settings->sftp_disable_download = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_SFTP_DISABLE_DOWNLOAD, false); /* Disable file uploads. */ settings->sftp_disable_upload = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_SFTP_DISABLE_UPLOAD, false); #ifdef ENABLE_SSH_AGENT settings->enable_agent = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_ENABLE_AGENT, false); #endif /* Read port */ settings->port = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_PORT, GUAC_SSH_DEFAULT_PORT); /* Read-only mode */ settings->read_only = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_READ_ONLY, false); /* Read command, if any */ settings->command = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_COMMAND, NULL); /* Read typescript path */ settings->typescript_path = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_TYPESCRIPT_PATH, NULL); /* Read typescript name */ settings->typescript_name = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_TYPESCRIPT_NAME, GUAC_SSH_DEFAULT_TYPESCRIPT_NAME); /* Parse path creation flag */ settings->create_typescript_path = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_CREATE_TYPESCRIPT_PATH, false); /* Read recording path */ settings->recording_path = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_RECORDING_PATH, NULL); /* Read recording name */ settings->recording_name = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_RECORDING_NAME, GUAC_SSH_DEFAULT_RECORDING_NAME); /* Parse output exclusion flag */ settings->recording_exclude_output = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_RECORDING_EXCLUDE_OUTPUT, false); /* Parse mouse exclusion flag */ settings->recording_exclude_mouse = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_RECORDING_EXCLUDE_MOUSE, false); /* Parse key event inclusion flag */ settings->recording_include_keys = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_RECORDING_INCLUDE_KEYS, false); /* Parse path creation flag */ settings->create_recording_path = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_CREATE_RECORDING_PATH, false); /* Parse server alive interval */ settings->server_alive_interval = guac_user_parse_args_int(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_SERVER_ALIVE_INTERVAL, 0); /* Parse backspace key setting */ settings->backspace = guac_user_parse_args_int(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_BACKSPACE, 127); /* Read terminal emulator type. */ settings->terminal_type = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_TERMINAL_TYPE, "linux"); /* Read locale */ settings->locale = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_LOCALE, NULL); /* Read the timezone parameter, or use client handshake. */ settings->timezone = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_TIMEZONE, user->info.timezone); /* Parse clipboard copy disable flag */ settings->disable_copy = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_DISABLE_COPY, false); /* Parse clipboard paste disable flag */ settings->disable_paste = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_DISABLE_PASTE, false); /* Parse Wake-on-LAN (WoL) parameters. */ settings->wol_send_packet = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_WOL_SEND_PACKET, false); if (settings->wol_send_packet) { if (strcmp(argv[IDX_WOL_MAC_ADDR], "") == 0) { guac_user_log(user, GUAC_LOG_WARNING, "WoL was enabled, but no ", "MAC address was provide. WoL will not be sent."); settings->wol_send_packet = false; } settings->wol_mac_addr = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_WOL_MAC_ADDR, NULL); settings->wol_broadcast_addr = guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_WOL_BROADCAST_ADDR, GUAC_WOL_LOCAL_IPV4_BROADCAST); settings->wol_wait_time = guac_user_parse_args_int(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_WOL_WAIT_TIME, GUAC_WOL_DEFAULT_BOOT_WAIT_TIME); } /* Parsing was successful */ return settings; } void guac_ssh_settings_free(guac_ssh_settings* settings) { /* Free network connection information */ free(settings->hostname); free(settings->host_key); free(settings->port); /* Free credentials */ free(settings->username); free(settings->password); free(settings->key_base64); free(settings->key_passphrase); /* Free display preferences */ free(settings->font_name); free(settings->color_scheme); /* Free requested command */ free(settings->command); /* Free SFTP settings */ free(settings->sftp_root_directory); /* Free typescript settings */ free(settings->typescript_name); free(settings->typescript_path); /* Free screen recording settings */ free(settings->recording_name); free(settings->recording_path); /* Free terminal emulator type. */ free(settings->terminal_type); /* Free locale */ free(settings->locale); /* Free the client timezone. */ free(settings->timezone); /* Free Wake-on-LAN settings. */ free(settings->wol_mac_addr); free(settings->wol_broadcast_addr); /* Free overall structure */ free(settings); } guacamole-server-1.3.0/src/protocols/ssh/ttymode.h0000644000175100001440000000535113702142276017150 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_SSH_TTYMODE_H #define GUAC_SSH_TTYMODE_H #include "config.h" #include /** * The size of a TTY mode encoding opcode and * value pair. As defined in the SSH RFC, this * is 5 bytes - a single byte for the opcode, and * 4 bytes for the value. */ #define GUAC_SSH_TTY_OPCODE_SIZE 5 /** * The SSH TTY mode encoding opcode that terminates * the list of TTY modes. */ #define GUAC_SSH_TTY_OP_END 0 /** * The SSH TTY mode encoding opcode that configures * the TTY erase code to configure the server * backspace key. */ #define GUAC_SSH_TTY_OP_VERASE 3 /** * Macro for calculating the number of bytes required * to pass a given number of opcodes, which calculates * the size of the number of opcodes plus the single byte * end opcode. * * @param num_opcodes * The number of opcodes for which a size in bytes * should be calculated. * * @returns * The number of bytes that the given number of * opcodes will require. */ #define GUAC_SSH_TTYMODES_SIZE(num_opcodes) ((GUAC_SSH_TTY_OPCODE_SIZE * num_opcodes) + 1) /** * Opcodes and value pairs are passed to the SSH connection * in a single array, beginning with the opcode and followed * by a four byte value, repeating until the end opcode is * encountered. This function takes the array that will be * sent and a variable number of opcode and value pair * arguments and places the opcode and values in the array * as expected by the SSH connection. * * @param opcode_array * Pointer to the opcode array that will ultimately * be passed to the SSH connection. The array must * be size to handle 5 bytes for each opcode and value * pair, plus one additional byte for the end opcode. * * @params ... * A variable number of opcode and value pairs * to place in the array. * * @return * Number of bytes written to the array, or zero * if a failure occurs. */ int guac_ssh_ttymodes_init(char opcode_array[], ...); #endif guacamole-server-1.3.0/src/protocols/ssh/ttymode.c0000644000175100001440000000352113702142276017140 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "ttymode.h" #include #include #include #include int guac_ssh_ttymodes_init(char opcode_array[], ...) { /* Initialize the variable argument list. */ va_list args; va_start(args, opcode_array); /* Initialize array pointer and byte counter. */ char *current = opcode_array; /* Loop through variable argument list. */ while (true) { /* Next argument should be an opcode. */ char opcode = (char)va_arg(args, int); *(current++) = opcode; /* If it's the end opcode, we're done. */ if (opcode == GUAC_SSH_TTY_OP_END) break; /* Next argument should be 4-byte value. */ uint32_t value = va_arg(args, uint32_t); *(current++) = (value >> 24) & 0xFF; *(current++) = (value >> 16) & 0xFF; *(current++) = (value >> 8) & 0xFF; *(current++) = value & 0xFF; } /* We're done processing arguments. */ va_end(args); return current - opcode_array; } guacamole-server-1.3.0/src/protocols/ssh/client.h0000644000175100001440000000236213702142276016740 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_SSH_CLIENT_H #define GUAC_SSH_CLIENT_H #include /** * The maximum number of bytes to allow within the clipboard. */ #define GUAC_SSH_CLIPBOARD_MAX_LENGTH 262144 /** * Handler which is invoked when the SSH client needs to be disconnected (if * connected) and freed. This can happen if initialization fails, or all users * have left the connection. */ guac_client_free_handler guac_ssh_client_free_handler; #endif guacamole-server-1.3.0/src/protocols/ssh/ssh.h0000644000175100001440000000556413750103434016262 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_SSH_H #define GUAC_SSH_H #include "config.h" #include "common/clipboard.h" #include "common/recording.h" #include "common-ssh/sftp.h" #include "common-ssh/ssh.h" #include "common-ssh/user.h" #include "settings.h" #include "terminal/terminal.h" #ifdef ENABLE_SSH_AGENT #include "ssh_agent.h" #endif #include #include /** * SSH-specific client data. */ typedef struct guac_ssh_client { /** * SSH connection settings. */ guac_ssh_settings* settings; #ifdef ENABLE_SSH_AGENT /** * The current agent, if any. */ ssh_auth_agent* auth_agent; #endif /** * The SSH client thread. */ pthread_t client_thread; /** * The user and credentials to use for all SSH sessions. */ guac_common_ssh_user* user; /** * SSH session, used by the SSH client thread. */ guac_common_ssh_session* session; /** * SFTP session, used by the SFTP client/filesystem. */ guac_common_ssh_session* sftp_session; /** * The filesystem object exposed for the SFTP session. */ guac_common_ssh_sftp_filesystem* sftp_filesystem; /** * SSH terminal channel, used by the SSH client thread. */ LIBSSH2_CHANNEL* term_channel; /** * Lock dictating access to the SSH terminal channel. */ pthread_mutex_t term_channel_lock; /** * The current clipboard contents. */ guac_common_clipboard* clipboard; /** * The terminal which will render all output from the SSH client. */ guac_terminal* term; /** * The in-progress session recording, or NULL if no recording is in * progress. */ guac_common_recording* recording; } guac_ssh_client ; /** * Main SSH client thread, handling transfer of SSH output to STDOUT. * * @param data * The guac_client to associate with a new SSH session, once the SSH * connection succeeds. * * @return * NULL in all cases. The return value of this thread is expected to be * ignored. */ void* ssh_client_thread(void* data); #endif guacamole-server-1.3.0/src/protocols/ssh/sftp.c0000644000175100001440000000601413613156714016432 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common-ssh/sftp.h" #include "sftp.h" #include "ssh.h" #include #include #include int guac_sftp_file_handler(guac_user* user, guac_stream* stream, char* mimetype, char* filename) { guac_client* client = user->client; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; guac_common_ssh_sftp_filesystem* filesystem = ssh_client->sftp_filesystem; /* Handle file upload */ return guac_common_ssh_sftp_handle_file_stream(filesystem, user, stream, mimetype, filename); } /** * Callback invoked on the current connection owner (if any) when a file * download is being initiated through the terminal. * * @param owner * The guac_user that is the owner of the connection, or NULL if the * connection owner has left. * * @param data * The filename of the file that should be downloaded. * * @return * The stream allocated for the file download, or NULL if no stream could * be allocated. */ static void* guac_sftp_download_to_owner(guac_user* owner, void* data) { /* Do not bother attempting the download if the owner has left */ if (owner == NULL) return NULL; guac_client* client = owner->client; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; guac_common_ssh_sftp_filesystem* filesystem = ssh_client->sftp_filesystem; /* Ignore download if filesystem has been unloaded */ if (filesystem == NULL) return NULL; char* filename = (char*) data; /* Initiate download of requested file */ return guac_common_ssh_sftp_download_file(filesystem, owner, filename); } guac_stream* guac_sftp_download_file(guac_client* client, char* filename) { /* Initiate download to the owner of the connection */ return (guac_stream*) guac_client_for_owner(client, guac_sftp_download_to_owner, filename); } void guac_sftp_set_upload_path(guac_client* client, char* path) { guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; guac_common_ssh_sftp_filesystem* filesystem = ssh_client->sftp_filesystem; /* Set upload path as specified */ guac_common_ssh_sftp_set_upload_path(filesystem, path); } guacamole-server-1.3.0/src/protocols/ssh/client.c0000644000175100001440000001020013770536337016733 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "client.h" #include "common/clipboard.h" #include "common/recording.h" #include "common-ssh/sftp.h" #include "ssh.h" #include "terminal/terminal.h" #include "user.h" #include #include #include #include #include #include int guac_client_init(guac_client* client) { /* Set client args */ client->args = GUAC_SSH_CLIENT_ARGS; /* Allocate client instance data */ guac_ssh_client* ssh_client = calloc(1, sizeof(guac_ssh_client)); client->data = ssh_client; /* Init clipboard */ ssh_client->clipboard = guac_common_clipboard_alloc(GUAC_SSH_CLIPBOARD_MAX_LENGTH); /* Set handlers */ client->join_handler = guac_ssh_user_join_handler; client->free_handler = guac_ssh_client_free_handler; /* Register handlers for argument values that may be sent after the handshake */ guac_argv_register(GUAC_SSH_ARGV_COLOR_SCHEME, guac_ssh_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO); guac_argv_register(GUAC_SSH_ARGV_FONT_NAME, guac_ssh_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO); guac_argv_register(GUAC_SSH_ARGV_FONT_SIZE, guac_ssh_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO); /* Set locale and warn if not UTF-8 */ setlocale(LC_CTYPE, ""); if (strcmp(nl_langinfo(CODESET), "UTF-8") != 0) { guac_client_log(client, GUAC_LOG_INFO, "Current locale does not use UTF-8. Some characters may " "not render correctly."); } /* Success */ return 0; } int guac_ssh_client_free_handler(guac_client* client) { guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; /* Close SSH channel */ if (ssh_client->term_channel != NULL) { libssh2_channel_send_eof(ssh_client->term_channel); libssh2_channel_close(ssh_client->term_channel); } /* Free terminal (which may still be using term_channel) */ if (ssh_client->term != NULL) { /* Stop the terminal to unblock any pending reads/writes */ guac_terminal_stop(ssh_client->term); /* Wait ssh_client_thread to finish before freeing the terminal */ pthread_join(ssh_client->client_thread, NULL); guac_terminal_free(ssh_client->term); } /* Free terminal channel now that the terminal is finished */ if (ssh_client->term_channel != NULL) libssh2_channel_free(ssh_client->term_channel); /* Clean up the SFTP filesystem object and session */ if (ssh_client->sftp_filesystem) { guac_common_ssh_destroy_sftp_filesystem(ssh_client->sftp_filesystem); guac_common_ssh_destroy_session(ssh_client->sftp_session); } /* Clean up recording, if in progress */ if (ssh_client->recording != NULL) guac_common_recording_free(ssh_client->recording); /* Free interactive SSH session */ if (ssh_client->session != NULL) guac_common_ssh_destroy_session(ssh_client->session); /* Free SSH client credentials */ if (ssh_client->user != NULL) guac_common_ssh_destroy_user(ssh_client->user); /* Free parsed settings */ if (ssh_client->settings != NULL) guac_ssh_settings_free(ssh_client->settings); /* Free client structure */ guac_common_clipboard_free(ssh_client->clipboard); free(ssh_client); guac_common_ssh_uninit(); return 0; } guacamole-server-1.3.0/src/protocols/ssh/pipe.h0000644000175100001440000000253013702142276016414 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_SSH_PIPE_H #define GUAC_SSH_PIPE_H #include "config.h" #include /** * The name reserved for the inbound pipe stream which forces the terminal * emulator's STDIN to be received from the pipe. */ #define GUAC_SSH_STDIN_PIPE_NAME "STDIN" /** * Handles an incoming stream from a Guacamole "pipe" instruction. If the pipe * is named "STDIN", the the contents of the pipe stream are redirected to * STDIN of the terminal emulator for as long as the pipe is open. */ guac_user_pipe_handler guac_ssh_pipe_handler; #endif guacamole-server-1.3.0/src/protocols/ssh/ssh.c0000644000175100001440000004157613764613616016275 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "common/recording.h" #include "common-ssh/sftp.h" #include "common-ssh/ssh.h" #include "settings.h" #include "sftp.h" #include "ssh.h" #include "terminal/terminal.h" #include "ttymode.h" #ifdef ENABLE_SSH_AGENT #include "ssh_agent.h" #endif #include #include #include #include #include #include #ifdef LIBSSH2_USES_GCRYPT #include #endif #include #include #include #include #include #include #include #include #include #include #include #include /** * Produces a new user object containing a username and password or private * key, prompting the user as necessary to obtain that information. * * @param client * The Guacamole client containing any existing user data, as well as the * terminal to use when prompting the user. * * @return * A new user object containing the user's username and other credentials, * or NULL if fails to import key. */ static guac_common_ssh_user* guac_ssh_get_user(guac_client* client) { guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; guac_ssh_settings* settings = ssh_client->settings; guac_common_ssh_user* user; /* Get username */ if (settings->username == NULL) settings->username = guac_terminal_prompt(ssh_client->term, "Login as: ", true); /* Create user object from username */ user = guac_common_ssh_create_user(settings->username); /* If key specified, import */ if (settings->key_base64 != NULL) { guac_client_log(client, GUAC_LOG_DEBUG, "Attempting private key import (WITHOUT passphrase)"); /* Attempt to read key without passphrase */ if (guac_common_ssh_user_import_key(user, settings->key_base64, NULL)) { /* Log failure of initial attempt */ guac_client_log(client, GUAC_LOG_DEBUG, "Initial import failed: %s", guac_common_ssh_key_error()); guac_client_log(client, GUAC_LOG_DEBUG, "Re-attempting private key import (WITH passphrase)"); /* Prompt for passphrase if missing */ if (settings->key_passphrase == NULL) settings->key_passphrase = guac_terminal_prompt(ssh_client->term, "Key passphrase: ", false); /* Reattempt import with passphrase */ if (guac_common_ssh_user_import_key(user, settings->key_base64, settings->key_passphrase)) { /* If still failing, give up */ guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED, "Auth key import failed: %s", guac_common_ssh_key_error()); guac_common_ssh_destroy_user(user); return NULL; } } /* end decrypt key with passphrase */ /* Success */ guac_client_log(client, GUAC_LOG_INFO, "Auth key successfully imported."); } /* end if key given */ /* If available, get password from settings */ else if (settings->password != NULL) { guac_common_ssh_user_set_password(user, settings->password); } /* Clear screen of any prompts */ guac_terminal_printf(ssh_client->term, "\x1B[H\x1B[J"); return user; } /** * A function used to generate a terminal prompt to gather additional * credentials from the guac_client during a connection, and using * the specified string to generate the prompt for the user. * * @param client * The guac_client object associated with the current connection * where additional credentials are required. * * @param cred_name * The prompt text to display to the screen when prompting for the * additional credentials. * * @return * The string of credentials gathered from the user. */ static char* guac_ssh_get_credential(guac_client *client, char* cred_name) { guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; return guac_terminal_prompt(ssh_client->term, cred_name, false); } void* ssh_input_thread(void* data) { guac_client* client = (guac_client*) data; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; char buffer[8192]; int bytes_read; /* Write all data read */ while ((bytes_read = guac_terminal_read_stdin(ssh_client->term, buffer, sizeof(buffer))) > 0) { pthread_mutex_lock(&(ssh_client->term_channel_lock)); libssh2_channel_write(ssh_client->term_channel, buffer, bytes_read); pthread_mutex_unlock(&(ssh_client->term_channel_lock)); /* Make sure ssh_input_thread can be terminated anyway */ if (client->state == GUAC_CLIENT_STOPPING) break; } /* Stop the client so that ssh_client_thread can be terminated */ guac_client_stop(client); return NULL; } void* ssh_client_thread(void* data) { guac_client* client = (guac_client*) data; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; guac_ssh_settings* settings = ssh_client->settings; char buffer[8192]; pthread_t input_thread; /* If Wake-on-LAN is enabled, attempt to wake. */ if (settings->wol_send_packet) { guac_client_log(client, GUAC_LOG_DEBUG, "Sending Wake-on-LAN packet, " "and pausing for %d seconds.", settings->wol_wait_time); /* Send the Wake-on-LAN request. */ if (guac_wol_wake(settings->wol_mac_addr, settings->wol_broadcast_addr)) return NULL; /* If wait time is specified, sleep for that amount of time. */ if (settings->wol_wait_time > 0) guac_timestamp_msleep(settings->wol_wait_time * 1000); } /* Init SSH base libraries */ if (guac_common_ssh_init(client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "SSH library initialization failed"); return NULL; } char ssh_ttymodes[GUAC_SSH_TTYMODES_SIZE(1)]; /* Set up screen recording, if requested */ if (settings->recording_path != NULL) { ssh_client->recording = guac_common_recording_create(client, settings->recording_path, settings->recording_name, settings->create_recording_path, !settings->recording_exclude_output, !settings->recording_exclude_mouse, settings->recording_include_keys); } /* Create terminal */ ssh_client->term = guac_terminal_create(client, ssh_client->clipboard, settings->disable_copy, settings->max_scrollback, settings->font_name, settings->font_size, settings->resolution, settings->width, settings->height, settings->color_scheme, settings->backspace); /* Fail if terminal init failed */ if (ssh_client->term == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Terminal initialization failed"); return NULL; } /* Send current values of exposed arguments to owner only */ guac_client_for_owner(client, guac_ssh_send_current_argv, ssh_client); /* Set up typescript, if requested */ if (settings->typescript_path != NULL) { guac_terminal_create_typescript(ssh_client->term, settings->typescript_path, settings->typescript_name, settings->create_typescript_path); } /* Get user and credentials */ ssh_client->user = guac_ssh_get_user(client); if (ssh_client->user == NULL) { /* Already aborted within guac_ssh_get_user() */ return NULL; } /* Ensure connection is kept alive during lengthy connects */ guac_socket_require_keep_alive(client->socket); /* Open SSH session */ ssh_client->session = guac_common_ssh_create_session(client, settings->hostname, settings->port, ssh_client->user, settings->server_alive_interval, settings->host_key, guac_ssh_get_credential); if (ssh_client->session == NULL) { /* Already aborted within guac_common_ssh_create_session() */ return NULL; } pthread_mutex_init(&ssh_client->term_channel_lock, NULL); /* Open channel for terminal */ ssh_client->term_channel = libssh2_channel_open_session(ssh_client->session->session); if (ssh_client->term_channel == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to open terminal channel."); return NULL; } /* Set the client timezone */ if (settings->timezone != NULL) { if (libssh2_channel_setenv(ssh_client->term_channel, "TZ", settings->timezone)) { guac_client_log(client, GUAC_LOG_WARNING, "Unable to set the timezone: SSH server " "refused to set \"TZ\" variable."); } } #ifdef ENABLE_SSH_AGENT /* Start SSH agent forwarding, if enabled */ if (ssh_client->enable_agent) { libssh2_session_callback_set(ssh_client->session, LIBSSH2_CALLBACK_AUTH_AGENT, (void*) ssh_auth_agent_callback); /* Request agent forwarding */ if (libssh2_channel_request_auth_agent(ssh_client->term_channel)) guac_client_log(client, GUAC_LOG_ERROR, "Agent forwarding request failed"); else guac_client_log(client, GUAC_LOG_INFO, "Agent forwarding enabled."); } ssh_client->auth_agent = NULL; #endif /* Start SFTP session as well, if enabled */ if (settings->enable_sftp) { /* Create SSH session specific for SFTP */ guac_client_log(client, GUAC_LOG_DEBUG, "Reconnecting for SFTP..."); ssh_client->sftp_session = guac_common_ssh_create_session(client, settings->hostname, settings->port, ssh_client->user, settings->server_alive_interval, settings->host_key, NULL); if (ssh_client->sftp_session == NULL) { /* Already aborted within guac_common_ssh_create_session() */ return NULL; } /* Request SFTP */ ssh_client->sftp_filesystem = guac_common_ssh_create_sftp_filesystem( ssh_client->sftp_session, settings->sftp_root_directory, NULL, settings->sftp_disable_download, settings->sftp_disable_upload); /* Expose filesystem to connection owner */ guac_client_for_owner(client, guac_common_ssh_expose_sftp_filesystem, ssh_client->sftp_filesystem); /* Init handlers for Guacamole-specific console codes */ if (!settings->sftp_disable_upload) ssh_client->term->upload_path_handler = guac_sftp_set_upload_path; if (!settings->sftp_disable_download) ssh_client->term->file_download_handler = guac_sftp_download_file; guac_client_log(client, GUAC_LOG_DEBUG, "SFTP session initialized"); } /* Set up the ttymode array prior to requesting the PTY */ int ttymodeBytes = guac_ssh_ttymodes_init(ssh_ttymodes, GUAC_SSH_TTY_OP_VERASE, settings->backspace, GUAC_SSH_TTY_OP_END); if (ttymodeBytes < 1) guac_client_log(client, GUAC_LOG_WARNING, "Unable to set TTY modes." " Backspace may not work as expected."); /* Request PTY */ if (libssh2_channel_request_pty_ex(ssh_client->term_channel, settings->terminal_type, strlen(settings->terminal_type), ssh_ttymodes, ttymodeBytes, ssh_client->term->term_width, ssh_client->term->term_height, 0, 0)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to allocate PTY."); return NULL; } /* Forward specified locale */ if (settings->locale != NULL) { if (libssh2_channel_setenv(ssh_client->term_channel, "LANG", settings->locale)) { guac_client_log(client, GUAC_LOG_WARNING, "Unable to forward locale: SSH server refused to set " "\"LANG\" environment variable."); } } /* If a command is specified, run that instead of a shell */ if (settings->command != NULL) { if (libssh2_channel_exec(ssh_client->term_channel, settings->command)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to execute command."); return NULL; } } /* Otherwise, request a shell */ else if (libssh2_channel_shell(ssh_client->term_channel)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to associate shell with PTY."); return NULL; } /* Logged in */ guac_client_log(client, GUAC_LOG_INFO, "SSH connection successful."); guac_terminal_start(ssh_client->term); /* Start input thread */ if (pthread_create(&(input_thread), NULL, ssh_input_thread, (void*) client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread"); return NULL; } /* Set non-blocking */ libssh2_session_set_blocking(ssh_client->session->session, 0); /* While data available, write to terminal */ int bytes_read = 0; for (;;) { /* Track total amount of data read */ int total_read = 0; /* Timeout for polling socket activity */ int timeout; pthread_mutex_lock(&(ssh_client->term_channel_lock)); /* Stop reading at EOF */ if (libssh2_channel_eof(ssh_client->term_channel)) { pthread_mutex_unlock(&(ssh_client->term_channel_lock)); break; } /* Client is stopping, break the loop */ if (client->state == GUAC_CLIENT_STOPPING) { pthread_mutex_unlock(&(ssh_client->term_channel_lock)); break; } /* Send keepalive at configured interval */ if (settings->server_alive_interval > 0) { timeout = 0; if (libssh2_keepalive_send(ssh_client->session->session, &timeout) > 0) break; timeout *= 1000; } /* If keepalive is not configured, sleep for the default of 1 second */ else timeout = GUAC_SSH_DEFAULT_POLL_TIMEOUT; /* Read terminal data */ bytes_read = libssh2_channel_read(ssh_client->term_channel, buffer, sizeof(buffer)); pthread_mutex_unlock(&(ssh_client->term_channel_lock)); /* Attempt to write data received. Exit on failure. */ if (bytes_read > 0) { int written = guac_terminal_write(ssh_client->term, buffer, bytes_read); if (written < 0) break; total_read += bytes_read; } else if (bytes_read < 0 && bytes_read != LIBSSH2_ERROR_EAGAIN) break; #ifdef ENABLE_SSH_AGENT /* If agent open, handle any agent packets */ if (ssh_client->auth_agent != NULL) { bytes_read = ssh_auth_agent_read(ssh_client->auth_agent); if (bytes_read > 0) total_read += bytes_read; else if (bytes_read < 0 && bytes_read != LIBSSH2_ERROR_EAGAIN) ssh_client->auth_agent = NULL; } #endif /* Wait for more data if reads turn up empty */ if (total_read == 0) { /* Wait on the SSH session file descriptor only */ struct pollfd fds[] = {{ .fd = ssh_client->session->fd, .events = POLLIN, .revents = 0, }}; /* Wait up to computed timeout */ if (poll(fds, 1, timeout) < 0) break; } } /* Kill client and Wait for input thread to die */ guac_client_stop(client); pthread_join(input_thread, NULL); pthread_mutex_destroy(&ssh_client->term_channel_lock); guac_client_log(client, GUAC_LOG_INFO, "SSH connection ended."); return NULL; } guacamole-server-1.3.0/src/protocols/ssh/Makefile.am0000644000175100001440000000502213702142276017341 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac-client-ssh.la libguac_client_ssh_la_SOURCES = \ argv.c \ client.c \ clipboard.c \ input.c \ pipe.c \ settings.c \ sftp.c \ ssh.c \ ttymode.c \ user.c noinst_HEADERS = \ argv.h \ client.h \ clipboard.h \ input.h \ pipe.h \ settings.h \ sftp.h \ ssh.h \ ttymode.h \ user.h # Add agent sources if enabled if ENABLE_SSH_AGENT libguac_client_ssh_la_SOURCES += ssh_agent.c noinst_HEADERS += ssh_agent.h endif libguac_client_ssh_la_CFLAGS = \ -Werror -Wall -Iinclude \ @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ \ @TERMINAL_INCLUDE@ libguac_client_ssh_la_LIBADD = \ @COMMON_LTLIB@ \ @COMMON_SSH_LTLIB@ \ @LIBGUAC_LTLIB@ \ @TERMINAL_LTLIB@ libguac_client_ssh_la_LDFLAGS = \ -version-info 0:0:0 \ @PTHREAD_LIBS@ \ @SSH_LIBS@ \ @SSL_LIBS@ guacamole-server-1.3.0/src/protocols/ssh/ssh_agent.c0000644000175100001440000001315313613156714017433 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "client.h" #include "ssh_agent.h" #include "ssh_buffer.h" #include #include #include #include #include #include #include #include #include #include void ssh_auth_agent_sign(ssh_auth_agent* agent, char* data, int data_length) { LIBSSH2_CHANNEL* channel = agent->channel; ssh_key* key = agent->identity; char sig[4096]; int sig_len; char buffer[4096]; char* pos = buffer; /* Sign with key */ sig_len = ssh_key_sign(key, data, data_length, (u_char*) sig); if (sig_len < 0) return; buffer_write_uint32(&pos, 1+4 + 4+7 + 4+sig_len); buffer_write_byte(&pos, SSH2_AGENT_SIGN_RESPONSE); buffer_write_uint32(&pos, 4+7 + 4+sig_len); /* Write key type */ if (key->type == SSH_KEY_RSA) buffer_write_string(&pos, "ssh-rsa", 7); else if (key->type == SSH_KEY_DSA) buffer_write_string(&pos, "ssh-dss", 7); else return; /* Write signature */ buffer_write_string(&pos, sig, sig_len); libssh2_channel_write(channel, buffer, pos-buffer); libssh2_channel_flush(channel); } void ssh_auth_agent_list_identities(ssh_auth_agent* auth_agent) { LIBSSH2_CHANNEL* channel = auth_agent->channel; ssh_key* key = auth_agent->identity; char buffer[4096]; char* pos = buffer; buffer_write_uint32(&pos, 1+4 + key->public_key_length+4 + sizeof(SSH_AGENT_COMMENT)+3); buffer_write_byte(&pos, SSH2_AGENT_IDENTITIES_ANSWER); buffer_write_uint32(&pos, 1); buffer_write_string(&pos, key->public_key, key->public_key_length); buffer_write_string(&pos, SSH_AGENT_COMMENT, sizeof(SSH_AGENT_COMMENT)-1); libssh2_channel_write(channel, buffer, pos-buffer); libssh2_channel_flush(channel); } void ssh_auth_agent_handle_packet(ssh_auth_agent* auth_agent, uint8_t type, char* data, int data_length) { switch (type) { /* List identities */ case SSH2_AGENT_REQUEST_IDENTITIES: ssh_auth_agent_list_identities(auth_agent); break; /* Sign request */ case SSH2_AGENT_SIGN_REQUEST: { char* pos = data; int key_blob_length; int sign_data_length; char* sign_data; /* Skip past key, read data, ignore flags */ buffer_read_string(&pos, &key_blob_length); sign_data = buffer_read_string(&pos, &sign_data_length); /* Sign given data */ ssh_auth_agent_sign(auth_agent, sign_data, sign_data_length); break; } /* Otherwise, return failure */ default: libssh2_channel_write(auth_agent->channel, UNSUPPORTED, sizeof(UNSUPPORTED)-1); } } int ssh_auth_agent_read(ssh_auth_agent* auth_agent) { LIBSSH2_CHANNEL* channel = auth_agent->channel; int bytes_read; if (libssh2_channel_eof(channel)) return -1; /* Read header if available */ if (auth_agent->buffer_length >= 5) { uint32_t length = (((unsigned char*) auth_agent->buffer)[0] << 24) | (((unsigned char*) auth_agent->buffer)[1] << 16) | (((unsigned char*) auth_agent->buffer)[2] << 8) | ((unsigned char*) auth_agent->buffer)[3]; uint8_t type = ((unsigned char*) auth_agent->buffer)[4]; /* If enough data read, call handler, shift data */ if (auth_agent->buffer_length >= length+4) { ssh_auth_agent_handle_packet(auth_agent, type, auth_agent->buffer+5, length-1); auth_agent->buffer_length -= length+4; memmove(auth_agent->buffer, auth_agent->buffer+length+4, auth_agent->buffer_length); return length+4; } } /* Read data into buffer */ bytes_read = libssh2_channel_read(channel, auth_agent->buffer+auth_agent->buffer_length, sizeof(auth_agent->buffer)-auth_agent->buffer_length); /* If unsuccessful, return error */ if (bytes_read < 0) return bytes_read; /* Update buffer length */ auth_agent->buffer_length += bytes_read; return bytes_read; } void ssh_auth_agent_callback(LIBSSH2_SESSION *session, LIBSSH2_CHANNEL *channel, void **abstract) { /* Get client data */ guac_client* client = (guac_client*) *abstract; ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; /* Init auth agent */ ssh_auth_agent* auth_agent = malloc(sizeof(ssh_auth_agent)); auth_agent->channel = channel; auth_agent->identity = client_data->key; auth_agent->buffer_length = 0; /* Store auth agent */ client_data->auth_agent = auth_agent; } guacamole-server-1.3.0/src/protocols/telnet/0000755000175100001440000000000013772471161016071 500000000000000guacamole-server-1.3.0/src/protocols/telnet/clipboard.c0000644000175100001440000000400513702142276020106 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "clipboard.h" #include "common/clipboard.h" #include "telnet.h" #include "terminal/terminal.h" #include #include #include int guac_telnet_clipboard_handler(guac_user* user, guac_stream* stream, char* mimetype) { /* Clear clipboard and prepare for new data */ guac_client* client = user->client; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_common_clipboard_reset(telnet_client->clipboard, mimetype); /* Set handlers for clipboard stream */ stream->blob_handler = guac_telnet_clipboard_blob_handler; stream->end_handler = guac_telnet_clipboard_end_handler; return 0; } int guac_telnet_clipboard_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { /* Append new data */ guac_client* client = user->client; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_common_clipboard_append(telnet_client->clipboard, data, length); return 0; } int guac_telnet_clipboard_end_handler(guac_user* user, guac_stream* stream) { /* Nothing to do - clipboard is implemented within client */ return 0; } guacamole-server-1.3.0/src/protocols/telnet/argv.c0000644000175100001440000000553713770536337017133 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "telnet.h" #include "terminal/terminal.h" #include #include #include #include #include int guac_telnet_argv_callback(guac_user* user, const char* mimetype, const char* name, const char* value, void* data) { guac_client* client = user->client; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_terminal* terminal = telnet_client->term; /* Update color scheme */ if (strcmp(name, GUAC_TELNET_ARGV_COLOR_SCHEME) == 0) guac_terminal_apply_color_scheme(terminal, value); /* Update font name */ else if (strcmp(name, GUAC_TELNET_ARGV_FONT_NAME) == 0) guac_terminal_apply_font(terminal, value, -1, 0); /* Update only if font size is sane */ else if (strcmp(name, GUAC_TELNET_ARGV_FONT_SIZE) == 0) { int size = atoi(value); if (size > 0) guac_terminal_apply_font(terminal, NULL, size, telnet_client->settings->resolution); } /* Update terminal window size if connected */ if (telnet_client->telnet != NULL && telnet_client->naws_enabled) guac_telnet_send_naws(telnet_client->telnet, terminal->term_width, terminal->term_height); return 0; } void* guac_telnet_send_current_argv(guac_user* user, void* data) { guac_telnet_client* telnet_client = (guac_telnet_client*) data; guac_terminal* terminal = telnet_client->term; /* Send current color scheme */ guac_user_stream_argv(user, user->socket, "text/plain", GUAC_TELNET_ARGV_COLOR_SCHEME, terminal->color_scheme); /* Send current font name */ guac_user_stream_argv(user, user->socket, "text/plain", GUAC_TELNET_ARGV_FONT_NAME, terminal->font_name); /* Send current font size */ char font_size[64]; sprintf(font_size, "%i", terminal->font_size); guac_user_stream_argv(user, user->socket, "text/plain", GUAC_TELNET_ARGV_FONT_SIZE, font_size); return NULL; } guacamole-server-1.3.0/src/protocols/telnet/input.h0000644000175100001440000000261213613156714017320 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TELNET_INPUT_H #define GUAC_TELNET_INPUT_H #include "config.h" #include /** * Handler for key events. Required by libguac and called whenever key events * are received. */ guac_user_key_handler guac_telnet_user_key_handler; /** * Handler for mouse events. Required by libguac and called whenever mouse * events are received. */ guac_user_mouse_handler guac_telnet_user_mouse_handler; /** * Handler for size events. Required by libguac and called whenever the remote * display (window) is resized. */ guac_user_size_handler guac_telnet_user_size_handler; #endif guacamole-server-1.3.0/src/protocols/telnet/pipe.c0000644000175100001440000000321313702142276017104 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "pipe.h" #include "telnet.h" #include "terminal/terminal.h" #include #include #include #include int guac_telnet_pipe_handler(guac_user* user, guac_stream* stream, char* mimetype, char* name) { guac_client* client = user->client; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; /* Redirect STDIN if pipe has required name */ if (strcmp(name, GUAC_TELNET_STDIN_PIPE_NAME) == 0) { guac_terminal_send_stream(telnet_client->term, user, stream); return 0; } /* No other inbound pipe streams are supported */ guac_protocol_send_ack(user->socket, stream, "No such input stream.", GUAC_PROTOCOL_STATUS_RESOURCE_NOT_FOUND); guac_socket_flush(user->socket); return 0; } guacamole-server-1.3.0/src/protocols/telnet/user.h0000644000175100001440000000212613613156714017137 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TELNET_USER_H #define GUAC_TELNET_USER_H #include "config.h" #include /** * Handler for joining users. */ guac_user_join_handler guac_telnet_user_join_handler; /** * Handler for leaving users. */ guac_user_leave_handler guac_telnet_user_leave_handler; #endif guacamole-server-1.3.0/src/protocols/telnet/argv.h0000644000175100001440000000444713770536337017137 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TELNET_ARGV_H #define GUAC_TELNET_ARGV_H #include "config.h" #include #include /** * The name of the parameter that specifies/updates the color scheme used by * the terminal emulator. */ #define GUAC_TELNET_ARGV_COLOR_SCHEME "color-scheme" /** * The name of the parameter that specifies/updates the name of the font used * by the terminal emulator. */ #define GUAC_TELNET_ARGV_FONT_NAME "font-name" /** * The name of the parameter that specifies/updates the font size used by the * terminal emulator. */ #define GUAC_TELNET_ARGV_FONT_SIZE "font-size" /** * Handles a received argument value from a Guacamole "argv" instruction, * updating the given connection parameter. */ guac_argv_callback guac_telnet_argv_callback; /** * Sends the current values of all non-sensitive parameters which may be set * while the connection is running to the given user. Note that the user * receiving these values will not necessarily be able to set new values * themselves if their connection is read-only. This function can be used as * the callback for guac_client_foreach_user() and guac_client_for_owner() * * @param user * The user that should receive the values of all non-sensitive parameters * which may be set while the connection is running. * * @param data * The guac_telnet_client instance associated with the current connection. * * @return * Always NULL. */ void* guac_telnet_send_current_argv(guac_user* user, void* data); #endif guacamole-server-1.3.0/src/protocols/telnet/user.c0000644000175100001440000000716413770536337017150 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "clipboard.h" #include "input.h" #include "pipe.h" #include "settings.h" #include "telnet.h" #include "terminal/terminal.h" #include "user.h" #include #include #include #include #include int guac_telnet_user_join_handler(guac_user* user, int argc, char** argv) { guac_client* client = user->client; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; /* Parse provided arguments */ guac_telnet_settings* settings = guac_telnet_parse_args(user, argc, (const char**) argv); /* Fail if settings cannot be parsed */ if (settings == NULL) { guac_user_log(user, GUAC_LOG_INFO, "Badly formatted client arguments."); return 1; } /* Store settings at user level */ user->data = settings; /* Connect via telnet if owner */ if (user->owner) { /* Store owner's settings at client level */ telnet_client->settings = settings; /* Start client thread */ if (pthread_create(&(telnet_client->client_thread), NULL, guac_telnet_client_thread, (void*) client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start telnet client thread"); return 1; } } /* If not owner, synchronize with current display */ else { guac_terminal_dup(telnet_client->term, user, user->socket); guac_telnet_send_current_argv(user, telnet_client); guac_socket_flush(user->socket); } /* Only handle events if not read-only */ if (!settings->read_only) { /* General mouse/keyboard events */ user->key_handler = guac_telnet_user_key_handler; user->mouse_handler = guac_telnet_user_mouse_handler; /* Inbound (client to server) clipboard transfer */ if (!settings->disable_paste) user->clipboard_handler = guac_telnet_clipboard_handler; /* STDIN redirection */ user->pipe_handler = guac_telnet_pipe_handler; /* Updates to connection parameters */ user->argv_handler = guac_argv_handler; /* Display size change events */ user->size_handler = guac_telnet_user_size_handler; } return 0; } int guac_telnet_user_leave_handler(guac_user* user) { guac_telnet_client* telnet_client = (guac_telnet_client*) user->client->data; /* Update shared cursor state */ guac_common_cursor_remove_user(telnet_client->term->cursor, user); /* Free settings if not owner (owner settings will be freed with client) */ if (!user->owner) { guac_telnet_settings* settings = (guac_telnet_settings*) user->data; guac_telnet_settings_free(settings); } return 0; } guacamole-server-1.3.0/src/protocols/telnet/input.c0000644000175100001440000001032513702142276017310 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/recording.h" #include "input.h" #include "terminal/terminal.h" #include "telnet.h" #include #include #include #include #include #include #include int guac_telnet_user_mouse_handler(guac_user* user, int x, int y, int mask) { guac_client* client = user->client; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_telnet_settings* settings = telnet_client->settings; guac_terminal* term = telnet_client->term; /* Skip if terminal not yet ready */ if (term == NULL) return 0; /* Report mouse position within recording */ if (telnet_client->recording != NULL) guac_common_recording_report_mouse(telnet_client->recording, x, y, mask); /* Send mouse if not searching for password or username */ if (settings->password_regex == NULL && settings->username_regex == NULL) guac_terminal_send_mouse(term, user, x, y, mask); return 0; } int guac_telnet_user_key_handler(guac_user* user, int keysym, int pressed) { guac_client* client = user->client; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_telnet_settings* settings = telnet_client->settings; guac_terminal* term = telnet_client->term; /* Report key state within recording */ if (telnet_client->recording != NULL) guac_common_recording_report_key(telnet_client->recording, keysym, pressed); /* Skip if terminal not yet ready */ if (term == NULL) return 0; /* Stop searching for password */ if (settings->password_regex != NULL) { guac_client_log(client, GUAC_LOG_DEBUG, "Stopping password prompt search due to user input."); regfree(settings->password_regex); free(settings->password_regex); settings->password_regex = NULL; } /* Stop searching for username */ if (settings->username_regex != NULL) { guac_client_log(client, GUAC_LOG_DEBUG, "Stopping username prompt search due to user input."); regfree(settings->username_regex); free(settings->username_regex); settings->username_regex = NULL; } /* Intercept and handle Pause / Break / Ctrl+0 as "IAC BRK" */ if (pressed && ( keysym == 0xFF13 /* Pause */ || keysym == 0xFF6B /* Break */ || (term->mod_ctrl && keysym == '0') /* Ctrl + 0 */ )) { /* Send IAC BRK */ telnet_iac(telnet_client->telnet, TELNET_BREAK); return 0; } /* Send key */ guac_terminal_send_key(term, keysym, pressed); return 0; } int guac_telnet_user_size_handler(guac_user* user, int width, int height) { /* Get terminal */ guac_client* client = user->client; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_terminal* terminal = telnet_client->term; /* Skip if terminal not yet ready */ if (terminal == NULL) return 0; /* Resize terminal */ guac_terminal_resize(terminal, width, height); /* Update terminal window size if connected */ if (telnet_client->telnet != NULL && telnet_client->naws_enabled) guac_telnet_send_naws(telnet_client->telnet, terminal->term_width, terminal->term_height); return 0; } guacamole-server-1.3.0/src/protocols/telnet/clipboard.h0000644000175100001440000000240113613156714020114 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TELNET_CLIPBOARD_H #define GUAC_TELNET_CLIPBOARD_H #include "config.h" #include /** * Handler for inbound clipboard streams. */ guac_user_clipboard_handler guac_telnet_clipboard_handler; /** * Handler for data received along clipboard streams. */ guac_user_blob_handler guac_telnet_clipboard_blob_handler; /** * Handler for end-of-stream related to clipboard. */ guac_user_end_handler guac_telnet_clipboard_end_handler; #endif guacamole-server-1.3.0/src/protocols/telnet/Makefile.in0000644000175100001440000010627213772471103020062 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/protocols/telnet ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) libguac_client_telnet_la_DEPENDENCIES = am_libguac_client_telnet_la_OBJECTS = \ libguac_client_telnet_la-argv.lo \ libguac_client_telnet_la-client.lo \ libguac_client_telnet_la-clipboard.lo \ libguac_client_telnet_la-input.lo \ libguac_client_telnet_la-pipe.lo \ libguac_client_telnet_la-settings.lo \ libguac_client_telnet_la-telnet.lo \ libguac_client_telnet_la-user.lo libguac_client_telnet_la_OBJECTS = \ $(am_libguac_client_telnet_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libguac_client_telnet_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) \ $(libguac_client_telnet_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libguac_client_telnet_la-argv.Plo \ ./$(DEPDIR)/libguac_client_telnet_la-client.Plo \ ./$(DEPDIR)/libguac_client_telnet_la-clipboard.Plo \ ./$(DEPDIR)/libguac_client_telnet_la-input.Plo \ ./$(DEPDIR)/libguac_client_telnet_la-pipe.Plo \ ./$(DEPDIR)/libguac_client_telnet_la-settings.Plo \ ./$(DEPDIR)/libguac_client_telnet_la-telnet.Plo \ ./$(DEPDIR)/libguac_client_telnet_la-user.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libguac_client_telnet_la_SOURCES) DIST_SOURCES = $(libguac_client_telnet_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac-client-telnet.la libguac_client_telnet_la_SOURCES = \ argv.c \ client.c \ clipboard.c \ input.c \ pipe.c \ settings.c \ telnet.c \ user.c noinst_HEADERS = \ argv.h \ client.h \ clipboard.h \ input.h \ pipe.h \ settings.h \ telnet.h \ user.h libguac_client_telnet_la_CFLAGS = \ -Werror -Wall -Iinclude \ @LIBGUAC_INCLUDE@ \ @TERMINAL_INCLUDE@ libguac_client_telnet_la_LIBADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ \ @TERMINAL_LTLIB@ libguac_client_telnet_la_LDFLAGS = \ -version-info 0:0:0 \ @PTHREAD_LIBS@ \ @TELNET_LIBS@ all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/protocols/telnet/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/protocols/telnet/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libguac-client-telnet.la: $(libguac_client_telnet_la_OBJECTS) $(libguac_client_telnet_la_DEPENDENCIES) $(EXTRA_libguac_client_telnet_la_DEPENDENCIES) $(AM_V_CCLD)$(libguac_client_telnet_la_LINK) -rpath $(libdir) $(libguac_client_telnet_la_OBJECTS) $(libguac_client_telnet_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_telnet_la-argv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_telnet_la-client.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_telnet_la-clipboard.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_telnet_la-input.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_telnet_la-pipe.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_telnet_la-settings.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_telnet_la-telnet.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_telnet_la-user.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libguac_client_telnet_la-argv.lo: argv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -MT libguac_client_telnet_la-argv.lo -MD -MP -MF $(DEPDIR)/libguac_client_telnet_la-argv.Tpo -c -o libguac_client_telnet_la-argv.lo `test -f 'argv.c' || echo '$(srcdir)/'`argv.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_telnet_la-argv.Tpo $(DEPDIR)/libguac_client_telnet_la-argv.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='argv.c' object='libguac_client_telnet_la-argv.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -c -o libguac_client_telnet_la-argv.lo `test -f 'argv.c' || echo '$(srcdir)/'`argv.c libguac_client_telnet_la-client.lo: client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -MT libguac_client_telnet_la-client.lo -MD -MP -MF $(DEPDIR)/libguac_client_telnet_la-client.Tpo -c -o libguac_client_telnet_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_telnet_la-client.Tpo $(DEPDIR)/libguac_client_telnet_la-client.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client.c' object='libguac_client_telnet_la-client.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -c -o libguac_client_telnet_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c libguac_client_telnet_la-clipboard.lo: clipboard.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -MT libguac_client_telnet_la-clipboard.lo -MD -MP -MF $(DEPDIR)/libguac_client_telnet_la-clipboard.Tpo -c -o libguac_client_telnet_la-clipboard.lo `test -f 'clipboard.c' || echo '$(srcdir)/'`clipboard.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_telnet_la-clipboard.Tpo $(DEPDIR)/libguac_client_telnet_la-clipboard.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='clipboard.c' object='libguac_client_telnet_la-clipboard.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -c -o libguac_client_telnet_la-clipboard.lo `test -f 'clipboard.c' || echo '$(srcdir)/'`clipboard.c libguac_client_telnet_la-input.lo: input.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -MT libguac_client_telnet_la-input.lo -MD -MP -MF $(DEPDIR)/libguac_client_telnet_la-input.Tpo -c -o libguac_client_telnet_la-input.lo `test -f 'input.c' || echo '$(srcdir)/'`input.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_telnet_la-input.Tpo $(DEPDIR)/libguac_client_telnet_la-input.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='input.c' object='libguac_client_telnet_la-input.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -c -o libguac_client_telnet_la-input.lo `test -f 'input.c' || echo '$(srcdir)/'`input.c libguac_client_telnet_la-pipe.lo: pipe.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -MT libguac_client_telnet_la-pipe.lo -MD -MP -MF $(DEPDIR)/libguac_client_telnet_la-pipe.Tpo -c -o libguac_client_telnet_la-pipe.lo `test -f 'pipe.c' || echo '$(srcdir)/'`pipe.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_telnet_la-pipe.Tpo $(DEPDIR)/libguac_client_telnet_la-pipe.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pipe.c' object='libguac_client_telnet_la-pipe.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -c -o libguac_client_telnet_la-pipe.lo `test -f 'pipe.c' || echo '$(srcdir)/'`pipe.c libguac_client_telnet_la-settings.lo: settings.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -MT libguac_client_telnet_la-settings.lo -MD -MP -MF $(DEPDIR)/libguac_client_telnet_la-settings.Tpo -c -o libguac_client_telnet_la-settings.lo `test -f 'settings.c' || echo '$(srcdir)/'`settings.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_telnet_la-settings.Tpo $(DEPDIR)/libguac_client_telnet_la-settings.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings.c' object='libguac_client_telnet_la-settings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -c -o libguac_client_telnet_la-settings.lo `test -f 'settings.c' || echo '$(srcdir)/'`settings.c libguac_client_telnet_la-telnet.lo: telnet.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -MT libguac_client_telnet_la-telnet.lo -MD -MP -MF $(DEPDIR)/libguac_client_telnet_la-telnet.Tpo -c -o libguac_client_telnet_la-telnet.lo `test -f 'telnet.c' || echo '$(srcdir)/'`telnet.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_telnet_la-telnet.Tpo $(DEPDIR)/libguac_client_telnet_la-telnet.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='telnet.c' object='libguac_client_telnet_la-telnet.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -c -o libguac_client_telnet_la-telnet.lo `test -f 'telnet.c' || echo '$(srcdir)/'`telnet.c libguac_client_telnet_la-user.lo: user.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -MT libguac_client_telnet_la-user.lo -MD -MP -MF $(DEPDIR)/libguac_client_telnet_la-user.Tpo -c -o libguac_client_telnet_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_telnet_la-user.Tpo $(DEPDIR)/libguac_client_telnet_la-user.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user.c' object='libguac_client_telnet_la-user.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_telnet_la_CFLAGS) $(CFLAGS) -c -o libguac_client_telnet_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libguac_client_telnet_la-argv.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-client.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-clipboard.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-input.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-pipe.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-settings.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-telnet.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-user.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libguac_client_telnet_la-argv.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-client.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-clipboard.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-input.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-pipe.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-settings.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-telnet.Plo -rm -f ./$(DEPDIR)/libguac_client_telnet_la-user.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/protocols/telnet/settings.h0000644000175100001440000002241413764613616020031 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TELNET_SETTINGS_H #define GUAC_TELNET_SETTINGS_H #include "config.h" #include #include #include #include /** * The name of the font to use for the terminal if no name is specified. */ #define GUAC_TELNET_DEFAULT_FONT_NAME "monospace" /** * The size of the font to use for the terminal if no font size is specified, * in points. */ #define GUAC_TELNET_DEFAULT_FONT_SIZE 12 /** * The port to connect to when initiating any telnet connection, if no other * port is specified. */ #define GUAC_TELNET_DEFAULT_PORT "23" /** * The filename to use for the typescript, if not specified. */ #define GUAC_TELNET_DEFAULT_TYPESCRIPT_NAME "typescript" /** * The filename to use for the screen recording, if not specified. */ #define GUAC_TELNET_DEFAULT_RECORDING_NAME "recording" /** * The regular expression to use when searching for the username/login prompt * if no other regular expression is specified. */ #define GUAC_TELNET_DEFAULT_USERNAME_REGEX "[Ll]ogin:" /** * The regular expression to use when searching for the password prompt if no * other regular expression is specified. */ #define GUAC_TELNET_DEFAULT_PASSWORD_REGEX "[Pp]assword:" /** * The default maximum scrollback size in rows. */ #define GUAC_TELNET_DEFAULT_MAX_SCROLLBACK 1000 /** * Settings for the telnet connection. The values for this structure are parsed * from the arguments given during the Guacamole protocol handshake using the * guac_telnet_parse_args() function. */ typedef struct guac_telnet_settings { /** * The hostname of the telnet server to connect to. */ char* hostname; /** * The port of the telnet server to connect to. */ char* port; /** * The name of the user to login as, if any. If no username is specified, * this will be NULL. */ char* username; /** * The regular expression to use when searching for the username/login * prompt. If no username is specified, this will be NULL. If a username * is specified, this will either be the specified username regex, or the * default username regex. */ regex_t* username_regex; /** * The password to give when authenticating, if any. If no password is * specified, this will be NULL. */ char* password; /** * The regular expression to use when searching for the password prompt. If * no password is specified, this will be NULL. If a password is specified, * this will either be the specified password regex, or the default * password regex. */ regex_t* password_regex; /** * The regular expression to use when searching for whether login was * successful. If no such regex is specified, or if no login failure regex * was specified, this will be NULL. */ regex_t* login_success_regex; /** * The regular expression to use when searching for whether login failed. * If no such regex is specified, or if no login success regex was * specified, this will be NULL. */ regex_t* login_failure_regex; /** * Whether this connection is read-only, and user input should be dropped. */ bool read_only; /** * The maximum size of the scrollback buffer in rows. */ int max_scrollback; /** * The name of the font to use for display rendering. */ char* font_name; /** * The size of the font to use, in points. */ int font_size; /** * The name of the color scheme to use. */ char* color_scheme; /** * The desired width of the terminal display, in pixels. */ int width; /** * The desired height of the terminal display, in pixels. */ int height; /** * The desired screen resolution, in DPI. */ int resolution; /** * Whether outbound clipboard access should be blocked. If set, it will not * be possible to copy data from the terminal to the client using the * clipboard. */ bool disable_copy; /** * Whether inbound clipboard access should be blocked. If set, it will not * be possible to paste data from the client to the terminal using the * clipboard. */ bool disable_paste; /** * The path in which the typescript should be saved, if enabled. If no * typescript should be saved, this will be NULL. */ char* typescript_path; /** * The filename to use for the typescript, if enabled. */ char* typescript_name; /** * Whether the typescript path should be automatically created if it does * not already exist. */ bool create_typescript_path; /** * The path in which the screen recording should be saved, if enabled. If * no screen recording should be saved, this will be NULL. */ char* recording_path; /** * The filename to use for the screen recording, if enabled. */ char* recording_name; /** * Whether the screen recording path should be automatically created if it * does not already exist. */ bool create_recording_path; /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output * is included by default, as it is necessary for any recording which must * later be viewable as video. */ bool recording_exclude_output; /** * Whether changes to mouse state, such as position and buttons pressed or * released, should NOT be included in the session recording. Mouse state * is included by default, as it is necessary for the mouse cursor to be * rendered in any resulting video. */ bool recording_exclude_mouse; /** * Whether keys pressed and released should be included in the session * recording. Key events are NOT included by default within the recording, * as doing so has privacy and security implications. Including key events * may be necessary in certain auditing contexts, but should only be done * with caution. Key events can easily contain sensitive information, such * as passwords, credit card numbers, etc. */ bool recording_include_keys; /** * The ASCII code, as an integer, that the telnet client will use when the * backspace key is pressed. By default, this is 127, ASCII delete, if * not specified in the client settings. */ int backspace; /** * The terminal emulator type that is passed to the remote system. */ char* terminal_type; /** * Whether or not to send the magic Wake-on-LAN (WoL) packet prior to * continuing the connection. */ bool wol_send_packet; /** * The MAC address to put in the magic WoL packet for the remote host to * wake. */ char* wol_mac_addr; /** * The broadcast address to which to send the magic WoL packet to wake * the remote host. */ char* wol_broadcast_addr; /** * The number of seconds to wait after sending the magic WoL packet before * continuing the connection. */ int wol_wait_time; } guac_telnet_settings; /** * Parses all given args, storing them in a newly-allocated settings object. If * the args fail to parse, NULL is returned. * * @param user * The user who submitted the given arguments while joining the * connection. * * @param argc * The number of arguments within the argv array. * * @param argv * The values of all arguments provided by the user. * * @return * A newly-allocated settings object which must be freed with * guac_telnet_settings_free() when no longer needed. If the arguments fail * to parse, NULL is returned. */ guac_telnet_settings* guac_telnet_parse_args(guac_user* user, int argc, const char** argv); /** * Frees the regex pointed to by the given pointer, assigning the value NULL to * that pointer once the regex is freed. If the pointer already contains NULL, * this function has no effect. * * @param regex * The address of the pointer to the regex that should be freed. */ void guac_telnet_regex_free(regex_t** regex); /** * Frees the given guac_telnet_settings object, having been previously * allocated via guac_telnet_parse_args(). * * @param settings * The settings object to free. */ void guac_telnet_settings_free(guac_telnet_settings* settings); /** * NULL-terminated array of accepted client args. */ extern const char* GUAC_TELNET_CLIENT_ARGS[]; #endif guacamole-server-1.3.0/src/protocols/telnet/settings.c0000644000175100001440000004437613770536337020040 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "common/defaults.h" #include "settings.h" #include #include #include #include #include #include #include /* Client plugin arguments */ const char* GUAC_TELNET_CLIENT_ARGS[] = { "hostname", "port", "username", "username-regex", "password", "password-regex", GUAC_TELNET_ARGV_FONT_NAME, GUAC_TELNET_ARGV_FONT_SIZE, GUAC_TELNET_ARGV_COLOR_SCHEME, "typescript-path", "typescript-name", "create-typescript-path", "recording-path", "recording-name", "recording-exclude-output", "recording-exclude-mouse", "recording-include-keys", "create-recording-path", "read-only", "backspace", "terminal-type", "scrollback", "login-success-regex", "login-failure-regex", "disable-copy", "disable-paste", "wol-send-packet", "wol-mac-addr", "wol-broadcast-addr", "wol-wait-time", NULL }; enum TELNET_ARGS_IDX { /** * The hostname to connect to. Required. */ IDX_HOSTNAME, /** * The port to connect to. Optional. */ IDX_PORT, /** * The name of the user to login as. Optional. */ IDX_USERNAME, /** * The regular expression to use when searching for the username/login * prompt. Optional. */ IDX_USERNAME_REGEX, /** * The password to use when logging in. Optional. */ IDX_PASSWORD, /** * The regular expression to use when searching for the password prompt. * Optional. */ IDX_PASSWORD_REGEX, /** * The name of the font to use within the terminal. */ IDX_FONT_NAME, /** * The size of the font to use within the terminal, in points. */ IDX_FONT_SIZE, /** * The color scheme to use, as a series of semicolon-separated color-value * pairs: "background: ", "foreground: ", or * "color: ", where is a number from 0 to 255, and is * "color" or an X11 color code (e.g. "aqua" or "rgb:12/34/56"). * The color scheme can also be one of the special values: "black-white", * "white-black", "gray-black", or "green-black". */ IDX_COLOR_SCHEME, /** * The full absolute path to the directory in which typescripts should be * written. */ IDX_TYPESCRIPT_PATH, /** * The name that should be given to typescripts which are written in the * given path. Each typescript will consist of two files: "NAME" and * "NAME.timing". */ IDX_TYPESCRIPT_NAME, /** * Whether the specified typescript path should automatically be created * if it does not yet exist. */ IDX_CREATE_TYPESCRIPT_PATH, /** * The full absolute path to the directory in which screen recordings * should be written. */ IDX_RECORDING_PATH, /** * The name that should be given to screen recordings which are written in * the given path. */ IDX_RECORDING_NAME, /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output * is included by default, as it is necessary for any recording which must * later be viewable as video. */ IDX_RECORDING_EXCLUDE_OUTPUT, /** * Whether changes to mouse state, such as position and buttons pressed or * released, should NOT be included in the session recording. Mouse state * is included by default, as it is necessary for the mouse cursor to be * rendered in any resulting video. */ IDX_RECORDING_EXCLUDE_MOUSE, /** * Whether keys pressed and released should be included in the session * recording. Key events are NOT included by default within the recording, * as doing so has privacy and security implications. Including key events * may be necessary in certain auditing contexts, but should only be done * with caution. Key events can easily contain sensitive information, such * as passwords, credit card numbers, etc. */ IDX_RECORDING_INCLUDE_KEYS, /** * Whether the specified screen recording path should automatically be * created if it does not yet exist. */ IDX_CREATE_RECORDING_PATH, /** * "true" if this connection should be read-only (user input should be * dropped), "false" or blank otherwise. */ IDX_READ_ONLY, /** * ASCII code, as an integer to use for the backspace key, or 127 * if not specified. */ IDX_BACKSPACE, /** * The terminal emulator type that is passed to the remote system (e.g. * "xterm" or "xterm-256color"). "linux" is used if unspecified. */ IDX_TERMINAL_TYPE, /** * The maximum size of the scrollback buffer in rows. */ IDX_SCROLLBACK, /** * The regular expression to use when searching for whether login was * successful. This parameter is optional. If given, the * "login-failure-regex" parameter must also be specified, and the first * frame of the Guacamole connection will be withheld until login * success/failure has been determined. */ IDX_LOGIN_SUCCESS_REGEX, /** * The regular expression to use when searching for whether login was * unsuccessful. This parameter is optional. If given, the * "login-success-regex" parameter must also be specified, and the first * frame of the Guacamole connection will be withheld until login * success/failure has been determined. */ IDX_LOGIN_FAILURE_REGEX, /** * Whether outbound clipboard access should be blocked. If set to "true", * it will not be possible to copy data from the terminal to the client * using the clipboard. By default, clipboard access is not blocked. */ IDX_DISABLE_COPY, /** * Whether inbound clipboard access should be blocked. If set to "true", it * will not be possible to paste data from the client to the terminal using * the clipboard. By default, clipboard access is not blocked. */ IDX_DISABLE_PASTE, /** * Whether to send the magic Wake-on-LAN (WoL) packet. If set to "true" * the WoL packet will be sent prior to attempting to connect to the remote * host. By default the WoL packet will not be sent. */ IDX_WOL_SEND_PACKET, /** * The MAC address to put in the magic WoL packet to wake the remote host. * There is no default value, and if WoL is enabled but the MAC address * is not provided, a warning will be logged and no packet will be sent. */ IDX_WOL_MAC_ADDR, /** * The broadcast address to which to send the magic WoL packet. */ IDX_WOL_BROADCAST_ADDR, /** * The amount of time, in seconds, to wait after the magic WoL packet is * sent before continuing the connection attempt. The default is not to * wait at all (0 seconds). */ IDX_WOL_WAIT_TIME, TELNET_ARGS_COUNT }; /** * Compiles the given regular expression, returning NULL if compilation fails * or of the given regular expression is NULL. The returned regex_t must be * freed with regfree() AND free(), or with guac_telnet_regex_free(). * * @param user * The user who provided the setting associated with the given regex * pattern. Error messages will be logged on behalf of this user. * * @param pattern * The regular expression pattern to compile. * * @return * The compiled regular expression, or NULL if compilation fails or NULL * was originally provided for the pattern. */ static regex_t* guac_telnet_compile_regex(guac_user* user, char* pattern) { /* Nothing to compile if no pattern provided */ if (pattern == NULL) return NULL; int compile_result; regex_t* regex = malloc(sizeof(regex_t)); /* Compile regular expression */ compile_result = regcomp(regex, pattern, REG_EXTENDED | REG_NOSUB | REG_ICASE | REG_NEWLINE); /* Notify of failure to parse/compile */ if (compile_result != 0) { guac_user_log(user, GUAC_LOG_ERROR, "Regular expression '%s' " "could not be compiled.", pattern); free(regex); return NULL; } return regex; } void guac_telnet_regex_free(regex_t** regex) { if (*regex != NULL) { regfree(*regex); free(*regex); *regex = NULL; } } guac_telnet_settings* guac_telnet_parse_args(guac_user* user, int argc, const char** argv) { /* Validate arg count */ if (argc != TELNET_ARGS_COUNT) { guac_user_log(user, GUAC_LOG_WARNING, "Incorrect number of connection " "parameters provided: expected %i, got %i.", TELNET_ARGS_COUNT, argc); return NULL; } guac_telnet_settings* settings = calloc(1, sizeof(guac_telnet_settings)); /* Read parameters */ settings->hostname = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_HOSTNAME, ""); /* Read username */ settings->username = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_USERNAME, NULL); /* Read username regex only if username is specified */ if (settings->username != NULL) { settings->username_regex = guac_telnet_compile_regex(user, guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_USERNAME_REGEX, GUAC_TELNET_DEFAULT_USERNAME_REGEX)); } /* Read password */ settings->password = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_PASSWORD, NULL); /* Read password regex only if password is specified */ if (settings->password != NULL) { settings->password_regex = guac_telnet_compile_regex(user, guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_PASSWORD_REGEX, GUAC_TELNET_DEFAULT_PASSWORD_REGEX)); } /* Read optional login success detection regex */ settings->login_success_regex = guac_telnet_compile_regex(user, guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_LOGIN_SUCCESS_REGEX, NULL)); /* Read optional login failure detection regex */ settings->login_failure_regex = guac_telnet_compile_regex(user, guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_LOGIN_FAILURE_REGEX, NULL)); /* Both login success and login failure regexes must be provided if either * is present at all */ if (settings->login_success_regex != NULL && settings->login_failure_regex == NULL) { guac_telnet_regex_free(&settings->login_success_regex); guac_user_log(user, GUAC_LOG_WARNING, "Ignoring provided value for " "\"%s\" as \"%s\" must also be provided.", GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_SUCCESS_REGEX], GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_FAILURE_REGEX]); } else if (settings->login_failure_regex != NULL && settings->login_success_regex == NULL) { guac_telnet_regex_free(&settings->login_failure_regex); guac_user_log(user, GUAC_LOG_WARNING, "Ignoring provided value for " "\"%s\" as \"%s\" must also be provided.", GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_FAILURE_REGEX], GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_SUCCESS_REGEX]); } /* Read-only mode */ settings->read_only = guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_READ_ONLY, false); /* Read maximum scrollback size */ settings->max_scrollback = guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_SCROLLBACK, GUAC_TELNET_DEFAULT_MAX_SCROLLBACK); /* Read font name */ settings->font_name = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_FONT_NAME, GUAC_TELNET_DEFAULT_FONT_NAME); /* Read font size */ settings->font_size = guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_FONT_SIZE, GUAC_TELNET_DEFAULT_FONT_SIZE); /* Copy requested color scheme */ settings->color_scheme = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_COLOR_SCHEME, ""); /* Pull width/height/resolution directly from user */ settings->width = user->info.optimal_width; settings->height = user->info.optimal_height; settings->resolution = user->info.optimal_resolution; /* Read port */ settings->port = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_PORT, GUAC_TELNET_DEFAULT_PORT); /* Read typescript path */ settings->typescript_path = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_TYPESCRIPT_PATH, NULL); /* Read typescript name */ settings->typescript_name = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_TYPESCRIPT_NAME, GUAC_TELNET_DEFAULT_TYPESCRIPT_NAME); /* Parse path creation flag */ settings->create_typescript_path = guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_CREATE_TYPESCRIPT_PATH, false); /* Read recording path */ settings->recording_path = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_RECORDING_PATH, NULL); /* Read recording name */ settings->recording_name = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_RECORDING_NAME, GUAC_TELNET_DEFAULT_RECORDING_NAME); /* Parse output exclusion flag */ settings->recording_exclude_output = guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_RECORDING_EXCLUDE_OUTPUT, false); /* Parse mouse exclusion flag */ settings->recording_exclude_mouse = guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_RECORDING_EXCLUDE_MOUSE, false); /* Parse key event inclusion flag */ settings->recording_include_keys = guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_RECORDING_INCLUDE_KEYS, false); /* Parse path creation flag */ settings->create_recording_path = guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_CREATE_RECORDING_PATH, false); /* Parse backspace key code */ settings->backspace = guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_BACKSPACE, 127); /* Read terminal emulator type. */ settings->terminal_type = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_TERMINAL_TYPE, "linux"); /* Parse clipboard copy disable flag */ settings->disable_copy = guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_DISABLE_COPY, false); /* Parse clipboard paste disable flag */ settings->disable_paste = guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_DISABLE_PASTE, false); /* Parse Wake-on-LAN (WoL) settings */ settings->wol_send_packet = guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_WOL_SEND_PACKET, false); if (settings->wol_send_packet) { /* If WoL has been enabled but no MAC provided, log warning and disable. */ if(strcmp(argv[IDX_WOL_MAC_ADDR], "") == 0) { guac_user_log(user, GUAC_LOG_WARNING, "Wake on LAN was requested, ", "but no MAC address was specified. WoL will not be sent."); settings->wol_send_packet = false; } /* Parse the WoL MAC address. */ settings->wol_mac_addr = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_WOL_MAC_ADDR, NULL); /* Parse the WoL broadcast address. */ settings->wol_broadcast_addr = guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_WOL_BROADCAST_ADDR, GUAC_WOL_LOCAL_IPV4_BROADCAST); /* Parse the WoL wait time. */ settings->wol_wait_time = guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_WOL_WAIT_TIME, GUAC_WOL_DEFAULT_BOOT_WAIT_TIME); } /* Parsing was successful */ return settings; } void guac_telnet_settings_free(guac_telnet_settings* settings) { /* Free network connection information */ free(settings->hostname); free(settings->port); /* Free credentials */ free(settings->username); free(settings->password); /* Free various regexes */ guac_telnet_regex_free(&settings->username_regex); guac_telnet_regex_free(&settings->password_regex); guac_telnet_regex_free(&settings->login_success_regex); guac_telnet_regex_free(&settings->login_failure_regex); /* Free display preferences */ free(settings->font_name); free(settings->color_scheme); /* Free typescript settings */ free(settings->typescript_name); free(settings->typescript_path); /* Free screen recording settings */ free(settings->recording_name); free(settings->recording_path); /* Free terminal emulator type. */ free(settings->terminal_type); /* Free overall structure */ free(settings); } guacamole-server-1.3.0/src/protocols/telnet/telnet.h0000644000175100001440000000514513702142276017455 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TELNET_H #define GUAC_TELNET_H #include "config.h" #include "common/clipboard.h" #include "common/recording.h" #include "settings.h" #include "terminal/terminal.h" #include #include /** * Telnet-specific client data. */ typedef struct guac_telnet_client { /** * Telnet connection settings. */ guac_telnet_settings* settings; /** * The telnet client thread. */ pthread_t client_thread; /** * The file descriptor of the socket connected to the telnet server, * or -1 if no connection has been established. */ int socket_fd; /** * Telnet connection, used by the telnet client thread. */ telnet_t* telnet; /** * Whether window size should be sent when the window is resized. */ int naws_enabled; /** * Whether all user input should be automatically echoed to the * terminal. */ int echo_enabled; /** * The current clipboard contents. */ guac_common_clipboard* clipboard; /** * The terminal which will render all output from the telnet client. */ guac_terminal* term; /** * The in-progress session recording, or NULL if no recording is in * progress. */ guac_common_recording* recording; } guac_telnet_client; /** * Main telnet client thread, handling transfer of telnet output to STDOUT. */ void* guac_telnet_client_thread(void* data); /** * Send a telnet NAWS message indicating the given terminal window dimensions * in characters. */ void guac_telnet_send_naws(telnet_t* telnet, uint16_t width, uint16_t height); /** * Sends the given username by setting the remote USER environment variable * using the telnet NEW-ENVIRON option. */ void guac_telnet_send_user(telnet_t* telnet, const char* username); #endif guacamole-server-1.3.0/src/protocols/telnet/client.h0000644000175100001440000000244413702142276017437 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TELNET__CLIENT_H #define GUAC_TELNET__CLIENT_H #include "config.h" #include "terminal/terminal.h" #include #include #include #include /** * The maximum number of bytes to allow within the clipboard. */ #define GUAC_TELNET_CLIPBOARD_MAX_LENGTH 262144 /** * Free handler. Required by libguac and called when the guac_client is * disconnected and must be cleaned up. */ guac_client_free_handler guac_telnet_client_free_handler; #endif guacamole-server-1.3.0/src/protocols/telnet/client.c0000644000175100001440000000662313770536337017447 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "client.h" #include "common/recording.h" #include "settings.h" #include "telnet.h" #include "terminal/terminal.h" #include "user.h" #include #include #include #include #include #include #include int guac_client_init(guac_client* client) { /* Set client args */ client->args = GUAC_TELNET_CLIENT_ARGS; /* Allocate client instance data */ guac_telnet_client* telnet_client = calloc(1, sizeof(guac_telnet_client)); client->data = telnet_client; /* Init clipboard */ telnet_client->clipboard = guac_common_clipboard_alloc(GUAC_TELNET_CLIPBOARD_MAX_LENGTH); /* Init telnet client */ telnet_client->socket_fd = -1; telnet_client->naws_enabled = 0; telnet_client->echo_enabled = 1; /* Set handlers */ client->join_handler = guac_telnet_user_join_handler; client->free_handler = guac_telnet_client_free_handler; /* Register handlers for argument values that may be sent after the handshake */ guac_argv_register(GUAC_TELNET_ARGV_COLOR_SCHEME, guac_telnet_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO); guac_argv_register(GUAC_TELNET_ARGV_FONT_NAME, guac_telnet_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO); guac_argv_register(GUAC_TELNET_ARGV_FONT_SIZE, guac_telnet_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO); /* Set locale and warn if not UTF-8 */ setlocale(LC_CTYPE, ""); if (strcmp(nl_langinfo(CODESET), "UTF-8") != 0) { guac_client_log(client, GUAC_LOG_INFO, "Current locale does not use UTF-8. Some characters may " "not render correctly."); } /* Success */ return 0; } int guac_telnet_client_free_handler(guac_client* client) { guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; /* Close telnet connection */ if (telnet_client->socket_fd != -1) close(telnet_client->socket_fd); /* Clean up recording, if in progress */ if (telnet_client->recording != NULL) guac_common_recording_free(telnet_client->recording); /* Kill terminal */ guac_terminal_free(telnet_client->term); /* Wait for and free telnet session, if connected */ if (telnet_client->telnet != NULL) { pthread_join(telnet_client->client_thread, NULL); telnet_free(telnet_client->telnet); } /* Free settings */ if (telnet_client->settings != NULL) guac_telnet_settings_free(telnet_client->settings); guac_common_clipboard_free(telnet_client->clipboard); free(telnet_client); return 0; } guacamole-server-1.3.0/src/protocols/telnet/pipe.h0000644000175100001440000000254413702142276017117 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TELNET_PIPE_H #define GUAC_TELNET_PIPE_H #include "config.h" #include /** * The name reserved for the inbound pipe stream which forces the terminal * emulator's STDIN to be received from the pipe. */ #define GUAC_TELNET_STDIN_PIPE_NAME "STDIN" /** * Handles an incoming stream from a Guacamole "pipe" instruction. If the pipe * is named "STDIN", the the contents of the pipe stream are redirected to * STDIN of the terminal emulator for as long as the pipe is open. */ guac_user_pipe_handler guac_telnet_pipe_handler; #endif guacamole-server-1.3.0/src/protocols/telnet/Makefile.am0000644000175100001440000000414213702142276020041 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac-client-telnet.la libguac_client_telnet_la_SOURCES = \ argv.c \ client.c \ clipboard.c \ input.c \ pipe.c \ settings.c \ telnet.c \ user.c noinst_HEADERS = \ argv.h \ client.h \ clipboard.h \ input.h \ pipe.h \ settings.h \ telnet.h \ user.h libguac_client_telnet_la_CFLAGS = \ -Werror -Wall -Iinclude \ @LIBGUAC_INCLUDE@ \ @TERMINAL_INCLUDE@ libguac_client_telnet_la_LIBADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ \ @TERMINAL_LTLIB@ libguac_client_telnet_la_LDFLAGS = \ -version-info 0:0:0 \ @PTHREAD_LIBS@ \ @TELNET_LIBS@ guacamole-server-1.3.0/src/protocols/telnet/telnet.c0000644000175100001440000005162013764613616017460 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "common/recording.h" #include "telnet.h" #include "terminal/terminal.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** * Support levels for various telnet options, required for connection * negotiation by telnet_init(), part of libtelnet. */ static const telnet_telopt_t __telnet_options[] = { { TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DO }, { TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DONT }, { TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO }, { TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DO }, { TELNET_TELOPT_NAWS, TELNET_WILL, TELNET_DONT }, { TELNET_TELOPT_NEW_ENVIRON, TELNET_WILL, TELNET_DONT }, { -1, 0, 0 } }; /** * Write the entire buffer given to the specified file descriptor, retrying * the write automatically if necessary. This function will return a value * not equal to the buffer's size iff an error occurs which prevents all * future writes. * * @param fd The file descriptor to write to. * @param buffer The buffer to write. * @param size The number of bytes from the buffer to write. */ static int __guac_telnet_write_all(int fd, const char* buffer, int size) { int remaining = size; while (remaining > 0) { /* Attempt to write data */ int ret_val = write(fd, buffer, remaining); if (ret_val <= 0) return -1; /* If successful, contine with what data remains (if any) */ remaining -= ret_val; buffer += ret_val; } return size; } /** * Matches the given line against the given regex, returning true and sending * the given value if a match is found. An enter keypress is automatically * sent after the value is sent. * * @param client * The guac_client associated with the telnet session. * * @param regex * The regex to search for within the given line buffer. * * @param value * The string value to send through STDIN of the telnet session if a * match is found, or NULL if no value should be sent. * * @param line_buffer * The line of character data to test. * * @return * true if a match is found, false otherwise. */ static bool guac_telnet_regex_exec(guac_client* client, regex_t* regex, const char* value, const char* line_buffer) { guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; /* Send value upon match */ if (regexec(regex, line_buffer, 0, NULL, 0) == 0) { /* Send value */ if (value != NULL) { guac_terminal_send_string(telnet_client->term, value); guac_terminal_send_string(telnet_client->term, "\x0D"); } /* Stop searching for prompt */ return true; } return false; } /** * Matches the given line against the various stored regexes, automatically * sending the configured username, password, or reporting login * success/failure depending on context. If no search is in progress, either * because no regexes have been defined or because all applicable searches have * completed, this function has no effect. * * @param client * The guac_client associated with the telnet session. * * @param line_buffer * The line of character data to test. */ static void guac_telnet_search_line(guac_client* client, const char* line_buffer) { guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_telnet_settings* settings = telnet_client->settings; /* Continue search for username prompt */ if (settings->username_regex != NULL) { if (guac_telnet_regex_exec(client, settings->username_regex, settings->username, line_buffer)) { guac_client_log(client, GUAC_LOG_DEBUG, "Username sent"); guac_telnet_regex_free(&settings->username_regex); } } /* Continue search for password prompt */ if (settings->password_regex != NULL) { if (guac_telnet_regex_exec(client, settings->password_regex, settings->password, line_buffer)) { guac_client_log(client, GUAC_LOG_DEBUG, "Password sent"); /* Do not continue searching for username/password once password is sent */ guac_telnet_regex_free(&settings->username_regex); guac_telnet_regex_free(&settings->password_regex); } } /* Continue search for login success */ if (settings->login_success_regex != NULL) { if (guac_telnet_regex_exec(client, settings->login_success_regex, NULL, line_buffer)) { /* Allow terminal to render now that login has been deemed successful */ guac_client_log(client, GUAC_LOG_DEBUG, "Login successful"); guac_terminal_start(telnet_client->term); /* Stop all searches */ guac_telnet_regex_free(&settings->username_regex); guac_telnet_regex_free(&settings->password_regex); guac_telnet_regex_free(&settings->login_success_regex); guac_telnet_regex_free(&settings->login_failure_regex); } } /* Continue search for login failure */ if (settings->login_failure_regex != NULL) { if (guac_telnet_regex_exec(client, settings->login_failure_regex, NULL, line_buffer)) { /* Advise that login has failed and connection should be closed */ guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED, "Login failed"); /* Stop all searches */ guac_telnet_regex_free(&settings->username_regex); guac_telnet_regex_free(&settings->password_regex); guac_telnet_regex_free(&settings->login_success_regex); guac_telnet_regex_free(&settings->login_failure_regex); } } } /** * Searches for a line matching the various stored regexes, automatically * sending the configured username, password, or reporting login * success/failure depending on context. If no search is in progress, either * because no regexes have been defined or because all applicable searches * have completed, this function has no effect. * * @param client * The guac_client associated with the telnet session. * * @param buffer * The buffer of received data to search through. * * @param size * The size of the given buffer, in bytes. */ static void guac_telnet_search(guac_client* client, const char* buffer, int size) { static char line_buffer[1024] = {0}; static int length = 0; /* Append all characters in buffer to current line */ const char* current = buffer; for (int i = 0; i < size; i++) { char c = *(current++); /* Attempt pattern match and clear buffer upon reading newline */ if (c == '\n') { if (length > 0) { line_buffer[length] = '\0'; guac_telnet_search_line(client, line_buffer); length = 0; } } /* Append all non-newline characters to line buffer as long as space * remains */ else if (length < sizeof(line_buffer) - 1) line_buffer[length++] = c; } /* Attempt pattern match if an unfinished line remains (may be a prompt) */ if (length > 0) { line_buffer[length] = '\0'; guac_telnet_search_line(client, line_buffer); } } /** * Event handler, as defined by libtelnet. This function is passed to * telnet_init() and will be called for every event fired by libtelnet, * including feature enable/disable and receipt/transmission of data. */ static void __guac_telnet_event_handler(telnet_t* telnet, telnet_event_t* event, void* data) { guac_client* client = (guac_client*) data; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_telnet_settings* settings = telnet_client->settings; switch (event->type) { /* Terminal output received */ case TELNET_EV_DATA: guac_terminal_write(telnet_client->term, event->data.buffer, event->data.size); guac_telnet_search(client, event->data.buffer, event->data.size); break; /* Data destined for remote end */ case TELNET_EV_SEND: if (__guac_telnet_write_all(telnet_client->socket_fd, event->data.buffer, event->data.size) != event->data.size) guac_client_stop(client); break; /* Remote feature enabled */ case TELNET_EV_WILL: if (event->neg.telopt == TELNET_TELOPT_ECHO) telnet_client->echo_enabled = 0; /* Disable local echo, as remote will echo */ break; /* Remote feature disabled */ case TELNET_EV_WONT: if (event->neg.telopt == TELNET_TELOPT_ECHO) telnet_client->echo_enabled = 1; /* Enable local echo, as remote won't echo */ break; /* Local feature enable */ case TELNET_EV_DO: if (event->neg.telopt == TELNET_TELOPT_NAWS) { telnet_client->naws_enabled = 1; guac_telnet_send_naws(telnet, telnet_client->term->term_width, telnet_client->term->term_height); } break; /* Terminal type request */ case TELNET_EV_TTYPE: if (event->ttype.cmd == TELNET_TTYPE_SEND) telnet_ttype_is(telnet_client->telnet, settings->terminal_type); break; /* Environment request */ case TELNET_EV_ENVIRON: /* Only send USER if entire environment was requested */ if (event->environ.size == 0) guac_telnet_send_user(telnet, settings->username); break; /* Connection warnings */ case TELNET_EV_WARNING: guac_client_log(client, GUAC_LOG_WARNING, "%s", event->error.msg); break; /* Connection errors */ case TELNET_EV_ERROR: guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Telnet connection closing with error: %s", event->error.msg); break; /* Ignore other events */ default: break; } } /** * Input thread, started by the main telnet client thread. This thread * continuously reads from the terminal's STDIN and transfers all read * data to the telnet connection. * * @param data The current guac_client instance. * @return Always NULL. */ static void* __guac_telnet_input_thread(void* data) { guac_client* client = (guac_client*) data; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; char buffer[8192]; int bytes_read; /* Write all data read */ while ((bytes_read = guac_terminal_read_stdin(telnet_client->term, buffer, sizeof(buffer))) > 0) { telnet_send(telnet_client->telnet, buffer, bytes_read); if (telnet_client->echo_enabled) guac_terminal_write(telnet_client->term, buffer, bytes_read); } return NULL; } /** * Connects to the telnet server specified within the data associated * with the given guac_client, which will have been populated by * guac_client_init. * * @return The connected telnet instance, if successful, or NULL if the * connection fails for any reason. */ static telnet_t* __guac_telnet_create_session(guac_client* client) { int retval; int fd; struct addrinfo* addresses; struct addrinfo* current_address; char connected_address[1024]; char connected_port[64]; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_telnet_settings* settings = telnet_client->settings; struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP }; /* Get socket */ fd = socket(AF_INET, SOCK_STREAM, 0); /* Get addresses connection */ if ((retval = getaddrinfo(settings->hostname, settings->port, &hints, &addresses))) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error parsing given address or port: %s", gai_strerror(retval)); return NULL; } /* Attempt connection to each address until success */ current_address = addresses; while (current_address != NULL) { int retval; /* Resolve hostname */ if ((retval = getnameinfo(current_address->ai_addr, current_address->ai_addrlen, connected_address, sizeof(connected_address), connected_port, sizeof(connected_port), NI_NUMERICHOST | NI_NUMERICSERV))) guac_client_log(client, GUAC_LOG_DEBUG, "Unable to resolve host: %s", gai_strerror(retval)); /* Connect */ if (connect(fd, current_address->ai_addr, current_address->ai_addrlen) == 0) { guac_client_log(client, GUAC_LOG_DEBUG, "Successfully connected to " "host %s, port %s", connected_address, connected_port); /* Done if successful connect */ break; } /* Otherwise log information regarding bind failure */ else guac_client_log(client, GUAC_LOG_DEBUG, "Unable to connect to " "host %s, port %s: %s", connected_address, connected_port, strerror(errno)); current_address = current_address->ai_next; } /* If unable to connect to anything, fail */ if (current_address == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND, "Unable to connect to any addresses."); return NULL; } /* Free addrinfo */ freeaddrinfo(addresses); /* Open telnet session */ telnet_t* telnet = telnet_init(__telnet_options, __guac_telnet_event_handler, 0, client); if (telnet == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Telnet client allocation failed."); return NULL; } /* Save file descriptor */ telnet_client->socket_fd = fd; return telnet; } /** * Sends a 16-bit value over the given telnet connection with the byte order * required by the telnet protocol. * * @param telnet The telnet connection to use. * @param value The value to send. */ static void __guac_telnet_send_uint16(telnet_t* telnet, uint16_t value) { unsigned char buffer[2]; buffer[0] = (value >> 8) & 0xFF; buffer[1] = value & 0xFF; telnet_send(telnet, (char*) buffer, 2); } /** * Sends an 8-bit value over the given telnet connection. * * @param telnet The telnet connection to use. * @param value The value to send. */ static void __guac_telnet_send_uint8(telnet_t* telnet, uint8_t value) { telnet_send(telnet, (char*) (&value), 1); } void guac_telnet_send_naws(telnet_t* telnet, uint16_t width, uint16_t height) { telnet_begin_sb(telnet, TELNET_TELOPT_NAWS); __guac_telnet_send_uint16(telnet, width); __guac_telnet_send_uint16(telnet, height); telnet_finish_sb(telnet); } void guac_telnet_send_user(telnet_t* telnet, const char* username) { /* IAC SB NEW-ENVIRON IS */ telnet_begin_sb(telnet, TELNET_TELOPT_NEW_ENVIRON); __guac_telnet_send_uint8(telnet, TELNET_ENVIRON_IS); /* Only send username if defined */ if (username != NULL) { /* VAR "USER" */ __guac_telnet_send_uint8(telnet, TELNET_ENVIRON_VAR); telnet_send(telnet, "USER", 4); /* VALUE username */ __guac_telnet_send_uint8(telnet, TELNET_ENVIRON_VALUE); telnet_send(telnet, username, strlen(username)); } /* IAC SE */ telnet_finish_sb(telnet); } /** * Waits for data on the given file descriptor for up to one second. The * return value is identical to that of select(): 0 on timeout, < 0 on * error, and > 0 on success. * * @param socket_fd The file descriptor to wait for. * @return A value greater than zero on success, zero on timeout, and * less than zero on error. */ static int __guac_telnet_wait(int socket_fd) { /* Build array of file descriptors */ struct pollfd fds[] = {{ .fd = socket_fd, .events = POLLIN, .revents = 0, }}; /* Wait for one second */ return poll(fds, 1, 1000); } void* guac_telnet_client_thread(void* data) { guac_client* client = (guac_client*) data; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_telnet_settings* settings = telnet_client->settings; pthread_t input_thread; char buffer[8192]; int wait_result; /* If Wake-on-LAN is enabled, attempt to wake. */ if (settings->wol_send_packet) { guac_client_log(client, GUAC_LOG_DEBUG, "Sending Wake-on-LAN packet, " "and pausing for %d seconds.", settings->wol_wait_time); /* Send the Wake-on-LAN request. */ if (guac_wol_wake(settings->wol_mac_addr, settings->wol_broadcast_addr)) return NULL; /* If wait time is specified, sleep for that amount of time. */ if (settings->wol_wait_time > 0) guac_timestamp_msleep(settings->wol_wait_time * 1000); } /* Set up screen recording, if requested */ if (settings->recording_path != NULL) { telnet_client->recording = guac_common_recording_create(client, settings->recording_path, settings->recording_name, settings->create_recording_path, !settings->recording_exclude_output, !settings->recording_exclude_mouse, settings->recording_include_keys); } /* Create terminal */ telnet_client->term = guac_terminal_create(client, telnet_client->clipboard, settings->disable_copy, settings->max_scrollback, settings->font_name, settings->font_size, settings->resolution, settings->width, settings->height, settings->color_scheme, settings->backspace); /* Fail if terminal init failed */ if (telnet_client->term == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Terminal initialization failed"); return NULL; } /* Send current values of exposed arguments to owner only */ guac_client_for_owner(client, guac_telnet_send_current_argv, telnet_client); /* Set up typescript, if requested */ if (settings->typescript_path != NULL) { guac_terminal_create_typescript(telnet_client->term, settings->typescript_path, settings->typescript_name, settings->create_typescript_path); } /* Open telnet session */ telnet_client->telnet = __guac_telnet_create_session(client); if (telnet_client->telnet == NULL) { /* Already aborted within __guac_telnet_create_session() */ return NULL; } /* Logged in */ guac_client_log(client, GUAC_LOG_INFO, "Telnet connection successful."); /* Allow terminal to render if login success/failure detection is not * enabled */ if (settings->login_success_regex == NULL && settings->login_failure_regex == NULL) guac_terminal_start(telnet_client->term); /* Start input thread */ if (pthread_create(&(input_thread), NULL, __guac_telnet_input_thread, (void*) client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread"); return NULL; } /* While data available, write to terminal */ while ((wait_result = __guac_telnet_wait(telnet_client->socket_fd)) >= 0) { /* Resume waiting of no data available */ if (wait_result == 0) continue; int bytes_read = read(telnet_client->socket_fd, buffer, sizeof(buffer)); if (bytes_read <= 0) break; telnet_recv(telnet_client->telnet, buffer, bytes_read); } /* Kill client and Wait for input thread to die */ guac_client_stop(client); pthread_join(input_thread, NULL); guac_client_log(client, GUAC_LOG_INFO, "Telnet connection ended."); return NULL; } guacamole-server-1.3.0/src/protocols/kubernetes/0000755000175100001440000000000013772471157016752 500000000000000guacamole-server-1.3.0/src/protocols/kubernetes/clipboard.c0000644000175100001440000000404413702142276020765 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "clipboard.h" #include "common/clipboard.h" #include "kubernetes.h" #include #include #include int guac_kubernetes_clipboard_handler(guac_user* user, guac_stream* stream, char* mimetype) { guac_client* client = user->client; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; /* Clear clipboard and prepare for new data */ guac_common_clipboard_reset(kubernetes_client->clipboard, mimetype); /* Set handlers for clipboard stream */ stream->blob_handler = guac_kubernetes_clipboard_blob_handler; stream->end_handler = guac_kubernetes_clipboard_end_handler; return 0; } int guac_kubernetes_clipboard_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { guac_client* client = user->client; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; /* Append new data */ guac_common_clipboard_append(kubernetes_client->clipboard, data, length); return 0; } int guac_kubernetes_clipboard_end_handler(guac_user* user, guac_stream* stream) { /* Nothing to do - clipboard is implemented within client */ return 0; } guacamole-server-1.3.0/src/protocols/kubernetes/argv.c0000644000175100001440000000550313770536337020000 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "kubernetes.h" #include "terminal/terminal.h" #include #include #include #include #include int guac_kubernetes_argv_callback(guac_user* user, const char* mimetype, const char* name, const char* value, void* data) { guac_client* client = user->client; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; guac_terminal* terminal = kubernetes_client->term; /* Update color scheme */ if (strcmp(name, GUAC_KUBERNETES_ARGV_COLOR_SCHEME) == 0) guac_terminal_apply_color_scheme(terminal, value); /* Update font name */ else if (strcmp(name, GUAC_KUBERNETES_ARGV_FONT_NAME) == 0) guac_terminal_apply_font(terminal, value, -1, 0); /* Update only if font size is sane */ else if (strcmp(name, GUAC_KUBERNETES_ARGV_FONT_SIZE) == 0) { int size = atoi(value); if (size > 0) guac_terminal_apply_font(terminal, NULL, size, kubernetes_client->settings->resolution); } /* Update Kubernetes terminal size */ guac_kubernetes_resize(client, terminal->term_height, terminal->term_width); return 0; } void* guac_kubernetes_send_current_argv(guac_user* user, void* data) { guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) data; guac_terminal* terminal = kubernetes_client->term; /* Send current color scheme */ guac_user_stream_argv(user, user->socket, "text/plain", GUAC_KUBERNETES_ARGV_COLOR_SCHEME, terminal->color_scheme); /* Send current font name */ guac_user_stream_argv(user, user->socket, "text/plain", GUAC_KUBERNETES_ARGV_FONT_NAME, terminal->font_name); /* Send current font size */ char font_size[64]; sprintf(font_size, "%i", terminal->font_size); guac_user_stream_argv(user, user->socket, "text/plain", GUAC_KUBERNETES_ARGV_FONT_SIZE, font_size); return NULL; } guacamole-server-1.3.0/src/protocols/kubernetes/input.h0000644000175100001440000000261113702142276020170 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_KUBERNETES_INPUT_H #define GUAC_KUBERNETES_INPUT_H #include /** * Handler for key events. Required by libguac and called whenever key events * are received. */ guac_user_key_handler guac_kubernetes_user_key_handler; /** * Handler for mouse events. Required by libguac and called whenever mouse * events are received. */ guac_user_mouse_handler guac_kubernetes_user_mouse_handler; /** * Handler for size events. Required by libguac and called whenever the remote * display (window) is resized. */ guac_user_size_handler guac_kubernetes_user_size_handler; #endif guacamole-server-1.3.0/src/protocols/kubernetes/url.h0000644000175100001440000000572113702142276017640 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_KUBERNETES_URL_H #define GUAC_KUBERNETES_URL_H /** * The maximum number of characters allowed in the full path for any Kubernetes * endpoint. */ #define GUAC_KUBERNETES_MAX_ENDPOINT_LENGTH 1024 /** * Escapes the given string such that it can be included safely within a URL. * This function duplicates the behavior of JavaScript's encodeURIComponent(), * escaping all but the following characters: A-Z a-z 0-9 - _ . ! ~ * ' ( ) * * @param output * The buffer which should receive the escaped string. This buffer may be * touched even if escaping is unsuccessful. * * @param length * The number of bytes available in the given output buffer. * * @param str * The string to escape. * * @return * Zero if the string was successfully escaped and written into the * provided output buffer without being truncated, including null * terminator, non-zero otherwise. */ int guac_kubernetes_escape_url_component(char* output, int length, const char* str); /** * Generates the full path to the Kubernetes API endpoint which handles * attaching to running containers within specific pods. Values within the path * will be URL-escaped as necessary. * * @param buffer * The buffer which should receive the endpoint path. This buffer may be * touched even if the endpoint path could not be generated. * * @param length * The number of bytes available in the given buffer. * * @param kubernetes_namespace * The name of the Kubernetes namespace of the pod containing the container * being attached to. * * @param kubernetes_pod * The name of the Kubernetes pod containing with the container being * attached to. * * @param kubernetes_container * The name of the container to attach to, or NULL to arbitrarily attach * to the first container in the pod. * * @return * Zero if the endpoint path was successfully written to the provided * buffer, non-zero if insufficient space exists within the buffer. */ int guac_kubernetes_endpoint_attach(char* buffer, int length, const char* kubernetes_namespace, const char* kubernetes_pod, const char* kubernetes_container); #endif guacamole-server-1.3.0/src/protocols/kubernetes/pipe.c0000644000175100001440000000333513702142276017765 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "kubernetes.h" #include "terminal/terminal.h" #include "pipe.h" #include #include #include #include #include #include int guac_kubernetes_pipe_handler(guac_user* user, guac_stream* stream, char* mimetype, char* name) { guac_client* client = user->client; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; /* Redirect STDIN if pipe has required name */ if (strcmp(name, GUAC_KUBERNETES_STDIN_PIPE_NAME) == 0) { guac_terminal_send_stream(kubernetes_client->term, user, stream); return 0; } /* No other inbound pipe streams are supported */ guac_protocol_send_ack(user->socket, stream, "No such input stream.", GUAC_PROTOCOL_STATUS_RESOURCE_NOT_FOUND); guac_socket_flush(user->socket); return 0; } guacamole-server-1.3.0/src/protocols/kubernetes/user.h0000644000175100001440000000212113702142276020003 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_KUBERNETES_USER_H #define GUAC_KUBERNETES_USER_H #include /** * Handler for joining users. */ guac_user_join_handler guac_kubernetes_user_join_handler; /** * Handler for leaving users. */ guac_user_leave_handler guac_kubernetes_user_leave_handler; #endif guacamole-server-1.3.0/src/protocols/kubernetes/kubernetes.c0000644000175100001440000003336013764613616021211 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "argv.h" #include "client.h" #include "common/recording.h" #include "io.h" #include "kubernetes.h" #include "ssl.h" #include "terminal/terminal.h" #include "url.h" #include #include #include #include #include #include /** * Callback invoked by libwebsockets for events related to a WebSocket being * used for communicating with an attached Kubernetes pod. * * @param wsi * The libwebsockets handle for the WebSocket connection. * * @param reason * The reason (event) that this callback was invoked. * * @param user * Arbitrary data assocated with the WebSocket session. In some cases, * this is actually event-specific data (such as the * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERT event). * * @param in * A pointer to arbitrary, reason-specific data. * * @param length * An arbitrary, reason-specific length value. * * @return * An undocumented integer value related the success of handling the * event, or -1 if the WebSocket connection should be closed. */ static int guac_kubernetes_lws_callback(struct lws* wsi, enum lws_callback_reasons reason, void* user, void* in, size_t length) { guac_client* client = guac_kubernetes_lws_current_client; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; /* Do not handle any further events if connection is closing */ if (client->state != GUAC_CLIENT_RUNNING) { #ifdef HAVE_LWS_CALLBACK_HTTP_DUMMY return lws_callback_http_dummy(wsi, reason, user, in, length); #else return 0; #endif } switch (reason) { /* Complete initialization of SSL */ case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: guac_kubernetes_init_ssl(client, (SSL_CTX*) user); break; /* Failed to connect */ case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND, "Error connecting to Kubernetes server: %s", in != NULL ? (char*) in : "(no error description " "available)"); break; /* Connected / logged in */ case LWS_CALLBACK_CLIENT_ESTABLISHED: guac_client_log(client, GUAC_LOG_INFO, "Kubernetes connection successful."); /* Allow terminal to render */ guac_terminal_start(kubernetes_client->term); /* Schedule check for pending messages in case messages were added * to the outbound message buffer prior to the connection being * fully established */ lws_callback_on_writable(wsi); break; /* Data received via WebSocket */ case LWS_CALLBACK_CLIENT_RECEIVE: guac_kubernetes_receive_data(client, (const char*) in, length); break; /* WebSocket is ready for writing */ case LWS_CALLBACK_CLIENT_WRITEABLE: /* Send any pending messages, requesting another callback if * yet more messages remain */ if (guac_kubernetes_write_pending_message(client)) lws_callback_on_writable(wsi); break; #ifdef HAVE_LWS_CALLBACK_CLIENT_CLOSED /* Connection closed (client-specific) */ case LWS_CALLBACK_CLIENT_CLOSED: #endif /* Connection closed */ case LWS_CALLBACK_WSI_DESTROY: case LWS_CALLBACK_CLOSED: guac_client_stop(client); guac_client_log(client, GUAC_LOG_DEBUG, "WebSocket connection to " "Kubernetes server closed."); break; /* No other event types are applicable */ default: break; } #ifdef HAVE_LWS_CALLBACK_HTTP_DUMMY return lws_callback_http_dummy(wsi, reason, user, in, length); #else return 0; #endif } /** * List of all WebSocket protocols which should be declared as supported by * libwebsockets during the initial WebSocket handshake, along with * corresponding event-handling callbacks. */ struct lws_protocols guac_kubernetes_lws_protocols[] = { { .name = GUAC_KUBERNETES_LWS_PROTOCOL, .callback = guac_kubernetes_lws_callback }, { 0 } }; /** * Input thread, started by the main Kubernetes client thread. This thread * continuously reads from the terminal's STDIN and transfers all read * data to the Kubernetes connection. * * @param data * The current guac_client instance. * * @return * Always NULL. */ static void* guac_kubernetes_input_thread(void* data) { guac_client* client = (guac_client*) data; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; char buffer[GUAC_KUBERNETES_MAX_MESSAGE_SIZE]; int bytes_read; /* Write all data read */ while ((bytes_read = guac_terminal_read_stdin(kubernetes_client->term, buffer, sizeof(buffer))) > 0) { /* Send received data to Kubernetes along STDIN channel */ guac_kubernetes_send_message(client, GUAC_KUBERNETES_CHANNEL_STDIN, buffer, bytes_read); } return NULL; } void* guac_kubernetes_client_thread(void* data) { guac_client* client = (guac_client*) data; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; guac_kubernetes_settings* settings = kubernetes_client->settings; pthread_t input_thread; char endpoint_path[GUAC_KUBERNETES_MAX_ENDPOINT_LENGTH]; /* Verify that the pod name was specified (it's always required) */ if (settings->kubernetes_pod == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "The name of the Kubernetes pod is a required parameter."); goto fail; } /* Generate endpoint for attachment URL */ if (guac_kubernetes_endpoint_attach(endpoint_path, sizeof(endpoint_path), settings->kubernetes_namespace, settings->kubernetes_pod, settings->kubernetes_container)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to generate path for Kubernetes API endpoint: " "Resulting path too long"); goto fail; } guac_client_log(client, GUAC_LOG_DEBUG, "The endpoint for attaching to " "the requested Kubernetes pod is \"%s\".", endpoint_path); /* Set up screen recording, if requested */ if (settings->recording_path != NULL) { kubernetes_client->recording = guac_common_recording_create(client, settings->recording_path, settings->recording_name, settings->create_recording_path, !settings->recording_exclude_output, !settings->recording_exclude_mouse, settings->recording_include_keys); } /* Create terminal */ kubernetes_client->term = guac_terminal_create(client, kubernetes_client->clipboard, settings->disable_copy, settings->max_scrollback, settings->font_name, settings->font_size, settings->resolution, settings->width, settings->height, settings->color_scheme, settings->backspace); /* Fail if terminal init failed */ if (kubernetes_client->term == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Terminal initialization failed"); goto fail; } /* Send current values of exposed arguments to owner only */ guac_client_for_owner(client, guac_kubernetes_send_current_argv, kubernetes_client); /* Set up typescript, if requested */ if (settings->typescript_path != NULL) { guac_terminal_create_typescript(kubernetes_client->term, settings->typescript_path, settings->typescript_name, settings->create_typescript_path); } /* Init libwebsockets context creation parameters */ struct lws_context_creation_info context_info = { .port = CONTEXT_PORT_NO_LISTEN, /* We are not a WebSocket server */ .uid = -1, .gid = -1, .protocols = guac_kubernetes_lws_protocols, .user = client }; /* Init WebSocket connection parameters which do not vary by Guacmaole * connection parameters or creation of future libwebsockets objects */ struct lws_client_connect_info connection_info = { .host = settings->hostname, .address = settings->hostname, .origin = settings->hostname, .port = settings->port, .protocol = GUAC_KUBERNETES_LWS_PROTOCOL, .userdata = client }; /* If requested, use an SSL/TLS connection for communication with * Kubernetes. Note that we disable hostname checks here because we * do our own validation - libwebsockets does not validate properly if * IP addresses are used. */ if (settings->use_ssl) { #ifdef HAVE_LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT context_info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; #endif #ifdef HAVE_LCCSCF_USE_SSL connection_info.ssl_connection = LCCSCF_USE_SSL | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK; #else connection_info.ssl_connection = 2; /* SSL + no hostname check */ #endif } /* Create libwebsockets context */ kubernetes_client->context = lws_create_context(&context_info); if (!kubernetes_client->context) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Initialization of libwebsockets failed"); goto fail; } /* Generate path dynamically */ connection_info.context = kubernetes_client->context; connection_info.path = endpoint_path; /* Open WebSocket connection to Kubernetes */ kubernetes_client->wsi = lws_client_connect_via_info(&connection_info); if (kubernetes_client->wsi == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Connection via libwebsockets failed"); goto fail; } /* Init outbound message buffer */ pthread_mutex_init(&(kubernetes_client->outbound_message_lock), NULL); /* Start input thread */ if (pthread_create(&(input_thread), NULL, guac_kubernetes_input_thread, (void*) client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread"); goto fail; } /* Force a redraw of the attached display (there will be no content * otherwise, given the stream nature of attaching to a running * container) */ guac_kubernetes_force_redraw(client); /* As long as client is connected, continue polling libwebsockets */ while (client->state == GUAC_CLIENT_RUNNING) { /* Cease polling libwebsockets if an error condition is signalled */ if (lws_service(kubernetes_client->context, GUAC_KUBERNETES_SERVICE_INTERVAL) < 0) break; } /* Kill client and Wait for input thread to die */ guac_terminal_stop(kubernetes_client->term); guac_client_stop(client); pthread_join(input_thread, NULL); fail: /* Kill and free terminal, if allocated */ if (kubernetes_client->term != NULL) guac_terminal_free(kubernetes_client->term); /* Clean up recording, if in progress */ if (kubernetes_client->recording != NULL) guac_common_recording_free(kubernetes_client->recording); /* Free WebSocket context if successfully allocated */ if (kubernetes_client->context != NULL) lws_context_destroy(kubernetes_client->context); guac_client_log(client, GUAC_LOG_INFO, "Kubernetes connection ended."); return NULL; } void guac_kubernetes_resize(guac_client* client, int rows, int columns) { char buffer[64]; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; /* Send request only if different from last request */ if (kubernetes_client->rows != rows || kubernetes_client->columns != columns) { kubernetes_client->rows = rows; kubernetes_client->columns = columns; /* Construct terminal resize message for Kubernetes */ int length = snprintf(buffer, sizeof(buffer), "{\"Width\":%i,\"Height\":%i}", columns, rows); /* Schedule message for sending */ guac_kubernetes_send_message(client, GUAC_KUBERNETES_CHANNEL_RESIZE, buffer, length); } } void guac_kubernetes_force_redraw(guac_client* client) { guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; /* Get current terminal dimensions */ guac_terminal* term = kubernetes_client->term; int rows = term->term_height; int columns = term->term_width; /* Force a redraw by increasing the terminal size by one character in * each dimension and then resizing it back to normal (the same technique * used by kubectl */ guac_kubernetes_resize(client, rows + 1, columns + 1); guac_kubernetes_resize(client, rows, columns); } guacamole-server-1.3.0/src/protocols/kubernetes/kubernetes.h0000644000175100001440000001113413702142276021200 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_KUBERNETES_H #define GUAC_KUBERNETES_H #include "common/clipboard.h" #include "common/recording.h" #include "io.h" #include "settings.h" #include "terminal/terminal.h" #include #include #include /** * The name of the WebSocket protocol specific to Kubernetes which should be * sent to the Kubernetes server when attaching to a pod. */ #define GUAC_KUBERNETES_LWS_PROTOCOL "v4.channel.k8s.io" /** * The maximum number of messages to allow within the outbound message buffer. * If messages are sent despite the buffer being full, those messages will be * dropped. */ #define GUAC_KUBERNETES_MAX_OUTBOUND_MESSAGES 8 /** * The maximum number of milliseconds to wait for a libwebsockets event to * occur before entering another iteration of the libwebsockets event loop. */ #define GUAC_KUBERNETES_SERVICE_INTERVAL 1000 /** * Kubernetes-specific client data. */ typedef struct guac_kubernetes_client { /** * Kubernetes connection settings. */ guac_kubernetes_settings* settings; /** * The libwebsockets context associated with the connected WebSocket. */ struct lws_context* context; /** * The connected WebSocket. */ struct lws* wsi; /** * Outbound message ring buffer for outbound WebSocket messages. As * libwebsockets uses an event loop for all operations, outbound messages * may be sent only in context of a particular event received via a * callback. Until that event is received, pending data must accumulate in * a buffer. */ guac_kubernetes_message outbound_messages[GUAC_KUBERNETES_MAX_OUTBOUND_MESSAGES]; /** * The number of messages currently waiting in the outbound message * buffer. */ int outbound_messages_waiting; /** * The index of the oldest entry in the outbound message buffer. Newer * messages follow this entry. */ int outbound_messages_top; /** * Lock which is acquired when the outbound message buffer is being read * or manipulated. */ pthread_mutex_t outbound_message_lock; /** * The Kubernetes client thread. */ pthread_t client_thread; /** * The current clipboard contents. */ guac_common_clipboard* clipboard; /** * The terminal which will render all output from the Kubernetes pod. */ guac_terminal* term; /** * The number of rows last sent to Kubernetes in a terminal resize * request. */ int rows; /** * The number of columns last sent to Kubernetes in a terminal resize * request. */ int columns; /** * The in-progress session recording, or NULL if no recording is in * progress. */ guac_common_recording* recording; } guac_kubernetes_client; /** * Main Kubernetes client thread, handling transfer of STDOUT/STDERR of an * attached Kubernetes pod to STDOUT of the terminal. */ void* guac_kubernetes_client_thread(void* data); /** * Sends a message to the Kubernetes server requesting that the terminal be * resized to the given dimensions. This message may be queued until the * underlying WebSocket connection is ready to send. * * @param client * The guac_client associated with the Kubernetes connection. * * @param rows * The new terminal size in rows. * * @param columns * The new terminal size in columns. */ void guac_kubernetes_resize(guac_client* client, int rows, int columns); /** * Sends messages to the Kubernetes server such that the terminal is forced * to redraw. This function should be invoked at the beginning of each * session in order to restore expected display state. * * @param client * The guac_client associated with the Kubernetes connection. */ void guac_kubernetes_force_redraw(guac_client* client); #endif guacamole-server-1.3.0/src/protocols/kubernetes/argv.h0000644000175100001440000000451613770536337020010 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_KUBERNETES_ARGV_H #define GUAC_KUBERNETES_ARGV_H #include "config.h" #include #include /** * The name of the parameter that specifies/updates the color scheme used by * the terminal emulator. */ #define GUAC_KUBERNETES_ARGV_COLOR_SCHEME "color-scheme" /** * The name of the parameter that specifies/updates the name of the font used * by the terminal emulator. */ #define GUAC_KUBERNETES_ARGV_FONT_NAME "font-name" /** * The name of the parameter that specifies/updates the font size used by the * terminal emulator. */ #define GUAC_KUBERNETES_ARGV_FONT_SIZE "font-size" /** * Handles a received argument value from a Guacamole "argv" instruction, * updating the given connection parameter. */ guac_argv_callback guac_kubernetes_argv_callback; /** * Sends the current values of all non-sensitive parameters which may be set * while the connection is running to the given user. Note that the user * receiving these values will not necessarily be able to set new values * themselves if their connection is read-only. This function can be used as * the callback for guac_client_foreach_user() and guac_client_for_owner() * * @param user * The user that should receive the values of all non-sensitive parameters * which may be set while the connection is running. * * @param data * The guac_kubernetes_client instance associated with the current * connection. * * @return * Always NULL. */ void* guac_kubernetes_send_current_argv(guac_user* user, void* data); #endif guacamole-server-1.3.0/src/protocols/kubernetes/user.c0000644000175100001440000000743513770536337020025 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "argv.h" #include "clipboard.h" #include "common/cursor.h" #include "input.h" #include "kubernetes.h" #include "pipe.h" #include "settings.h" #include "terminal/terminal.h" #include "user.h" #include #include #include #include #include #include int guac_kubernetes_user_join_handler(guac_user* user, int argc, char** argv) { guac_client* client = user->client; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; /* Parse provided arguments */ guac_kubernetes_settings* settings = guac_kubernetes_parse_args(user, argc, (const char**) argv); /* Fail if settings cannot be parsed */ if (settings == NULL) { guac_user_log(user, GUAC_LOG_INFO, "Badly formatted client arguments."); return 1; } /* Store settings at user level */ user->data = settings; /* Connect to Kubernetes if owner */ if (user->owner) { /* Store owner's settings at client level */ kubernetes_client->settings = settings; /* Start client thread */ if (pthread_create(&(kubernetes_client->client_thread), NULL, guac_kubernetes_client_thread, (void*) client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start Kubernetes client thread"); return 1; } } /* If not owner, synchronize with current display */ else { guac_terminal_dup(kubernetes_client->term, user, user->socket); guac_kubernetes_send_current_argv(user, kubernetes_client); guac_socket_flush(user->socket); } /* Only handle events if not read-only */ if (!settings->read_only) { /* General mouse/keyboard events */ user->key_handler = guac_kubernetes_user_key_handler; user->mouse_handler = guac_kubernetes_user_mouse_handler; /* Inbound (client to server) clipboard transfer */ if (!settings->disable_paste) user->clipboard_handler = guac_kubernetes_clipboard_handler; /* STDIN redirection */ user->pipe_handler = guac_kubernetes_pipe_handler; /* Updates to connection parameters */ user->argv_handler = guac_argv_handler; /* Display size change events */ user->size_handler = guac_kubernetes_user_size_handler; } return 0; } int guac_kubernetes_user_leave_handler(guac_user* user) { guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) user->client->data; /* Update shared cursor state */ guac_common_cursor_remove_user(kubernetes_client->term->cursor, user); /* Free settings if not owner (owner settings will be freed with client) */ if (!user->owner) { guac_kubernetes_settings* settings = (guac_kubernetes_settings*) user->data; guac_kubernetes_settings_free(settings); } return 0; } guacamole-server-1.3.0/src/protocols/kubernetes/input.c0000644000175100001440000000547313702142276020174 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/recording.h" #include "input.h" #include "kubernetes.h" #include "terminal/terminal.h" #include #include #include int guac_kubernetes_user_mouse_handler(guac_user* user, int x, int y, int mask) { guac_client* client = user->client; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; /* Skip if terminal not yet ready */ guac_terminal* term = kubernetes_client->term; if (term == NULL) return 0; /* Report mouse position within recording */ if (kubernetes_client->recording != NULL) guac_common_recording_report_mouse(kubernetes_client->recording, x, y, mask); guac_terminal_send_mouse(term, user, x, y, mask); return 0; } int guac_kubernetes_user_key_handler(guac_user* user, int keysym, int pressed) { guac_client* client = user->client; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; /* Report key state within recording */ if (kubernetes_client->recording != NULL) guac_common_recording_report_key(kubernetes_client->recording, keysym, pressed); /* Skip if terminal not yet ready */ guac_terminal* term = kubernetes_client->term; if (term == NULL) return 0; guac_terminal_send_key(term, keysym, pressed); return 0; } int guac_kubernetes_user_size_handler(guac_user* user, int width, int height) { /* Get terminal */ guac_client* client = user->client; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; /* Skip if terminal not yet ready */ guac_terminal* terminal = kubernetes_client->term; if (terminal == NULL) return 0; /* Resize terminal */ guac_terminal_resize(terminal, width, height); /* Update Kubernetes terminal window size if connected */ guac_kubernetes_resize(client, terminal->term_height, terminal->term_width); return 0; } guacamole-server-1.3.0/src/protocols/kubernetes/clipboard.h0000644000175100001440000000240013702142276020764 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_KUBERNETES_CLIPBOARD_H #define GUAC_KUBERNETES_CLIPBOARD_H #include /** * Handler for inbound clipboard streams. */ guac_user_clipboard_handler guac_kubernetes_clipboard_handler; /** * Handler for data received along clipboard streams. */ guac_user_blob_handler guac_kubernetes_clipboard_blob_handler; /** * Handler for end-of-stream related to clipboard. */ guac_user_end_handler guac_kubernetes_clipboard_end_handler; #endif guacamole-server-1.3.0/src/protocols/kubernetes/Makefile.in0000644000175100001440000012063613772471102020735 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/protocols/kubernetes ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) libguac_client_kubernetes_la_DEPENDENCIES = am_libguac_client_kubernetes_la_OBJECTS = \ libguac_client_kubernetes_la-argv.lo \ libguac_client_kubernetes_la-client.lo \ libguac_client_kubernetes_la-clipboard.lo \ libguac_client_kubernetes_la-input.lo \ libguac_client_kubernetes_la-io.lo \ libguac_client_kubernetes_la-pipe.lo \ libguac_client_kubernetes_la-settings.lo \ libguac_client_kubernetes_la-ssl.lo \ libguac_client_kubernetes_la-kubernetes.lo \ libguac_client_kubernetes_la-url.lo \ libguac_client_kubernetes_la-user.lo libguac_client_kubernetes_la_OBJECTS = \ $(am_libguac_client_kubernetes_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libguac_client_kubernetes_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) \ $(libguac_client_kubernetes_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = \ ./$(DEPDIR)/libguac_client_kubernetes_la-argv.Plo \ ./$(DEPDIR)/libguac_client_kubernetes_la-client.Plo \ ./$(DEPDIR)/libguac_client_kubernetes_la-clipboard.Plo \ ./$(DEPDIR)/libguac_client_kubernetes_la-input.Plo \ ./$(DEPDIR)/libguac_client_kubernetes_la-io.Plo \ ./$(DEPDIR)/libguac_client_kubernetes_la-kubernetes.Plo \ ./$(DEPDIR)/libguac_client_kubernetes_la-pipe.Plo \ ./$(DEPDIR)/libguac_client_kubernetes_la-settings.Plo \ ./$(DEPDIR)/libguac_client_kubernetes_la-ssl.Plo \ ./$(DEPDIR)/libguac_client_kubernetes_la-url.Plo \ ./$(DEPDIR)/libguac_client_kubernetes_la-user.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libguac_client_kubernetes_la_SOURCES) DIST_SOURCES = $(libguac_client_kubernetes_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac-client-kubernetes.la libguac_client_kubernetes_la_SOURCES = \ argv.c \ client.c \ clipboard.c \ input.c \ io.c \ pipe.c \ settings.c \ ssl.c \ kubernetes.c \ url.c \ user.c noinst_HEADERS = \ argv.h \ client.h \ clipboard.h \ input.h \ io.h \ pipe.h \ settings.h \ ssl.h \ kubernetes.h \ url.h \ user.h libguac_client_kubernetes_la_CFLAGS = \ -Werror -Wall -Iinclude \ @LIBGUAC_INCLUDE@ \ @TERMINAL_INCLUDE@ libguac_client_kubernetes_la_LIBADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ \ @TERMINAL_LTLIB@ libguac_client_kubernetes_la_LDFLAGS = \ -version-info 0:0:0 \ @PTHREAD_LIBS@ \ @SSL_LIBS@ \ @WEBSOCKETS_LIBS@ all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/protocols/kubernetes/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/protocols/kubernetes/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libguac-client-kubernetes.la: $(libguac_client_kubernetes_la_OBJECTS) $(libguac_client_kubernetes_la_DEPENDENCIES) $(EXTRA_libguac_client_kubernetes_la_DEPENDENCIES) $(AM_V_CCLD)$(libguac_client_kubernetes_la_LINK) -rpath $(libdir) $(libguac_client_kubernetes_la_OBJECTS) $(libguac_client_kubernetes_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_kubernetes_la-argv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_kubernetes_la-client.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_kubernetes_la-clipboard.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_kubernetes_la-input.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_kubernetes_la-io.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_kubernetes_la-kubernetes.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_kubernetes_la-pipe.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_kubernetes_la-settings.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_kubernetes_la-ssl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_kubernetes_la-url.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_client_kubernetes_la-user.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libguac_client_kubernetes_la-argv.lo: argv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -MT libguac_client_kubernetes_la-argv.lo -MD -MP -MF $(DEPDIR)/libguac_client_kubernetes_la-argv.Tpo -c -o libguac_client_kubernetes_la-argv.lo `test -f 'argv.c' || echo '$(srcdir)/'`argv.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_kubernetes_la-argv.Tpo $(DEPDIR)/libguac_client_kubernetes_la-argv.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='argv.c' object='libguac_client_kubernetes_la-argv.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -c -o libguac_client_kubernetes_la-argv.lo `test -f 'argv.c' || echo '$(srcdir)/'`argv.c libguac_client_kubernetes_la-client.lo: client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -MT libguac_client_kubernetes_la-client.lo -MD -MP -MF $(DEPDIR)/libguac_client_kubernetes_la-client.Tpo -c -o libguac_client_kubernetes_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_kubernetes_la-client.Tpo $(DEPDIR)/libguac_client_kubernetes_la-client.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client.c' object='libguac_client_kubernetes_la-client.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -c -o libguac_client_kubernetes_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c libguac_client_kubernetes_la-clipboard.lo: clipboard.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -MT libguac_client_kubernetes_la-clipboard.lo -MD -MP -MF $(DEPDIR)/libguac_client_kubernetes_la-clipboard.Tpo -c -o libguac_client_kubernetes_la-clipboard.lo `test -f 'clipboard.c' || echo '$(srcdir)/'`clipboard.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_kubernetes_la-clipboard.Tpo $(DEPDIR)/libguac_client_kubernetes_la-clipboard.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='clipboard.c' object='libguac_client_kubernetes_la-clipboard.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -c -o libguac_client_kubernetes_la-clipboard.lo `test -f 'clipboard.c' || echo '$(srcdir)/'`clipboard.c libguac_client_kubernetes_la-input.lo: input.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -MT libguac_client_kubernetes_la-input.lo -MD -MP -MF $(DEPDIR)/libguac_client_kubernetes_la-input.Tpo -c -o libguac_client_kubernetes_la-input.lo `test -f 'input.c' || echo '$(srcdir)/'`input.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_kubernetes_la-input.Tpo $(DEPDIR)/libguac_client_kubernetes_la-input.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='input.c' object='libguac_client_kubernetes_la-input.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -c -o libguac_client_kubernetes_la-input.lo `test -f 'input.c' || echo '$(srcdir)/'`input.c libguac_client_kubernetes_la-io.lo: io.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -MT libguac_client_kubernetes_la-io.lo -MD -MP -MF $(DEPDIR)/libguac_client_kubernetes_la-io.Tpo -c -o libguac_client_kubernetes_la-io.lo `test -f 'io.c' || echo '$(srcdir)/'`io.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_kubernetes_la-io.Tpo $(DEPDIR)/libguac_client_kubernetes_la-io.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='io.c' object='libguac_client_kubernetes_la-io.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -c -o libguac_client_kubernetes_la-io.lo `test -f 'io.c' || echo '$(srcdir)/'`io.c libguac_client_kubernetes_la-pipe.lo: pipe.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -MT libguac_client_kubernetes_la-pipe.lo -MD -MP -MF $(DEPDIR)/libguac_client_kubernetes_la-pipe.Tpo -c -o libguac_client_kubernetes_la-pipe.lo `test -f 'pipe.c' || echo '$(srcdir)/'`pipe.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_kubernetes_la-pipe.Tpo $(DEPDIR)/libguac_client_kubernetes_la-pipe.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pipe.c' object='libguac_client_kubernetes_la-pipe.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -c -o libguac_client_kubernetes_la-pipe.lo `test -f 'pipe.c' || echo '$(srcdir)/'`pipe.c libguac_client_kubernetes_la-settings.lo: settings.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -MT libguac_client_kubernetes_la-settings.lo -MD -MP -MF $(DEPDIR)/libguac_client_kubernetes_la-settings.Tpo -c -o libguac_client_kubernetes_la-settings.lo `test -f 'settings.c' || echo '$(srcdir)/'`settings.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_kubernetes_la-settings.Tpo $(DEPDIR)/libguac_client_kubernetes_la-settings.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='settings.c' object='libguac_client_kubernetes_la-settings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -c -o libguac_client_kubernetes_la-settings.lo `test -f 'settings.c' || echo '$(srcdir)/'`settings.c libguac_client_kubernetes_la-ssl.lo: ssl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -MT libguac_client_kubernetes_la-ssl.lo -MD -MP -MF $(DEPDIR)/libguac_client_kubernetes_la-ssl.Tpo -c -o libguac_client_kubernetes_la-ssl.lo `test -f 'ssl.c' || echo '$(srcdir)/'`ssl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_kubernetes_la-ssl.Tpo $(DEPDIR)/libguac_client_kubernetes_la-ssl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ssl.c' object='libguac_client_kubernetes_la-ssl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -c -o libguac_client_kubernetes_la-ssl.lo `test -f 'ssl.c' || echo '$(srcdir)/'`ssl.c libguac_client_kubernetes_la-kubernetes.lo: kubernetes.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -MT libguac_client_kubernetes_la-kubernetes.lo -MD -MP -MF $(DEPDIR)/libguac_client_kubernetes_la-kubernetes.Tpo -c -o libguac_client_kubernetes_la-kubernetes.lo `test -f 'kubernetes.c' || echo '$(srcdir)/'`kubernetes.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_kubernetes_la-kubernetes.Tpo $(DEPDIR)/libguac_client_kubernetes_la-kubernetes.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kubernetes.c' object='libguac_client_kubernetes_la-kubernetes.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -c -o libguac_client_kubernetes_la-kubernetes.lo `test -f 'kubernetes.c' || echo '$(srcdir)/'`kubernetes.c libguac_client_kubernetes_la-url.lo: url.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -MT libguac_client_kubernetes_la-url.lo -MD -MP -MF $(DEPDIR)/libguac_client_kubernetes_la-url.Tpo -c -o libguac_client_kubernetes_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_kubernetes_la-url.Tpo $(DEPDIR)/libguac_client_kubernetes_la-url.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='url.c' object='libguac_client_kubernetes_la-url.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -c -o libguac_client_kubernetes_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c libguac_client_kubernetes_la-user.lo: user.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -MT libguac_client_kubernetes_la-user.lo -MD -MP -MF $(DEPDIR)/libguac_client_kubernetes_la-user.Tpo -c -o libguac_client_kubernetes_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_client_kubernetes_la-user.Tpo $(DEPDIR)/libguac_client_kubernetes_la-user.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user.c' object='libguac_client_kubernetes_la-user.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_client_kubernetes_la_CFLAGS) $(CFLAGS) -c -o libguac_client_kubernetes_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-argv.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-client.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-clipboard.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-input.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-io.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-kubernetes.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-pipe.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-settings.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-ssl.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-url.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-user.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-argv.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-client.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-clipboard.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-input.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-io.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-kubernetes.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-pipe.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-settings.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-ssl.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-url.Plo -rm -f ./$(DEPDIR)/libguac_client_kubernetes_la-user.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/protocols/kubernetes/settings.h0000644000175100001440000002026313764613616020705 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_KUBERNETES_SETTINGS_H #define GUAC_KUBERNETES_SETTINGS_H #include #include /** * The name of the font to use for the terminal if no name is specified. */ #define GUAC_KUBERNETES_DEFAULT_FONT_NAME "monospace" /** * The size of the font to use for the terminal if no font size is specified, * in points. */ #define GUAC_KUBERNETES_DEFAULT_FONT_SIZE 12 /** * The port to connect to when initiating any Kubernetes connection, if no * other port is specified. */ #define GUAC_KUBERNETES_DEFAULT_PORT 8080 /** * The name of the Kubernetes namespace that should be used by default if no * specific Kubernetes namespace is provided. */ #define GUAC_KUBERNETES_DEFAULT_NAMESPACE "default" /** * The filename to use for the typescript, if not specified. */ #define GUAC_KUBERNETES_DEFAULT_TYPESCRIPT_NAME "typescript" /** * The filename to use for the screen recording, if not specified. */ #define GUAC_KUBERNETES_DEFAULT_RECORDING_NAME "recording" /** * The default maximum scrollback size in rows. */ #define GUAC_KUBERNETES_DEFAULT_MAX_SCROLLBACK 1000 /** * Settings for the Kubernetes connection. The values for this structure are * parsed from the arguments given during the Guacamole protocol handshake * using the guac_kubernetes_parse_args() function. */ typedef struct guac_kubernetes_settings { /** * The hostname of the Kubernetes server to connect to. */ char* hostname; /** * The port of the Kubernetes server to connect to. */ int port; /** * The name of the Kubernetes namespace of the pod containing the container * being attached to. */ char* kubernetes_namespace; /** * The name of the Kubernetes pod containing with the container being * attached to. */ char* kubernetes_pod; /** * The name of the container to attach to, or NULL to arbitrarily attach to * the first container in the pod. */ char* kubernetes_container; /** * Whether SSL/TLS should be used. */ bool use_ssl; /** * The certificate to use if performing SSL/TLS client authentication to * authenticate with the Kubernetes server, in PEM format. If omitted, SSL * client authentication will not be performed. */ char* client_cert; /** * The key to use if performing SSL/TLS client authentication to * authenticate with the Kubernetes server, in PEM format. If omitted, SSL * client authentication will not be performed. */ char* client_key; /** * The certificate of the certificate authority that signed the certificate * of the Kubernetes server, in PEM format. If omitted. verification of * the Kubernetes server certificate will use the systemwide certificate * authorities. */ char* ca_cert; /** * Whether the certificate used by the Kubernetes server for SSL/TLS should * be ignored if it cannot be validated. */ bool ignore_cert; /** * Whether this connection is read-only, and user input should be dropped. */ bool read_only; /** * The maximum size of the scrollback buffer in rows. */ int max_scrollback; /** * The name of the font to use for display rendering. */ char* font_name; /** * The size of the font to use, in points. */ int font_size; /** * The name of the color scheme to use. */ char* color_scheme; /** * The desired width of the terminal display, in pixels. */ int width; /** * The desired height of the terminal display, in pixels. */ int height; /** * The desired screen resolution, in DPI. */ int resolution; /** * Whether outbound clipboard access should be blocked. If set, it will not * be possible to copy data from the terminal to the client using the * clipboard. */ bool disable_copy; /** * Whether inbound clipboard access should be blocked. If set, it will not * be possible to paste data from the client to the terminal using the * clipboard. */ bool disable_paste; /** * The path in which the typescript should be saved, if enabled. If no * typescript should be saved, this will be NULL. */ char* typescript_path; /** * The filename to use for the typescript, if enabled. */ char* typescript_name; /** * Whether the typescript path should be automatically created if it does * not already exist. */ bool create_typescript_path; /** * The path in which the screen recording should be saved, if enabled. If * no screen recording should be saved, this will be NULL. */ char* recording_path; /** * The filename to use for the screen recording, if enabled. */ char* recording_name; /** * Whether the screen recording path should be automatically created if it * does not already exist. */ bool create_recording_path; /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output * is included by default, as it is necessary for any recording which must * later be viewable as video. */ bool recording_exclude_output; /** * Whether changes to mouse state, such as position and buttons pressed or * released, should NOT be included in the session recording. Mouse state * is included by default, as it is necessary for the mouse cursor to be * rendered in any resulting video. */ bool recording_exclude_mouse; /** * Whether keys pressed and released should be included in the session * recording. Key events are NOT included by default within the recording, * as doing so has privacy and security implications. Including key events * may be necessary in certain auditing contexts, but should only be done * with caution. Key events can easily contain sensitive information, such * as passwords, credit card numbers, etc. */ bool recording_include_keys; /** * The ASCII code, as an integer, that the Kubernetes client will use when * the backspace key is pressed. By default, this is 127, ASCII delete, if * not specified in the client settings. */ int backspace; } guac_kubernetes_settings; /** * Parses all given args, storing them in a newly-allocated settings object. If * the args fail to parse, NULL is returned. * * @param user * The user who submitted the given arguments while joining the * connection. * * @param argc * The number of arguments within the argv array. * * @param argv * The values of all arguments provided by the user. * * @return * A newly-allocated settings object which must be freed with * guac_kubernetes_settings_free() when no longer needed. If the arguments * fail to parse, NULL is returned. */ guac_kubernetes_settings* guac_kubernetes_parse_args(guac_user* user, int argc, const char** argv); /** * Frees the given guac_kubernetes_settings object, having been previously * allocated via guac_kubernetes_parse_args(). * * @param settings * The settings object to free. */ void guac_kubernetes_settings_free(guac_kubernetes_settings* settings); /** * NULL-terminated array of accepted client args. */ extern const char* GUAC_KUBERNETES_CLIENT_ARGS[]; #endif guacamole-server-1.3.0/src/protocols/kubernetes/settings.c0000644000175100001440000003274213770536337020706 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "argv.h" #include "settings.h" #include #include /* Client plugin arguments */ const char* GUAC_KUBERNETES_CLIENT_ARGS[] = { "hostname", "port", "namespace", "pod", "container", "use-ssl", "client-cert", "client-key", "ca-cert", "ignore-cert", GUAC_KUBERNETES_ARGV_FONT_NAME, GUAC_KUBERNETES_ARGV_FONT_SIZE, GUAC_KUBERNETES_ARGV_COLOR_SCHEME, "typescript-path", "typescript-name", "create-typescript-path", "recording-path", "recording-name", "recording-exclude-output", "recording-exclude-mouse", "recording-include-keys", "create-recording-path", "read-only", "backspace", "scrollback", "disable-copy", "disable-paste", NULL }; enum KUBERNETES_ARGS_IDX { /** * The hostname to connect to. Required. */ IDX_HOSTNAME, /** * The port to connect to. Optional. */ IDX_PORT, /** * The name of the Kubernetes namespace of the pod containing the container * being attached to. If omitted, the default namespace will be used. */ IDX_NAMESPACE, /** * The name of the Kubernetes pod containing with the container being * attached to. Required. */ IDX_POD, /** * The name of the container to attach to. If omitted, the first container * in the pod will be used. */ IDX_CONTAINER, /** * Whether SSL/TLS should be used. If omitted, SSL/TLS will not be used. */ IDX_USE_SSL, /** * The certificate to use if performing SSL/TLS client authentication to * authenticate with the Kubernetes server, in PEM format. If omitted, SSL * client authentication will not be performed. */ IDX_CLIENT_CERT, /** * The key to use if performing SSL/TLS client authentication to * authenticate with the Kubernetes server, in PEM format. If omitted, SSL * client authentication will not be performed. */ IDX_CLIENT_KEY, /** * The certificate of the certificate authority that signed the certificate * of the Kubernetes server, in PEM format. If omitted. verification of * the Kubernetes server certificate will use the systemwide certificate * authorities. */ IDX_CA_CERT, /** * Whether the certificate used by the Kubernetes server for SSL/TLS should * be ignored if it cannot be validated. */ IDX_IGNORE_CERT, /** * The name of the font to use within the terminal. */ IDX_FONT_NAME, /** * The size of the font to use within the terminal, in points. */ IDX_FONT_SIZE, /** * The color scheme to use, as a series of semicolon-separated color-value * pairs: "background: ", "foreground: ", or * "color: ", where is a number from 0 to 255, and is * "color" or an X11 color code (e.g. "aqua" or "rgb:12/34/56"). * The color scheme can also be one of the special values: "black-white", * "white-black", "gray-black", or "green-black". */ IDX_COLOR_SCHEME, /** * The full absolute path to the directory in which typescripts should be * written. */ IDX_TYPESCRIPT_PATH, /** * The name that should be given to typescripts which are written in the * given path. Each typescript will consist of two files: "NAME" and * "NAME.timing". */ IDX_TYPESCRIPT_NAME, /** * Whether the specified typescript path should automatically be created * if it does not yet exist. */ IDX_CREATE_TYPESCRIPT_PATH, /** * The full absolute path to the directory in which screen recordings * should be written. */ IDX_RECORDING_PATH, /** * The name that should be given to screen recordings which are written in * the given path. */ IDX_RECORDING_NAME, /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output * is included by default, as it is necessary for any recording which must * later be viewable as video. */ IDX_RECORDING_EXCLUDE_OUTPUT, /** * Whether changes to mouse state, such as position and buttons pressed or * released, should NOT be included in the session recording. Mouse state * is included by default, as it is necessary for the mouse cursor to be * rendered in any resulting video. */ IDX_RECORDING_EXCLUDE_MOUSE, /** * Whether keys pressed and released should be included in the session * recording. Key events are NOT included by default within the recording, * as doing so has privacy and security implications. Including key events * may be necessary in certain auditing contexts, but should only be done * with caution. Key events can easily contain sensitive information, such * as passwords, credit card numbers, etc. */ IDX_RECORDING_INCLUDE_KEYS, /** * Whether the specified screen recording path should automatically be * created if it does not yet exist. */ IDX_CREATE_RECORDING_PATH, /** * "true" if this connection should be read-only (user input should be * dropped), "false" or blank otherwise. */ IDX_READ_ONLY, /** * ASCII code, as an integer to use for the backspace key, or 127 * if not specified. */ IDX_BACKSPACE, /** * The maximum size of the scrollback buffer in rows. */ IDX_SCROLLBACK, /** * Whether outbound clipboard access should be blocked. If set to "true", * it will not be possible to copy data from the terminal to the client * using the clipboard. By default, clipboard access is not blocked. */ IDX_DISABLE_COPY, /** * Whether inbound clipboard access should be blocked. If set to "true", it * will not be possible to paste data from the client to the terminal using * the clipboard. By default, clipboard access is not blocked. */ IDX_DISABLE_PASTE, KUBERNETES_ARGS_COUNT }; guac_kubernetes_settings* guac_kubernetes_parse_args(guac_user* user, int argc, const char** argv) { /* Validate arg count */ if (argc != KUBERNETES_ARGS_COUNT) { guac_user_log(user, GUAC_LOG_WARNING, "Incorrect number of connection " "parameters provided: expected %i, got %i.", KUBERNETES_ARGS_COUNT, argc); return NULL; } guac_kubernetes_settings* settings = calloc(1, sizeof(guac_kubernetes_settings)); /* Read hostname */ settings->hostname = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_HOSTNAME, ""); /* Read port */ settings->port = guac_user_parse_args_int(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_PORT, GUAC_KUBERNETES_DEFAULT_PORT); /* Read Kubernetes namespace */ settings->kubernetes_namespace = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_NAMESPACE, GUAC_KUBERNETES_DEFAULT_NAMESPACE); /* Read name of Kubernetes pod (required) */ settings->kubernetes_pod = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_POD, NULL); /* Read container of pod (optional) */ settings->kubernetes_container = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_CONTAINER, NULL); /* Parse whether SSL should be used */ settings->use_ssl = guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_USE_SSL, false); /* Read SSL/TLS connection details only if enabled */ if (settings->use_ssl) { settings->client_cert = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_CLIENT_CERT, NULL); settings->client_key = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_CLIENT_KEY, NULL); settings->ca_cert = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_CA_CERT, NULL); settings->ignore_cert = guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_IGNORE_CERT, false); } /* Read-only mode */ settings->read_only = guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_READ_ONLY, false); /* Read maximum scrollback size */ settings->max_scrollback = guac_user_parse_args_int(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_SCROLLBACK, GUAC_KUBERNETES_DEFAULT_MAX_SCROLLBACK); /* Read font name */ settings->font_name = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_FONT_NAME, GUAC_KUBERNETES_DEFAULT_FONT_NAME); /* Read font size */ settings->font_size = guac_user_parse_args_int(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_FONT_SIZE, GUAC_KUBERNETES_DEFAULT_FONT_SIZE); /* Copy requested color scheme */ settings->color_scheme = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_COLOR_SCHEME, ""); /* Pull width/height/resolution directly from user */ settings->width = user->info.optimal_width; settings->height = user->info.optimal_height; settings->resolution = user->info.optimal_resolution; /* Read typescript path */ settings->typescript_path = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_TYPESCRIPT_PATH, NULL); /* Read typescript name */ settings->typescript_name = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_TYPESCRIPT_NAME, GUAC_KUBERNETES_DEFAULT_TYPESCRIPT_NAME); /* Parse path creation flag */ settings->create_typescript_path = guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_CREATE_TYPESCRIPT_PATH, false); /* Read recording path */ settings->recording_path = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_RECORDING_PATH, NULL); /* Read recording name */ settings->recording_name = guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_RECORDING_NAME, GUAC_KUBERNETES_DEFAULT_RECORDING_NAME); /* Parse output exclusion flag */ settings->recording_exclude_output = guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_RECORDING_EXCLUDE_OUTPUT, false); /* Parse mouse exclusion flag */ settings->recording_exclude_mouse = guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_RECORDING_EXCLUDE_MOUSE, false); /* Parse key event inclusion flag */ settings->recording_include_keys = guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_RECORDING_INCLUDE_KEYS, false); /* Parse path creation flag */ settings->create_recording_path = guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_CREATE_RECORDING_PATH, false); /* Parse backspace key code */ settings->backspace = guac_user_parse_args_int(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_BACKSPACE, 127); /* Parse clipboard copy disable flag */ settings->disable_copy = guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_DISABLE_COPY, false); /* Parse clipboard paste disable flag */ settings->disable_paste = guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_DISABLE_PASTE, false); /* Parsing was successful */ return settings; } void guac_kubernetes_settings_free(guac_kubernetes_settings* settings) { /* Free network connection information */ free(settings->hostname); /* Free Kubernetes pod/container details */ free(settings->kubernetes_namespace); free(settings->kubernetes_pod); free(settings->kubernetes_container); /* Free SSL/TLS details */ free(settings->client_cert); free(settings->client_key); free(settings->ca_cert); /* Free display preferences */ free(settings->font_name); free(settings->color_scheme); /* Free typescript settings */ free(settings->typescript_name); free(settings->typescript_path); /* Free screen recording settings */ free(settings->recording_name); free(settings->recording_path); /* Free overall structure */ free(settings); } guacamole-server-1.3.0/src/protocols/kubernetes/client.h0000644000175100001440000000274513702142276020317 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_KUBERNETES_CLIENT_H #define GUAC_KUBERNETES_CLIENT_H #include /** * The maximum number of bytes to allow within the clipboard. */ #define GUAC_KUBERNETES_CLIPBOARD_MAX_LENGTH 262144 /** * Static reference to the guac_client associated with the active Kubernetes * connection. While libwebsockets provides some means of storing and * retrieving custom data in some structures, this is not always available. */ extern guac_client* guac_kubernetes_lws_current_client; /** * Free handler. Required by libguac and called when the guac_client is * disconnected and must be cleaned up. */ guac_client_free_handler guac_kubernetes_client_free_handler; #endif guacamole-server-1.3.0/src/protocols/kubernetes/ssl.c0000644000175100001440000001653613702142276017640 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "kubernetes.h" #include "settings.h" #include #include #include #include #include #include #include /** * Tests whether the given hostname is, in fact, an IP address. * * @param hostname * The hostname to test. * * @return * Non-zero if the given hostname is an IP address, zero otherwise. */ static int guac_kubernetes_is_address(const char* hostname) { /* Attempt to interpret the hostname as an IP address */ ASN1_OCTET_STRING* ip = a2i_IPADDRESS(hostname); /* If unsuccessful, the hostname is not an IP address */ if (ip == NULL) return 0; /* Converted hostname must be freed */ ASN1_OCTET_STRING_free(ip); return 1; } /** * Parses the given PEM certificate, returning a new OpenSSL X509 structure * representing that certificate. * * @param pem * The PEM certificate. * * @return * An X509 structure representing the given certificate, or NULL if the * certificate was unreadable. */ static X509* guac_kubernetes_read_cert(char* pem) { /* Prepare a BIO which provides access to the in-memory CA cert */ BIO* bio = BIO_new_mem_buf(pem, -1); if (bio == NULL) return NULL; /* Read the CA cert as PEM */ X509* certificate = PEM_read_bio_X509(bio, NULL, NULL, NULL); if (certificate == NULL) { BIO_free(bio); return NULL; } return certificate; } /** * Parses the given PEM private key, returning a new OpenSSL EVP_PKEY structure * representing that key. * * @param pem * The PEM private key. * * @return * An EVP_KEY representing the given private key, or NULL if the private * key was unreadable. */ static EVP_PKEY* guac_kubernetes_read_key(char* pem) { /* Prepare a BIO which provides access to the in-memory key */ BIO* bio = BIO_new_mem_buf(pem, -1); if (bio == NULL) return NULL; /* Read the private key as PEM */ EVP_PKEY* key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); if (key == NULL) { BIO_free(bio); return NULL; } return key; } /** * OpenSSL certificate verification callback which universally accepts all * certificates without performing any verification at all. * * @param x509_ctx * The current context of the certificate verification process. This * parameter is ignored by this particular implementation of the callback. * * @param arg * The arbitrary value passed to SSL_CTX_set_cert_verify_callback(). This * parameter is ignored by this particular implementation of the callback. * * @return * Strictly 0 if certificate verification fails, 1 if the certificate is * verified. No other values are legal return values for this callback as * documented by OpenSSL. */ static int guac_kubernetes_assume_cert_ok(X509_STORE_CTX* x509_ctx, void* arg) { return 1; } void guac_kubernetes_init_ssl(guac_client* client, SSL_CTX* context) { guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; guac_kubernetes_settings* settings = kubernetes_client->settings; /* Bypass certificate checks if requested */ if (settings->ignore_cert) { SSL_CTX_set_verify(context, SSL_VERIFY_PEER, NULL); SSL_CTX_set_cert_verify_callback(context, guac_kubernetes_assume_cert_ok, NULL); } /* Otherwise use the given CA certificate to validate (if any) */ else if (settings->ca_cert != NULL) { /* Read CA certificate from configuration data */ X509* ca_cert = guac_kubernetes_read_cert(settings->ca_cert); if (ca_cert == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Provided CA certificate is unreadable"); return; } /* Add certificate to CA store */ X509_STORE* ca_store = SSL_CTX_get_cert_store(context); if (!X509_STORE_add_cert(ca_store, ca_cert)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to add CA certificate to certificate store of " "SSL context"); return; } } /* Certificate for SSL/TLS client auth */ if (settings->client_cert != NULL) { /* Read client certificate from configuration data */ X509* client_cert = guac_kubernetes_read_cert(settings->client_cert); if (client_cert == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Provided client certificate is unreadable"); return; } /* Use parsed certificate for authentication */ if (!SSL_CTX_use_certificate(context, client_cert)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Client certificate could not be used for SSL/TLS " "client authentication"); return; } } /* Private key for SSL/TLS client auth */ if (settings->client_key != NULL) { /* Read client private key from configuration data */ EVP_PKEY* client_key = guac_kubernetes_read_key(settings->client_key); if (client_key == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Provided client private key is unreadable"); return; } /* Use parsed key for authentication */ if (!SSL_CTX_use_PrivateKey(context, client_key)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Client private key could not be used for SSL/TLS " "client authentication"); return; } } /* Enable hostname checking */ X509_VERIFY_PARAM *param = SSL_CTX_get0_param(context); X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); /* Validate properly depending on whether hostname is an IP address */ if (guac_kubernetes_is_address(settings->hostname)) { if (!X509_VERIFY_PARAM_set1_ip_asc(param, settings->hostname)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Server IP address validation could not be enabled"); return; } } else { if (!X509_VERIFY_PARAM_set1_host(param, settings->hostname, 0)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Server hostname validation could not be enabled"); return; } } } guacamole-server-1.3.0/src/protocols/kubernetes/ssl.h0000644000175100001440000000250013702142276017627 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_KUBERNETES_SSL_H #define GUAC_KUBERNETES_SSL_H #include "settings.h" #include /** * Initializes the given SSL/TLS context using the configuration parameters * associated with the given guac_client, setting up hostname/address * validation and client authentication. * * @param client * The guac_client associated with the Kubernetes connection. * * @param context * The SSL_CTX in use by libwebsockets. */ void guac_kubernetes_init_ssl(guac_client* client, SSL_CTX* context); #endif guacamole-server-1.3.0/src/protocols/kubernetes/client.c0000644000175100001440000001112613770536337020315 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "argv.h" #include "client.h" #include "common/clipboard.h" #include "kubernetes.h" #include "settings.h" #include "user.h" #include #include #include #include #include #include #include #include guac_client* guac_kubernetes_lws_current_client = NULL; /** * Logging callback invoked by libwebsockets to log a single line of logging * output. As libwebsockets messages are all generally low-level, the log * level provided by libwebsockets is ignored here, with all messages logged * instead at guacd's debug level. * * @param level * The libwebsockets log level associated with the log message. This value * is ignored by this implementation of the logging callback. * * @param line * The line of logging output to log. */ static void guac_kubernetes_log(int level, const char* line) { char buffer[1024]; /* Drop log message if there's nowhere to log yet */ if (guac_kubernetes_lws_current_client == NULL) return; /* Trim length of line to fit buffer (plus null terminator) */ int length = strlen(line); if (length > sizeof(buffer) - 1) length = sizeof(buffer) - 1; /* Copy as much of the received line as will fit in the buffer */ memcpy(buffer, line, length); /* If the line ends with a newline character, trim the character */ if (length > 0 && buffer[length - 1] == '\n') length--; /* Null-terminate the trimmed string */ buffer[length] = '\0'; /* Log using guacd's own log facilities */ guac_client_log(guac_kubernetes_lws_current_client, GUAC_LOG_DEBUG, "libwebsockets: %s", buffer); } int guac_client_init(guac_client* client) { /* Ensure reference to main guac_client remains available in all * libwebsockets contexts */ guac_kubernetes_lws_current_client = client; /* Redirect libwebsockets logging */ lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_INFO, guac_kubernetes_log); /* Set client args */ client->args = GUAC_KUBERNETES_CLIENT_ARGS; /* Allocate client instance data */ guac_kubernetes_client* kubernetes_client = calloc(1, sizeof(guac_kubernetes_client)); client->data = kubernetes_client; /* Init clipboard */ kubernetes_client->clipboard = guac_common_clipboard_alloc(GUAC_KUBERNETES_CLIPBOARD_MAX_LENGTH); /* Set handlers */ client->join_handler = guac_kubernetes_user_join_handler; client->free_handler = guac_kubernetes_client_free_handler; /* Register handlers for argument values that may be sent after the handshake */ guac_argv_register(GUAC_KUBERNETES_ARGV_COLOR_SCHEME, guac_kubernetes_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO); guac_argv_register(GUAC_KUBERNETES_ARGV_FONT_NAME, guac_kubernetes_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO); guac_argv_register(GUAC_KUBERNETES_ARGV_FONT_SIZE, guac_kubernetes_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO); /* Set locale and warn if not UTF-8 */ setlocale(LC_CTYPE, ""); if (strcmp(nl_langinfo(CODESET), "UTF-8") != 0) { guac_client_log(client, GUAC_LOG_INFO, "Current locale does not use UTF-8. Some characters may " "not render correctly."); } /* Success */ return 0; } int guac_kubernetes_client_free_handler(guac_client* client) { guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; /* Wait client thread to terminate */ pthread_join(kubernetes_client->client_thread, NULL); /* Free settings */ if (kubernetes_client->settings != NULL) guac_kubernetes_settings_free(kubernetes_client->settings); guac_common_clipboard_free(kubernetes_client->clipboard); free(kubernetes_client); return 0; } guacamole-server-1.3.0/src/protocols/kubernetes/pipe.h0000644000175100001440000000253713702142276017775 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_KUBERNETES_PIPE_H #define GUAC_KUBERNETES_PIPE_H #include /** * The name reserved for the inbound pipe stream which forces the terminal * emulator's STDIN to be received from the pipe. */ #define GUAC_KUBERNETES_STDIN_PIPE_NAME "STDIN" /** * Handles an incoming stream from a Guacamole "pipe" instruction. If the pipe * is named "STDIN", the the contents of the pipe stream are redirected to * STDIN of the terminal emulator for as long as the pipe is open. */ guac_user_pipe_handler guac_kubernetes_pipe_handler; #endif guacamole-server-1.3.0/src/protocols/kubernetes/io.c0000644000175100001440000001121413702142276017432 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "kubernetes.h" #include "terminal/terminal.h" #include #include #include #include #include void guac_kubernetes_receive_data(guac_client* client, const char* buffer, size_t length) { guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; /* Strip channel index from beginning of buffer */ int channel = *(buffer++); length--; switch (channel) { /* Write STDOUT / STDERR directly to terminal as output */ case GUAC_KUBERNETES_CHANNEL_STDOUT: case GUAC_KUBERNETES_CHANNEL_STDERR: guac_terminal_write(kubernetes_client->term, buffer, length); break; /* Ignore data on other channels */ default: guac_client_log(client, GUAC_LOG_DEBUG, "Received %i bytes along " "channel %i.", length, channel); } } void guac_kubernetes_send_message(guac_client* client, int channel, const char* data, int length) { guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; pthread_mutex_lock(&(kubernetes_client->outbound_message_lock)); /* Add message to buffer if space is available */ if (kubernetes_client->outbound_messages_waiting < GUAC_KUBERNETES_MAX_OUTBOUND_MESSAGES) { /* Calculate storage position of next message */ int index = (kubernetes_client->outbound_messages_top + kubernetes_client->outbound_messages_waiting) % GUAC_KUBERNETES_MAX_OUTBOUND_MESSAGES; /* Obtain pointer to message slot at calculated position */ guac_kubernetes_message* message = &(kubernetes_client->outbound_messages[index]); /* Copy details of message into buffer */ message->channel = channel; memcpy(message->data, data, length); message->length = length; /* One more message is now waiting */ kubernetes_client->outbound_messages_waiting++; /* Notify libwebsockets that we need a callback to send pending * messages */ lws_callback_on_writable(kubernetes_client->wsi); lws_cancel_service(kubernetes_client->context); } /* Warn if data has to be dropped */ else guac_client_log(client, GUAC_LOG_WARNING, "Send buffer could not be " "flushed in time to handle additional data. Outbound " "message dropped."); pthread_mutex_unlock(&(kubernetes_client->outbound_message_lock)); } bool guac_kubernetes_write_pending_message(guac_client* client) { bool messages_remain; guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; pthread_mutex_lock(&(kubernetes_client->outbound_message_lock)); /* Send one message from top of buffer */ if (kubernetes_client->outbound_messages_waiting > 0) { /* Obtain pointer to message at top */ int top = kubernetes_client->outbound_messages_top; guac_kubernetes_message* message = &(kubernetes_client->outbound_messages[top]); /* Write message including channel index */ lws_write(kubernetes_client->wsi, ((unsigned char*) message) + LWS_PRE, message->length + 1, LWS_WRITE_BINARY); /* Advance top to next message */ kubernetes_client->outbound_messages_top++; kubernetes_client->outbound_messages_top %= GUAC_KUBERNETES_MAX_OUTBOUND_MESSAGES; /* One less message is waiting */ kubernetes_client->outbound_messages_waiting--; } /* Record whether messages remained at time of completion */ messages_remain = (kubernetes_client->outbound_messages_waiting > 0); pthread_mutex_unlock(&(kubernetes_client->outbound_message_lock)); return messages_remain; } guacamole-server-1.3.0/src/protocols/kubernetes/url.c0000644000175100001440000000764413702142276017641 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "url.h" #include #include #include /** * Returns whether the given character is a character that need not be * escaped when included as part of a component of a URL. * * @param c * The character to test. * * @return * Zero if the character does not need to be escaped when included as * part of a component of a URL, non-zero otherwise. */ static int guac_kubernetes_is_url_safe(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || strchr("-_.!~*'()", c) != NULL; } int guac_kubernetes_escape_url_component(char* output, int length, const char* str) { char* current = output; while (*str != '\0') { char c = *str; /* Store alphanumeric characters verbatim */ if (guac_kubernetes_is_url_safe(c)) { /* Verify space exists for single character */ if (length < 1) return 1; *(current++) = c; length--; } /* Escape EVERYTHING else as hex */ else { /* Verify space exists for hex-encoded character */ if (length < 4) return 1; snprintf(current, 4, "%%%02X", (int) c); current += 3; length -= 3; } /* Next character */ str++; } /* Verify space exists for null terminator */ if (length < 1) return 1; /* Append null terminator */ *current = '\0'; return 0; } int guac_kubernetes_endpoint_attach(char* buffer, int length, const char* kubernetes_namespace, const char* kubernetes_pod, const char* kubernetes_container) { int written; char escaped_namespace[GUAC_KUBERNETES_MAX_ENDPOINT_LENGTH]; char escaped_pod[GUAC_KUBERNETES_MAX_ENDPOINT_LENGTH]; char escaped_container[GUAC_KUBERNETES_MAX_ENDPOINT_LENGTH]; /* Escape Kubernetes namespace */ if (guac_kubernetes_escape_url_component(escaped_namespace, sizeof(escaped_namespace), kubernetes_namespace)) return 1; /* Escape name of Kubernetes pod */ if (guac_kubernetes_escape_url_component(escaped_pod, sizeof(escaped_pod), kubernetes_pod)) return 1; /* Generate attachment endpoint URL */ if (kubernetes_container != NULL) { /* Escape container name */ if (guac_kubernetes_escape_url_component(escaped_container, sizeof(escaped_container), kubernetes_container)) return 1; written = snprintf(buffer, length, "/api/v1/namespaces/%s/pods/%s/attach" "?container=%s&stdin=true&stdout=true&tty=true", escaped_namespace, escaped_pod, escaped_container); } else { written = snprintf(buffer, length, "/api/v1/namespaces/%s/pods/%s/attach" "?stdin=true&stdout=true&tty=true", escaped_namespace, escaped_pod); } /* Endpoint URL was successfully generated if it was written to the given * buffer without truncation */ return !(written < length - 1); } guacamole-server-1.3.0/src/protocols/kubernetes/Makefile.am0000644000175100001440000000461313764613616020731 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac-client-kubernetes.la libguac_client_kubernetes_la_SOURCES = \ argv.c \ client.c \ clipboard.c \ input.c \ io.c \ pipe.c \ settings.c \ ssl.c \ kubernetes.c \ url.c \ user.c noinst_HEADERS = \ argv.h \ client.h \ clipboard.h \ input.h \ io.h \ pipe.h \ settings.h \ ssl.h \ kubernetes.h \ url.h \ user.h libguac_client_kubernetes_la_CFLAGS = \ -Werror -Wall -Iinclude \ @LIBGUAC_INCLUDE@ \ @TERMINAL_INCLUDE@ libguac_client_kubernetes_la_LIBADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ \ @TERMINAL_LTLIB@ libguac_client_kubernetes_la_LDFLAGS = \ -version-info 0:0:0 \ @PTHREAD_LIBS@ \ @SSL_LIBS@ \ @WEBSOCKETS_LIBS@ guacamole-server-1.3.0/src/protocols/kubernetes/io.h0000644000175100001440000001030413702142276017436 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_KUBERNETES_IO_H #define GUAC_KUBERNETES_IO_H #include #include #include #include /** * The maximum amount of data to include in any particular WebSocket message * to Kubernetes. This excludes the storage space required for the channel * index. */ #define GUAC_KUBERNETES_MAX_MESSAGE_SIZE 1024 /** * The index of the Kubernetes channel used for STDIN. */ #define GUAC_KUBERNETES_CHANNEL_STDIN 0 /** * The index of the Kubernetes channel used for STDOUT. */ #define GUAC_KUBERNETES_CHANNEL_STDOUT 1 /** * The index of the Kubernetes channel used for STDERR. */ #define GUAC_KUBERNETES_CHANNEL_STDERR 2 /** * The index of the Kubernetes channel used for terminal resize messages. */ #define GUAC_KUBERNETES_CHANNEL_RESIZE 4 /** * An outbound message to be received by Kubernetes over WebSocket. */ typedef struct guac_kubernetes_message { /** * lws_write() requires leading padding of LWS_PRE bytes to provide * scratch space for WebSocket framing. */ uint8_t _padding[LWS_PRE]; /** * The index of the channel receiving the data, such as * GUAC_KUBERNETES_CHANNEL_STDIN. */ uint8_t channel; /** * The data that should be sent to Kubernetes (along with the channel * index). */ char data[GUAC_KUBERNETES_MAX_MESSAGE_SIZE]; /** * The length of the data to be sent, excluding the channel index. */ int length; } guac_kubernetes_message; /** * Handles data received from Kubernetes over WebSocket, decoding the channel * index of the received data and forwarding that data accordingly. * * @param client * The guac_client associated with the connection to Kubernetes. * * @param buffer * The data received from Kubernetes. * * @param length * The size of the data received from Kubernetes, in bytes. */ void guac_kubernetes_receive_data(guac_client* client, const char* buffer, size_t length); /** * Requests that the given data be sent along the given channel to the * Kubernetes server when the WebSocket connection is next available for * writing. If the WebSocket connection has not been available for writing for * long enough that the outbound message buffer is full, the request to send * this particular message will be dropped. * * @param client * The guac_client associated with the Kubernetes connection. * * @param channel * The Kubernetes channel on which to send the message, * such as GUAC_KUBERNETES_CHANNEL_STDIN. * * @param data * A buffer containing the data to send. * * @param length * The number of bytes to send. */ void guac_kubernetes_send_message(guac_client* client, int channel, const char* data, int length); /** * Writes the oldest pending message within the outbound message queue, * as scheduled with guac_kubernetes_send_message(), removing that message * from the queue. This function MAY NOT be invoked outside the libwebsockets * event callback and MUST only be invoked in the context of a * LWS_CALLBACK_CLIENT_WRITEABLE event. If no messages are pending, this * function has no effect. * * @param client * The guac_client associated with the Kubernetes connection. * * @return * true if messages still remain to be written within the outbound message * queue, false otherwise. */ bool guac_kubernetes_write_pending_message(guac_client* client); #endif guacamole-server-1.3.0/src/libguac/0000755000175100001440000000000013772471155014163 500000000000000guacamole-server-1.3.0/src/libguac/encode-webp.c0000644000175100001440000001555313764613616016451 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "encode-webp.h" #include "guacamole/error.h" #include "guacamole/protocol.h" #include "guacamole/stream.h" #include "palette.h" #include #include #include #include #include #include #include /** * Structure which describes the current state of the WebP image writer. */ typedef struct guac_webp_stream_writer { /** * The socket over which all WebP blobs will be written. */ guac_socket* socket; /** * The Guacamole stream to associate with each WebP blob. */ guac_stream* stream; /** * Buffer of pending WebP data. */ char buffer[GUAC_PROTOCOL_BLOB_MAX_LENGTH]; /** * The number of bytes currently stored in the buffer. */ int buffer_size; } guac_webp_stream_writer; /** * Writes the contents of the WebP stream writer as a blob to its associated * socket. * * @param writer * The writer structure to flush. */ static void guac_webp_flush_data(guac_webp_stream_writer* writer) { /* Send blob */ guac_protocol_send_blob(writer->socket, writer->stream, writer->buffer, writer->buffer_size); /* Clear buffer */ writer->buffer_size = 0; } /** * Configures the given stream writer object to use the given Guacamole stream * object for WebP output. * * @param writer * The Guacamole WebP stream writer structure to configure. * * @param socket * The Guacamole socket to use when sending blob instructions. * * @param stream * The stream over which WebP-encoded blobs of image data should be sent. */ static void guac_webp_stream_writer_init(guac_webp_stream_writer* writer, guac_socket* socket, guac_stream* stream) { writer->buffer_size = 0; /* Store Guacamole-specific objects */ writer->socket = socket; writer->stream = stream; } /** * WebP output function which appends the given WebP data to the internal * buffer of the Guacamole stream writer structure, automatically flushing the * writer as necessary. * * @param data * The segment of data to write. * * @param data_size * The size of segment of data to write. * * @param picture * The WebP picture associated with this write operation. Provides access to * picture->custom_ptr which contains the Guacamole stream writer structure. * * @return * Non-zero if writing was successful, zero on failure. */ static int guac_webp_stream_write(const uint8_t* data, size_t data_size, const WebPPicture* picture) { guac_webp_stream_writer* const writer = (guac_webp_stream_writer*) picture->custom_ptr; assert(writer != NULL); const unsigned char* current = data; int length = data_size; /* Append all data given */ while (length > 0) { /* Calculate space remaining */ int remaining = sizeof(writer->buffer) - writer->buffer_size; /* If no space remains, flush buffer to make room */ if (remaining == 0) { guac_webp_flush_data(writer); remaining = sizeof(writer->buffer); } /* Calculate size of next block of data to append */ int block_size = remaining; if (block_size > length) block_size = length; /* Append block */ memcpy(writer->buffer + writer->buffer_size, current, block_size); /* Next block */ current += block_size; writer->buffer_size += block_size; length -= block_size; } return 1; } int guac_webp_write(guac_socket* socket, guac_stream* stream, cairo_surface_t* surface, int quality, int lossless) { guac_webp_stream_writer writer; WebPPicture picture; uint32_t* argb_output; int x, y; int width = cairo_image_surface_get_width(surface); int height = cairo_image_surface_get_height(surface); int stride = cairo_image_surface_get_stride(surface); cairo_format_t format = cairo_image_surface_get_format(surface); unsigned char* data = cairo_image_surface_get_data(surface); if (format != CAIRO_FORMAT_RGB24 && format != CAIRO_FORMAT_ARGB32) { guac_error = GUAC_STATUS_INTERNAL_ERROR; guac_error_message = "Invalid Cairo image format. Unable to create WebP."; return -1; } /* Flush pending operations to surface */ cairo_surface_flush(surface); /* Configure WebP compression bits */ WebPConfig config; if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, quality)) return -1; /* Add additional tuning */ config.lossless = lossless; config.quality = quality; config.thread_level = 1; /* Multi threaded */ config.method = 2; /* Compression method (0=fast/larger, 6=slow/smaller) */ /* Validate configuration */ WebPValidateConfig(&config); /* Set up WebP picture */ WebPPictureInit(&picture); picture.use_argb = 1; picture.width = width; picture.height = height; /* Allocate and init writer */ WebPPictureAlloc(&picture); picture.writer = guac_webp_stream_write; picture.custom_ptr = &writer; guac_webp_stream_writer_init(&writer, socket, stream); /* Copy image data into WebP picture */ argb_output = picture.argb; for (y = 0; y < height; y++) { /* Get pixels at start of each row */ uint32_t* src = (uint32_t*) data; uint32_t* dst = argb_output; /* For each pixel in row */ for (x = 0; x < width; x++) { /* Pull pixel data, removing alpha channel if necessary */ uint32_t src_pixel = *src; if (format != CAIRO_FORMAT_ARGB32) src_pixel |= 0xFF000000; /* Store converted pixel data */ *dst = src_pixel; /* Next pixel */ src++; dst++; } /* Next row */ data += stride; argb_output += picture.argb_stride; } /* Encode image */ WebPEncode(&config, &picture); /* Free picture */ WebPPictureFree(&picture); /* Ensure all data is written */ guac_webp_flush_data(&writer); return 0; } guacamole-server-1.3.0/src/libguac/wait-fd.c0000644000175100001440000000373313676721354015612 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #ifdef ENABLE_WINSOCK # include #else # ifdef HAVE_POLL # include # else # include # endif #endif #ifdef HAVE_POLL int guac_wait_for_fd(int fd, int usec_timeout) { /* Initialize with single underlying file descriptor */ struct pollfd fds[1] = {{ .fd = fd, .events = POLLIN, .revents = 0 }}; /* No timeout if usec_timeout is negative */ if (usec_timeout < 0) return poll(fds, 1, -1); /* Handle timeout if specified, rounding up to poll()'s granularity */ return poll(fds, 1, (usec_timeout + 999) / 1000); } #else int guac_wait_for_fd(int fd, int usec_timeout) { fd_set fds; /* Initialize fd_set with single underlying file descriptor */ FD_ZERO(&fds); FD_SET(fd, &fds); /* No timeout if usec_timeout is negative */ if (usec_timeout < 0) return select(fd + 1, &fds, NULL, NULL, NULL); /* Handle timeout if specified */ struct timeval timeout = { .tv_sec = usec_timeout / 1000000, .tv_usec = usec_timeout % 1000000 }; return select(fd + 1, &fds, NULL, NULL, &timeout); } #endif guacamole-server-1.3.0/src/libguac/error.c0000644000175100001440000002021613764613616015402 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/error.h" #include #include #include #ifdef HAVE_LIBPTHREAD #include #endif /* * Error strings */ const char* __GUAC_STATUS_SUCCESS_STR = "Success"; const char* __GUAC_STATUS_NO_MEMORY_STR = "Insufficient memory"; const char* __GUAC_STATUS_CLOSED_STR = "Closed"; const char* __GUAC_STATUS_TIMEOUT_STR = "Timed out"; const char* __GUAC_STATUS_IO_ERROR_STR = "Input/output error"; const char* __GUAC_STATUS_INVALID_ARGUMENT_STR = "Invalid argument"; const char* __GUAC_STATUS_INTERNAL_ERROR_STR = "Internal error"; const char* __GUAC_STATUS_UNKNOWN_STATUS_STR = "UNKNOWN STATUS CODE"; const char* __GUAC_STATUS_NO_SPACE_STR = "Insufficient space"; const char* __GUAC_STATUS_INPUT_TOO_LARGE_STR = "Input too large"; const char* __GUAC_STATUS_RESULT_TOO_LARGE_STR = "Result too large"; const char* __GUAC_STATUS_PERMISSION_DENIED_STR = "Permission denied"; const char* __GUAC_STATUS_BUSY_STR = "Resource busy"; const char* __GUAC_STATUS_NOT_AVAILABLE_STR = "Resource not available"; const char* __GUAC_STATUS_NOT_SUPPORTED_STR = "Not supported"; const char* __GUAC_STATUS_NOT_INPLEMENTED_STR = "Not implemented"; const char* __GUAC_STATUS_TRY_AGAIN_STR = "Temporary failure"; const char* __GUAC_STATUS_PROTOCOL_ERROR_STR = "Protocol violation"; const char* __GUAC_STATUS_NOT_FOUND_STR = "Not found"; const char* __GUAC_STATUS_CANCELED_STR = "Canceled"; const char* __GUAC_STATUS_OUT_OF_RANGE_STR = "Value out of range"; const char* __GUAC_STATUS_REFUSED_STR = "Operation refused"; const char* __GUAC_STATUS_TOO_MANY_STR = "Insufficient resources"; const char* __GUAC_STATUS_WOULD_BLOCK_STR = "Operation would block"; const char* guac_status_string(guac_status status) { switch (status) { /* No error */ case GUAC_STATUS_SUCCESS: return __GUAC_STATUS_SUCCESS_STR; /* Out of memory */ case GUAC_STATUS_NO_MEMORY: return __GUAC_STATUS_NO_MEMORY_STR; /* End of stream */ case GUAC_STATUS_CLOSED: return __GUAC_STATUS_CLOSED_STR; /* Timeout */ case GUAC_STATUS_TIMEOUT: return __GUAC_STATUS_TIMEOUT_STR; /* Further information in errno */ case GUAC_STATUS_SEE_ERRNO: return strerror(errno); /* Input/output error */ case GUAC_STATUS_IO_ERROR: return __GUAC_STATUS_IO_ERROR_STR; /* Invalid argument */ case GUAC_STATUS_INVALID_ARGUMENT: return __GUAC_STATUS_INVALID_ARGUMENT_STR; /* Internal error */ case GUAC_STATUS_INTERNAL_ERROR: return __GUAC_STATUS_INTERNAL_ERROR_STR; /* Out of space */ case GUAC_STATUS_NO_SPACE: return __GUAC_STATUS_NO_SPACE_STR; /* Input too large */ case GUAC_STATUS_INPUT_TOO_LARGE: return __GUAC_STATUS_INPUT_TOO_LARGE_STR; /* Result too large */ case GUAC_STATUS_RESULT_TOO_LARGE: return __GUAC_STATUS_RESULT_TOO_LARGE_STR; /* Permission denied */ case GUAC_STATUS_PERMISSION_DENIED: return __GUAC_STATUS_PERMISSION_DENIED_STR; /* Resource is busy */ case GUAC_STATUS_BUSY: return __GUAC_STATUS_BUSY_STR; /* Resource not available */ case GUAC_STATUS_NOT_AVAILABLE: return __GUAC_STATUS_NOT_AVAILABLE_STR; /* Not supported */ case GUAC_STATUS_NOT_SUPPORTED: return __GUAC_STATUS_NOT_SUPPORTED_STR; /* Not implemented */ case GUAC_STATUS_NOT_INPLEMENTED: return __GUAC_STATUS_NOT_INPLEMENTED_STR; /* Temporary failure */ case GUAC_STATUS_TRY_AGAIN: return __GUAC_STATUS_TRY_AGAIN_STR; /* Guacamole protocol error */ case GUAC_STATUS_PROTOCOL_ERROR: return __GUAC_STATUS_PROTOCOL_ERROR_STR; /* Resource not found */ case GUAC_STATUS_NOT_FOUND: return __GUAC_STATUS_NOT_FOUND_STR; /* Operation canceled */ case GUAC_STATUS_CANCELED: return __GUAC_STATUS_CANCELED_STR; /* Value out of range */ case GUAC_STATUS_OUT_OF_RANGE: return __GUAC_STATUS_OUT_OF_RANGE_STR; /* Operation refused */ case GUAC_STATUS_REFUSED: return __GUAC_STATUS_REFUSED_STR; /* Too many resource in use */ case GUAC_STATUS_TOO_MANY: return __GUAC_STATUS_TOO_MANY_STR; /* Operation would block */ case GUAC_STATUS_WOULD_BLOCK: return __GUAC_STATUS_WOULD_BLOCK_STR; /* Unknown status code */ default: return __GUAC_STATUS_UNKNOWN_STATUS_STR; } } #ifdef HAVE_LIBPTHREAD /* PThread implementation of __guac_error */ static pthread_key_t __guac_error_key; static pthread_once_t __guac_error_key_init = PTHREAD_ONCE_INIT; static pthread_key_t __guac_error_message_key; static pthread_once_t __guac_error_message_key_init = PTHREAD_ONCE_INIT; static void __guac_free_pointer(void* pointer) { /* Free memory allocated to status variable */ free(pointer); } static void __guac_alloc_error_key() { /* Create key, destroy any allocated variable on thread exit */ pthread_key_create(&__guac_error_key, __guac_free_pointer); } static void __guac_alloc_error_message_key() { /* Create key, destroy any allocated variable on thread exit */ pthread_key_create(&__guac_error_message_key, __guac_free_pointer); } guac_status* __guac_error() { /* Pointer for thread-local data */ guac_status* status; /* Init error key, if not already initialized */ pthread_once(&__guac_error_key_init, __guac_alloc_error_key); /* Retrieve thread-local status variable */ status = (guac_status*) pthread_getspecific(__guac_error_key); /* Allocate thread-local status variable if not already allocated */ if (status == NULL) { status = malloc(sizeof(guac_status)); pthread_setspecific(__guac_error_key, status); } return status; } const char** __guac_error_message() { /* Pointer for thread-local data */ const char** message; /* Init error message key, if not already initialized */ pthread_once( &__guac_error_message_key_init, __guac_alloc_error_message_key ); /* Retrieve thread-local message variable */ message = (const char**) pthread_getspecific(__guac_error_message_key); /* Allocate thread-local message variable if not already allocated */ if (message == NULL) { message = malloc(sizeof(const char*)); pthread_setspecific(__guac_error_message_key, message); } return message; } #else /* Default (not-threadsafe) implementation */ static guac_status __guac_error_unsafe_storage; static const char** __guac_error_message_unsafe_storage; guac_status* __guac_error() { return &__guac_error_unsafe_storage; } const char** __guac_error_message() { return &__guac_error_message_unsafe_storage; } /* Warn about threadsafety */ #warn No threadsafe implementation of __guac_error exists for your platform, so a default non-threadsafe implementation has been used instead. This may lead to incorrect status codes being reported for failures. Please consider adding support for your platform, or filing a bug report with the Guacamole project. #endif guacamole-server-1.3.0/src/libguac/socket-tee.c0000644000175100001440000001465113764613616016322 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/socket.h" #include /** * Data specific to the tee implementation of guac_socket. */ typedef struct guac_socket_tee_data { /** * The guac_socket to which all socket operations should be delegated. */ guac_socket* primary; /** * The guac_socket to which all write and flush operations should be * duplicated. */ guac_socket* secondary; } guac_socket_tee_data; /** * Callback function which reads only from the primary socket. * * @param socket * The tee socket to read from. * * @param buf * The buffer to read data into. * * @param count * The maximum number of bytes to read into the given buffer. * * @return * The value returned by guac_socket_read() when invoked on the primary * socket with the given parameters. */ static ssize_t __guac_socket_tee_read_handler(guac_socket* socket, void* buf, size_t count) { guac_socket_tee_data* data = (guac_socket_tee_data*) socket->data; /* Delegate read to wrapped socket */ return guac_socket_read(data->primary, buf, count); } /** * Callback function which writes the given data to both underlying sockets, * returning only the result from the primary socket. * * @param socket * The tee socket to write through. * * @param buf * The buffer of data to write. * * @param count * The number of bytes in the buffer to be written. * * @return * The number of bytes written if the write was successful, or -1 if an * error occurs. */ static ssize_t __guac_socket_tee_write_handler(guac_socket* socket, const void* buf, size_t count) { guac_socket_tee_data* data = (guac_socket_tee_data*) socket->data; /* Write to secondary socket (ignoring result) */ guac_socket_write(data->secondary, buf, count); /* Delegate write to wrapped socket */ if (guac_socket_write(data->primary, buf, count)) return -1; /* All data written successfully */ return count; } /** * Callback function which flushes both underlying sockets, returning only the * result from the primary socket. * * @param socket * The tee socket to flush. * * @return * The value returned by guac_socket_flush() when invoked on the primary * socket. */ static ssize_t __guac_socket_tee_flush_handler(guac_socket* socket) { guac_socket_tee_data* data = (guac_socket_tee_data*) socket->data; /* Flush secondary socket (ignoring result) */ guac_socket_flush(data->secondary); /* Delegate flush to wrapped socket */ return guac_socket_flush(data->primary); } /** * Callback function which delegates the lock operation to the primary * socket alone. * * @param socket * The tee socket on which guac_socket_instruction_begin() was invoked. */ static void __guac_socket_tee_lock_handler(guac_socket* socket) { guac_socket_tee_data* data = (guac_socket_tee_data*) socket->data; /* Delegate lock to wrapped sockets */ guac_socket_instruction_begin(data->primary); guac_socket_instruction_begin(data->secondary); } /** * Callback function which delegates the unlock operation to the primary * socket alone. * * @param socket * The tee socket on which guac_socket_instruction_end() was invoked. */ static void __guac_socket_tee_unlock_handler(guac_socket* socket) { guac_socket_tee_data* data = (guac_socket_tee_data*) socket->data; /* Delegate unlock to wrapped sockets */ guac_socket_instruction_end(data->secondary); guac_socket_instruction_end(data->primary); } /** * Callback function which delegates the select operation to the primary * socket alone. * * @param socket * The tee socket on which guac_socket_select() was invoked. * * @param usec_timeout * The timeout to specify when invoking guac_socket_select() on the * primary socket. * * @return * The value returned by guac_socket_select() when invoked with the * given parameters on the primary socket. */ static int __guac_socket_tee_select_handler(guac_socket* socket, int usec_timeout) { guac_socket_tee_data* data = (guac_socket_tee_data*) socket->data; /* Delegate select to wrapped socket */ return guac_socket_select(data->primary, usec_timeout); } /** * Callback function which frees all underlying data associated with the * given tee socket, including both primary and secondary sockets. * * @param socket * The tee socket being freed. * * @return * Always zero. */ static int __guac_socket_tee_free_handler(guac_socket* socket) { guac_socket_tee_data* data = (guac_socket_tee_data*) socket->data; /* Free underlying sockets */ guac_socket_free(data->primary); guac_socket_free(data->secondary); /* Freeing the tee socket always succeeds */ free(data); return 0; } guac_socket* guac_socket_tee(guac_socket* primary, guac_socket* secondary) { /* Set up socket to split outout into a file */ guac_socket_tee_data* data = malloc(sizeof(guac_socket_tee_data)); data->primary = primary; data->secondary = secondary; /* Associate tee-specific data with new socket */ guac_socket* socket = guac_socket_alloc(); socket->data = data; /* Assign handlers */ socket->read_handler = __guac_socket_tee_read_handler; socket->write_handler = __guac_socket_tee_write_handler; socket->select_handler = __guac_socket_tee_select_handler; socket->flush_handler = __guac_socket_tee_flush_handler; socket->lock_handler = __guac_socket_tee_lock_handler; socket->unlock_handler = __guac_socket_tee_unlock_handler; socket->free_handler = __guac_socket_tee_free_handler; return socket; } guacamole-server-1.3.0/src/libguac/encode-webp.h0000644000175100001440000000360613764613616016452 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_ENCODE_WEBP_H #define GUAC_ENCODE_WEBP_H #include "config.h" #include "guacamole/socket.h" #include "guacamole/stream.h" #include /** * Encodes the given surface as a WebP, and sends the resulting data over the * given stream and socket as blobs. * * @param socket * The socket to send WebP blobs over. * * @param stream * The stream to associate with each blob. * * @param surface * The Cairo surface to write to the given stream and socket as PNG blobs. * * @param quality * The WebP image quality to use. For lossy images, larger values indicate * improving quality at the expense of larger file size. For lossless * images, this dictates the quality of compression, with larger values * producing smaller files at the expense of speed. * * @param lossless * Zero for a lossy image, non-zero for lossless. * * @return * Zero if the encoding operation is successful, non-zero otherwise. */ int guac_webp_write(guac_socket* socket, guac_stream* stream, cairo_surface_t* surface, int quality, int lossless); #endif guacamole-server-1.3.0/src/libguac/argv.c0000644000175100001440000002327513770536337015221 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/argv.h" #include "guacamole/client.h" #include "guacamole/protocol.h" #include "guacamole/socket.h" #include "guacamole/stream.h" #include "guacamole/string.h" #include "guacamole/user.h" #include #include #include /** * The state of an argument that will be automatically processed. Note that * this is distinct from the state of an argument value that is currently being * processed. Argument value states are dynamically-allocated and scoped by the * associated guac_stream. */ typedef struct guac_argv_state { /** * The name of the argument. */ char name[GUAC_ARGV_MAX_NAME_LENGTH]; /** * Whether at least one value for this argument has been received since it * was registered. */ int received; /** * Bitwise OR of all option flags that should affect processing of this * argument. */ int options; /** * The callback that should be invoked when a new value for the associated * argument has been received. If the GUAC_ARGV_OPTION_ONCE flag is set, * the callback will be invoked at most once. */ guac_argv_callback* callback; /** * The arbitrary data that should be passed to the callback. */ void* data; } guac_argv_state; /** * The current state of automatic processing of "argv" streams. */ typedef struct guac_argv_await_state { /** * Whether automatic argument processing has been stopped via a call to * guac_argv_stop(). */ int stopped; /** * The total number of arguments registered. */ unsigned int num_registered; /** * All registered arguments and their corresponding callbacks. */ guac_argv_state registered[GUAC_ARGV_MAX_REGISTERED]; /** * Lock which protects multi-threaded access to this entire state * structure, including the condition that signals specific modifications * to the structure. */ pthread_mutex_t lock; /** * Condition which is signalled whenever the overall state of "argv" * processing changes, either through the receipt of a new argument value * or due to a call to guac_argv_stop(). */ pthread_cond_t changed; } guac_argv_await_state; /** * The value or current status of a connection parameter received over an * "argv" stream. */ typedef struct guac_argv { /** * The state of the specific setting being updated. */ guac_argv_state* state; /** * The mimetype of the data being received. */ char mimetype[GUAC_ARGV_MAX_MIMETYPE_LENGTH]; /** * Buffer space for containing the received argument value. */ char buffer[GUAC_ARGV_MAX_LENGTH]; /** * The number of bytes received so far. */ int length; } guac_argv; /** * Statically-allocated, shared state of the guac_argv_*() family of functions. */ static guac_argv_await_state await_state = { .lock = PTHREAD_MUTEX_INITIALIZER, .changed = PTHREAD_COND_INITIALIZER }; /** * Returns whether at least one value for each of the provided arguments has * been received. * * @param args * A NULL-terminated array of the names of all arguments to test. * * @return * Non-zero if at least one value has been received for each of the * provided arguments, zero otherwise. */ static int guac_argv_is_received(const char** args) { for (int i = 0; i < await_state.num_registered; i++) { /* Ignore all received arguments */ guac_argv_state* state = &await_state.registered[i]; if (state->received) continue; /* Fail immediately for any matching non-received arguments */ for (const char** arg = args; *arg != NULL; arg++) { if (strcmp(state->name, *arg) == 0) return 0; } } /* All arguments were received */ return 1; } int guac_argv_register(const char* name, guac_argv_callback* callback, void* data, int options) { pthread_mutex_lock(&await_state.lock); if (await_state.num_registered == GUAC_ARGV_MAX_REGISTERED) { pthread_mutex_unlock(&await_state.lock); return 1; } guac_argv_state* state = &await_state.registered[await_state.num_registered++]; guac_strlcpy(state->name, name, sizeof(state->name)); state->options = options; state->callback = callback; state->data = data; pthread_mutex_unlock(&await_state.lock); return 0; } int guac_argv_await(const char** args) { /* Wait for all requested arguments to be received (or for receipt to be * stopped) */ pthread_mutex_lock(&await_state.lock); while (!await_state.stopped && !guac_argv_is_received(args)) pthread_cond_wait(&await_state.changed, &await_state.lock); /* Arguments were successfully received only if receipt was not stopped */ int retval = await_state.stopped; pthread_mutex_unlock(&await_state.lock); return retval; } /** * Handler for "blob" instructions which appends the data from received blobs * to the end of the in-progress argument value buffer. * * @see guac_user_blob_handler */ static int guac_argv_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { guac_argv* argv = (guac_argv*) stream->data; /* Calculate buffer size remaining, including space for null terminator, * adjusting received length accordingly */ int remaining = sizeof(argv->buffer) - argv->length - 1; if (length > remaining) length = remaining; /* Append received data to end of buffer */ memcpy(argv->buffer + argv->length, data, length); argv->length += length; return 0; } /** * Handler for "end" instructions which applies the changes specified by the * argument value buffer associated with the stream. * * @see guac_user_end_handler */ static int guac_argv_end_handler(guac_user* user, guac_stream* stream) { int result = 0; /* Append null terminator to value */ guac_argv* argv = (guac_argv*) stream->data; argv->buffer[argv->length] = '\0'; pthread_mutex_lock(&await_state.lock); /* Invoke callback, limiting to a single invocation if * GUAC_ARGV_OPTION_ONCE applies */ guac_argv_state* state = argv->state; if (!(state->options & GUAC_ARGV_OPTION_ONCE) || !state->received) { if (state->callback != NULL) result = state->callback(user, argv->mimetype, state->name, argv->buffer, state->data); } /* Alert connected clients regarding newly-accepted values if echo is * enabled */ if (!result && (state->options & GUAC_ARGV_OPTION_ECHO)) { guac_client* client = user->client; guac_client_stream_argv(client, client->socket, argv->mimetype, state->name, argv->buffer); } /* Notify that argument has been received */ state->received = 1; pthread_cond_broadcast(&await_state.changed); pthread_mutex_unlock(&await_state.lock); free(argv); return 0; } int guac_argv_received(guac_stream* stream, const char* mimetype, const char* name) { pthread_mutex_lock(&await_state.lock); for (int i = 0; i < await_state.num_registered; i++) { /* Ignore any arguments that have already been received if they are * declared as being acceptable only once */ guac_argv_state* state = &await_state.registered[i]; if ((state->options & GUAC_ARGV_OPTION_ONCE) && state->received) continue; /* Argument matched */ if (strcmp(state->name, name) == 0) { guac_argv* argv = malloc(sizeof(guac_argv)); guac_strlcpy(argv->mimetype, mimetype, sizeof(argv->mimetype)); argv->state = state; argv->length = 0; stream->data = argv; stream->blob_handler = guac_argv_blob_handler; stream->end_handler = guac_argv_end_handler; pthread_mutex_unlock(&await_state.lock); return 0; } } /* No such argument awaiting processing */ pthread_mutex_unlock(&await_state.lock); return 1; } void guac_argv_stop() { pthread_mutex_lock(&await_state.lock); /* Signal any waiting threads that no further argument values will be * received */ if (!await_state.stopped) { await_state.stopped = 1; pthread_cond_broadcast(&await_state.changed); } pthread_mutex_unlock(&await_state.lock); } int guac_argv_handler(guac_user* user, guac_stream* stream, char* mimetype, char* name) { /* Refuse stream if argument is not registered */ if (guac_argv_received(stream, mimetype, name)) { guac_protocol_send_ack(user->socket, stream, "Not allowed.", GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); guac_socket_flush(user->socket); return 0; } /* Signal stream is ready */ guac_protocol_send_ack(user->socket, stream, "Ready for updated " "parameter.", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(user->socket); return 0; } guacamole-server-1.3.0/src/libguac/parser.c0000644000175100001440000002276313764613616015556 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/error.h" #include "guacamole/parser.h" #include "guacamole/socket.h" #include "guacamole/unicode.h" #include #include #include static void guac_parser_reset(guac_parser* parser) { parser->opcode = NULL; parser->argc = 0; parser->state = GUAC_PARSE_LENGTH; parser->__elementc = 0; parser->__element_length = 0; } guac_parser* guac_parser_alloc() { /* Allocate space for parser */ guac_parser* parser = malloc(sizeof(guac_parser)); if (parser == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; guac_error_message = "Insufficient memory to allocate parser"; return NULL; } /* Init parse start/end markers */ parser->__instructionbuf_unparsed_start = parser->__instructionbuf; parser->__instructionbuf_unparsed_end = parser->__instructionbuf; guac_parser_reset(parser); return parser; } int guac_parser_append(guac_parser* parser, void* buffer, int length) { char* char_buffer = (char*) buffer; int bytes_parsed = 0; /* Do not exceed maximum number of elements */ if (parser->__elementc == GUAC_INSTRUCTION_MAX_ELEMENTS && parser->state != GUAC_PARSE_COMPLETE) { parser->state = GUAC_PARSE_ERROR; return 0; } /* Parse element length */ if (parser->state == GUAC_PARSE_LENGTH) { int parsed_length = parser->__element_length; while (bytes_parsed < length) { /* Pull next character */ char c = *(char_buffer++); bytes_parsed++; /* If digit, add to length */ if (c >= '0' && c <= '9') parsed_length = parsed_length*10 + c - '0'; /* If period, switch to parsing content */ else if (c == '.') { parser->__elementv[parser->__elementc++] = char_buffer; parser->state = GUAC_PARSE_CONTENT; break; } /* If not digit, parse error */ else { parser->state = GUAC_PARSE_ERROR; return 0; } } /* If too long, parse error */ if (parsed_length > GUAC_INSTRUCTION_MAX_LENGTH) { parser->state = GUAC_PARSE_ERROR; return 0; } /* Save length */ parser->__element_length = parsed_length; } /* end parse length */ /* Parse element content */ if (parser->state == GUAC_PARSE_CONTENT) { while (bytes_parsed < length && parser->__element_length >= 0) { /* Get length of current character */ char c = *char_buffer; int char_length = guac_utf8_charsize((unsigned char) c); /* If full character not present in buffer, stop now */ if (char_length + bytes_parsed > length) break; /* Record character as parsed */ bytes_parsed += char_length; /* If end of element, handle terminator */ if (parser->__element_length == 0) { *char_buffer = '\0'; /* If semicolon, store end-of-instruction */ if (c == ';') { parser->state = GUAC_PARSE_COMPLETE; parser->opcode = parser->__elementv[0]; parser->argv = &(parser->__elementv[1]); parser->argc = parser->__elementc - 1; break; } /* If comma, move on to next element */ else if (c == ',') { parser->state = GUAC_PARSE_LENGTH; break; } /* Otherwise, parse error */ else { parser->state = GUAC_PARSE_ERROR; return 0; } } /* end if end of element */ /* Advance to next character */ parser->__element_length--; char_buffer += char_length; } } /* end parse content */ return bytes_parsed; } int guac_parser_read(guac_parser* parser, guac_socket* socket, int usec_timeout) { char* unparsed_end = parser->__instructionbuf_unparsed_end; char* unparsed_start = parser->__instructionbuf_unparsed_start; char* instr_start = parser->__instructionbuf_unparsed_start; char* buffer_end = parser->__instructionbuf + sizeof(parser->__instructionbuf); /* Begin next instruction if previous was ended */ if (parser->state == GUAC_PARSE_COMPLETE) guac_parser_reset(parser); while (parser->state != GUAC_PARSE_COMPLETE && parser->state != GUAC_PARSE_ERROR) { /* Add any available data to buffer */ int parsed = guac_parser_append(parser, unparsed_start, unparsed_end - unparsed_start); /* Read more data if not enough data to parse */ if (parsed == 0 && parser->state != GUAC_PARSE_ERROR) { int retval; /* If no space left to read, fail */ if (unparsed_end == buffer_end) { /* Shift backward if possible */ if (instr_start != parser->__instructionbuf) { int i; /* Shift buffer */ int offset = instr_start - parser->__instructionbuf; memmove(parser->__instructionbuf, instr_start, unparsed_end - instr_start); /* Update tracking pointers */ unparsed_end -= offset; unparsed_start -= offset; instr_start = parser->__instructionbuf; /* Update parsed elements, if any */ for (i=0; i < parser->__elementc; i++) parser->__elementv[i] -= offset; } /* Otherwise, no memory to read */ else { guac_error = GUAC_STATUS_NO_MEMORY; guac_error_message = "Instruction too long"; return -1; } } /* No instruction yet? Get more data ... */ retval = guac_socket_select(socket, usec_timeout); if (retval <= 0) return -1; /* Attempt to fill buffer */ retval = guac_socket_read(socket, unparsed_end, buffer_end - unparsed_end); /* Set guac_error if read unsuccessful */ if (retval < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Error filling instruction buffer"; return -1; } /* EOF */ if (retval == 0) { guac_error = GUAC_STATUS_CLOSED; guac_error_message = "End of stream reached while " "reading instruction"; return -1; } /* Update internal buffer */ unparsed_end += retval; } /* If data was parsed, advance buffer */ else unparsed_start += parsed; } /* end while parsing data */ /* Fail on error */ if (parser->state == GUAC_PARSE_ERROR) { guac_error = GUAC_STATUS_PROTOCOL_ERROR; guac_error_message = "Instruction parse error"; return -1; } parser->__instructionbuf_unparsed_start = unparsed_start; parser->__instructionbuf_unparsed_end = unparsed_end; return 0; } int guac_parser_expect(guac_parser* parser, guac_socket* socket, int usec_timeout, const char* opcode) { /* Read next instruction */ if (guac_parser_read(parser, socket, usec_timeout) != 0) return -1; /* Validate instruction */ if (strcmp(parser->opcode, opcode) != 0) { guac_error = GUAC_STATUS_PROTOCOL_ERROR; guac_error_message = "Instruction read did not have expected opcode"; return -1; } /* Return non-zero only if valid instruction read */ return parser->state != GUAC_PARSE_COMPLETE; } int guac_parser_length(guac_parser* parser) { char* unparsed_end = parser->__instructionbuf_unparsed_end; char* unparsed_start = parser->__instructionbuf_unparsed_start; return unparsed_end - unparsed_start; } int guac_parser_shift(guac_parser* parser, void* buffer, int length) { char* copy_end = parser->__instructionbuf_unparsed_end; char* copy_start = parser->__instructionbuf_unparsed_start; /* Contain copy region within length */ if (copy_end - copy_start > length) copy_end = copy_start + length; /* Copy buffer */ length = copy_end - copy_start; memcpy(buffer, copy_start, length); parser->__instructionbuf_unparsed_start = copy_end; return length; } void guac_parser_free(guac_parser* parser) { free(parser); } guacamole-server-1.3.0/src/libguac/id.h0000644000175100001440000000260513613156714014646 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_ID_H #define __GUAC_ID_H /** * Generates a guaranteed-unique identifier which is a total of 37 characters * long, having the given single-character prefix. The resulting identifier * must be freed with a call to free() when no longer needed. If an error * occurs, NULL is returned, no memory is allocated, and guac_error is set * appropriately. * * @param prefix The single-character prefix to use. * @return A newly-allocated unique identifier with the given prefix, or * NULL if the identifier could not be generated. */ char* guac_generate_id(char prefix); #endif guacamole-server-1.3.0/src/libguac/socket-fd.c0000644000175100001440000003010013764613616016121 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/error.h" #include "guacamole/socket.h" #include "wait-fd.h" #include #include #include #include #include #include #include #ifdef ENABLE_WINSOCK #include #endif /** * Data associated with an open socket which writes to a file descriptor. */ typedef struct guac_socket_fd_data { /** * The associated file descriptor; */ int fd; /** * The number of bytes currently in the main write buffer. */ int written; /** * The main write buffer. Bytes written go here before being flushed * to the open file descriptor. */ char out_buf[GUAC_SOCKET_OUTPUT_BUFFER_SIZE]; /** * Lock which is acquired when an instruction is being written, and * released when the instruction is finished being written. */ pthread_mutex_t socket_lock; /** * Lock which protects access to the internal buffer of this socket, * guaranteeing atomicity of writes and flushes. */ pthread_mutex_t buffer_lock; } guac_socket_fd_data; /** * Writes the entire contents of the given buffer to the file descriptor * associated with the given socket, retrying as necessary until the whole * buffer is written, and aborting if an error occurs. * * @param socket * The guac_socket associated with the file descriptor to which the given * buffer should be written. * * @param buf * The buffer of data to write to the given guac_socket. * * @param count * The number of bytes within the given buffer. * * @return * The number of bytes written, which will be exactly the size of the given * buffer, or a negative value if an error occurs. */ ssize_t guac_socket_fd_write(guac_socket* socket, const void* buf, size_t count) { guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; const char* buffer = buf; /* Write until completely written */ while (count > 0) { int retval; #ifdef ENABLE_WINSOCK /* WSA only works with send() */ retval = send(data->fd, buffer, count, 0); #else /* Use write() for all other platforms */ retval = write(data->fd, buffer, count); #endif /* Record errors in guac_error */ if (retval < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Error writing data to socket"; return retval; } /* Advance buffer to next chunk */ buffer += retval; count -= retval; } return 0; } /** * Attempts to read from the underlying file descriptor of the given * guac_socket, populating the given buffer. * * @param socket * The guac_socket being read from. * * @param buf * The arbitrary buffer which we must populate with data. * * @param count * The maximum number of bytes to read into the buffer. * * @return * The number of bytes read, or -1 if an error occurs. */ static ssize_t guac_socket_fd_read_handler(guac_socket* socket, void* buf, size_t count) { guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; int retval; #ifdef ENABLE_WINSOCK /* Winsock only works with recv() */ retval = recv(data->fd, buf, count, 0); #else /* Use read() for all other platforms */ retval = read(data->fd, buf, count); #endif /* Record errors in guac_error */ if (retval < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Error reading data from socket"; } return retval; } /** * Flushes the contents of the output buffer of the given socket immediately, * without first locking access to the output buffer. This function must ONLY * be called if the buffer lock has already been acquired. * * @param socket * The guac_socket to flush. * * @return * Zero if the flush operation was successful, non-zero otherwise. */ static ssize_t guac_socket_fd_flush(guac_socket* socket) { guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; /* Flush remaining bytes in buffer */ if (data->written > 0) { /* Write ALL bytes in buffer immediately */ if (guac_socket_fd_write(socket, data->out_buf, data->written)) return 1; data->written = 0; } return 0; } /** * Flushes the internal buffer of the given guac_socket, writing all data * to the underlying file descriptor. * * @param socket * The guac_socket to flush. * * @return * Zero if the flush operation was successful, non-zero otherwise. */ static ssize_t guac_socket_fd_flush_handler(guac_socket* socket) { int retval; guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; /* Acquire exclusive access to buffer */ pthread_mutex_lock(&(data->buffer_lock)); /* Flush contents of buffer */ retval = guac_socket_fd_flush(socket); /* Relinquish exclusive access to buffer */ pthread_mutex_unlock(&(data->buffer_lock)); return retval; } /** * Writes the contents of the buffer to the output buffer of the given socket, * flushing the output buffer as necessary, without first locking access to the * output buffer. This function must ONLY be called if the buffer lock has * already been acquired. * * @param socket * The guac_socket to write the given buffer to. * * @param buf * The buffer to write to the given socket. * * @param count * The number of bytes in the given buffer. * * @return * The number of bytes written, or a negative value if an error occurs * during write. */ static ssize_t guac_socket_fd_write_buffered(guac_socket* socket, const void* buf, size_t count) { size_t original_count = count; const char* current = buf; guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; /* Append to buffer, flush if necessary */ while (count > 0) { int chunk_size; int remaining = sizeof(data->out_buf) - data->written; /* If no space left in buffer, flush and retry */ if (remaining == 0) { /* Abort if error occurs during flush */ if (guac_socket_fd_flush(socket)) return -1; /* Retry buffer append */ continue; } /* Calculate size of chunk to be written to buffer */ chunk_size = count; if (chunk_size > remaining) chunk_size = remaining; /* Update output buffer */ memcpy(data->out_buf + data->written, current, chunk_size); data->written += chunk_size; /* Update provided buffer */ current += chunk_size; count -= chunk_size; } /* All bytes have been written, possibly some to the internal buffer */ return original_count; } /** * Appends the provided data to the internal buffer for future writing. The * actual write attempt will occur only upon flush, or when the internal buffer * is full. * * @param socket * The guac_socket being write to. * * @param buf * The arbitrary buffer containing the data to be written. * * @param count * The number of bytes contained within the buffer. * * @return * The number of bytes written, or -1 if an error occurs. */ static ssize_t guac_socket_fd_write_handler(guac_socket* socket, const void* buf, size_t count) { int retval; guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; /* Acquire exclusive access to buffer */ pthread_mutex_lock(&(data->buffer_lock)); /* Write provided data to buffer */ retval = guac_socket_fd_write_buffered(socket, buf, count); /* Relinquish exclusive access to buffer */ pthread_mutex_unlock(&(data->buffer_lock)); return retval; } /** * Waits for data on the underlying file desriptor of the given socket to * become available such that the next read operation will not block. * * @param socket * The guac_socket to wait for. * * @param usec_timeout * The maximum amount of time to wait for data, in microseconds, or -1 to * potentially wait forever. * * @return * A positive value on success, zero if the timeout elapsed and no data is * available, or a negative value if an error occurs. */ static int guac_socket_fd_select_handler(guac_socket* socket, int usec_timeout) { /* Wait for data on socket */ guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; int retval = guac_wait_for_fd(data->fd, usec_timeout); /* Properly set guac_error */ if (retval < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Error while waiting for data on socket"; } else if (retval == 0) { guac_error = GUAC_STATUS_TIMEOUT; guac_error_message = "Timeout while waiting for data on socket"; } return retval; } /** * Frees all implementation-specific data associated with the given socket, but * not the socket object itself. * * @param socket * The guac_socket whose associated data should be freed. * * @return * Zero if the data was successfully freed, non-zero otherwise. This * implementation always succeeds, and will always return zero. */ static int guac_socket_fd_free_handler(guac_socket* socket) { guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; /* Destroy locks */ pthread_mutex_destroy(&(data->socket_lock)); pthread_mutex_destroy(&(data->buffer_lock)); /* Close file descriptor */ close(data->fd); free(data); return 0; } /** * Acquires exclusive access to the given socket. * * @param socket * The guac_socket to which exclusive access is required. */ static void guac_socket_fd_lock_handler(guac_socket* socket) { guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; /* Acquire exclusive access to socket */ pthread_mutex_lock(&(data->socket_lock)); } /** * Relinquishes exclusive access to the given socket. * * @param socket * The guac_socket to which exclusive access is no longer required. */ static void guac_socket_fd_unlock_handler(guac_socket* socket) { guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; /* Relinquish exclusive access to socket */ pthread_mutex_unlock(&(data->socket_lock)); } guac_socket* guac_socket_open(int fd) { pthread_mutexattr_t lock_attributes; /* Allocate socket and associated data */ guac_socket* socket = guac_socket_alloc(); guac_socket_fd_data* data = malloc(sizeof(guac_socket_fd_data)); /* Store file descriptor as socket data */ data->fd = fd; data->written = 0; socket->data = data; pthread_mutexattr_init(&lock_attributes); pthread_mutexattr_setpshared(&lock_attributes, PTHREAD_PROCESS_SHARED); /* Init locks */ pthread_mutex_init(&(data->socket_lock), &lock_attributes); pthread_mutex_init(&(data->buffer_lock), &lock_attributes); /* Set read/write handlers */ socket->read_handler = guac_socket_fd_read_handler; socket->write_handler = guac_socket_fd_write_handler; socket->select_handler = guac_socket_fd_select_handler; socket->lock_handler = guac_socket_fd_lock_handler; socket->unlock_handler = guac_socket_fd_unlock_handler; socket->flush_handler = guac_socket_fd_flush_handler; socket->free_handler = guac_socket_fd_free_handler; return socket; } guacamole-server-1.3.0/src/libguac/id.c0000644000175100001440000000451013764613616014644 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/error.h" #include "id.h" #ifdef HAVE_OSSP_UUID_H #include #else #include #endif #include char* guac_generate_id(char prefix) { char* buffer; char* identifier; size_t identifier_length; uuid_t* uuid; /* Attempt to create UUID object */ if (uuid_create(&uuid) != UUID_RC_OK) { guac_error = GUAC_STATUS_NO_MEMORY; guac_error_message = "Could not allocate memory for UUID"; return NULL; } /* Generate random UUID */ if (uuid_make(uuid, UUID_MAKE_V4) != UUID_RC_OK) { uuid_destroy(uuid); guac_error = GUAC_STATUS_NO_MEMORY; guac_error_message = "UUID generation failed"; return NULL; } /* Allocate buffer for future formatted ID */ buffer = malloc(UUID_LEN_STR + 2); if (buffer == NULL) { uuid_destroy(uuid); guac_error = GUAC_STATUS_NO_MEMORY; guac_error_message = "Could not allocate memory for connection ID"; return NULL; } identifier = &(buffer[1]); identifier_length = UUID_LEN_STR + 1; /* Build connection ID from UUID */ if (uuid_export(uuid, UUID_FMT_STR, &identifier, &identifier_length) != UUID_RC_OK) { free(buffer); uuid_destroy(uuid); guac_error = GUAC_STATUS_INTERNAL_ERROR; guac_error_message = "Conversion of UUID to connection ID failed"; return NULL; } uuid_destroy(uuid); buffer[0] = prefix; buffer[UUID_LEN_STR + 1] = '\0'; return buffer; } guacamole-server-1.3.0/src/libguac/raw_encoder.c0000644000175100001440000001100713764613616016537 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/audio.h" #include "guacamole/client.h" #include "guacamole/protocol.h" #include "guacamole/socket.h" #include "guacamole/user.h" #include "raw_encoder.h" #include #include #include static void raw_encoder_send_audio(guac_audio_stream* audio, guac_socket* socket) { char mimetype[256]; /* Produce mimetype string from format info */ snprintf(mimetype, sizeof(mimetype), "audio/L%i;rate=%i,channels=%i", audio->bps, audio->rate, audio->channels); /* Associate stream */ guac_protocol_send_audio(socket, audio->stream, mimetype); } static void raw_encoder_begin_handler(guac_audio_stream* audio) { raw_encoder_state* state; /* Broadcast existence of stream */ raw_encoder_send_audio(audio, audio->client->socket); /* Allocate and init encoder state */ audio->data = state = malloc(sizeof(raw_encoder_state)); state->written = 0; state->length = GUAC_RAW_ENCODER_BUFFER_SIZE * audio->rate * audio->channels * audio->bps / 8 / 1000; state->buffer = malloc(state->length); } static void raw_encoder_join_handler(guac_audio_stream* audio, guac_user* user) { /* Notify user of existence of stream */ raw_encoder_send_audio(audio, user->socket); } static void raw_encoder_end_handler(guac_audio_stream* audio) { raw_encoder_state* state = (raw_encoder_state*) audio->data; /* Send end of stream */ guac_protocol_send_end(audio->client->socket, audio->stream); /* Free state information */ free(state->buffer); free(state); } static void raw_encoder_write_handler(guac_audio_stream* audio, const unsigned char* pcm_data, int length) { raw_encoder_state* state = (raw_encoder_state*) audio->data; while (length > 0) { /* Prefer to copy a chunk of equal size to available buffer space */ int chunk_size = state->length - state->written; /* If no space remains, flush and retry */ if (chunk_size == 0) { guac_audio_stream_flush(audio); continue; } /* Do not copy more data than is available in source PCM */ if (chunk_size > length) chunk_size = length; /* Copy block of PCM data into buffer */ memcpy(state->buffer + state->written, pcm_data, chunk_size); /* Advance to next block */ state->written += chunk_size; pcm_data += chunk_size; length -= chunk_size; } } static void raw_encoder_flush_handler(guac_audio_stream* audio) { raw_encoder_state* state = (raw_encoder_state*) audio->data; guac_socket* socket = audio->client->socket; guac_stream* stream = audio->stream; /* Flush all data in buffer as blobs */ guac_protocol_send_blobs(socket, stream, state->buffer, state->written); /* All data has been flushed */ state->written = 0; } /* 8-bit raw encoder handlers */ guac_audio_encoder _raw8_encoder = { .mimetype = "audio/L8", .begin_handler = raw_encoder_begin_handler, .write_handler = raw_encoder_write_handler, .flush_handler = raw_encoder_flush_handler, .join_handler = raw_encoder_join_handler, .end_handler = raw_encoder_end_handler }; /* 16-bit raw encoder handlers */ guac_audio_encoder _raw16_encoder = { .mimetype = "audio/L16", .begin_handler = raw_encoder_begin_handler, .write_handler = raw_encoder_write_handler, .flush_handler = raw_encoder_flush_handler, .join_handler = raw_encoder_join_handler, .end_handler = raw_encoder_end_handler }; /* Actual encoder definitions */ guac_audio_encoder* raw8_encoder = &_raw8_encoder; guac_audio_encoder* raw16_encoder = &_raw16_encoder; guacamole-server-1.3.0/src/libguac/palette.h0000644000175100001440000000242213613156714015705 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_PALETTE_H #define __GUAC_PALETTE_H #include #include typedef struct guac_palette_entry { int index; int color; } guac_palette_entry; typedef struct guac_palette { guac_palette_entry entries[0x1000]; png_color colors[256]; int size; } guac_palette; guac_palette* guac_palette_alloc(cairo_surface_t* surface); int guac_palette_find(guac_palette* palette, int color); void guac_palette_free(guac_palette* palette); #endif guacamole-server-1.3.0/src/libguac/protocol.c0000644000175100001440000012037113770536337016116 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/error.h" #include "guacamole/layer.h" #include "guacamole/object.h" #include "guacamole/protocol.h" #include "guacamole/protocol-types.h" #include "guacamole/socket.h" #include "guacamole/stream.h" #include "guacamole/unicode.h" #include "palette.h" #include #include #include #include #include #include #include #include #include /** * A structure mapping the enum value of a Guacamole protocol version to the * string representation of the version. */ typedef struct guac_protocol_version_mapping { /** * The enum value of the protocol version. */ guac_protocol_version version; /** * The string value representing the protocol version. */ char* version_string; } guac_protocol_version_mapping; /** * The map of known protocol versions to the corresponding string value. */ guac_protocol_version_mapping guac_protocol_version_table[] = { { GUAC_PROTOCOL_VERSION_1_0_0, "VERSION_1_0_0" }, { GUAC_PROTOCOL_VERSION_1_1_0, "VERSION_1_1_0" }, { GUAC_PROTOCOL_VERSION_1_3_0, "VERSION_1_3_0" }, { GUAC_PROTOCOL_VERSION_UNKNOWN, NULL } }; /* Output formatting functions */ ssize_t __guac_socket_write_length_string(guac_socket* socket, const char* str) { return guac_socket_write_int(socket, guac_utf8_strlen(str)) || guac_socket_write_string(socket, ".") || guac_socket_write_string(socket, str); } ssize_t __guac_socket_write_length_int(guac_socket* socket, int64_t i) { char buffer[128]; snprintf(buffer, sizeof(buffer), "%"PRIi64, i); return __guac_socket_write_length_string(socket, buffer); } ssize_t __guac_socket_write_length_double(guac_socket* socket, double d) { char buffer[128]; snprintf(buffer, sizeof(buffer), "%.16g", d); return __guac_socket_write_length_string(socket, buffer); } /** * Loop through the provided NULL-terminated array, writing the values in the * array to the given socket. Values are written as a series of Guacamole * protocol elements, including the leading comma and the value length in * addition to the value itself. Returns zero on success, non-zero on error. * * @param socket * The socket to which the data should be written. * * @param array * The NULL-terminated array of values to write. * * @return * Zero on success, non-zero on error. */ static int guac_socket_write_array(guac_socket* socket, const char** array) { /* Loop through array, writing provided values to the socket. */ for (int i=0; array[i] != NULL; i++) { if (guac_socket_write_string(socket, ",")) return -1; if (__guac_socket_write_length_string(socket, array[i])) return -1; } return 0; } /* Protocol functions */ int guac_protocol_send_ack(guac_socket* socket, guac_stream* stream, const char* error, guac_protocol_status status) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "3.ack,") || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, error) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, status) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } static int __guac_protocol_send_args(guac_socket* socket, const char** args) { if (guac_socket_write_string(socket, "4.args")) return -1; /* Send protocol version ahead of other args. */ if (guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, GUACAMOLE_PROTOCOL_VERSION)) return -1; if (guac_socket_write_array(socket, args)) return -1; return guac_socket_write_string(socket, ";"); } int guac_protocol_send_args(guac_socket* socket, const char** args) { int ret_val; guac_socket_instruction_begin(socket); ret_val = __guac_protocol_send_args(socket, args); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_argv(guac_socket* socket, guac_stream* stream, const char* mimetype, const char* name) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.argv,") || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, name) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, int x, int y, int radius, double startAngle, double endAngle, int negative) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "3.arc,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, x) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, y) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, radius) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, startAngle) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, endAngle) || guac_socket_write_string(socket, ",") || guac_socket_write_string(socket, negative ? "1.1" : "1.0") || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_audio(guac_socket* socket, const guac_stream* stream, const char* mimetype) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "5.audio,") || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_blob(guac_socket* socket, const guac_stream* stream, const void* data, int count) { int base64_length = (count + 2) / 3 * 4; int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.blob,") || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || guac_socket_write_int(socket, base64_length) || guac_socket_write_string(socket, ".") || guac_socket_write_base64(socket, data, count) || guac_socket_flush_base64(socket) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_blobs(guac_socket* socket, const guac_stream* stream, const void* data, int count) { int ret_val = 0; /* Send blob instructions while data remains and instructions are being * sent successfully */ while (count > 0 && ret_val == 0) { /* Limit blob size to maximum allowed */ int blob_size = count; if (blob_size > GUAC_PROTOCOL_BLOB_MAX_LENGTH) blob_size = GUAC_PROTOCOL_BLOB_MAX_LENGTH; /* Send next blob of data */ ret_val = guac_protocol_send_blob(socket, stream, data, blob_size); /* Advance to next blob */ data = (const char*) data + blob_size; count -= blob_size; } return ret_val; } int guac_protocol_send_body(guac_socket* socket, const guac_object* object, const guac_stream* stream, const char* mimetype, const char* name) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.body,") || __guac_socket_write_length_int(socket, object->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, name) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_cfill(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int r, int g, int b, int a) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "5.cfill,") || __guac_socket_write_length_int(socket, mode) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, r) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, g) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, b) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, a) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_close(guac_socket* socket, const guac_layer* layer) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "5.close,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } static int __guac_protocol_send_connect(guac_socket* socket, const char** args) { if (guac_socket_write_string(socket, "7.connect")) return -1; if (guac_socket_write_array(socket, args)) return -1; return guac_socket_write_string(socket, ";"); } int guac_protocol_send_connect(guac_socket* socket, const char** args) { int ret_val; guac_socket_instruction_begin(socket); ret_val = __guac_protocol_send_connect(socket, args); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.clip,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_clipboard(guac_socket* socket, const guac_stream* stream, const char* mimetype) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "9.clipboard,") || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_copy(guac_socket* socket, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.copy,") || __guac_socket_write_length_int(socket, srcl->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, srcx) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, srcy) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, w) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, h) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, mode) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, dstl->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, dstx) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, dsty) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_cstroke(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, guac_line_cap_style cap, guac_line_join_style join, int thickness, int r, int g, int b, int a) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "7.cstroke,") || __guac_socket_write_length_int(socket, mode) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, cap) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, join) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, thickness) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, r) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, g) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, b) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, a) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_cursor(guac_socket* socket, int x, int y, const guac_layer* srcl, int srcx, int srcy, int w, int h) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "6.cursor,") || __guac_socket_write_length_int(socket, x) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, y) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, srcl->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, srcx) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, srcy) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, w) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, h) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_curve(guac_socket* socket, const guac_layer* layer, int cp1x, int cp1y, int cp2x, int cp2y, int x, int y) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "5.curve,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, cp1x) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, cp1y) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, cp2x) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, cp2y) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, x) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, y) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_disconnect(guac_socket* socket) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "10.disconnect;"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_dispose(guac_socket* socket, const guac_layer* layer) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "7.dispose,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_distort(guac_socket* socket, const guac_layer* layer, double a, double b, double c, double d, double e, double f) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "7.distort,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, a) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, b) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, c) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, d) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, e) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, f) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_end(guac_socket* socket, const guac_stream* stream) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "3.end,") || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_error(guac_socket* socket, const char* error, guac_protocol_status status) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "5.error,") || __guac_socket_write_length_string(socket, error) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, status) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int vguac_protocol_send_log(guac_socket* socket, const char* format, va_list args) { int ret_val; /* Copy log message into buffer */ char message[4096]; vsnprintf(message, sizeof(message), format, args); /* Log to instruction */ guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "3.log,") || __guac_socket_write_length_string(socket, message) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_log(guac_socket* socket, const char* format, ...) { int ret_val; va_list args; va_start(args, format); ret_val = vguac_protocol_send_log(socket, format, args); va_end(args); return ret_val; } int guac_protocol_send_file(guac_socket* socket, const guac_stream* stream, const char* mimetype, const char* name) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.file,") || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, name) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_filesystem(guac_socket* socket, const guac_object* object, const char* name) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "10.filesystem,") || __guac_socket_write_length_int(socket, object->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, name) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_identity(guac_socket* socket, const guac_layer* layer) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "8.identity,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_key(guac_socket* socket, int keysym, int pressed, guac_timestamp timestamp) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "3.key,") || __guac_socket_write_length_int(socket, keysym) || guac_socket_write_string(socket, pressed ? ",1.1," : ",1.0,") || __guac_socket_write_length_int(socket, timestamp) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_lfill(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, const guac_layer* srcl) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "5.lfill,") || __guac_socket_write_length_int(socket, mode) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, srcl->index) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_line(guac_socket* socket, const guac_layer* layer, int x, int y) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.line,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, x) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, y) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_lstroke(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, guac_line_cap_style cap, guac_line_join_style join, int thickness, const guac_layer* srcl) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "7.lstroke,") || __guac_socket_write_length_int(socket, mode) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, cap) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, join) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, thickness) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, srcl->index) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_mouse(guac_socket* socket, int x, int y, int button_mask, guac_timestamp timestamp) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "5.mouse,") || __guac_socket_write_length_int(socket, x) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, y) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, button_mask) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, timestamp) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer, const guac_layer* parent, int x, int y, int z) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.move,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, parent->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, x) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, y) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, z) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_name(guac_socket* socket, const char* name) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.name,") || __guac_socket_write_length_string(socket, name) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_nest(guac_socket* socket, int index, const char* data) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.nest,") || __guac_socket_write_length_int(socket, index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, data) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_nop(guac_socket* socket) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "3.nop;"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_pipe(guac_socket* socket, const guac_stream* stream, const char* mimetype, const char* name) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.pipe,") || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, name) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_img(guac_socket* socket, const guac_stream* stream, guac_composite_mode mode, const guac_layer* layer, const char* mimetype, int x, int y) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "3.img,") || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, mode) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, x) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, y) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_pop(guac_socket* socket, const guac_layer* layer) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "3.pop,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_push(guac_socket* socket, const guac_layer* layer) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.push,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_ready(guac_socket* socket, const char* id) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "5.ready,") || __guac_socket_write_length_string(socket, id) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_rect(guac_socket* socket, const guac_layer* layer, int x, int y, int width, int height) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.rect,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, x) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, y) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, width) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, height) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_required(guac_socket* socket, const char** required) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "8.required") || guac_socket_write_array(socket, required) || guac_socket_write_string(socket, ";") || guac_socket_flush(socket); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_reset(guac_socket* socket, const guac_layer* layer) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "5.reset,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_set(guac_socket* socket, const guac_layer* layer, const char* name, const char* value) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "3.set,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, name) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, value) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_select(guac_socket* socket, const char* protocol) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "6.select,") || __guac_socket_write_length_string(socket, protocol) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_shade(guac_socket* socket, const guac_layer* layer, int a) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "5.shade,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, a) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, int w, int h) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.size,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, w) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, h) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_start(guac_socket* socket, const guac_layer* layer, int x, int y) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "5.start,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, x) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, y) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.sync,") || __guac_socket_write_length_int(socket, timestamp) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_transfer(guac_socket* socket, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_transfer_function fn, const guac_layer* dstl, int dstx, int dsty) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "8.transfer,") || __guac_socket_write_length_int(socket, srcl->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, srcx) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, srcy) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, w) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, h) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, fn) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, dstl->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, dstx) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, dsty) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_transform(guac_socket* socket, const guac_layer* layer, double a, double b, double c, double d, double e, double f) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "9.transform,") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, a) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, b) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, c) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, d) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, e) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, f) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_undefine(guac_socket* socket, const guac_object* object) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "8.undefine,") || __guac_socket_write_length_int(socket, object->index) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } int guac_protocol_send_video(guac_socket* socket, const guac_stream* stream, const guac_layer* layer, const char* mimetype) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "5.video,") || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); return ret_val; } /** * Returns the value of a single base64 character. */ static int __guac_base64_value(char c) { if (c >= 'A' && c <= 'Z') return c - 'A'; if (c >= 'a' && c <= 'z') return c - 'a' + 26; if (c >= '0' && c <= '9') return c - '0' + 52; if (c == '+') return 62; if (c == '/') return 63; return 0; } int guac_protocol_decode_base64(char* base64) { char* input = base64; char* output = base64; int length = 0; int bits_read = 0; int value = 0; char current; /* For all characters in string */ while ((current = *(input++)) != 0) { /* If we've reached padding, then we're done */ if (current == '=') break; /* Otherwise, shift on the latest 6 bits */ value = (value << 6) | __guac_base64_value(current); bits_read += 6; /* If we have at least one byte, write out the latest whole byte */ if (bits_read >= 8) { *(output++) = (value >> (bits_read % 8)) & 0xFF; bits_read -= 8; length++; } } /* Return number of bytes written */ return length; } guac_protocol_version guac_protocol_string_to_version(const char* version_string) { guac_protocol_version_mapping* current = guac_protocol_version_table; while (current->version != GUAC_PROTOCOL_VERSION_UNKNOWN) { if (strcmp(current->version_string, version_string) == 0) return current->version; current++; } return GUAC_PROTOCOL_VERSION_UNKNOWN; } const char* guac_protocol_version_to_string(guac_protocol_version version) { guac_protocol_version_mapping* current = guac_protocol_version_table; while (current->version != GUAC_PROTOCOL_VERSION_UNKNOWN) { if (current->version == version) return (const char*) current->version_string; current++; } return NULL; } guacamole-server-1.3.0/src/libguac/hash.c0000644000175100001440000000720513721010341015152 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include #include #include /* * Arbitrary hash function whhich maps ALL 32-bit numbers onto 24-bit numbers * evenly, while guaranteeing that all 24-bit numbers are mapped onto * themselves. */ unsigned int _guac_hash_32to24(unsigned int value) { /* Grab highest-order byte */ unsigned int upper = value & 0xFF000000; /* XOR upper with lower three bytes, truncate to 24-bit */ return (value & 0xFFFFFF) ^ (upper >> 8) ^ (upper >> 16) ^ (upper >> 24); } /** * Rotates a given 32-bit integer by N bits. * * NOTE: We probably should check for available bitops.h macros first. */ unsigned int _guac_rotate(unsigned int value, int amount) { /* amount = amount % 32 */ amount &= 0x1F; /* Return rotated amount */ return (value >> amount) | (value << (32 - amount)); } unsigned int guac_hash_surface(cairo_surface_t* surface) { /* Init to zero */ unsigned int hash_value = 0; int x, y; /* Get image data and metrics */ unsigned char* data = cairo_image_surface_get_data(surface); int width = cairo_image_surface_get_width(surface); int height = cairo_image_surface_get_height(surface); int stride = cairo_image_surface_get_stride(surface); for (y=0; y #include #include /** * Test which verifies that conversion of the guac_protocol_version enum to * string values succeeds and produces the expected results. */ void test_guac_protocol__version_to_string() { guac_protocol_version version_a = GUAC_PROTOCOL_VERSION_1_3_0; guac_protocol_version version_b = GUAC_PROTOCOL_VERSION_1_0_0; guac_protocol_version version_c = GUAC_PROTOCOL_VERSION_UNKNOWN; CU_ASSERT_STRING_EQUAL(guac_protocol_version_to_string(version_a), "VERSION_1_3_0"); CU_ASSERT_STRING_EQUAL(guac_protocol_version_to_string(version_b), "VERSION_1_0_0"); CU_ASSERT_PTR_NULL(guac_protocol_version_to_string(version_c)); } /** * Test which verifies that the version of String representations of Guacamole * protocol versions are successfully converted into their matching * guac_protocol_version enum values, and that versions that do not match * any version get the correct unknown value. */ void test_guac_protocol__string_to_version() { char* str_version_a = "VERSION_1_3_0"; char* str_version_b = "VERSION_1_1_0"; char* str_version_c = "AVACADO"; char* str_version_d = "VERSION_31_4_1"; CU_ASSERT_EQUAL(guac_protocol_string_to_version(str_version_a), GUAC_PROTOCOL_VERSION_1_3_0); CU_ASSERT_EQUAL(guac_protocol_string_to_version(str_version_b), GUAC_PROTOCOL_VERSION_1_1_0); CU_ASSERT_EQUAL(guac_protocol_string_to_version(str_version_c), GUAC_PROTOCOL_VERSION_UNKNOWN); CU_ASSERT_EQUAL(guac_protocol_string_to_version(str_version_d), GUAC_PROTOCOL_VERSION_UNKNOWN); } /** * Test which verifies that the comparisons between guac_protocol_version enum * values produces the expected results. */ void test_gauc_protocol__version_comparison() { CU_ASSERT_TRUE(GUAC_PROTOCOL_VERSION_1_3_0 > GUAC_PROTOCOL_VERSION_1_0_0); CU_ASSERT_TRUE(GUAC_PROTOCOL_VERSION_UNKNOWN < GUAC_PROTOCOL_VERSION_1_1_0); }guacamole-server-1.3.0/src/libguac/tests/protocol/base64_decode.c0000644000175100001440000000364313726006252021636 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include /** * Tests that libguac's in-place base64 decoding function properly decodes * valid base64 and fails for invalid base64. */ void test_protocol__decode_base64() { /* Test strings */ char test_HELLO[] = "SEVMTE8="; char test_AVOCADO[] = "QVZPQ0FETw=="; char test_GUACAMOLE[] = "R1VBQ0FNT0xF"; /* Invalid strings */ char invalid1[] = "===="; char invalid2[] = ""; /* Test one character of padding */ CU_ASSERT_EQUAL(guac_protocol_decode_base64(test_HELLO), 5); CU_ASSERT_NSTRING_EQUAL(test_HELLO, "HELLO", 5); /* Test two characters of padding */ CU_ASSERT_EQUAL(guac_protocol_decode_base64(test_AVOCADO), 7); CU_ASSERT_NSTRING_EQUAL(test_AVOCADO, "AVOCADO", 7); /* Test three characters of padding */ CU_ASSERT_EQUAL(guac_protocol_decode_base64(test_GUACAMOLE), 9); CU_ASSERT_NSTRING_EQUAL(test_GUACAMOLE, "GUACAMOLE", 9); /* Verify invalid strings stop early as expected */ CU_ASSERT_EQUAL(guac_protocol_decode_base64(invalid1), 0); CU_ASSERT_EQUAL(guac_protocol_decode_base64(invalid2), 0); } guacamole-server-1.3.0/src/libguac/tests/pool/0000755000175100001440000000000013772471155016276 500000000000000guacamole-server-1.3.0/src/libguac/tests/pool/next_free.c0000644000175100001440000000472413726006252020337 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include /** * The number of unique integers to provide through the guac_pool instance * being tested. */ #define POOL_SIZE 128 /** * Test which verifies that guac_pool provides access to a given number of * unique integers, never repeating a retrieved integer until that integer * is returned to the pool. */ void test_pool__next_free() { guac_pool* pool; int i; int seen[POOL_SIZE] = {0}; int value; /* Get pool */ pool = guac_pool_alloc(POOL_SIZE); CU_ASSERT_PTR_NOT_NULL_FATAL(pool); /* Fill pool */ for (i=0; i= 0); CU_ASSERT_FATAL(value < POOL_SIZE); /* This should be an integer we have not seen yet */ CU_ASSERT_EQUAL(0, seen[value]); seen[value]++; /* Return value to pool */ guac_pool_free_int(pool, value); } /* Now that pool is filled, we should get ONLY previously seen integers */ for (i=0; i= 0); CU_ASSERT_FATAL(value < POOL_SIZE); /* This should be an integer we have seen only once */ CU_ASSERT_EQUAL(1, seen[value]); seen[value]++; } /* Pool is filled to minimum now. Next value should be equal to size. */ value = guac_pool_next_int(pool); CU_ASSERT_EQUAL(POOL_SIZE, value); /* Free pool */ guac_pool_free(pool); } guacamole-server-1.3.0/src/libguac/tests/client/0000755000175100001440000000000013772471155016603 500000000000000guacamole-server-1.3.0/src/libguac/tests/client/buffer_pool.c0000644000175100001440000000452013726006252021161 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include /** * Test which verifies that buffers can be allocated and freed using the pool * of buffers available to each guac_client, and that doing so does not disturb * the similar pool of layers. */ void test_client__buffer_pool() { guac_client* client; int i; bool seen[GUAC_BUFFER_POOL_INITIAL_SIZE] = { 0 }; guac_layer* layer; /* Get client */ client = guac_client_alloc(); CU_ASSERT_PTR_NOT_NULL_FATAL(client); /* Fill pool */ for (i=0; iindex < 0); CU_ASSERT_FATAL(layer->index >= -GUAC_BUFFER_POOL_INITIAL_SIZE); /* This should be a layer we have not seen yet */ CU_ASSERT_FALSE(seen[-layer->index - 1]); seen[-layer->index - 1] = true; guac_client_free_buffer(client, layer); } /* Now that pool is filled, we should get a previously seen layer */ layer = guac_client_alloc_buffer(client); CU_ASSERT_FATAL(layer->index < 0); CU_ASSERT_FATAL(layer->index >= -GUAC_BUFFER_POOL_INITIAL_SIZE); CU_ASSERT_TRUE(seen[-layer->index - 1]); /* Free client */ guac_client_free(client); } guacamole-server-1.3.0/src/libguac/tests/client/layer_pool.c0000644000175100001440000000450513726006252021027 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include /** * Test which verifies that layers can be allocated and freed using the pool * of layers available to each guac_client, and that doing so does not disturb * the similar pool of buffers. */ void test_client__layer_pool() { guac_client* client; int i; bool seen[GUAC_BUFFER_POOL_INITIAL_SIZE] = {0}; guac_layer* layer; /* Get client */ client = guac_client_alloc(); CU_ASSERT_PTR_NOT_NULL_FATAL(client); /* Fill pool */ for (i=0; iindex > 0); CU_ASSERT_FATAL(layer->index <= GUAC_BUFFER_POOL_INITIAL_SIZE); /* This should be a layer we have not seen yet */ CU_ASSERT_FALSE(seen[layer->index - 1]); seen[layer->index - 1] = true; guac_client_free_layer(client, layer); } /* Now that pool is filled, we should get a previously seen layer */ layer = guac_client_alloc_layer(client); CU_ASSERT_FATAL(layer->index > 0); CU_ASSERT_FATAL(layer->index <= GUAC_BUFFER_POOL_INITIAL_SIZE); CU_ASSERT_TRUE(seen[layer->index - 1]); /* Free client */ guac_client_free(client); } guacamole-server-1.3.0/src/libguac/tests/socket/0000755000175100001440000000000013772471155016615 500000000000000guacamole-server-1.3.0/src/libguac/tests/socket/fd_send_instruction.c0000644000175100001440000000773513726006252022747 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include /** * Test string which contains exactly four Unicode characters encoded in UTF-8. * This particular test string uses several characters which encode to multiple * bytes in UTF-8. */ #define UTF8_4 "\xe7\x8a\xac\xf0\x90\xac\x80z\xc3\xa1" /** * Writes a series of Guacamole instructions using a normal guac_socket * wrapping the given file descriptor. The instructions written correspond to * the instructions verified by read_expected_instructions(). The given file * descriptor is automatically closed as a result of calling this function. * * @param fd * The file descriptor to write instructions to. */ static void write_instructions(int fd) { /* Open guac socket */ guac_socket* socket = guac_socket_open(fd); /* Write nothing if socket cannot be allocated (test will fail in parent * process due to failure to read) */ if (socket == NULL) { close(fd); return; } /* Write instructions */ guac_protocol_send_name(socket, "a" UTF8_4 "b" UTF8_4 "c"); guac_protocol_send_sync(socket, 12345); guac_socket_flush(socket); /* Close and free socket */ guac_socket_free(socket); } /** * Reads raw bytes from the given file descriptor until no further bytes * remain, verfying that those bytes represent the series of Guacamole * instructions expected to be written by write_instructions(). The given * file descriptor is automatically closed as a result of calling this * function. * * @param fd * The file descriptor to read data from. */ static void read_expected_instructions(int fd) { char expected[] = "4.name,11.a" UTF8_4 "b" UTF8_4 "c;" "4.sync,5.12345;"; int numread; char buffer[1024]; int offset = 0; /* Read everything available into buffer */ while ((numread = read(fd, &(buffer[offset]), sizeof(buffer) - offset)) > 0) { offset += numread; } /* Verify length of read data */ CU_ASSERT_EQUAL(offset, strlen(expected)); /* Add NULL terminator */ buffer[offset] = '\0'; /* Read value should be equal to expected value */ CU_ASSERT_STRING_EQUAL(buffer, expected); /* File descriptor is no longer needed */ close(fd); } /** * Tests that the file descriptor implementation of guac_socket properly * implements writing of instructions. A child process is forked to write a * series of instructions which are read and verified by the parent process. */ void test_socket__fd_send_instruction() { int fd[2]; /* Create pipe */ CU_ASSERT_EQUAL_FATAL(pipe(fd), 0); int read_fd = fd[0]; int write_fd = fd[1]; /* Fork into writer process (child) and reader process (parent) */ int childpid; CU_ASSERT_NOT_EQUAL_FATAL((childpid = fork()), -1); /* Attempt to write a series of instructions within the child process */ if (childpid == 0) { close(read_fd); write_instructions(write_fd); exit(0); } /* Read and verify the expected instructions within the parent process */ close(write_fd); read_expected_instructions(read_fd); } guacamole-server-1.3.0/src/libguac/tests/socket/nested_send_instruction.c0000644000175100001440000001056213726006252023630 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include /** * Test string which contains exactly four Unicode characters encoded in UTF-8. * This particular test string uses several characters which encode to multiple * bytes in UTF-8. */ #define UTF8_4 "\xe7\x8a\xac\xf0\x90\xac\x80z\xc3\xa1" /** * Writes a series of Guacamole instructions using a nested guac_socket * wrapping another guac_socket which writes to the given file descriptor. The * instructions written correspond to the instructions verified by * read_expected_instructions(). The given file descriptor is automatically * closed as a result of calling this function. * * @param fd * The file descriptor to write instructions to. */ static void write_instructions(int fd) { /* Open guac socket */ guac_socket* socket = guac_socket_open(fd); /* Write nothing if socket cannot be allocated (test will fail in parent * process due to failure to read) */ if (socket == NULL) { close(fd); return; } /* Nest socket */ guac_socket* nested_socket = guac_socket_nest(socket, 123); /* Write nothing if nested socket cannot be allocated (test will fail in * parent process due to failure to read) */ if (socket == NULL) { guac_socket_free(socket); return; } /* Write instructions */ guac_protocol_send_name(nested_socket, "a" UTF8_4 "b" UTF8_4 "c"); guac_protocol_send_sync(nested_socket, 12345); /* Close and free sockets */ guac_socket_free(nested_socket); guac_socket_free(socket); } /** * Reads raw bytes from the given file descriptor until no further bytes * remain, verfying that those bytes represent the series of Guacamole * instructions expected to be written by write_instructions(). The given * file descriptor is automatically closed as a result of calling this * function. * * @param fd * The file descriptor to read data from. */ static void read_expected_instructions(int fd) { char expected[] = "4.nest,3.123,37." "4.name,11.a" UTF8_4 "b" UTF8_4 "c;" "4.sync,5.12345;" ";"; int numread; char buffer[1024]; int offset = 0; /* Read everything available into buffer */ while ((numread = read(fd, &(buffer[offset]), sizeof(buffer) - offset)) > 0) { offset += numread; } /* Verify length of read data */ CU_ASSERT_EQUAL(offset, strlen(expected)); /* Add NULL terminator */ buffer[offset] = '\0'; /* Read value should be equal to expected value */ CU_ASSERT_STRING_EQUAL(buffer, expected); /* File descriptor is no longer needed */ close(fd); } /** * Tests that the nested socket implementation of guac_socket properly * implements writing of instructions. A child process is forked to write a * series of instructions which are read and verified by the parent process. */ void test_socket__nested_send_instruction() { int fd[2]; /* Create pipe */ CU_ASSERT_EQUAL_FATAL(pipe(fd), 0); int read_fd = fd[0]; int write_fd = fd[1]; /* Fork into writer process (child) and reader process (parent) */ int childpid; CU_ASSERT_NOT_EQUAL_FATAL((childpid = fork()), -1); /* Attempt to write a series of instructions within the child process */ if (childpid == 0) { close(read_fd); write_instructions(write_fd); exit(0); } /* Read and verify the expected instructions within the parent process */ close(write_fd); read_expected_instructions(read_fd); } guacamole-server-1.3.0/src/libguac/tests/Makefile.in0000644000175100001440000024455613772471102017322 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ check_PROGRAMS = test_libguac$(EXEEXT) subdir = src/libguac/tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__dirstamp = $(am__leading_dot)dirstamp am_test_libguac_OBJECTS = client/test_libguac-buffer_pool.$(OBJEXT) \ client/test_libguac-layer_pool.$(OBJEXT) \ parser/test_libguac-append.$(OBJEXT) \ parser/test_libguac-read.$(OBJEXT) \ pool/test_libguac-next_free.$(OBJEXT) \ protocol/test_libguac-base64_decode.$(OBJEXT) \ protocol/test_libguac-guac_protocol_version.$(OBJEXT) \ socket/test_libguac-fd_send_instruction.$(OBJEXT) \ socket/test_libguac-nested_send_instruction.$(OBJEXT) \ string/test_libguac-strdup.$(OBJEXT) \ string/test_libguac-strlcat.$(OBJEXT) \ string/test_libguac-strlcpy.$(OBJEXT) \ string/test_libguac-strljoin.$(OBJEXT) \ unicode/test_libguac-charsize.$(OBJEXT) \ unicode/test_libguac-read.$(OBJEXT) \ unicode/test_libguac-strlen.$(OBJEXT) \ unicode/test_libguac-write.$(OBJEXT) nodist_test_libguac_OBJECTS = \ test_libguac-_generated_runner.$(OBJEXT) test_libguac_OBJECTS = $(am_test_libguac_OBJECTS) \ $(nodist_test_libguac_OBJECTS) test_libguac_DEPENDENCIES = AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = test_libguac_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_libguac_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/test_libguac-_generated_runner.Po \ client/$(DEPDIR)/test_libguac-buffer_pool.Po \ client/$(DEPDIR)/test_libguac-layer_pool.Po \ parser/$(DEPDIR)/test_libguac-append.Po \ parser/$(DEPDIR)/test_libguac-read.Po \ pool/$(DEPDIR)/test_libguac-next_free.Po \ protocol/$(DEPDIR)/test_libguac-base64_decode.Po \ protocol/$(DEPDIR)/test_libguac-guac_protocol_version.Po \ socket/$(DEPDIR)/test_libguac-fd_send_instruction.Po \ socket/$(DEPDIR)/test_libguac-nested_send_instruction.Po \ string/$(DEPDIR)/test_libguac-strdup.Po \ string/$(DEPDIR)/test_libguac-strlcat.Po \ string/$(DEPDIR)/test_libguac-strlcpy.Po \ string/$(DEPDIR)/test_libguac-strljoin.Po \ unicode/$(DEPDIR)/test_libguac-charsize.Po \ unicode/$(DEPDIR)/test_libguac-read.Po \ unicode/$(DEPDIR)/test_libguac-strlen.Po \ unicode/$(DEPDIR)/test_libguac-write.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(test_libguac_SOURCES) $(nodist_test_libguac_SOURCES) DIST_SOURCES = $(test_libguac_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp \ $(top_srcdir)/build-aux/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 TESTS = $(check_PROGRAMS) test_libguac_SOURCES = \ client/buffer_pool.c \ client/layer_pool.c \ parser/append.c \ parser/read.c \ pool/next_free.c \ protocol/base64_decode.c \ protocol/guac_protocol_version.c \ socket/fd_send_instruction.c \ socket/nested_send_instruction.c \ string/strdup.c \ string/strlcat.c \ string/strlcpy.c \ string/strljoin.c \ unicode/charsize.c \ unicode/read.c \ unicode/strlen.c \ unicode/write.c test_libguac_CFLAGS = \ -Werror -Wall -pedantic \ @LIBGUAC_INCLUDE@ test_libguac_LDADD = \ @CUNIT_LIBS@ \ @LIBGUAC_LTLIB@ # # Autogenerate test runner # GEN_RUNNER = $(top_srcdir)/util/generate-test-runner.pl CLEANFILES = _generated_runner.c nodist_test_libguac_SOURCES = \ _generated_runner.c # Use automake's TAP test driver for running any tests LOG_DRIVER = \ env AM_TAP_AWK='$(AWK)' \ $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/libguac/tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/libguac/tests/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list client/$(am__dirstamp): @$(MKDIR_P) client @: > client/$(am__dirstamp) client/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) client/$(DEPDIR) @: > client/$(DEPDIR)/$(am__dirstamp) client/test_libguac-buffer_pool.$(OBJEXT): client/$(am__dirstamp) \ client/$(DEPDIR)/$(am__dirstamp) client/test_libguac-layer_pool.$(OBJEXT): client/$(am__dirstamp) \ client/$(DEPDIR)/$(am__dirstamp) parser/$(am__dirstamp): @$(MKDIR_P) parser @: > parser/$(am__dirstamp) parser/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) parser/$(DEPDIR) @: > parser/$(DEPDIR)/$(am__dirstamp) parser/test_libguac-append.$(OBJEXT): parser/$(am__dirstamp) \ parser/$(DEPDIR)/$(am__dirstamp) parser/test_libguac-read.$(OBJEXT): parser/$(am__dirstamp) \ parser/$(DEPDIR)/$(am__dirstamp) pool/$(am__dirstamp): @$(MKDIR_P) pool @: > pool/$(am__dirstamp) pool/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) pool/$(DEPDIR) @: > pool/$(DEPDIR)/$(am__dirstamp) pool/test_libguac-next_free.$(OBJEXT): pool/$(am__dirstamp) \ pool/$(DEPDIR)/$(am__dirstamp) protocol/$(am__dirstamp): @$(MKDIR_P) protocol @: > protocol/$(am__dirstamp) protocol/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) protocol/$(DEPDIR) @: > protocol/$(DEPDIR)/$(am__dirstamp) protocol/test_libguac-base64_decode.$(OBJEXT): \ protocol/$(am__dirstamp) protocol/$(DEPDIR)/$(am__dirstamp) protocol/test_libguac-guac_protocol_version.$(OBJEXT): \ protocol/$(am__dirstamp) protocol/$(DEPDIR)/$(am__dirstamp) socket/$(am__dirstamp): @$(MKDIR_P) socket @: > socket/$(am__dirstamp) socket/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) socket/$(DEPDIR) @: > socket/$(DEPDIR)/$(am__dirstamp) socket/test_libguac-fd_send_instruction.$(OBJEXT): \ socket/$(am__dirstamp) socket/$(DEPDIR)/$(am__dirstamp) socket/test_libguac-nested_send_instruction.$(OBJEXT): \ socket/$(am__dirstamp) socket/$(DEPDIR)/$(am__dirstamp) string/$(am__dirstamp): @$(MKDIR_P) string @: > string/$(am__dirstamp) string/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) string/$(DEPDIR) @: > string/$(DEPDIR)/$(am__dirstamp) string/test_libguac-strdup.$(OBJEXT): string/$(am__dirstamp) \ string/$(DEPDIR)/$(am__dirstamp) string/test_libguac-strlcat.$(OBJEXT): string/$(am__dirstamp) \ string/$(DEPDIR)/$(am__dirstamp) string/test_libguac-strlcpy.$(OBJEXT): string/$(am__dirstamp) \ string/$(DEPDIR)/$(am__dirstamp) string/test_libguac-strljoin.$(OBJEXT): string/$(am__dirstamp) \ string/$(DEPDIR)/$(am__dirstamp) unicode/$(am__dirstamp): @$(MKDIR_P) unicode @: > unicode/$(am__dirstamp) unicode/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) unicode/$(DEPDIR) @: > unicode/$(DEPDIR)/$(am__dirstamp) unicode/test_libguac-charsize.$(OBJEXT): unicode/$(am__dirstamp) \ unicode/$(DEPDIR)/$(am__dirstamp) unicode/test_libguac-read.$(OBJEXT): unicode/$(am__dirstamp) \ unicode/$(DEPDIR)/$(am__dirstamp) unicode/test_libguac-strlen.$(OBJEXT): unicode/$(am__dirstamp) \ unicode/$(DEPDIR)/$(am__dirstamp) unicode/test_libguac-write.$(OBJEXT): unicode/$(am__dirstamp) \ unicode/$(DEPDIR)/$(am__dirstamp) test_libguac$(EXEEXT): $(test_libguac_OBJECTS) $(test_libguac_DEPENDENCIES) $(EXTRA_test_libguac_DEPENDENCIES) @rm -f test_libguac$(EXEEXT) $(AM_V_CCLD)$(test_libguac_LINK) $(test_libguac_OBJECTS) $(test_libguac_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f client/*.$(OBJEXT) -rm -f parser/*.$(OBJEXT) -rm -f pool/*.$(OBJEXT) -rm -f protocol/*.$(OBJEXT) -rm -f socket/*.$(OBJEXT) -rm -f string/*.$(OBJEXT) -rm -f unicode/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_libguac-_generated_runner.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/test_libguac-buffer_pool.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/test_libguac-layer_pool.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@parser/$(DEPDIR)/test_libguac-append.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@parser/$(DEPDIR)/test_libguac-read.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@pool/$(DEPDIR)/test_libguac-next_free.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/test_libguac-base64_decode.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/test_libguac-guac_protocol_version.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@socket/$(DEPDIR)/test_libguac-fd_send_instruction.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@socket/$(DEPDIR)/test_libguac-nested_send_instruction.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@string/$(DEPDIR)/test_libguac-strdup.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@string/$(DEPDIR)/test_libguac-strlcat.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@string/$(DEPDIR)/test_libguac-strlcpy.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@string/$(DEPDIR)/test_libguac-strljoin.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@unicode/$(DEPDIR)/test_libguac-charsize.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@unicode/$(DEPDIR)/test_libguac-read.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@unicode/$(DEPDIR)/test_libguac-strlen.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@unicode/$(DEPDIR)/test_libguac-write.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< client/test_libguac-buffer_pool.o: client/buffer_pool.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT client/test_libguac-buffer_pool.o -MD -MP -MF client/$(DEPDIR)/test_libguac-buffer_pool.Tpo -c -o client/test_libguac-buffer_pool.o `test -f 'client/buffer_pool.c' || echo '$(srcdir)/'`client/buffer_pool.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) client/$(DEPDIR)/test_libguac-buffer_pool.Tpo client/$(DEPDIR)/test_libguac-buffer_pool.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client/buffer_pool.c' object='client/test_libguac-buffer_pool.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o client/test_libguac-buffer_pool.o `test -f 'client/buffer_pool.c' || echo '$(srcdir)/'`client/buffer_pool.c client/test_libguac-buffer_pool.obj: client/buffer_pool.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT client/test_libguac-buffer_pool.obj -MD -MP -MF client/$(DEPDIR)/test_libguac-buffer_pool.Tpo -c -o client/test_libguac-buffer_pool.obj `if test -f 'client/buffer_pool.c'; then $(CYGPATH_W) 'client/buffer_pool.c'; else $(CYGPATH_W) '$(srcdir)/client/buffer_pool.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) client/$(DEPDIR)/test_libguac-buffer_pool.Tpo client/$(DEPDIR)/test_libguac-buffer_pool.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client/buffer_pool.c' object='client/test_libguac-buffer_pool.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o client/test_libguac-buffer_pool.obj `if test -f 'client/buffer_pool.c'; then $(CYGPATH_W) 'client/buffer_pool.c'; else $(CYGPATH_W) '$(srcdir)/client/buffer_pool.c'; fi` client/test_libguac-layer_pool.o: client/layer_pool.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT client/test_libguac-layer_pool.o -MD -MP -MF client/$(DEPDIR)/test_libguac-layer_pool.Tpo -c -o client/test_libguac-layer_pool.o `test -f 'client/layer_pool.c' || echo '$(srcdir)/'`client/layer_pool.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) client/$(DEPDIR)/test_libguac-layer_pool.Tpo client/$(DEPDIR)/test_libguac-layer_pool.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client/layer_pool.c' object='client/test_libguac-layer_pool.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o client/test_libguac-layer_pool.o `test -f 'client/layer_pool.c' || echo '$(srcdir)/'`client/layer_pool.c client/test_libguac-layer_pool.obj: client/layer_pool.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT client/test_libguac-layer_pool.obj -MD -MP -MF client/$(DEPDIR)/test_libguac-layer_pool.Tpo -c -o client/test_libguac-layer_pool.obj `if test -f 'client/layer_pool.c'; then $(CYGPATH_W) 'client/layer_pool.c'; else $(CYGPATH_W) '$(srcdir)/client/layer_pool.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) client/$(DEPDIR)/test_libguac-layer_pool.Tpo client/$(DEPDIR)/test_libguac-layer_pool.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client/layer_pool.c' object='client/test_libguac-layer_pool.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o client/test_libguac-layer_pool.obj `if test -f 'client/layer_pool.c'; then $(CYGPATH_W) 'client/layer_pool.c'; else $(CYGPATH_W) '$(srcdir)/client/layer_pool.c'; fi` parser/test_libguac-append.o: parser/append.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT parser/test_libguac-append.o -MD -MP -MF parser/$(DEPDIR)/test_libguac-append.Tpo -c -o parser/test_libguac-append.o `test -f 'parser/append.c' || echo '$(srcdir)/'`parser/append.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) parser/$(DEPDIR)/test_libguac-append.Tpo parser/$(DEPDIR)/test_libguac-append.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parser/append.c' object='parser/test_libguac-append.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o parser/test_libguac-append.o `test -f 'parser/append.c' || echo '$(srcdir)/'`parser/append.c parser/test_libguac-append.obj: parser/append.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT parser/test_libguac-append.obj -MD -MP -MF parser/$(DEPDIR)/test_libguac-append.Tpo -c -o parser/test_libguac-append.obj `if test -f 'parser/append.c'; then $(CYGPATH_W) 'parser/append.c'; else $(CYGPATH_W) '$(srcdir)/parser/append.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) parser/$(DEPDIR)/test_libguac-append.Tpo parser/$(DEPDIR)/test_libguac-append.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parser/append.c' object='parser/test_libguac-append.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o parser/test_libguac-append.obj `if test -f 'parser/append.c'; then $(CYGPATH_W) 'parser/append.c'; else $(CYGPATH_W) '$(srcdir)/parser/append.c'; fi` parser/test_libguac-read.o: parser/read.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT parser/test_libguac-read.o -MD -MP -MF parser/$(DEPDIR)/test_libguac-read.Tpo -c -o parser/test_libguac-read.o `test -f 'parser/read.c' || echo '$(srcdir)/'`parser/read.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) parser/$(DEPDIR)/test_libguac-read.Tpo parser/$(DEPDIR)/test_libguac-read.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parser/read.c' object='parser/test_libguac-read.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o parser/test_libguac-read.o `test -f 'parser/read.c' || echo '$(srcdir)/'`parser/read.c parser/test_libguac-read.obj: parser/read.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT parser/test_libguac-read.obj -MD -MP -MF parser/$(DEPDIR)/test_libguac-read.Tpo -c -o parser/test_libguac-read.obj `if test -f 'parser/read.c'; then $(CYGPATH_W) 'parser/read.c'; else $(CYGPATH_W) '$(srcdir)/parser/read.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) parser/$(DEPDIR)/test_libguac-read.Tpo parser/$(DEPDIR)/test_libguac-read.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parser/read.c' object='parser/test_libguac-read.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o parser/test_libguac-read.obj `if test -f 'parser/read.c'; then $(CYGPATH_W) 'parser/read.c'; else $(CYGPATH_W) '$(srcdir)/parser/read.c'; fi` pool/test_libguac-next_free.o: pool/next_free.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT pool/test_libguac-next_free.o -MD -MP -MF pool/$(DEPDIR)/test_libguac-next_free.Tpo -c -o pool/test_libguac-next_free.o `test -f 'pool/next_free.c' || echo '$(srcdir)/'`pool/next_free.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) pool/$(DEPDIR)/test_libguac-next_free.Tpo pool/$(DEPDIR)/test_libguac-next_free.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pool/next_free.c' object='pool/test_libguac-next_free.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o pool/test_libguac-next_free.o `test -f 'pool/next_free.c' || echo '$(srcdir)/'`pool/next_free.c pool/test_libguac-next_free.obj: pool/next_free.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT pool/test_libguac-next_free.obj -MD -MP -MF pool/$(DEPDIR)/test_libguac-next_free.Tpo -c -o pool/test_libguac-next_free.obj `if test -f 'pool/next_free.c'; then $(CYGPATH_W) 'pool/next_free.c'; else $(CYGPATH_W) '$(srcdir)/pool/next_free.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) pool/$(DEPDIR)/test_libguac-next_free.Tpo pool/$(DEPDIR)/test_libguac-next_free.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pool/next_free.c' object='pool/test_libguac-next_free.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o pool/test_libguac-next_free.obj `if test -f 'pool/next_free.c'; then $(CYGPATH_W) 'pool/next_free.c'; else $(CYGPATH_W) '$(srcdir)/pool/next_free.c'; fi` protocol/test_libguac-base64_decode.o: protocol/base64_decode.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT protocol/test_libguac-base64_decode.o -MD -MP -MF protocol/$(DEPDIR)/test_libguac-base64_decode.Tpo -c -o protocol/test_libguac-base64_decode.o `test -f 'protocol/base64_decode.c' || echo '$(srcdir)/'`protocol/base64_decode.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) protocol/$(DEPDIR)/test_libguac-base64_decode.Tpo protocol/$(DEPDIR)/test_libguac-base64_decode.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='protocol/base64_decode.c' object='protocol/test_libguac-base64_decode.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o protocol/test_libguac-base64_decode.o `test -f 'protocol/base64_decode.c' || echo '$(srcdir)/'`protocol/base64_decode.c protocol/test_libguac-base64_decode.obj: protocol/base64_decode.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT protocol/test_libguac-base64_decode.obj -MD -MP -MF protocol/$(DEPDIR)/test_libguac-base64_decode.Tpo -c -o protocol/test_libguac-base64_decode.obj `if test -f 'protocol/base64_decode.c'; then $(CYGPATH_W) 'protocol/base64_decode.c'; else $(CYGPATH_W) '$(srcdir)/protocol/base64_decode.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) protocol/$(DEPDIR)/test_libguac-base64_decode.Tpo protocol/$(DEPDIR)/test_libguac-base64_decode.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='protocol/base64_decode.c' object='protocol/test_libguac-base64_decode.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o protocol/test_libguac-base64_decode.obj `if test -f 'protocol/base64_decode.c'; then $(CYGPATH_W) 'protocol/base64_decode.c'; else $(CYGPATH_W) '$(srcdir)/protocol/base64_decode.c'; fi` protocol/test_libguac-guac_protocol_version.o: protocol/guac_protocol_version.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT protocol/test_libguac-guac_protocol_version.o -MD -MP -MF protocol/$(DEPDIR)/test_libguac-guac_protocol_version.Tpo -c -o protocol/test_libguac-guac_protocol_version.o `test -f 'protocol/guac_protocol_version.c' || echo '$(srcdir)/'`protocol/guac_protocol_version.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) protocol/$(DEPDIR)/test_libguac-guac_protocol_version.Tpo protocol/$(DEPDIR)/test_libguac-guac_protocol_version.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='protocol/guac_protocol_version.c' object='protocol/test_libguac-guac_protocol_version.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o protocol/test_libguac-guac_protocol_version.o `test -f 'protocol/guac_protocol_version.c' || echo '$(srcdir)/'`protocol/guac_protocol_version.c protocol/test_libguac-guac_protocol_version.obj: protocol/guac_protocol_version.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT protocol/test_libguac-guac_protocol_version.obj -MD -MP -MF protocol/$(DEPDIR)/test_libguac-guac_protocol_version.Tpo -c -o protocol/test_libguac-guac_protocol_version.obj `if test -f 'protocol/guac_protocol_version.c'; then $(CYGPATH_W) 'protocol/guac_protocol_version.c'; else $(CYGPATH_W) '$(srcdir)/protocol/guac_protocol_version.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) protocol/$(DEPDIR)/test_libguac-guac_protocol_version.Tpo protocol/$(DEPDIR)/test_libguac-guac_protocol_version.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='protocol/guac_protocol_version.c' object='protocol/test_libguac-guac_protocol_version.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o protocol/test_libguac-guac_protocol_version.obj `if test -f 'protocol/guac_protocol_version.c'; then $(CYGPATH_W) 'protocol/guac_protocol_version.c'; else $(CYGPATH_W) '$(srcdir)/protocol/guac_protocol_version.c'; fi` socket/test_libguac-fd_send_instruction.o: socket/fd_send_instruction.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT socket/test_libguac-fd_send_instruction.o -MD -MP -MF socket/$(DEPDIR)/test_libguac-fd_send_instruction.Tpo -c -o socket/test_libguac-fd_send_instruction.o `test -f 'socket/fd_send_instruction.c' || echo '$(srcdir)/'`socket/fd_send_instruction.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) socket/$(DEPDIR)/test_libguac-fd_send_instruction.Tpo socket/$(DEPDIR)/test_libguac-fd_send_instruction.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socket/fd_send_instruction.c' object='socket/test_libguac-fd_send_instruction.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o socket/test_libguac-fd_send_instruction.o `test -f 'socket/fd_send_instruction.c' || echo '$(srcdir)/'`socket/fd_send_instruction.c socket/test_libguac-fd_send_instruction.obj: socket/fd_send_instruction.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT socket/test_libguac-fd_send_instruction.obj -MD -MP -MF socket/$(DEPDIR)/test_libguac-fd_send_instruction.Tpo -c -o socket/test_libguac-fd_send_instruction.obj `if test -f 'socket/fd_send_instruction.c'; then $(CYGPATH_W) 'socket/fd_send_instruction.c'; else $(CYGPATH_W) '$(srcdir)/socket/fd_send_instruction.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) socket/$(DEPDIR)/test_libguac-fd_send_instruction.Tpo socket/$(DEPDIR)/test_libguac-fd_send_instruction.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socket/fd_send_instruction.c' object='socket/test_libguac-fd_send_instruction.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o socket/test_libguac-fd_send_instruction.obj `if test -f 'socket/fd_send_instruction.c'; then $(CYGPATH_W) 'socket/fd_send_instruction.c'; else $(CYGPATH_W) '$(srcdir)/socket/fd_send_instruction.c'; fi` socket/test_libguac-nested_send_instruction.o: socket/nested_send_instruction.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT socket/test_libguac-nested_send_instruction.o -MD -MP -MF socket/$(DEPDIR)/test_libguac-nested_send_instruction.Tpo -c -o socket/test_libguac-nested_send_instruction.o `test -f 'socket/nested_send_instruction.c' || echo '$(srcdir)/'`socket/nested_send_instruction.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) socket/$(DEPDIR)/test_libguac-nested_send_instruction.Tpo socket/$(DEPDIR)/test_libguac-nested_send_instruction.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socket/nested_send_instruction.c' object='socket/test_libguac-nested_send_instruction.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o socket/test_libguac-nested_send_instruction.o `test -f 'socket/nested_send_instruction.c' || echo '$(srcdir)/'`socket/nested_send_instruction.c socket/test_libguac-nested_send_instruction.obj: socket/nested_send_instruction.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT socket/test_libguac-nested_send_instruction.obj -MD -MP -MF socket/$(DEPDIR)/test_libguac-nested_send_instruction.Tpo -c -o socket/test_libguac-nested_send_instruction.obj `if test -f 'socket/nested_send_instruction.c'; then $(CYGPATH_W) 'socket/nested_send_instruction.c'; else $(CYGPATH_W) '$(srcdir)/socket/nested_send_instruction.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) socket/$(DEPDIR)/test_libguac-nested_send_instruction.Tpo socket/$(DEPDIR)/test_libguac-nested_send_instruction.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socket/nested_send_instruction.c' object='socket/test_libguac-nested_send_instruction.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o socket/test_libguac-nested_send_instruction.obj `if test -f 'socket/nested_send_instruction.c'; then $(CYGPATH_W) 'socket/nested_send_instruction.c'; else $(CYGPATH_W) '$(srcdir)/socket/nested_send_instruction.c'; fi` string/test_libguac-strdup.o: string/strdup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT string/test_libguac-strdup.o -MD -MP -MF string/$(DEPDIR)/test_libguac-strdup.Tpo -c -o string/test_libguac-strdup.o `test -f 'string/strdup.c' || echo '$(srcdir)/'`string/strdup.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) string/$(DEPDIR)/test_libguac-strdup.Tpo string/$(DEPDIR)/test_libguac-strdup.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string/strdup.c' object='string/test_libguac-strdup.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o string/test_libguac-strdup.o `test -f 'string/strdup.c' || echo '$(srcdir)/'`string/strdup.c string/test_libguac-strdup.obj: string/strdup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT string/test_libguac-strdup.obj -MD -MP -MF string/$(DEPDIR)/test_libguac-strdup.Tpo -c -o string/test_libguac-strdup.obj `if test -f 'string/strdup.c'; then $(CYGPATH_W) 'string/strdup.c'; else $(CYGPATH_W) '$(srcdir)/string/strdup.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) string/$(DEPDIR)/test_libguac-strdup.Tpo string/$(DEPDIR)/test_libguac-strdup.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string/strdup.c' object='string/test_libguac-strdup.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o string/test_libguac-strdup.obj `if test -f 'string/strdup.c'; then $(CYGPATH_W) 'string/strdup.c'; else $(CYGPATH_W) '$(srcdir)/string/strdup.c'; fi` string/test_libguac-strlcat.o: string/strlcat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT string/test_libguac-strlcat.o -MD -MP -MF string/$(DEPDIR)/test_libguac-strlcat.Tpo -c -o string/test_libguac-strlcat.o `test -f 'string/strlcat.c' || echo '$(srcdir)/'`string/strlcat.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) string/$(DEPDIR)/test_libguac-strlcat.Tpo string/$(DEPDIR)/test_libguac-strlcat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string/strlcat.c' object='string/test_libguac-strlcat.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o string/test_libguac-strlcat.o `test -f 'string/strlcat.c' || echo '$(srcdir)/'`string/strlcat.c string/test_libguac-strlcat.obj: string/strlcat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT string/test_libguac-strlcat.obj -MD -MP -MF string/$(DEPDIR)/test_libguac-strlcat.Tpo -c -o string/test_libguac-strlcat.obj `if test -f 'string/strlcat.c'; then $(CYGPATH_W) 'string/strlcat.c'; else $(CYGPATH_W) '$(srcdir)/string/strlcat.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) string/$(DEPDIR)/test_libguac-strlcat.Tpo string/$(DEPDIR)/test_libguac-strlcat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string/strlcat.c' object='string/test_libguac-strlcat.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o string/test_libguac-strlcat.obj `if test -f 'string/strlcat.c'; then $(CYGPATH_W) 'string/strlcat.c'; else $(CYGPATH_W) '$(srcdir)/string/strlcat.c'; fi` string/test_libguac-strlcpy.o: string/strlcpy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT string/test_libguac-strlcpy.o -MD -MP -MF string/$(DEPDIR)/test_libguac-strlcpy.Tpo -c -o string/test_libguac-strlcpy.o `test -f 'string/strlcpy.c' || echo '$(srcdir)/'`string/strlcpy.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) string/$(DEPDIR)/test_libguac-strlcpy.Tpo string/$(DEPDIR)/test_libguac-strlcpy.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string/strlcpy.c' object='string/test_libguac-strlcpy.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o string/test_libguac-strlcpy.o `test -f 'string/strlcpy.c' || echo '$(srcdir)/'`string/strlcpy.c string/test_libguac-strlcpy.obj: string/strlcpy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT string/test_libguac-strlcpy.obj -MD -MP -MF string/$(DEPDIR)/test_libguac-strlcpy.Tpo -c -o string/test_libguac-strlcpy.obj `if test -f 'string/strlcpy.c'; then $(CYGPATH_W) 'string/strlcpy.c'; else $(CYGPATH_W) '$(srcdir)/string/strlcpy.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) string/$(DEPDIR)/test_libguac-strlcpy.Tpo string/$(DEPDIR)/test_libguac-strlcpy.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string/strlcpy.c' object='string/test_libguac-strlcpy.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o string/test_libguac-strlcpy.obj `if test -f 'string/strlcpy.c'; then $(CYGPATH_W) 'string/strlcpy.c'; else $(CYGPATH_W) '$(srcdir)/string/strlcpy.c'; fi` string/test_libguac-strljoin.o: string/strljoin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT string/test_libguac-strljoin.o -MD -MP -MF string/$(DEPDIR)/test_libguac-strljoin.Tpo -c -o string/test_libguac-strljoin.o `test -f 'string/strljoin.c' || echo '$(srcdir)/'`string/strljoin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) string/$(DEPDIR)/test_libguac-strljoin.Tpo string/$(DEPDIR)/test_libguac-strljoin.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string/strljoin.c' object='string/test_libguac-strljoin.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o string/test_libguac-strljoin.o `test -f 'string/strljoin.c' || echo '$(srcdir)/'`string/strljoin.c string/test_libguac-strljoin.obj: string/strljoin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT string/test_libguac-strljoin.obj -MD -MP -MF string/$(DEPDIR)/test_libguac-strljoin.Tpo -c -o string/test_libguac-strljoin.obj `if test -f 'string/strljoin.c'; then $(CYGPATH_W) 'string/strljoin.c'; else $(CYGPATH_W) '$(srcdir)/string/strljoin.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) string/$(DEPDIR)/test_libguac-strljoin.Tpo string/$(DEPDIR)/test_libguac-strljoin.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string/strljoin.c' object='string/test_libguac-strljoin.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o string/test_libguac-strljoin.obj `if test -f 'string/strljoin.c'; then $(CYGPATH_W) 'string/strljoin.c'; else $(CYGPATH_W) '$(srcdir)/string/strljoin.c'; fi` unicode/test_libguac-charsize.o: unicode/charsize.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT unicode/test_libguac-charsize.o -MD -MP -MF unicode/$(DEPDIR)/test_libguac-charsize.Tpo -c -o unicode/test_libguac-charsize.o `test -f 'unicode/charsize.c' || echo '$(srcdir)/'`unicode/charsize.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unicode/$(DEPDIR)/test_libguac-charsize.Tpo unicode/$(DEPDIR)/test_libguac-charsize.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unicode/charsize.c' object='unicode/test_libguac-charsize.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o unicode/test_libguac-charsize.o `test -f 'unicode/charsize.c' || echo '$(srcdir)/'`unicode/charsize.c unicode/test_libguac-charsize.obj: unicode/charsize.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT unicode/test_libguac-charsize.obj -MD -MP -MF unicode/$(DEPDIR)/test_libguac-charsize.Tpo -c -o unicode/test_libguac-charsize.obj `if test -f 'unicode/charsize.c'; then $(CYGPATH_W) 'unicode/charsize.c'; else $(CYGPATH_W) '$(srcdir)/unicode/charsize.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unicode/$(DEPDIR)/test_libguac-charsize.Tpo unicode/$(DEPDIR)/test_libguac-charsize.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unicode/charsize.c' object='unicode/test_libguac-charsize.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o unicode/test_libguac-charsize.obj `if test -f 'unicode/charsize.c'; then $(CYGPATH_W) 'unicode/charsize.c'; else $(CYGPATH_W) '$(srcdir)/unicode/charsize.c'; fi` unicode/test_libguac-read.o: unicode/read.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT unicode/test_libguac-read.o -MD -MP -MF unicode/$(DEPDIR)/test_libguac-read.Tpo -c -o unicode/test_libguac-read.o `test -f 'unicode/read.c' || echo '$(srcdir)/'`unicode/read.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unicode/$(DEPDIR)/test_libguac-read.Tpo unicode/$(DEPDIR)/test_libguac-read.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unicode/read.c' object='unicode/test_libguac-read.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o unicode/test_libguac-read.o `test -f 'unicode/read.c' || echo '$(srcdir)/'`unicode/read.c unicode/test_libguac-read.obj: unicode/read.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT unicode/test_libguac-read.obj -MD -MP -MF unicode/$(DEPDIR)/test_libguac-read.Tpo -c -o unicode/test_libguac-read.obj `if test -f 'unicode/read.c'; then $(CYGPATH_W) 'unicode/read.c'; else $(CYGPATH_W) '$(srcdir)/unicode/read.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unicode/$(DEPDIR)/test_libguac-read.Tpo unicode/$(DEPDIR)/test_libguac-read.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unicode/read.c' object='unicode/test_libguac-read.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o unicode/test_libguac-read.obj `if test -f 'unicode/read.c'; then $(CYGPATH_W) 'unicode/read.c'; else $(CYGPATH_W) '$(srcdir)/unicode/read.c'; fi` unicode/test_libguac-strlen.o: unicode/strlen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT unicode/test_libguac-strlen.o -MD -MP -MF unicode/$(DEPDIR)/test_libguac-strlen.Tpo -c -o unicode/test_libguac-strlen.o `test -f 'unicode/strlen.c' || echo '$(srcdir)/'`unicode/strlen.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unicode/$(DEPDIR)/test_libguac-strlen.Tpo unicode/$(DEPDIR)/test_libguac-strlen.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unicode/strlen.c' object='unicode/test_libguac-strlen.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o unicode/test_libguac-strlen.o `test -f 'unicode/strlen.c' || echo '$(srcdir)/'`unicode/strlen.c unicode/test_libguac-strlen.obj: unicode/strlen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT unicode/test_libguac-strlen.obj -MD -MP -MF unicode/$(DEPDIR)/test_libguac-strlen.Tpo -c -o unicode/test_libguac-strlen.obj `if test -f 'unicode/strlen.c'; then $(CYGPATH_W) 'unicode/strlen.c'; else $(CYGPATH_W) '$(srcdir)/unicode/strlen.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unicode/$(DEPDIR)/test_libguac-strlen.Tpo unicode/$(DEPDIR)/test_libguac-strlen.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unicode/strlen.c' object='unicode/test_libguac-strlen.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o unicode/test_libguac-strlen.obj `if test -f 'unicode/strlen.c'; then $(CYGPATH_W) 'unicode/strlen.c'; else $(CYGPATH_W) '$(srcdir)/unicode/strlen.c'; fi` unicode/test_libguac-write.o: unicode/write.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT unicode/test_libguac-write.o -MD -MP -MF unicode/$(DEPDIR)/test_libguac-write.Tpo -c -o unicode/test_libguac-write.o `test -f 'unicode/write.c' || echo '$(srcdir)/'`unicode/write.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unicode/$(DEPDIR)/test_libguac-write.Tpo unicode/$(DEPDIR)/test_libguac-write.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unicode/write.c' object='unicode/test_libguac-write.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o unicode/test_libguac-write.o `test -f 'unicode/write.c' || echo '$(srcdir)/'`unicode/write.c unicode/test_libguac-write.obj: unicode/write.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT unicode/test_libguac-write.obj -MD -MP -MF unicode/$(DEPDIR)/test_libguac-write.Tpo -c -o unicode/test_libguac-write.obj `if test -f 'unicode/write.c'; then $(CYGPATH_W) 'unicode/write.c'; else $(CYGPATH_W) '$(srcdir)/unicode/write.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) unicode/$(DEPDIR)/test_libguac-write.Tpo unicode/$(DEPDIR)/test_libguac-write.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unicode/write.c' object='unicode/test_libguac-write.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o unicode/test_libguac-write.obj `if test -f 'unicode/write.c'; then $(CYGPATH_W) 'unicode/write.c'; else $(CYGPATH_W) '$(srcdir)/unicode/write.c'; fi` test_libguac-_generated_runner.o: _generated_runner.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT test_libguac-_generated_runner.o -MD -MP -MF $(DEPDIR)/test_libguac-_generated_runner.Tpo -c -o test_libguac-_generated_runner.o `test -f '_generated_runner.c' || echo '$(srcdir)/'`_generated_runner.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_libguac-_generated_runner.Tpo $(DEPDIR)/test_libguac-_generated_runner.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='_generated_runner.c' object='test_libguac-_generated_runner.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o test_libguac-_generated_runner.o `test -f '_generated_runner.c' || echo '$(srcdir)/'`_generated_runner.c test_libguac-_generated_runner.obj: _generated_runner.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -MT test_libguac-_generated_runner.obj -MD -MP -MF $(DEPDIR)/test_libguac-_generated_runner.Tpo -c -o test_libguac-_generated_runner.obj `if test -f '_generated_runner.c'; then $(CYGPATH_W) '_generated_runner.c'; else $(CYGPATH_W) '$(srcdir)/_generated_runner.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_libguac-_generated_runner.Tpo $(DEPDIR)/test_libguac-_generated_runner.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='_generated_runner.c' object='test_libguac-_generated_runner.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libguac_CFLAGS) $(CFLAGS) -c -o test_libguac-_generated_runner.obj `if test -f '_generated_runner.c'; then $(CYGPATH_W) '_generated_runner.c'; else $(CYGPATH_W) '$(srcdir)/_generated_runner.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: $(check_PROGRAMS) @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_libguac.log: test_libguac$(EXEEXT) @p='test_libguac$(EXEEXT)'; \ b='test_libguac'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f client/$(DEPDIR)/$(am__dirstamp) -rm -f client/$(am__dirstamp) -rm -f parser/$(DEPDIR)/$(am__dirstamp) -rm -f parser/$(am__dirstamp) -rm -f pool/$(DEPDIR)/$(am__dirstamp) -rm -f pool/$(am__dirstamp) -rm -f protocol/$(DEPDIR)/$(am__dirstamp) -rm -f protocol/$(am__dirstamp) -rm -f socket/$(DEPDIR)/$(am__dirstamp) -rm -f socket/$(am__dirstamp) -rm -f string/$(DEPDIR)/$(am__dirstamp) -rm -f string/$(am__dirstamp) -rm -f unicode/$(DEPDIR)/$(am__dirstamp) -rm -f unicode/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/test_libguac-_generated_runner.Po -rm -f client/$(DEPDIR)/test_libguac-buffer_pool.Po -rm -f client/$(DEPDIR)/test_libguac-layer_pool.Po -rm -f parser/$(DEPDIR)/test_libguac-append.Po -rm -f parser/$(DEPDIR)/test_libguac-read.Po -rm -f pool/$(DEPDIR)/test_libguac-next_free.Po -rm -f protocol/$(DEPDIR)/test_libguac-base64_decode.Po -rm -f protocol/$(DEPDIR)/test_libguac-guac_protocol_version.Po -rm -f socket/$(DEPDIR)/test_libguac-fd_send_instruction.Po -rm -f socket/$(DEPDIR)/test_libguac-nested_send_instruction.Po -rm -f string/$(DEPDIR)/test_libguac-strdup.Po -rm -f string/$(DEPDIR)/test_libguac-strlcat.Po -rm -f string/$(DEPDIR)/test_libguac-strlcpy.Po -rm -f string/$(DEPDIR)/test_libguac-strljoin.Po -rm -f unicode/$(DEPDIR)/test_libguac-charsize.Po -rm -f unicode/$(DEPDIR)/test_libguac-read.Po -rm -f unicode/$(DEPDIR)/test_libguac-strlen.Po -rm -f unicode/$(DEPDIR)/test_libguac-write.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/test_libguac-_generated_runner.Po -rm -f client/$(DEPDIR)/test_libguac-buffer_pool.Po -rm -f client/$(DEPDIR)/test_libguac-layer_pool.Po -rm -f parser/$(DEPDIR)/test_libguac-append.Po -rm -f parser/$(DEPDIR)/test_libguac-read.Po -rm -f pool/$(DEPDIR)/test_libguac-next_free.Po -rm -f protocol/$(DEPDIR)/test_libguac-base64_decode.Po -rm -f protocol/$(DEPDIR)/test_libguac-guac_protocol_version.Po -rm -f socket/$(DEPDIR)/test_libguac-fd_send_instruction.Po -rm -f socket/$(DEPDIR)/test_libguac-nested_send_instruction.Po -rm -f string/$(DEPDIR)/test_libguac-strdup.Po -rm -f string/$(DEPDIR)/test_libguac-strlcat.Po -rm -f string/$(DEPDIR)/test_libguac-strlcpy.Po -rm -f string/$(DEPDIR)/test_libguac-strljoin.Po -rm -f unicode/$(DEPDIR)/test_libguac-charsize.Po -rm -f unicode/$(DEPDIR)/test_libguac-read.Po -rm -f unicode/$(DEPDIR)/test_libguac-strlen.Po -rm -f unicode/$(DEPDIR)/test_libguac-write.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am .PRECIOUS: Makefile _generated_runner.c: $(test_libguac_SOURCES) $(AM_V_GEN) $(GEN_RUNNER) $(test_libguac_SOURCES) > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/libguac/tests/string/0000755000175100001440000000000013772471155016633 500000000000000guacamole-server-1.3.0/src/libguac/tests/string/strlcpy.c0000644000175100001440000000623213764613616020423 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include /** * Verify guac_strlcpy() behavior when the string fits the buffer without * truncation. */ void test_string__strlcpy() { char buffer[1024]; memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strlcpy(buffer, "Guacamole", sizeof(buffer)), 9); CU_ASSERT_STRING_EQUAL(buffer, "Guacamole"); CU_ASSERT_EQUAL(buffer[10], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strlcpy(buffer, "This is a test", sizeof(buffer)), 14); CU_ASSERT_STRING_EQUAL(buffer, "This is a test"); CU_ASSERT_EQUAL(buffer[15], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strlcpy(buffer, "X", sizeof(buffer)), 1); CU_ASSERT_STRING_EQUAL(buffer, "X"); CU_ASSERT_EQUAL(buffer[2], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strlcpy(buffer, "", sizeof(buffer)), 0); CU_ASSERT_STRING_EQUAL(buffer, ""); CU_ASSERT_EQUAL(buffer[1], '\xFF'); } /** * Verify guac_strlcpy() behavior when the string must be truncated to fit the * buffer. */ void test_string__strlcpy_truncate() { char buffer[1024]; memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strlcpy(buffer, "Guacamole", 6), 9); CU_ASSERT_STRING_EQUAL(buffer, "Guaca"); CU_ASSERT_EQUAL(buffer[6], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strlcpy(buffer, "This is a test", 10), 14); CU_ASSERT_STRING_EQUAL(buffer, "This is a"); CU_ASSERT_EQUAL(buffer[10], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strlcpy(buffer, "This is ANOTHER test", 2), 20); CU_ASSERT_STRING_EQUAL(buffer, "T"); CU_ASSERT_EQUAL(buffer[2], '\xFF'); } /** * Verify guac_strlcpy() behavior with zero buffer sizes. */ void test_string__strlcpy_nospace() { /* 0-byte buffer plus 1 guard byte (to test overrun) */ char buffer[1] = { '\xFF' }; CU_ASSERT_EQUAL(guac_strlcpy(buffer, "Guacamole", 0), 9); CU_ASSERT_EQUAL(buffer[0], '\xFF'); CU_ASSERT_EQUAL(guac_strlcpy(buffer, "This is a test", 0), 14); CU_ASSERT_EQUAL(buffer[0], '\xFF'); CU_ASSERT_EQUAL(guac_strlcpy(buffer, "X", 0), 1); CU_ASSERT_EQUAL(buffer[0], '\xFF'); CU_ASSERT_EQUAL(guac_strlcpy(buffer, "", 0), 0); CU_ASSERT_EQUAL(buffer[0], '\xFF'); } guacamole-server-1.3.0/src/libguac/tests/string/strljoin.c0000644000175100001440000001233613764613616020571 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include /** * Array of test elements containing the strings "Apache" and "Guacamole". */ const char* const apache_guacamole[] = { "Apache", "Guacamole" }; /** * Array of test elements containing the strings "This", "is", "a", and "test". */ const char* const this_is_a_test[] = { "This", "is", "a", "test" }; /** * Array of four test elements containing the strings "A" and "B", each * preceded by an empty string (""). */ const char* const empty_a_empty_b[] = { "", "A", "", "B" }; /** * Array of test elements containing ten empty strings. */ const char* const empty_x10[] = { "", "", "", "", "", "", "", "", "", "" }; /** * Verify guac_strljoin() behavior when the string fits the buffer without * truncation. The return value of each call should be the length of the * resulting string. Each resulting string should contain the full result of * the join operation, including null terminator. */ void test_string__strljoin() { char buffer[1024]; memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strljoin(buffer, apache_guacamole, 2, " ", sizeof(buffer)), 16); CU_ASSERT_STRING_EQUAL(buffer, "Apache Guacamole"); CU_ASSERT_EQUAL(buffer[17], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strljoin(buffer, this_is_a_test, 4, "", sizeof(buffer)), 11); CU_ASSERT_STRING_EQUAL(buffer, "Thisisatest"); CU_ASSERT_EQUAL(buffer[12], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strljoin(buffer, this_is_a_test, 4, "-/-", sizeof(buffer)), 20); CU_ASSERT_STRING_EQUAL(buffer, "This-/-is-/-a-/-test"); CU_ASSERT_EQUAL(buffer[21], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strljoin(buffer, empty_a_empty_b, 4, "/", sizeof(buffer)), 5); CU_ASSERT_STRING_EQUAL(buffer, "/A//B"); CU_ASSERT_EQUAL(buffer[6], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strljoin(buffer, empty_x10, 10, "/", sizeof(buffer)), 9); CU_ASSERT_STRING_EQUAL(buffer, "/////////"); CU_ASSERT_EQUAL(buffer[10], '\xFF'); } /** * Verify guac_strljoin() behavior when the string must be truncated to fit the * buffer. The return value of each call should be the length that would result * from joining the strings given an infinite buffer, however only as many * characters as can fit should be appended to the string within the buffer, * and the buffer should be null-terminated. */ void test_string__strljoin_truncate() { char buffer[1024]; memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strljoin(buffer, apache_guacamole, 2, " ", 9), 16); CU_ASSERT_STRING_EQUAL(buffer, "Apache G"); CU_ASSERT_EQUAL(buffer[9], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strljoin(buffer, this_is_a_test, 4, "", 8), 11); CU_ASSERT_STRING_EQUAL(buffer, "Thisisa"); CU_ASSERT_EQUAL(buffer[8], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strljoin(buffer, this_is_a_test, 4, "-/-", 12), 20); CU_ASSERT_STRING_EQUAL(buffer, "This-/-is-/"); CU_ASSERT_EQUAL(buffer[12], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strljoin(buffer, empty_a_empty_b, 4, "/", 2), 5); CU_ASSERT_STRING_EQUAL(buffer, "/"); CU_ASSERT_EQUAL(buffer[2], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strljoin(buffer, empty_x10, 10, "/", 7), 9); CU_ASSERT_STRING_EQUAL(buffer, "//////"); CU_ASSERT_EQUAL(buffer[7], '\xFF'); } /** * Verify guac_strljoin() behavior with zero buffer sizes. The return value of * each call should be the size of the input string, while the buffer remains * untouched. */ void test_string__strljoin_nospace() { /* 0-byte buffer plus 1 guard byte (to test overrun) */ char buffer[1] = { '\xFF' }; CU_ASSERT_EQUAL(guac_strljoin(buffer, apache_guacamole, 2, " ", 0), 16); CU_ASSERT_EQUAL(buffer[0], '\xFF'); CU_ASSERT_EQUAL(guac_strljoin(buffer, this_is_a_test, 4, "", 0), 11); CU_ASSERT_EQUAL(buffer[0], '\xFF'); CU_ASSERT_EQUAL(guac_strljoin(buffer, this_is_a_test, 4, "-/-", 0), 20); CU_ASSERT_EQUAL(buffer[0], '\xFF'); CU_ASSERT_EQUAL(guac_strljoin(buffer, empty_a_empty_b, 4, "/", 0), 5); CU_ASSERT_EQUAL(buffer[0], '\xFF'); CU_ASSERT_EQUAL(guac_strljoin(buffer, empty_x10, 10, "/", 0), 9); CU_ASSERT_EQUAL(buffer[0], '\xFF'); } guacamole-server-1.3.0/src/libguac/tests/string/strdup.c0000644000175100001440000000272113770536337020244 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include /** * Source test string for copying. */ const char* source_string = "Mashing avocados."; /** * A NULL string variable for copying to insure that NULL is copied properly. */ const char* null_string = NULL; /** * Verify guac_strdup() behavior when the string is both NULL and not NULL. */ void test_string__strdup() { /* Copy the strings. */ char* dest_string = guac_strdup(source_string); char* null_copy = guac_strdup(null_string); /* Run the tests. */ CU_ASSERT_STRING_EQUAL(dest_string, "Mashing avocados."); CU_ASSERT_PTR_NULL(null_copy); }guacamole-server-1.3.0/src/libguac/tests/string/strlcat.c0000644000175100001440000001225513764613616020401 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include /** * Verify guac_strlcat() behavior when the string fits the buffer without * truncation. The return value of each call should be the length of the * resulting string. Each resulting string should contain the full result of * the concatenation, including null terminator. */ void test_string__strlcat() { char buffer[1024]; memset(buffer, 0xFF, sizeof(buffer)); strcpy(buffer, "Apache "); CU_ASSERT_EQUAL(guac_strlcat(buffer, "Guacamole", sizeof(buffer)), 16); CU_ASSERT_STRING_EQUAL(buffer, "Apache Guacamole"); CU_ASSERT_EQUAL(buffer[17], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); strcpy(buffer, ""); CU_ASSERT_EQUAL(guac_strlcat(buffer, "This is a test", sizeof(buffer)), 14); CU_ASSERT_STRING_EQUAL(buffer, "This is a test"); CU_ASSERT_EQUAL(buffer[15], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); strcpy(buffer, "AB"); CU_ASSERT_EQUAL(guac_strlcat(buffer, "X", sizeof(buffer)), 3); CU_ASSERT_STRING_EQUAL(buffer, "ABX"); CU_ASSERT_EQUAL(buffer[4], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); strcpy(buffer, "X"); CU_ASSERT_EQUAL(guac_strlcat(buffer, "", sizeof(buffer)), 1); CU_ASSERT_STRING_EQUAL(buffer, "X"); CU_ASSERT_EQUAL(buffer[2], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); strcpy(buffer, ""); CU_ASSERT_EQUAL(guac_strlcat(buffer, "", sizeof(buffer)), 0); CU_ASSERT_STRING_EQUAL(buffer, ""); CU_ASSERT_EQUAL(buffer[1], '\xFF'); } /** * Verify guac_strlcat() behavior when the string must be truncated to fit the * buffer. The return value of each call should be the length that would result * from concatenating the strings given an infinite buffer, however only as * many characters as can fit should be appended to the string within the * buffer, and the buffer should be null-terminated. */ void test_string__strlcat_truncate() { char buffer[1024]; memset(buffer, 0xFF, sizeof(buffer)); strcpy(buffer, "Apache "); CU_ASSERT_EQUAL(guac_strlcat(buffer, "Guacamole", 9), 16); CU_ASSERT_STRING_EQUAL(buffer, "Apache G"); CU_ASSERT_EQUAL(buffer[9], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); strcpy(buffer, ""); CU_ASSERT_EQUAL(guac_strlcat(buffer, "This is a test", 10), 14); CU_ASSERT_STRING_EQUAL(buffer, "This is a"); CU_ASSERT_EQUAL(buffer[10], '\xFF'); memset(buffer, 0xFF, sizeof(buffer)); strcpy(buffer, "This "); CU_ASSERT_EQUAL(guac_strlcat(buffer, "is ANOTHER test", 6), 20); CU_ASSERT_STRING_EQUAL(buffer, "This "); CU_ASSERT_EQUAL(buffer[6], '\xFF'); } /** * Verify guac_strlcat() behavior with zero buffer sizes. The return value of * each call should be the size of the input string, while the buffer remains * untouched. */ void test_string__strlcat_nospace() { /* 0-byte buffer plus 1 guard byte (to test overrun) */ char buffer[1] = { '\xFF' }; CU_ASSERT_EQUAL(guac_strlcat(buffer, "Guacamole", 0), 9); CU_ASSERT_EQUAL(buffer[0], '\xFF'); CU_ASSERT_EQUAL(guac_strlcat(buffer, "This is a test", 0), 14); CU_ASSERT_EQUAL(buffer[0], '\xFF'); CU_ASSERT_EQUAL(guac_strlcat(buffer, "X", 0), 1); CU_ASSERT_EQUAL(buffer[0], '\xFF'); CU_ASSERT_EQUAL(guac_strlcat(buffer, "", 0), 0); CU_ASSERT_EQUAL(buffer[0], '\xFF'); } /** * Verify guac_strlcat() behavior with unterminated buffers. With respect to * the return value, the length of the string in the buffer should be * considered equal to the size of the buffer, however the resulting buffer * should not be null-terminated. */ void test_string__strlcat_nonull() { char expected[1024]; memset(expected, 0xFF, sizeof(expected)); char buffer[1024]; memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strlcat(buffer, "Guacamole", 256), 265); CU_ASSERT_NSTRING_EQUAL(buffer, expected, sizeof(expected)); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strlcat(buffer, "This is a test", 37), 51); CU_ASSERT_NSTRING_EQUAL(buffer, expected, sizeof(expected)); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strlcat(buffer, "X", 12), 13); CU_ASSERT_NSTRING_EQUAL(buffer, expected, sizeof(expected)); memset(buffer, 0xFF, sizeof(buffer)); CU_ASSERT_EQUAL(guac_strlcat(buffer, "", 100), 100); CU_ASSERT_NSTRING_EQUAL(buffer, expected, sizeof(expected)); } guacamole-server-1.3.0/src/libguac/tests/unicode/0000755000175100001440000000000013772471155016753 500000000000000guacamole-server-1.3.0/src/libguac/tests/unicode/strlen.c0000644000175100001440000000372313726006252020342 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include /** * A single Unicode character encoded as one byte with UTF-8. */ #define UTF8_1b "g" /** * A single Unicode character encoded as two bytes with UTF-8. */ #define UTF8_2b "\xc4\xa3" /** * A single Unicode character encoded as three bytes with UTF-8. */ #define UTF8_3b "\xe7\x8a\xac" /** * A single Unicode character encoded as four bytes with UTF-8. */ #define UTF8_4b "\xf0\x90\x84\xa3" /** * Test which verifies that guac_utf8_strlen() properly calculates the length * of UTF-8 strings. */ void test_unicode__utf8_strlen() { CU_ASSERT_EQUAL(0, guac_utf8_strlen("")); CU_ASSERT_EQUAL(1, guac_utf8_strlen(UTF8_4b)); CU_ASSERT_EQUAL(2, guac_utf8_strlen(UTF8_4b UTF8_1b)); CU_ASSERT_EQUAL(2, guac_utf8_strlen(UTF8_2b UTF8_3b)); CU_ASSERT_EQUAL(3, guac_utf8_strlen(UTF8_1b UTF8_3b UTF8_4b)); CU_ASSERT_EQUAL(3, guac_utf8_strlen(UTF8_2b UTF8_1b UTF8_3b)); CU_ASSERT_EQUAL(3, guac_utf8_strlen(UTF8_4b UTF8_2b UTF8_1b)); CU_ASSERT_EQUAL(3, guac_utf8_strlen(UTF8_3b UTF8_4b UTF8_2b)); CU_ASSERT_EQUAL(5, guac_utf8_strlen("hello")); CU_ASSERT_EQUAL(9, guac_utf8_strlen("guacamole")); } guacamole-server-1.3.0/src/libguac/tests/unicode/write.c0000644000175100001440000000332113726006252020157 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include /** * Test which verifies that guac_utf8_write() properly encodes Unicode * codepoints as UTF-8. */ void test_unicode__utf8_write() { char buffer[16]; /* Test writes */ CU_ASSERT_EQUAL(1, guac_utf8_write(0x00065, &(buffer[0]), 10)); CU_ASSERT_EQUAL(2, guac_utf8_write(0x00654, &(buffer[1]), 9)); CU_ASSERT_EQUAL(3, guac_utf8_write(0x00876, &(buffer[3]), 7)); CU_ASSERT_EQUAL(4, guac_utf8_write(0x12345, &(buffer[6]), 4)); CU_ASSERT_EQUAL(0, guac_utf8_write(0x00066, &(buffer[10]), 0)); /* Test result of write */ CU_ASSERT(memcmp("\x65", &(buffer[0]), 1) == 0); /* U+0065 */ CU_ASSERT(memcmp("\xD9\x94", &(buffer[1]), 2) == 0); /* U+0654 */ CU_ASSERT(memcmp("\xE0\xA1\xB6", &(buffer[3]), 3) == 0); /* U+0876 */ CU_ASSERT(memcmp("\xF0\x92\x8D\x85", &(buffer[6]), 4) == 0); /* U+12345 */ } guacamole-server-1.3.0/src/libguac/tests/unicode/charsize.c0000644000175100001440000000236013726006252020637 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include /** * Test which verifies that guac_utf8_charsize() correctly determines the * length of UTF-8 characters from the leading byte of that character. */ void test_unicode__utf8_charsize() { CU_ASSERT_EQUAL(1, guac_utf8_charsize('g')); CU_ASSERT_EQUAL(2, guac_utf8_charsize('\xC4')); CU_ASSERT_EQUAL(3, guac_utf8_charsize('\xE7')); CU_ASSERT_EQUAL(4, guac_utf8_charsize('\xF0')); } guacamole-server-1.3.0/src/libguac/tests/unicode/read.c0000644000175100001440000000327013726006252017743 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include /** * Test which verifies that guac_utf8_read() properly parses UTF-8. */ void test_unicode__utf8_read() { int codepoint; char buffer[16] = /* U+0065 */ "\x65" /* U+0654 */ "\xD9\x94" /* U+0876 */ "\xE0\xA1\xB6" /* U+12345 */ "\xF0\x92\x8D\x85"; CU_ASSERT_EQUAL(1, guac_utf8_read(&(buffer[0]), 10, &codepoint)); CU_ASSERT_EQUAL(0x0065, codepoint); CU_ASSERT_EQUAL(2, guac_utf8_read(&(buffer[1]), 9, &codepoint)); CU_ASSERT_EQUAL(0x0654, codepoint); CU_ASSERT_EQUAL(3, guac_utf8_read(&(buffer[3]), 7, &codepoint)); CU_ASSERT_EQUAL(0x0876, codepoint); CU_ASSERT_EQUAL(4, guac_utf8_read(&(buffer[6]), 4, &codepoint)); CU_ASSERT_EQUAL(0x12345, codepoint); CU_ASSERT_EQUAL(0, guac_utf8_read(&(buffer[10]), 0, &codepoint)); CU_ASSERT_EQUAL(0x12345, codepoint); } guacamole-server-1.3.0/src/libguac/tests/parser/0000755000175100001440000000000013772471155016621 500000000000000guacamole-server-1.3.0/src/libguac/tests/parser/append.c0000644000175100001440000000476013726006252020152 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include /** * Test which verifies that guac_parser correctly parses Guacamole instructions * from arbitrary blocks of data passed to guac_parser_append(). */ void test_parser__append() { /* Allocate parser */ guac_parser* parser = guac_parser_alloc(); CU_ASSERT_PTR_NOT_NULL_FATAL(parser); /* Instruction input */ char buffer[] = "4.test,8.testdata,5.zxcvb,13.guacamoletest;XXXXXXXXXXXXXXXXXX"; char* current = buffer; /* While data remains */ int remaining = sizeof(buffer)-1; while (remaining > 18) { /* Parse more data */ int parsed = guac_parser_append(parser, current, remaining); if (parsed == 0) break; current += parsed; remaining -= parsed; } /* Parse of instruction should be complete */ CU_ASSERT_EQUAL(remaining, 18); CU_ASSERT_EQUAL(parser->state, GUAC_PARSE_COMPLETE); /* Parse is complete - no more data should be read */ CU_ASSERT_EQUAL(guac_parser_append(parser, current, 18), 0); CU_ASSERT_EQUAL(parser->state, GUAC_PARSE_COMPLETE); /* Validate resulting structure */ CU_ASSERT_EQUAL(parser->argc, 3); CU_ASSERT_PTR_NOT_NULL_FATAL(parser->opcode); CU_ASSERT_PTR_NOT_NULL_FATAL(parser->argv[0]); CU_ASSERT_PTR_NOT_NULL_FATAL(parser->argv[1]); CU_ASSERT_PTR_NOT_NULL_FATAL(parser->argv[2]); /* Validate resulting content */ CU_ASSERT_STRING_EQUAL(parser->opcode, "test"); CU_ASSERT_STRING_EQUAL(parser->argv[0], "testdata"); CU_ASSERT_STRING_EQUAL(parser->argv[1], "zxcvb"); CU_ASSERT_STRING_EQUAL(parser->argv[2], "guacamoletest"); } guacamole-server-1.3.0/src/libguac/tests/parser/read.c0000644000175100001440000001107013726006252017606 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include /** * Test string which contains exactly four Unicode characters encoded in UTF-8. * This particular test string uses several characters which encode to multiple * bytes in UTF-8. */ #define UTF8_4 "\xe7\x8a\xac\xf0\x90\xac\x80z\xc3\xa1" /** * Writes a series of Guacamole instructions as raw bytes to the given file * descriptor. The instructions written correspond to the instructions verified * by read_expected_instructions(). The given file descriptor is automatically * closed as a result of calling this function. * * @param fd * The file descriptor to write instructions to. */ static void write_instructions(int fd) { char test_string[] = "4.test,6.a" UTF8_4 "b," "5.12345,10.a" UTF8_4 UTF8_4 "c;" "5.test2,10.hellohello,15.worldworldworld;"; char* current = test_string; int remaining = sizeof(test_string) - 1; /* Write all bytes in test string */ while (remaining > 0) { /* Bail out immediately if write fails (test will fail in parent * process due to failure to read) */ int written = write(fd, current, remaining); if (written <= 0) break; current += written; remaining -= written; } /* Done writing */ close(fd); } /** * Reads and parses instructions from the given file descriptor using a * guac_socket and guac_parser, verfying that those instructions match the * series of Guacamole instructions expected to be written by * write_instructions(). The given file descriptor is automatically closed as a * result of calling this function. * * @param fd * The file descriptor to read data from. */ static void read_expected_instructions(int fd) { /* Open guac socket */ guac_socket* socket = guac_socket_open(fd); CU_ASSERT_PTR_NOT_NULL_FATAL(socket); /* Allocate parser */ guac_parser* parser = guac_parser_alloc(); CU_ASSERT_PTR_NOT_NULL_FATAL(parser); /* Read and validate first instruction */ CU_ASSERT_EQUAL_FATAL(guac_parser_read(parser, socket, 1000000), 0); CU_ASSERT_STRING_EQUAL(parser->opcode, "test"); CU_ASSERT_EQUAL_FATAL(parser->argc, 3); CU_ASSERT_STRING_EQUAL(parser->argv[0], "a" UTF8_4 "b"); CU_ASSERT_STRING_EQUAL(parser->argv[1], "12345"); CU_ASSERT_STRING_EQUAL(parser->argv[2], "a" UTF8_4 UTF8_4 "c"); /* Read and validate second instruction */ CU_ASSERT_EQUAL_FATAL(guac_parser_read(parser, socket, 1000000), 0); CU_ASSERT_STRING_EQUAL(parser->opcode, "test2"); CU_ASSERT_EQUAL_FATAL(parser->argc, 2); CU_ASSERT_STRING_EQUAL(parser->argv[0], "hellohello"); CU_ASSERT_STRING_EQUAL(parser->argv[1], "worldworldworld"); /* Done */ guac_parser_free(parser); guac_socket_free(socket); } /** * Tests that guac_parser_read() correctly reads and parses instructions * received over a guac_socket. A child process is forked to write a series of * instructions which are read and verified by the parent process. */ void test_parser__read() { int fd[2]; /* Create pipe */ CU_ASSERT_EQUAL_FATAL(pipe(fd), 0); int read_fd = fd[0]; int write_fd = fd[1]; /* Fork into writer process (child) and reader process (parent) */ int childpid; CU_ASSERT_NOT_EQUAL_FATAL((childpid = fork()), -1); /* Attempt to write a series of instructions within the child process */ if (childpid == 0) { close(read_fd); write_instructions(write_fd); exit(0); } /* Read and verify the expected instructions within the parent process */ close(write_fd); read_expected_instructions(read_fd); } guacamole-server-1.3.0/src/libguac/tests/Makefile.am0000644000175100001440000000506113770536337017305 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 # # Unit tests for libguac # check_PROGRAMS = test_libguac TESTS = $(check_PROGRAMS) test_libguac_SOURCES = \ client/buffer_pool.c \ client/layer_pool.c \ parser/append.c \ parser/read.c \ pool/next_free.c \ protocol/base64_decode.c \ protocol/guac_protocol_version.c \ socket/fd_send_instruction.c \ socket/nested_send_instruction.c \ string/strdup.c \ string/strlcat.c \ string/strlcpy.c \ string/strljoin.c \ unicode/charsize.c \ unicode/read.c \ unicode/strlen.c \ unicode/write.c test_libguac_CFLAGS = \ -Werror -Wall -pedantic \ @LIBGUAC_INCLUDE@ test_libguac_LDADD = \ @CUNIT_LIBS@ \ @LIBGUAC_LTLIB@ # # Autogenerate test runner # GEN_RUNNER = $(top_srcdir)/util/generate-test-runner.pl CLEANFILES = _generated_runner.c _generated_runner.c: $(test_libguac_SOURCES) $(AM_V_GEN) $(GEN_RUNNER) $(test_libguac_SOURCES) > $@ nodist_test_libguac_SOURCES = \ _generated_runner.c # Use automake's TAP test driver for running any tests LOG_DRIVER = \ env AM_TAP_AWK='$(AWK)' \ $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh guacamole-server-1.3.0/src/libguac/timestamp.c0000644000175100001440000000357113764613616016261 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/timestamp.h" #include #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_NANOSLEEP) #include #endif guac_timestamp guac_timestamp_current() { #ifdef HAVE_CLOCK_GETTIME struct timespec current; /* Get current time, monotonically increasing */ #ifdef CLOCK_MONOTONIC clock_gettime(CLOCK_MONOTONIC, ¤t); #else clock_gettime(CLOCK_REALTIME, ¤t); #endif /* Calculate milliseconds */ return (guac_timestamp) current.tv_sec * 1000 + current.tv_nsec / 1000000; #else struct timeval current; /* Get current time */ gettimeofday(¤t, NULL); /* Calculate milliseconds */ return (guac_timestamp) current.tv_sec * 1000 + current.tv_usec / 1000; #endif } void guac_timestamp_msleep(int duration) { /* Split milliseconds into equivalent seconds + nanoseconds */ struct timespec sleep_period = { .tv_sec = duration / 1000, .tv_nsec = (duration % 1000) * 1000000 }; /* Sleep for specified interval */ nanosleep(&sleep_period, NULL); } guacamole-server-1.3.0/src/libguac/unicode.c0000644000175100001440000001001613764613616015674 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/unicode.h" #include size_t guac_utf8_charsize(unsigned char c) { /* Determine size in bytes of character */ if ((c | 0x7F) == 0x7F) return 1; if ((c | 0x1F) == 0xDF) return 2; if ((c | 0x0F) == 0xEF) return 3; if ((c | 0x07) == 0xF7) return 4; /* Default to one character */ return 1; } size_t guac_utf8_strlen(const char* str) { /* The current length of the string */ int length = 0; /* Number of characters before start of next character */ int skip = 0; while (*str != 0) { /* If skipping, then skip */ if (skip > 0) skip--; /* Otherwise, determine next skip value, and increment length */ else { /* Get next character */ unsigned char c = (unsigned char) *str; /* Determine skip value (size in bytes of rest of character) */ skip = guac_utf8_charsize(c) - 1; length++; } str++; } return length; } int guac_utf8_write(int codepoint, char* utf8, int length) { int i; int mask, bytes; /* If not even one byte, cannot write */ if (length <= 0) return 0; /* Determine size and initial byte mask */ if (codepoint <= 0x007F) { mask = 0x00; bytes = 1; } else if (codepoint <= 0x7FF) { mask = 0xC0; bytes = 2; } else if (codepoint <= 0xFFFF) { mask = 0xE0; bytes = 3; } else if (codepoint <= 0x1FFFFF) { mask = 0xF0; bytes = 4; } /* Otherwise, invalid codepoint */ else { *(utf8++) = '?'; return 1; } /* If not enough room, don't write anything */ if (bytes > length) return 0; /* Offset buffer by size */ utf8 += bytes - 1; /* Add trailing bytes, if any */ for (i=1; i>= 6; } /* Set initial byte */ *utf8 = mask | codepoint; /* Done */ return bytes; } int guac_utf8_read(const char* utf8, int length, int* codepoint) { unsigned char initial; int bytes; int result; int i; /* If not even one byte, cannot read */ if (length <= 0) return 0; /* Read initial byte */ initial = (unsigned char) *(utf8++); /* 0xxxxxxx */ if ((initial | 0x7F) == 0x7F) { result = initial; bytes = 1; } /* 110xxxxx 10xxxxxx */ else if ((initial | 0x1F) == 0xDF) { result = initial & 0x1F; bytes = 2; } /* 1110xxxx 10xxxxxx 10xxxxxx */ else if ((initial | 0x0F) == 0xEF) { result = initial & 0x0F; bytes = 3; } /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ else if ((initial | 0x07) == 0xF7) { result = initial & 0x07; bytes = 4; } /* Otherwise, invalid codepoint */ else { *codepoint = 0xFFFD; /* Replacement character */ return 1; } /* If not enough room, don't read anything */ if (bytes > length) return 0; /* Read trailing bytes, if any */ for (i=1; i #include #include #include #include #include /** * Extended version of the standard libjpeg jpeg_destination_mgr struct, which * provides access to the pointers to the output buffer and size. The values * of this structure will be initialized by jpeg_guac_dest(). */ typedef struct guac_jpeg_destination_mgr { /** * Original jpeg_destination_mgr structure. This MUST be the first member * for guac_jpeg_destination_mgr to be usable as a jpeg_destination_mgr. */ struct jpeg_destination_mgr parent; /** * The socket over which all JPEG blobs will be written. */ guac_socket* socket; /** * The Guacamole stream to associate with each JPEG blob. */ guac_stream* stream; /** * The output buffer. */ unsigned char buffer[GUAC_PROTOCOL_BLOB_MAX_LENGTH]; } guac_jpeg_destination_mgr; /** * Initializes the destination structure of the given compression structure. * * @param cinfo * The compression structure whose destination structure should be * initialized. */ static void guac_jpeg_init_destination(j_compress_ptr cinfo) { guac_jpeg_destination_mgr* dest = (guac_jpeg_destination_mgr*) cinfo->dest; /* Init parent destination state */ dest->parent.next_output_byte = dest->buffer; dest->parent.free_in_buffer = sizeof(dest->buffer); } /** * Flushes the current output buffer associated with the given compression * structure, as the current output buffer is full. * * @param cinfo * The compression structure whose output buffer should be flushed. * * @return * TRUE, always, indicating that space is now available. FALSE is returned * only by applications that may need additional time to empty the buffer. */ static boolean guac_jpeg_empty_output_buffer(j_compress_ptr cinfo) { guac_jpeg_destination_mgr* dest = (guac_jpeg_destination_mgr*) cinfo->dest; /* Write blob */ guac_protocol_send_blob(dest->socket, dest->stream, dest->buffer, sizeof(dest->buffer)); /* Update destination offset */ dest->parent.next_output_byte = dest->buffer; dest->parent.free_in_buffer = sizeof(dest->buffer); return TRUE; } /** * Flushes the final blob of JPEG data, if any, as JPEG compression is now * complete. * * @param cinfo * The compression structure associated with the now-complete JPEG * compression operation. */ static void guac_jpeg_term_destination(j_compress_ptr cinfo) { guac_jpeg_destination_mgr* dest = (guac_jpeg_destination_mgr*) cinfo->dest; /* Write final blob, if any */ if (dest->parent.free_in_buffer != sizeof(dest->buffer)) guac_protocol_send_blob(dest->socket, dest->stream, dest->buffer, sizeof(dest->buffer) - dest->parent.free_in_buffer); } /** * Configures the given compression structure to use the given Guacamole stream * for JPEG output. * * @param cinfo * The libjpeg compression structure to configure. * * @param socket * The Guacamole socket to use when sending blob instructions. * * @param stream * The stream over which JPEG-encoded blobs of image data should be sent. */ static void jpeg_guac_dest(j_compress_ptr cinfo, guac_socket* socket, guac_stream* stream) { guac_jpeg_destination_mgr* dest; /* Allocate dest from pool if not already allocated */ if (cinfo->dest == NULL) cinfo->dest = (struct jpeg_destination_mgr*) (cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(guac_jpeg_destination_mgr)); /* Pull possibly-new destination struct from cinfo */ dest = (guac_jpeg_destination_mgr*) cinfo->dest; /* Associate destination handlers */ dest->parent.init_destination = guac_jpeg_init_destination; dest->parent.empty_output_buffer = guac_jpeg_empty_output_buffer; dest->parent.term_destination = guac_jpeg_term_destination; /* Store Guacamole-specific objects */ dest->socket = socket; dest->stream = stream; } int guac_jpeg_write(guac_socket* socket, guac_stream* stream, cairo_surface_t* surface, int quality) { /* Get image surface properties and data */ cairo_format_t format = cairo_image_surface_get_format(surface); if (format != CAIRO_FORMAT_RGB24) { guac_error = GUAC_STATUS_INTERNAL_ERROR; guac_error_message = "Invalid Cairo image format. Unable to create JPEG."; return -1; } int width = cairo_image_surface_get_width(surface); int height = cairo_image_surface_get_height(surface); int stride = cairo_image_surface_get_stride(surface); unsigned char* data = cairo_image_surface_get_data(surface); /* Flush pending operations to surface */ cairo_surface_flush(surface); /* Prepare JPEG bits */ struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); /* Write JPEG directly to given stream */ jpeg_guac_dest(&cinfo, socket, stream); cinfo.image_width = width; /* image width and height, in pixels */ cinfo.image_height = height; cinfo.arith_code = TRUE; #ifdef JCS_EXTENSIONS /* The Turbo JPEG extentions allows us to use the Cairo surface * (BGRx) as input without converting it */ cinfo.input_components = 4; cinfo.in_color_space = JCS_EXT_BGRX; #else /* Standard JPEG supports RGB as input so we will have to convert * the contents of the Cairo surface from (BGRx) to RGB */ cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; /* Create a buffer for the write scan line which is where we will * put the converted pixels (BGRx -> RGB) */ int write_stride = cinfo.image_width * cinfo.input_components; unsigned char *scanline_data = malloc(write_stride); memset(scanline_data, 0, write_stride); #endif /* Initialize the JPEG compressor */ jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); jpeg_start_compress(&cinfo, TRUE); JSAMPROW row_pointer[1]; /* pointer to a single row */ /* Write scanlines to be used in JPEG compression */ while (cinfo.next_scanline < cinfo.image_height) { int row_offset = stride * cinfo.next_scanline; #ifdef JCS_EXTENSIONS /* In Turbo JPEG we can use the raw BGRx scanline */ row_pointer[0] = &data[row_offset]; #else /* For standard JPEG libraries we have to convert the * scanline from 24 bit (4 byte) BGRx to 24 bit (3 byte) RGB */ unsigned char *inptr = data + row_offset; unsigned char *outptr = scanline_data; for (int x = 0; x < width; ++x) { outptr[2] = *inptr++; /* B */ outptr[1] = *inptr++; /* G */ outptr[0] = *inptr++; /* R */ inptr++; /* skip the upper byte (x/A) */ outptr += 3; } row_pointer[0] = scanline_data; #endif jpeg_write_scanlines(&cinfo, row_pointer, 1); } #ifndef JCS_EXTENSIONS free(scanline_data); #endif /* Finalize compression */ jpeg_finish_compress(&cinfo); /* Clean up */ jpeg_destroy_compress(&cinfo); return 0; } guacamole-server-1.3.0/src/libguac/socket-wsa.c0000644000175100001440000003016313764613616016333 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "guacamole/error.h" #include "guacamole/socket.h" #include #include #include #include #include #include #include /** * Data associated with an open socket which uses the Windows Socket API. */ typedef struct guac_socket_wsa_data { /** * The associated Windows socket handle. */ SOCKET sock; /** * The number of bytes currently in the main write buffer. */ int written; /** * The main write buffer. Bytes written go here before being flushed * to the open socket. */ char out_buf[GUAC_SOCKET_OUTPUT_BUFFER_SIZE]; /** * Lock which is acquired when an instruction is being written, and * released when the instruction is finished being written. */ pthread_mutex_t socket_lock; /** * Lock which protects access to the internal buffer of this socket, * guaranteeing atomicity of writes and flushes. */ pthread_mutex_t buffer_lock; } guac_socket_wsa_data; /** * Writes the entire contents of the given buffer to the SOCKET handle * associated with the given socket, retrying as necessary until the whole * buffer is written, and aborting if an error occurs. * * @param socket * The guac_socket associated with the SOCKET handle to which the given * buffer should be written. * * @param buf * The buffer of data to write to the given guac_socket. * * @param count * The number of bytes within the given buffer. * * @return * The number of bytes written, which will be exactly the size of the given * buffer, or a negative value if an error occurs. */ ssize_t guac_socket_wsa_write(guac_socket* socket, const void* buf, size_t count) { guac_socket_wsa_data* data = (guac_socket_wsa_data*) socket->data; const char* buffer = buf; /* Write until completely written */ while (count > 0) { int retval = send(data->sock, buffer, count, 0); /* Record errors in guac_error */ if (retval < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Error writing data to socket"; return retval; } /* Advance buffer as data retval */ buffer += retval; count -= retval; } return 0; } /** * Attempts to read from the underlying SOCKET handle of the given guac_socket, * populating the given buffer. * * @param socket * The guac_socket being read from. * * @param buf * The arbitrary buffer which we must populate with data. * * @param count * The maximum number of bytes to read into the buffer. * * @return * The number of bytes read, or -1 if an error occurs. */ static ssize_t guac_socket_wsa_read_handler(guac_socket* socket, void* buf, size_t count) { guac_socket_wsa_data* data = (guac_socket_wsa_data*) socket->data; /* Read from socket */ int retval = recv(data->sock, buf, count, 0); /* Record errors in guac_error */ if (retval < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Error reading data from socket"; } return retval; } /** * Flushes the contents of the output buffer of the given socket immediately, * without first locking access to the output buffer. This function must ONLY * be called if the buffer lock has already been acquired. * * @param socket * The guac_socket to flush. * * @return * Zero if the flush operation was successful, non-zero otherwise. */ static ssize_t guac_socket_wsa_flush(guac_socket* socket) { guac_socket_wsa_data* data = (guac_socket_wsa_data*) socket->data; /* Flush remaining bytes in buffer */ if (data->written > 0) { /* Write ALL bytes in buffer immediately */ if (guac_socket_wsa_write(socket, data->out_buf, data->written)) return 1; data->written = 0; } return 0; } /** * Flushes the internal buffer of the given guac_socket, writing all data * to the underlying SOCKET handle. * * @param socket * The guac_socket to flush. * * @return * Zero if the flush operation was successful, non-zero otherwise. */ static ssize_t guac_socket_wsa_flush_handler(guac_socket* socket) { int retval; guac_socket_wsa_data* data = (guac_socket_wsa_data*) socket->data; /* Acquire exclusive access to buffer */ pthread_mutex_lock(&(data->buffer_lock)); /* Flush contents of buffer */ retval = guac_socket_wsa_flush(socket); /* Relinquish exclusive access to buffer */ pthread_mutex_unlock(&(data->buffer_lock)); return retval; } /** * Writes the contents of the buffer to the output buffer of the given socket, * flushing the output buffer as necessary, without first locking access to the * output buffer. This function must ONLY be called if the buffer lock has * already been acquired. * * @param socket * The guac_socket to write the given buffer to. * * @param buf * The buffer to write to the given socket. * * @param count * The number of bytes in the given buffer. * * @return * The number of bytes written, or a negative value if an error occurs * during write. */ static ssize_t guac_socket_wsa_write_buffered(guac_socket* socket, const void* buf, size_t count) { size_t original_count = count; const char* current = buf; guac_socket_wsa_data* data = (guac_socket_wsa_data*) socket->data; /* Append to buffer, flush if necessary */ while (count > 0) { int chunk_size; int remaining = sizeof(data->out_buf) - data->written; /* If no space left in buffer, flush and retry */ if (remaining == 0) { /* Abort if error occurs during flush */ if (guac_socket_wsa_flush(socket)) return -1; /* Retry buffer append */ continue; } /* Calculate size of chunk to be written to buffer */ chunk_size = count; if (chunk_size > remaining) chunk_size = remaining; /* Update output buffer */ memcpy(data->out_buf + data->written, current, chunk_size); data->written += chunk_size; /* Update provided buffer */ current += chunk_size; count -= chunk_size; } /* All bytes have been written, possibly some to the internal buffer */ return original_count; } /** * Appends the provided data to the internal buffer for future writing. The * actual write attempt will occur only upon flush, or when the internal buffer * is full. * * @param socket * The guac_socket being write to. * * @param buf * The arbitrary buffer containing the data to be written. * * @param count * The number of bytes contained within the buffer. * * @return * The number of bytes written, or -1 if an error occurs. */ static ssize_t guac_socket_wsa_write_handler(guac_socket* socket, const void* buf, size_t count) { int retval; guac_socket_wsa_data* data = (guac_socket_wsa_data*) socket->data; /* Acquire exclusive access to buffer */ pthread_mutex_lock(&(data->buffer_lock)); /* Write provided data to buffer */ retval = guac_socket_wsa_write_buffered(socket, buf, count); /* Relinquish exclusive access to buffer */ pthread_mutex_unlock(&(data->buffer_lock)); return retval; } /** * Waits for data on the underlying SOCKET handle of the given socket to * become available such that the next read operation will not block. * * @param socket * The guac_socket to wait for. * * @param usec_timeout * The maximum amount of time to wait for data, in microseconds, or -1 to * potentially wait forever. * * @return * A positive value on success, zero if the timeout elapsed and no data is * available, or a negative value if an error occurs. */ static int guac_socket_wsa_select_handler(guac_socket* socket, int usec_timeout) { guac_socket_wsa_data* data = (guac_socket_wsa_data*) socket->data; fd_set sockets; struct timeval timeout; int retval; /* Initialize fd_set with single underlying socket handle */ FD_ZERO(&sockets); FD_SET(data->sock, &sockets); /* No timeout if usec_timeout is negative */ if (usec_timeout < 0) retval = select(0, &sockets, NULL, NULL, NULL); /* Handle timeout if specified */ else { timeout.tv_sec = usec_timeout / 1000000; timeout.tv_usec = usec_timeout % 1000000; retval = select(0, &sockets, NULL, NULL, &timeout); } /* Properly set guac_error */ if (retval < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Error while waiting for data on socket"; } if (retval == 0) { guac_error = GUAC_STATUS_TIMEOUT; guac_error_message = "Timeout while waiting for data on socket"; } return retval; } /** * Frees all implementation-specific data associated with the given socket, but * not the socket object itself. * * @param socket * The guac_socket whose associated data should be freed. * * @return * Zero if the data was successfully freed, non-zero otherwise. This * implementation always succeeds, and will always return zero. */ static int guac_socket_wsa_free_handler(guac_socket* socket) { guac_socket_wsa_data* data = (guac_socket_wsa_data*) socket->data; /* Destroy locks */ pthread_mutex_destroy(&(data->socket_lock)); pthread_mutex_destroy(&(data->buffer_lock)); /* Close socket */ closesocket(data->sock); free(data); return 0; } /** * Acquires exclusive access to the given socket. * * @param socket * The guac_socket to which exclusive access is required. */ static void guac_socket_wsa_lock_handler(guac_socket* socket) { guac_socket_wsa_data* data = (guac_socket_wsa_data*) socket->data; /* Acquire exclusive access to socket */ pthread_mutex_lock(&(data->socket_lock)); } /** * Relinquishes exclusive access to the given socket. * * @param socket * The guac_socket to which exclusive access is no longer required. */ static void guac_socket_wsa_unlock_handler(guac_socket* socket) { guac_socket_wsa_data* data = (guac_socket_wsa_data*) socket->data; /* Relinquish exclusive access to socket */ pthread_mutex_unlock(&(data->socket_lock)); } guac_socket* guac_socket_open_wsa(SOCKET sock) { pthread_mutexattr_t lock_attributes; /* Allocate socket and associated data */ guac_socket* socket = guac_socket_alloc(); guac_socket_wsa_data* data = malloc(sizeof(guac_socket_wsa_data)); /* Store socket as socket data */ data->sock = sock; data->written = 0; socket->data = data; pthread_mutexattr_init(&lock_attributes); pthread_mutexattr_setpshared(&lock_attributes, PTHREAD_PROCESS_SHARED); /* Init locks */ pthread_mutex_init(&(data->socket_lock), &lock_attributes); pthread_mutex_init(&(data->buffer_lock), &lock_attributes); /* Set read/write handlers */ socket->read_handler = guac_socket_wsa_read_handler; socket->write_handler = guac_socket_wsa_write_handler; socket->select_handler = guac_socket_wsa_select_handler; socket->lock_handler = guac_socket_wsa_lock_handler; socket->unlock_handler = guac_socket_wsa_unlock_handler; socket->flush_handler = guac_socket_wsa_flush_handler; socket->free_handler = guac_socket_wsa_free_handler; return socket; } guacamole-server-1.3.0/src/libguac/user-handshake.c0000644000175100001440000002773713772470243017166 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/client.h" #include "guacamole/error.h" #include "guacamole/parser.h" #include "guacamole/protocol.h" #include "guacamole/socket.h" #include "guacamole/user.h" #include "user-handlers.h" #include #include #include /** * Parameters required by the user input thread. */ typedef struct guac_user_input_thread_params { /** * The parser which will be used throughout the user's session. */ guac_parser* parser; /** * A reference to the connected user. */ guac_user* user; /** * The number of microseconds to wait for instructions from a connected * user before closing the connection with an error. */ int usec_timeout; } guac_user_input_thread_params; /** * Prints an error message using the logging facilities of the given user, * automatically including any information present in guac_error. * * @param user * The guac_user associated with the error that occurred. * * @param level * The level at which to log this message. * * @param message * The message to log. */ static void guac_user_log_guac_error(guac_user* user, guac_client_log_level level, const char* message) { if (guac_error != GUAC_STATUS_SUCCESS) { /* If error message provided, include in log */ if (guac_error_message != NULL) guac_user_log(user, level, "%s: %s", message, guac_error_message); /* Otherwise just log with standard status string */ else guac_user_log(user, level, "%s: %s", message, guac_status_string(guac_error)); } /* Just log message if no status code */ else guac_user_log(user, level, "%s", message); } /** * Logs a reasonable explanatory message regarding handshake failure based on * the current value of guac_error. * * @param user * The guac_user associated with the failed Guacamole protocol handshake. */ static void guac_user_log_handshake_failure(guac_user* user) { if (guac_error == GUAC_STATUS_CLOSED) guac_user_log(user, GUAC_LOG_DEBUG, "Guacamole connection closed during handshake"); else if (guac_error == GUAC_STATUS_PROTOCOL_ERROR) guac_user_log(user, GUAC_LOG_ERROR, "Guacamole protocol violation. Perhaps the version of " "guacamole-client is incompatible with this version of " "libguac?"); else guac_user_log(user, GUAC_LOG_WARNING, "Guacamole handshake failed: %s", guac_status_string(guac_error)); } /** * The thread which handles all user input, calling event handlers for received * instructions. * * @param data * A pointer to a guac_user_input_thread_params structure describing the * user whose input is being handled and the guac_parser with which to * handle it. * * @return * Always NULL. */ static void* guac_user_input_thread(void* data) { guac_user_input_thread_params* params = (guac_user_input_thread_params*) data; int usec_timeout = params->usec_timeout; guac_user* user = params->user; guac_parser* parser = params->parser; guac_client* client = user->client; guac_socket* socket = user->socket; /* Guacamole user input loop */ while (client->state == GUAC_CLIENT_RUNNING && user->active) { /* Read instruction, stop on error */ if (guac_parser_read(parser, socket, usec_timeout)) { if (guac_error == GUAC_STATUS_TIMEOUT) guac_user_abort(user, GUAC_PROTOCOL_STATUS_CLIENT_TIMEOUT, "User is not responding."); else { if (guac_error != GUAC_STATUS_CLOSED) guac_user_log_guac_error(user, GUAC_LOG_WARNING, "Guacamole connection failure"); guac_user_stop(user); } return NULL; } /* Reset guac_error and guac_error_message (user/client handlers are not * guaranteed to set these) */ guac_error = GUAC_STATUS_SUCCESS; guac_error_message = NULL; /* Call handler, stop on error */ if (__guac_user_call_opcode_handler(__guac_instruction_handler_map, user, parser->opcode, parser->argc, parser->argv)) { /* Log error */ guac_user_log_guac_error(user, GUAC_LOG_WARNING, "User connection aborted"); /* Log handler details */ guac_user_log(user, GUAC_LOG_DEBUG, "Failing instruction handler in user was \"%s\"", parser->opcode); guac_user_stop(user); return NULL; } } return NULL; } /** * Starts the input/output threads of a new user. This function will block * until the user disconnects. If an error prevents the input/output threads * from starting, guac_user_stop() will be invoked on the given user. * * @param parser * The guac_parser to use to handle all input from the given user. * * @param user * The user whose associated I/O transfer threads should be started. * * @param usec_timeout * The number of microseconds to wait for instructions from the given * user before closing the connection with an error. * * @return * Zero if the I/O threads started successfully and user has disconnected, * or non-zero if the I/O threads could not be started. */ static int guac_user_start(guac_parser* parser, guac_user* user, int usec_timeout) { guac_user_input_thread_params params = { .parser = parser, .user = user, .usec_timeout = usec_timeout }; pthread_t input_thread; if (pthread_create(&input_thread, NULL, guac_user_input_thread, (void*) ¶ms)) { guac_user_log(user, GUAC_LOG_ERROR, "Unable to start input thread"); guac_user_stop(user); return -1; } /* Wait for I/O threads */ pthread_join(input_thread, NULL); /* Explicitly signal disconnect */ guac_protocol_send_disconnect(user->socket); guac_socket_flush(user->socket); /* Done */ return 0; } /** * This function loops through the received instructions during the handshake * with the client attempting to join the connection, and runs the handlers * for each of the opcodes, ending when the connect instruction is received. * Returns zero if the handshake completes successfully with the connect opcode, * or a non-zero value if an error occurs. * * @param user * The guac_user attempting to join the connection. * * @param parser * The parser used to examine the received data. * * @param usec_timeout * The timeout, in microseconds, for reading the instructions. * * @return * Zero if the handshake completes successfully with the connect opcode, * or non-zero if an error occurs. */ static int __guac_user_handshake(guac_user* user, guac_parser* parser, int usec_timeout) { guac_socket* socket = user->socket; /* Handle each of the opcodes. */ while (guac_parser_read(parser, socket, usec_timeout) == 0) { /* If we receive the connect opcode, we're done. */ if (strcmp(parser->opcode, "connect") == 0) return 0; guac_user_log(user, GUAC_LOG_DEBUG, "Processing instruction: %s", parser->opcode); /* Run instruction handler for opcode with arguments. */ if (__guac_user_call_opcode_handler(__guac_handshake_handler_map, user, parser->opcode, parser->argc, parser->argv)) { guac_user_log_handshake_failure(user); guac_user_log_guac_error(user, GUAC_LOG_DEBUG, "Error handling instruction during handshake."); guac_user_log(user, GUAC_LOG_DEBUG, "Failed opcode: %s", parser->opcode); guac_parser_free(parser); return 1; } } /* If we get here it's because we never got the connect instruction. */ guac_user_log(user, GUAC_LOG_ERROR, "Handshake failed, \"connect\" instruction was not received."); return 1; } int guac_user_handle_connection(guac_user* user, int usec_timeout) { guac_socket* socket = user->socket; guac_client* client = user->client; user->info.audio_mimetypes = NULL; user->info.image_mimetypes = NULL; user->info.video_mimetypes = NULL; user->info.timezone = NULL; /* Count number of arguments. */ int num_args; for (num_args = 0; client->args[num_args] != NULL; num_args++); /* Send args */ if (guac_protocol_send_args(socket, client->args) || guac_socket_flush(socket)) { /* Log error */ guac_user_log_handshake_failure(user); guac_user_log_guac_error(user, GUAC_LOG_DEBUG, "Error sending \"args\" to new user"); return 1; } guac_parser* parser = guac_parser_alloc(); /* Perform the handshake with the client. */ if (__guac_user_handshake(user, parser, usec_timeout)) { guac_parser_free(parser); return 1; } /* Acknowledge connection availability */ guac_protocol_send_ready(socket, client->connection_id); guac_socket_flush(socket); /* Verify argument count. */ if (parser->argc != (num_args + 1)) { guac_client_log(client, GUAC_LOG_ERROR, "Client did not return the " "expected number of arguments."); return 1; } /* Attempt to join user to connection. */ if (guac_client_add_user(client, user, (parser->argc - 1), parser->argv + 1)) guac_client_log(client, GUAC_LOG_ERROR, "User \"%s\" could NOT " "join connection \"%s\"", user->user_id, client->connection_id); /* Begin user connection if join successful */ else { guac_client_log(client, GUAC_LOG_INFO, "User \"%s\" joined connection " "\"%s\" (%i users now present)", user->user_id, client->connection_id, client->connected_users); if (strcmp(parser->argv[0],"") != 0) { guac_client_log(client, GUAC_LOG_DEBUG, "Client is using protocol " "version \"%s\"", parser->argv[0]); user->info.protocol_version = guac_protocol_string_to_version(parser->argv[0]); } else { guac_client_log(client, GUAC_LOG_DEBUG, "Client has not defined " "its protocol version."); user->info.protocol_version = GUAC_PROTOCOL_VERSION_1_0_0; } /* Handle user I/O, wait for connection to terminate */ guac_user_start(parser, user, usec_timeout); /* Remove/free user */ guac_client_remove_user(client, user); guac_client_log(client, GUAC_LOG_INFO, "User \"%s\" disconnected (%i " "users remain)", user->user_id, client->connected_users); } /* Free mimetype character arrays. */ guac_free_mimetypes((char **) user->info.audio_mimetypes); guac_free_mimetypes((char **) user->info.image_mimetypes); guac_free_mimetypes((char **) user->info.video_mimetypes); /* Free timezone info. */ free((char *) user->info.timezone); guac_parser_free(parser); /* Successful disconnect */ return 0; } guacamole-server-1.3.0/src/libguac/encode-png.h0000644000175100001440000000275113764613616016301 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_ENCODE_PNG_H #define GUAC_ENCODE_PNG_H #include "config.h" #include "guacamole/socket.h" #include "guacamole/stream.h" #include /** * Encodes the given surface as a PNG, and sends the resulting data over the * given stream and socket as blobs. * * @param socket * The socket to send PNG blobs over. * * @param stream * The stream to associate with each blob. * * @param surface * The Cairo surface to write to the given stream and socket as PNG blobs. * * @return * Zero if the encoding operation is successful, non-zero otherwise. */ int guac_png_write(guac_socket* socket, guac_stream* stream, cairo_surface_t* surface); #endif guacamole-server-1.3.0/src/libguac/encode-png.c0000644000175100001440000002642513764613616016300 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "encode-png.h" #include "guacamole/error.h" #include "guacamole/protocol.h" #include "guacamole/stream.h" #include "palette.h" #include #include #ifdef HAVE_PNGSTRUCT_H #include #endif #include #include #include #include #include /** * Data describing the current write state of PNG data. */ typedef struct guac_png_write_state { /** * The socket over which all PNG blobs will be written. */ guac_socket* socket; /** * The Guacamole stream to associate with each PNG blob. */ guac_stream* stream; /** * Buffer of pending PNG data. */ char buffer[GUAC_PROTOCOL_BLOB_MAX_LENGTH]; /** * The number of bytes currently stored in the buffer. */ int buffer_size; } guac_png_write_state; /** * Writes the contents of the PNG write state as a blob to its associated * socket. * * @param write_state * The write state to flush. */ static void guac_png_flush_data(guac_png_write_state* write_state) { /* Send blob */ guac_protocol_send_blob(write_state->socket, write_state->stream, write_state->buffer, write_state->buffer_size); /* Clear buffer */ write_state->buffer_size = 0; } /** * Appends the given PNG data to the internal buffer of the given write state, * automatically flushing the write state as necessary. * socket. * * @param write_state * The write state to append the given data to. * * @param data * The PNG data to append. * * @param length * The size of the given PNG data, in bytes. */ static void guac_png_write_data(guac_png_write_state* write_state, const void* data, int length) { const unsigned char* current = data; /* Append all data given */ while (length > 0) { /* Calculate space remaining */ int remaining = sizeof(write_state->buffer) - write_state->buffer_size; /* If no space remains, flush buffer to make room */ if (remaining == 0) { guac_png_flush_data(write_state); remaining = sizeof(write_state->buffer); } /* Calculate size of next block of data to append */ int block_size = remaining; if (block_size > length) block_size = length; /* Append block */ memcpy(write_state->buffer + write_state->buffer_size, current, block_size); /* Next block */ current += block_size; write_state->buffer_size += block_size; length -= block_size; } } /** * Writes the given buffer of PNG data to the buffer of the given write state, * flushing that buffer to blob instructions if necessary. This handler is * called by Cairo when writing PNG data via * cairo_surface_write_to_png_stream(). * * @param closure * Pointer to arbitrary data passed to cairo_surface_write_to_png_stream(). * In the case of this handler, this data will be the guac_png_write_state. * * @param data * The buffer of PNG data to write. * * @param length * The size of the given buffer, in bytes. * * @return * A Cairo status code indicating whether the write operation succeeded. * In the case of this handler, this will always be CAIRO_STATUS_SUCCESS. */ static cairo_status_t guac_png_cairo_write_handler(void* closure, const unsigned char* data, unsigned int length) { guac_png_write_state* write_state = (guac_png_write_state*) closure; /* Append data to buffer, writing as necessary */ guac_png_write_data(write_state, data, length); return CAIRO_STATUS_SUCCESS; } /** * Implementation of guac_png_write() which uses Cairo's own PNG encoder to * write PNG data, rather than using libpng directly. * * @param socket * The socket to send PNG blobs over. * * @param stream * The stream to associate with each blob. * * @param surface * The Cairo surface to write to the given stream and socket as PNG blobs. * * @return * Zero if the encoding operation is successful, non-zero otherwise. */ static int guac_png_cairo_write(guac_socket* socket, guac_stream* stream, cairo_surface_t* surface) { guac_png_write_state write_state; /* Init write state */ write_state.socket = socket; write_state.stream = stream; write_state.buffer_size = 0; /* Write surface as PNG */ if (cairo_surface_write_to_png_stream(surface, guac_png_cairo_write_handler, &write_state) != CAIRO_STATUS_SUCCESS) { guac_error = GUAC_STATUS_INTERNAL_ERROR; guac_error_message = "Cairo PNG backend failed"; return -1; } /* Flush remaining PNG data */ guac_png_flush_data(&write_state); return 0; } /** * Writes the given buffer of PNG data to the buffer of the given write state, * flushing that buffer to blob instructions if necessary. This handler is * called by libpng when writing PNG data via png_write_png(). * * @param png * The PNG compression state structure associated with the write operation. * The pointer to arbitrary data will have been set to the * guac_png_write_state by png_set_write_fn(), and will be accessible via * png->io_ptr or png_get_io_ptr(png), depending on the version of libpng. * * @param data * The buffer of PNG data to write. * * @param length * The size of the given buffer, in bytes. */ static void guac_png_write_handler(png_structp png, png_bytep data, png_size_t length) { /* Get png buffer structure */ guac_png_write_state* write_state; #ifdef HAVE_PNG_GET_IO_PTR write_state = (guac_png_write_state*) png_get_io_ptr(png); #else write_state = (guac_png_write_state*) png->io_ptr; #endif /* Append data to buffer, writing as necessary */ guac_png_write_data(write_state, data, length); } /** * Flushes any PNG data within the buffer of the given write state as a blob * instruction. If no data is within the buffer, this function has no effect. * This handler is called by libpng when it has finished writing PNG data via * png_write_png(). * * @param png * The PNG compression state structure associated with the write operation. * The pointer to arbitrary data will have been set to the * guac_png_write_state by png_set_write_fn(), and will be accessible via * png->io_ptr or png_get_io_ptr(png), depending on the version of libpng. */ static void guac_png_flush_handler(png_structp png) { /* Get png buffer structure */ guac_png_write_state* write_state; #ifdef HAVE_PNG_GET_IO_PTR write_state = (guac_png_write_state*) png_get_io_ptr(png); #else write_state = (guac_png_write_state*) png->io_ptr; #endif /* Flush buffer */ guac_png_flush_data(write_state); } int guac_png_write(guac_socket* socket, guac_stream* stream, cairo_surface_t* surface) { png_structp png; png_infop png_info; png_byte** png_rows; int bpp; int x, y; guac_png_write_state write_state; /* Get image surface properties and data */ cairo_format_t format = cairo_image_surface_get_format(surface); int width = cairo_image_surface_get_width(surface); int height = cairo_image_surface_get_height(surface); int stride = cairo_image_surface_get_stride(surface); unsigned char* data = cairo_image_surface_get_data(surface); /* If not RGB24, use Cairo PNG writer */ if (format != CAIRO_FORMAT_RGB24 || data == NULL) return guac_png_cairo_write(socket, stream, surface); /* Flush pending operations to surface */ cairo_surface_flush(surface); /* Attempt to build palette */ guac_palette* palette = guac_palette_alloc(surface); /* If not possible, resort to Cairo PNG writer */ if (palette == NULL) return guac_png_cairo_write(socket, stream, surface); /* Calculate BPP from palette size */ if (palette->size <= 2) bpp = 1; else if (palette->size <= 4) bpp = 2; else if (palette->size <= 16) bpp = 4; else bpp = 8; /* Set up PNG writer */ png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { guac_palette_free(palette); guac_error = GUAC_STATUS_INTERNAL_ERROR; guac_error_message = "libpng failed to create write structure"; return -1; } png_info = png_create_info_struct(png); if (!png_info) { png_destroy_write_struct(&png, NULL); guac_palette_free(palette); guac_error = GUAC_STATUS_INTERNAL_ERROR; guac_error_message = "libpng failed to create info structure"; return -1; } /* Set error handler */ if (setjmp(png_jmpbuf(png))) { png_destroy_write_struct(&png, &png_info); guac_palette_free(palette); guac_error = GUAC_STATUS_IO_ERROR; guac_error_message = "libpng output error"; return -1; } /* Init write state */ write_state.socket = socket; write_state.stream = stream; write_state.buffer_size = 0; /* Set up writer */ png_set_write_fn(png, &write_state, guac_png_write_handler, guac_png_flush_handler); /* Copy data from surface into PNG data */ png_rows = (png_byte**) malloc(sizeof(png_byte*) * height); for (y=0; ycolors, palette->size); /* Write image */ png_set_rows(png, png_info, png_rows); png_write_png(png, png_info, PNG_TRANSFORM_PACKING, NULL); /* Finish write */ png_destroy_write_struct(&png, &png_info); /* Free palette */ guac_palette_free(palette); /* Free PNG data */ for (y=0; y #include #include #include #include #include #include #include #include char __guac_socket_BASE64_CHARACTERS[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; static void* __guac_socket_keep_alive_thread(void* data) { int old_cancelstate; /* Calculate sleep interval */ struct timespec interval; interval.tv_sec = GUAC_SOCKET_KEEP_ALIVE_INTERVAL / 1000; interval.tv_nsec = (GUAC_SOCKET_KEEP_ALIVE_INTERVAL % 1000) * 1000000L; /* Socket keep-alive loop */ guac_socket* socket = (guac_socket*) data; while (socket->state == GUAC_SOCKET_OPEN) { /* Send NOP keep-alive if it's been a while since the last output */ guac_timestamp timestamp = guac_timestamp_current(); if (timestamp - socket->last_write_timestamp > GUAC_SOCKET_KEEP_ALIVE_INTERVAL) { /* Send NOP */ if (guac_protocol_send_nop(socket) || guac_socket_flush(socket)) break; } /* Sleep until next keep-alive check, but allow thread cancellation * during that sleep */ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancelstate); nanosleep(&interval, NULL); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelstate); } return NULL; } static ssize_t __guac_socket_write(guac_socket* socket, const void* buf, size_t count) { /* Update timestamp of last write */ socket->last_write_timestamp = guac_timestamp_current(); /* If handler defined, call it. */ if (socket->write_handler) return socket->write_handler(socket, buf, count); /* Otherwise, pretend everything was written. */ return count; } ssize_t guac_socket_write(guac_socket* socket, const void* buf, size_t count) { const char* buffer = buf; /* Write until completely written */ while (count > 0) { /* Attempt to write, return on error */ int written = __guac_socket_write(socket, buffer, count); if (written == -1) return 1; /* Advance buffer as data written */ buffer += written; count -= written; } return 0; } ssize_t guac_socket_read(guac_socket* socket, void* buf, size_t count) { /* If handler defined, call it. */ if (socket->read_handler) return socket->read_handler(socket, buf, count); /* Otherwise, pretend nothing was read. */ return 0; } int guac_socket_select(guac_socket* socket, int usec_timeout) { /* Call select handler if defined */ if (socket->select_handler) return socket->select_handler(socket, usec_timeout); /* Otherwise, assume ready. */ return 1; } guac_socket* guac_socket_alloc() { guac_socket* socket = malloc(sizeof(guac_socket)); /* If no memory available, return with error */ if (socket == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; guac_error_message = "Could not allocate memory for socket"; return NULL; } socket->__ready = 0; socket->data = NULL; socket->state = GUAC_SOCKET_OPEN; socket->last_write_timestamp = guac_timestamp_current(); /* No keep alive ping by default */ socket->__keep_alive_enabled = 0; /* No handlers yet */ socket->read_handler = NULL; socket->write_handler = NULL; socket->select_handler = NULL; socket->free_handler = NULL; socket->flush_handler = NULL; socket->lock_handler = NULL; socket->unlock_handler = NULL; return socket; } void guac_socket_require_keep_alive(guac_socket* socket) { /* Start keep-alive thread */ socket->__keep_alive_enabled = 1; pthread_create(&(socket->__keep_alive_thread), NULL, __guac_socket_keep_alive_thread, (void*) socket); } void guac_socket_instruction_begin(guac_socket* socket) { /* Call instruction begin handler if defined */ if (socket->lock_handler) socket->lock_handler(socket); } void guac_socket_instruction_end(guac_socket* socket) { /* Call instruction end handler if defined */ if (socket->unlock_handler) socket->unlock_handler(socket); } void guac_socket_free(guac_socket* socket) { guac_socket_flush(socket); /* Call free handler if defined */ if (socket->free_handler) socket->free_handler(socket); /* Mark as closed */ socket->state = GUAC_SOCKET_CLOSED; /* Stop keep-alive thread, if enabled */ if (socket->__keep_alive_enabled) { pthread_cancel(socket->__keep_alive_thread); pthread_join(socket->__keep_alive_thread, NULL); } free(socket); } ssize_t guac_socket_write_int(guac_socket* socket, int64_t i) { char buffer[128]; int length; /* Write provided integer as a string */ length = snprintf(buffer, sizeof(buffer), "%"PRIi64, i); return guac_socket_write(socket, buffer, length); } ssize_t guac_socket_write_string(guac_socket* socket, const char* str) { /* Write contents of string */ if (guac_socket_write(socket, str, strlen(str))) return 1; return 0; } ssize_t __guac_socket_write_base64_triplet(guac_socket* socket, int a, int b, int c) { char output[4]; /* Byte 0:[AAAAAA] AABBBB BBBBCC CCCCCC */ output[0] = __guac_socket_BASE64_CHARACTERS[(a & 0xFC) >> 2]; if (b >= 0) { /* Byte 1: AAAAAA [AABBBB] BBBBCC CCCCCC */ output[1] = __guac_socket_BASE64_CHARACTERS[((a & 0x03) << 4) | ((b & 0xF0) >> 4)]; /* * Bytes 2 and 3, zero characters of padding: * * AAAAAA AABBBB [BBBBCC] CCCCCC * AAAAAA AABBBB BBBBCC [CCCCCC] */ if (c >= 0) { output[2] = __guac_socket_BASE64_CHARACTERS[((b & 0x0F) << 2) | ((c & 0xC0) >> 6)]; output[3] = __guac_socket_BASE64_CHARACTERS[c & 0x3F]; } /* * Bytes 2 and 3, one character of padding: * * AAAAAA AABBBB [BBBB--] ------ * AAAAAA AABBBB BBBB-- [------] */ else { output[2] = __guac_socket_BASE64_CHARACTERS[((b & 0x0F) << 2)]; output[3] = '='; } } /* * Bytes 1, 2, and 3, two characters of padding: * * AAAAAA [AA----] ------ ------ * AAAAAA AA---- [------] ------ * AAAAAA AA---- ------ [------] */ else { output[1] = __guac_socket_BASE64_CHARACTERS[((a & 0x03) << 4)]; output[2] = '='; output[3] = '='; } /* At this point, 4 base64 bytes have been written */ if (guac_socket_write(socket, output, 4)) return -1; /* If no second byte was provided, only one byte was written */ if (b < 0) return 1; /* If no third byte was provided, only two bytes were written */ if (c < 0) return 2; /* Otherwise, three bytes were written */ return 3; } ssize_t __guac_socket_write_base64_byte(guac_socket* socket, int buf) { int* __ready_buf = socket->__ready_buf; int retval; __ready_buf[socket->__ready++] = buf; /* Flush triplet */ if (socket->__ready == 3) { retval = __guac_socket_write_base64_triplet(socket, __ready_buf[0], __ready_buf[1], __ready_buf[2]); if (retval < 0) return retval; socket->__ready = 0; } return 1; } ssize_t guac_socket_write_base64(guac_socket* socket, const void* buf, size_t count) { int retval; const unsigned char* char_buf = (const unsigned char*) buf; const unsigned char* end = char_buf + count; while (char_buf < end) { retval = __guac_socket_write_base64_byte(socket, *(char_buf++)); if (retval < 0) return retval; } return 0; } ssize_t guac_socket_flush(guac_socket* socket) { /* If handler defined, call it. */ if (socket->flush_handler) return socket->flush_handler(socket); /* Otherwise, do nothing */ return 0; } ssize_t guac_socket_flush_base64(guac_socket* socket) { int retval; /* Flush triplet to output buffer */ while (socket->__ready > 0) { retval = __guac_socket_write_base64_byte(socket, -1); if (retval < 0) return retval; } return 0; } guacamole-server-1.3.0/src/libguac/socket-ssl.c0000644000175100001440000000756013764613616016347 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/error.h" #include "guacamole/socket-ssl.h" #include "guacamole/socket.h" #include "wait-fd.h" #include #include static ssize_t __guac_socket_ssl_read_handler(guac_socket* socket, void* buf, size_t count) { /* Read from socket */ guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data; int retval; retval = SSL_read(data->ssl, buf, count); /* Record errors in guac_error */ if (retval <= 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Error reading data from secure socket"; } return retval; } static ssize_t __guac_socket_ssl_write_handler(guac_socket* socket, const void* buf, size_t count) { /* Write data to socket */ guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data; int retval; retval = SSL_write(data->ssl, buf, count); /* Record errors in guac_error */ if (retval <= 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Error writing data to secure socket"; } return retval; } static int __guac_socket_ssl_select_handler(guac_socket* socket, int usec_timeout) { guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data; int retval = guac_wait_for_fd(data->fd, usec_timeout); /* Properly set guac_error */ if (retval < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Error while waiting for data on secure socket"; } else if (retval == 0) { guac_error = GUAC_STATUS_TIMEOUT; guac_error_message = "Timeout while waiting for data on secure socket"; } return retval; } static int __guac_socket_ssl_free_handler(guac_socket* socket) { /* Shutdown SSL */ guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data; SSL_shutdown(data->ssl); SSL_free(data->ssl); /* Close file descriptor */ close(data->fd); free(data); return 0; } guac_socket* guac_socket_open_secure(SSL_CTX* context, int fd) { /* Create new SSL structure */ SSL* ssl = SSL_new(context); if (ssl == NULL) return NULL; /* Allocate socket and associated data */ guac_socket* socket = guac_socket_alloc(); guac_socket_ssl_data* data = malloc(sizeof(guac_socket_ssl_data)); /* Init SSL */ data->context = context; data->ssl = ssl; SSL_set_fd(data->ssl, fd); /* Accept SSL connection, handle errors */ if (SSL_accept(ssl) <= 0) { guac_error = GUAC_STATUS_INTERNAL_ERROR; guac_error_message = "SSL accept failed"; free(data); guac_socket_free(socket); SSL_free(ssl); return NULL; } /* Store file descriptor as socket data */ data->fd = fd; socket->data = data; /* Set read/write handlers */ socket->read_handler = __guac_socket_ssl_read_handler; socket->write_handler = __guac_socket_ssl_write_handler; socket->select_handler = __guac_socket_ssl_select_handler; socket->free_handler = __guac_socket_ssl_free_handler; return socket; } guacamole-server-1.3.0/src/libguac/wol.c0000644000175100001440000001432113764613616015052 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/error.h" #include "guacamole/wol.h" #include #include #include #include #include #include #include /** * Generate the magic Wake-on-LAN (WoL) packet for the specified MAC address * and place it in the character array. * * @param packet * The character array that will contain the generated packet. * * @param mac_address * The unsigned int representation of the MAC address to place in the packet. */ static void __guac_wol_create_magic_packet(unsigned char packet[], unsigned int mac_address[]) { int i; unsigned char mac[6]; /* Concurrently fill the first part of the packet with 0xFF, and copy the MAC address from the int array to the char array. */ for (i = 0; i < 6; i++) { packet[i] = 0xFF; mac[i] = mac_address[i]; } /* Copy the MAC address contents into the char array that is storing the rest of the packet. */ for (i = 1; i <= 16; i++) { memcpy(&packet[i * 6], &mac, 6 * sizeof(unsigned char)); } } /** * Send the magic Wake-on-LAN (WoL) packet to the specified broadcast address, * returning the number of bytes sent, or zero if any error occurred and nothing * was sent. * * @param broadcast_addr * The broadcast address to which to send the magic WoL packet. * * @param packet * The magic WoL packet to send. * * @return * The number of bytes sent, or zero if nothing could be sent. */ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, unsigned char packet[]) { struct sockaddr_in wol_dest; int wol_socket; /* Determine the IP version, starting with IPv4. */ wol_dest.sin_port = htons(GUAC_WOL_PORT); wol_dest.sin_family = AF_INET; int retval = inet_pton(wol_dest.sin_family, broadcast_addr, &(wol_dest.sin_addr)); /* If return value is less than zero, this system doesn't know about IPv4. */ if (retval < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "IPv4 address family is not supported"; return 0; } /* If return value is zero, address doesn't match the IPv4, so try IPv6. */ else if (retval == 0) { wol_dest.sin_family = AF_INET6; retval = inet_pton(wol_dest.sin_family, broadcast_addr, &(wol_dest.sin_addr)); /* System does not support IPv6. */ if (retval < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "IPv6 address family is not supported"; return 0; } /* Address didn't match IPv6. */ else if (retval == 0) { guac_error = GUAC_STATUS_INVALID_ARGUMENT; guac_error_message = "Invalid broadcast or multicast address specified for Wake-on-LAN"; return 0; } } /* Set up the socket */ wol_socket = socket(wol_dest.sin_family, SOCK_DGRAM, 0); /* If socket open fails, bail out. */ if (wol_socket < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Failed to open socket to send Wake-on-LAN packet"; return 0; } /* Set up socket for IPv4 broadcast. */ if (wol_dest.sin_family == AF_INET) { /* For configuring socket broadcast */ int wol_bcast = 1; /* Attempt to set IPv4 broadcast; exit with error if this fails. */ if (setsockopt(wol_socket, SOL_SOCKET, SO_BROADCAST, &wol_bcast, sizeof(wol_bcast)) < 0) { close(wol_socket); guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Failed to set IPv4 broadcast for Wake-on-LAN socket"; return 0; } } /* Set up socket for IPv6 multicast. */ else { /* Stick to a single hop for now. */ int hops = 1; /* Attempt to set IPv6 multicast; exit with error if this fails. */ if (setsockopt(wol_socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) < 0) { close(wol_socket); guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Failed to set IPv6 multicast for Wake-on-LAN socket"; return 0; } } /* Send the packet and return number of bytes sent. */ int bytes = sendto(wol_socket, packet, GUAC_WOL_PACKET_SIZE, 0, (struct sockaddr*) &wol_dest, sizeof(wol_dest)); close(wol_socket); return bytes; } int guac_wol_wake(const char* mac_addr, const char* broadcast_addr) { unsigned char wol_packet[GUAC_WOL_PACKET_SIZE]; unsigned int dest_mac[6]; /* Parse mac address and return with error if parsing fails. */ if (sscanf(mac_addr, "%x:%x:%x:%x:%x:%x", &(dest_mac[0]), &(dest_mac[1]), &(dest_mac[2]), &(dest_mac[3]), &(dest_mac[4]), &(dest_mac[5])) != 6) { guac_error = GUAC_STATUS_INVALID_ARGUMENT; guac_error_message = "Invalid argument for Wake-on-LAN MAC address"; return -1; } /* Generate the magic packet. */ __guac_wol_create_magic_packet(wol_packet, dest_mac); /* Send the packet and record bytes sent. */ int bytes_sent = __guac_wol_send_packet(broadcast_addr, wol_packet); /* Return 0 if bytes were sent, otherwise return an error. */ if (bytes_sent) return 0; return -1; }guacamole-server-1.3.0/src/libguac/user.c0000644000175100001440000002777513770536337015251 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "encode-jpeg.h" #include "encode-png.h" #include "encode-webp.h" #include "guacamole/client.h" #include "guacamole/object.h" #include "guacamole/pool.h" #include "guacamole/protocol.h" #include "guacamole/socket.h" #include "guacamole/stream.h" #include "guacamole/timestamp.h" #include "guacamole/user.h" #include "id.h" #include "user-handlers.h" #include #include #include #include guac_user* guac_user_alloc() { guac_user* user = calloc(1, sizeof(guac_user)); int i; /* Generate ID */ user->user_id = guac_generate_id(GUAC_USER_ID_PREFIX); if (user->user_id == NULL) { free(user); return NULL; } user->last_received_timestamp = guac_timestamp_current(); user->last_frame_duration = 0; user->processing_lag = 0; user->active = 1; /* Allocate stream pool */ user->__stream_pool = guac_pool_alloc(0); /* Initialze streams */ user->__input_streams = malloc(sizeof(guac_stream) * GUAC_USER_MAX_STREAMS); user->__output_streams = malloc(sizeof(guac_stream) * GUAC_USER_MAX_STREAMS); for (i=0; i__input_streams[i].index = GUAC_USER_CLOSED_STREAM_INDEX; user->__output_streams[i].index = GUAC_USER_CLOSED_STREAM_INDEX; } /* Allocate object pool */ user->__object_pool = guac_pool_alloc(0); /* Initialize objects */ user->__objects = malloc(sizeof(guac_object) * GUAC_USER_MAX_OBJECTS); for (i=0; i__objects[i].index = GUAC_USER_UNDEFINED_OBJECT_INDEX; return user; } void guac_user_free(guac_user* user) { /* Free streams */ free(user->__input_streams); free(user->__output_streams); /* Free stream pool */ guac_pool_free(user->__stream_pool); /* Free objects */ free(user->__objects); /* Free object pool */ guac_pool_free(user->__object_pool); /* Clean up user */ free(user->user_id); free(user); } guac_stream* guac_user_alloc_stream(guac_user* user) { guac_stream* allocd_stream; int stream_index; /* Refuse to allocate beyond maximum */ if (user->__stream_pool->active == GUAC_USER_MAX_STREAMS) return NULL; /* Allocate stream */ stream_index = guac_pool_next_int(user->__stream_pool); /* Initialize stream with even index (odd indices are client-level) */ allocd_stream = &(user->__output_streams[stream_index]); allocd_stream->index = stream_index * 2; allocd_stream->data = NULL; allocd_stream->ack_handler = NULL; allocd_stream->blob_handler = NULL; allocd_stream->end_handler = NULL; return allocd_stream; } void guac_user_free_stream(guac_user* user, guac_stream* stream) { /* Release index to pool */ guac_pool_free_int(user->__stream_pool, stream->index / 2); /* Mark stream as closed */ stream->index = GUAC_USER_CLOSED_STREAM_INDEX; } guac_object* guac_user_alloc_object(guac_user* user) { guac_object* allocd_object; int object_index; /* Refuse to allocate beyond maximum */ if (user->__object_pool->active == GUAC_USER_MAX_OBJECTS) return NULL; /* Allocate object */ object_index = guac_pool_next_int(user->__object_pool); /* Initialize object */ allocd_object = &(user->__objects[object_index]); allocd_object->index = object_index; allocd_object->data = NULL; allocd_object->get_handler = NULL; allocd_object->put_handler = NULL; return allocd_object; } void guac_user_free_object(guac_user* user, guac_object* object) { /* Release index to pool */ guac_pool_free_int(user->__object_pool, object->index); /* Mark object as undefined */ object->index = GUAC_USER_UNDEFINED_OBJECT_INDEX; } int guac_user_handle_instruction(guac_user* user, const char* opcode, int argc, char** argv) { return __guac_user_call_opcode_handler(__guac_instruction_handler_map, user, opcode, argc, argv); } void guac_user_stop(guac_user* user) { user->active = 0; } void vguac_user_abort(guac_user* user, guac_protocol_status status, const char* format, va_list ap) { /* Only relevant if user is active */ if (user->active) { /* Log detail of error */ vguac_user_log(user, GUAC_LOG_ERROR, format, ap); /* Send error immediately, limit information given */ guac_protocol_send_error(user->socket, "Aborted. See logs.", status); guac_socket_flush(user->socket); /* Stop user */ guac_user_stop(user); } } void guac_user_abort(guac_user* user, guac_protocol_status status, const char* format, ...) { va_list args; va_start(args, format); vguac_user_abort(user, status, format, args); va_end(args); } void vguac_user_log(guac_user* user, guac_client_log_level level, const char* format, va_list ap) { vguac_client_log(user->client, level, format, ap); } void guac_user_log(guac_user* user, guac_client_log_level level, const char* format, ...) { va_list args; va_start(args, format); vguac_client_log(user->client, level, format, args); va_end(args); } void guac_user_stream_argv(guac_user* user, guac_socket* socket, const char* mimetype, const char* name, const char* value) { /* Allocate new stream for argument value */ guac_stream* stream = guac_user_alloc_stream(user); /* Declare stream as containing connection parameter data */ guac_protocol_send_argv(socket, stream, mimetype, name); /* Write parameter data */ guac_protocol_send_blobs(socket, stream, value, strlen(value)); /* Terminate stream */ guac_protocol_send_end(socket, stream); /* Free allocated stream */ guac_user_free_stream(user, stream); } void guac_user_stream_png(guac_user* user, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface) { /* Allocate new stream for image */ guac_stream* stream = guac_user_alloc_stream(user); /* Declare stream as containing image data */ guac_protocol_send_img(socket, stream, mode, layer, "image/png", x, y); /* Write PNG data */ guac_png_write(socket, stream, surface); /* Terminate stream */ guac_protocol_send_end(socket, stream); /* Free allocated stream */ guac_user_free_stream(user, stream); } void guac_user_stream_jpeg(guac_user* user, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface, int quality) { /* Allocate new stream for image */ guac_stream* stream = guac_user_alloc_stream(user); /* Declare stream as containing image data */ guac_protocol_send_img(socket, stream, mode, layer, "image/jpeg", x, y); /* Write JPEG data */ guac_jpeg_write(socket, stream, surface, quality); /* Terminate stream */ guac_protocol_send_end(socket, stream); /* Free allocated stream */ guac_user_free_stream(user, stream); } void guac_user_stream_webp(guac_user* user, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface, int quality, int lossless) { #ifdef ENABLE_WEBP /* Allocate new stream for image */ guac_stream* stream = guac_user_alloc_stream(user); /* Declare stream as containing image data */ guac_protocol_send_img(socket, stream, mode, layer, "image/webp", x, y); /* Write WebP data */ guac_webp_write(socket, stream, surface, quality, lossless); /* Terminate stream */ guac_protocol_send_end(socket, stream); /* Free allocated stream */ guac_user_free_stream(user, stream); #else /* Do nothing if WebP support is not built in */ #endif } int guac_user_supports_required(guac_user* user) { if (user == NULL) return 0; return (user->info.protocol_version >= GUAC_PROTOCOL_VERSION_1_3_0); } int guac_user_supports_webp(guac_user* user) { #ifdef ENABLE_WEBP const char** mimetype = user->info.image_mimetypes; /* Search for WebP mimetype in list of supported image mimetypes */ while (*mimetype != NULL) { /* If WebP mimetype found, no need to search further */ if (strcmp(*mimetype, "image/webp") == 0) return 1; /* Next mimetype */ mimetype++; } /* User does not support WebP */ return 0; #else /* Support for WebP is completely absent */ return 0; #endif } char* guac_user_parse_args_string(guac_user* user, const char** arg_names, const char** argv, int index, const char* default_value) { /* Pull parameter value from argv */ const char* value = argv[index]; /* Use default value if blank */ if (value[0] == 0) { /* NULL is a completely legal default value */ if (default_value == NULL) return NULL; /* Log use of default */ guac_user_log(user, GUAC_LOG_DEBUG, "Parameter \"%s\" omitted. Using " "default value of \"%s\".", arg_names[index], default_value); return strdup(default_value); } /* Otherwise use provided value */ return strdup(value); } int guac_user_parse_args_int(guac_user* user, const char** arg_names, const char** argv, int index, int default_value) { char* parse_end; long parsed_value; /* Pull parameter value from argv */ const char* value = argv[index]; /* Use default value if blank */ if (value[0] == 0) { /* Log use of default */ guac_user_log(user, GUAC_LOG_DEBUG, "Parameter \"%s\" omitted. Using " "default value of %i.", arg_names[index], default_value); return default_value; } /* Parse value, checking for errors */ errno = 0; parsed_value = strtol(value, &parse_end, 10); /* Ensure parsed value is within the legal range of an int */ if (parsed_value < INT_MIN || parsed_value > INT_MAX) errno = ERANGE; /* Resort to default if input is invalid */ if (errno != 0 || *parse_end != '\0') { /* Log use of default */ guac_user_log(user, GUAC_LOG_WARNING, "Specified value \"%s\" for " "parameter \"%s\" is not a valid integer. Using default value " "of %i.", value, arg_names[index], default_value); return default_value; } /* Parsed successfully */ return parsed_value; } int guac_user_parse_args_boolean(guac_user* user, const char** arg_names, const char** argv, int index, int default_value) { /* Pull parameter value from argv */ const char* value = argv[index]; /* Use default value if blank */ if (value[0] == 0) { /* Log use of default */ guac_user_log(user, GUAC_LOG_DEBUG, "Parameter \"%s\" omitted. Using " "default value of %i.", arg_names[index], default_value); return default_value; } /* Parse string "true" as true */ if (strcmp(value, "true") == 0) return 1; /* Parse string "false" as false */ if (strcmp(value, "false") == 0) return 0; /* All other values are invalid */ guac_user_log(user, GUAC_LOG_WARNING, "Parameter \"%s\" must be either " "\"true\" or \"false\". Using default value.", arg_names[index]); return default_value; } guacamole-server-1.3.0/src/libguac/raw_encoder.h0000644000175100001440000000371313764613616016551 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_RAW_ENCODER_H #define GUAC_RAW_ENCODER_H #include "config.h" #include "guacamole/audio.h" /** * The number of bytes to send in each audio blob. */ #define GUAC_RAW_ENCODER_BLOB_SIZE 6048 /** * The size of the raw encoder output PCM buffer, in milliseconds. The * equivalent size in bytes will vary by PCM rate, number of channels, and bits * per sample. */ #define GUAC_RAW_ENCODER_BUFFER_SIZE 250 /** * The current state of the raw encoder. The raw encoder performs very minimal * processing, buffering provided PCM data only as necessary to ensure audio * packet sizes are reasonable. */ typedef struct raw_encoder_state { /** * Buffer of not-yet-written raw PCM data. */ unsigned char* buffer; /** * Size of the PCM buffer, in bytes. */ int length; /** * The current number of bytes stored within the PCM buffer. */ int written; } raw_encoder_state; /** * Audio encoder which writes 8-bit raw PCM (one byte per sample). */ extern guac_audio_encoder* raw8_encoder; /** * Audio encoder which writes 16-bit raw PCM (two bytes per sample). */ extern guac_audio_encoder* raw16_encoder; #endif guacamole-server-1.3.0/src/libguac/Makefile.in0000644000175100001440000021137313772471102016147 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ # Compile WebP support if available @ENABLE_WEBP_TRUE@am__append_1 = encode-webp.c @ENABLE_WEBP_TRUE@am__append_2 = encode-webp.h # SSL support @ENABLE_SSL_TRUE@am__append_3 = socket-ssl.c @ENABLE_SSL_TRUE@am__append_4 = guacamole/socket-ssl.h # Winsock support @ENABLE_WINSOCK_TRUE@am__append_5 = socket-wsa.c @ENABLE_WINSOCK_TRUE@am__append_6 = guacamole/socket-wsa.h subdir = src/libguac ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__libguacinc_HEADERS_DIST) \ $(am__noinst_HEADERS_DIST) $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libguacincdir)" LTLIBRARIES = $(lib_LTLIBRARIES) libguac_la_LIBADD = am__libguac_la_SOURCES_DIST = argv.c audio.c client.c encode-jpeg.c \ encode-png.c error.c hash.c id.c palette.c parser.c pool.c \ protocol.c raw_encoder.c socket.c socket-broadcast.c \ socket-fd.c socket-nest.c socket-tee.c string.c timestamp.c \ unicode.c user.c user-handlers.c user-handshake.c wait-fd.c \ wol.c encode-webp.c socket-ssl.c socket-wsa.c @ENABLE_WEBP_TRUE@am__objects_1 = libguac_la-encode-webp.lo @ENABLE_SSL_TRUE@am__objects_2 = libguac_la-socket-ssl.lo @ENABLE_WINSOCK_TRUE@am__objects_3 = libguac_la-socket-wsa.lo am_libguac_la_OBJECTS = libguac_la-argv.lo libguac_la-audio.lo \ libguac_la-client.lo libguac_la-encode-jpeg.lo \ libguac_la-encode-png.lo libguac_la-error.lo \ libguac_la-hash.lo libguac_la-id.lo libguac_la-palette.lo \ libguac_la-parser.lo libguac_la-pool.lo libguac_la-protocol.lo \ libguac_la-raw_encoder.lo libguac_la-socket.lo \ libguac_la-socket-broadcast.lo libguac_la-socket-fd.lo \ libguac_la-socket-nest.lo libguac_la-socket-tee.lo \ libguac_la-string.lo libguac_la-timestamp.lo \ libguac_la-unicode.lo libguac_la-user.lo \ libguac_la-user-handlers.lo libguac_la-user-handshake.lo \ libguac_la-wait-fd.lo libguac_la-wol.lo $(am__objects_1) \ $(am__objects_2) $(am__objects_3) libguac_la_OBJECTS = $(am_libguac_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libguac_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libguac_la_CFLAGS) \ $(CFLAGS) $(libguac_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libguac_la-argv.Plo \ ./$(DEPDIR)/libguac_la-audio.Plo \ ./$(DEPDIR)/libguac_la-client.Plo \ ./$(DEPDIR)/libguac_la-encode-jpeg.Plo \ ./$(DEPDIR)/libguac_la-encode-png.Plo \ ./$(DEPDIR)/libguac_la-encode-webp.Plo \ ./$(DEPDIR)/libguac_la-error.Plo \ ./$(DEPDIR)/libguac_la-hash.Plo ./$(DEPDIR)/libguac_la-id.Plo \ ./$(DEPDIR)/libguac_la-palette.Plo \ ./$(DEPDIR)/libguac_la-parser.Plo \ ./$(DEPDIR)/libguac_la-pool.Plo \ ./$(DEPDIR)/libguac_la-protocol.Plo \ ./$(DEPDIR)/libguac_la-raw_encoder.Plo \ ./$(DEPDIR)/libguac_la-socket-broadcast.Plo \ ./$(DEPDIR)/libguac_la-socket-fd.Plo \ ./$(DEPDIR)/libguac_la-socket-nest.Plo \ ./$(DEPDIR)/libguac_la-socket-ssl.Plo \ ./$(DEPDIR)/libguac_la-socket-tee.Plo \ ./$(DEPDIR)/libguac_la-socket-wsa.Plo \ ./$(DEPDIR)/libguac_la-socket.Plo \ ./$(DEPDIR)/libguac_la-string.Plo \ ./$(DEPDIR)/libguac_la-timestamp.Plo \ ./$(DEPDIR)/libguac_la-unicode.Plo \ ./$(DEPDIR)/libguac_la-user-handlers.Plo \ ./$(DEPDIR)/libguac_la-user-handshake.Plo \ ./$(DEPDIR)/libguac_la-user.Plo \ ./$(DEPDIR)/libguac_la-wait-fd.Plo \ ./$(DEPDIR)/libguac_la-wol.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libguac_la_SOURCES) DIST_SOURCES = $(am__libguac_la_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__libguacinc_HEADERS_DIST = guacamole/argv.h \ guacamole/argv-constants.h guacamole/argv-fntypes.h \ guacamole/audio.h guacamole/audio-fntypes.h \ guacamole/audio-types.h guacamole/client-constants.h \ guacamole/client.h guacamole/client-fntypes.h \ guacamole/client-types.h guacamole/error.h \ guacamole/error-types.h guacamole/hash.h guacamole/layer.h \ guacamole/layer-types.h guacamole/object.h \ guacamole/object-types.h guacamole/parser-constants.h \ guacamole/parser.h guacamole/parser-types.h \ guacamole/plugin-constants.h guacamole/plugin.h \ guacamole/pool.h guacamole/pool-types.h guacamole/protocol.h \ guacamole/protocol-constants.h guacamole/protocol-types.h \ guacamole/socket-constants.h guacamole/socket.h \ guacamole/socket-fntypes.h guacamole/socket-types.h \ guacamole/stream.h guacamole/stream-types.h guacamole/string.h \ guacamole/timestamp.h guacamole/timestamp-types.h \ guacamole/unicode.h guacamole/user.h \ guacamole/user-constants.h guacamole/user-fntypes.h \ guacamole/user-types.h guacamole/wol.h \ guacamole/wol-constants.h guacamole/socket-ssl.h \ guacamole/socket-wsa.h am__noinst_HEADERS_DIST = id.h encode-jpeg.h encode-png.h palette.h \ user-handlers.h raw_encoder.h wait-fd.h encode-webp.h HEADERS = $(libguacinc_HEADERS) $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir distdir-am am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac.la SUBDIRS = . tests libguacincdir = $(includedir)/guacamole libguacinc_HEADERS = guacamole/argv.h guacamole/argv-constants.h \ guacamole/argv-fntypes.h guacamole/audio.h \ guacamole/audio-fntypes.h guacamole/audio-types.h \ guacamole/client-constants.h guacamole/client.h \ guacamole/client-fntypes.h guacamole/client-types.h \ guacamole/error.h guacamole/error-types.h guacamole/hash.h \ guacamole/layer.h guacamole/layer-types.h guacamole/object.h \ guacamole/object-types.h guacamole/parser-constants.h \ guacamole/parser.h guacamole/parser-types.h \ guacamole/plugin-constants.h guacamole/plugin.h \ guacamole/pool.h guacamole/pool-types.h guacamole/protocol.h \ guacamole/protocol-constants.h guacamole/protocol-types.h \ guacamole/socket-constants.h guacamole/socket.h \ guacamole/socket-fntypes.h guacamole/socket-types.h \ guacamole/stream.h guacamole/stream-types.h guacamole/string.h \ guacamole/timestamp.h guacamole/timestamp-types.h \ guacamole/unicode.h guacamole/user.h \ guacamole/user-constants.h guacamole/user-fntypes.h \ guacamole/user-types.h guacamole/wol.h \ guacamole/wol-constants.h $(am__append_4) $(am__append_6) noinst_HEADERS = id.h encode-jpeg.h encode-png.h palette.h \ user-handlers.h raw_encoder.h wait-fd.h $(am__append_2) libguac_la_SOURCES = argv.c audio.c client.c encode-jpeg.c \ encode-png.c error.c hash.c id.c palette.c parser.c pool.c \ protocol.c raw_encoder.c socket.c socket-broadcast.c \ socket-fd.c socket-nest.c socket-tee.c string.c timestamp.c \ unicode.c user.c user-handlers.c user-handshake.c wait-fd.c \ wol.c $(am__append_1) $(am__append_3) $(am__append_5) libguac_la_CFLAGS = \ -Werror -Wall -pedantic libguac_la_LDFLAGS = \ -version-info 19:0:0 \ -no-undefined \ @CAIRO_LIBS@ \ @DL_LIBS@ \ @JPEG_LIBS@ \ @PNG_LIBS@ \ @PTHREAD_LIBS@ \ @SSL_LIBS@ \ @UUID_LIBS@ \ @VORBIS_LIBS@ \ @WEBP_LIBS@ \ @WINSOCK_LIBS@ all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/libguac/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/libguac/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libguac.la: $(libguac_la_OBJECTS) $(libguac_la_DEPENDENCIES) $(EXTRA_libguac_la_DEPENDENCIES) $(AM_V_CCLD)$(libguac_la_LINK) -rpath $(libdir) $(libguac_la_OBJECTS) $(libguac_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-argv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-audio.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-client.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-encode-jpeg.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-encode-png.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-encode-webp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-error.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-hash.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-id.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-palette.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-pool.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-protocol.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-raw_encoder.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-socket-broadcast.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-socket-fd.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-socket-nest.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-socket-ssl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-socket-tee.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-socket-wsa.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-socket.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-string.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-timestamp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-unicode.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-user-handlers.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-user-handshake.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-user.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-wait-fd.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_la-wol.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libguac_la-argv.lo: argv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-argv.lo -MD -MP -MF $(DEPDIR)/libguac_la-argv.Tpo -c -o libguac_la-argv.lo `test -f 'argv.c' || echo '$(srcdir)/'`argv.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-argv.Tpo $(DEPDIR)/libguac_la-argv.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='argv.c' object='libguac_la-argv.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-argv.lo `test -f 'argv.c' || echo '$(srcdir)/'`argv.c libguac_la-audio.lo: audio.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-audio.lo -MD -MP -MF $(DEPDIR)/libguac_la-audio.Tpo -c -o libguac_la-audio.lo `test -f 'audio.c' || echo '$(srcdir)/'`audio.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-audio.Tpo $(DEPDIR)/libguac_la-audio.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='audio.c' object='libguac_la-audio.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-audio.lo `test -f 'audio.c' || echo '$(srcdir)/'`audio.c libguac_la-client.lo: client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-client.lo -MD -MP -MF $(DEPDIR)/libguac_la-client.Tpo -c -o libguac_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-client.Tpo $(DEPDIR)/libguac_la-client.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client.c' object='libguac_la-client.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c libguac_la-encode-jpeg.lo: encode-jpeg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-encode-jpeg.lo -MD -MP -MF $(DEPDIR)/libguac_la-encode-jpeg.Tpo -c -o libguac_la-encode-jpeg.lo `test -f 'encode-jpeg.c' || echo '$(srcdir)/'`encode-jpeg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-encode-jpeg.Tpo $(DEPDIR)/libguac_la-encode-jpeg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encode-jpeg.c' object='libguac_la-encode-jpeg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-encode-jpeg.lo `test -f 'encode-jpeg.c' || echo '$(srcdir)/'`encode-jpeg.c libguac_la-encode-png.lo: encode-png.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-encode-png.lo -MD -MP -MF $(DEPDIR)/libguac_la-encode-png.Tpo -c -o libguac_la-encode-png.lo `test -f 'encode-png.c' || echo '$(srcdir)/'`encode-png.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-encode-png.Tpo $(DEPDIR)/libguac_la-encode-png.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encode-png.c' object='libguac_la-encode-png.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-encode-png.lo `test -f 'encode-png.c' || echo '$(srcdir)/'`encode-png.c libguac_la-error.lo: error.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-error.lo -MD -MP -MF $(DEPDIR)/libguac_la-error.Tpo -c -o libguac_la-error.lo `test -f 'error.c' || echo '$(srcdir)/'`error.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-error.Tpo $(DEPDIR)/libguac_la-error.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='error.c' object='libguac_la-error.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-error.lo `test -f 'error.c' || echo '$(srcdir)/'`error.c libguac_la-hash.lo: hash.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-hash.lo -MD -MP -MF $(DEPDIR)/libguac_la-hash.Tpo -c -o libguac_la-hash.lo `test -f 'hash.c' || echo '$(srcdir)/'`hash.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-hash.Tpo $(DEPDIR)/libguac_la-hash.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hash.c' object='libguac_la-hash.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-hash.lo `test -f 'hash.c' || echo '$(srcdir)/'`hash.c libguac_la-id.lo: id.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-id.lo -MD -MP -MF $(DEPDIR)/libguac_la-id.Tpo -c -o libguac_la-id.lo `test -f 'id.c' || echo '$(srcdir)/'`id.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-id.Tpo $(DEPDIR)/libguac_la-id.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='id.c' object='libguac_la-id.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-id.lo `test -f 'id.c' || echo '$(srcdir)/'`id.c libguac_la-palette.lo: palette.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-palette.lo -MD -MP -MF $(DEPDIR)/libguac_la-palette.Tpo -c -o libguac_la-palette.lo `test -f 'palette.c' || echo '$(srcdir)/'`palette.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-palette.Tpo $(DEPDIR)/libguac_la-palette.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='palette.c' object='libguac_la-palette.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-palette.lo `test -f 'palette.c' || echo '$(srcdir)/'`palette.c libguac_la-parser.lo: parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-parser.lo -MD -MP -MF $(DEPDIR)/libguac_la-parser.Tpo -c -o libguac_la-parser.lo `test -f 'parser.c' || echo '$(srcdir)/'`parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-parser.Tpo $(DEPDIR)/libguac_la-parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parser.c' object='libguac_la-parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-parser.lo `test -f 'parser.c' || echo '$(srcdir)/'`parser.c libguac_la-pool.lo: pool.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-pool.lo -MD -MP -MF $(DEPDIR)/libguac_la-pool.Tpo -c -o libguac_la-pool.lo `test -f 'pool.c' || echo '$(srcdir)/'`pool.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-pool.Tpo $(DEPDIR)/libguac_la-pool.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pool.c' object='libguac_la-pool.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-pool.lo `test -f 'pool.c' || echo '$(srcdir)/'`pool.c libguac_la-protocol.lo: protocol.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-protocol.lo -MD -MP -MF $(DEPDIR)/libguac_la-protocol.Tpo -c -o libguac_la-protocol.lo `test -f 'protocol.c' || echo '$(srcdir)/'`protocol.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-protocol.Tpo $(DEPDIR)/libguac_la-protocol.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='protocol.c' object='libguac_la-protocol.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-protocol.lo `test -f 'protocol.c' || echo '$(srcdir)/'`protocol.c libguac_la-raw_encoder.lo: raw_encoder.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-raw_encoder.lo -MD -MP -MF $(DEPDIR)/libguac_la-raw_encoder.Tpo -c -o libguac_la-raw_encoder.lo `test -f 'raw_encoder.c' || echo '$(srcdir)/'`raw_encoder.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-raw_encoder.Tpo $(DEPDIR)/libguac_la-raw_encoder.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='raw_encoder.c' object='libguac_la-raw_encoder.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-raw_encoder.lo `test -f 'raw_encoder.c' || echo '$(srcdir)/'`raw_encoder.c libguac_la-socket.lo: socket.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-socket.lo -MD -MP -MF $(DEPDIR)/libguac_la-socket.Tpo -c -o libguac_la-socket.lo `test -f 'socket.c' || echo '$(srcdir)/'`socket.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-socket.Tpo $(DEPDIR)/libguac_la-socket.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socket.c' object='libguac_la-socket.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-socket.lo `test -f 'socket.c' || echo '$(srcdir)/'`socket.c libguac_la-socket-broadcast.lo: socket-broadcast.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-socket-broadcast.lo -MD -MP -MF $(DEPDIR)/libguac_la-socket-broadcast.Tpo -c -o libguac_la-socket-broadcast.lo `test -f 'socket-broadcast.c' || echo '$(srcdir)/'`socket-broadcast.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-socket-broadcast.Tpo $(DEPDIR)/libguac_la-socket-broadcast.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socket-broadcast.c' object='libguac_la-socket-broadcast.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-socket-broadcast.lo `test -f 'socket-broadcast.c' || echo '$(srcdir)/'`socket-broadcast.c libguac_la-socket-fd.lo: socket-fd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-socket-fd.lo -MD -MP -MF $(DEPDIR)/libguac_la-socket-fd.Tpo -c -o libguac_la-socket-fd.lo `test -f 'socket-fd.c' || echo '$(srcdir)/'`socket-fd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-socket-fd.Tpo $(DEPDIR)/libguac_la-socket-fd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socket-fd.c' object='libguac_la-socket-fd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-socket-fd.lo `test -f 'socket-fd.c' || echo '$(srcdir)/'`socket-fd.c libguac_la-socket-nest.lo: socket-nest.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-socket-nest.lo -MD -MP -MF $(DEPDIR)/libguac_la-socket-nest.Tpo -c -o libguac_la-socket-nest.lo `test -f 'socket-nest.c' || echo '$(srcdir)/'`socket-nest.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-socket-nest.Tpo $(DEPDIR)/libguac_la-socket-nest.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socket-nest.c' object='libguac_la-socket-nest.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-socket-nest.lo `test -f 'socket-nest.c' || echo '$(srcdir)/'`socket-nest.c libguac_la-socket-tee.lo: socket-tee.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-socket-tee.lo -MD -MP -MF $(DEPDIR)/libguac_la-socket-tee.Tpo -c -o libguac_la-socket-tee.lo `test -f 'socket-tee.c' || echo '$(srcdir)/'`socket-tee.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-socket-tee.Tpo $(DEPDIR)/libguac_la-socket-tee.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socket-tee.c' object='libguac_la-socket-tee.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-socket-tee.lo `test -f 'socket-tee.c' || echo '$(srcdir)/'`socket-tee.c libguac_la-string.lo: string.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-string.lo -MD -MP -MF $(DEPDIR)/libguac_la-string.Tpo -c -o libguac_la-string.lo `test -f 'string.c' || echo '$(srcdir)/'`string.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-string.Tpo $(DEPDIR)/libguac_la-string.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string.c' object='libguac_la-string.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-string.lo `test -f 'string.c' || echo '$(srcdir)/'`string.c libguac_la-timestamp.lo: timestamp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-timestamp.lo -MD -MP -MF $(DEPDIR)/libguac_la-timestamp.Tpo -c -o libguac_la-timestamp.lo `test -f 'timestamp.c' || echo '$(srcdir)/'`timestamp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-timestamp.Tpo $(DEPDIR)/libguac_la-timestamp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='timestamp.c' object='libguac_la-timestamp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-timestamp.lo `test -f 'timestamp.c' || echo '$(srcdir)/'`timestamp.c libguac_la-unicode.lo: unicode.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-unicode.lo -MD -MP -MF $(DEPDIR)/libguac_la-unicode.Tpo -c -o libguac_la-unicode.lo `test -f 'unicode.c' || echo '$(srcdir)/'`unicode.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-unicode.Tpo $(DEPDIR)/libguac_la-unicode.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unicode.c' object='libguac_la-unicode.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-unicode.lo `test -f 'unicode.c' || echo '$(srcdir)/'`unicode.c libguac_la-user.lo: user.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-user.lo -MD -MP -MF $(DEPDIR)/libguac_la-user.Tpo -c -o libguac_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-user.Tpo $(DEPDIR)/libguac_la-user.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user.c' object='libguac_la-user.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c libguac_la-user-handlers.lo: user-handlers.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-user-handlers.lo -MD -MP -MF $(DEPDIR)/libguac_la-user-handlers.Tpo -c -o libguac_la-user-handlers.lo `test -f 'user-handlers.c' || echo '$(srcdir)/'`user-handlers.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-user-handlers.Tpo $(DEPDIR)/libguac_la-user-handlers.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user-handlers.c' object='libguac_la-user-handlers.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-user-handlers.lo `test -f 'user-handlers.c' || echo '$(srcdir)/'`user-handlers.c libguac_la-user-handshake.lo: user-handshake.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-user-handshake.lo -MD -MP -MF $(DEPDIR)/libguac_la-user-handshake.Tpo -c -o libguac_la-user-handshake.lo `test -f 'user-handshake.c' || echo '$(srcdir)/'`user-handshake.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-user-handshake.Tpo $(DEPDIR)/libguac_la-user-handshake.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user-handshake.c' object='libguac_la-user-handshake.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-user-handshake.lo `test -f 'user-handshake.c' || echo '$(srcdir)/'`user-handshake.c libguac_la-wait-fd.lo: wait-fd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-wait-fd.lo -MD -MP -MF $(DEPDIR)/libguac_la-wait-fd.Tpo -c -o libguac_la-wait-fd.lo `test -f 'wait-fd.c' || echo '$(srcdir)/'`wait-fd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-wait-fd.Tpo $(DEPDIR)/libguac_la-wait-fd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wait-fd.c' object='libguac_la-wait-fd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-wait-fd.lo `test -f 'wait-fd.c' || echo '$(srcdir)/'`wait-fd.c libguac_la-wol.lo: wol.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-wol.lo -MD -MP -MF $(DEPDIR)/libguac_la-wol.Tpo -c -o libguac_la-wol.lo `test -f 'wol.c' || echo '$(srcdir)/'`wol.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-wol.Tpo $(DEPDIR)/libguac_la-wol.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wol.c' object='libguac_la-wol.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-wol.lo `test -f 'wol.c' || echo '$(srcdir)/'`wol.c libguac_la-encode-webp.lo: encode-webp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-encode-webp.lo -MD -MP -MF $(DEPDIR)/libguac_la-encode-webp.Tpo -c -o libguac_la-encode-webp.lo `test -f 'encode-webp.c' || echo '$(srcdir)/'`encode-webp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-encode-webp.Tpo $(DEPDIR)/libguac_la-encode-webp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encode-webp.c' object='libguac_la-encode-webp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-encode-webp.lo `test -f 'encode-webp.c' || echo '$(srcdir)/'`encode-webp.c libguac_la-socket-ssl.lo: socket-ssl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-socket-ssl.lo -MD -MP -MF $(DEPDIR)/libguac_la-socket-ssl.Tpo -c -o libguac_la-socket-ssl.lo `test -f 'socket-ssl.c' || echo '$(srcdir)/'`socket-ssl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-socket-ssl.Tpo $(DEPDIR)/libguac_la-socket-ssl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socket-ssl.c' object='libguac_la-socket-ssl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-socket-ssl.lo `test -f 'socket-ssl.c' || echo '$(srcdir)/'`socket-ssl.c libguac_la-socket-wsa.lo: socket-wsa.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -MT libguac_la-socket-wsa.lo -MD -MP -MF $(DEPDIR)/libguac_la-socket-wsa.Tpo -c -o libguac_la-socket-wsa.lo `test -f 'socket-wsa.c' || echo '$(srcdir)/'`socket-wsa.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_la-socket-wsa.Tpo $(DEPDIR)/libguac_la-socket-wsa.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socket-wsa.c' object='libguac_la-socket-wsa.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_la_CFLAGS) $(CFLAGS) -c -o libguac_la-socket-wsa.lo `test -f 'socket-wsa.c' || echo '$(srcdir)/'`socket-wsa.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-libguacincHEADERS: $(libguacinc_HEADERS) @$(NORMAL_INSTALL) @list='$(libguacinc_HEADERS)'; test -n "$(libguacincdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libguacincdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libguacincdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libguacincdir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libguacincdir)" || exit $$?; \ done uninstall-libguacincHEADERS: @$(NORMAL_UNINSTALL) @list='$(libguacinc_HEADERS)'; test -n "$(libguacincdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libguacincdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libguacincdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-recursive -rm -f ./$(DEPDIR)/libguac_la-argv.Plo -rm -f ./$(DEPDIR)/libguac_la-audio.Plo -rm -f ./$(DEPDIR)/libguac_la-client.Plo -rm -f ./$(DEPDIR)/libguac_la-encode-jpeg.Plo -rm -f ./$(DEPDIR)/libguac_la-encode-png.Plo -rm -f ./$(DEPDIR)/libguac_la-encode-webp.Plo -rm -f ./$(DEPDIR)/libguac_la-error.Plo -rm -f ./$(DEPDIR)/libguac_la-hash.Plo -rm -f ./$(DEPDIR)/libguac_la-id.Plo -rm -f ./$(DEPDIR)/libguac_la-palette.Plo -rm -f ./$(DEPDIR)/libguac_la-parser.Plo -rm -f ./$(DEPDIR)/libguac_la-pool.Plo -rm -f ./$(DEPDIR)/libguac_la-protocol.Plo -rm -f ./$(DEPDIR)/libguac_la-raw_encoder.Plo -rm -f ./$(DEPDIR)/libguac_la-socket-broadcast.Plo -rm -f ./$(DEPDIR)/libguac_la-socket-fd.Plo -rm -f ./$(DEPDIR)/libguac_la-socket-nest.Plo -rm -f ./$(DEPDIR)/libguac_la-socket-ssl.Plo -rm -f ./$(DEPDIR)/libguac_la-socket-tee.Plo -rm -f ./$(DEPDIR)/libguac_la-socket-wsa.Plo -rm -f ./$(DEPDIR)/libguac_la-socket.Plo -rm -f ./$(DEPDIR)/libguac_la-string.Plo -rm -f ./$(DEPDIR)/libguac_la-timestamp.Plo -rm -f ./$(DEPDIR)/libguac_la-unicode.Plo -rm -f ./$(DEPDIR)/libguac_la-user-handlers.Plo -rm -f ./$(DEPDIR)/libguac_la-user-handshake.Plo -rm -f ./$(DEPDIR)/libguac_la-user.Plo -rm -f ./$(DEPDIR)/libguac_la-wait-fd.Plo -rm -f ./$(DEPDIR)/libguac_la-wol.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-libguacincHEADERS install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/libguac_la-argv.Plo -rm -f ./$(DEPDIR)/libguac_la-audio.Plo -rm -f ./$(DEPDIR)/libguac_la-client.Plo -rm -f ./$(DEPDIR)/libguac_la-encode-jpeg.Plo -rm -f ./$(DEPDIR)/libguac_la-encode-png.Plo -rm -f ./$(DEPDIR)/libguac_la-encode-webp.Plo -rm -f ./$(DEPDIR)/libguac_la-error.Plo -rm -f ./$(DEPDIR)/libguac_la-hash.Plo -rm -f ./$(DEPDIR)/libguac_la-id.Plo -rm -f ./$(DEPDIR)/libguac_la-palette.Plo -rm -f ./$(DEPDIR)/libguac_la-parser.Plo -rm -f ./$(DEPDIR)/libguac_la-pool.Plo -rm -f ./$(DEPDIR)/libguac_la-protocol.Plo -rm -f ./$(DEPDIR)/libguac_la-raw_encoder.Plo -rm -f ./$(DEPDIR)/libguac_la-socket-broadcast.Plo -rm -f ./$(DEPDIR)/libguac_la-socket-fd.Plo -rm -f ./$(DEPDIR)/libguac_la-socket-nest.Plo -rm -f ./$(DEPDIR)/libguac_la-socket-ssl.Plo -rm -f ./$(DEPDIR)/libguac_la-socket-tee.Plo -rm -f ./$(DEPDIR)/libguac_la-socket-wsa.Plo -rm -f ./$(DEPDIR)/libguac_la-socket.Plo -rm -f ./$(DEPDIR)/libguac_la-string.Plo -rm -f ./$(DEPDIR)/libguac_la-timestamp.Plo -rm -f ./$(DEPDIR)/libguac_la-unicode.Plo -rm -f ./$(DEPDIR)/libguac_la-user-handlers.Plo -rm -f ./$(DEPDIR)/libguac_la-user-handshake.Plo -rm -f ./$(DEPDIR)/libguac_la-user.Plo -rm -f ./$(DEPDIR)/libguac_la-wait-fd.Plo -rm -f ./$(DEPDIR)/libguac_la-wol.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-libguacincHEADERS .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--depfiles check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES \ install-libguacincHEADERS install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-libLTLIBRARIES uninstall-libguacincHEADERS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/libguac/palette.c0000644000175100001440000000723313613156714015705 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "palette.h" #include #include #include #include #include guac_palette* guac_palette_alloc(cairo_surface_t* surface) { int x, y; int width = cairo_image_surface_get_width(surface); int height = cairo_image_surface_get_height(surface); int stride = cairo_image_surface_get_stride(surface); unsigned char* data = cairo_image_surface_get_data(surface); /* Allocate palette */ guac_palette* palette = (guac_palette*) malloc(sizeof(guac_palette)); memset(palette, 0, sizeof(guac_palette)); for (y=0; y> 12) ^ (color & 0xFFF); guac_palette_entry* entry; /* Search for open palette entry */ for (;;) { entry = &(palette->entries[hash]); /* If we've found a free space, use it */ if (entry->index == 0) { png_color* c; /* Stop if already at capacity */ if (palette->size == 256) { guac_palette_free(palette); return NULL; } /* Store in palette */ c = &(palette->colors[palette->size]); c->blue = (color ) & 0xFF; c->green = (color >> 8 ) & 0xFF; c->red = (color >> 16) & 0xFF; /* Add color to map */ entry->index = ++palette->size; entry->color = color; break; } /* Otherwise, if already stored here, done */ if (entry->color == color) break; /* Otherwise, collision. Move on to another bucket */ hash = (hash+1) & 0xFFF; } } /* Advance to next data row */ data += stride; } return palette; } int guac_palette_find(guac_palette* palette, int color) { /* Calculate hash code */ int hash = ((color & 0xFFF000) >> 12) ^ (color & 0xFFF); guac_palette_entry* entry; /* Search for palette entry */ for (;;) { entry = &(palette->entries[hash]); /* If we've found a free space, color not stored. */ if (entry->index == 0) return -1; /* Otherwise, if color indeed stored here, done */ if (entry->color == color) return entry->index - 1; /* Otherwise, collision. Move on to another bucket */ hash = (hash+1) & 0xFFF; } } void guac_palette_free(guac_palette* palette) { free(palette); } guacamole-server-1.3.0/src/libguac/socket-broadcast.c0000644000175100001440000002506713764613616017512 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/client.h" #include "guacamole/error.h" #include "guacamole/socket.h" #include "guacamole/user.h" #include #include /** * Data associated with an open socket which writes to all connected users of * a particular guac_client. */ typedef struct guac_socket_broadcast_data { /** * The guac_client whose connected users should receive all instructions * written to this socket. */ guac_client* client; /** * Lock which is acquired when an instruction is being written, and * released when the instruction is finished being written. */ pthread_mutex_t socket_lock; } guac_socket_broadcast_data; /** * Single chunk of data, to be broadcast to all users. */ typedef struct __write_chunk { /** * The buffer to write. */ const void* buffer; /** * The number of bytes in the buffer. */ size_t length; } __write_chunk; /** * Callback which handles read requests on the broadcast socket. This callback * always fails, as the broadcast socket is write-only; it cannot be read. * * @param socket * The broadcast socket to read from. * * @param buf * The buffer into which data should be read. * * @param count * The number of bytes to attempt to read. * * @return * The number of bytes read, or -1 if an error occurs. This implementation * always returns -1, as the broadcast socket is write-only and cannot be * read. */ static ssize_t __guac_socket_broadcast_read_handler(guac_socket* socket, void* buf, size_t count) { /* Broadcast socket reads are not allowed */ return -1; } /** * Callback invoked by guac_client_foreach_user() which write a given chunk of * data to that user's socket. If the write attempt fails, the user is * signalled to stop with guac_user_stop(). * * @param user * The user that the chunk of data should be written to. * * @param data * A pointer to a __write_chunk which describes the data to be written. * * @return * Always NULL. */ static void* __write_chunk_callback(guac_user* user, void* data) { __write_chunk* chunk = (__write_chunk*) data; /* Attempt write, disconnect on failure */ if (guac_socket_write(user->socket, chunk->buffer, chunk->length)) guac_user_stop(user); return NULL; } /** * Socket write handler which operates on each of the sockets of all connected * users. This write handler will always succeed, but any failing user-specific * writes will invoke guac_user_stop() on the failing user. * * @param socket * The socket to which the given data must be written. * * @param buf * The buffer containing the data to write. * * @param count * The number of bytes to attempt to write from the given buffer. * * @return * The number of bytes written, or -1 if an error occurs. This handler will * always succeed, and thus will always return the exact number of bytes * specified by count. */ static ssize_t __guac_socket_broadcast_write_handler(guac_socket* socket, const void* buf, size_t count) { guac_socket_broadcast_data* data = (guac_socket_broadcast_data*) socket->data; /* Build chunk */ __write_chunk chunk; chunk.buffer = buf; chunk.length = count; /* Broadcast chunk to all users */ guac_client_foreach_user(data->client, __write_chunk_callback, &chunk); return count; } /** * Callback which is invoked by guac_client_foreach_user() to flush all * pending data on the given user's socket. If an error occurs while flushing * a user's socket, that user is signalled to stop with guac_user_stop(). * * @param user * The user whose socket should be flushed. * * @param data * Arbitrary data passed to guac_client_foreach_user(). This is not needed * by this callback, and should be left as NULL. * * @return * Always NULL. */ static void* __flush_callback(guac_user* user, void* data) { /* Attempt flush, disconnect on failure */ if (guac_socket_flush(user->socket)) guac_user_stop(user); return NULL; } /** * Socket flush handler which operates on each of the sockets of all connected * users. This flush handler will always succeed, but any failing user-specific * flush will invoke guac_user_stop() on the failing user. * * @param socket * The broadcast socket to flush. * * @return * Zero if the flush operation succeeds, non-zero if the operation fails. * This handler will always succeed, and thus will always return zero. */ static ssize_t __guac_socket_broadcast_flush_handler(guac_socket* socket) { guac_socket_broadcast_data* data = (guac_socket_broadcast_data*) socket->data; /* Flush all users */ guac_client_foreach_user(data->client, __flush_callback, NULL); return 0; } /** * Callback which is invoked by guac_client_foreach_user() to lock the given * user's socket in preparation for the beginning of a Guacamole protocol * instruction. * * @param user * The user whose socket should be locked. * * @param data * Arbitrary data passed to guac_client_foreach_user(). This is not needed * by this callback, and should be left as NULL. * * @return * Always NULL. */ static void* __lock_callback(guac_user* user, void* data) { /* Lock socket */ guac_socket_instruction_begin(user->socket); return NULL; } /** * Socket lock handler which acquires the socket locks of all connected users. * Socket-level locks are acquired in preparation for the beginning of a new * Guacamole instruction to ensure that parallel writes are only interleaved at * instruction boundaries. * * @param socket * The broadcast socket to lock. */ static void __guac_socket_broadcast_lock_handler(guac_socket* socket) { guac_socket_broadcast_data* data = (guac_socket_broadcast_data*) socket->data; /* Acquire exclusive access to socket */ pthread_mutex_lock(&(data->socket_lock)); /* Lock sockets of all users */ guac_client_foreach_user(data->client, __lock_callback, NULL); } /** * Callback which is invoked by guac_client_foreach_user() to unlock the given * user's socket at the end of a Guacamole protocol instruction. * * @param user * The user whose socket should be unlocked. * * @param data * Arbitrary data passed to guac_client_foreach_user(). This is not needed * by this callback, and should be left as NULL. * * @return * Always NULL. */ static void* __unlock_callback(guac_user* user, void* data) { /* Unlock socket */ guac_socket_instruction_end(user->socket); return NULL; } /** * Socket unlock handler which releases the socket locks of all connected users. * Socket-level locks are released after a Guacamole instruction has finished * being written. * * @param socket * The broadcast socket to unlock. */ static void __guac_socket_broadcast_unlock_handler(guac_socket* socket) { guac_socket_broadcast_data* data = (guac_socket_broadcast_data*) socket->data; /* Unlock sockets of all users */ guac_client_foreach_user(data->client, __unlock_callback, NULL); /* Relinquish exclusive access to socket */ pthread_mutex_unlock(&(data->socket_lock)); } /** * Callback which handles select operations on the broadcast socket, waiting * for data to become available such that the next read operation will not * block. This callback always fails, as the broadcast socket is write-only; it * cannot be read. * * @param socket * The broadcast socket to wait for. * * @param usec_timeout * The maximum amount of time to wait for data, in microseconds, or -1 to * potentially wait forever. * * @return * A positive value on success, zero if the timeout elapsed and no data is * available, or a negative value if an error occurs. This implementation * always returns -1, as the broadcast socket is write-only and cannot be * read. */ static int __guac_socket_broadcast_select_handler(guac_socket* socket, int usec_timeout) { /* Selecting the broadcast socket is not possible */ return -1; } /** * Frees all implementation-specific data associated with the given socket, but * not the socket object itself. * * @param socket * The guac_socket whose associated data should be freed. * * @return * Zero if the data was successfully freed, non-zero otherwise. This * implementation always succeeds, and will always return zero. */ static int __guac_socket_broadcast_free_handler(guac_socket* socket) { guac_socket_broadcast_data* data = (guac_socket_broadcast_data*) socket->data; /* Destroy locks */ pthread_mutex_destroy(&(data->socket_lock)); free(data); return 0; } guac_socket* guac_socket_broadcast(guac_client* client) { pthread_mutexattr_t lock_attributes; /* Allocate socket and associated data */ guac_socket* socket = guac_socket_alloc(); guac_socket_broadcast_data* data = malloc(sizeof(guac_socket_broadcast_data)); /* Store client as socket data */ data->client = client; socket->data = data; pthread_mutexattr_init(&lock_attributes); pthread_mutexattr_setpshared(&lock_attributes, PTHREAD_PROCESS_SHARED); /* Init lock */ pthread_mutex_init(&(data->socket_lock), &lock_attributes); /* Set read/write handlers */ socket->read_handler = __guac_socket_broadcast_read_handler; socket->write_handler = __guac_socket_broadcast_write_handler; socket->select_handler = __guac_socket_broadcast_select_handler; socket->flush_handler = __guac_socket_broadcast_flush_handler; socket->lock_handler = __guac_socket_broadcast_lock_handler; socket->unlock_handler = __guac_socket_broadcast_unlock_handler; socket->free_handler = __guac_socket_broadcast_free_handler; return socket; } guacamole-server-1.3.0/src/libguac/guacamole/0000755000175100001440000000000013772471155016120 500000000000000guacamole-server-1.3.0/src/libguac/guacamole/socket-types.h0000644000175100001440000000270513613156714020642 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_SOCKET_TYPES_H #define _GUAC_SOCKET_TYPES_H /** * Type definitions related to the guac_socket object. * * @file socket-types.h */ /** * The core I/O object of Guacamole. guac_socket provides buffered input and * output as well as convenience methods for efficiently writing base64 data. */ typedef struct guac_socket guac_socket; /** * Possible current states of a guac_socket. */ typedef enum guac_socket_state { /** * The socket is open and can be written to / read from. */ GUAC_SOCKET_OPEN, /** * The socket is closed. Reads and writes will fail. */ GUAC_SOCKET_CLOSED } guac_socket_state; #endif guacamole-server-1.3.0/src/libguac/guacamole/error.h0000644000175100001440000000610213613156714017334 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_ERROR_H #define _GUAC_ERROR_H /** * Provides functions and structures required for handling return values and * errors. * * @file error.h */ #include "error-types.h" /** * Returns a human-readable explanation of the status code given. */ const char* guac_status_string(guac_status status); /** * Returns the status code associated with the error which occurred during the * last function call. This value will only be set by functions documented to * use it (most libguac functions), and is undefined if no error occurred. * * The storage of this value is thread-local. Assignment of a status code to * guac_error in one thread will not affect its value in another thread. */ #define guac_error (*__guac_error()) guac_status* __guac_error(); /** * Returns a message describing the error which occurred during the last * function call. If an error occurred, but no message is associated with it, * NULL is returned. This value is undefined if no error occurred. * * The storage of this value is thread-local. Assignment of a message to * guac_error_message in one thread will not affect its value in another * thread. */ #define guac_error_message (*__guac_error_message()) const char** __guac_error_message(); /** * Returns a human-readable explanation of the status code given. */ const char* guac_status_string(guac_status status); /** * Returns the status code associated with the error which occurred during the * last function call. This value will only be set by functions documented to * use it (most libguac functions), and is undefined if no error occurred. * * The storage of this value is thread-local. Assignment of a status code to * guac_error in one thread will not affect its value in another thread. */ #define guac_error (*__guac_error()) guac_status* __guac_error(); /** * Returns a message describing the error which occurred during the last * function call. If an error occurred, but no message is associated with it, * NULL is returned. This value is undefined if no error occurred. * * The storage of this value is thread-local. Assignment of a message to * guac_error_message in one thread will not affect its value in another * thread. */ #define guac_error_message (*__guac_error_message()) const char** __guac_error_message(); #endif guacamole-server-1.3.0/src/libguac/guacamole/hash.h0000644000175100001440000000410413721010341017107 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_HASH_H #define _GUAC_HASH_H /** * Provides functions and structures for producing likely-to-be-unique hash * values for images. * * @file hash.h */ #include /** * Produces a 24-bit hash value from all pixels of the given surface. The * surface provided must be RGB or ARGB with each pixel stored in 32 bits. * The hashing algorithm used is a variant of the cyclic polynomial rolling * hash. * * @param surface The Cairo surface to hash. * @return An arbitrary 24-bit unsigned integer value intended to be well * distributed across different images. */ unsigned int guac_hash_surface(cairo_surface_t* surface); /** * Given two Cairo surfaces, returns zero if the data contained within each * is identical, and a positive or negative value if the value of the first * is found to be lexically greater or less than the second respectively. * * @param a The first Cairo surface to compare. * @param b The Cairo surface to compare the first surface against. * @return Zero if the data contained within each is identical, and a positive * or negative value if the value of the first is found to be lexically * greater or less than the second respectively. */ int guac_surface_cmp(cairo_surface_t* a, cairo_surface_t* b); #endif guacamole-server-1.3.0/src/libguac/guacamole/wol-constants.h0000644000175100001440000000323013764613616021023 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_WOL_CONSTANTS_H #define GUAC_WOL_CONSTANTS_H /** * Header file that provides constants and defaults related to libguac * Wake-on-LAN support. * * @file wol-constants.h */ /** * The value for the local IPv4 broadcast address. */ #define GUAC_WOL_LOCAL_IPV4_BROADCAST "255.255.255.255" /** * The size of the magic Wake-on-LAN packet to send to wake a remote host. This * consists of 6 bytes of 0xFF, and then the MAC address repeated 16 times. * https://en.wikipedia.org/wiki/Wake-on-LAN#Magic_packet */ #define GUAC_WOL_PACKET_SIZE 102 /** * The port number that the magic packet should contain as the destination. In * reality this doesn't matter all that much, since the packet is not usually * processed by a full IP stack, but defining one is considered a standard * practice. */ #define GUAC_WOL_PORT 9 #endif /* GUAC_WOL_CONSTANTS_H */ guacamole-server-1.3.0/src/libguac/guacamole/argv-fntypes.h0000644000175100001440000000374413770536337020650 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_ARGV_FNTYPES_H #define GUAC_ARGV_FNTYPES_H /** * Function type definitions related to automatic handling of received "argv" * instructions. * * @file argv-fntypes.h */ #include "user-types.h" /** * Callback which is invoked by the automatic "argv" handling when the full * value of a received argument has been received. * * @param user * The user that opened the argument value stream. * * @param mimetype * The mimetype of the data that will be sent along the stream. * * @param name * The name of the connection parameter being updated. It is up to the * implementation of this handler to decide whether and how to update a * connection parameter. * * @param value * The value of the received argument. * * @param data * Any arbitrary data that was provided when the received argument was * registered with guac_argv_register(). * * @return * Zero if the received argument value has been accepted and has either * taken effect or is being intentionally ignored, non-zero otherwise. */ typedef int guac_argv_callback(guac_user* user, const char* mimetype, const char* name, const char* value, void* data); #endif guacamole-server-1.3.0/src/libguac/guacamole/user-constants.h0000644000175100001440000000357313613156714021204 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_USER_CONSTANTS_H #define _GUAC_USER_CONSTANTS_H /** * Constants related to the Guacamole user structure, guac_user. * * @file user-constants.h */ /** * The character prefix which identifies a user ID. */ #define GUAC_USER_ID_PREFIX '@' /** * The maximum number of inbound or outbound streams supported by any one * guac_user. */ #define GUAC_USER_MAX_STREAMS 64 /** * The index of a closed stream. */ #define GUAC_USER_CLOSED_STREAM_INDEX -1 /** * The maximum number of objects supported by any one guac_client. */ #define GUAC_USER_MAX_OBJECTS 64 /** * The index of an object which has not been defined. */ #define GUAC_USER_UNDEFINED_OBJECT_INDEX -1 /** * The stream name reserved for the root of a Guacamole protocol object. */ #define GUAC_USER_OBJECT_ROOT_NAME "/" /** * The mimetype of a stream containing a map of available stream names to their * corresponding mimetypes. The root of a Guacamole protocol object is * guaranteed to have this type. */ #define GUAC_USER_STREAM_INDEX_MIMETYPE "application/vnd.glyptodon.guacamole.stream-index+json" #endif guacamole-server-1.3.0/src/libguac/guacamole/protocol.h0000644000175100001440000011103113770536337020051 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_PROTOCOL_H #define _GUAC_PROTOCOL_H /** * Provides functions and structures required for communicating using the * Guacamole protocol over a guac_socket connection, such as that provided by * guac_client objects. * * @file protocol.h */ #include "layer-types.h" #include "object-types.h" #include "protocol-constants.h" #include "protocol-types.h" #include "socket-types.h" #include "stream-types.h" #include "timestamp-types.h" #include #include /* CONTROL INSTRUCTIONS */ /** * Sends an ack instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param stream The guac_stream associated with the operation this ack is * acknowledging. * @param error The human-readable description associated with the error or * status update. * @param status The status code related to the error or status. * @return Zero on success, non-zero on error. */ int guac_protocol_send_ack(guac_socket* socket, guac_stream* stream, const char* error, guac_protocol_status status); /** * Sends an args instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param args The NULL-terminated array of argument names (strings). * @return Zero on success, non-zero on error. */ int guac_protocol_send_args(guac_socket* socket, const char** args); /** * Sends a connect instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param args The NULL-terminated array of argument values (strings). * @return Zero on success, non-zero on error. */ int guac_protocol_send_connect(guac_socket* socket, const char** args); /** * Sends a disconnect instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @return Zero on success, non-zero on error. */ int guac_protocol_send_disconnect(guac_socket* socket); /** * Sends an error instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param error The human-readable description associated with the error. * @param status The status code related to the error. * @return Zero on success, non-zero on error. */ int guac_protocol_send_error(guac_socket* socket, const char* error, guac_protocol_status status); /** * Sends a key instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket * The guac_socket connection to use. * * @param keysym * The X11 keysym of the key that was pressed or released. * * @param pressed * Non-zero if the key represented by the given keysym is currently * pressed, zero if it is released. * * @param timestamp * The server timestamp (in milliseconds) at the point in time this key * event was acknowledged. * * @return * Zero on success, non-zero on error. */ int guac_protocol_send_key(guac_socket* socket, int keysym, int pressed, guac_timestamp timestamp); /** * Sends a log instruction over the given guac_socket connection. This is * mainly useful in debugging. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param format A printf-style format string to log. * @param ... Arguments to use when filling the format string for printing. * @return Zero on success, non-zero on error. */ int guac_protocol_send_log(guac_socket* socket, const char* format, ...); /** * Sends a log instruction over the given guac_socket connection. This is * mainly useful in debugging. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket * The guac_socket connection to use. * * @param format * A printf-style format string to log. * * @param args * The va_list containing the arguments to be used when filling the * format string for printing. * * @return * Zero if the instruction was sent successfully, non-zero if an error * occurs. */ int vguac_protocol_send_log(guac_socket* socket, const char* format, va_list args); /** * Sends a mouse instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket * The guac_socket connection to use. * * @param x * The X coordinate of the current mouse position. * * @param y * The Y coordinate of the current mouse position. * * @param button_mask * An integer value representing the current state of each button, where * the Nth bit within the integer is set to 1 if and only if the Nth mouse * button is currently pressed. The lowest-order bit is the left mouse * button, followed by the middle button, right button, and finally the up * and down buttons of the scroll wheel. * * @see GUAC_CLIENT_MOUSE_LEFT * @see GUAC_CLIENT_MOUSE_MIDDLE * @see GUAC_CLIENT_MOUSE_RIGHT * @see GUAC_CLIENT_MOUSE_SCROLL_UP * @see GUAC_CLIENT_MOUSE_SCROLL_DOWN * * @param timestamp * The server timestamp (in milliseconds) at the point in time this mouse * position was acknowledged. * * @return * Zero on success, non-zero on error. */ int guac_protocol_send_mouse(guac_socket* socket, int x, int y, int button_mask, guac_timestamp timestamp); /** * Sends a nest instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @deprecated * The "nest" instruction and the corresponding guac_socket * implementation are no longer necessary, having been replaced by * the streaming instructions ("blob", "ack", "end"). Code using nested * sockets or the "nest" instruction should instead write to a normal * socket directly. * * @param socket The guac_socket connection to use. * @param index The integer index of the stram to send the protocol * data over. * @param data A string containing protocol data, which must be UTF-8 * encoded and null-terminated. * @return Zero on success, non-zero on error. */ int guac_protocol_send_nest(guac_socket* socket, int index, const char* data); /** * Sends a nop instruction (null-operation) over the given guac_socket * connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @return Zero on success, non-zero on error. */ int guac_protocol_send_nop(guac_socket* socket); /** * Sends a ready instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param id The connection ID of the connection that is ready. * @return Zero on success, non-zero on error. */ int guac_protocol_send_ready(guac_socket* socket, const char* id); /** * Sends a set instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The layer to set the parameter of. * @param name The name of the parameter to set. * @param value The value to set the parameter to. * @return Zero on success, non-zero on error. */ int guac_protocol_send_set(guac_socket* socket, const guac_layer* layer, const char* name, const char* value); /** * Sends a select instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param protocol The protocol to request. * @return Zero on success, non-zero on error. */ int guac_protocol_send_select(guac_socket* socket, const char* protocol); /** * Sends a sync instruction over the given guac_socket connection. The * current time in milliseconds should be passed in as the timestamp. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param timestamp The current timestamp (in milliseconds). * @return Zero on success, non-zero on error. */ int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp); /* OBJECT INSTRUCTIONS */ /** * Sends a body instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket * The guac_socket connection to use. * * @param object * The object to associated with the stream being used. * * @param stream * The stream to use. * * @param mimetype * The mimetype of the data being sent. * * @param name * The name of the stream whose body is being sent, as requested by a "get" * instruction. * * @return * Zero on success, non-zero on error. */ int guac_protocol_send_body(guac_socket* socket, const guac_object* object, const guac_stream* stream, const char* mimetype, const char* name); /** * Sends a filesystem instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket * The guac_socket connection to use. * * @param object * The object representing the filesystem being exposed. * * @param name * A name describing the filesystem being exposed. * * @return * Zero on success, non-zero on error. */ int guac_protocol_send_filesystem(guac_socket* socket, const guac_object* object, const char* name); /** * Sends an undefine instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket * The guac_socket connection to use. * * @param object * The object being undefined. * * @return * Zero on success, non-zero on error. */ int guac_protocol_send_undefine(guac_socket* socket, const guac_object* object); /* MEDIA INSTRUCTIONS */ /** * Sends an audio instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket * The guac_socket connection to use when sending the audio instruction. * * @param stream * The stream to use for future audio data. * * @param mimetype * The mimetype of the audio data which will be sent over the given stream. * * @return * Zero on success, non-zero on error. */ int guac_protocol_send_audio(guac_socket* socket, const guac_stream* stream, const char* mimetype); /** * Sends a file instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param stream The stream to use. * @param mimetype The mimetype of the data being sent. * @param name A name describing the file being sent. * @return Zero on success, non-zero on error. */ int guac_protocol_send_file(guac_socket* socket, const guac_stream* stream, const char* mimetype, const char* name); /** * Sends a pipe instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param stream The stream to use. * @param mimetype The mimetype of the data being sent. * @param name An arbitrary name uniquely identifying this pipe. * @return Zero on success, non-zero on error. */ int guac_protocol_send_pipe(guac_socket* socket, const guac_stream* stream, const char* mimetype, const char* name); /** * Writes a block of data to the currently in-progress blob which was already * created. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param stream The stream to use. * @param data The file data to write. * @param count The number of bytes within the given buffer of file data * that must be written. * @return Zero on success, non-zero on error. */ int guac_protocol_send_blob(guac_socket* socket, const guac_stream* stream, const void* data, int count); /** * Sends a series of blob instructions, splitting the given data across the * number of instructions required to ensure the size of each blob does not * exceed GUAC_PROTOCOL_BLOB_MAX_LENGTH. If the size of data provided is zero, * no blob instructions are sent. * * If an error occurs sending any blob instruction, a non-zero value is * returned, guac_error is set appropriately, and no further blobs are sent. * * @see GUAC_PROTOCOL_BLOB_MAX_LENGTH * * @param socket * The guac_socket connection to use to send the blob instructions. * * @param stream * The stream to associate with each blob sent. * * @param data * The data which should be sent using the required number of blob * instructions. * * @param count * The number of bytes within the given buffer of data that must be * written. * * @return * Zero on success, non-zero on error. */ int guac_protocol_send_blobs(guac_socket* socket, const guac_stream* stream, const void* data, int count); /** * Sends an end instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param stream The stream to use. * @return Zero on success, non-zero on error. */ int guac_protocol_send_end(guac_socket* socket, const guac_stream* stream); /** * Sends a video instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket * The guac_socket connection to use when sending the video instruction. * * @param stream * The stream to use for future video data. * * @param layer * The destination layer on which the streamed video should be played. * * @param mimetype * The mimetype of the video data which will be sent over the given stream. * * @return * Zero on success, non-zero on error. */ int guac_protocol_send_video(guac_socket* socket, const guac_stream* stream, const guac_layer* layer, const char* mimetype); /* DRAWING INSTRUCTIONS */ /** * Sends an arc instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The destination layer. * @param x The X coordinate of the center of the circle containing the arc. * @param y The Y coordinate of the center of the circle containing the arc. * @param radius The radius of the circle containing the arc. * @param startAngle The starting angle, in radians. * @param endAngle The ending angle, in radians. * @param negative Zero if the arc should be drawn in order of increasing * angle, non-zero otherwise. * @return Zero on success, non-zero on error. */ int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, int x, int y, int radius, double startAngle, double endAngle, int negative); /** * Sends a cfill instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param mode The composite mode to use. * @param layer The destination layer. * @param r The red component of the color of the rectangle. * @param g The green component of the color of the rectangle. * @param b The blue component of the color of the rectangle. * @param a The alpha (transparency) component of the color of the rectangle. * @return Zero on success, non-zero on error. */ int guac_protocol_send_cfill(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int r, int g, int b, int a); /** * Sends a clip instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The layer to set the clipping region of. * @return Zero on success, non-zero on error. */ int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer); /** * Sends a close instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The destination layer. * @return Zero on success, non-zero on error. */ int guac_protocol_send_close(guac_socket* socket, const guac_layer* layer); /** * Sends a copy instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param srcl The source layer. * @param srcx The X coordinate of the source rectangle. * @param srcy The Y coordinate of the source rectangle. * @param w The width of the source rectangle. * @param h The height of the source rectangle. * @param mode The composite mode to use. * @param dstl The destination layer. * @param dstx The X coordinate of the destination, where the source rectangle * should be copied. * @param dsty The Y coordinate of the destination, where the source rectangle * should be copied. * @return Zero on success, non-zero on error. */ int guac_protocol_send_copy(guac_socket* socket, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty); /** * Sends a cstroke instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param mode The composite mode to use. * @param layer The destination layer. * @param cap The style of line cap to use when drawing the stroke. * @param join The style of line join to use when drawing the stroke. * @param thickness The thickness of the stroke in pixels. * @param r The red component of the color of the rectangle. * @param g The green component of the color of the rectangle. * @param b The blue component of the color of the rectangle. * @param a The alpha (transparency) component of the color of the rectangle. * @return Zero on success, non-zero on error. */ int guac_protocol_send_cstroke(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, guac_line_cap_style cap, guac_line_join_style join, int thickness, int r, int g, int b, int a); /** * Sends a cursor instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param x The X coordinate of the cursor hotspot. * @param y The Y coordinate of the cursor hotspot. * @param srcl The source layer. * @param srcx The X coordinate of the source rectangle. * @param srcy The Y coordinate of the source rectangle. * @param w The width of the source rectangle. * @param h The height of the source rectangle. * @return Zero on success, non-zero on error. */ int guac_protocol_send_cursor(guac_socket* socket, int x, int y, const guac_layer* srcl, int srcx, int srcy, int w, int h); /** * Sends a curve instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The destination layer. * @param cp1x The X coordinate of the first control point. * @param cp1y The Y coordinate of the first control point. * @param cp2x The X coordinate of the second control point. * @param cp2y The Y coordinate of the second control point. * @param x The X coordinate of the endpoint of the curve. * @param y The Y coordinate of the endpoint of the curve. * @return Zero on success, non-zero on error. */ int guac_protocol_send_curve(guac_socket* socket, const guac_layer* layer, int cp1x, int cp1y, int cp2x, int cp2y, int x, int y); /** * Sends an identity instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The destination layer. * @return Zero on success, non-zero on error. */ int guac_protocol_send_identity(guac_socket* socket, const guac_layer* layer); /** * Sends an lfill instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param mode The composite mode to use. * @param layer The destination layer. * @param srcl The source layer. * @return Zero on success, non-zero on error. */ int guac_protocol_send_lfill(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, const guac_layer* srcl); /** * Sends a line instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The destination layer. * @param x The X coordinate of the endpoint of the line. * @param y The Y coordinate of the endpoint of the line. * @return Zero on success, non-zero on error. */ int guac_protocol_send_line(guac_socket* socket, const guac_layer* layer, int x, int y); /** * Sends an lstroke instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param mode The composite mode to use. * @param layer The destination layer. * @param cap The style of line cap to use when drawing the stroke. * @param join The style of line join to use when drawing the stroke. * @param thickness The thickness of the stroke in pixels. * @param srcl The source layer. * @return Zero on success, non-zero on error. */ int guac_protocol_send_lstroke(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, guac_line_cap_style cap, guac_line_join_style join, int thickness, const guac_layer* srcl); /** * Sends an img instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket * The guac_socket connection to use when sending the img instruction. * * @param stream * The stream over which the image data will be sent. * * @param mode * The composite mode to use when drawing the image over the destination * layer. * * @param layer * The destination layer. * * @param mimetype * The mimetype of the image data being sent. * * @param x * The X coordinate of the upper-left corner of the destination rectangle * within the destination layer, in pixels. * * @param y * The Y coordinate of the upper-left corner of the destination rectangle * within the destination layer, in pixels. * * @return * Zero if the instruction was successfully sent, non-zero on error. */ int guac_protocol_send_img(guac_socket* socket, const guac_stream* stream, guac_composite_mode mode, const guac_layer* layer, const char* mimetype, int x, int y); /** * Sends a pop instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The layer to set the clipping region of. * @return Zero on success, non-zero on error. */ int guac_protocol_send_pop(guac_socket* socket, const guac_layer* layer); /** * Sends a push instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The layer to set the clipping region of. * @return Zero on success, non-zero on error. */ int guac_protocol_send_push(guac_socket* socket, const guac_layer* layer); /** * Sends a rect instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The destination layer. * @param x The X coordinate of the rectangle. * @param y The Y coordinate of the rectangle. * @param width The width of the rectangle. * @param height The height of the rectangle. * @return Zero on success, non-zero on error. */ int guac_protocol_send_rect(guac_socket* socket, const guac_layer* layer, int x, int y, int width, int height); /** * Sends a "required" instruction over the given guac_socket connection. This * instruction indicates to the client that one or more additional parameters * are needed to continue the connection. * * @param socket * The guac_socket connection to which to send the instruction. * * @param required * A NULL-terminated array of required parameters. * * @return * Zero on success, non-zero on error. */ int guac_protocol_send_required(guac_socket* socket, const char** required); /** * Sends a reset instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The layer to set the clipping region of. * @return Zero on success, non-zero on error. */ int guac_protocol_send_reset(guac_socket* socket, const guac_layer* layer); /** * Sends a start instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The destination layer. * @param x The X coordinate of the first point of the subpath. * @param y The Y coordinate of the first point of the subpath. * @return Zero on success, non-zero on error. */ int guac_protocol_send_start(guac_socket* socket, const guac_layer* layer, int x, int y); /** * Sends a transfer instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param srcl The source layer. * @param srcx The X coordinate of the source rectangle. * @param srcy The Y coordinate of the source rectangle. * @param w The width of the source rectangle. * @param h The height of the source rectangle. * @param fn The transfer function to use. * @param dstl The destination layer. * @param dstx The X coordinate of the destination, where the source rectangle * should be copied. * @param dsty The Y coordinate of the destination, where the source rectangle * should be copied. * @return Zero on success, non-zero on error. */ int guac_protocol_send_transfer(guac_socket* socket, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_transfer_function fn, const guac_layer* dstl, int dstx, int dsty); /** * Sends a transform instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The layer to apply the given transform matrix to. * @param a The first value of the affine transform matrix. * @param b The second value of the affine transform matrix. * @param c The third value of the affine transform matrix. * @param d The fourth value of the affine transform matrix. * @param e The fifth value of the affine transform matrix. * @param f The sixth value of the affine transform matrix. * @return Zero on success, non-zero on error. */ int guac_protocol_send_transform(guac_socket* socket, const guac_layer* layer, double a, double b, double c, double d, double e, double f); /* LAYER INSTRUCTIONS */ /** * Sends a dispose instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The layer to dispose. * @return Zero on success, non-zero on error. */ int guac_protocol_send_dispose(guac_socket* socket, const guac_layer* layer); /** * Sends a distort instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The layer to distort with the given transform matrix. * @param a The first value of the affine transform matrix. * @param b The second value of the affine transform matrix. * @param c The third value of the affine transform matrix. * @param d The fourth value of the affine transform matrix. * @param e The fifth value of the affine transform matrix. * @param f The sixth value of the affine transform matrix. * @return Zero on success, non-zero on error. */ int guac_protocol_send_distort(guac_socket* socket, const guac_layer* layer, double a, double b, double c, double d, double e, double f); /** * Sends a move instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The layer to move. * @param parent The parent layer the specified layer will be positioned * relative to. * @param x The X coordinate of the layer. * @param y The Y coordinate of the layer. * @param z The Z index of the layer, relative to other layers in its parent. * @return Zero on success, non-zero on error. */ int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer, const guac_layer* parent, int x, int y, int z); /** * Sends a shade instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The layer to shade. * @param a The alpha value of the layer. * @return Zero on success, non-zero on error. */ int guac_protocol_send_shade(guac_socket* socket, const guac_layer* layer, int a); /** * Sends a size instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param layer The layer to resize. * @param w The new width of the layer. * @param h The new height of the layer. * @return Zero on success, non-zero on error. */ int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, int w, int h); /* TEXT INSTRUCTIONS */ /** * Sends an argv instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket * The guac_socket connection to use to send the connection parameter * value. * * @param stream * The stream to use to send the connection parameter value. * * @param mimetype * The mimetype of the connection parameter value being sent. * * @param name * The name of the connection parameter whose current value is being sent. * * @return * Zero on success, non-zero on error. */ int guac_protocol_send_argv(guac_socket* socket, guac_stream* stream, const char* mimetype, const char* name); /** * Sends a clipboard instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. * @param stream The stream to use. * @param mimetype The mimetype of the clipboard data being sent. * @return Zero on success, non-zero on error. */ int guac_protocol_send_clipboard(guac_socket* socket, const guac_stream* stream, const char* mimetype); /** * Sends a name instruction over the given guac_socket connection. * * @param socket The guac_socket connection to use. * @param name The name to send within the name instruction. * @return Zero on success, non-zero on error. */ int guac_protocol_send_name(guac_socket* socket, const char* name); /** * Decodes the given base64-encoded string in-place. The base64 string must * be NULL-terminated. * * @param base64 The base64-encoded string to decode. * @return The number of bytes resulting from the decode operation. */ int guac_protocol_decode_base64(char* base64); /** * Given a string representation of a protocol version, return the enum value of * that protocol version, or GUAC_PROTOCOL_VERSION_UNKNOWN if the value is not a * known version. * * @param version_string * The string representation of the protocol version. * * @return * The enum value of the protocol version, or GUAC_PROTOCOL_VERSION_UNKNOWN * if the provided version is not known. */ guac_protocol_version guac_protocol_string_to_version(const char* version_string); /** * Given the enum value of the protocol version, return a pointer to the string * representation of the version, or NULL if the version is unknown. * * @param version * The enum value of the protocol version. * * @return * A pointer to the string representation of the protocol version, or NULL * if the version is unknown. */ const char* guac_protocol_version_to_string(guac_protocol_version version); #endif guacamole-server-1.3.0/src/libguac/guacamole/unicode.h0000644000175100001440000000543413613156714017640 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_UNICODE_H #define _GUAC_UNICODE_H /** * Provides functions for manipulating Unicode strings. * * @file unicode.h */ #include /** * Given the initial byte of a single UTF-8 character, returns the overall * byte size of the entire character. * * @param c The initial byte of the character to check. * @return The number of bytes in the given character overall. */ size_t guac_utf8_charsize(unsigned char c); /** * Given a UTF-8-encoded string, returns the length of the string in characters * (not bytes). * * @param str The UTF-8 string to calculate the length of. * @return The length in characters of the given UTF-8 string. */ size_t guac_utf8_strlen(const char* str); /** * Given destination buffer and its length, writes the given codepoint as UTF-8 * to the buffer, returning the number of bytes written. If there is not enough * space in the buffer to write the character, no bytes are written at all. * * @param codepoint The Unicode codepoint to write to the buffer. * @param utf8 The buffer to write to. * @param length The length of the buffer, in bytes. * @return The number of bytes written, which may be zero if there is not * enough space in the buffer to write the UTF-8 character. */ int guac_utf8_write(int codepoint, char* utf8, int length); /** * Given a buffer containing UTF-8 characters, reads the first codepoint in the * buffer, returning the length of the codepoint in bytes. If no codepoint * could be read, zero is returned. * * @param utf8 A buffer containing UTF-8 characters. * @param length The length of the buffer, in bytes. * @param codepoint A pointer to an integer which will contain the codepoint * read, if any. If no character can be read, the integer * will be left untouched. * @return The number of bytes read, which may be zero if there is not enough * space in the buffer to read a character. */ int guac_utf8_read(const char* utf8, int length, int* codepoint); #endif guacamole-server-1.3.0/src/libguac/guacamole/plugin-constants.h0000644000175100001440000000423013613156714021513 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_PLUGIN_CONSTANTS_H #define _GUAC_PLUGIN_CONSTANTS_H /** * Constants related to client plugins. * * @file plugin-constants.h */ /** * String prefix which begins the library filename of all client plugins. */ #define GUAC_PROTOCOL_LIBRARY_PREFIX "libguac-client-" /** * String suffix which ends the library filename of all client plugins. */ #define GUAC_PROTOCOL_LIBRARY_SUFFIX ".so" /** * The maximum number of characters (COUNTING NULL TERMINATOR) to allow * for protocol names within the library filename of client plugins. */ #define GUAC_PROTOCOL_NAME_LIMIT 256 /** * The maximum number of characters (INCLUDING NULL TERMINATOR) that a * character array containing the concatenation of the library prefix, * protocol name, and suffix can contain, assuming the protocol name is * limited to GUAC_PROTOCOL_NAME_LIMIT characters. */ #define GUAC_PROTOCOL_LIBRARY_LIMIT ( \ \ sizeof(GUAC_PROTOCOL_LIBRARY_PREFIX) - 1 /* "libguac-client-" */ \ + GUAC_PROTOCOL_NAME_LIMIT - 1 /* [up to 256 chars] */ \ + sizeof(GUAC_PROTOCOL_LIBRARY_SUFFIX) - 1 /* ".so" */ \ + 1 /* NULL terminator */ \ \ ) #endif guacamole-server-1.3.0/src/libguac/guacamole/client-types.h0000644000175100001440000000531113676721354020633 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_CLIENT_TYPES_H #define _GUAC_CLIENT_TYPES_H /** * Type definitions related to the Guacamole client structure, guac_client. * * @file client-types.h */ /** * Guacamole proxy client. * * Represents a Guacamole proxy client (the client which communicates to * a server on behalf of Guacamole, on behalf of the web-client). */ typedef struct guac_client guac_client; /** * Possible current states of the Guacamole client. Currently, the only * two states are GUAC_CLIENT_RUNNING and GUAC_CLIENT_STOPPING. */ typedef enum guac_client_state { /** * The state of the client from when it has been allocated by the main * daemon until it is killed or disconnected. */ GUAC_CLIENT_RUNNING, /** * The state of the client when a stop has been requested, signalling the * I/O threads to shutdown. */ GUAC_CLIENT_STOPPING } guac_client_state; /** * All supported log levels used by the logging subsystem of each Guacamole * client. With the exception of GUAC_LOG_TRACE, these log levels correspond to * a subset of the log levels defined by RFC 5424. */ typedef enum guac_client_log_level { /** * Fatal errors. */ GUAC_LOG_ERROR = 3, /** * Non-fatal conditions that indicate problems. */ GUAC_LOG_WARNING = 4, /** * Informational messages of general interest to users or administrators. */ GUAC_LOG_INFO = 6, /** * Informational messages which can be useful for debugging, but are * otherwise not useful to users or administrators. It is expected that * debug level messages, while verbose, will not negatively affect * performance. */ GUAC_LOG_DEBUG = 7, /** * Informational messages which can be useful for debugging, like * GUAC_LOG_DEBUG, but which are so low-level that they may affect * performance. */ GUAC_LOG_TRACE = 8 } guac_client_log_level; #endif guacamole-server-1.3.0/src/libguac/guacamole/audio-fntypes.h0000644000175100001440000000502513613156714020775 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_AUDIO_FNTYPES_H #define GUAC_AUDIO_FNTYPES_H /** * Function type definitions related to simple streaming audio. * * @file audio-fntypes.h */ #include "audio-types.h" #include "user-types.h" /** * Handler which is called when the audio stream is opened. * * @param audio * The audio stream being opened. */ typedef void guac_audio_encoder_begin_handler(guac_audio_stream* audio); /** * Handler which is called when the audio stream needs to be flushed. * * @param audio * The audio stream being flushed. */ typedef void guac_audio_encoder_flush_handler(guac_audio_stream* audio); /** * Handler which is called when the audio stream is closed. * * @param audio * The audio stream being closed. */ typedef void guac_audio_encoder_end_handler(guac_audio_stream* audio); /** * Handler which is called when a new user has joined the Guacamole * connection associated with the audio stream. * * @param audio * The audio stream associated with the Guacamole connection being * joined. * * @param user * The user that joined the connection. */ typedef void guac_audio_encoder_join_handler(guac_audio_stream* audio, guac_user* user); /** * Handler which is called when PCM data is written to the audio stream. The * format of the PCM data is dictated by the properties of the audio stream. * * @param audio * The audio stream to which data is being written. * * @param pcm_data * A buffer containing the raw PCM data to be written. * * @param length * The number of bytes within the buffer that should be written to the * audio stream. */ typedef void guac_audio_encoder_write_handler(guac_audio_stream* audio, const unsigned char* pcm_data, int length); #endif guacamole-server-1.3.0/src/libguac/guacamole/user-fntypes.h0000644000175100001440000003740213702142276020653 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_USER_FNTYPES_H #define _GUAC_USER_FNTYPES_H /** * Function type definitions related to the guac_user object. * * @file user-fntypes.h */ #include "object-types.h" #include "protocol-types.h" #include "stream-types.h" #include "timestamp-types.h" #include "user-types.h" /** * Callback which relates to a single guac_user at a time, along with arbitrary * data. * * @see guac_client_foreach_user() * @see guac_client_for_owner() * * @param user * The user for which this callback was invoked. Depending on whether * guac_client_foreach_user() or guac_client_for_owner() was called, this * will either be the current user as the "foreach" iteration continues, * or the owner of the connection. If guac_client_for_owner() was called * for a connection which has no owner, this may be NULL. * * @param data * The arbitrary data passed to guac_client_foreach_user() or * guac_client_for_owner(). * * @return * An arbitrary return value, the semantics of which are determined by the * implementation of the callback and the manner of its user. In the case * of a callback provided to guac_client_foreach_user(), this value is * always discarded. */ typedef void* guac_user_callback(guac_user* user, void* data); /** * Handler for Guacamole mouse events, invoked when a "mouse" instruction has * been received from a user. * * @param user * The user that sent the mouse event. * * @param x * The X coordinate of the mouse within the display when the event * occurred, in pixels. This value is not guaranteed to be within the * bounds of the display area. * * @param y * The Y coordinate of the mouse within the display when the event * occurred, in pixels. This value is not guaranteed to be within the * bounds of the display area. * * @param button_mask * An integer value representing the current state of each button, where * the Nth bit within the integer is set to 1 if and only if the Nth mouse * button is currently pressed. The lowest-order bit is the left mouse * button, followed by the middle button, right button, and finally the up * and down buttons of the scroll wheel. * * @see GUAC_CLIENT_MOUSE_LEFT * @see GUAC_CLIENT_MOUSE_MIDDLE * @see GUAC_CLIENT_MOUSE_RIGHT * @see GUAC_CLIENT_MOUSE_SCROLL_UP * @see GUAC_CLIENT_MOUSE_SCROLL_DOWN * * @return * Zero if the mouse event was handled successfully, or non-zero if an * error occurred. */ typedef int guac_user_mouse_handler(guac_user* user, int x, int y, int button_mask); /** * Handler for Guacamole key events, invoked when a "key" event has been * received from a user. * * @param user * The user that sent the key event. * * @param keysym * The X11 keysym of the key that was pressed or released. * * @param pressed * Non-zero if the key represented by the given keysym is currently * pressed, zero if it is released. * * @return * Zero if the key event was handled successfully, or non-zero if an error * occurred. */ typedef int guac_user_key_handler(guac_user* user, int keysym, int pressed); /** * Handler for Guacamole audio streams received from a user. Each such audio * stream begins when the user sends an "audio" instruction. To handle received * data along this stream, implementations of this handler must assign blob and * end handlers to the given stream object. * * @param user * The user that opened the audio stream. * * @param stream * The stream object allocated by libguac to represent the audio stream * opened by the user. * * @param mimetype * The mimetype of the data that will be sent along the stream. * * @return * Zero if the opening of the audio stream has been handled successfully, * or non-zero if an error occurs. */ typedef int guac_user_audio_handler(guac_user* user, guac_stream* stream, char* mimetype); /** * Handler for Guacamole clipboard streams received from a user. Each such * clipboard stream begins when the user sends a "clipboard" instruction. To * handle received data along this stream, implementations of this handler * must assign blob and end handlers to the given stream object. * * @param user * The user that opened the clipboard stream. * * @param stream * The stream object allocated by libguac to represent the clipboard stream * opened by the user. * * @param mimetype * The mimetype of the data that will be sent along the stream. * * @return * Zero if the opening of the clipboard stream has been handled * successfully, or non-zero if an error occurs. */ typedef int guac_user_clipboard_handler(guac_user* user, guac_stream* stream, char* mimetype); /** * Handler for Guacamole size events, invoked when a "size" instruction has * been received from a user. A "size" instruction indicates that the desired * display size has changed. * * @param user * The user whose desired display size has changed. * * @param width * The desired width of the display, in pixels. * * @param height * The desired height of the display, in pixels. * * @return * Zero if the size event has been successfully handled, non-zero * otherwise. */ typedef int guac_user_size_handler(guac_user* user, int width, int height); /** * Handler for Guacamole file streams received from a user. Each such file * stream begins when the user sends a "file" instruction. To handle received * data along this stream, implementations of this handler must assign blob and * end handlers to the given stream object. * * @param user * The user that opened the file stream. * * @param stream * The stream object allocated by libguac to represent the file stream * opened by the user. * * @param mimetype * The mimetype of the data that will be sent along the stream. * * @param filename * The name of the file being transferred. * * @return * Zero if the opening of the file stream has been handled successfully, or * non-zero if an error occurs. */ typedef int guac_user_file_handler(guac_user* user, guac_stream* stream, char* mimetype, char* filename); /** * Handler for Guacamole pipe streams received from a user. Pipe streams are * unidirectional, arbitrary, named pipes. Each such pipe stream begins when * the user sends a "pipe" instruction. To handle received data along this * stream, implementations of this handler must assign blob and end handlers to * the given stream object. * * @param user * The user that opened the pipe stream. * * @param stream * The stream object allocated by libguac to represent the pipe stream * opened by the user. * * @param mimetype * The mimetype of the data that will be sent along the stream. * * @param name * The arbitrary name assigned to this pipe. It is up to the implementation * of this handler and the application containing the Guacamole client to * determine the semantics of a pipe stream having this name. * * @return * Zero if the opening of the pipe stream has been handled successfully, or * non-zero if an error occurs. */ typedef int guac_user_pipe_handler(guac_user* user, guac_stream* stream, char* mimetype, char* name); /** * Handler for Guacamole argument value (argv) streams received from a user. * Argument value streams are real-time revisions to the connection parameters * of an in-progress connection. Each such argument value stream begins when * the user sends a "argv" instruction. To handle received data along this * stream, implementations of this handler must assign blob and end handlers to * the given stream object. * * @param user * The user that opened the argument value stream. * * @param stream * The stream object allocated by libguac to represent the argument value * stream opened by the user. * * @param mimetype * The mimetype of the data that will be sent along the stream. * * @param name * The name of the connection parameter being updated. It is up to the * implementation of this handler to decide whether and how to update a * connection parameter. * * @return * Zero if the opening of the argument value stream has been handled * successfully, or non-zero if an error occurs. */ typedef int guac_user_argv_handler(guac_user* user, guac_stream* stream, char* mimetype, char* name); /** * Handler for Guacamole stream blobs. Each blob originates from a "blob" * instruction which was associated with a previously-created stream. * * @param user * The user that is sending this blob of data along the stream. * * @param stream * The stream along which the blob was received. The semantics associated * with this stream are determined by the manner of its creation. * * @param data * The blob of data received. * * @param length * The number of bytes within the blob of data received. * * @return * Zero if the blob of data was successfully handled, non-zero otherwise. */ typedef int guac_user_blob_handler(guac_user* user, guac_stream* stream, void* data, int length); /** * Handler for Guacamole stream "ack" instructions. A user will send "ack" * instructions to acknowledge the successful receipt of blobs along a stream * opened by the server, or to notify of errors. An "ack" with an error status * implicitly closes the stream. * * @param user * The user sending the "ack" instruction. * * @param stream * The stream for which the "ack" was received. * * @param error * An arbitrary, human-readable message describing the error that * occurred, if any. If no error occurs, this will likely be blank, * "SUCCESS", or similar. This value exists for the sake of readability, * not for the sake of data interchange. * * @param status * GUAC_PROTOCOL_STATUS_SUCCESS if the blob was received and handled * successfully, or a different status code describing the problem if an * error occurred and the stream has been implicitly closed. * * @return * Zero if the "ack" message was successfully handled, non-zero otherwise. */ typedef int guac_user_ack_handler(guac_user* user, guac_stream* stream, char* error, guac_protocol_status status); /** * Handler for Guacamole stream "end" instructions. End instructions are sent * by the user when a stream is closing because its end has been reached. * * @param user * The user that sent the "end" instruction. * * @param stream * The stream that is being closed. * * @return * Zero if the end-of-stream condition has been sucessfully handled, * non-zero otherwise. */ typedef int guac_user_end_handler(guac_user* user, guac_stream* stream); /** * Handler for Guacamole join events. A join event is fired by the * guac_client whenever a guac_user joins the connection. There is no * instruction associated with a join event. * * Implementations of the join handler MUST NOT use the client-level * broadcast socket, nor invoke guac_client_foreach_user() or * guac_client_for_owner(). Doing so will result in undefined behavior, * including segfaults. * * @param user * The user joining the connection. The guac_client associated with the * connection will already be populated within the user object. * * @param argc * The number of arguments stored within argv. * * @param argv * An array of all arguments provided by the user when they joined. These * arguments must correspond to the argument names declared when the * guac_client was initialized. If the number of arguments does not match * the number of argument names declared, then the joining user has * violated the Guacamole protocol. * * @return * Zero if the user has been successfully initialized and should be allowed * to join the connection, non-zero otherwise. */ typedef int guac_user_join_handler(guac_user* user, int argc, char** argv); /** * Handler for Guacamole leave events. A leave event is fired by the * guac_client whenever a guac_user leaves the connection. There is no * instruction associated with a leave event. * * Implementations of the leave handler MUST NOT use the client-level * broadcast socket, nor invoke guac_client_foreach_user() or * guac_client_for_owner(). Doing so will result in undefined behavior, * including segfaults. * * @param user * The user that has left the connection. * * @return * Zero if the leave event has been successfully handled, non-zero * otherwise. */ typedef int guac_user_leave_handler(guac_user* user); /** * Handler for Guacamole sync events. A sync event is fired by the * guac_client whenever a guac_user responds to a "sync" instruction. Sync * instructions are sent by the Guacamole server to mark the logical end of a * frame, and to inform the Guacamole client that all data up to a particular * point in time has been sent. The response from the Guacamole client * similarly indicates that all data received up to a particular point in * server time has been handled. * * @param user * The user that sent the "sync" instruction. * * @param timestamp * The timestamp contained within the sync instruction. * * @return * Zero if the sync event has been handled successfully, non-zero * otherwise. */ typedef int guac_user_sync_handler(guac_user* user, guac_timestamp timestamp); /** * Handler for Guacamole object get requests. The semantics of the stream * which will be created in response to the request are determined by the type * of the object and the name of the stream requested. It is up to the * implementation of this handler to then respond with a "body" instruction * that begins the requested stream. * * @param user * The user requesting read access to the stream having the given name. * * @param object * The object from which the given named stream is being requested. * * @param name * The name of the stream being requested. * * @return * Zero if the get request was successfully handled, non-zero otherwise. */ typedef int guac_user_get_handler(guac_user* user, guac_object* object, char* name); /** * Handler for Guacamole object put requests. Put requests implicitly create a * stream, the semantics of which are determined by the type of the object * and the name of the stream requested. * * @param user * The user requesting write access to the stream having the given name. * * @param object * The object from which the given named stream is being requested. * * @param stream * The stream along which the blobs which should be written to the named * stream will be received. * * @param mimetype * The mimetype of the data that will be received along the given stream. * * @param name * The name of the stream being requested. * * @return * Zero if the put request was successfully handled, non-zero otherwise. */ typedef int guac_user_put_handler(guac_user* user, guac_object* object, guac_stream* stream, char* mimetype, char* name); #endif guacamole-server-1.3.0/src/libguac/guacamole/layer.h0000644000175100001440000000220113613156714017313 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_LAYER_H #define _GUAC_LAYER_H /** * Provides functions and structures required for allocating and using layers. * * @file layer.h */ #include "layer-types.h" /** * Represents a single layer within the Guacamole protocol. */ struct guac_layer { /** * The index of this layer. */ int index; }; #endif guacamole-server-1.3.0/src/libguac/guacamole/error-types.h0000644000175100001440000001013313613156714020475 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_ERROR_TYPES_H #define _GUAC_ERROR_TYPES_H /** * Type definitions related to return values and errors. * * @file error-types.h */ /** * Return codes shared by all Guacamole functions which can fail. */ typedef enum guac_status { /** * No errors occurred and the operation was successful. */ GUAC_STATUS_SUCCESS = 0, /** * Insufficient memory to complete the operation. */ GUAC_STATUS_NO_MEMORY, /** * The resource associated with the operation can no longer be used as it * has reached the end of its normal lifecycle. */ GUAC_STATUS_CLOSED, /** * Time ran out before the operation could complete. */ GUAC_STATUS_TIMEOUT, /** * An error occurred, and further information about the error is already * stored in errno. */ GUAC_STATUS_SEE_ERRNO, /** * An I/O error prevented the operation from succeeding. */ GUAC_STATUS_IO_ERROR, /** * The operation could not be performed because an invalid argument was * given. */ GUAC_STATUS_INVALID_ARGUMENT, /** * The operation failed due to a bug in the software or a serious system * problem. */ GUAC_STATUS_INTERNAL_ERROR, /** * Insufficient space remaining to complete the operation. */ GUAC_STATUS_NO_SPACE, /** * The operation failed because the input provided is too large. */ GUAC_STATUS_INPUT_TOO_LARGE, /** * The operation failed because the result could not be stored in the * space provided. */ GUAC_STATUS_RESULT_TOO_LARGE, /** * Permission was denied to perform the operation. */ GUAC_STATUS_PERMISSION_DENIED, /** * The operation could not be performed because associated resources are * busy. */ GUAC_STATUS_BUSY, /** * The operation could not be performed because, while the associated * resources do exist, they are not currently available for use. */ GUAC_STATUS_NOT_AVAILABLE, /** * The requested operation is not supported. */ GUAC_STATUS_NOT_SUPPORTED, /** * Support for the requested operation is not yet implemented. */ GUAC_STATUS_NOT_INPLEMENTED, /** * The operation is temporarily unable to be performed, but may succeed if * reattempted. */ GUAC_STATUS_TRY_AGAIN, /** * A violation of the Guacamole protocol occurred. */ GUAC_STATUS_PROTOCOL_ERROR, /** * The operation could not be performed because the requested resources do * not exist. */ GUAC_STATUS_NOT_FOUND, /** * The operation was canceled prior to completion. */ GUAC_STATUS_CANCELED, /** * The operation could not be performed because input values are outside * the allowed range. */ GUAC_STATUS_OUT_OF_RANGE, /** * The operation could not be performed because access to an underlying * resource is explicitly not allowed, though not necessarily due to * permissions. */ GUAC_STATUS_REFUSED, /** * The operation failed because too many resources are already in use. */ GUAC_STATUS_TOO_MANY, /** * The operation was not performed because it would otherwise block. */ GUAC_STATUS_WOULD_BLOCK } guac_status; #endif guacamole-server-1.3.0/src/libguac/guacamole/user.h0000644000175100001440000010155613770536337017201 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_USER_H #define _GUAC_USER_H /** * Defines the guac_user object, which represents a physical connection * within a larger, possibly shared, logical connection represented by a * guac_client. * * @file user.h */ #include "client-types.h" #include "layer-types.h" #include "pool-types.h" #include "socket-types.h" #include "stream-types.h" #include "timestamp-types.h" #include "user-constants.h" #include "user-fntypes.h" #include "user-types.h" #include #include #include struct guac_user_info { /** * The number of pixels the remote client requests for the display width. * This need not be honored by a client plugin implementation, but if the * underlying protocol of the client plugin supports dynamic sizing of the * screen, honoring the display size request is recommended. */ int optimal_width; /** * The number of pixels the remote client requests for the display height. * This need not be honored by a client plugin implementation, but if the * underlying protocol of the client plugin supports dynamic sizing of the * screen, honoring the display size request is recommended. */ int optimal_height; /** * NULL-terminated array of client-supported audio mimetypes. If the client * does not support audio at all, this will be NULL. */ const char** audio_mimetypes; /** * NULL-terminated array of client-supported video mimetypes. If the client * does not support video at all, this will be NULL. */ const char** video_mimetypes; /** * NULL-terminated array of client-supported image mimetypes. Though all * supported image mimetypes will be listed here, it can be safely assumed * that all clients will support at least "image/png" and "image/jpeg". */ const char** image_mimetypes; /** * The DPI of the physical remote display if configured for the optimal * width/height combination described here. This need not be honored by * a client plugin implementation, but if the underlying protocol of the * client plugin supports dynamic sizing of the screen, honoring the * stated resolution of the display size request is recommended. */ int optimal_resolution; /** * The timezone of the remote system. If the client does not provide * a specific timezone then this will be NULL. The format of the timezone * is the standard tzdata naming convention. */ const char* timezone; /** * The Guacamole protocol version that the remote system supports, allowing * for feature support to be negotiated between client and server. */ guac_protocol_version protocol_version; }; struct guac_user { /** * The guac_client to which this user belongs. */ guac_client* client; /** * This user's actual socket. Data written to this socket will * be received by this user alone, and data sent by this specific * user will be received by this socket. */ guac_socket* socket; /** * The unique identifier allocated for this user, which may be used within * the Guacamole protocol to refer to this user. This identifier is * guaranteed to be unique from all existing connections and users, and * will not collide with any available protocol names. */ char* user_id; /** * Non-zero if this user is the owner of the associated connection, zero * otherwise. The owner is the user which created the connection. */ int owner; /** * Non-zero if this user is active (connected), and zero otherwise. When * the user is created, this will be set to a non-zero value. If an event * occurs which requires that the user disconnect, or the user has * disconnected, this will be reset to zero. */ int active; /** * The previous user in the group of users within the same logical * connection. This is currently only used internally by guac_client to * track its set of connected users. To iterate connected users, use * guac_client_foreach_user(). */ guac_user* __prev; /** * The next user in the group of users within the same logical connection. * This is currently only used internally by guac_client to track its set * of connected users. To iterate connected users, use * guac_client_foreach_user(). */ guac_user* __next; /** * The time (in milliseconds) of receipt of the last sync message from * the user. */ guac_timestamp last_received_timestamp; /** * The duration of the last frame rendered by the user, in milliseconds. * This duration will include network and processing lag, and thus should * be slightly higher than the true frame duration. */ int last_frame_duration; /** * The overall lag experienced by the user relative to the stream of * frames, roughly excluding network lag. */ int processing_lag; /** * Information structure containing properties exposed by the remote * user during the initial handshake process. */ guac_user_info info; /** * Pool of stream indices. */ guac_pool* __stream_pool; /** * All available output streams (data going to connected user). */ guac_stream* __output_streams; /** * All available input streams (data coming from connected user). */ guac_stream* __input_streams; /** * Pool of object indices. */ guac_pool* __object_pool; /** * All available objects (arbitrary sets of named streams). */ guac_object* __objects; /** * Arbitrary user-specific data. */ void* data; /** * Handler for mouse events sent by the Gaucamole web-client. * * The handler takes the integer mouse X and Y coordinates, as well as * a button mask containing the bitwise OR of all button values currently * being pressed. Those values are: * * * * * * * * *
Button Value
Left 1
Middle 2
Right 4
Scrollwheel Up 8
Scrollwheel Down16
* Example: * @code * int mouse_handler(guac_user* user, int x, int y, int button_mask); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->mouse_handler = mouse_handler; * } * @endcode */ guac_user_mouse_handler* mouse_handler; /** * Handler for key events sent by the Guacamole web-client. * * The handler takes the integer X11 keysym associated with the key * being pressed/released, and an integer representing whether the key * is being pressed (1) or released (0). * * Example: * @code * int key_handler(guac_user* user, int keysym, int pressed); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->key_handler = key_handler; * } * @endcode */ guac_user_key_handler* key_handler; /** * Handler for clipboard events sent by the Guacamole web-client. This * handler will be called whenever the web-client sets the data of the * clipboard. * * The handler takes a guac_stream, which contains the stream index and * will persist through the duration of the transfer, and the mimetype * of the data being transferred. * * Example: * @code * int clipboard_handler(guac_user* user, guac_stream* stream, * char* mimetype); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->clipboard_handler = clipboard_handler; * } * @endcode */ guac_user_clipboard_handler* clipboard_handler; /** * Handler for size events sent by the Guacamole web-client. * * The handler takes an integer width and integer height, representing * the current visible screen area of the client. * * Example: * @code * int size_handler(guac_user* user, int width, int height); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->size_handler = size_handler; * } * @endcode */ guac_user_size_handler* size_handler; /** * Handler for file events sent by the Guacamole web-client. * * The handler takes a guac_stream which contains the stream index and * will persist through the duration of the transfer, the mimetype of * the file being transferred, and the filename. * * Example: * @code * int file_handler(guac_user* user, guac_stream* stream, * char* mimetype, char* filename); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->file_handler = file_handler; * } * @endcode */ guac_user_file_handler* file_handler; /** * Handler for pipe events sent by the Guacamole web-client. * * The handler takes a guac_stream which contains the stream index and * will persist through the duration of the transfer, the mimetype of * the data being transferred, and the pipe name. * * Example: * @code * int pipe_handler(guac_user* user, guac_stream* stream, * char* mimetype, char* name); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->pipe_handler = pipe_handler; * } * @endcode */ guac_user_pipe_handler* pipe_handler; /** * Handler for ack events sent by the Guacamole web-client. * * The handler takes a guac_stream which contains the stream index and * will persist through the duration of the transfer, a string containing * the error or status message, and a status code. * * Example: * @code * int ack_handler(guac_user* user, guac_stream* stream, * char* error, guac_protocol_status status); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->ack_handler = ack_handler; * } * @endcode */ guac_user_ack_handler* ack_handler; /** * Handler for blob events sent by the Guacamole web-client. * * The handler takes a guac_stream which contains the stream index and * will persist through the duration of the transfer, an arbitrary buffer * containing the blob, and the length of the blob. * * Example: * @code * int blob_handler(guac_user* user, guac_stream* stream, * void* data, int length); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->blob_handler = blob_handler; * } * @endcode */ guac_user_blob_handler* blob_handler; /** * Handler for stream end events sent by the Guacamole web-client. * * The handler takes only a guac_stream which contains the stream index. * This guac_stream will be disposed of immediately after this event is * finished. * * Example: * @code * int end_handler(guac_user* user, guac_stream* stream); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->end_handler = end_handler; * } * @endcode */ guac_user_end_handler* end_handler; /** * Handler for sync events sent by the Guacamole web-client. Sync events * are used to track per-user latency. * * The handler takes only a guac_timestamp which contains the timestamp * received from the user. Latency can be determined by comparing this * timestamp against the last_sent_timestamp of guac_client. * * Example: * @code * int sync_handler(guac_user* user, guac_timestamp timestamp); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->sync_handler = sync_handler; * } * @endcode */ guac_user_sync_handler* sync_handler; /** * Handler for leave events fired by the guac_client when a guac_user * is leaving an active connection. * * The handler takes only a guac_user which will be the guac_user that * left the connection. This guac_user will be disposed of immediately * after this event is finished. * * Example: * @code * int leave_handler(guac_user* user); * * int my_join_handler(guac_user* user, int argv, char** argv) { * user->leave_handler = leave_handler; * } * @endcode */ guac_user_leave_handler* leave_handler; /** * Handler for get events sent by the Guacamole web-client. * * The handler takes a guac_object, containing the object index which will * persist through the duration of the transfer, and the name of the stream * being requested. It is up to the get handler to create the required body * stream. * * Example: * @code * int get_handler(guac_user* user, guac_object* object, * char* name); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->get_handler = get_handler; * } * @endcode */ guac_user_get_handler* get_handler; /** * Handler for put events sent by the Guacamole web-client. * * The handler takes a guac_object and guac_stream, which each contain their * respective indices which will persist through the duration of the * transfer, the mimetype of the data being transferred, and the name of * the stream within the object being written to. * * Example: * @code * int put_handler(guac_user* user, guac_object* object, * guac_stream* stream, char* mimetype, char* name); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->put_handler = put_handler; * } * @endcode */ guac_user_put_handler* put_handler; /** * Handler for audio events sent by the Guacamole web-client. This handler * will be called whenever the web-client wishes to send a continuous * stream of audio data from some arbitrary source (a microphone, for * example). * * The handler takes a guac_stream, which contains the stream index and * will persist through the duration of the transfer, and the mimetype * of the data being transferred. * * Example: * @code * int audio_handler(guac_user* user, guac_stream* stream, * char* mimetype); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->audio_handler = audio_handler; * } * @endcode */ guac_user_audio_handler* audio_handler; /** * Handler for argv events (updates to the connection parameters of an * in-progress connection) sent by the Guacamole web-client. * * The handler takes a guac_stream which contains the stream index and * will persist through the duration of the transfer, the mimetype of * the data being transferred, and the argument (connection parameter) * name. * * Example: * @code * int argv_handler(guac_user* user, guac_stream* stream, * char* mimetype, char* name); * * int guac_user_init(guac_user* user, int argc, char** argv) { * user->argv_handler = argv_handler; * } * @endcode */ guac_user_argv_handler* argv_handler; }; /** * Allocates a new, blank user, not associated with any specific client or * socket. * * @return The newly allocated guac_user, or NULL if allocation failed. */ guac_user* guac_user_alloc(); /** * Frees the given user and all associated resources. * * @param user The guac_user to free. */ void guac_user_free(guac_user* user); /** * Handles all I/O for the portion of a user's Guacamole connection following * the initial "select" instruction, including the rest of the handshake. The * handshake-related properties of the given guac_user are automatically * populated, and guac_user_handle_instruction() is invoked for all * instructions received after the handshake has completed. This function * blocks until the connection/user is aborted or the user disconnects. * * @param user * The user whose handshake and entire Guacamole protocol exchange should * be handled. The user must already be associated with a guac_socket and * guac_client, and the guac_client must already be fully initialized. * * @param usec_timeout * The number of microseconds to wait for instructions from the given * user before closing the connection with an error. * * @return * Zero if the user's Guacamole connection was successfully handled and * the user has disconnected, or non-zero if an error prevented the user's * connection from being handled properly. */ int guac_user_handle_connection(guac_user* user, int usec_timeout); /** * Call the appropriate handler defined by the given user for the given * instruction. A comparison is made between the instruction opcode and the * initial handler lookup table defined in user-handlers.c. The initial handlers * will in turn call the user's handler (if defined). * * @param user * The user whose handlers should be called. * * @param opcode * The opcode of the instruction to pass to the user via the appropriate * handler. * * @param argc * The number of arguments which are part of the instruction. * * @param argv * An array of all arguments which are part of the instruction. * * @return * Non-negative if the instruction was handled successfully, or negative * if an error occurred. */ int guac_user_handle_instruction(guac_user* user, const char* opcode, int argc, char** argv); /** * Allocates a new stream. An arbitrary index is automatically assigned * if no previously-allocated stream is available for use. * * @param user * The user to allocate the stream for. * * @return * The next available stream, or a newly allocated stream, or NULL if the * maximum number of active streams has been reached. */ guac_stream* guac_user_alloc_stream(guac_user* user); /** * Returns the given stream to the pool of available streams, such that it * can be reused by any subsequent call to guac_user_alloc_stream(). * * @param user The user to return the stream to. * @param stream The stream to return to the pool of available stream. */ void guac_user_free_stream(guac_user* user, guac_stream* stream); /** * Signals the given user that it must disconnect, or advises cooperating * services that the given user is no longer connected. * * @param user The user to stop. */ void guac_user_stop(guac_user* user); /** * Signals the given user to stop gracefully, while also signalling via the * Guacamole protocol that an error has occurred. Note that this is a completely * cooperative signal, and can be ignored by the user or the hosting * daemon. The message given will be logged to the system logs. * * @param user The user to signal to stop. * @param status The status to send over the Guacamole protocol. * @param format A printf-style format string to log. * @param ... Arguments to use when filling the format string for printing. */ void guac_user_abort(guac_user* user, guac_protocol_status status, const char* format, ...); /** * Signals the given user to stop gracefully, while also signalling via the * Guacamole protocol that an error has occurred. Note that this is a completely * cooperative signal, and can be ignored by the user or the hosting * daemon. The message given will be logged to the system logs. * * @param user The user to signal to stop. * @param status The status to send over the Guacamole protocol. * @param format A printf-style format string to log. * @param ap The va_list containing the arguments to be used when filling the * format string for printing. */ void vguac_user_abort(guac_user* user, guac_protocol_status status, const char* format, va_list ap); /** * Writes a message in the log used by the given user. The logger used will * normally be defined by guacd (or whichever program loads the user) * by setting the logging handlers of the user when it is loaded. * * @param user The user logging this message. * @param level The level at which to log this message. * @param format A printf-style format string to log. * @param ... Arguments to use when filling the format string for printing. */ void guac_user_log(guac_user* user, guac_client_log_level level, const char* format, ...); /** * Writes a message in the log used by the given user. The logger used will * normally be defined by guacd (or whichever program loads the user) * by setting the logging handlers of the user when it is loaded. * * @param user The user logging this message. * @param level The level at which to log this message. * @param format A printf-style format string to log. * @param ap The va_list containing the arguments to be used when filling the * format string for printing. */ void vguac_user_log(guac_user* user, guac_client_log_level level, const char* format, va_list ap); /** * Allocates a new object. An arbitrary index is automatically assigned * if no previously-allocated object is available for use. * * @param user * The user to allocate the object for. * * @return * The next available object, or a newly allocated object. */ guac_object* guac_user_alloc_object(guac_user* user); /** * Returns the given object to the pool of available objects, such that it * can be reused by any subsequent call to guac_user_alloc_object(). * * @param user * The user to return the object to. * * @param object * The object to return to the pool of available object. */ void guac_user_free_object(guac_user* user, guac_object* object); /** * Streams the given connection parameter value over an argument value stream * ("argv" instruction), exposing the current value of the named connection * parameter to the given user. The argument value stream will be automatically * allocated and freed. * * @param user * The Guacamole user who should receive the connection parameter value. * * @param socket * The socket over which instructions associated with the argument value * stream should be sent. * * @param mimetype * The mimetype of the data within the connection parameter value being * sent. * * @param name * The name of the connection parameter being sent. * * @param value * The current value of the connection parameter being sent. */ void guac_user_stream_argv(guac_user* user, guac_socket* socket, const char* mimetype, const char* name, const char* value); /** * Streams the image data of the given surface over an image stream ("img" * instruction) as PNG-encoded data. The image stream will be automatically * allocated and freed. * * @param user * The Guacamole user for whom the image stream should be allocated. * * @param socket * The socket over which instructions associated with the image stream * should be sent. * * @param mode * The composite mode to use when rendering the image over the given layer. * * @param layer * The destination layer. * * @param x * The X coordinate of the upper-left corner of the destination rectangle * within the given layer. * * @param y * The Y coordinate of the upper-left corner of the destination rectangle * within the given layer. * * @param surface * A Cairo surface containing the image data to be streamed. */ void guac_user_stream_png(guac_user* user, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface); /** * Streams the image data of the given surface over an image stream ("img" * instruction) as JPEG-encoded data at the given quality. The image stream * will be automatically allocated and freed. * * @param user * The Guacamole user for whom the image stream should be allocated. * * @param socket * The socket over which instructions associated with the image stream * should be sent. * * @param mode * The composite mode to use when rendering the image over the given layer. * * @param layer * The destination layer. * * @param x * The X coordinate of the upper-left corner of the destination rectangle * within the given layer. * * @param y * The Y coordinate of the upper-left corner of the destination rectangle * within the given layer. * * @param surface * A Cairo surface containing the image data to be streamed. * * @param quality * The JPEG image quality, which must be an integer value between 0 and 100 * inclusive. Larger values indicate improving quality at the expense of * larger file size. */ void guac_user_stream_jpeg(guac_user* user, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface, int quality); /** * Streams the image data of the given surface over an image stream ("img" * instruction) as WebP-encoded data at the given quality. The image stream * will be automatically allocated and freed. If the server does not support * WebP, this function has no effect, so be sure to check the result of * guac_user_supports_webp() or guac_client_supports_webp() prior to calling * this function. * * @param user * The Guacamole user for whom the image stream should be allocated. * * @param socket * The socket over which instructions associated with the image stream * should be sent. * * @param mode * The composite mode to use when rendering the image over the given layer. * * @param layer * The destination layer. * * @param x * The X coordinate of the upper-left corner of the destination rectangle * within the given layer. * * @param y * The Y coordinate of the upper-left corner of the destination rectangle * within the given layer. * * @param surface * A Cairo surface containing the image data to be streamed. * * @param quality * The WebP image quality, which must be an integer value between 0 and 100 * inclusive. For lossy images, larger values indicate improving quality at * the expense of larger file size. For lossless images, this dictates the * quality of compression, with larger values producing smaller files at * the expense of speed. * * @param lossless * Zero to encode a lossy image, non-zero to encode losslessly. */ void guac_user_stream_webp(guac_user* user, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface, int quality, int lossless); /** * Returns whether the given user supports the "required" instruction. * * @param user * The Guacamole user to check for support of the "required" instruction. * * @return * Non-zero if the user supports the "required" instruction, otherwise zero. */ int guac_user_supports_required(guac_user* user); /** * Returns whether the given user supports WebP. If the user does not * support WebP, or the server cannot encode WebP images, zero is returned. * * @param user * The Guacamole user to check for WebP support. * * @return * Non-zero if the given user claims to support WebP and the server has * been built with WebP support, zero otherwise. */ int guac_user_supports_webp(guac_user* user); /** * Automatically handles a single argument received from a joining user, * returning a newly-allocated string containing that value. If the argument * provided by the user is blank, a newly-allocated string containing the * default value is returned. * * @param user * The user joining the connection and providing the given arguments. * * @param arg_names * A NULL-terminated array of argument names, corresponding to the provided * array of argument values. This array must be exactly the same size as * the argument value array, with one additional entry for the NULL * terminator. * * @param argv * An array of all argument values, corresponding to the provided array of * argument names. This array must be exactly the same size as the argument * name array, with the exception of the NULL terminator. * * @param index * The index of the entry in both the arg_names and argv arrays which * corresponds to the argument being parsed. * * @param default_value * The value to return if the provided argument is blank. If this value is * not NULL, the returned value will be a newly-allocated string containing * this value. * * @return * A newly-allocated string containing the provided argument value. If the * provided argument value is blank, this newly-allocated string will * contain the default value. If the default value is NULL and the provided * argument value is blank, no string will be allocated and NULL is * returned. */ char* guac_user_parse_args_string(guac_user* user, const char** arg_names, const char** argv, int index, const char* default_value); /** * Automatically handles a single integer argument received from a joining * user, returning the integer value of that argument. If the argument provided * by the user is blank or invalid, the default value is returned. * * @param user * The user joining the connection and providing the given arguments. * * @param arg_names * A NULL-terminated array of argument names, corresponding to the provided * array of argument values. This array must be exactly the same size as * the argument value array, with one additional entry for the NULL * terminator. * * @param argv * An array of all argument values, corresponding to the provided array of * argument names. This array must be exactly the same size as the argument * name array, with the exception of the NULL terminator. * * @param index * The index of the entry in both the arg_names and argv arrays which * corresponds to the argument being parsed. * * @param default_value * The value to return if the provided argument is blank or invalid. * * @return * The integer value parsed from the provided argument value, or the * default value if the provided argument value is blank or invalid. */ int guac_user_parse_args_int(guac_user* user, const char** arg_names, const char** argv, int index, int default_value); /** * Automatically handles a single boolean argument received from a joining * user, returning the value of that argument (either 1 for true or 0 for * false). Only "true" and "false" are legitimate values for a boolean * argument. If the argument provided by the user is blank or invalid, the * default value is returned. * * @param user * The user joining the connection and providing the given arguments. * * @param arg_names * A NULL-terminated array of argument names, corresponding to the provided * array of argument values. This array must be exactly the same size as * the argument value array, with one additional entry for the NULL * terminator. * * @param argv * An array of all argument values, corresponding to the provided array of * argument names. This array must be exactly the same size as the argument * name array, with the exception of the NULL terminator. * * @param index * The index of the entry in both the arg_names and argv arrays which * corresponds to the argument being parsed. * * @param default_value * The value to return if the provided argument is blank or invalid. * * @return * true (1) if the provided argument value is "true", false (0) if the * provided argument value is "false", or the default value if the provided * argument value is blank or invalid. */ int guac_user_parse_args_boolean(guac_user* user, const char** arg_names, const char** argv, int index, int default_value); #endif guacamole-server-1.3.0/src/libguac/guacamole/parser-constants.h0000644000175100001440000000244113702142276021510 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_PARSER_CONSTANTS_H #define _GUAC_PARSER_CONSTANTS_H /** * Constants related to the Guacamole protocol parser. * * @file parser-constants.h */ /** * The maximum number of characters per instruction. */ #define GUAC_INSTRUCTION_MAX_LENGTH 8192 /** * The maximum number of digits to allow per length prefix. */ #define GUAC_INSTRUCTION_MAX_DIGITS 5 /** * The maximum number of elements per instruction, including the opcode. */ #define GUAC_INSTRUCTION_MAX_ELEMENTS 128 #endif guacamole-server-1.3.0/src/libguac/guacamole/socket.h0000644000175100001440000003142113750103434017466 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_SOCKET_H #define _GUAC_SOCKET_H /** * Defines the guac_socket object and functionss for using and manipulating it. * * @file socket.h */ #include "client-types.h" #include "socket-constants.h" #include "socket-fntypes.h" #include "socket-types.h" #include "timestamp-types.h" #include #include #include struct guac_socket { /** * Arbitrary socket-specific data. */ void* data; /** * Handler which will be called when data needs to be read from the socket. */ guac_socket_read_handler* read_handler; /** * Handler which will be called whenever data is written to this socket. */ guac_socket_write_handler* write_handler; /** * Handler which will be called whenever this socket needs to be flushed. */ guac_socket_flush_handler* flush_handler; /** * Handler which will be called whenever a socket needs to be acquired for * exclusive access, such as when an instruction is about to be written. */ guac_socket_lock_handler* lock_handler; /** * Handler which will be called whenever exclusive access to a socket is * being released, such as when an instruction has finished being written. */ guac_socket_unlock_handler* unlock_handler; /** * Handler which will be called whenever guac_socket_select() is invoked * on this socket. */ guac_socket_select_handler* select_handler; /** * Handler which will be called when the socket is free'd (closed). */ guac_socket_free_handler* free_handler; /** * The current state of this guac_socket. */ guac_socket_state state; /** * The timestamp associated with the time the last block of data was * written to this guac_socket. */ guac_timestamp last_write_timestamp; /** * The number of bytes present in the base64 "ready" buffer. */ int __ready; /** * The base64 "ready" buffer. Once this buffer is filled, base64 data is * flushed to the main write buffer. */ int __ready_buf[3]; /** * Whether automatic keep-alive is enabled. */ int __keep_alive_enabled; /** * The keep-alive thread. */ pthread_t __keep_alive_thread; }; /** * Allocates a new, completely blank guac_socket. This guac_socket will do * absolutely nothing when used unless its handlers are defined. * * @returns A newly-allocated guac_socket, or NULL if the guac_socket could * not be allocated. */ guac_socket* guac_socket_alloc(); /** * Frees the given guac_socket and all associated resources. * * @param socket The guac_socket to free. */ void guac_socket_free(guac_socket* socket); /** * Declares that the given socket must automatically send a keep-alive ping * to ensure neither side of the socket times out while the socket is open. * This ping will take the form of a "nop" instruction. * * @param socket * The guac_socket to declare as requiring an automatic keep-alive ping. */ void guac_socket_require_keep_alive(guac_socket* socket); /** * Marks the beginning of a Guacamole protocol instruction. * * @param socket * The guac_socket beginning an instruction. */ void guac_socket_instruction_begin(guac_socket* socket); /** * Marks the end of a Guacamole protocol instruction. * * @param socket * The guac_socket ending an instruction. */ void guac_socket_instruction_end(guac_socket* socket); /** * Allocates and initializes a new guac_socket object with the given open * file descriptor. The file descriptor will be automatically closed when * the allocated guac_socket is freed. * * If an error occurs while allocating the guac_socket object, NULL is returned, * and guac_error is set appropriately. * * @param fd An open file descriptor that this guac_socket object should manage. * @return A newly allocated guac_socket object associated with the given * file descriptor, or NULL if an error occurs while allocating * the guac_socket object. */ guac_socket* guac_socket_open(int fd); /** * Allocates and initializes a new guac_socket which writes all data via * nest instructions to the given existing, open guac_socket. Freeing the * returned guac_socket has no effect on the underlying, nested guac_socket. * * If an error occurs while allocating the guac_socket object, NULL is returned, * and guac_error is set appropriately. * * @deprecated * The "nest" instruction and the corresponding guac_socket * implementation are no longer necessary, having been replaced by * the streaming instructions ("blob", "ack", "end"). Code using nested * sockets or the "nest" instruction should instead write to a normal * socket directly. * * @param parent The guac_socket this new guac_socket should write nest * instructions to. * @param index The stream index to use for the written nest instructions. * @return A newly allocated guac_socket object associated with the given * guac_socket and stream index, or NULL if an error occurs while * allocating the guac_socket object. */ guac_socket* guac_socket_nest(guac_socket* parent, int index); /** * Allocates and initializes a new guac_socket which delegates all socket * operations to the given primary socket, while simultaneously duplicating all * written data to the secondary socket. Freeing the returned guac_socket will * free both primary and secondary sockets. * * Return values (error codes) will come only from the primary socket. Locks * (like those used by guac_socket_instruction_begin() and * guac_socket_instruction_end()) will affect only the primary socket. * * If an error occurs while allocating the guac_socket object, NULL is returned, * and guac_error is set appropriately. * * @param primary * The primary guac_socket to which all socket operations should be * delegated. The error codes returned by socket operations, if any, will * always come from this socket. This socket will also be the only socket * locked when instructions begin (or unlocked when instructions end). * * @param secondary * The secondary guac_socket to which all data written to the primary * guac_socket should be copied. If an error prevents the write from * succeeding, that error will be ignored. Only errors from the primary * guac_socket will be acknowledged. * * @return * A newly allocated guac_socket object associated with the given primary * and secondary sockets, or NULL if an error occurs while allocating the * guac_socket object. */ guac_socket* guac_socket_tee(guac_socket* primary, guac_socket* secondary); /** * Allocates and initializes a new guac_socket which duplicates all * instructions written across the sockets of each connected user of the given * guac_client. The returned socket is a write-only socket. Attempts to read * from the socket will fail. If a write occurs while no users are connected, * that write will simply be dropped. * * Return values (error codes) from each user's socket will not affect the * in-progress write, but each failing user will be forcibly stopped with * guac_user_stop(). * * If an error occurs while allocating the guac_socket object, NULL is returned, * and guac_error is set appropriately. * * @param client * The client associated with the group of connected users across which * duplicates of all instructions should be written. * * @return * A write-only guac_socket object which broadcasts copies of all * instructions written across all connected users of the given * guac_client, or NULL if an error occurs while allocating the guac_socket * object. */ guac_socket* guac_socket_broadcast(guac_client* client); /** * Writes the given unsigned int to the given guac_socket object. The data * written may be buffered until the buffer is flushed automatically or * manually. * * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * * @param socket The guac_socket object to write to. * @param i The unsigned int to write. * @return Zero on success, or non-zero if an error occurs while writing. */ ssize_t guac_socket_write_int(guac_socket* socket, int64_t i); /** * Writes the given string to the given guac_socket object. The data * written may be buffered until the buffer is flushed automatically or * manually. * * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * * @param socket The guac_socket object to write to. * @param str The string to write. * @return Zero on success, or non-zero if an error occurs while writing. */ ssize_t guac_socket_write_string(guac_socket* socket, const char* str); /** * Writes the given binary data to the given guac_socket object as base64- * encoded data. The data written may be buffered until the buffer is flushed * automatically or manually. Beware that, because base64 data is buffered * on top of the write buffer already used, a call to guac_socket_flush_base64() * MUST be made before non-base64 writes (or writes of an independent block of * base64 data) can be made. * * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * * @param socket The guac_socket object to write to. * @param buf A buffer containing the data to write. * @param count The number of bytes to write. * @return Zero on success, or non-zero if an error occurs while writing. */ ssize_t guac_socket_write_base64(guac_socket* socket, const void* buf, size_t count); /** * Writes the given data to the specified socket. The data written may be * buffered until the buffer is flushed automatically or manually. * * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * * @param socket The guac_socket object to write to. * @param buf A buffer containing the data to write. * @param count The number of bytes to write. * @return Zero on success, or non-zero if an error occurs while writing. */ ssize_t guac_socket_write(guac_socket* socket, const void* buf, size_t count); /** * Attempts to read data from the socket, filling up to the specified number * of bytes in the given buffer. * * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * * @param socket The guac_socket to read from. * @param buf The buffer to read bytes into. * @param count The maximum number of bytes to read. * @return The number of bytes read, or non-zero if an error occurs while * reading. */ ssize_t guac_socket_read(guac_socket* socket, void* buf, size_t count); /** * Flushes the base64 buffer, writing padding characters as necessary. * * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * * @param socket The guac_socket object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ ssize_t guac_socket_flush_base64(guac_socket* socket); /** * Flushes the write buffer. * * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * * @param socket The guac_socket object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ ssize_t guac_socket_flush(guac_socket* socket); /** * Waits for input to be available on the given guac_socket object until the * specified timeout elapses. * * If an error occurs while waiting, a negative value is returned, and * guac_error is set appropriately. * * If a timeout occurs while waiting, zero value is returned, and * guac_error is set to GUAC_STATUS_INPUT_TIMEOUT. * * @param socket The guac_socket object to wait for. * @param usec_timeout The maximum number of microseconds to wait for data, or * -1 to potentially wait forever. * @return Positive on success, zero if the timeout elapsed and no data is * available, negative on error. */ int guac_socket_select(guac_socket* socket, int usec_timeout); #endif guacamole-server-1.3.0/src/libguac/guacamole/object.h0000644000175100001440000000525013613156714017454 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_OBJECT_H #define GUAC_OBJECT_H /** * Provides functions and structures required for allocating and using objects. * * @file object.h */ #include "object-types.h" #include "user-fntypes.h" struct guac_object { /** * The index of this object. */ int index; /** * Arbitrary data associated with this object. */ void* data; /** * Handler for get events sent by the Guacamole web-client. * * The handler takes a guac_object, containing the object index which will * persist through the duration of the transfer, and the name of the stream * being requested. It is up to the get handler to create the required body * stream. * * Example: * @code * int get_handler(guac_user* user, guac_object* object, * char* name); * * int some_function(guac_user* user) { * * guac_object* object = guac_user_alloc_object(user); * object->get_handler = get_handler; * * } * @endcode */ guac_user_get_handler* get_handler; /** * Handler for put events sent by the Guacamole web-client. * * The handler takes a guac_object and guac_stream, which each contain their * respective indices which will persist through the duration of the * transfer, the mimetype of the data being transferred, and the name of * the stream within the object being written to. * * Example: * @code * int put_handler(guac_user* user, guac_object* object, * guac_stream* stream, char* mimetype, char* name); * * int some_function(guac_user* user) { * * guac_object* object = guac_user_alloc_object(user); * object->put_handler = put_handler; * * } * @endcode */ guac_user_put_handler* put_handler; }; #endif guacamole-server-1.3.0/src/libguac/guacamole/timestamp.h0000644000175100001440000000275513613156714020220 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_TIMESTAMP_H #define _GUAC_TIMESTAMP_H /** * Provides functions and structures for creating timestamps. * * @file timestamp.h */ #include "timestamp-types.h" /** * Returns an arbitrary timestamp. The difference between return values of any * two calls is equal to the amount of time in milliseconds between those * calls. The return value from a single call will not have any useful * (or defined) meaning. * * @return * An arbitrary millisecond timestamp. */ guac_timestamp guac_timestamp_current(); /** * Sleeps for the given number of milliseconds. * * @param duration * The number of milliseconds to sleep. */ void guac_timestamp_msleep(int duration); #endif guacamole-server-1.3.0/src/libguac/guacamole/socket-constants.h0000644000175100001440000000234313613156714021510 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_SOCKET_CONSTANTS_H #define _GUAC_SOCKET_CONSTANTS_H /** * Constants related to the guac_socket object. * * @file socket-constants.h */ /** * The number of bytes to buffer within each socket before flushing. */ #define GUAC_SOCKET_OUTPUT_BUFFER_SIZE 8192 /** * The number of milliseconds to wait between keep-alive pings on a socket * with keep-alive enabled. */ #define GUAC_SOCKET_KEEP_ALIVE_INTERVAL 5000 #endif guacamole-server-1.3.0/src/libguac/guacamole/layer-types.h0000644000175100001440000000205113613156714020460 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_LAYER_TYPES_H #define _GUAC_LAYER_TYPES_H /** * Type definitions related to Guacamole layers. * * @file layer-types.h */ /** * Represents a single layer within the Guacamole protocol. */ typedef struct guac_layer guac_layer; #endif guacamole-server-1.3.0/src/libguac/guacamole/parser-types.h0000644000175100001440000000345413613156714020650 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_PARSER_TYPES_H #define _GUAC_PARSER_TYPES_H /** * Type definitions related to parsing the Guacamole protocol. * * @file parser-types.h */ /** * All possible states of the instruction parser. */ typedef enum guac_parse_state { /** * The parser is currently waiting for data to complete the length prefix * of the current element of the instruction. */ GUAC_PARSE_LENGTH, /** * The parser has finished reading the length prefix and is currently * waiting for data to complete the content of the instruction. */ GUAC_PARSE_CONTENT, /** * The instruction has been fully parsed. */ GUAC_PARSE_COMPLETE, /** * The instruction cannot be parsed because of a protocol error. */ GUAC_PARSE_ERROR } guac_parse_state; /** * A Guacamole protocol parser, which reads individual instructions, filling * its own internal structure with the most recently read instruction data. */ typedef struct guac_parser guac_parser; #endif guacamole-server-1.3.0/src/libguac/guacamole/user-types.h0000644000175100001440000000246213613156714020330 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_USER_TYPES_H #define _GUAC_USER_TYPES_H /** * Type definitions related to the guac_user object. * * @file user-types.h */ /** * Representation of a physical connection within a larger logical connection * which may be shared. Logical connections are represented by guac_client. */ typedef struct guac_user guac_user; /** * Information exposed by the remote client during the connection handshake * which can be used by a client plugin. */ typedef struct guac_user_info guac_user_info; #endif guacamole-server-1.3.0/src/libguac/guacamole/argv-constants.h0000644000175100001440000000450113770536337021164 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_ARGV_CONSTANTS_H #define GUAC_ARGV_CONSTANTS_H /** * Constants related to automatic handling of received "argv" instructions. * * @file argv-constants.h */ /** * Option flag which declares to guac_argv_register() that the associated * argument should be processed exactly once. If multiple "argv" streams are * received for the argument, only the first such stream is processed. * Additional streams will be rejected. */ #define GUAC_ARGV_OPTION_ONCE 1 /** * Option flag which declares to guac_argv_register() that the values received * and accepted for the associated argument should be echoed to all connected * users via outbound "argv" streams. */ #define GUAC_ARGV_OPTION_ECHO 2 /** * The maximum number of bytes to allow for any argument value received via an * argv stream and processed using guac_argv_received(), including null * terminator. */ #define GUAC_ARGV_MAX_LENGTH 16384 /** * The maximum number of bytes to allow within the name of any argument * registered with guac_argv_register(), including null terminator. */ #define GUAC_ARGV_MAX_NAME_LENGTH 256 /** * The maximum number of bytes to allow within the mimetype of any received * argument value passed to a callback registered with guac_argv_register(), * including null terminator. */ #define GUAC_ARGV_MAX_MIMETYPE_LENGTH 4096 /** * The maximum number of arguments that may be registered via guac_argv_await() * or guac_argv_await_async() before further argument registrations will fail. */ #define GUAC_ARGV_MAX_REGISTERED 128 #endif guacamole-server-1.3.0/src/libguac/guacamole/pool.h0000644000175100001440000000667113613156714017167 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_POOL_H #define _GUAC_POOL_H /** * Provides functions and structures for maintaining dynamically allocated and * freed pools of integers. * * @file pool.h */ #include "pool-types.h" #include struct guac_pool { /** * The minimum number of integers which must have been returned by * guac_pool_next_int before previously-used and freed integers are * allowed to be returned. */ int min_size; /** * The number of integers currently in use. */ int active; /** * The next integer to be released (after no more integers remain in the * pool. */ int __next_value; /** * The first integer in the pool, if any. */ guac_pool_int* __head; /** * The last integer in the pool, if any. */ guac_pool_int* __tail; /** * Lock which is acquired when the pool is being modified or accessed. */ pthread_mutex_t __lock; }; struct guac_pool_int { /** * The integer value of this pool entry. */ int value; /** * The next available (unused) guac_pool_int in the list of * allocated but free'd ints. */ guac_pool_int* __next; }; /** * Allocates a new guac_pool having the given minimum size. * * @param size The minimum number of integers which must have been returned by * guac_pool_next_int before freed integers (previously used * integers) are allowed to be returned. * @return A new, empty guac_pool, having the given minimum size. */ guac_pool* guac_pool_alloc(int size); /** * Frees the given guac_pool. * * @param pool The guac_pool to free. */ void guac_pool_free(guac_pool* pool); /** * Returns the next available integer from the given guac_pool. All integers * returned are non-negative, and are returned in sequences, starting from 0. * This operation is threadsafe. * * @param pool * The guac_pool to retrieve an integer from. * * @return * The next available integer, which may be either an integer not yet * returned by a call to guac_pool_next_int, or an integer which was * previously returned, but has since been freed. */ int guac_pool_next_int(guac_pool* pool); /** * Frees the given integer back into the given guac_pool. The integer given * will be available for future calls to guac_pool_next_int. This operation is * threadsafe. * * @param pool * The guac_pool to free the given integer into. * * @param value * The integer which should be returned to the given pool, such that it can * be received by a future call to guac_pool_next_int. */ void guac_pool_free_int(guac_pool* pool, int value); #endif guacamole-server-1.3.0/src/libguac/guacamole/protocol-types.h0000644000175100001440000002277713770536337021235 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_PROTOCOL_TYPES_H #define _GUAC_PROTOCOL_TYPES_H /** * Type definitions related to the Guacamole protocol. * * @file protocol-types.h */ /** * Set of all possible status codes returned by protocol operations. These * codes relate to Guacamole server/client communication, and not to internal * communication of errors within libguac and linked software. * * In general: * * 0x0000 - 0x00FF: Successful operations. * 0x0100 - 0x01FF: Operations that failed due to implementation status. * 0x0200 - 0x02FF: Operations that failed due to remote state/environment. * 0x0300 - 0x03FF: Operations that failed due to user/client action. * * There is a general correspondence of these status codes with HTTP response * codes. */ typedef enum guac_protocol_status { /** * The operation succeeded. */ GUAC_PROTOCOL_STATUS_SUCCESS = 0x0000, /** * The requested operation is unsupported. */ GUAC_PROTOCOL_STATUS_UNSUPPORTED = 0x0100, /** * The operation could not be performed due to an internal failure. */ GUAC_PROTOCOL_STATUS_SERVER_ERROR = 0x0200, /** * The operation could not be performed due as the server is busy. */ GUAC_PROTOCOL_STATUS_SERVER_BUSY = 0x0201, /** * The operation could not be performed because the upstream server * is not responding. */ GUAC_PROTOCOL_STATUS_UPSTREAM_TIMEOUT = 0x0202, /** * The operation was unsuccessful due to an error or otherwise * unexpected condition of the upstream server. */ GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR = 0x0203, /** * The operation could not be performed as the requested resource * does not exist. */ GUAC_PROTOCOL_STATUS_RESOURCE_NOT_FOUND = 0x0204, /** * The operation could not be performed as the requested resource is * already in use. */ GUAC_PROTOCOL_STATUS_RESOURCE_CONFLICT = 0x0205, /** * The operation could not be performed as the requested resource is now * closed. */ GUAC_PROTOCOL_STATUS_RESOURCE_CLOSED = 0x0206, /** * The operation could not be performed because the upstream server does * not appear to exist. */ GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND = 0x0207, /** * The operation could not be performed because the upstream server is not * available to service the request. */ GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE = 0x0208, /** * The session within the upstream server has ended because it conflicted * with another session. */ GUAC_PROTOCOL_STATUS_SESSION_CONFLICT = 0x0209, /** * The session within the upstream server has ended because it appeared to * be inactive. */ GUAC_PROTOCOL_STATUS_SESSION_TIMEOUT = 0x020A, /** * The session within the upstream server has been forcibly terminated. */ GUAC_PROTOCOL_STATUS_SESSION_CLOSED = 0x020B, /** * The operation could not be performed because bad parameters were * given. */ GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST = 0x300, /** * Permission was denied to perform the operation, as the user is not * yet authorized (not yet logged in, for example). */ GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED = 0x0301, /** * Permission was denied to perform the operation, and this permission * will not be granted even if the user is authorized. */ GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN = 0x0303, /** * The client took too long to respond. */ GUAC_PROTOCOL_STATUS_CLIENT_TIMEOUT = 0x308, /** * The client sent too much data. */ GUAC_PROTOCOL_STATUS_CLIENT_OVERRUN = 0x30D, /** * The client sent data of an unsupported or unexpected type. */ GUAC_PROTOCOL_STATUS_CLIENT_BAD_TYPE = 0x30F, /** * The operation failed because the current client is already * using too many resources. */ GUAC_PROTOCOL_STATUS_CLIENT_TOO_MANY = 0x31D } guac_protocol_status; /** * Composite modes used by Guacamole draw instructions. Each * composite mode maps to a unique channel mask integer. */ typedef enum guac_composite_mode { /* * A: Source where destination transparent = S n D' * B: Source where destination opaque = S n D * C: Destination where source transparent = D n S' * D: Destination where source opaque = D n S * * 0 = Active, 1 = Inactive */ /* ABCD */ GUAC_COMP_ROUT = 0x2, /* 0010 - Clears destination where source opaque */ GUAC_COMP_ATOP = 0x6, /* 0110 - Fill where destination opaque only */ GUAC_COMP_XOR = 0xA, /* 1010 - XOR */ GUAC_COMP_ROVER = 0xB, /* 1011 - Fill where destination transparent only */ GUAC_COMP_OVER = 0xE, /* 1110 - Draw normally */ GUAC_COMP_PLUS = 0xF, /* 1111 - Add */ /* Unimplemented in client: */ /* NOT IMPLEMENTED: 0000 - Clear */ /* NOT IMPLEMENTED: 0011 - No operation */ /* NOT IMPLEMENTED: 0101 - Additive IN */ /* NOT IMPLEMENTED: 0111 - Additive ATOP */ /* NOT IMPLEMENTED: 1101 - Additive RATOP */ /* Buggy in webkit browsers, as they keep channel C on in all cases: */ GUAC_COMP_RIN = 0x1, /* 0001 */ GUAC_COMP_IN = 0x4, /* 0100 */ GUAC_COMP_OUT = 0x8, /* 1000 */ GUAC_COMP_RATOP = 0x9, /* 1001 */ GUAC_COMP_SRC = 0xC /* 1100 */ /* Bitwise composite operations (binary) */ /* * A: S' & D' * B: S' & D * C: S & D' * D: S & D * * 0 = Active, 1 = Inactive */ } guac_composite_mode; /** * Default transfer functions. There is no current facility in the * Guacamole protocol to define custom transfer functions. */ typedef enum guac_transfer_function { /* Constant functions */ /* ABCD */ GUAC_TRANSFER_BINARY_BLACK = 0x0, /* 0000 */ GUAC_TRANSFER_BINARY_WHITE = 0xF, /* 1111 */ /* Copy functions */ GUAC_TRANSFER_BINARY_SRC = 0x3, /* 0011 */ GUAC_TRANSFER_BINARY_DEST = 0x5, /* 0101 */ GUAC_TRANSFER_BINARY_NSRC = 0xC, /* 1100 */ GUAC_TRANSFER_BINARY_NDEST = 0xA, /* 1010 */ /* AND / NAND */ GUAC_TRANSFER_BINARY_AND = 0x1, /* 0001 */ GUAC_TRANSFER_BINARY_NAND = 0xE, /* 1110 */ /* OR / NOR */ GUAC_TRANSFER_BINARY_OR = 0x7, /* 0111 */ GUAC_TRANSFER_BINARY_NOR = 0x8, /* 1000 */ /* XOR / XNOR */ GUAC_TRANSFER_BINARY_XOR = 0x6, /* 0110 */ GUAC_TRANSFER_BINARY_XNOR = 0x9, /* 1001 */ /* AND / NAND with inverted source */ GUAC_TRANSFER_BINARY_NSRC_AND = 0x4, /* 0100 */ GUAC_TRANSFER_BINARY_NSRC_NAND = 0xB, /* 1011 */ /* OR / NOR with inverted source */ GUAC_TRANSFER_BINARY_NSRC_OR = 0xD, /* 1101 */ GUAC_TRANSFER_BINARY_NSRC_NOR = 0x2, /* 0010 */ /* AND / NAND with inverted destination */ GUAC_TRANSFER_BINARY_NDEST_AND = 0x2, /* 0010 */ GUAC_TRANSFER_BINARY_NDEST_NAND = 0xD, /* 1101 */ /* OR / NOR with inverted destination */ GUAC_TRANSFER_BINARY_NDEST_OR = 0xB, /* 1011 */ GUAC_TRANSFER_BINARY_NDEST_NOR = 0x4 /* 0100 */ } guac_transfer_function; /** * Supported line cap styles */ typedef enum guac_line_cap_style { GUAC_LINE_CAP_BUTT = 0x0, GUAC_LINE_CAP_ROUND = 0x1, GUAC_LINE_CAP_SQUARE = 0x2 } guac_line_cap_style; /** * Supported line join styles */ typedef enum guac_line_join_style { GUAC_LINE_JOIN_BEVEL = 0x0, GUAC_LINE_JOIN_MITER = 0x1, GUAC_LINE_JOIN_ROUND = 0x2 } guac_line_join_style; /** * The set of protocol versions known to guacd to handle negotiation or feature * support between differing versions of Guacamole clients and guacd. */ typedef enum guac_protocol_version { /** * An unknown version of the Guacamole protocol. */ GUAC_PROTOCOL_VERSION_UNKNOWN = 0x000000, /** * Original protocol version 1.0.0, which lacks support for negotiating * parameters and protocol version, and requires that parameters in the * client/server handshake be delivered in order. */ GUAC_PROTOCOL_VERSION_1_0_0 = 0x010000, /** * Protocol version 1.1.0, which includes support for parameter and version * negotiation and for sending timezone information from the client * to the server. */ GUAC_PROTOCOL_VERSION_1_1_0 = 0x010100, /** * Protocol version 1.3.0, which supports the "required" instruction, * allowing connections in guacd to request information from the client and * await a response. */ GUAC_PROTOCOL_VERSION_1_3_0 = 0x010300 } guac_protocol_version; #endif guacamole-server-1.3.0/src/libguac/guacamole/argv.h0000644000175100001440000001100113770536337017143 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_ARGV_H #define GUAC_ARGV_H /** * Convenience functions for processing parameter values that are submitted * dynamically using "argv" instructions. * * @file argv.h */ #include "argv-constants.h" #include "argv-fntypes.h" #include "stream-types.h" #include "user-fntypes.h" /** * Registers the given callback such that it is automatically invoked when an * "argv" stream for an argument having the given name is processed using * guac_argv_received(). The maximum number of arguments that may be registered * in this way is limited by GUAC_ARGV_MAX_REGISTERED. The maximum length of * any provided argument name is limited by GUAC_ARGV_MAX_NAME_LENGTH. * * @see GUAC_ARGV_MAX_NAME_LENGTH * @see GUAC_ARGV_MAX_REGISTERED * * @see GUAC_ARGV_OPTION_ONCE * @see GUAC_ARGV_OPTION_ECHO * * @param name * The name of the argument that should be handled by the given callback. * * @param callback * The callback to invoke when the value of an argument having the given * name has finished being received. * * @param data * Arbitrary data to be passed to the given callback when a value is * received for the given argument. * * @param options * Bitwise OR of all option flags that should affect processing of this * argument. * * @return * Zero if the callback was successfully registered, non-zero if the * maximum number of registered callbacks has already been reached. */ int guac_argv_register(const char* name, guac_argv_callback* callback, void* data, int options); /** * Waits for receipt of each of the given arguments via guac_argv_received(). * This function will block until either ALL of the given arguments have been * received via guac_argv_received() or until automatic processing of received * arguments is stopped with guac_argv_stop(). * * @param args * A NULL-terminated array of the names of all arguments that this function * should wait for. * * @return * Zero if all of the specified arguments were received, non-zero if * guac_argv_stop() was called before all arguments were received. */ int guac_argv_await(const char** args); /** * Hands off management of the given guac_stream, automatically processing data * received over that stream as the value of the argument having the given * name. The argument must have already been registered with * guac_argv_register(). The blob_handler and end_handler of the given stream, * if already set, will be overridden without regard to their current value. * * It is the responsibility of the caller to properly send any required "ack" * instructions to accept or reject the received stream. * * @param stream * The guac_stream that will receive the value of the argument having the * given name. * * @param mimetype * The mimetype of the data that will be received over the stream. * * @param name * The name of the argument being received. * * @return * Zero if handling of the guac_stream has been successfully handed off, * non-zero if the provided argument has not yet been registered with * guac_argv_register(). */ int guac_argv_received(guac_stream* stream, const char* mimetype, const char* name); /** * Stops further automatic processing of received "argv" streams. Any call to * guac_argv_await() that is currently blocking will return, and any future * calls to guac_argv_await() will return immediately without blocking. */ void guac_argv_stop(); /** * Convenience implementation of the "argv" instruction handler which * automatically sends any required "ack" instructions and invokes * guac_argv_received(). Only arguments that are registered with * guac_argv_register() will be processed. */ guac_user_argv_handler guac_argv_handler; #endif guacamole-server-1.3.0/src/libguac/guacamole/string.h0000644000175100001440000001662713770536337017535 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_STRING_H #define GUAC_STRING_H /** * Provides convenience functions for manipulating strings. * * @file string.h */ #include #include /** * Copies a limited number of bytes from the given source string to the given * destination buffer. The resulting buffer will always be null-terminated, * even if doing so means that the intended string is truncated, unless the * destination buffer has no space available at all. As this function always * returns the length of the string it tried to create (the length of the * source string), whether truncation has occurred can be detected by comparing * the return value against the size of the destination buffer. If the value * returned is greater than or equal to the size of the destination buffer, then * the string has been truncated. * * The source and destination buffers MAY NOT overlap. * * @param dest * The buffer which should receive the contents of the source string. This * buffer will always be null terminated unless zero bytes are available * within the buffer. * * @param src * The source string to copy into the destination buffer. This string MUST * be null terminated. * * @param n * The number of bytes available within the destination buffer. If this * value is zero, no bytes will be written to the destination buffer, and * the destination buffer may not be null terminated. In all other cases, * the destination buffer will always be null terminated, even if doing * so means that the copied data from the source string will be truncated. * * @return * The length of the copied string (the source string) in bytes, excluding * the null terminator. */ size_t guac_strlcpy(char* restrict dest, const char* restrict src, size_t n); /** * Appends the given source string after the end of the given destination * string, writing at most the given number of bytes. Both the source and * destination strings MUST be null-terminated. The resulting buffer will * always be null-terminated, even if doing so means that the intended string * is truncated, unless the destination buffer has no space available at all. * As this function always returns the length of the string it tried to create * (the length of destination and source strings added together), whether * truncation has occurred can be detected by comparing the return value * against the size of the destination buffer. If the value returned is greater * than or equal to the size of the destination buffer, then the string has * been truncated. * * The source and destination buffers MAY NOT overlap. * * @param dest * The buffer which should be appended with the contents of the source * string. This buffer MUST already be null-terminated and will always be * null-terminated unless zero bytes are available within the buffer. * * As a safeguard against incorrectly-written code, in the event that the * destination buffer is not null-terminated, this function will still stop * before overrunning the buffer, instead behaving as if the length of the * string in the buffer is exactly the size of the buffer. The destination * buffer will remain untouched (and unterminated) in this case. * * @param src * The source string to append to the the destination buffer. This string * MUST be null-terminated. * * @param n * The number of bytes available within the destination buffer. If this * value is not greater than zero, no bytes will be written to the * destination buffer, and the destination buffer may not be * null-terminated. In all other cases, the destination buffer will always * be null-terminated, even if doing so means that the copied data from the * source string will be truncated. * * @return * The length of the string this function tried to create (the lengths of * the source and destination strings added together) in bytes, excluding * the null terminator. */ size_t guac_strlcat(char* restrict dest, const char* restrict src, size_t n); /** * Simple wrapper for strdup() which behaves identically to standard strdup(), * except that NULL will be returned if the provided string is NULL. * * @param str * The string to duplicate as a newly-allocated string. * * @return * A newly-allocated string containing identically the same content as the * given string, or NULL if the given string was NULL. */ char* guac_strdup(const char* str); /** * Concatenates each of the given strings, separated by the given delimiter, * storing the result within a destination buffer. The number of bytes written * will be no more than the given number of bytes, and the destination buffer * is guaranteed to be null-terminated, even if doing so means that one or more * of the intended strings are truncated or omitted from the end of the result, * unless the destination buffer has no space available at all. As this * function always returns the length of the string it tried to create (the * length of all source strings and all delimiters added together), whether * truncation has occurred can be detected by comparing the return value * against the size of the destination buffer. If the value returned is greater * than or equal to the size of the destination buffer, then the string has * been truncated. * * The source strings, delimiter string, and destination buffer MAY NOT * overlap. * * @param dest * The buffer which should receive the result of joining the given strings. * This buffer will always be null terminated unless zero bytes are * available within the buffer. * * @param elements * The elements to concatenate together, separated by the given delimiter. * Each element MUST be null-terminated. * * @param nmemb * The number of elements within the elements array. * * @param delim * The delimiter to include between each pair of elements. * * @param n * The number of bytes available within the destination buffer. If this * value is not greater than zero, no bytes will be written to the * destination buffer, and the destination buffer may not be null * terminated. In all other cases, the destination buffer will always be * null terminated, even if doing so means that the result will be * truncated. * * @return * The length of the string this function tried to create (the length of * all source strings and all delimiters added together) in bytes, * excluding the null terminator. */ size_t guac_strljoin(char* restrict dest, const char* restrict const* elements, int nmemb, const char* restrict delim, size_t n); #endif guacamole-server-1.3.0/src/libguac/guacamole/client-constants.h0000644000175100001440000000540513613156714021500 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_CLIENT_CONSTANTS_H #define _GUAC_CLIENT_CONSTANTS_H /** * Constants related to the Guacamole client structure, guac_client. * * @file client-constants.h */ /** * The maximum number of inbound or outbound streams supported by any one * guac_client. */ #define GUAC_CLIENT_MAX_STREAMS 64 /** * The index of a closed stream. */ #define GUAC_CLIENT_CLOSED_STREAM_INDEX -1 /** * The character prefix which identifies a client ID. */ #define GUAC_CLIENT_ID_PREFIX '$' /** * The flag set in the mouse button mask when the left mouse button is down. */ #define GUAC_CLIENT_MOUSE_LEFT 0x01 /** * The flag set in the mouse button mask when the middle mouse button is down. */ #define GUAC_CLIENT_MOUSE_MIDDLE 0x02 /** * The flag set in the mouse button mask when the right mouse button is down. */ #define GUAC_CLIENT_MOUSE_RIGHT 0x04 /** * The flag set in the mouse button mask when the mouse scrollwheel is scrolled * up. Note that mouse scrollwheels are actually sets of two buttons. One * button is pressed and released for an upward scroll, and the other is * pressed and released for a downward scroll. Some mice may actually implement * these as separate buttons, not a wheel. */ #define GUAC_CLIENT_MOUSE_SCROLL_UP 0x08 /** * The flag set in the mouse button mask when the mouse scrollwheel is scrolled * down. Note that mouse scrollwheels are actually sets of two buttons. One * button is pressed and released for an upward scroll, and the other is * pressed and released for a downward scroll. Some mice may actually implement * these as separate buttons, not a wheel. */ #define GUAC_CLIENT_MOUSE_SCROLL_DOWN 0x10 /** * The minimum number of buffers to create before allowing free'd buffers to * be reclaimed. In the case a protocol rapidly creates, uses, and destroys * buffers, this can prevent unnecessary reuse of the same buffer (which * would make draw operations unnecessarily synchronous). */ #define GUAC_BUFFER_POOL_INITIAL_SIZE 1024 #endif guacamole-server-1.3.0/src/libguac/guacamole/audio.h0000644000175100001440000001610313764613616017314 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_AUDIO_H #define __GUAC_AUDIO_H /** * Provides functions and structures used for providing simple streaming audio. * * @file audio.h */ #include "audio-fntypes.h" #include "audio-types.h" #include "client-types.h" #include "stream-types.h" struct guac_audio_encoder { /** * The mimetype of the audio data encoded by this audio * encoder. */ const char* mimetype; /** * Handler which will be called when the audio stream is first created. */ guac_audio_encoder_begin_handler* begin_handler; /** * Handler which will be called when PCM data is written to the audio * stream for encoding. */ guac_audio_encoder_write_handler* write_handler; /** * Handler which will be called when the audio stream is flushed. */ guac_audio_encoder_flush_handler* flush_handler; /** * Handler which will be called when the audio stream is closed. */ guac_audio_encoder_end_handler* end_handler; /** * Handler which will be called when a new user joins the Guacamole * connection associated with an audio stream. */ guac_audio_encoder_join_handler* join_handler; }; struct guac_audio_stream { /** * Arbitrary codec encoder which will receive raw PCM data. */ guac_audio_encoder* encoder; /** * The client associated with this audio stream. */ guac_client* client; /** * The actual stream associated with this audio stream. */ guac_stream* stream; /** * The number of samples per second of PCM data sent to this stream. */ int rate; /** * The number of audio channels per sample of PCM data. Legal values are * 1 or 2. */ int channels; /** * The number of bits per sample per channel for PCM data. Legal values are * 8 or 16. */ int bps; /** * Encoder-specific state data. */ void* data; }; /** * Allocates a new audio stream at the client level which encodes audio data * using the given encoder. If NULL is specified for the encoder, an * appropriate encoder will be selected based on the encoders built into * libguac and the level of support declared by users associated with the * given guac_client. The PCM format specified here (via rate, channels, and * bps) must be the format used for all PCM data provided to the audio stream. * The format may only be changed using guac_audio_stream_reset(). * * If a new user joins the connection after the audio stream is created, that * user will not be aware of the existence of the audio stream, and * guac_audio_stream_add_user() will need to be invoked to recreate the stream * for the new user. * * @param client * The guac_client for which this audio stream is being allocated. The * connection owner is given priority when determining the level of audio * support. It is currently assumed that all other joining users on the * connection will have the same level of audio support. * * @param encoder * The guac_audio_encoder to use when encoding audio, or NULL if libguac * should select an appropriate built-in encoder on its own. * * @param rate * The number of samples per second of PCM data sent to this stream. * * @param channels * The number of audio channels per sample of PCM data. Legal values are * 1 or 2. * * @param bps * The number of bits per sample per channel for PCM data. Legal values are * 8 or 16. * * @return * The newly allocated guac_audio_stream, or NULL if no audio stream could * be allocated due to lack of support on the part of the connecting * Guacamole client or due to reaching the maximum number of active * streams. */ guac_audio_stream* guac_audio_stream_alloc(guac_client* client, guac_audio_encoder* encoder, int rate, int channels, int bps); /** * Resets the given audio stream, switching to the given encoder, rate, * channels, and bits per sample. If NULL is specified for the encoder, the * encoder is left unchanged. If the encoder, rate, channels, and bits per * sample are all identical to the current settings, this function has no * effect. * * @param audio * The guac_audio_stream to reset. * * @param encoder * The guac_audio_encoder to use when encoding audio, or NULL to leave this * unchanged. * * @param rate * The number of samples per second of PCM data sent to this stream. * * @param channels * The number of audio channels per sample of PCM data. Legal values are * 1 or 2. * * @param bps * The number of bits per sample per channel for PCM data. Legal values are * 8 or 16. */ void guac_audio_stream_reset(guac_audio_stream* audio, guac_audio_encoder* encoder, int rate, int channels, int bps); /** * Notifies the given audio stream that a user has joined the connection. The * audio stream itself may need to be restarted. and the audio stream will need * to be created for the new user to ensure they can properly handle future * data received along the stream. * * @param audio * The guac_audio_stream associated with the Guacamole connection being * joined. * * @param user * The user that has joined the Guacamole connection. */ void guac_audio_stream_add_user(guac_audio_stream* audio, guac_user* user); /** * Closes and frees the given audio stream. * * @param stream * The guac_audio_stream to free. */ void guac_audio_stream_free(guac_audio_stream* stream); /** * Writes PCM data to the given audio stream. This PCM data will be * automatically encoded by the audio encoder associated with this stream. The * PCM data must be 2-channel, 44100 Hz, with signed 16-bit samples. * * @param stream * The guac_audio_stream to write PCM data through. * * @param data * The PCM data to write. * * @param length * The number of bytes of PCM data provided. */ void guac_audio_stream_write_pcm(guac_audio_stream* stream, const unsigned char* data, int length); /** * Flushes the underlying audio buffer, if any, ensuring that all audio * previously written via guac_audio_stream_write_pcm() has been encoded and * sent to the client. * * @param stream * The guac_audio_stream whose audio buffers should be flushed. */ void guac_audio_stream_flush(guac_audio_stream* stream); #endif guacamole-server-1.3.0/src/libguac/guacamole/audio-types.h0000644000175100001440000000244313613156714020452 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_AUDIO_TYPES_H #define __GUAC_AUDIO_TYPES_H /** * Type definitions related to simple streaming audio. * * @file audio-types.h */ /** * Basic audio stream. PCM data is added to the stream. When the stream is * flushed, a write handler receives PCM data packets and, presumably, streams * them to the guac_stream provided. */ typedef struct guac_audio_stream guac_audio_stream; /** * Arbitrary audio codec encoder. */ typedef struct guac_audio_encoder guac_audio_encoder; #endif guacamole-server-1.3.0/src/libguac/guacamole/socket-fntypes.h0000644000175100001440000001032513613156714021163 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_SOCKET_FNTYPES_H #define _GUAC_SOCKET_FNTYPES_H /** * Function type definitions related to the guac_socket object. * * @file socket-fntypes.h */ #include "socket-types.h" #include /** * Generic read handler for socket read operations, modeled after the standard * POSIX read() function. When set within a guac_socket, a handler of this type * will be called when data needs to be read into the socket. * * @param socket The guac_socket being read from. * @param buf The arbitrary buffer we must populate with data. * @param count The maximum number of bytes to read into the buffer. * @return The number of bytes read, or -1 if an error occurs. */ typedef ssize_t guac_socket_read_handler(guac_socket* socket, void* buf, size_t count); /** * Generic write handler for socket write operations, modeled after the standard * POSIX write() function. When set within a guac_socket, a handler of this type * will be called when data needs to be written to the socket. * * @param socket The guac_socket being written to. * @param buf The arbitrary buffer containing data to be written. * @param count The maximum number of bytes to written to the buffer. * @return The number of bytes written, or -1 if an error occurs. */ typedef ssize_t guac_socket_write_handler(guac_socket* socket, const void* buf, size_t count); /** * Generic handler for socket select operations, similar to the POSIX select() * function. When guac_socket_select() is called on a guac_socket, its * guac_socket_select_handler will be invoked, if defined. * * @param socket The guac_socket being selected. * @param usec_timeout The maximum number of microseconds to wait for data, or * -1 to potentially wait forever. * @return Positive on success, zero if the timeout elapsed and no data is * available, negative on error. */ typedef int guac_socket_select_handler(guac_socket* socket, int usec_timeout); /** * Generic flush handler for socket flush operations. This function is not * modeled after any POSIX function. When set within a guac_socket, a handler * of this type will be called when guac_socket_flush() is called. * * @param socket * The guac_socket being flushed. * * @return * Zero on success, or non-zero if an error occurs during flush. */ typedef ssize_t guac_socket_flush_handler(guac_socket* socket); /** * When set within a guac_socket, a handler of this type will be called * whenever exclusive access to the guac_socket is required, such as when * guac_socket_instruction_begin() is called. * * @param socket * The guac_socket to which exclusive access is required. */ typedef void guac_socket_lock_handler(guac_socket* socket); /** * When set within a guac_socket, a handler of this type will be called * whenever exclusive access to the guac_socket is no longer required, such as * when guac_socket_instruction_end() is called. * * @param socket * The guac_socket to which exclusive access is no longer required. */ typedef void guac_socket_unlock_handler(guac_socket* socket); /** * Generic handler for the closing of a socket, modeled after the standard * POSIX close() function. When set within a guac_socket, a handler of this type * will be called when the socket is closed. * * @param socket The guac_socket being closed. * @return Zero on success, or -1 if an error occurs. */ typedef int guac_socket_free_handler(guac_socket* socket); #endif guacamole-server-1.3.0/src/libguac/guacamole/parser.h0000644000175100001440000001434713613156714017511 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_PARSER_H #define _GUAC_PARSER_H /** * Provides functions and structures for parsing the Guacamole protocol. * * @file parser.h */ #include "parser-types.h" #include "parser-constants.h" #include "socket-types.h" struct guac_parser { /** * The opcode of the instruction. */ char* opcode; /** * The number of arguments passed to this instruction. */ int argc; /** * Array of all arguments passed to this instruction. */ char** argv; /** * The parse state of the instruction. */ guac_parse_state state; /** * The length of the current element, if known. */ int __element_length; /** * The number of elements currently parsed. */ int __elementc; /** * All currently parsed elements. */ char* __elementv[GUAC_INSTRUCTION_MAX_ELEMENTS]; /** * Pointer to the first character of the current in-progress instruction * within the buffer. */ char* __instructionbuf_unparsed_start; /** * Pointer to the first unused section of the instruction buffer. */ char* __instructionbuf_unparsed_end; /** * The instruction buffer. This is essentially the input buffer, * provided as a convenience to be used to buffer instructions until * those instructions are complete and ready to be parsed. */ char __instructionbuf[32768]; }; /** * Allocates a new parser. * * @return The newly allocated parser, or NULL if an error occurs during * allocation, in which case guac_error will be set appropriately. */ guac_parser* guac_parser_alloc(); /** * Appends data from the given buffer to the given parser. The data will be * appended, if possible, to the in-progress instruction as a reference and * thus the buffer must remain valid throughout the life of the current * instruction. This function may modify the contents of the buffer when those * contents are part of an element within the instruction being read. * * @param parser The parser to append data to. * @param buffer A buffer containing data that should be appended to this * parser. * @param length The number of bytes available for appending within the buffer. * @return The number of bytes appended to this parser, which may be * zero if more data is needed. */ int guac_parser_append(guac_parser* parser, void* buffer, int length); /** * Returns the number of unparsed bytes stored in the given parser's internal * buffers. * * @param parser The parser to return the length of. * @return The number of unparsed bytes stored in the given parser. */ int guac_parser_length(guac_parser* parser); /** * Removes up to length bytes from internal buffer of unparsed bytes, storing * them in the given buffer. * * @param parser The parser to remove unparsed bytes from. * @param buffer The buffer to store the unparsed bytes within. * @param length The length of the given buffer. * @return The number of bytes stored in the given buffer. */ int guac_parser_shift(guac_parser* parser, void* buffer, int length); /** * Frees all memory allocated to the given parser. * * @param parser The parser to free. */ void guac_parser_free(guac_parser* parser); /** * Reads a single instruction from the given guac_socket connection. This * may result in additional data being read from the guac_socket, stored * internally within a buffer for future parsing. Future calls to * guac_parser_read() will read from the interal buffer before reading * from the guac_socket. Data from the internal buffer can be removed * and used elsewhere through guac_parser_shift(). * * If an error occurs reading the instruction, non-zero is returned, * and guac_error is set appropriately. * * @param parser The guac_parser to read instruction data from. * @param socket The guac_socket connection to use. * @param usec_timeout The maximum number of microseconds to wait before * giving up. * @return Zero if an instruction was read within the time allowed, or * non-zero if no instruction could be read. If the instruction * could not be read completely because the timeout elapsed, in * which case guac_error will be set to GUAC_STATUS_INPUT_TIMEOUT * and additional calls to guac_parser_read() will be required. */ int guac_parser_read(guac_parser* parser, guac_socket* socket, int usec_timeout); /** * Reads a single instruction from the given guac_socket. This operates * identically to guac_parser_read(), except that an error is returned if * the expected opcode is not received. * * If an error occurs reading the instruction, NULL is returned, * and guac_error is set appropriately. * * If the instruction read is not the expected instruction, NULL is returned, * and guac_error is set to GUAC_STATUS_BAD_STATE. * * @param parser The guac_parser to read instruction data from. * @param socket The guac_socket connection to use. * @param usec_timeout The maximum number of microseconds to wait before * giving up. * @param opcode The opcode of the instruction to read. * @return Zero if an instruction with the given opcode was read, non-zero * otherwise. If an instruction was read, but the instruction had a * different opcode, non-zero is returned and guac_error is set to * GUAC_STATUS_BAD_STATE. */ int guac_parser_expect(guac_parser* parser, guac_socket* socket, int usec_timeout, const char* opcode); #endif guacamole-server-1.3.0/src/libguac/guacamole/stream.h0000644000175100001440000000636013613156714017504 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_STREAM_H #define _GUAC_STREAM_H /** * Provides functions and structures required for allocating and using streams. * * @file stream.h */ #include "user-fntypes.h" #include "stream-types.h" struct guac_stream { /** * The index of this stream. */ int index; /** * Arbitrary data associated with this stream. */ void* data; /** * Handler for ack events sent by the Guacamole web-client. * * The handler takes a guac_stream which contains the stream index and * will persist through the duration of the transfer, a string containing * the error or status message, and a status code. * * Example: * @code * int ack_handler(guac_user* user, guac_stream* stream, * char* error, guac_protocol_status status); * * int some_function(guac_user* user) { * * guac_stream* stream = guac_user_alloc_stream(user); * stream->ack_handler = ack_handler; * * guac_protocol_send_clipboard(user->socket, * stream, "text/plain"); * * } * @endcode */ guac_user_ack_handler* ack_handler; /** * Handler for blob events sent by the Guacamole web-client. * * The handler takes a guac_stream which contains the stream index and * will persist through the duration of the transfer, an arbitrary buffer * containing the blob, and the length of the blob. * * Example: * @code * int blob_handler(guac_user* user, guac_stream* stream, * void* data, int length); * * int my_clipboard_handler(guac_user* user, guac_stream* stream, * char* mimetype) { * stream->blob_handler = blob_handler; * } * @endcode */ guac_user_blob_handler* blob_handler; /** * Handler for stream end events sent by the Guacamole web-client. * * The handler takes only a guac_stream which contains the stream index. * This guac_stream will be disposed of immediately after this event is * finished. * * Example: * @code * int end_handler(guac_user* user, guac_stream* stream); * * int my_clipboard_handler(guac_user* user, guac_stream* stream, * char* mimetype) { * stream->end_handler = end_handler; * } * @endcode */ guac_user_end_handler* end_handler; }; #endif guacamole-server-1.3.0/src/libguac/guacamole/client.h0000644000175100001440000006331213770536337017476 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_CLIENT_H #define _GUAC_CLIENT_H /** * Functions and structure contents for the Guacamole proxy client. * * @file client.h */ #include "client-fntypes.h" #include "client-types.h" #include "client-constants.h" #include "layer-types.h" #include "object-types.h" #include "pool-types.h" #include "socket-types.h" #include "stream-types.h" #include "timestamp-types.h" #include "user-fntypes.h" #include "user-types.h" #include #include #include struct guac_client { /** * The guac_socket structure to be used to communicate with all connected * web-clients (users). Unlike the user-level guac_socket, this guac_socket * will broadcast instructions to all connected users simultaneously. It * is expected that the implementor of any Guacamole proxy client will * provide their own mechanism of I/O for their protocol. The guac_socket * structure is used only to communicate conveniently with the Guacamole * web-client. */ guac_socket* socket; /** * The current state of the client. When the client is first allocated, * this will be initialized to GUAC_CLIENT_RUNNING. It will remain at * GUAC_CLIENT_RUNNING until an event occurs which requires the client to * shutdown, at which point the state becomes GUAC_CLIENT_STOPPING. */ guac_client_state state; /** * Arbitrary reference to proxy client-specific data. Implementors of a * Guacamole proxy client can store any data they want here, which can then * be retrieved as necessary in the message handlers. */ void* data; /** * The time (in milliseconds) that the last sync message was sent to the * client. */ guac_timestamp last_sent_timestamp; /** * Handler for freeing data when the client is being unloaded. * * This handler will be called when the client needs to be unloaded * by the proxy, and any data allocated by the proxy client should be * freed. * * Note that this handler will NOT be called if the client's * guac_client_init() function fails. * * Implement this handler if you store data inside the client. * * Example: * @code * int free_handler(guac_client* client); * * int guac_client_init(guac_client* client) { * client->free_handler = free_handler; * } * @endcode */ guac_client_free_handler* free_handler; /** * Logging handler. This handler will be called via guac_client_log() when * the client needs to log messages of any type. * * In general, only programs loading the client should implement this * handler, as those are the programs that would provide the logging * facilities. * * Client implementations should expect these handlers to already be * set. * * Example: * @code * void log_handler(guac_client* client, guac_client_log_level level, const char* format, va_list args); * * void function_of_daemon() { * * guac_client* client = [pass log_handler to guac_client_plugin_get_client()]; * * } * @endcode */ guac_client_log_handler* log_handler; /** * Pool of buffer indices. Buffers are simply layers with negative indices. * Note that because guac_pool always gives non-negative indices starting * at 0, the output of this guac_pool will be adjusted. */ guac_pool* __buffer_pool; /** * Pool of layer indices. Note that because guac_pool always gives * non-negative indices starting at 0, the output of this guac_pool will * be adjusted. */ guac_pool* __layer_pool; /** * Pool of stream indices. */ guac_pool* __stream_pool; /** * All available client-level output streams (data going to all connected * users). */ guac_stream* __output_streams; /** * The unique identifier allocated for the connection, which may * be used within the Guacamole protocol to refer to this connection. * This identifier is guaranteed to be unique from all existing * connections and will not collide with any available protocol * names. */ char* connection_id; /** * Lock which is acquired when the users list is being manipulated, or when * the users list is being iterated. */ pthread_rwlock_t __users_lock; /** * The first user within the list of all connected users, or NULL if no * users are currently connected. */ guac_user* __users; /** * The user that first created this connection. This user will also have * their "owner" flag set to a non-zero value. If the owner has left the * connection, this will be NULL. */ guac_user* __owner; /** * The number of currently-connected users. This value may include inactive * users if cleanup of those users has not yet finished. */ int connected_users; /** * Handler for join events, called whenever a new user is joining an active * connection. Note that because users may leave the connection at any * time, a reference to a guac_user can become invalid at any time and * should never be maintained outside the scope of a function invoked by * libguac to which that guac_user was passed (the scope in which the * guac_user reference is guaranteed to be valid) UNLESS that reference is * properly invalidated within the leave_handler. * * The handler is given a pointer to a newly-allocated guac_user which * must then be initialized, if needed. * * Example: * @code * int join_handler(guac_user* user, int argc, char** argv); * * int guac_client_init(guac_client* client) { * client->join_handler = join_handler; * } * @endcode */ guac_user_join_handler* join_handler; /** * Handler for leave events, called whenever a new user is leaving an * active connection. * * The handler is given a pointer to the leaving guac_user whose custom * data and associated resources must now be freed, if any. * * Example: * @code * int leave_handler(guac_user* user); * * int guac_client_init(guac_client* client) { * client->leave_handler = leave_handler; * } * @endcode */ guac_user_leave_handler* leave_handler; /** * NULL-terminated array of all arguments accepted by this client , in * order. New users will specify these arguments when they join the * connection, and the values of those arguments will be made available to * the function initializing newly-joined users. * * The guac_client_init entry point is expected to initialize this, if * arguments are expected. * * Example: * @code * const char* __my_args[] = { * "hostname", * "port", * "username", * "password", * NULL * }; * * int guac_client_init(guac_client* client) { * client->args = __my_args; * } * @endcode */ const char** args; /** * Handle to the dlopen()'d plugin, which should be given to dlclose() when * this client is freed. This is only assigned if guac_client_load_plugin() * is used. */ void* __plugin_handle; }; /** * Returns a new, barebones guac_client. This new guac_client has no handlers * set, but is otherwise usable. * * @return A pointer to the new client. */ guac_client* guac_client_alloc(); /** * Free all resources associated with the given client. * * @param client The proxy client to free all reasources of. */ void guac_client_free(guac_client* client); /** * Writes a message in the log used by the given client. The logger used will * normally be defined by guacd (or whichever program loads the proxy client) * by setting the logging handlers of the client when it is loaded. * * @param client The proxy client logging this message. * @param level The level at which to log this message. * @param format A printf-style format string to log. * @param ... Arguments to use when filling the format string for printing. */ void guac_client_log(guac_client* client, guac_client_log_level level, const char* format, ...); /** * Writes a message in the log used by the given client. The logger used will * normally be defined by guacd (or whichever program loads the proxy client) * by setting the logging handlers of the client when it is loaded. * * @param client The proxy client logging this message. * @param level The level at which to log this message. * @param format A printf-style format string to log. * @param ap The va_list containing the arguments to be used when filling the * format string for printing. */ void vguac_client_log(guac_client* client, guac_client_log_level level, const char* format, va_list ap); /** * Signals the given client to stop gracefully. This is a completely * cooperative signal, and can be ignored by the client or the hosting * daemon. * * @param client The proxy client to signal to stop. */ void guac_client_stop(guac_client* client); /** * Signals the given client to stop gracefully, while also signalling via the * Guacamole protocol that an error has occurred. Note that this is a completely * cooperative signal, and can be ignored by the client or the hosting * daemon. The message given will be logged to the system logs. * * @param client The proxy client to signal to stop. * @param status The status to send over the Guacamole protocol. * @param format A printf-style format string to log. * @param ... Arguments to use when filling the format string for printing. */ void guac_client_abort(guac_client* client, guac_protocol_status status, const char* format, ...); /** * Signals the given client to stop gracefully, while also signalling via the * Guacamole protocol that an error has occurred. Note that this is a completely * cooperative signal, and can be ignored by the client or the hosting * daemon. The message given will be logged to the system logs. * * @param client The proxy client to signal to stop. * @param status The status to send over the Guacamole protocol. * @param format A printf-style format string to log. * @param ap The va_list containing the arguments to be used when filling the * format string for printing. */ void vguac_client_abort(guac_client* client, guac_protocol_status status, const char* format, va_list ap); /** * Allocates a new buffer (invisible layer). An arbitrary index is * automatically assigned if no existing buffer is available for use. * * @param client The proxy client to allocate the buffer for. * @return The next available buffer, or a newly allocated buffer. */ guac_layer* guac_client_alloc_buffer(guac_client* client); /** * Allocates a new layer. An arbitrary index is automatically assigned * if no existing layer is available for use. * * @param client The proxy client to allocate the layer buffer for. * @return The next available layer, or a newly allocated layer. */ guac_layer* guac_client_alloc_layer(guac_client* client); /** * Returns the given buffer to the pool of available buffers, such that it * can be reused by any subsequent call to guac_client_allow_buffer(). * * @param client The proxy client to return the buffer to. * @param layer The buffer to return to the pool of available buffers. */ void guac_client_free_buffer(guac_client* client, guac_layer* layer); /** * Returns the given layer to the pool of available layers, such that it * can be reused by any subsequent call to guac_client_allow_layer(). * * @param client The proxy client to return the layer to. * @param layer The buffer to return to the pool of available layer. */ void guac_client_free_layer(guac_client* client, guac_layer* layer); /** * Allocates a new stream. An arbitrary index is automatically assigned * if no previously-allocated stream is available for use. * * @param client * The client to allocate the stream for. * * @return * The next available stream, or a newly allocated stream, or NULL if the * maximum number of active streams has been reached. */ guac_stream* guac_client_alloc_stream(guac_client* client); /** * Returns the given stream to the pool of available streams, such that it * can be reused by any subsequent call to guac_client_alloc_stream(). * * @param client * The client to return the stream to. * * @param stream * The stream to return to the pool of available stream. */ void guac_client_free_stream(guac_client* client, guac_stream* stream); /** * Adds the given user to the internal list of connected users. Future writes * to the broadcast socket stored within guac_client will also write to this * user. The join handler of this guac_client will be called. * * @param client The proxy client to add the user to. * @param user The user to add. * @param argc The number of arguments to pass to the new user. * @param argv An array of strings containing the argument values being passed. * @return Zero if the user was added successfully, non-zero if the user could * not join the connection. */ int guac_client_add_user(guac_client* client, guac_user* user, int argc, char** argv); /** * Removes the given user, removing the user from the internally-tracked list * of connected users, and calling any appropriate leave handler. * * @param client The proxy client to return the buffer to. * @param user The user to remove. */ void guac_client_remove_user(guac_client* client, guac_user* user); /** * Calls the given function on all currently-connected users of the given * client. The function will be given a reference to a guac_user and the * specified arbitrary data. The value returned by the callback will be * ignored. * * This function is reentrant, but the user list MUST NOT be manipulated * within the same thread as a callback to this function. Though the callback * MAY invoke guac_client_foreach_user(), doing so should not be necessary, and * may indicate poor design choices. * * @param client * The client whose users should be iterated. * * @param callback * The function to call for each user. * * @param data * Arbitrary data to pass to the callback each time it is invoked. */ void guac_client_foreach_user(guac_client* client, guac_user_callback* callback, void* data); /** * Calls the given function with the currently-connected user that is marked as * the owner. The owner of a connection is the user that established the * initial connection that created the connection (the first user to connect * and join). The function will be given a reference to the guac_user and the * specified arbitrary data. If the owner has since left the connection, the * function will instead be invoked with NULL as the guac_user. The value * returned by the callback will be returned by this function. * * This function is reentrant, but the user list MUST NOT be manipulated * within the same thread as a callback to this function. * * @param client * The client to retrieve the owner from. * * @param callback * The callback to invoke on the user marked as the owner of the * connection. NULL will be passed to this callback instead if there is no * owner. * * @param data * Arbitrary data to pass to the given callback. * * @return * The value returned by the callback. */ void* guac_client_for_owner(guac_client* client, guac_user_callback* callback, void* data); /** * Calls the given function with the given user ONLY if they are currently * connected. The function will be given a reference to the guac_user and the * specified arbitrary data. If the provided user doesn't exist or has since * left the connection, the function will instead be invoked with NULL as the * guac_user. The value returned by the callback will be returned by this * function. * * This function is reentrant, but the user list MUST NOT be manipulated * within the same thread as a callback to this function. * * @param client * The client that the given user is expected to be associated with. * * @param user * The user to provide to the given callback if valid. The pointer need not * even point to properly allocated memory; the user will only be passed to * the callback function if they are valid, and the provided user pointer * will not be dereferenced during this process. * * @param callback * The callback to invoke on the given user if they are valid. NULL will be * passed to this callback instead if the user is not valid. * * @param data * Arbitrary data to pass to the given callback. * * @return * The value returned by the callback. */ void* guac_client_for_user(guac_client* client, guac_user* user, guac_user_callback* callback, void* data); /** * Marks the end of the current frame by sending a "sync" instruction to * all connected users. This instruction will contain the current timestamp. * The last_sent_timestamp member of guac_client will be updated accordingly. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * * @param client The guac_client which has finished a frame. * @return Zero on success, non-zero on error. */ int guac_client_end_frame(guac_client* client); /** * Initializes the given guac_client using the initialization routine provided * by the plugin corresponding to the named protocol. This will automatically * invoke guac_client_init within the plugin for the given protocol. * * Note that the connection will likely not be established until the first * user (the "owner") is added to the client. * * @param client The guac_client to initialize. * @param protocol The name of the protocol to use. * @return Zero if initialization was successful, non-zero otherwise. */ int guac_client_load_plugin(guac_client* client, const char* protocol); /** * Calculates and returns the approximate processing lag experienced by the * pool of users. The processing lag is the difference in time between server * and client due purely to data processing and excluding network delays. * * @param client * The guac_client to calculate the processing lag of. * * @return * The approximate processing lag of the pool of users associated with the * given guac_client, in milliseconds. */ int guac_client_get_processing_lag(guac_client* client); /** * Sends a request to the owner of the given guac_client for parameters required * to continue the connection started by the client. The function returns zero * on success or non-zero on failure. * * @param client * The client where additional connection parameters are required. * * @param required * The NULL-terminated array of required parameters. * * @return * Zero on success, non-zero on failure. */ int guac_client_owner_send_required(guac_client* client, const char** required); /** * Streams the given connection parameter value over an argument value stream * ("argv" instruction), exposing the current value of the named connection * parameter to all users of the given client. The argument value stream will * be automatically allocated and freed. * * @param client * The Guacamole client for which the argument value stream should be * allocated. * * @param socket * The socket over which instructions associated with the argument value * stream should be sent. * * @param mimetype * The mimetype of the data within the connection parameter value being * sent. * * @param name * The name of the connection parameter being sent. * * @param value * The current value of the connection parameter being sent. */ void guac_client_stream_argv(guac_client* client, guac_socket* socket, const char* mimetype, const char* name, const char* value); /** * Streams the image data of the given surface over an image stream ("img" * instruction) as PNG-encoded data. The image stream will be automatically * allocated and freed. * * @param client * The Guacamole client for which the image stream should be allocated. * * @param socket * The socket over which instructions associated with the image stream * should be sent. * * @param mode * The composite mode to use when rendering the image over the given layer. * * @param layer * The destination layer. * * @param x * The X coordinate of the upper-left corner of the destination rectangle * within the given layer. * * @param y * The Y coordinate of the upper-left corner of the destination rectangle * within the given layer. * * @param surface * A Cairo surface containing the image data to be streamed. */ void guac_client_stream_png(guac_client* client, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface); /** * Streams the image data of the given surface over an image stream ("img" * instruction) as JPEG-encoded data at the given quality. The image stream * will be automatically allocated and freed. * * @param client * The Guacamole client for which the image stream should be allocated. * * @param socket * The socket over which instructions associated with the image stream * should be sent. * * @param mode * The composite mode to use when rendering the image over the given layer. * * @param layer * The destination layer. * * @param x * The X coordinate of the upper-left corner of the destination rectangle * within the given layer. * * @param y * The Y coordinate of the upper-left corner of the destination rectangle * within the given layer. * * @param surface * A Cairo surface containing the image data to be streamed. * * @param quality * The JPEG image quality, which must be an integer value between 0 and 100 * inclusive. Larger values indicate improving quality at the expense of * larger file size. */ void guac_client_stream_jpeg(guac_client* client, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface, int quality); /** * Streams the image data of the given surface over an image stream ("img" * instruction) as WebP-encoded data at the given quality. The image stream * will be automatically allocated and freed. If the server does not support * WebP, this function has no effect, so be sure to check the result of * guac_client_supports_webp() prior to calling this function. * * @param client * The Guacamole client for whom the image stream should be allocated. * * @param socket * The socket over which instructions associated with the image stream * should be sent. * * @param mode * The composite mode to use when rendering the image over the given layer. * * @param layer * The destination layer. * * @param x * The X coordinate of the upper-left corner of the destination rectangle * within the given layer. * * @param y * The Y coordinate of the upper-left corner of the destination rectangle * within the given layer. * * @param surface * A Cairo surface containing the image data to be streamed. * * @param quality * The WebP image quality, which must be an integer value between 0 and 100 * inclusive. For lossy images, larger values indicate improving quality at * the expense of larger file size. For lossless images, this dictates the * quality of compression, with larger values producing smaller files at * the expense of speed. * * @param lossless * Zero to encode a lossy image, non-zero to encode losslessly. */ void guac_client_stream_webp(guac_client* client, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface, int quality, int lossless); /** * Returns whether the owner of the given client supports the "required" * instruction, returning non-zero if the client owner does support the * instruction, or zero if the owner does not. * * @param client * The Guacamole client whose owner should be checked for supporting * the "required" instruction. * * @return * Non-zero if the owner of the given client supports the "required" * instruction, zero otherwise. */ int guac_client_owner_supports_required(guac_client* client); /** * Returns whether all users of the given client support WebP. If any user does * not support WebP, or the server cannot encode WebP images, zero is returned. * * @param client * The Guacamole client whose users should be checked for WebP support. * * @return * Non-zero if the all users of the given client claim to support WebP and * the server has been built with WebP support, zero otherwise. */ int guac_client_supports_webp(guac_client* client); /** * The default Guacamole client layer, layer 0. */ extern const guac_layer* GUAC_DEFAULT_LAYER; #endif guacamole-server-1.3.0/src/libguac/guacamole/pool-types.h0000644000175100001440000000255013613156714020321 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_POOL_TYPES_H #define _GUAC_POOL_TYPES_H /** * Type definitions related to the guac_pool pool of unique integers. * * @file pool-types.h */ /** * Represents a single integer within a larger pool of integers. */ typedef struct guac_pool_int guac_pool_int; /** * A pool of integers. Integers can be removed from and later free'd back * into the pool. New integers are returned when the pool is exhausted, * or when the pool has not met some minimum size. Old, free'd integers * are returned otherwise. */ typedef struct guac_pool guac_pool; #endif guacamole-server-1.3.0/src/libguac/guacamole/protocol-constants.h0000644000175100001440000000363113770536337022071 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_PROTOCOL_CONSTANTS_H #define GUAC_PROTOCOL_CONSTANTS_H /** * Constants related to the Guacamole protocol. * * @file protocol-constants.h */ /** * This defines the overall protocol version that this build of libguac * supports. The protocol version is used to provide compatibility between * potentially different versions of Guacamole server and clients. The * version number is a MAJOR_MINOR_PATCH version that matches the versioning * used throughout the components of the Guacamole project. This version * will not necessarily increment with the other components, unless additional * functionality is introduced that affects compatibility. * * This version is passed by the __guac_protocol_send_args() function from the * server to the client during the client/server handshake. */ #define GUACAMOLE_PROTOCOL_VERSION "VERSION_1_3_0" /** * The maximum number of bytes that should be sent in any one blob instruction * to ensure the instruction does not exceed the maximum allowed instruction * size. * * @see GUAC_INSTRUCTION_MAX_LENGTH */ #define GUAC_PROTOCOL_BLOB_MAX_LENGTH 6048 #endif guacamole-server-1.3.0/src/libguac/guacamole/plugin.h0000644000175100001440000000175013613156714017505 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_PLUGIN_H #define _GUAC_PLUGIN_H #include "plugin-constants.h" /** * Provides functions and structures required for handling a client plugin. * * @file plugin.h */ #endif guacamole-server-1.3.0/src/libguac/guacamole/client-fntypes.h0000644000175100001440000000471313613156714021155 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_CLIENT_FNTYPES_H #define _GUAC_CLIENT_FNTYPES_H /** * Function type definitions related to the Guacamole client structure, * guac_client. * * @file client-fntypes.h */ #include "client-types.h" #include "object-types.h" #include "protocol-types.h" #include "stream-types.h" #include "user-types.h" #include /** * Handler for freeing up any extra data allocated by the client * implementation. * * @param client * The client whose extra data should be freed (if any). * * @return * Zero if the data was successfully freed, non-zero if an error prevents * the data from being freed. */ typedef int guac_client_free_handler(guac_client* client); /** * Handler for logging messages related to a given guac_client instance. * * @param client * The client related to the message being logged. * * @param level * The log level at which to log the given message. * * @param format * A printf-style format string, defining the message to be logged. * * @param args * The va_list containing the arguments to be used when filling the * conversion specifiers ("%s", "%i", etc.) within the format string. */ typedef void guac_client_log_handler(guac_client* client, guac_client_log_level level, const char* format, va_list args); /** * The entry point of a client plugin which must initialize the given * guac_client. In practice, this function will be called "guac_client_init". * * @param client * The guac_client that must be initialized. * * @return * Zero on success, non-zero if initialization fails for any reason. */ typedef int guac_client_init_handler(guac_client* client); #endif guacamole-server-1.3.0/src/libguac/guacamole/wol.h0000644000175100001440000000331613764613616017016 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_WOL_H #define GUAC_WOL_H /** * Header that provides functions and structures related to Wake-on-LAN * support in libguac. * * @file wol.h */ #include "wol-constants.h" /** * Send the wake-up packet to the specified destination, returning zero if the * wake was sent successfully, or non-zero if an error occurs sending the * wake packet. Note that the return value does not specify whether the * system actually wakes up successfully, only whether or not the packet * is transmitted. * * @param mac_addr * The MAC address to place in the magic Wake-on-LAN packet. * * @param broadcast_addr * The broadcast address to which to send the magic Wake-on-LAN packet. * * @return * Zero if the packet is successfully sent to the destination; non-zero * if the packet cannot be sent. */ int guac_wol_wake(const char* mac_addr, const char* broadcast_addr); #endif /* GUAC_WOL_H */ guacamole-server-1.3.0/src/libguac/guacamole/socket-ssl.h0000644000175100001440000000377413676721354020315 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUACD_SOCKET_SSL_H #define __GUACD_SOCKET_SSL_H /** * Provides an SSL/TLS implementation of guac_socket. This header will only be * available if libguac was built with SSL support. * * @file socket-ssl.h */ #include "socket-types.h" #include /** * SSL socket-specific data. */ typedef struct guac_socket_ssl_data { /** * The file descriptor that SSL communication will take place * over. */ int fd; /** * The current SSL context. */ SSL_CTX* context; /** * The SSL connection, created automatically via * guac_socket_open_secure(). */ SSL* ssl; } guac_socket_ssl_data; /** * Creates a new guac_socket which will use SSL for all communication. Freeing * this guac_socket will automatically close the associated file descriptor. * * @param context * The SSL_CTX structure describing the desired SSL configuration. * * @param fd * The file descriptor to use for the SSL connection underlying the * created guac_socket. * * @return * A newly-allocated guac_socket which will transparently use SSL for * all communication. */ guac_socket* guac_socket_open_secure(SSL_CTX* context, int fd); #endif guacamole-server-1.3.0/src/libguac/guacamole/timestamp-types.h0000644000175100001440000000213713613156714021354 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_TIMESTAMP_TYPES_H #define _GUAC_TIMESTAMP_TYPES_H /** * Type definitions related to Guacamole protocol timestamps. * * @file timestamp-types.h */ #include /** * An arbitrary timestamp denoting a relative time value in milliseconds. */ typedef int64_t guac_timestamp; #endif guacamole-server-1.3.0/src/libguac/guacamole/stream-types.h0000644000175100001440000000207113613156714020641 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_STREAM_TYPES_H #define _GUAC_STREAM_TYPES_H /** * Type definitions related to Guacamole protocol streams. * * @file stream-types.h */ /** * Represents a single stream within the Guacamole protocol. */ typedef struct guac_stream guac_stream; #endif guacamole-server-1.3.0/src/libguac/guacamole/socket-wsa.h0000644000175100001440000000315313676721354020275 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_SOCKET_WSA_H #define GUAC_SOCKET_WSA_H /** * Provides an implementation of guac_socket specific to the Windows Socket API * (aka WSA or "winsock"). This header will only be available if libguac was * built with WSA support. * * @file socket-wsa.h */ #include "socket-types.h" #include /** * Creates a new guac_socket which will use the Windows Socket API (aka WSA or * "winsock") for all communication. Freeing this guac_socket will * automatically close the associated SOCKET handle. * * @param sock * The WSA SOCKET handle to use for the connection underlying the created * guac_socket. * * @return * A newly-allocated guac_socket which will transparently use the Windows * Socket API for all communication. */ guac_socket* guac_socket_open_wsa(SOCKET sock); #endif guacamole-server-1.3.0/src/libguac/guacamole/object-types.h0000644000175100001440000000206713613156714020621 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_OBJECT_TYPES_H #define GUAC_OBJECT_TYPES_H /** * Type definitions related to Guacamole protocol objects. * * @file object-types.h */ /** * Represents a single object within the Guacamole protocol. */ typedef struct guac_object guac_object; #endif guacamole-server-1.3.0/src/libguac/audio.c0000644000175100001440000001522613764613616015357 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/audio.h" #include "guacamole/client.h" #include "guacamole/protocol.h" #include "guacamole/stream.h" #include "guacamole/user.h" #include "raw_encoder.h" #include #include /** * Sets the encoder associated with the given guac_audio_stream, automatically * invoking its begin_handler. The guac_audio_stream MUST NOT already be * associated with an encoder. * * @param audio * The guac_audio_stream whose encoder is being set. * * @param encoder * The encoder to associate with the given guac_audio_stream. */ static void guac_audio_stream_set_encoder(guac_audio_stream* audio, guac_audio_encoder* encoder) { /* Call handler, if defined */ if (encoder != NULL && encoder->begin_handler) encoder->begin_handler(audio); /* Assign encoder, which may be NULL */ audio->encoder = encoder; } /** * Assigns a new audio encoder to the given guac_audio_stream based on the * audio mimetypes declared as supported by the given user. If no audio encoder * can be found, no new audio encoder is assigned, and the existing encoder is * left untouched (if any). * * @param user * The user whose supported audio mimetypes should determine the audio * encoder selected. * * @param data * The guac_audio_stream to which the new encoder should be assigned. * Existing properties set on this audio stream, such as the bits per * sample, may affect the encoder chosen. * * @return * The assigned audio encoder. If no new audio encoder can be assigned, * this will be the currently-assigned audio encoder (which may be NULL). */ static void* guac_audio_assign_encoder(guac_user* user, void* data) { int i; guac_audio_stream* audio = (guac_audio_stream*) data; int bps = audio->bps; /* If no user is provided, or an encoder has already been assigned, * do not attempt to assign a new encoder */ if (user == NULL || audio->encoder != NULL) return audio->encoder; /* For each supported mimetype, check for an associated encoder */ for (i=0; user->info.audio_mimetypes[i] != NULL; i++) { const char* mimetype = user->info.audio_mimetypes[i]; /* If 16-bit raw audio is supported, done. */ if (bps == 16 && strcmp(mimetype, raw16_encoder->mimetype) == 0) { guac_audio_stream_set_encoder(audio, raw16_encoder); break; } /* If 8-bit raw audio is supported, done. */ if (bps == 8 && strcmp(mimetype, raw8_encoder->mimetype) == 0) { guac_audio_stream_set_encoder(audio, raw8_encoder); break; } } /* end for each mimetype */ /* Return assigned encoder, if any */ return audio->encoder; } guac_audio_stream* guac_audio_stream_alloc(guac_client* client, guac_audio_encoder* encoder, int rate, int channels, int bps) { guac_audio_stream* audio; /* Allocate stream */ audio = (guac_audio_stream*) calloc(1, sizeof(guac_audio_stream)); audio->client = client; audio->stream = guac_client_alloc_stream(client); /* Abort allocation if underlying stream cannot be allocated */ if (audio->stream == NULL) { free(audio); return NULL; } /* Load PCM properties */ audio->rate = rate; audio->channels = channels; audio->bps = bps; /* Assign encoder if explicitly provided */ if (encoder != NULL) guac_audio_stream_set_encoder(audio, encoder); /* Otherwise, attempt to automatically assign encoder for owner */ if (audio->encoder == NULL) guac_client_for_owner(client, guac_audio_assign_encoder, audio); /* Failing that, attempt to assign encoder for ANY connected user */ if (audio->encoder == NULL) guac_client_foreach_user(client, guac_audio_assign_encoder, audio); return audio; } void guac_audio_stream_reset(guac_audio_stream* audio, guac_audio_encoder* encoder, int rate, int channels, int bps) { /* Pull assigned encoder if no other encoder is requested */ if (encoder == NULL) encoder = audio->encoder; /* Do nothing if nothing is changing */ if (encoder == audio->encoder && rate == audio->rate && channels == audio->channels && bps == audio->bps) { return; } /* Free old encoder data */ if (audio->encoder != NULL && audio->encoder->end_handler) audio->encoder->end_handler(audio); /* Set PCM properties */ audio->rate = rate; audio->channels = channels; audio->bps = bps; /* Re-init encoder */ guac_audio_stream_set_encoder(audio, encoder); } void guac_audio_stream_add_user(guac_audio_stream* audio, guac_user* user) { /* Attempt to assign encoder if no encoder has yet been assigned */ if (audio->encoder == NULL) guac_audio_assign_encoder(user, audio); /* Notify encoder that a new user is present */ if (audio->encoder != NULL && audio->encoder->join_handler) audio->encoder->join_handler(audio, user); } void guac_audio_stream_free(guac_audio_stream* audio) { /* Flush stream encoding */ guac_audio_stream_flush(audio); /* Clean up encoder */ if (audio->encoder != NULL && audio->encoder->end_handler) audio->encoder->end_handler(audio); /* Release stream back to client pool */ guac_client_free_stream(audio->client, audio->stream); /* Free associated data */ free(audio); } void guac_audio_stream_write_pcm(guac_audio_stream* audio, const unsigned char* data, int length) { /* Write data */ if (audio->encoder != NULL && audio->encoder->write_handler) audio->encoder->write_handler(audio, data, length); } void guac_audio_stream_flush(guac_audio_stream* audio) { /* Flush any buffered data */ if (audio->encoder != NULL && audio->encoder->flush_handler) audio->encoder->flush_handler(audio); } guacamole-server-1.3.0/src/libguac/encode-jpeg.h0000644000175100001440000000305513764613616016440 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_ENCODE_JPEG_H #define GUAC_ENCODE_JPEG_H #include "config.h" #include "guacamole/socket.h" #include "guacamole/stream.h" #include /** * Encodes the given surface as a JPEG, and sends the resulting data over the * given stream and socket as blobs. * * @param socket * The socket to send JPEG blobs over. * * @param stream * The stream to associate with each blob. * * @param surface * The Cairo surface to write to the given stream and socket as JPEG blobs. * * @param quality * JPEG image quality. * * @return * Zero if the encoding operation is successful, non-zero otherwise. */ int guac_jpeg_write(guac_socket* socket, guac_stream* stream, cairo_surface_t* surface, int quality); #endif guacamole-server-1.3.0/src/libguac/string.c0000644000175100001440000000702113770536337015557 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include #include /** * Returns the space remaining in a buffer assuming that the given number of * bytes have already been written. If the number of bytes exceeds the size * of the buffer, zero is returned. * * @param n * The size of the buffer in bytes. * * @param length * The number of bytes which have been written to the buffer so far. If * the routine writing the bytes will automatically truncate its writes, * this value may exceed the size of the buffer. * * @return * The number of bytes remaining in the buffer. This value will always * be non-negative. If the number of bytes written already exceeds the * size of the buffer, zero will be returned. */ #define REMAINING(n, length) (((n) < (length)) ? 0 : ((n) - (length))) size_t guac_strlcpy(char* restrict dest, const char* restrict src, size_t n) { #ifdef HAVE_STRLCPY return strlcpy(dest, src, n); #else /* Calculate actual length of desired string */ size_t length = strlen(src); /* Copy nothing if there is no space */ if (n == 0) return length; /* Calculate length of the string which will be copied */ size_t copy_length = length; if (copy_length >= n) copy_length = n - 1; /* Copy only as much of string as possible, manually adding a null * terminator */ memcpy(dest, src, copy_length); dest[copy_length] = '\0'; /* Return the overall length of the desired string */ return length; #endif } size_t guac_strlcat(char* restrict dest, const char* restrict src, size_t n) { #ifdef HAVE_STRLCPY return strlcat(dest, src, n); #else size_t length = strnlen(dest, n); return length + guac_strlcpy(dest + length, src, REMAINING(n, length)); #endif } char* guac_strdup(const char* str) { /* Return NULL if no string provided */ if (str == NULL) return NULL; /* Otherwise just invoke strdup() */ return strdup(str); } size_t guac_strljoin(char* restrict dest, const char* restrict const* elements, int nmemb, const char* restrict delim, size_t n) { size_t length = 0; const char* restrict const* current = elements; /* If no elements are provided, nothing to do but ensure the destination * buffer is null terminated */ if (nmemb <= 0) return guac_strlcpy(dest, "", n); /* Initialize destination buffer with first element */ length += guac_strlcpy(dest, *current, n); /* Copy all remaining elements, separated by delimiter */ for (current++; nmemb > 1; current++, nmemb--) { length += guac_strlcat(dest + length, delim, REMAINING(n, length)); length += guac_strlcat(dest + length, *current, REMAINING(n, length)); } return length; } guacamole-server-1.3.0/src/libguac/client.c0000644000175100001440000004632613770536337015542 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "encode-jpeg.h" #include "encode-png.h" #include "encode-webp.h" #include "guacamole/client.h" #include "guacamole/error.h" #include "guacamole/layer.h" #include "guacamole/plugin.h" #include "guacamole/pool.h" #include "guacamole/protocol.h" #include "guacamole/socket.h" #include "guacamole/stream.h" #include "guacamole/string.h" #include "guacamole/timestamp.h" #include "guacamole/user.h" #include "id.h" #include #include #include #include #include #include #include /** * Empty NULL-terminated array of argument names. */ const char* __GUAC_CLIENT_NO_ARGS[] = { NULL }; guac_layer __GUAC_DEFAULT_LAYER = { .index = 0 }; const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; guac_layer* guac_client_alloc_layer(guac_client* client) { /* Init new layer */ guac_layer* allocd_layer = malloc(sizeof(guac_layer)); allocd_layer->index = guac_pool_next_int(client->__layer_pool)+1; return allocd_layer; } guac_layer* guac_client_alloc_buffer(guac_client* client) { /* Init new layer */ guac_layer* allocd_layer = malloc(sizeof(guac_layer)); allocd_layer->index = -guac_pool_next_int(client->__buffer_pool) - 1; return allocd_layer; } void guac_client_free_buffer(guac_client* client, guac_layer* layer) { /* Release index to pool */ guac_pool_free_int(client->__buffer_pool, -layer->index - 1); /* Free layer */ free(layer); } void guac_client_free_layer(guac_client* client, guac_layer* layer) { /* Release index to pool */ guac_pool_free_int(client->__layer_pool, layer->index); /* Free layer */ free(layer); } guac_stream* guac_client_alloc_stream(guac_client* client) { guac_stream* allocd_stream; int stream_index; /* Refuse to allocate beyond maximum */ if (client->__stream_pool->active == GUAC_CLIENT_MAX_STREAMS) return NULL; /* Allocate stream */ stream_index = guac_pool_next_int(client->__stream_pool); /* Initialize stream with odd index (even indices are user-level) */ allocd_stream = &(client->__output_streams[stream_index]); allocd_stream->index = (stream_index * 2) + 1; allocd_stream->data = NULL; allocd_stream->ack_handler = NULL; allocd_stream->blob_handler = NULL; allocd_stream->end_handler = NULL; return allocd_stream; } void guac_client_free_stream(guac_client* client, guac_stream* stream) { /* Release index to pool */ guac_pool_free_int(client->__stream_pool, (stream->index - 1) / 2); /* Mark stream as closed */ stream->index = GUAC_CLIENT_CLOSED_STREAM_INDEX; } guac_client* guac_client_alloc() { int i; pthread_rwlockattr_t lock_attributes; /* Allocate new client */ guac_client* client = malloc(sizeof(guac_client)); if (client == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; guac_error_message = "Could not allocate memory for client"; return NULL; } /* Init new client */ memset(client, 0, sizeof(guac_client)); client->args = __GUAC_CLIENT_NO_ARGS; client->state = GUAC_CLIENT_RUNNING; client->last_sent_timestamp = guac_timestamp_current(); /* Generate ID */ client->connection_id = guac_generate_id(GUAC_CLIENT_ID_PREFIX); if (client->connection_id == NULL) { free(client); return NULL; } /* Allocate buffer and layer pools */ client->__buffer_pool = guac_pool_alloc(GUAC_BUFFER_POOL_INITIAL_SIZE); client->__layer_pool = guac_pool_alloc(GUAC_BUFFER_POOL_INITIAL_SIZE); /* Allocate stream pool */ client->__stream_pool = guac_pool_alloc(0); /* Initialize streams */ client->__output_streams = malloc(sizeof(guac_stream) * GUAC_CLIENT_MAX_STREAMS); for (i=0; i__output_streams[i].index = GUAC_CLIENT_CLOSED_STREAM_INDEX; } /* Init locks */ pthread_rwlockattr_init(&lock_attributes); pthread_rwlockattr_setpshared(&lock_attributes, PTHREAD_PROCESS_SHARED); pthread_rwlock_init(&(client->__users_lock), &lock_attributes); /* Set up socket to broadcast to all users */ client->socket = guac_socket_broadcast(client); return client; } void guac_client_free(guac_client* client) { /* Remove all users */ while (client->__users != NULL) guac_client_remove_user(client, client->__users); if (client->free_handler) { /* FIXME: Errors currently ignored... */ client->free_handler(client); } /* Free socket */ guac_socket_free(client->socket); /* Free layer pools */ guac_pool_free(client->__buffer_pool); guac_pool_free(client->__layer_pool); /* Free streams */ free(client->__output_streams); /* Free stream pool */ guac_pool_free(client->__stream_pool); /* Close associated plugin */ if (client->__plugin_handle != NULL) { if (dlclose(client->__plugin_handle)) guac_client_log(client, GUAC_LOG_ERROR, "Unable to close plugin: %s", dlerror()); } pthread_rwlock_destroy(&(client->__users_lock)); free(client->connection_id); free(client); } void vguac_client_log(guac_client* client, guac_client_log_level level, const char* format, va_list ap) { /* Call handler if defined */ if (client->log_handler != NULL) client->log_handler(client, level, format, ap); } void guac_client_log(guac_client* client, guac_client_log_level level, const char* format, ...) { va_list args; va_start(args, format); vguac_client_log(client, level, format, args); va_end(args); } void guac_client_stop(guac_client* client) { client->state = GUAC_CLIENT_STOPPING; } void vguac_client_abort(guac_client* client, guac_protocol_status status, const char* format, va_list ap) { /* Only relevant if client is running */ if (client->state == GUAC_CLIENT_RUNNING) { /* Log detail of error */ vguac_client_log(client, GUAC_LOG_ERROR, format, ap); /* Send error immediately, limit information given */ guac_protocol_send_error(client->socket, "Aborted. See logs.", status); guac_socket_flush(client->socket); /* Stop client */ guac_client_stop(client); } } void guac_client_abort(guac_client* client, guac_protocol_status status, const char* format, ...) { va_list args; va_start(args, format); vguac_client_abort(client, status, format, args); va_end(args); } int guac_client_add_user(guac_client* client, guac_user* user, int argc, char** argv) { int retval = 0; /* Call handler, if defined */ if (client->join_handler) retval = client->join_handler(user, argc, argv); pthread_rwlock_wrlock(&(client->__users_lock)); /* Add to list if join was successful */ if (retval == 0) { user->__prev = NULL; user->__next = client->__users; if (client->__users != NULL) client->__users->__prev = user; client->__users = user; client->connected_users++; /* Update owner pointer if user is owner */ if (user->owner) client->__owner = user; } pthread_rwlock_unlock(&(client->__users_lock)); return retval; } void guac_client_remove_user(guac_client* client, guac_user* user) { pthread_rwlock_wrlock(&(client->__users_lock)); /* Update prev / head */ if (user->__prev != NULL) user->__prev->__next = user->__next; else client->__users = user->__next; /* Update next */ if (user->__next != NULL) user->__next->__prev = user->__prev; client->connected_users--; /* Update owner pointer if user was owner */ if (user->owner) client->__owner = NULL; pthread_rwlock_unlock(&(client->__users_lock)); /* Call handler, if defined */ if (user->leave_handler) user->leave_handler(user); else if (client->leave_handler) client->leave_handler(user); } void guac_client_foreach_user(guac_client* client, guac_user_callback* callback, void* data) { guac_user* current; pthread_rwlock_rdlock(&(client->__users_lock)); /* Call function on each user */ current = client->__users; while (current != NULL) { callback(current, data); current = current->__next; } pthread_rwlock_unlock(&(client->__users_lock)); } void* guac_client_for_owner(guac_client* client, guac_user_callback* callback, void* data) { void* retval; pthread_rwlock_rdlock(&(client->__users_lock)); /* Invoke callback with current owner */ retval = callback(client->__owner, data); pthread_rwlock_unlock(&(client->__users_lock)); /* Return value from callback */ return retval; } void* guac_client_for_user(guac_client* client, guac_user* user, guac_user_callback* callback, void* data) { guac_user* current; int user_valid = 0; void* retval; pthread_rwlock_rdlock(&(client->__users_lock)); /* Loop through all users, searching for a pointer to the given user */ current = client->__users; while (current != NULL) { /* If the user's pointer exists in the list, they are indeed valid */ if (current == user) { user_valid = 1; break; } current = current->__next; } /* Use NULL if user does not actually exist */ if (!user_valid) user = NULL; /* Invoke callback with requested user (if they exist) */ retval = callback(user, data); pthread_rwlock_unlock(&(client->__users_lock)); /* Return value from callback */ return retval; } int guac_client_end_frame(guac_client* client) { /* Update and send timestamp */ client->last_sent_timestamp = guac_timestamp_current(); /* Log received timestamp and calculated lag (at TRACE level only) */ guac_client_log(client, GUAC_LOG_TRACE, "Server completed " "frame %" PRIu64 "ms.", client->last_sent_timestamp); return guac_protocol_send_sync(client->socket, client->last_sent_timestamp); } int guac_client_load_plugin(guac_client* client, const char* protocol) { /* Reference to dlopen()'d plugin */ void* client_plugin_handle; /* Pluggable client */ char protocol_lib[GUAC_PROTOCOL_LIBRARY_LIMIT] = GUAC_PROTOCOL_LIBRARY_PREFIX; /* Type-pun for the sake of dlsym() - cannot typecast a void* to a function * pointer otherwise */ union { guac_client_init_handler* client_init; void* obj; } alias; /* Add protocol and .so suffix to protocol_lib */ guac_strlcat(protocol_lib, protocol, sizeof(protocol_lib)); if (guac_strlcat(protocol_lib, GUAC_PROTOCOL_LIBRARY_SUFFIX, sizeof(protocol_lib)) >= sizeof(protocol_lib)) { guac_error = GUAC_STATUS_NO_MEMORY; guac_error_message = "Protocol name is too long"; return -1; } /* Load client plugin */ client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); if (!client_plugin_handle) { guac_error = GUAC_STATUS_NOT_FOUND; guac_error_message = dlerror(); return -1; } dlerror(); /* Clear errors */ /* Get init function */ alias.obj = dlsym(client_plugin_handle, "guac_client_init"); /* Fail if cannot find guac_client_init */ if (dlerror() != NULL) { guac_error = GUAC_STATUS_INTERNAL_ERROR; guac_error_message = dlerror(); dlclose(client_plugin_handle); return -1; } /* Init client */ client->__plugin_handle = client_plugin_handle; return alias.client_init(client); } /** * A callback function which is invoked by guac_client_owner_send_required() to * send the required parameters to the specified user, who is the owner of the * client session. * * @param user * The guac_user that will receive the required parameters, who is the owner * of the client. * * @param data * A pointer to a NULL-terminated array of required parameters that will be * passed on to the owner to continue the connection. * * @return * Zero if the operation succeeds or non-zero on failure, cast as a void*. */ static void* guac_client_owner_send_required_callback(guac_user* user, void* data) { const char** required = (const char **) data; /* Send required parameters to owner. */ if (user != NULL) return (void*) ((intptr_t) guac_protocol_send_required(user->socket, required)); return (void*) ((intptr_t) -1); } int guac_client_owner_send_required(guac_client* client, const char** required) { /* Don't send required instruction if client does not support it. */ if (!guac_client_owner_supports_required(client)) return -1; return (int) ((intptr_t) guac_client_for_owner(client, guac_client_owner_send_required_callback, required)); } /** * Updates the provided approximate processing lag, taking into account the * processing lag of the given user. * * @param user * The guac_user to use to update the approximate processing lag. * * @param data * Pointer to an int containing the current approximate processing lag. * The int will be updated according to the processing lag of the given * user. * * @return * Always NULL. */ static void* __calculate_lag(guac_user* user, void* data) { int* processing_lag = (int*) data; /* Simply find maximum */ if (user->processing_lag > *processing_lag) *processing_lag = user->processing_lag; return NULL; } int guac_client_get_processing_lag(guac_client* client) { int processing_lag = 0; /* Approximate the processing lag of all users */ guac_client_foreach_user(client, __calculate_lag, &processing_lag); return processing_lag; } void guac_client_stream_argv(guac_client* client, guac_socket* socket, const char* mimetype, const char* name, const char* value) { /* Allocate new stream for argument value */ guac_stream* stream = guac_client_alloc_stream(client); /* Declare stream as containing connection parameter data */ guac_protocol_send_argv(socket, stream, mimetype, name); /* Write parameter data */ guac_protocol_send_blobs(socket, stream, value, strlen(value)); /* Terminate stream */ guac_protocol_send_end(socket, stream); /* Free allocated stream */ guac_client_free_stream(client, stream); } void guac_client_stream_png(guac_client* client, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface) { /* Allocate new stream for image */ guac_stream* stream = guac_client_alloc_stream(client); /* Declare stream as containing image data */ guac_protocol_send_img(socket, stream, mode, layer, "image/png", x, y); /* Write PNG data */ guac_png_write(socket, stream, surface); /* Terminate stream */ guac_protocol_send_end(socket, stream); /* Free allocated stream */ guac_client_free_stream(client, stream); } void guac_client_stream_jpeg(guac_client* client, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface, int quality) { /* Allocate new stream for image */ guac_stream* stream = guac_client_alloc_stream(client); /* Declare stream as containing image data */ guac_protocol_send_img(socket, stream, mode, layer, "image/jpeg", x, y); /* Write JPEG data */ guac_jpeg_write(socket, stream, surface, quality); /* Terminate stream */ guac_protocol_send_end(socket, stream); /* Free allocated stream */ guac_client_free_stream(client, stream); } void guac_client_stream_webp(guac_client* client, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface, int quality, int lossless) { #ifdef ENABLE_WEBP /* Allocate new stream for image */ guac_stream* stream = guac_client_alloc_stream(client); /* Declare stream as containing image data */ guac_protocol_send_img(socket, stream, mode, layer, "image/webp", x, y); /* Write WebP data */ guac_webp_write(socket, stream, surface, quality, lossless); /* Terminate stream */ guac_protocol_send_end(socket, stream); /* Free allocated stream */ guac_client_free_stream(client, stream); #else /* Do nothing if WebP support is not built in */ #endif } #ifdef ENABLE_WEBP /** * Callback which is invoked by guac_client_supports_webp() for each user * associated with the given client, thus updating an overall support flag * describing the WebP support state for the client as a whole. * * @param user * The user to check for WebP support. * * @param data * Pointer to an int containing the current WebP support status for the * client associated with the given user. This flag will be 0 if any user * already checked has lacked WebP support, or 1 otherwise. * * @return * Always NULL. */ static void* __webp_support_callback(guac_user* user, void* data) { int* webp_supported = (int*) data; /* Check whether current user supports WebP */ if (*webp_supported) *webp_supported = guac_user_supports_webp(user); return NULL; } #endif /** * A callback function which is invoked by guac_client_owner_supports_required() * to determine if the owner of a client supports the "required" instruction, * returning zero if the user does not support the instruction or non-zero if * the user supports it. * * @param user * The guac_user that will be checked for "required" instruction support. * * @param data * Data provided to the callback. This value is never used within this * callback. * * @return * A non-zero integer if the provided user who owns the connection supports * the "required" instruction, or zero if the user does not. The integer * is cast as a void*. */ static void* guac_owner_supports_required_callback(guac_user* user, void* data) { return (void*) ((intptr_t) guac_user_supports_required(user)); } int guac_client_owner_supports_required(guac_client* client) { return (int) ((intptr_t) guac_client_for_owner(client, guac_owner_supports_required_callback, NULL)); } int guac_client_supports_webp(guac_client* client) { #ifdef ENABLE_WEBP int webp_supported = 1; /* WebP is supported for entire client only if each user supports it */ guac_client_foreach_user(client, __webp_support_callback, &webp_supported); return webp_supported; #else /* Support for WebP is completely absent */ return 0; #endif } guacamole-server-1.3.0/src/libguac/user-handlers.c0000644000175100001440000005037613764613616017037 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/client.h" #include "guacamole/object.h" #include "guacamole/protocol.h" #include "guacamole/stream.h" #include "guacamole/timestamp.h" #include "guacamole/user.h" #include "user-handlers.h" #include #include #include #include #include /* Guacamole instruction handler map */ __guac_instruction_handler_mapping __guac_instruction_handler_map[] = { {"sync", __guac_handle_sync}, {"mouse", __guac_handle_mouse}, {"key", __guac_handle_key}, {"clipboard", __guac_handle_clipboard}, {"disconnect", __guac_handle_disconnect}, {"size", __guac_handle_size}, {"file", __guac_handle_file}, {"pipe", __guac_handle_pipe}, {"ack", __guac_handle_ack}, {"blob", __guac_handle_blob}, {"end", __guac_handle_end}, {"get", __guac_handle_get}, {"put", __guac_handle_put}, {"audio", __guac_handle_audio}, {"argv", __guac_handle_argv}, {"nop", __guac_handle_nop}, {NULL, NULL} }; /* Guacamole handshake handler map */ __guac_instruction_handler_mapping __guac_handshake_handler_map[] = { {"size", __guac_handshake_size_handler}, {"audio", __guac_handshake_audio_handler}, {"video", __guac_handshake_video_handler}, {"image", __guac_handshake_image_handler}, {"timezone", __guac_handshake_timezone_handler}, {NULL, NULL} }; /** * Parses a 64-bit integer from the given string. It is assumed that the string * will contain only decimal digits, with an optional leading minus sign. * The result of parsing a string which does not conform to this pattern is * undefined. * * @param str * The string to parse, which must contain only decimal digits and an * optional leading minus sign. * * @return * The 64-bit integer value represented by the given string. */ static int64_t __guac_parse_int(const char* str) { int sign = 1; int64_t num = 0; for (; *str != '\0'; str++) { if (*str == '-') sign = -sign; else num = num * 10 + (*str - '0'); } return num * sign; } /* Guacamole instruction handlers */ int __guac_handle_sync(guac_user* user, int argc, char** argv) { int frame_duration; guac_timestamp current = guac_timestamp_current(); guac_timestamp timestamp = __guac_parse_int(argv[0]); /* Error if timestamp is in future */ if (timestamp > user->client->last_sent_timestamp) return -1; /* Only update lag calculations if timestamp is sane */ if (timestamp >= user->last_received_timestamp) { /* Update stored timestamp */ user->last_received_timestamp = timestamp; /* Calculate length of frame, including network and processing lag */ frame_duration = current - timestamp; /* Update lag statistics if at least one frame has been rendered */ if (user->last_frame_duration != 0) { /* Calculate lag using the previous frame as a baseline */ int processing_lag = frame_duration - user->last_frame_duration; /* Adjust back to zero if cumulative error leads to a negative * value */ if (processing_lag < 0) processing_lag = 0; user->processing_lag = processing_lag; } /* Record baseline duration of frame by excluding lag */ user->last_frame_duration = frame_duration - user->processing_lag; } /* Log received timestamp and calculated lag (at TRACE level only) */ guac_user_log(user, GUAC_LOG_TRACE, "User confirmation of frame %" PRIu64 "ms received " "at %" PRIu64 "ms (processing_lag=%ims)", timestamp, current, user->processing_lag); if (user->sync_handler) return user->sync_handler(user, timestamp); return 0; } int __guac_handle_mouse(guac_user* user, int argc, char** argv) { if (user->mouse_handler) return user->mouse_handler( user, atoi(argv[0]), /* x */ atoi(argv[1]), /* y */ atoi(argv[2]) /* mask */ ); return 0; } int __guac_handle_key(guac_user* user, int argc, char** argv) { if (user->key_handler) return user->key_handler( user, atoi(argv[0]), /* keysym */ atoi(argv[1]) /* pressed */ ); return 0; } /** * Retrieves the existing user-level input stream having the given index. These * will be streams which were created by the remotely-connected user. If the * index is invalid or too large, this function will automatically respond with * an "ack" instruction containing an appropriate error code. * * @param user * The user associated with the stream being retrieved. * * @param stream_index * The index of the stream to retrieve. * * @return * The stream associated with the given user and having the given index, * or NULL if the index is invalid. */ static guac_stream* __get_input_stream(guac_user* user, int stream_index) { /* Validate stream index */ if (stream_index < 0 || stream_index >= GUAC_USER_MAX_STREAMS) { guac_stream dummy_stream; dummy_stream.index = stream_index; guac_protocol_send_ack(user->socket, &dummy_stream, "Invalid stream index", GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST); return NULL; } return &(user->__input_streams[stream_index]); } /** * Retrieves the existing, in-progress (open) user-level input stream having * the given index. These will be streams which were created by the * remotely-connected user. If the index is invalid, too large, or the stream * is closed, this function will automatically respond with an "ack" * instruction containing an appropriate error code. * * @param user * The user associated with the stream being retrieved. * * @param stream_index * The index of the stream to retrieve. * * @return * The in-progress (open)stream associated with the given user and having * the given index, or NULL if the index is invalid or the stream is * closed. */ static guac_stream* __get_open_input_stream(guac_user* user, int stream_index) { guac_stream* stream = __get_input_stream(user, stream_index); /* Fail if no such stream */ if (stream == NULL) return NULL; /* Validate initialization of stream */ if (stream->index == GUAC_USER_CLOSED_STREAM_INDEX) { guac_stream dummy_stream; dummy_stream.index = stream_index; guac_protocol_send_ack(user->socket, &dummy_stream, "Invalid stream index", GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST); return NULL; } return stream; } /** * Initializes and returns a new user-level input stream having the given * index, clearing any values that may have been assigned by a past use of the * underlying stream object storage. If the stream was already open, it will * first be closed and its end handlers invoked as if explicitly closed by the * user. * * @param user * The user associated with the stream being initialized. * * @param stream_index * The index of the stream to initialized. * * @return * A new initialized user-level input stream having the given index, or * NULL if the index is invalid. */ static guac_stream* __init_input_stream(guac_user* user, int stream_index) { guac_stream* stream = __get_input_stream(user, stream_index); /* Fail if no such stream */ if (stream == NULL) return NULL; /* Force end of previous stream if open */ if (stream->index != GUAC_USER_CLOSED_STREAM_INDEX) { /* Call stream handler if defined */ if (stream->end_handler) stream->end_handler(user, stream); /* Fall back to global handler if defined */ else if (user->end_handler) user->end_handler(user, stream); } /* Initialize stream */ stream->index = stream_index; stream->data = NULL; stream->ack_handler = NULL; stream->blob_handler = NULL; stream->end_handler = NULL; return stream; } int __guac_handle_audio(guac_user* user, int argc, char** argv) { /* Pull corresponding stream */ int stream_index = atoi(argv[0]); guac_stream* stream = __init_input_stream(user, stream_index); if (stream == NULL) return 0; /* If supported, call handler */ if (user->audio_handler) return user->audio_handler( user, stream, argv[1] /* mimetype */ ); /* Otherwise, abort */ guac_protocol_send_ack(user->socket, stream, "Audio input unsupported", GUAC_PROTOCOL_STATUS_UNSUPPORTED); return 0; } int __guac_handle_clipboard(guac_user* user, int argc, char** argv) { /* Pull corresponding stream */ int stream_index = atoi(argv[0]); guac_stream* stream = __init_input_stream(user, stream_index); if (stream == NULL) return 0; /* If supported, call handler */ if (user->clipboard_handler) return user->clipboard_handler( user, stream, argv[1] /* mimetype */ ); /* Otherwise, abort */ guac_protocol_send_ack(user->socket, stream, "Clipboard unsupported", GUAC_PROTOCOL_STATUS_UNSUPPORTED); return 0; } int __guac_handle_size(guac_user* user, int argc, char** argv) { if (user->size_handler) return user->size_handler( user, atoi(argv[0]), /* width */ atoi(argv[1]) /* height */ ); return 0; } int __guac_handle_file(guac_user* user, int argc, char** argv) { /* Pull corresponding stream */ int stream_index = atoi(argv[0]); guac_stream* stream = __init_input_stream(user, stream_index); if (stream == NULL) return 0; /* If supported, call handler */ if (user->file_handler) return user->file_handler( user, stream, argv[1], /* mimetype */ argv[2] /* filename */ ); /* Otherwise, abort */ guac_protocol_send_ack(user->socket, stream, "File transfer unsupported", GUAC_PROTOCOL_STATUS_UNSUPPORTED); return 0; } int __guac_handle_pipe(guac_user* user, int argc, char** argv) { /* Pull corresponding stream */ int stream_index = atoi(argv[0]); guac_stream* stream = __init_input_stream(user, stream_index); if (stream == NULL) return 0; /* If supported, call handler */ if (user->pipe_handler) return user->pipe_handler( user, stream, argv[1], /* mimetype */ argv[2] /* name */ ); /* Otherwise, abort */ guac_protocol_send_ack(user->socket, stream, "Named pipes unsupported", GUAC_PROTOCOL_STATUS_UNSUPPORTED); return 0; } int __guac_handle_argv(guac_user* user, int argc, char** argv) { /* Pull corresponding stream */ int stream_index = atoi(argv[0]); guac_stream* stream = __init_input_stream(user, stream_index); if (stream == NULL) return 0; /* If supported, call handler */ if (user->argv_handler) return user->argv_handler( user, stream, argv[1], /* mimetype */ argv[2] /* name */ ); /* Otherwise, abort */ guac_protocol_send_ack(user->socket, stream, "Reconfiguring in-progress connections unsupported", GUAC_PROTOCOL_STATUS_UNSUPPORTED); return 0; } int __guac_handle_ack(guac_user* user, int argc, char** argv) { guac_stream* stream; /* Parse stream index */ int stream_index = atoi(argv[0]); /* Ignore indices of client-level streams */ if (stream_index % 2 != 0) return 0; /* Determine index within user-level array of streams */ stream_index /= 2; /* Validate stream index */ if (stream_index < 0 || stream_index >= GUAC_USER_MAX_STREAMS) return 0; stream = &(user->__output_streams[stream_index]); /* Validate initialization of stream */ if (stream->index == GUAC_USER_CLOSED_STREAM_INDEX) return 0; /* Call stream handler if defined */ if (stream->ack_handler) return stream->ack_handler(user, stream, argv[1], atoi(argv[2])); /* Fall back to global handler if defined */ if (user->ack_handler) return user->ack_handler(user, stream, argv[1], atoi(argv[2])); return 0; } int __guac_handle_blob(guac_user* user, int argc, char** argv) { int stream_index = atoi(argv[0]); guac_stream* stream = __get_open_input_stream(user, stream_index); /* Fail if no such stream */ if (stream == NULL) return 0; /* Call stream handler if defined */ if (stream->blob_handler) { int length = guac_protocol_decode_base64(argv[1]); return stream->blob_handler(user, stream, argv[1], length); } /* Fall back to global handler if defined */ if (user->blob_handler) { int length = guac_protocol_decode_base64(argv[1]); return user->blob_handler(user, stream, argv[1], length); } guac_protocol_send_ack(user->socket, stream, "File transfer unsupported", GUAC_PROTOCOL_STATUS_UNSUPPORTED); return 0; } int __guac_handle_end(guac_user* user, int argc, char** argv) { int result = 0; int stream_index = atoi(argv[0]); guac_stream* stream = __get_open_input_stream(user, stream_index); /* Fail if no such stream */ if (stream == NULL) return 0; /* Call stream handler if defined */ if (stream->end_handler) result = stream->end_handler(user, stream); /* Fall back to global handler if defined */ else if (user->end_handler) result = user->end_handler(user, stream); /* Mark stream as closed */ stream->index = GUAC_USER_CLOSED_STREAM_INDEX; return result; } int __guac_handle_get(guac_user* user, int argc, char** argv) { guac_object* object; /* Validate object index */ int object_index = atoi(argv[0]); if (object_index < 0 || object_index >= GUAC_USER_MAX_OBJECTS) return 0; object = &(user->__objects[object_index]); /* Validate initialization of object */ if (object->index == GUAC_USER_UNDEFINED_OBJECT_INDEX) return 0; /* Call object handler if defined */ if (object->get_handler) return object->get_handler( user, object, argv[1] /* name */ ); /* Fall back to global handler if defined */ if (user->get_handler) return user->get_handler( user, object, argv[1] /* name */ ); return 0; } int __guac_handle_put(guac_user* user, int argc, char** argv) { guac_object* object; /* Validate object index */ int object_index = atoi(argv[0]); if (object_index < 0 || object_index >= GUAC_USER_MAX_OBJECTS) return 0; object = &(user->__objects[object_index]); /* Validate initialization of object */ if (object->index == GUAC_USER_UNDEFINED_OBJECT_INDEX) return 0; /* Pull corresponding stream */ int stream_index = atoi(argv[1]); guac_stream* stream = __init_input_stream(user, stream_index); if (stream == NULL) return 0; /* Call object handler if defined */ if (object->put_handler) return object->put_handler( user, object, stream, argv[2], /* mimetype */ argv[3] /* name */ ); /* Fall back to global handler if defined */ if (user->put_handler) return user->put_handler( user, object, stream, argv[2], /* mimetype */ argv[3] /* name */ ); /* Otherwise, abort */ guac_protocol_send_ack(user->socket, stream, "Object write unsupported", GUAC_PROTOCOL_STATUS_UNSUPPORTED); return 0; } int __guac_handle_nop(guac_user* user, int argc, char** argv) { guac_user_log(user, GUAC_LOG_TRACE, "Received nop instruction"); return 0; } int __guac_handle_disconnect(guac_user* user, int argc, char** argv) { guac_user_stop(user); return 0; } /* Guacamole handshake handler functions. */ int __guac_handshake_size_handler(guac_user* user, int argc, char** argv) { /* Validate size of instruction. */ if (argc < 2) { guac_user_log(user, GUAC_LOG_ERROR, "Received \"size\" " "instruction lacked required arguments."); return 1; } /* Parse optimal screen dimensions from size instruction */ user->info.optimal_width = atoi(argv[0]); user->info.optimal_height = atoi(argv[1]); /* If DPI given, set the user resolution */ if (argc >= 3) user->info.optimal_resolution = atoi(argv[2]); /* Otherwise, use a safe default for rough backwards compatibility */ else user->info.optimal_resolution = 96; return 0; } int __guac_handshake_audio_handler(guac_user* user, int argc, char** argv) { guac_free_mimetypes((char **) user->info.audio_mimetypes); /* Store audio mimetypes */ user->info.audio_mimetypes = (const char**) guac_copy_mimetypes(argv, argc); return 0; } int __guac_handshake_video_handler(guac_user* user, int argc, char** argv) { guac_free_mimetypes((char **) user->info.video_mimetypes); /* Store video mimetypes */ user->info.video_mimetypes = (const char**) guac_copy_mimetypes(argv, argc); return 0; } int __guac_handshake_image_handler(guac_user* user, int argc, char** argv) { guac_free_mimetypes((char **) user->info.image_mimetypes); /* Store image mimetypes */ user->info.image_mimetypes = (const char**) guac_copy_mimetypes(argv, argc); return 0; } int __guac_handshake_timezone_handler(guac_user* user, int argc, char** argv) { /* Free any past value */ free((char *) user->info.timezone); /* Store timezone, if present */ if (argc > 0 && strcmp(argv[0], "")) user->info.timezone = (const char*) strdup(argv[0]); else user->info.timezone = NULL; return 0; } char** guac_copy_mimetypes(char** mimetypes, int count) { int i; /* Allocate sufficient space for NULL-terminated array of mimetypes */ char** mimetypes_copy = malloc(sizeof(char*) * (count+1)); /* Copy each provided mimetype */ for (i = 0; i < count; i++) mimetypes_copy[i] = strdup(mimetypes[i]); /* Terminate with NULL */ mimetypes_copy[count] = NULL; return mimetypes_copy; } void guac_free_mimetypes(char** mimetypes) { if (mimetypes == NULL) return; char** current_mimetype = mimetypes; /* Free all strings within NULL-terminated mimetype array */ while (*current_mimetype != NULL) { free(*current_mimetype); current_mimetype++; } /* Free the array itself, now that its contents have been freed */ free(mimetypes); } int __guac_user_call_opcode_handler(__guac_instruction_handler_mapping* map, guac_user* user, const char* opcode, int argc, char** argv) { /* For each defined instruction */ __guac_instruction_handler_mapping* current = map; while (current->opcode != NULL) { /* If recognized, call handler */ if (strcmp(opcode, current->opcode) == 0) return current->handler(user, argc, argv); current++; } /* If unrecognized, log and ignore */ guac_user_log(user, GUAC_LOG_DEBUG, "Handler not found for \"%s\"", opcode); return 0; } guacamole-server-1.3.0/src/libguac/pool.c0000644000175100001440000000656013764613616015230 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/pool.h" #include guac_pool* guac_pool_alloc(int size) { pthread_mutexattr_t lock_attributes; guac_pool* pool = malloc(sizeof(guac_pool)); /* If unable to allocate, just return NULL. */ if (pool == NULL) return NULL; /* Initialize empty pool */ pool->min_size = size; pool->active = 0; pool->__next_value = 0; pool->__head = NULL; pool->__tail = NULL; /* Init lock */ pthread_mutexattr_init(&lock_attributes); pthread_mutexattr_setpshared(&lock_attributes, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&(pool->__lock), &lock_attributes); return pool; } void guac_pool_free(guac_pool* pool) { /* Free all ints in pool */ guac_pool_int* current = pool->__head; while (current != NULL) { guac_pool_int* old = current; current = current->__next; free(old); } /* Destroy lock */ pthread_mutex_destroy(&(pool->__lock)); /* Free pool */ free(pool); } int guac_pool_next_int(guac_pool* pool) { int value; /* Acquire exclusive access */ pthread_mutex_lock(&(pool->__lock)); pool->active++; /* If more integers are needed, return a new one. */ if (pool->__head == NULL || pool->__next_value < pool->min_size) { value = pool->__next_value++; pthread_mutex_unlock(&(pool->__lock)); return value; } /* Otherwise, remove first integer. */ value = pool->__head->value; /* If only one element exists, reset pool to empty. */ if (pool->__tail == pool->__head) { free(pool->__head); pool->__head = NULL; pool->__tail = NULL; } /* Otherwise, advance head. */ else { guac_pool_int* old_head = pool->__head; pool->__head = old_head->__next; free(old_head); } /* Return retrieved value. */ pthread_mutex_unlock(&(pool->__lock)); return value; } void guac_pool_free_int(guac_pool* pool, int value) { /* Allocate and initialize new returned value */ guac_pool_int* pool_int = malloc(sizeof(guac_pool_int)); pool_int->value = value; pool_int->__next = NULL; /* Acquire exclusive access */ pthread_mutex_lock(&(pool->__lock)); pool->active--; /* If pool empty, store as sole entry. */ if (pool->__tail == NULL) pool->__head = pool->__tail = pool_int; /* Otherwise, append to end of pool. */ else { pool->__tail->__next = pool_int; pool->__tail = pool_int; } /* Value has been freed */ pthread_mutex_unlock(&(pool->__lock)); } guacamole-server-1.3.0/src/libguac/socket-nest.c0000644000175100001440000002314013764613616016507 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacamole/protocol.h" #include "guacamole/socket.h" #include "guacamole/unicode.h" #include #include #include #include /** * The maximum number of bytes to buffer before sending a "nest" instruction. * As some of the 8 KB space available for each instruction will be taken up by * the "nest" opcode and other parameters, and 1 KB will be more than enough * space for that extra data, this space is reduced to an even 7 KB. */ #define GUAC_SOCKET_NEST_BUFFER_SIZE 7168 /** * Internal data associated with an open socket which writes via a series of * "nest" instructions to some underlying, parent socket. */ typedef struct guac_socket_nest_data { /** * The underlying socket which should be used to write "nest" instructions. */ guac_socket* parent; /** * The arbitrary index of the nested socket, assigned at time of * allocation. */ int index; /** * The number of bytes currently in the main write buffer. */ int written; /** * The main write buffer. Bytes written go here before being flushed * as nest instructions. Space is included for the null terminator * required by guac_protocol_send_nest(). */ char buffer[GUAC_SOCKET_NEST_BUFFER_SIZE]; /** * Lock which is acquired when an instruction is being written, and * released when the instruction is finished being written. */ pthread_mutex_t socket_lock; /** * Lock which protects access to the internal buffer of this socket, * guaranteeing atomicity of writes and flushes. */ pthread_mutex_t buffer_lock; } guac_socket_nest_data; /** * Flushes the contents of the output buffer of the given socket immediately, * without first locking access to the output buffer. This function must ONLY * be called if the buffer lock has already been acquired. * * @param socket * The guac_socket to flush. * * @return * Zero if the flush operation was successful, non-zero otherwise. */ static ssize_t guac_socket_nest_flush(guac_socket* socket) { guac_socket_nest_data* data = (guac_socket_nest_data*) socket->data; /* Flush remaining bytes in buffer */ if (data->written > 0) { /* Determine length of buffer containing complete UTF-8 characters * (buffer may end with a partial, multi-byte character) */ int length = 0; while (length < data->written) length += guac_utf8_charsize(*(data->buffer + length)); /* Add null terminator, preserving overwritten character for later * restoration (guac_protocol_send_nest() requires null-terminated * strings) */ char overwritten = data->buffer[length]; data->buffer[length] = '\0'; /* Write ALL bytes in buffer as nest instruction */ int retval = guac_protocol_send_nest(data->parent, data->index, data->buffer); /* Restore original value overwritten by null terminator */ data->buffer[length] = overwritten; if (retval) return 1; /* Shift any remaining data to beginning of buffer */ memcpy(data->buffer, data->buffer + length, data->written - length); data->written -= length; } return 0; } /** * Flushes the internal buffer of the given guac_socket, writing all data * to the underlying socket using "nest" instructions. * * @param socket * The guac_socket to flush. * * @return * Zero if the flush operation was successful, non-zero otherwise. */ static ssize_t guac_socket_nest_flush_handler(guac_socket* socket) { int retval; guac_socket_nest_data* data = (guac_socket_nest_data*) socket->data; /* Acquire exclusive access to buffer */ pthread_mutex_lock(&(data->buffer_lock)); /* Flush contents of buffer */ retval = guac_socket_nest_flush(socket); /* Relinquish exclusive access to buffer */ pthread_mutex_unlock(&(data->buffer_lock)); return retval; } /** * Writes the contents of the buffer to the output buffer of the given socket, * flushing the output buffer as necessary, without first locking access to the * output buffer. This function must ONLY be called if the buffer lock has * already been acquired. * * @param socket * The guac_socket to write the given buffer to. * * @param buf * The buffer to write to the given socket. * * @param count * The number of bytes in the given buffer. * * @return * The number of bytes written, or a negative value if an error occurs * during write. */ static ssize_t guac_socket_nest_write_buffered(guac_socket* socket, const void* buf, size_t count) { size_t original_count = count; const char* current = buf; guac_socket_nest_data* data = (guac_socket_nest_data*) socket->data; /* Append to buffer, flush if necessary */ while (count > 0) { int chunk_size; /* Calculate space remaining, including one extra byte for the null * terminator added upon flush */ int remaining = sizeof(data->buffer) - data->written - 1; /* If no space left in buffer, flush and retry */ if (remaining == 0) { /* Abort if error occurs during flush */ if (guac_socket_nest_flush(socket)) return -1; /* Retry buffer append */ continue; } /* Calculate size of chunk to be written to buffer */ chunk_size = count; if (chunk_size > remaining) chunk_size = remaining; /* Update output buffer */ memcpy(data->buffer + data->written, current, chunk_size); data->written += chunk_size; /* Update provided buffer */ current += chunk_size; count -= chunk_size; } /* All bytes have been written, possibly some to the internal buffer */ return original_count; } /** * Appends the provided data to the internal buffer for future writing. The * actual write attempt will occur only upon flush, or when the internal buffer * is full. * * @param socket * The guac_socket being write to. * * @param buf * The arbitrary buffer containing the data to be written. * * @param count * The number of bytes contained within the buffer. * * @return * The number of bytes written, or -1 if an error occurs. */ static ssize_t guac_socket_nest_write_handler(guac_socket* socket, const void* buf, size_t count) { int retval; guac_socket_nest_data* data = (guac_socket_nest_data*) socket->data; /* Acquire exclusive access to buffer */ pthread_mutex_lock(&(data->buffer_lock)); /* Write provided data to buffer */ retval = guac_socket_nest_write_buffered(socket, buf, count); /* Relinquish exclusive access to buffer */ pthread_mutex_unlock(&(data->buffer_lock)); return retval; } /** * Frees all implementation-specific data associated with the given socket, but * not the socket object itself. * * @param socket * The guac_socket whose associated data should be freed. * * @return * Zero if the data was successfully freed, non-zero otherwise. This * implementation always succeeds, and will always return zero. */ static int guac_socket_nest_free_handler(guac_socket* socket) { /* Free associated data */ guac_socket_nest_data* data = (guac_socket_nest_data*) socket->data; free(data); return 0; } /** * Acquires exclusive access to the given socket. * * @param socket * The guac_socket to which exclusive access is required. */ static void guac_socket_nest_lock_handler(guac_socket* socket) { guac_socket_nest_data* data = (guac_socket_nest_data*) socket->data; /* Acquire exclusive access to socket */ pthread_mutex_lock(&(data->socket_lock)); } /** * Relinquishes exclusive access to the given socket. * * @param socket * The guac_socket to which exclusive access is no longer required. */ static void guac_socket_nest_unlock_handler(guac_socket* socket) { guac_socket_nest_data* data = (guac_socket_nest_data*) socket->data; /* Relinquish exclusive access to socket */ pthread_mutex_unlock(&(data->socket_lock)); } guac_socket* guac_socket_nest(guac_socket* parent, int index) { /* Allocate socket and associated data */ guac_socket* socket = guac_socket_alloc(); guac_socket_nest_data* data = malloc(sizeof(guac_socket_nest_data)); /* Store nested socket details as socket data */ data->parent = parent; data->index = index; socket->data = data; /* Set relevant handlers */ socket->write_handler = guac_socket_nest_write_handler; socket->lock_handler = guac_socket_nest_lock_handler; socket->unlock_handler = guac_socket_nest_unlock_handler; socket->flush_handler = guac_socket_nest_flush_handler; socket->free_handler = guac_socket_nest_free_handler; return socket; } guacamole-server-1.3.0/src/libguac/Makefile.am0000644000175100001440000001111013770536337016133 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac.la SUBDIRS = . tests libguacincdir = $(includedir)/guacamole libguacinc_HEADERS = \ guacamole/argv.h \ guacamole/argv-constants.h \ guacamole/argv-fntypes.h \ guacamole/audio.h \ guacamole/audio-fntypes.h \ guacamole/audio-types.h \ guacamole/client-constants.h \ guacamole/client.h \ guacamole/client-fntypes.h \ guacamole/client-types.h \ guacamole/error.h \ guacamole/error-types.h \ guacamole/hash.h \ guacamole/layer.h \ guacamole/layer-types.h \ guacamole/object.h \ guacamole/object-types.h \ guacamole/parser-constants.h \ guacamole/parser.h \ guacamole/parser-types.h \ guacamole/plugin-constants.h \ guacamole/plugin.h \ guacamole/pool.h \ guacamole/pool-types.h \ guacamole/protocol.h \ guacamole/protocol-constants.h \ guacamole/protocol-types.h \ guacamole/socket-constants.h \ guacamole/socket.h \ guacamole/socket-fntypes.h \ guacamole/socket-types.h \ guacamole/stream.h \ guacamole/stream-types.h \ guacamole/string.h \ guacamole/timestamp.h \ guacamole/timestamp-types.h \ guacamole/unicode.h \ guacamole/user.h \ guacamole/user-constants.h \ guacamole/user-fntypes.h \ guacamole/user-types.h \ guacamole/wol.h \ guacamole/wol-constants.h noinst_HEADERS = \ id.h \ encode-jpeg.h \ encode-png.h \ palette.h \ user-handlers.h \ raw_encoder.h \ wait-fd.h libguac_la_SOURCES = \ argv.c \ audio.c \ client.c \ encode-jpeg.c \ encode-png.c \ error.c \ hash.c \ id.c \ palette.c \ parser.c \ pool.c \ protocol.c \ raw_encoder.c \ socket.c \ socket-broadcast.c \ socket-fd.c \ socket-nest.c \ socket-tee.c \ string.c \ timestamp.c \ unicode.c \ user.c \ user-handlers.c \ user-handshake.c \ wait-fd.c \ wol.c # Compile WebP support if available if ENABLE_WEBP libguac_la_SOURCES += encode-webp.c noinst_HEADERS += encode-webp.h endif # SSL support if ENABLE_SSL libguac_la_SOURCES += socket-ssl.c libguacinc_HEADERS += guacamole/socket-ssl.h endif # Winsock support if ENABLE_WINSOCK libguac_la_SOURCES += socket-wsa.c libguacinc_HEADERS += guacamole/socket-wsa.h endif libguac_la_CFLAGS = \ -Werror -Wall -pedantic libguac_la_LDFLAGS = \ -version-info 19:0:0 \ -no-undefined \ @CAIRO_LIBS@ \ @DL_LIBS@ \ @JPEG_LIBS@ \ @PNG_LIBS@ \ @PTHREAD_LIBS@ \ @SSL_LIBS@ \ @UUID_LIBS@ \ @VORBIS_LIBS@ \ @WEBP_LIBS@ \ @WINSOCK_LIBS@ guacamole-server-1.3.0/src/guacenc/0000755000175100001440000000000013772471157014164 500000000000000guacamole-server-1.3.0/src/guacenc/guacenc.h0000644000175100001440000000316413613156714015657 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_H #define GUACENC_H #include "config.h" #include /** * The width of the output video, in pixels, if no other width is given on the * command line. Note that different codecs will have different restrictions * regarding legal widths. */ #define GUACENC_DEFAULT_WIDTH 640 /** * The height of the output video, in pixels, if no other height is given on the * command line. Note that different codecs will have different restrictions * regarding legal heights. */ #define GUACENC_DEFAULT_HEIGHT 480 /** * The desired bitrate of the output video, in bits per second, if no other * bitrate is given on the command line. */ #define GUACENC_DEFAULT_BITRATE 2000000 /** * The default log level below which no messages should be logged. */ #define GUACENC_DEFAULT_LOG_LEVEL GUAC_LOG_INFO #endif guacamole-server-1.3.0/src/guacenc/instruction-shade.c0000644000175100001440000000267613613156714017717 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "log.h" #include #include int guacenc_handle_shade(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 2) { guacenc_log(GUAC_LOG_WARNING, "\"shade\" instruction incomplete"); return 1; } /* Parse arguments */ int index = atoi(argv[0]); int opacity = atoi(argv[1]); /* Retrieve requested layer */ guacenc_layer* layer = guacenc_display_get_layer(display, index); if (layer == NULL) return 1; /* Update layer properties */ layer->opacity = opacity; return 0; } guacamole-server-1.3.0/src/guacenc/instruction-size.c0000644000175100001440000000276513676721354017613 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "log.h" #include #include int guacenc_handle_size(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 3) { guacenc_log(GUAC_LOG_WARNING, "\"size\" instruction incomplete"); return 1; } /* Parse arguments */ int index = atoi(argv[0]); int width = atoi(argv[1]); int height = atoi(argv[2]); /* Retrieve requested layer/buffer */ guacenc_buffer* buffer = guacenc_display_get_related_buffer(display, index); if (buffer == NULL) return 1; /* Resize layer/buffer */ return guacenc_buffer_resize(buffer, width, height); } guacamole-server-1.3.0/src/guacenc/instruction-dispose.c0000644000175100001440000000264413613156714020274 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "log.h" #include #include int guacenc_handle_dispose(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 1) { guacenc_log(GUAC_LOG_WARNING, "\"dispose\" instruction incomplete"); return 1; } /* Parse arguments */ int index = atoi(argv[0]); /* If non-negative, dispose of layer */ if (index >= 0) return guacenc_display_free_layer(display, index); /* Otherwise, we're referring to a buffer */ return guacenc_display_free_buffer(display, index); } guacamole-server-1.3.0/src/guacenc/png.h0000644000175100001440000000176713613156714015045 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_PNG_H #define GUACENC_PNG_H #include "config.h" #include "image-stream.h" /** * Decoder implementation which handles "image/png" images. */ guacenc_decoder guacenc_png_decoder; #endif guacamole-server-1.3.0/src/guacenc/image-stream.h0000644000175100001440000001575713613156714016640 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_IMAGE_STREAM_H #define GUACENC_IMAGE_STREAM_H #include "config.h" #include "buffer.h" #include /** * The initial number of bytes to allocate for the image data buffer. If this * buffer is not sufficiently large, it will be dynamically reallocated as it * grows. */ #define GUACENC_IMAGE_STREAM_INITIAL_LENGTH 4096 /** * Callback function which is provided raw, encoded image data of the given * length. The function is expected to return a new Cairo surface which will * later (by guacenc) be freed via cairo_surface_destroy(). * * @param data * The raw encoded image data that this function must decode. * * @param length * The length of the image data, in bytes. * * @return * A newly-allocated Cairo surface containing the decoded image, or NULL * or decoding fails. */ typedef cairo_surface_t* guacenc_decoder(unsigned char* data, int length); /** * The current state of an allocated Guacamole image stream. */ typedef struct guacenc_image_stream { /** * The index of the destination layer or buffer. */ int index; /** * The Guacamole protocol compositing operation (channel mask) to apply * when drawing the image. */ int mask; /** * The X coordinate of the upper-left corner of the rectangle within the * destination layer or buffer that the decoded image should be drawn to. */ int x; /** * The Y coordinate of the upper-left corner of the rectangle within the * destination layer or buffer that the decoded image should be drawn to. */ int y; /** * Buffer of image data which will be built up over time as chunks are * received via "blob" instructions. This will ultimately be passed in its * entirety to the decoder function. */ unsigned char* buffer; /** * The number of bytes currently stored in the buffer. */ int length; /** * The maximum number of bytes that can be stored in the current buffer * before it must be reallocated. */ int max_length; /** * The decoder to use when decoding the raw data received along this * stream, or NULL if no such decoder exists. */ guacenc_decoder* decoder; } guacenc_image_stream; /** * Mapping of image mimetype to corresponding decoder function. */ typedef struct guacenc_decoder_mapping { /** * The mimetype of the image that the associated decoder can read. */ const char* mimetype; /** * The decoder function to use when an image stream of the associated * mimetype is received. */ guacenc_decoder* decoder; } guacenc_decoder_mapping; /** * Array of all mimetype/decoder mappings for all supported image types, * terminated by an entry with a NULL mimetype. */ extern guacenc_decoder_mapping guacenc_decoder_map[]; /** * Returns the decoder associated with the given mimetype. If no such decoder * exists, NULL is returned. * * @param mimetype * The image mimetype to return the associated decoder of. * * @return * The decoder associated with the given mimetype, or NULL if no such * decoder exists. */ guacenc_decoder* guacenc_get_decoder(const char* mimetype); /** * Allocates and initializes a new image stream. This allocation is independent * of the Guacamole video encoder display; the allocated guacenc_image_stream * will not automatically be associated with the active display, nor will the * provided layer/buffer index be validated. * * @param mask * The Guacamole protocol compositing operation (channel mask) to apply * when drawing the image. * * @param index * The index of the layer or buffer that the image should be drawn to. * * @param mimetype * The mimetype of the image data that will be received along this stream. * * @param x * The X coordinate of the upper-left corner of the rectangle within the * destination layer or buffer that the image should be drawn to. * * @param y * The Y coordinate of the upper-left corner of the rectangle within the * destination layer or buffer that the image should be drawn to. * * @return * A newly-allocated and initialized guacenc_image_stream, or NULL if * allocation fails. */ guacenc_image_stream* guacenc_image_stream_alloc(int mask, int index, const char* mimetype, int x, int y); /** * Appends newly-received data to the internal buffer of the given image * stream, such that the entire received image can be fed to the decoder as one * buffer once the stream ends. * * @param stream * The image stream that received the data. * * @param data * The chunk of data received along the image stream. * * @param length * The length of the chunk of data received, in bytes. * * @return * Zero if the given data was successfully appended to the in-progress * image, non-zero if an error occurs. */ int guacenc_image_stream_receive(guacenc_image_stream* stream, unsigned char* data, int length); /** * Marks the end of the given image stream (no more data will be received) and * invokes the associated decoder. The decoded image will be written to the * given buffer as-is. If no decoder is associated with the given image stream, * this function has no effect. Meta-information describing the image draw * operation itself is pulled from the guacenc_image_stream, having been stored * there when the image stream was created. * * @param stream * The image stream that has ended. * * @param buffer * The buffer that the decoded image should be written to. * * @return * Zero if the image is written successfully, or non-zero if an error * occurs. */ int guacenc_image_stream_end(guacenc_image_stream* stream, guacenc_buffer* buffer); /** * Frees the given image stream and all associated data. If the image stream * has not yet ended (reached end-of-stream), no image will be drawn to the * associated buffer or layer. * * @param stream * The stream to free. * * @return * Zero if freeing the stream succeeded, or non-zero if freeing the stream * failed (for example, due to an error in the free handler of the * decoder). */ int guacenc_image_stream_free(guacenc_image_stream* stream); #endif guacamole-server-1.3.0/src/guacenc/webp.c0000644000175100001440000000443513613156714015204 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "log.h" #include "webp.h" #include #include #include #include #include cairo_surface_t* guacenc_webp_decoder(unsigned char* data, int length) { int width, height; /* Validate WebP and pull dimensions */ if (!WebPGetInfo((uint8_t*) data, length, &width, &height)) { guacenc_log(GUAC_LOG_WARNING, "Invalid WebP data"); return NULL; } /* Create blank Cairo surface */ cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); /* Fill surface with opaque black */ cairo_t* cairo = cairo_create(surface); cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba(cairo, 0.0, 0.0, 0.0, 1.0); cairo_paint(cairo); cairo_destroy(cairo); /* Finish any pending draws */ cairo_surface_flush(surface); /* Pull underlying buffer and its stride */ int stride = cairo_image_surface_get_stride(surface); unsigned char* image = cairo_image_surface_get_data(surface); /* Read WebP into surface */ uint8_t* result = WebPDecodeBGRAInto((uint8_t*) data, length, (uint8_t*) image, stride * height, stride); /* Verify WebP was successfully decoded */ if (result == NULL) { guacenc_log(GUAC_LOG_WARNING, "Invalid WebP data"); cairo_surface_destroy(surface); return NULL; } /* WebP was read successfully */ return surface; } guacamole-server-1.3.0/src/guacenc/cursor.h0000644000175100001440000000443113702142276015562 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_CURSOR_H #define GUACENC_CURSOR_H #include "config.h" #include "buffer.h" #include #include /** * A mouse cursor, having a current location, hostspot, and associated cursor * image. */ typedef struct guacenc_cursor { /** * The current X coordinate of the mouse cursor, in pixels. Valid values * are non-negative. Negative values indicate that the cursor should not * be rendered. */ int x; /** * The current Y coordinate of the mouse cursor, in pixels. Valid values * are non-negative. Negative values indicate that the cursor should not * be rendered. */ int y; /** * The X coordinate of the mouse cursor hotspot within the cursor image, * in pixels. */ int hotspot_x; /** * The Y coordinate of the mouse cursor hotspot within the cursor image, * in pixels. */ int hotspot_y; /** * The current mouse cursor image. */ guacenc_buffer* buffer; } guacenc_cursor; /** * Allocates and initializes a new cursor object. * * @return * A newly-allocated and initialized guacenc_cursor, or NULL if allocation * fails. */ guacenc_cursor* guacenc_cursor_alloc(); /** * Frees all memory associated with the given cursor object. If the cursor * provided is NULL, this function has no effect. * * @param cursor * The cursor to free, which may be NULL. */ void guacenc_cursor_free(guacenc_cursor* cursor); #endif guacamole-server-1.3.0/src/guacenc/instructions.h0000644000175100001440000001132613702142276017012 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_INSTRUCTIONS_H #define GUACENC_INSTRUCTIONS_H #include "config.h" #include "display.h" /** * A callback function which, when invoked, handles a particular Guacamole * instruction. The opcode of the instruction is implied (as it is expected * that there will be a 1:1 mapping of opcode to callback function), while the * arguments for that instruction are included in the parameters given to the * callback. * * @param display * The current internal display of the Guacamole video encoder. * * @param argc * The number of arguments (excluding opcode) passed to the instruction * being handled by the callback. * * @param argv * All arguments (excluding opcode) associated with the instruction being * handled by the callback. * * @return * Zero if the instruction was handled successfully, non-zero if an error * occurs. */ typedef int guacenc_instruction_handler(guacenc_display* display, int argc, char** argv); /** * Mapping of instruction opcode to corresponding handler function. */ typedef struct guacenc_instruction_handler_mapping { /** * The opcode of the instruction that the associated handler function * should be invoked for. */ const char* opcode; /** * The handler function to invoke whenever an instruction having the * associated opcode is parsed. */ guacenc_instruction_handler* handler; } guacenc_instruction_handler_mapping; /** * Array of all opcode/handler mappings for all supported opcodes, terminated * by an entry with a NULL opcode. All opcodes not listed here can be safely * ignored. */ extern guacenc_instruction_handler_mapping guacenc_instruction_handler_map[]; /** * Handles the instruction having the given opcode and arguments, encoding the * result to the in-progress video. * * @param display * The current internal display of the Guacamole video encoder. * * @param opcode * The opcode of the instruction being handled. * * @param argc * The number of arguments (excluding opcode) passed to the instruction * being handled by the callback. * * @param argv * All arguments (excluding opcode) associated with the instruction being * handled by the callback. * * @return * Zero if the instruction was handled successfully, non-zero if an error * occurs. */ int guacenc_handle_instruction(guacenc_display* display, const char* opcode, int argc, char** argv); /** * Handler for the Guacamole "blob" instruction. */ guacenc_instruction_handler guacenc_handle_blob; /** * Handler for the Guacamole "img" instruction. */ guacenc_instruction_handler guacenc_handle_img; /** * Handler for the Guacamole "end" instruction. */ guacenc_instruction_handler guacenc_handle_end; /** * Handler for the Guacamole "mouse" instruction. */ guacenc_instruction_handler guacenc_handle_mouse; /** * Handler for the Guacamole "sync" instruction. */ guacenc_instruction_handler guacenc_handle_sync; /** * Handler for the Guacamole "cursor" instruction. */ guacenc_instruction_handler guacenc_handle_cursor; /** * Handler for the Guacamole "copy" instruction. */ guacenc_instruction_handler guacenc_handle_copy; /** * Handler for the Guacamole "transfer" instruction. */ guacenc_instruction_handler guacenc_handle_transfer; /** * Handler for the Guacamole "size" instruction. */ guacenc_instruction_handler guacenc_handle_size; /** * Handler for the Guacamole "rect" instruction. */ guacenc_instruction_handler guacenc_handle_rect; /** * Handler for the Guacamole "cfill" instruction. */ guacenc_instruction_handler guacenc_handle_cfill; /** * Handler for the Guacamole "move" instruction. */ guacenc_instruction_handler guacenc_handle_move; /** * Handler for the Guacamole "shade" instruction. */ guacenc_instruction_handler guacenc_handle_shade; /** * Handler for the Guacamole "dispose" instruction. */ guacenc_instruction_handler guacenc_handle_dispose; #endif guacamole-server-1.3.0/src/guacenc/instruction-rect.c0000644000175100001440000000345413613156714017563 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "buffer.h" #include "display.h" #include "log.h" #include #include #include int guacenc_handle_rect(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 5) { guacenc_log(GUAC_LOG_WARNING, "\"rect\" instruction incomplete"); return 1; } /* Parse arguments */ int index = atoi(argv[0]); int x = atoi(argv[1]); int y = atoi(argv[2]); int width = atoi(argv[3]); int height = atoi(argv[4]); /* Pull buffer of requested layer/buffer */ guacenc_buffer* buffer = guacenc_display_get_related_buffer(display, index); if (buffer == NULL) return 1; /* Expand the buffer as necessary to fit the draw operation */ if (buffer->autosize) guacenc_buffer_fit(buffer, x + width, y + height); /* Set path to rectangle */ if (buffer->cairo != NULL) cairo_rectangle(buffer->cairo, x, y, width, height); return 0; } guacamole-server-1.3.0/src/guacenc/display.c0000644000175100001440000000713313702142276015707 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "cursor.h" #include "display.h" #include "video.h" #include #include cairo_operator_t guacenc_display_cairo_operator(guac_composite_mode mask) { /* Translate Guacamole channel mask into Cairo operator */ switch (mask) { /* Source */ case GUAC_COMP_SRC: return CAIRO_OPERATOR_SOURCE; /* Over */ case GUAC_COMP_OVER: return CAIRO_OPERATOR_OVER; /* In */ case GUAC_COMP_IN: return CAIRO_OPERATOR_IN; /* Out */ case GUAC_COMP_OUT: return CAIRO_OPERATOR_OUT; /* Atop */ case GUAC_COMP_ATOP: return CAIRO_OPERATOR_ATOP; /* Over (source/destination reversed) */ case GUAC_COMP_ROVER: return CAIRO_OPERATOR_DEST_OVER; /* In (source/destination reversed) */ case GUAC_COMP_RIN: return CAIRO_OPERATOR_DEST_IN; /* Out (source/destination reversed) */ case GUAC_COMP_ROUT: return CAIRO_OPERATOR_DEST_OUT; /* Atop (source/destination reversed) */ case GUAC_COMP_RATOP: return CAIRO_OPERATOR_DEST_ATOP; /* XOR */ case GUAC_COMP_XOR: return CAIRO_OPERATOR_XOR; /* Additive */ case GUAC_COMP_PLUS: return CAIRO_OPERATOR_ADD; /* If unrecognized, just default to CAIRO_OPERATOR_OVER */ default: return CAIRO_OPERATOR_OVER; } } guacenc_display* guacenc_display_alloc(const char* path, const char* codec, int width, int height, int bitrate) { /* Prepare video encoding */ guacenc_video* video = guacenc_video_alloc(path, codec, width, height, bitrate); if (video == NULL) return NULL; /* Allocate display */ guacenc_display* display = (guacenc_display*) calloc(1, sizeof(guacenc_display)); /* Associate display with video output */ display->output = video; /* Allocate special-purpose cursor layer */ display->cursor = guacenc_cursor_alloc(); return display; } int guacenc_display_free(guacenc_display* display) { int i; /* Ignore NULL display */ if (display == NULL) return 0; /* Finalize video */ int retval = guacenc_video_free(display->output); /* Free all buffers */ for (i = 0; i < GUACENC_DISPLAY_MAX_BUFFERS; i++) guacenc_buffer_free(display->buffers[i]); /* Free all layers */ for (i = 0; i < GUACENC_DISPLAY_MAX_LAYERS; i++) guacenc_layer_free(display->layers[i]); /* Free all streams */ for (i = 0; i < GUACENC_DISPLAY_MAX_STREAMS; i++) guacenc_image_stream_free(display->image_streams[i]); /* Free cursor */ guacenc_cursor_free(display->cursor); free(display); return retval; } guacamole-server-1.3.0/src/guacenc/layer.h0000644000175100001440000000535213613156714015367 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_LAYER_H #define GUACENC_LAYER_H #include "config.h" #include "buffer.h" /** * The value assigned to the parent_index property of a guacenc_layer if it has * no parent. */ #define GUACENC_LAYER_NO_PARENT -1 /** * A visible Guacamole layer. */ typedef struct guacenc_layer { /** * The actual image contents of this layer, as well as this layer's size * (width and height). */ guacenc_buffer* buffer; /** * The index of the layer that contains this layer. If this layer is the * default layer (and thus has no parent), this will be * GUACENC_LAYER_NO_PARENT. */ int parent_index; /** * The X coordinate of the upper-left corner of this layer within the * Guacamole display. */ int x; /** * The Y coordinate of the upper-left corner of this layer within the * Guacamole display. */ int y; /** * The relative stacking order of this layer with respect to other sibling * layers. */ int z; /** * The opacity of this layer, where 0 is completely transparent and 255 is * completely opaque. */ int opacity; /** * The internal buffer used by to record the state of this layer in the * previous frame and to render additional frames. */ guacenc_buffer* frame; } guacenc_layer; /** * Allocates and initializes a new layer object. This allocation is independent * of the Guacamole video encoder display; the allocated guacenc_layer will not * automatically be associated with the active display. * * @return * A newly-allocated and initialized guacenc_layer, or NULL if allocation * fails. */ guacenc_layer* guacenc_layer_alloc(); /** * Frees all memory associated with the given layer object. If the layer * provided is NULL, this function has no effect. * * @param layer * The layer to free, which may be NULL. */ void guacenc_layer_free(guacenc_layer* layer); #endif guacamole-server-1.3.0/src/guacenc/display-flatten.c0000644000175100001440000001440313702142276017340 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "layer.h" #include "log.h" #include #include #include #include #include /** * The Guacamole video encoder display related to the current qsort() * operation. As qsort() does not provide a means of passing arbitrary data to * the comparitor, this value must be set prior to invoking qsort() with * guacenc_display_layer_comparator. */ guacenc_display* __qsort_display; /** * Comparator which orders layer pointers such that (1) NULL pointers are last, * (2) layers with the same parent_index are adjacent, and (3) layers with the * same parent_index are ordered by Z. * * @see qsort() */ static int guacenc_display_layer_comparator(const void* a, const void* b) { guacenc_layer* layer_a = *((guacenc_layer**) a); guacenc_layer* layer_b = *((guacenc_layer**) b); /* If a is NULL, sort it to bottom */ if (layer_a == NULL) { /* ... unless b is also NULL, in which case they are equal */ if (layer_b == NULL) return 0; return 1; } /* If b is NULL (and a is not NULL), sort it to bottom */ if (layer_b == NULL) return -1; /* Order such that the deepest layers are first */ int a_depth = guacenc_display_get_depth(__qsort_display, layer_a); int b_depth = guacenc_display_get_depth(__qsort_display, layer_b); if (b_depth != a_depth) return b_depth - a_depth; /* Order such that sibling layers are adjacent */ if (layer_b->parent_index != layer_a->parent_index) return layer_b->parent_index - layer_a->parent_index; /* Order sibling layers according to descending Z */ return layer_b->z - layer_a->z; } /** * Renders the mouse cursor on top of the frame buffer of the default layer of * the given display. * * @param display * The display whose mouse cursor should be rendered to the frame buffer * of its default layer. * * @return * Zero if rendering succeeds, non-zero otherwise. */ static int guacenc_display_render_cursor(guacenc_display* display) { guacenc_cursor* cursor = display->cursor; /* Do not render cursor if coordinates are negative */ if (cursor->x < 0 || cursor->y < 0) return 0; /* Retrieve default layer (guaranteed to not be NULL) */ guacenc_layer* def_layer = guacenc_display_get_layer(display, 0); assert(def_layer != NULL); /* Get source and destination buffers */ guacenc_buffer* src = cursor->buffer; guacenc_buffer* dst = def_layer->frame; /* Render cursor to layer */ if (src->width > 0 && src->height > 0) { cairo_set_source_surface(dst->cairo, src->surface, cursor->x - cursor->hotspot_x, cursor->y - cursor->hotspot_y); cairo_rectangle(dst->cairo, cursor->x - cursor->hotspot_x, cursor->y - cursor->hotspot_y, src->width, src->height); cairo_fill(dst->cairo); } /* Always succeeds */ return 0; } int guacenc_display_flatten(guacenc_display* display) { int i; guacenc_layer* render_order[GUACENC_DISPLAY_MAX_LAYERS]; /* Copy list of layers within display */ memcpy(render_order, display->layers, sizeof(render_order)); /* Sort layers by depth, parent, and Z */ __qsort_display = display; qsort(render_order, GUACENC_DISPLAY_MAX_LAYERS, sizeof(guacenc_layer*), guacenc_display_layer_comparator); /* Reset layer frame buffers */ for (i = 0; i < GUACENC_DISPLAY_MAX_LAYERS; i++) { /* Pull current layer, ignoring unallocated layers */ guacenc_layer* layer = render_order[i]; if (layer == NULL) continue; /* Get source buffer and destination frame buffer */ guacenc_buffer* buffer = layer->buffer; guacenc_buffer* frame = layer->frame; /* Reset frame contents */ guacenc_buffer_copy(frame, buffer); } /* Render each layer, in order */ for (i = 0; i < GUACENC_DISPLAY_MAX_LAYERS; i++) { /* Pull current layer, ignoring unallocated layers */ guacenc_layer* layer = render_order[i]; if (layer == NULL) continue; /* Skip fully-transparent layers */ if (layer->opacity == 0) continue; /* Ignore layers without a parent */ int parent_index = layer->parent_index; if (parent_index == GUACENC_LAYER_NO_PARENT) continue; /* Retrieve parent layer, ignoring layers with invalid parents */ guacenc_layer* parent = guacenc_display_get_layer(display, parent_index); if (parent == NULL) continue; /* Get source and destination frame buffer */ guacenc_buffer* src = layer->frame; guacenc_buffer* dst = parent->frame; /* Ignore layers with empty buffers */ cairo_surface_t* surface = src->surface; if (surface == NULL) continue; /* Ignore if parent has no pixels */ cairo_t* cairo = dst->cairo; if (cairo == NULL) continue; /* Render buffer to layer */ cairo_reset_clip(cairo); cairo_rectangle(cairo, layer->x, layer->y, src->width, src->height); cairo_clip(cairo); cairo_set_source_surface(cairo, surface, layer->x, layer->y); cairo_paint_with_alpha(cairo, layer->opacity / 255.0); } /* Render cursor on top of everything else */ return guacenc_display_render_cursor(display); } guacamole-server-1.3.0/src/guacenc/log.h0000644000175100001440000000372313613156714015034 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_LOG_H #define GUACENC_LOG_H #include "config.h" #include #include /** * The maximum level at which to log messages. All other messages will be * dropped. */ extern int guacenc_log_level; /** * The string to prepend to all log messages. */ #define GUACENC_LOG_NAME "guacenc" /** * Writes a message to guacenc's logs. This function takes a format and * va_list, similar to vprintf. * * @param level * The level at which to log this message. * * @param format * A printf-style format string to log. * * @param args * The va_list containing the arguments to be used when filling the format * string for printing. */ void vguacenc_log(guac_client_log_level level, const char* format, va_list args); /** * Writes a message to guacenc's logs. This function accepts parameters * identically to printf. * * @param level * The level at which to log this message. * * @param format * A printf-style format string to log. * * @param ... * Arguments to use when filling the format string for printing. */ void guacenc_log(guac_client_log_level level, const char* format, ...); #endif guacamole-server-1.3.0/src/guacenc/png.c0000644000175100001440000000576113613156714015036 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "log.h" #include "png.h" #include #include #include /** * The current state of the PNG decoder. */ typedef struct guacenc_png_read_state { /** * The buffer of unread image data. This pointer will be updated to point * to the next unread byte when data is read. */ unsigned char* data; /** * The number of bytes remaining to be read within the buffer. */ unsigned int length; } guacenc_png_read_state; /** * Attempts to fill the given buffer with read image data. The behavior of * this function is dictated by cairo_read_t. * * @param closure * The current state of the PNG decoding process (an instance of * guacenc_png_read_state). * * @param data * The data buffer to fill. * * @param length * The number of bytes to fill within the data buffer. * * @return * CAIRO_STATUS_SUCCESS if all data was read successfully (the entire * buffer was filled), CAIRO_STATUS_READ_ERROR otherwise. */ static cairo_status_t guacenc_png_read(void* closure, unsigned char* data, unsigned int length) { guacenc_png_read_state* state = (guacenc_png_read_state*) closure; /* If more data is requested than is available in buffer, fail */ if (length > state->length) return CAIRO_STATUS_READ_ERROR; /* Read chunk into buffer */ memcpy(data, state->data, length); /* Advance to next chunk */ state->length -= length; state->data += length; /* Read was successful */ return CAIRO_STATUS_SUCCESS; } cairo_surface_t* guacenc_png_decoder(unsigned char* data, int length) { guacenc_png_read_state state = { .data = data, .length = length }; /* Read PNG from data */ cairo_surface_t* surface = cairo_image_surface_create_from_png_stream(guacenc_png_read, &state); /* If surface returned with an error, just return NULL */ if (surface != NULL && cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) { guacenc_log(GUAC_LOG_WARNING, "Invalid PNG data"); cairo_surface_destroy(surface); return NULL; } /* PNG was read successfully */ return surface; } guacamole-server-1.3.0/src/guacenc/webp.h0000644000175100001440000000177313613156714015213 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_WEBP_H #define GUACENC_WEBP_H #include "config.h" #include "image-stream.h" /** * Decoder implementation which handles "image/webp" images. */ guacenc_decoder guacenc_webp_decoder; #endif guacamole-server-1.3.0/src/guacenc/jpeg.c0000644000175100001440000001061613613156714015172 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "jpeg.h" #include "log.h" #include #include #include #include #include /** * Translates libjpeg's 24-bit RGB format into Cairo's 32-bit ARGB32 / RGB24 * format. The red, green, and blue components from the libjpeg pixel are * copied verbatim, while the extra high byte used within Cairo is set to 0xFF. * * @param src * A pointer to the first byte of the 24-bit RGB pixel within a libjpeg * scanline buffer. * * @return * A 32-bit Cairo ARGB32 / RGB24 pixel value equivalent to the libjpeg * pixel at the given pointer. */ static uint32_t guacenc_jpeg_translate_rgb(const unsigned char* src) { /* Pull components from source */ int r = *(src++); int g = *(src++); int b = *(src++); /* Translate to 32-bit integer compatible with Cairo */ return 0xFF000000 | (r << 16) | (g << 8) | b; } /** * Copies the data from a libjpeg scanline buffer into a row of image data * within a Cairo surface, translating each pixel as necessary. * * @param dst * The destination buffer into which the scanline should be copied. * * @param src * The libjpeg scanline buffer that should be copied into the * destination buffer. * * @param width * The number of pixels available within both the scanline buffer and the * destination buffer. */ static void guacenc_jpeg_copy_scanline(unsigned char* dst, const unsigned char* src, int width) { uint32_t* current = (uint32_t*) dst; /* Copy all pixels from source to destination, translating for Cairo */ for (; width > 0; width--, src += 3) { *(current++) = guacenc_jpeg_translate_rgb(src); } } cairo_surface_t* guacenc_jpeg_decoder(unsigned char* data, int length) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; /* Create decompressor with standard error handling */ jpeg_create_decompress(&cinfo); cinfo.err = jpeg_std_error(&jerr); /* Read JPEG directly from memory buffer */ jpeg_mem_src(&cinfo, data, length); /* Read and validate JPEG header */ if (!jpeg_read_header(&cinfo, TRUE)) { guacenc_log(GUAC_LOG_WARNING, "Invalid JPEG data"); jpeg_destroy_decompress(&cinfo); return NULL; } /* Begin decompression */ cinfo.out_color_space = JCS_RGB; jpeg_start_decompress(&cinfo); /* Pull JPEG dimensions from decompressor */ int width = cinfo.output_width; int height = cinfo.output_height; /* Allocate sufficient buffer space for one JPEG scanline */ unsigned char* jpeg_scanline = malloc(width * 3); /* Create blank Cairo surface (no transparency in JPEG) */ cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height); /* Pull underlying buffer and its stride */ int stride = cairo_image_surface_get_stride(surface); unsigned char* row = cairo_image_surface_get_data(surface); /* Read JPEG into surface */ while (cinfo.output_scanline < height) { /* Read single scanline */ unsigned char* buffers[1] = { jpeg_scanline }; jpeg_read_scanlines(&cinfo, buffers, 1); /* Copy scanline to Cairo surface */ guacenc_jpeg_copy_scanline(row, jpeg_scanline, width); /* Advance to next row of Cairo surface */ row += stride; } /* Scanline buffer is no longer needed */ free(jpeg_scanline); /* End decompression */ jpeg_finish_decompress(&cinfo); /* Free decompressor */ jpeg_destroy_decompress(&cinfo); /* JPEG was read successfully */ return surface; } guacamole-server-1.3.0/src/guacenc/ffmpeg-compat.c0000644000175100001440000001632213764613616017000 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "ffmpeg-compat.h" #include "log.h" #include "video.h" #include #include #include #include #include #include #include /** * Writes a single packet of video data to the current output file. If an error * occurs preventing the packet from being written, messages describing the * error are logged. * * @param video * The video associated with the output file that the given packet should * be written to. * * @param data * The buffer of data containing the video packet which should be written. * * @param size * The number of bytes within the video packet. * * @return * Zero if the packet was written successfully, non-zero otherwise. */ static int guacenc_write_packet(guacenc_video* video, void* data, int size) { int ret; #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,1,0) AVPacket pkt; /* Have to create a packet around the encoded data we have */ av_init_packet(&pkt); if (video->context->coded_frame->pts != AV_NOPTS_VALUE) { pkt.pts = av_rescale_q(video->context->coded_frame->pts, video->context->time_base, video->output_stream->time_base); } if (video->context->coded_frame->key_frame) { pkt->flags |= AV_PKT_FLAG_KEY; } pkt.data = data; pkt.size = size; pkt.stream_index = video->output_stream->index; ret = av_interleaved_write_frame(video->container_format_context, &pkt); #else /* We know data is already a packet if we're using a newer libavcodec */ AVPacket* pkt = (AVPacket*) data; av_packet_rescale_ts(pkt, video->context->time_base, video->output_stream->time_base); pkt->stream_index = video->output_stream->index; ret = av_interleaved_write_frame(video->container_format_context, pkt); #endif if (ret != 0) { guacenc_log(GUAC_LOG_ERROR, "Unable to write frame " "#%" PRId64 ": %s", video->next_pts, strerror(errno)); return -1; } /* Data was written successfully */ guacenc_log(GUAC_LOG_DEBUG, "Frame #%08" PRId64 ": wrote %i bytes", video->next_pts, size); return ret; } int guacenc_avcodec_encode_video(guacenc_video* video, AVFrame* frame) { /* For libavcodec < 54.1.0: packets were handled as raw malloc'd buffers */ #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,1,0) AVCodecContext* context = video->context; /* Calculate appropriate buffer size */ int length = FF_MIN_BUFFER_SIZE + 12 * context->width * context->height; /* Allocate space for output */ uint8_t* data = malloc(length); if (data == NULL) return -1; /* Encode packet of video data */ int used = avcodec_encode_video(context, data, length, frame); if (used < 0) { guacenc_log(GUAC_LOG_WARNING, "Error encoding frame #%" PRId64, video->next_pts); free(data); return -1; } /* Report if no data needs to be written */ if (used == 0) { free(data); return 0; } /* Write data, logging any errors */ guacenc_write_packet(video, data, used); free(data); return 1; #else /* Init video packet */ AVPacket packet; av_init_packet(&packet); /* Request that encoder allocate data for packet */ packet.data = NULL; packet.size = 0; /* For libavcodec < 57.37.100: input/output was not decoupled */ #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,37,100) /* Write frame to video */ int got_data; if (avcodec_encode_video2(video->context, &packet, frame, &got_data) < 0) { guacenc_log(GUAC_LOG_WARNING, "Error encoding frame #%" PRId64, video->next_pts); return -1; } /* Write corresponding data to file */ if (got_data) { guacenc_write_packet(video, (void*) &packet, packet.size); av_packet_unref(&packet); } #else /* Write frame to video */ int result = avcodec_send_frame(video->context, frame); /* Stop once encoded has been flushed */ if (result == AVERROR_EOF) return 0; /* Abort on error */ else if (result < 0) { guacenc_log(GUAC_LOG_WARNING, "Error encoding frame #%" PRId64, video->next_pts); return -1; } /* Flush all available packets */ int got_data = 0; while (avcodec_receive_packet(video->context, &packet) == 0) { /* Data was received */ got_data = 1; /* Attempt to write data to output file */ guacenc_write_packet(video, (void*) &packet, packet.size); av_packet_unref(&packet); } #endif /* Frame may have been queued for later writing / reordering */ if (!got_data) guacenc_log(GUAC_LOG_DEBUG, "Frame #%08" PRId64 ": queued for later", video->next_pts); return got_data; #endif } AVCodecContext* guacenc_build_avcodeccontext(AVStream* stream, AVCodec* codec, int bitrate, int width, int height, int gop_size, int qmax, int qmin, int pix_fmt, AVRational time_base) { #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100) stream->codec->bit_rate = bitrate; stream->codec->width = width; stream->codec->height = height; stream->codec->gop_size = gop_size; stream->codec->qmax = qmax; stream->codec->qmin = qmin; stream->codec->pix_fmt = pix_fmt; stream->codec->time_base = time_base; #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(55, 44, 100) stream->time_base = time_base; #endif return stream->codec; #else AVCodecContext* context = avcodec_alloc_context3(codec); if (context) { context->bit_rate = bitrate; context->width = width; context->height = height; context->gop_size = gop_size; context->qmax = qmax; context->qmin = qmin; context->pix_fmt = pix_fmt; context->time_base = time_base; stream->time_base = time_base; } return context; #endif } int guacenc_open_avcodec(AVCodecContext *avcodec_context, AVCodec *codec, AVDictionary **options, AVStream* stream) { int ret = avcodec_open2(avcodec_context, codec, options); #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100) /* Copy stream parameters to the muxer */ int codecpar_ret = avcodec_parameters_from_context(stream->codecpar, avcodec_context); if (codecpar_ret < 0) return codecpar_ret; #endif return ret; } guacamole-server-1.3.0/src/guacenc/instruction-copy.c0000644000175100001440000000630613613156714017577 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "log.h" #include #include int guacenc_handle_copy(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 9) { guacenc_log(GUAC_LOG_WARNING, "\"copy\" instruction incomplete"); return 1; } /* Parse arguments */ int sindex = atoi(argv[0]); int sx = atoi(argv[1]); int sy = atoi(argv[2]); int width = atoi(argv[3]); int height = atoi(argv[4]); int mask = atoi(argv[5]); int dindex = atoi(argv[6]); int dx = atoi(argv[7]); int dy = atoi(argv[8]); /* Pull buffer of source layer/buffer */ guacenc_buffer* src = guacenc_display_get_related_buffer(display, sindex); if (src == NULL) return 1; /* Pull buffer of destination layer/buffer */ guacenc_buffer* dst = guacenc_display_get_related_buffer(display, dindex); if (dst == NULL) return 1; /* Expand the destination buffer as necessary to fit the draw operation */ if (dst->autosize) guacenc_buffer_fit(dst, dx + width, dy + height); /* Copy rectangle from source to destination */ if (src->surface != NULL && dst->cairo != NULL) { /* If surfaces are different, no need to copy */ cairo_surface_t* surface; if (src != dst) surface = src->surface; /* Otherwise, copy to a temporary surface */ else { /* Create new surface to hold the source rect */ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); /* Copy relevant rectangle from source surface */ cairo_t* cairo = cairo_create(surface); cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(cairo, src->surface, -sx, -sy); cairo_paint(cairo); cairo_destroy(cairo); /* Source coordinates are now (0, 0) */ sx = sy = 0; } /* Perform copy */ cairo_set_operator(dst->cairo, guacenc_display_cairo_operator(mask)); cairo_set_source_surface(dst->cairo, surface, dx - sx, dy - sy); cairo_rectangle(dst->cairo, dx, dy, width, height); cairo_fill(dst->cairo); /* Destroy temporary surface if it was created */ if (surface != src->surface) cairo_surface_destroy(surface); } return 0; } guacamole-server-1.3.0/src/guacenc/instruction-cursor.c0000644000175100001440000000420613702142276020134 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "buffer.h" #include "cursor.h" #include "display.h" #include "log.h" #include #include int guacenc_handle_cursor(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 7) { guacenc_log(GUAC_LOG_WARNING, "\"cursor\" instruction incomplete"); return 1; } /* Parse arguments */ int hotspot_x = atoi(argv[0]); int hotspot_y = atoi(argv[1]); int sindex = atoi(argv[2]); int sx = atoi(argv[3]); int sy = atoi(argv[4]); int width = atoi(argv[5]); int height = atoi(argv[6]); /* Pull buffer of source layer/buffer */ guacenc_buffer* src = guacenc_display_get_related_buffer(display, sindex); if (src == NULL) return 1; /* Update cursor hotspot */ guacenc_cursor* cursor = display->cursor; cursor->hotspot_x = hotspot_x; cursor->hotspot_y = hotspot_y; /* Resize cursor to exactly fit */ guacenc_buffer_resize(cursor->buffer, width, height); /* Copy rectangle from source to cursor */ guacenc_buffer* dst = cursor->buffer; if (src->surface != NULL && dst->cairo != NULL) { cairo_set_operator(dst->cairo, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(dst->cairo, src->surface, sx, sy); cairo_paint(dst->cairo); } return 0; } guacamole-server-1.3.0/src/guacenc/instruction-mouse.c0000644000175100001440000000316313702142276017750 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "cursor.h" #include "display.h" #include "log.h" #include "parse.h" #include #include int guacenc_handle_mouse(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 2) { guacenc_log(GUAC_LOG_WARNING, "\"mouse\" instruction incomplete"); return 1; } /* Parse arguments */ int x = atoi(argv[0]); int y = atoi(argv[1]); /* Update cursor properties */ guacenc_cursor* cursor = display->cursor; cursor->x = x; cursor->y = y; /* If no timestamp provided, nothing further to do */ if (argc < 4) return 0; /* Leverage timestamp to render frame */ guac_timestamp timestamp = guacenc_parse_timestamp(argv[3]); return guacenc_display_sync(display, timestamp); } guacamole-server-1.3.0/src/guacenc/man/0000755000175100001440000000000013772471154014734 500000000000000guacamole-server-1.3.0/src/guacenc/man/guacenc.1.in0000644000175100001440000000606513764613616016761 00000000000000.\" .\" Licensed to the Apache Software Foundation (ASF) under one .\" or more contributor license agreements. See the NOTICE file .\" distributed with this work for additional information .\" regarding copyright ownership. The ASF licenses this file .\" to you under the Apache License, Version 2.0 (the .\" "License"); you may not use this file except in compliance .\" with the License. You may obtain a copy of the License at .\" .\" http://www.apache.org/licenses/LICENSE-2.0 .\" .\" Unless required by applicable law or agreed to in writing, .\" software distributed under the License is distributed on an .\" "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY .\" KIND, either express or implied. See the License for the .\" specific language governing permissions and limitations .\" under the License. .\" .TH guacenc 1 "26 Jan 2018" "version @PACKAGE_VERSION@" "Apache Guacamole" . .SH NAME guacenc \- Guacamole video encoder . .SH SYNOPSIS .B guacenc [\fB-s\fR \fIWIDTH\fRx\fIHEIGHT\fR] [\fB-r\fR \fIBITRATE\fR] [\fB-f\fR] [\fIFILE\fR]... . .SH DESCRIPTION .B guacenc is a video encoder which accepts Guacamole protocol dumps, such as those saved when screen recording is enabled on a Guacamole connection, writing standard video files as output. .B guacenc is essentially an implementation of a Guacamole client which accepts its input from files instead of a network connection, and renders directly to video instead of to the user's screen. .P Each \fIFILE\fR specified will be encoded as MPEG-4 video to a new file named \fIFILE\fR.m4v, encoded according to the other options specified. By default, the output video will be \fI640\fRx\fI480\fR pixels, and will be saved with a bitrate of \fI2000000\fR bits per second (2 Mbps). These defaults can be overridden with the \fB-s\fR and \fB-r\fR options respectively. Existing files will not be overwritten; the encoding process for any input file will be aborted if it would result in overwriting an existing file. .P Guacamole acquires a write lock on recordings as they are being written. By default, .B guacenc will check whether the each input file is locked and will refuse to read and encode an input file if it appears to be an in-progress recording. This behavior can be overridden by specifying the \fB-f\fR option. Encoding an in-progress recording will still result in a valid video; the video will simply cover the user's session only up to the current point in time. . .SH OPTIONS .TP \fB-s\fR \fIWIDTH\fRx\fIHEIGHT\fR Changes the resolution of the video that .B guacenc renders. By default, this will be \fI640\fRx\fI480\fR. .TP \fB-r\fR \fIBITRATE\fR Changes the bitrate that .B guacenc will use for the saved video. This is specified in bits per second. By default, this will be \fI2000000\fR (2 Mbps). Higher values will result in larger but higher-quality video files. Lower values will result in smaller but lower-quality video files. .TP \fB-f\fR Overrides the default behavior of .B guacenc such that input files will be encoded even if they appear to be recordings of in-progress Guacamole sessions. . .SH SEE ALSO .BR guaclog (1) guacamole-server-1.3.0/src/guacenc/guacenc.c0000644000175100001440000001046713764613616015664 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "encode.h" #include "guacenc.h" #include "log.h" #include "parse.h" #include #include #include #include #include int main(int argc, char* argv[]) { int i; /* Load defaults */ bool force = false; int width = GUACENC_DEFAULT_WIDTH; int height = GUACENC_DEFAULT_HEIGHT; int bitrate = GUACENC_DEFAULT_BITRATE; /* Parse arguments */ int opt; while ((opt = getopt(argc, argv, "s:r:f")) != -1) { /* -s: Dimensions (WIDTHxHEIGHT) */ if (opt == 's') { if (guacenc_parse_dimensions(optarg, &width, &height)) { guacenc_log(GUAC_LOG_ERROR, "Invalid dimensions."); goto invalid_options; } } /* -r: Bitrate (bits per second) */ else if (opt == 'r') { if (guacenc_parse_int(optarg, &bitrate)) { guacenc_log(GUAC_LOG_ERROR, "Invalid bitrate."); goto invalid_options; } } /* -f: Force */ else if (opt == 'f') force = true; /* Invalid option */ else { goto invalid_options; } } /* Log start */ guacenc_log(GUAC_LOG_INFO, "Guacamole video encoder (guacenc) " "version " VERSION); #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100) /* Prepare libavcodec */ avcodec_register_all(); #endif #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100) av_register_all(); #endif /* Track number of overall failures */ int total_files = argc - optind; int failures = 0; /* Abort if no files given */ if (total_files <= 0) { guacenc_log(GUAC_LOG_INFO, "No input files specified. Nothing to do."); return 0; } guacenc_log(GUAC_LOG_INFO, "%i input file(s) provided.", total_files); guacenc_log(GUAC_LOG_INFO, "Video will be encoded at %ix%i " "and %i bps.", width, height, bitrate); /* Encode all input files */ for (i = optind; i < argc; i++) { /* Get current filename */ const char* path = argv[i]; /* Generate output filename */ char out_path[4096]; int len = snprintf(out_path, sizeof(out_path), "%s.m4v", path); /* Do not write if filename exceeds maximum length */ if (len >= sizeof(out_path)) { guacenc_log(GUAC_LOG_ERROR, "Cannot write output file for \"%s\": " "Name too long", path); continue; } /* Attempt encoding, log granular success/failure at debug level */ if (guacenc_encode(path, out_path, "mpeg4", width, height, bitrate, force)) { failures++; guacenc_log(GUAC_LOG_DEBUG, "%s was NOT successfully encoded.", path); } else guacenc_log(GUAC_LOG_DEBUG, "%s was successfully encoded.", path); } /* Warn if at least one file failed */ if (failures != 0) guacenc_log(GUAC_LOG_WARNING, "Encoding failed for %i of %i file(s).", failures, total_files); /* Notify of success */ else guacenc_log(GUAC_LOG_INFO, "All files encoded successfully."); /* Encoding complete */ return 0; /* Display usage and exit with error if options are invalid */ invalid_options: fprintf(stderr, "USAGE: %s" " [-s WIDTHxHEIGHT]" " [-r BITRATE]" " [-f]" " [FILE]...\n", argv[0]); return 1; } guacamole-server-1.3.0/src/guacenc/log.c0000644000175100001440000000442713613156714015031 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "guacenc.h" #include "log.h" #include #include #include #include int guacenc_log_level = GUACENC_DEFAULT_LOG_LEVEL; void vguacenc_log(guac_client_log_level level, const char* format, va_list args) { const char* priority_name; char message[2048]; /* Don't bother if the log level is too high */ if (level > guacenc_log_level) return; /* Copy log message into buffer */ vsnprintf(message, sizeof(message), format, args); /* Convert log level to human-readable name */ switch (level) { /* Error log level */ case GUAC_LOG_ERROR: priority_name = "ERROR"; break; /* Warning log level */ case GUAC_LOG_WARNING: priority_name = "WARNING"; break; /* Informational log level */ case GUAC_LOG_INFO: priority_name = "INFO"; break; /* Debug log level */ case GUAC_LOG_DEBUG: priority_name = "DEBUG"; break; /* Any unknown/undefined log level */ default: priority_name = "UNKNOWN"; break; } /* Log to STDERR */ fprintf(stderr, GUACENC_LOG_NAME ": %s: %s\n", priority_name, message); } void guacenc_log(guac_client_log_level level, const char* format, ...) { va_list args; va_start(args, format); vguacenc_log(level, format, args); va_end(args); } guacamole-server-1.3.0/src/guacenc/instruction-sync.c0000644000175100001440000000260313702142276017572 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "log.h" #include "parse.h" #include #include #include #include int guacenc_handle_sync(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 1) { guacenc_log(GUAC_LOG_WARNING, "\"sync\" instruction incomplete"); return 1; } /* Parse arguments */ guac_timestamp timestamp = guacenc_parse_timestamp(argv[0]); /* Update timestamp / flush frame */ return guacenc_display_sync(display, timestamp); } guacamole-server-1.3.0/src/guacenc/display-sync.c0000644000175100001440000000351413613156714016663 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "layer.h" #include "log.h" #include "video.h" #include #include #include #include int guacenc_display_sync(guacenc_display* display, guac_timestamp timestamp) { /* Verify timestamp is not decreasing */ if (timestamp < display->last_sync) { guacenc_log(GUAC_LOG_WARNING, "Decreasing sync timestamp"); return 1; } /* Update timestamp of display */ display->last_sync = timestamp; /* Flatten display to default layer */ if (guacenc_display_flatten(display)) return 1; /* Retrieve default layer (guaranteed to not be NULL) */ guacenc_layer* def_layer = guacenc_display_get_layer(display, 0); assert(def_layer != NULL); /* Update video timeline */ if (guacenc_video_advance_timeline(display->output, timestamp)) return 1; /* Prepare frame for write upon next flush */ guacenc_video_prepare_frame(display->output, def_layer->frame); return 0; } guacamole-server-1.3.0/src/guacenc/jpeg.h0000644000175100001440000000177313613156714015203 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_JPEG_H #define GUACENC_JPEG_H #include "config.h" #include "image-stream.h" /** * Decoder implementation which handles "image/jpeg" images. */ guacenc_decoder guacenc_jpeg_decoder; #endif guacamole-server-1.3.0/src/guacenc/Makefile.in0000644000175100001440000030721413772471102016146 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = guacenc$(EXEEXT) # Compile WebP support if available @ENABLE_WEBP_TRUE@am__append_1 = webp.c @ENABLE_WEBP_TRUE@am__append_2 = webp.h subdir = src/guacenc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__noinst_HEADERS_DIST) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" PROGRAMS = $(bin_PROGRAMS) am__guacenc_SOURCES_DIST = buffer.c cursor.c display.c \ display-buffers.c display-image-streams.c display-flatten.c \ display-layers.c display-sync.c encode.c ffmpeg-compat.c \ guacenc.c image-stream.c instructions.c instruction-blob.c \ instruction-cfill.c instruction-copy.c instruction-cursor.c \ instruction-dispose.c instruction-end.c instruction-img.c \ instruction-mouse.c instruction-move.c instruction-rect.c \ instruction-shade.c instruction-size.c instruction-sync.c \ instruction-transfer.c jpeg.c layer.c log.c parse.c png.c \ video.c webp.c @ENABLE_WEBP_TRUE@am__objects_1 = guacenc-webp.$(OBJEXT) am_guacenc_OBJECTS = guacenc-buffer.$(OBJEXT) guacenc-cursor.$(OBJEXT) \ guacenc-display.$(OBJEXT) guacenc-display-buffers.$(OBJEXT) \ guacenc-display-image-streams.$(OBJEXT) \ guacenc-display-flatten.$(OBJEXT) \ guacenc-display-layers.$(OBJEXT) \ guacenc-display-sync.$(OBJEXT) guacenc-encode.$(OBJEXT) \ guacenc-ffmpeg-compat.$(OBJEXT) guacenc-guacenc.$(OBJEXT) \ guacenc-image-stream.$(OBJEXT) guacenc-instructions.$(OBJEXT) \ guacenc-instruction-blob.$(OBJEXT) \ guacenc-instruction-cfill.$(OBJEXT) \ guacenc-instruction-copy.$(OBJEXT) \ guacenc-instruction-cursor.$(OBJEXT) \ guacenc-instruction-dispose.$(OBJEXT) \ guacenc-instruction-end.$(OBJEXT) \ guacenc-instruction-img.$(OBJEXT) \ guacenc-instruction-mouse.$(OBJEXT) \ guacenc-instruction-move.$(OBJEXT) \ guacenc-instruction-rect.$(OBJEXT) \ guacenc-instruction-shade.$(OBJEXT) \ guacenc-instruction-size.$(OBJEXT) \ guacenc-instruction-sync.$(OBJEXT) \ guacenc-instruction-transfer.$(OBJEXT) guacenc-jpeg.$(OBJEXT) \ guacenc-layer.$(OBJEXT) guacenc-log.$(OBJEXT) \ guacenc-parse.$(OBJEXT) guacenc-png.$(OBJEXT) \ guacenc-video.$(OBJEXT) $(am__objects_1) guacenc_OBJECTS = $(am_guacenc_OBJECTS) guacenc_DEPENDENCIES = AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = guacenc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(guacenc_CFLAGS) \ $(CFLAGS) $(guacenc_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/guacenc-buffer.Po \ ./$(DEPDIR)/guacenc-cursor.Po \ ./$(DEPDIR)/guacenc-display-buffers.Po \ ./$(DEPDIR)/guacenc-display-flatten.Po \ ./$(DEPDIR)/guacenc-display-image-streams.Po \ ./$(DEPDIR)/guacenc-display-layers.Po \ ./$(DEPDIR)/guacenc-display-sync.Po \ ./$(DEPDIR)/guacenc-display.Po ./$(DEPDIR)/guacenc-encode.Po \ ./$(DEPDIR)/guacenc-ffmpeg-compat.Po \ ./$(DEPDIR)/guacenc-guacenc.Po \ ./$(DEPDIR)/guacenc-image-stream.Po \ ./$(DEPDIR)/guacenc-instruction-blob.Po \ ./$(DEPDIR)/guacenc-instruction-cfill.Po \ ./$(DEPDIR)/guacenc-instruction-copy.Po \ ./$(DEPDIR)/guacenc-instruction-cursor.Po \ ./$(DEPDIR)/guacenc-instruction-dispose.Po \ ./$(DEPDIR)/guacenc-instruction-end.Po \ ./$(DEPDIR)/guacenc-instruction-img.Po \ ./$(DEPDIR)/guacenc-instruction-mouse.Po \ ./$(DEPDIR)/guacenc-instruction-move.Po \ ./$(DEPDIR)/guacenc-instruction-rect.Po \ ./$(DEPDIR)/guacenc-instruction-shade.Po \ ./$(DEPDIR)/guacenc-instruction-size.Po \ ./$(DEPDIR)/guacenc-instruction-sync.Po \ ./$(DEPDIR)/guacenc-instruction-transfer.Po \ ./$(DEPDIR)/guacenc-instructions.Po \ ./$(DEPDIR)/guacenc-jpeg.Po ./$(DEPDIR)/guacenc-layer.Po \ ./$(DEPDIR)/guacenc-log.Po ./$(DEPDIR)/guacenc-parse.Po \ ./$(DEPDIR)/guacenc-png.Po ./$(DEPDIR)/guacenc-video.Po \ ./$(DEPDIR)/guacenc-webp.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(guacenc_SOURCES) DIST_SOURCES = $(am__guacenc_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 NROFF = nroff MANS = $(man_MANS) am__noinst_HEADERS_DIST = buffer.h cursor.h display.h encode.h \ ffmpeg-compat.h guacenc.h image-stream.h instructions.h jpeg.h \ layer.h log.h parse.h png.h video.h webp.h HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign man_MANS = \ man/guacenc.1 noinst_HEADERS = buffer.h cursor.h display.h encode.h ffmpeg-compat.h \ guacenc.h image-stream.h instructions.h jpeg.h layer.h log.h \ parse.h png.h video.h $(am__append_2) guacenc_SOURCES = buffer.c cursor.c display.c display-buffers.c \ display-image-streams.c display-flatten.c display-layers.c \ display-sync.c encode.c ffmpeg-compat.c guacenc.c \ image-stream.c instructions.c instruction-blob.c \ instruction-cfill.c instruction-copy.c instruction-cursor.c \ instruction-dispose.c instruction-end.c instruction-img.c \ instruction-mouse.c instruction-move.c instruction-rect.c \ instruction-shade.c instruction-size.c instruction-sync.c \ instruction-transfer.c jpeg.c layer.c log.c parse.c png.c \ video.c $(am__append_1) guacenc_CFLAGS = \ -Werror -Wall \ @AVCODEC_CFLAGS@ \ @AVFORMAT_CFLAGS@ \ @AVUTIL_CFLAGS@ \ @LIBGUAC_INCLUDE@ \ @SWSCALE_CFLAGS@ guacenc_LDADD = \ @LIBGUAC_LTLIB@ guacenc_LDFLAGS = \ @AVCODEC_LIBS@ \ @AVFORMAT_LIBS@ \ @AVUTIL_LIBS@ \ @CAIRO_LIBS@ \ @JPEG_LIBS@ \ @SWSCALE_LIBS@ \ @WEBP_LIBS@ EXTRA_DIST = \ man/guacenc.1.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/guacenc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/guacenc/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list guacenc$(EXEEXT): $(guacenc_OBJECTS) $(guacenc_DEPENDENCIES) $(EXTRA_guacenc_DEPENDENCIES) @rm -f guacenc$(EXEEXT) $(AM_V_CCLD)$(guacenc_LINK) $(guacenc_OBJECTS) $(guacenc_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-buffer.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-cursor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-display-buffers.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-display-flatten.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-display-image-streams.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-display-layers.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-display-sync.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-display.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-encode.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-ffmpeg-compat.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-guacenc.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-image-stream.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-blob.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-cfill.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-copy.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-cursor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-dispose.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-end.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-img.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-mouse.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-move.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-rect.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-shade.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-size.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-sync.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instruction-transfer.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-instructions.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-jpeg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-layer.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-log.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-parse.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-png.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-video.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guacenc-webp.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< guacenc-buffer.o: buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-buffer.o -MD -MP -MF $(DEPDIR)/guacenc-buffer.Tpo -c -o guacenc-buffer.o `test -f 'buffer.c' || echo '$(srcdir)/'`buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-buffer.Tpo $(DEPDIR)/guacenc-buffer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='buffer.c' object='guacenc-buffer.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-buffer.o `test -f 'buffer.c' || echo '$(srcdir)/'`buffer.c guacenc-buffer.obj: buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-buffer.obj -MD -MP -MF $(DEPDIR)/guacenc-buffer.Tpo -c -o guacenc-buffer.obj `if test -f 'buffer.c'; then $(CYGPATH_W) 'buffer.c'; else $(CYGPATH_W) '$(srcdir)/buffer.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-buffer.Tpo $(DEPDIR)/guacenc-buffer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='buffer.c' object='guacenc-buffer.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-buffer.obj `if test -f 'buffer.c'; then $(CYGPATH_W) 'buffer.c'; else $(CYGPATH_W) '$(srcdir)/buffer.c'; fi` guacenc-cursor.o: cursor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-cursor.o -MD -MP -MF $(DEPDIR)/guacenc-cursor.Tpo -c -o guacenc-cursor.o `test -f 'cursor.c' || echo '$(srcdir)/'`cursor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-cursor.Tpo $(DEPDIR)/guacenc-cursor.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cursor.c' object='guacenc-cursor.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-cursor.o `test -f 'cursor.c' || echo '$(srcdir)/'`cursor.c guacenc-cursor.obj: cursor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-cursor.obj -MD -MP -MF $(DEPDIR)/guacenc-cursor.Tpo -c -o guacenc-cursor.obj `if test -f 'cursor.c'; then $(CYGPATH_W) 'cursor.c'; else $(CYGPATH_W) '$(srcdir)/cursor.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-cursor.Tpo $(DEPDIR)/guacenc-cursor.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cursor.c' object='guacenc-cursor.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-cursor.obj `if test -f 'cursor.c'; then $(CYGPATH_W) 'cursor.c'; else $(CYGPATH_W) '$(srcdir)/cursor.c'; fi` guacenc-display.o: display.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-display.o -MD -MP -MF $(DEPDIR)/guacenc-display.Tpo -c -o guacenc-display.o `test -f 'display.c' || echo '$(srcdir)/'`display.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-display.Tpo $(DEPDIR)/guacenc-display.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display.c' object='guacenc-display.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-display.o `test -f 'display.c' || echo '$(srcdir)/'`display.c guacenc-display.obj: display.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-display.obj -MD -MP -MF $(DEPDIR)/guacenc-display.Tpo -c -o guacenc-display.obj `if test -f 'display.c'; then $(CYGPATH_W) 'display.c'; else $(CYGPATH_W) '$(srcdir)/display.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-display.Tpo $(DEPDIR)/guacenc-display.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display.c' object='guacenc-display.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-display.obj `if test -f 'display.c'; then $(CYGPATH_W) 'display.c'; else $(CYGPATH_W) '$(srcdir)/display.c'; fi` guacenc-display-buffers.o: display-buffers.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-display-buffers.o -MD -MP -MF $(DEPDIR)/guacenc-display-buffers.Tpo -c -o guacenc-display-buffers.o `test -f 'display-buffers.c' || echo '$(srcdir)/'`display-buffers.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-display-buffers.Tpo $(DEPDIR)/guacenc-display-buffers.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display-buffers.c' object='guacenc-display-buffers.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-display-buffers.o `test -f 'display-buffers.c' || echo '$(srcdir)/'`display-buffers.c guacenc-display-buffers.obj: display-buffers.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-display-buffers.obj -MD -MP -MF $(DEPDIR)/guacenc-display-buffers.Tpo -c -o guacenc-display-buffers.obj `if test -f 'display-buffers.c'; then $(CYGPATH_W) 'display-buffers.c'; else $(CYGPATH_W) '$(srcdir)/display-buffers.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-display-buffers.Tpo $(DEPDIR)/guacenc-display-buffers.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display-buffers.c' object='guacenc-display-buffers.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-display-buffers.obj `if test -f 'display-buffers.c'; then $(CYGPATH_W) 'display-buffers.c'; else $(CYGPATH_W) '$(srcdir)/display-buffers.c'; fi` guacenc-display-image-streams.o: display-image-streams.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-display-image-streams.o -MD -MP -MF $(DEPDIR)/guacenc-display-image-streams.Tpo -c -o guacenc-display-image-streams.o `test -f 'display-image-streams.c' || echo '$(srcdir)/'`display-image-streams.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-display-image-streams.Tpo $(DEPDIR)/guacenc-display-image-streams.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display-image-streams.c' object='guacenc-display-image-streams.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-display-image-streams.o `test -f 'display-image-streams.c' || echo '$(srcdir)/'`display-image-streams.c guacenc-display-image-streams.obj: display-image-streams.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-display-image-streams.obj -MD -MP -MF $(DEPDIR)/guacenc-display-image-streams.Tpo -c -o guacenc-display-image-streams.obj `if test -f 'display-image-streams.c'; then $(CYGPATH_W) 'display-image-streams.c'; else $(CYGPATH_W) '$(srcdir)/display-image-streams.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-display-image-streams.Tpo $(DEPDIR)/guacenc-display-image-streams.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display-image-streams.c' object='guacenc-display-image-streams.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-display-image-streams.obj `if test -f 'display-image-streams.c'; then $(CYGPATH_W) 'display-image-streams.c'; else $(CYGPATH_W) '$(srcdir)/display-image-streams.c'; fi` guacenc-display-flatten.o: display-flatten.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-display-flatten.o -MD -MP -MF $(DEPDIR)/guacenc-display-flatten.Tpo -c -o guacenc-display-flatten.o `test -f 'display-flatten.c' || echo '$(srcdir)/'`display-flatten.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-display-flatten.Tpo $(DEPDIR)/guacenc-display-flatten.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display-flatten.c' object='guacenc-display-flatten.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-display-flatten.o `test -f 'display-flatten.c' || echo '$(srcdir)/'`display-flatten.c guacenc-display-flatten.obj: display-flatten.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-display-flatten.obj -MD -MP -MF $(DEPDIR)/guacenc-display-flatten.Tpo -c -o guacenc-display-flatten.obj `if test -f 'display-flatten.c'; then $(CYGPATH_W) 'display-flatten.c'; else $(CYGPATH_W) '$(srcdir)/display-flatten.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-display-flatten.Tpo $(DEPDIR)/guacenc-display-flatten.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display-flatten.c' object='guacenc-display-flatten.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-display-flatten.obj `if test -f 'display-flatten.c'; then $(CYGPATH_W) 'display-flatten.c'; else $(CYGPATH_W) '$(srcdir)/display-flatten.c'; fi` guacenc-display-layers.o: display-layers.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-display-layers.o -MD -MP -MF $(DEPDIR)/guacenc-display-layers.Tpo -c -o guacenc-display-layers.o `test -f 'display-layers.c' || echo '$(srcdir)/'`display-layers.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-display-layers.Tpo $(DEPDIR)/guacenc-display-layers.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display-layers.c' object='guacenc-display-layers.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-display-layers.o `test -f 'display-layers.c' || echo '$(srcdir)/'`display-layers.c guacenc-display-layers.obj: display-layers.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-display-layers.obj -MD -MP -MF $(DEPDIR)/guacenc-display-layers.Tpo -c -o guacenc-display-layers.obj `if test -f 'display-layers.c'; then $(CYGPATH_W) 'display-layers.c'; else $(CYGPATH_W) '$(srcdir)/display-layers.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-display-layers.Tpo $(DEPDIR)/guacenc-display-layers.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display-layers.c' object='guacenc-display-layers.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-display-layers.obj `if test -f 'display-layers.c'; then $(CYGPATH_W) 'display-layers.c'; else $(CYGPATH_W) '$(srcdir)/display-layers.c'; fi` guacenc-display-sync.o: display-sync.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-display-sync.o -MD -MP -MF $(DEPDIR)/guacenc-display-sync.Tpo -c -o guacenc-display-sync.o `test -f 'display-sync.c' || echo '$(srcdir)/'`display-sync.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-display-sync.Tpo $(DEPDIR)/guacenc-display-sync.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display-sync.c' object='guacenc-display-sync.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-display-sync.o `test -f 'display-sync.c' || echo '$(srcdir)/'`display-sync.c guacenc-display-sync.obj: display-sync.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-display-sync.obj -MD -MP -MF $(DEPDIR)/guacenc-display-sync.Tpo -c -o guacenc-display-sync.obj `if test -f 'display-sync.c'; then $(CYGPATH_W) 'display-sync.c'; else $(CYGPATH_W) '$(srcdir)/display-sync.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-display-sync.Tpo $(DEPDIR)/guacenc-display-sync.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display-sync.c' object='guacenc-display-sync.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-display-sync.obj `if test -f 'display-sync.c'; then $(CYGPATH_W) 'display-sync.c'; else $(CYGPATH_W) '$(srcdir)/display-sync.c'; fi` guacenc-encode.o: encode.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-encode.o -MD -MP -MF $(DEPDIR)/guacenc-encode.Tpo -c -o guacenc-encode.o `test -f 'encode.c' || echo '$(srcdir)/'`encode.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-encode.Tpo $(DEPDIR)/guacenc-encode.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encode.c' object='guacenc-encode.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-encode.o `test -f 'encode.c' || echo '$(srcdir)/'`encode.c guacenc-encode.obj: encode.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-encode.obj -MD -MP -MF $(DEPDIR)/guacenc-encode.Tpo -c -o guacenc-encode.obj `if test -f 'encode.c'; then $(CYGPATH_W) 'encode.c'; else $(CYGPATH_W) '$(srcdir)/encode.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-encode.Tpo $(DEPDIR)/guacenc-encode.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encode.c' object='guacenc-encode.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-encode.obj `if test -f 'encode.c'; then $(CYGPATH_W) 'encode.c'; else $(CYGPATH_W) '$(srcdir)/encode.c'; fi` guacenc-ffmpeg-compat.o: ffmpeg-compat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-ffmpeg-compat.o -MD -MP -MF $(DEPDIR)/guacenc-ffmpeg-compat.Tpo -c -o guacenc-ffmpeg-compat.o `test -f 'ffmpeg-compat.c' || echo '$(srcdir)/'`ffmpeg-compat.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-ffmpeg-compat.Tpo $(DEPDIR)/guacenc-ffmpeg-compat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ffmpeg-compat.c' object='guacenc-ffmpeg-compat.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-ffmpeg-compat.o `test -f 'ffmpeg-compat.c' || echo '$(srcdir)/'`ffmpeg-compat.c guacenc-ffmpeg-compat.obj: ffmpeg-compat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-ffmpeg-compat.obj -MD -MP -MF $(DEPDIR)/guacenc-ffmpeg-compat.Tpo -c -o guacenc-ffmpeg-compat.obj `if test -f 'ffmpeg-compat.c'; then $(CYGPATH_W) 'ffmpeg-compat.c'; else $(CYGPATH_W) '$(srcdir)/ffmpeg-compat.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-ffmpeg-compat.Tpo $(DEPDIR)/guacenc-ffmpeg-compat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ffmpeg-compat.c' object='guacenc-ffmpeg-compat.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-ffmpeg-compat.obj `if test -f 'ffmpeg-compat.c'; then $(CYGPATH_W) 'ffmpeg-compat.c'; else $(CYGPATH_W) '$(srcdir)/ffmpeg-compat.c'; fi` guacenc-guacenc.o: guacenc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-guacenc.o -MD -MP -MF $(DEPDIR)/guacenc-guacenc.Tpo -c -o guacenc-guacenc.o `test -f 'guacenc.c' || echo '$(srcdir)/'`guacenc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-guacenc.Tpo $(DEPDIR)/guacenc-guacenc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='guacenc.c' object='guacenc-guacenc.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-guacenc.o `test -f 'guacenc.c' || echo '$(srcdir)/'`guacenc.c guacenc-guacenc.obj: guacenc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-guacenc.obj -MD -MP -MF $(DEPDIR)/guacenc-guacenc.Tpo -c -o guacenc-guacenc.obj `if test -f 'guacenc.c'; then $(CYGPATH_W) 'guacenc.c'; else $(CYGPATH_W) '$(srcdir)/guacenc.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-guacenc.Tpo $(DEPDIR)/guacenc-guacenc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='guacenc.c' object='guacenc-guacenc.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-guacenc.obj `if test -f 'guacenc.c'; then $(CYGPATH_W) 'guacenc.c'; else $(CYGPATH_W) '$(srcdir)/guacenc.c'; fi` guacenc-image-stream.o: image-stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-image-stream.o -MD -MP -MF $(DEPDIR)/guacenc-image-stream.Tpo -c -o guacenc-image-stream.o `test -f 'image-stream.c' || echo '$(srcdir)/'`image-stream.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-image-stream.Tpo $(DEPDIR)/guacenc-image-stream.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='image-stream.c' object='guacenc-image-stream.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-image-stream.o `test -f 'image-stream.c' || echo '$(srcdir)/'`image-stream.c guacenc-image-stream.obj: image-stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-image-stream.obj -MD -MP -MF $(DEPDIR)/guacenc-image-stream.Tpo -c -o guacenc-image-stream.obj `if test -f 'image-stream.c'; then $(CYGPATH_W) 'image-stream.c'; else $(CYGPATH_W) '$(srcdir)/image-stream.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-image-stream.Tpo $(DEPDIR)/guacenc-image-stream.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='image-stream.c' object='guacenc-image-stream.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-image-stream.obj `if test -f 'image-stream.c'; then $(CYGPATH_W) 'image-stream.c'; else $(CYGPATH_W) '$(srcdir)/image-stream.c'; fi` guacenc-instructions.o: instructions.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instructions.o -MD -MP -MF $(DEPDIR)/guacenc-instructions.Tpo -c -o guacenc-instructions.o `test -f 'instructions.c' || echo '$(srcdir)/'`instructions.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instructions.Tpo $(DEPDIR)/guacenc-instructions.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instructions.c' object='guacenc-instructions.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instructions.o `test -f 'instructions.c' || echo '$(srcdir)/'`instructions.c guacenc-instructions.obj: instructions.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instructions.obj -MD -MP -MF $(DEPDIR)/guacenc-instructions.Tpo -c -o guacenc-instructions.obj `if test -f 'instructions.c'; then $(CYGPATH_W) 'instructions.c'; else $(CYGPATH_W) '$(srcdir)/instructions.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instructions.Tpo $(DEPDIR)/guacenc-instructions.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instructions.c' object='guacenc-instructions.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instructions.obj `if test -f 'instructions.c'; then $(CYGPATH_W) 'instructions.c'; else $(CYGPATH_W) '$(srcdir)/instructions.c'; fi` guacenc-instruction-blob.o: instruction-blob.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-blob.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-blob.Tpo -c -o guacenc-instruction-blob.o `test -f 'instruction-blob.c' || echo '$(srcdir)/'`instruction-blob.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-blob.Tpo $(DEPDIR)/guacenc-instruction-blob.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-blob.c' object='guacenc-instruction-blob.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-blob.o `test -f 'instruction-blob.c' || echo '$(srcdir)/'`instruction-blob.c guacenc-instruction-blob.obj: instruction-blob.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-blob.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-blob.Tpo -c -o guacenc-instruction-blob.obj `if test -f 'instruction-blob.c'; then $(CYGPATH_W) 'instruction-blob.c'; else $(CYGPATH_W) '$(srcdir)/instruction-blob.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-blob.Tpo $(DEPDIR)/guacenc-instruction-blob.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-blob.c' object='guacenc-instruction-blob.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-blob.obj `if test -f 'instruction-blob.c'; then $(CYGPATH_W) 'instruction-blob.c'; else $(CYGPATH_W) '$(srcdir)/instruction-blob.c'; fi` guacenc-instruction-cfill.o: instruction-cfill.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-cfill.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-cfill.Tpo -c -o guacenc-instruction-cfill.o `test -f 'instruction-cfill.c' || echo '$(srcdir)/'`instruction-cfill.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-cfill.Tpo $(DEPDIR)/guacenc-instruction-cfill.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-cfill.c' object='guacenc-instruction-cfill.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-cfill.o `test -f 'instruction-cfill.c' || echo '$(srcdir)/'`instruction-cfill.c guacenc-instruction-cfill.obj: instruction-cfill.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-cfill.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-cfill.Tpo -c -o guacenc-instruction-cfill.obj `if test -f 'instruction-cfill.c'; then $(CYGPATH_W) 'instruction-cfill.c'; else $(CYGPATH_W) '$(srcdir)/instruction-cfill.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-cfill.Tpo $(DEPDIR)/guacenc-instruction-cfill.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-cfill.c' object='guacenc-instruction-cfill.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-cfill.obj `if test -f 'instruction-cfill.c'; then $(CYGPATH_W) 'instruction-cfill.c'; else $(CYGPATH_W) '$(srcdir)/instruction-cfill.c'; fi` guacenc-instruction-copy.o: instruction-copy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-copy.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-copy.Tpo -c -o guacenc-instruction-copy.o `test -f 'instruction-copy.c' || echo '$(srcdir)/'`instruction-copy.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-copy.Tpo $(DEPDIR)/guacenc-instruction-copy.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-copy.c' object='guacenc-instruction-copy.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-copy.o `test -f 'instruction-copy.c' || echo '$(srcdir)/'`instruction-copy.c guacenc-instruction-copy.obj: instruction-copy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-copy.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-copy.Tpo -c -o guacenc-instruction-copy.obj `if test -f 'instruction-copy.c'; then $(CYGPATH_W) 'instruction-copy.c'; else $(CYGPATH_W) '$(srcdir)/instruction-copy.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-copy.Tpo $(DEPDIR)/guacenc-instruction-copy.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-copy.c' object='guacenc-instruction-copy.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-copy.obj `if test -f 'instruction-copy.c'; then $(CYGPATH_W) 'instruction-copy.c'; else $(CYGPATH_W) '$(srcdir)/instruction-copy.c'; fi` guacenc-instruction-cursor.o: instruction-cursor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-cursor.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-cursor.Tpo -c -o guacenc-instruction-cursor.o `test -f 'instruction-cursor.c' || echo '$(srcdir)/'`instruction-cursor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-cursor.Tpo $(DEPDIR)/guacenc-instruction-cursor.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-cursor.c' object='guacenc-instruction-cursor.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-cursor.o `test -f 'instruction-cursor.c' || echo '$(srcdir)/'`instruction-cursor.c guacenc-instruction-cursor.obj: instruction-cursor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-cursor.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-cursor.Tpo -c -o guacenc-instruction-cursor.obj `if test -f 'instruction-cursor.c'; then $(CYGPATH_W) 'instruction-cursor.c'; else $(CYGPATH_W) '$(srcdir)/instruction-cursor.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-cursor.Tpo $(DEPDIR)/guacenc-instruction-cursor.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-cursor.c' object='guacenc-instruction-cursor.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-cursor.obj `if test -f 'instruction-cursor.c'; then $(CYGPATH_W) 'instruction-cursor.c'; else $(CYGPATH_W) '$(srcdir)/instruction-cursor.c'; fi` guacenc-instruction-dispose.o: instruction-dispose.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-dispose.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-dispose.Tpo -c -o guacenc-instruction-dispose.o `test -f 'instruction-dispose.c' || echo '$(srcdir)/'`instruction-dispose.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-dispose.Tpo $(DEPDIR)/guacenc-instruction-dispose.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-dispose.c' object='guacenc-instruction-dispose.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-dispose.o `test -f 'instruction-dispose.c' || echo '$(srcdir)/'`instruction-dispose.c guacenc-instruction-dispose.obj: instruction-dispose.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-dispose.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-dispose.Tpo -c -o guacenc-instruction-dispose.obj `if test -f 'instruction-dispose.c'; then $(CYGPATH_W) 'instruction-dispose.c'; else $(CYGPATH_W) '$(srcdir)/instruction-dispose.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-dispose.Tpo $(DEPDIR)/guacenc-instruction-dispose.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-dispose.c' object='guacenc-instruction-dispose.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-dispose.obj `if test -f 'instruction-dispose.c'; then $(CYGPATH_W) 'instruction-dispose.c'; else $(CYGPATH_W) '$(srcdir)/instruction-dispose.c'; fi` guacenc-instruction-end.o: instruction-end.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-end.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-end.Tpo -c -o guacenc-instruction-end.o `test -f 'instruction-end.c' || echo '$(srcdir)/'`instruction-end.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-end.Tpo $(DEPDIR)/guacenc-instruction-end.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-end.c' object='guacenc-instruction-end.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-end.o `test -f 'instruction-end.c' || echo '$(srcdir)/'`instruction-end.c guacenc-instruction-end.obj: instruction-end.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-end.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-end.Tpo -c -o guacenc-instruction-end.obj `if test -f 'instruction-end.c'; then $(CYGPATH_W) 'instruction-end.c'; else $(CYGPATH_W) '$(srcdir)/instruction-end.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-end.Tpo $(DEPDIR)/guacenc-instruction-end.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-end.c' object='guacenc-instruction-end.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-end.obj `if test -f 'instruction-end.c'; then $(CYGPATH_W) 'instruction-end.c'; else $(CYGPATH_W) '$(srcdir)/instruction-end.c'; fi` guacenc-instruction-img.o: instruction-img.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-img.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-img.Tpo -c -o guacenc-instruction-img.o `test -f 'instruction-img.c' || echo '$(srcdir)/'`instruction-img.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-img.Tpo $(DEPDIR)/guacenc-instruction-img.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-img.c' object='guacenc-instruction-img.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-img.o `test -f 'instruction-img.c' || echo '$(srcdir)/'`instruction-img.c guacenc-instruction-img.obj: instruction-img.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-img.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-img.Tpo -c -o guacenc-instruction-img.obj `if test -f 'instruction-img.c'; then $(CYGPATH_W) 'instruction-img.c'; else $(CYGPATH_W) '$(srcdir)/instruction-img.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-img.Tpo $(DEPDIR)/guacenc-instruction-img.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-img.c' object='guacenc-instruction-img.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-img.obj `if test -f 'instruction-img.c'; then $(CYGPATH_W) 'instruction-img.c'; else $(CYGPATH_W) '$(srcdir)/instruction-img.c'; fi` guacenc-instruction-mouse.o: instruction-mouse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-mouse.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-mouse.Tpo -c -o guacenc-instruction-mouse.o `test -f 'instruction-mouse.c' || echo '$(srcdir)/'`instruction-mouse.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-mouse.Tpo $(DEPDIR)/guacenc-instruction-mouse.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-mouse.c' object='guacenc-instruction-mouse.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-mouse.o `test -f 'instruction-mouse.c' || echo '$(srcdir)/'`instruction-mouse.c guacenc-instruction-mouse.obj: instruction-mouse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-mouse.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-mouse.Tpo -c -o guacenc-instruction-mouse.obj `if test -f 'instruction-mouse.c'; then $(CYGPATH_W) 'instruction-mouse.c'; else $(CYGPATH_W) '$(srcdir)/instruction-mouse.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-mouse.Tpo $(DEPDIR)/guacenc-instruction-mouse.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-mouse.c' object='guacenc-instruction-mouse.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-mouse.obj `if test -f 'instruction-mouse.c'; then $(CYGPATH_W) 'instruction-mouse.c'; else $(CYGPATH_W) '$(srcdir)/instruction-mouse.c'; fi` guacenc-instruction-move.o: instruction-move.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-move.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-move.Tpo -c -o guacenc-instruction-move.o `test -f 'instruction-move.c' || echo '$(srcdir)/'`instruction-move.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-move.Tpo $(DEPDIR)/guacenc-instruction-move.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-move.c' object='guacenc-instruction-move.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-move.o `test -f 'instruction-move.c' || echo '$(srcdir)/'`instruction-move.c guacenc-instruction-move.obj: instruction-move.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-move.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-move.Tpo -c -o guacenc-instruction-move.obj `if test -f 'instruction-move.c'; then $(CYGPATH_W) 'instruction-move.c'; else $(CYGPATH_W) '$(srcdir)/instruction-move.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-move.Tpo $(DEPDIR)/guacenc-instruction-move.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-move.c' object='guacenc-instruction-move.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-move.obj `if test -f 'instruction-move.c'; then $(CYGPATH_W) 'instruction-move.c'; else $(CYGPATH_W) '$(srcdir)/instruction-move.c'; fi` guacenc-instruction-rect.o: instruction-rect.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-rect.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-rect.Tpo -c -o guacenc-instruction-rect.o `test -f 'instruction-rect.c' || echo '$(srcdir)/'`instruction-rect.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-rect.Tpo $(DEPDIR)/guacenc-instruction-rect.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-rect.c' object='guacenc-instruction-rect.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-rect.o `test -f 'instruction-rect.c' || echo '$(srcdir)/'`instruction-rect.c guacenc-instruction-rect.obj: instruction-rect.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-rect.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-rect.Tpo -c -o guacenc-instruction-rect.obj `if test -f 'instruction-rect.c'; then $(CYGPATH_W) 'instruction-rect.c'; else $(CYGPATH_W) '$(srcdir)/instruction-rect.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-rect.Tpo $(DEPDIR)/guacenc-instruction-rect.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-rect.c' object='guacenc-instruction-rect.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-rect.obj `if test -f 'instruction-rect.c'; then $(CYGPATH_W) 'instruction-rect.c'; else $(CYGPATH_W) '$(srcdir)/instruction-rect.c'; fi` guacenc-instruction-shade.o: instruction-shade.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-shade.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-shade.Tpo -c -o guacenc-instruction-shade.o `test -f 'instruction-shade.c' || echo '$(srcdir)/'`instruction-shade.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-shade.Tpo $(DEPDIR)/guacenc-instruction-shade.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-shade.c' object='guacenc-instruction-shade.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-shade.o `test -f 'instruction-shade.c' || echo '$(srcdir)/'`instruction-shade.c guacenc-instruction-shade.obj: instruction-shade.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-shade.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-shade.Tpo -c -o guacenc-instruction-shade.obj `if test -f 'instruction-shade.c'; then $(CYGPATH_W) 'instruction-shade.c'; else $(CYGPATH_W) '$(srcdir)/instruction-shade.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-shade.Tpo $(DEPDIR)/guacenc-instruction-shade.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-shade.c' object='guacenc-instruction-shade.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-shade.obj `if test -f 'instruction-shade.c'; then $(CYGPATH_W) 'instruction-shade.c'; else $(CYGPATH_W) '$(srcdir)/instruction-shade.c'; fi` guacenc-instruction-size.o: instruction-size.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-size.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-size.Tpo -c -o guacenc-instruction-size.o `test -f 'instruction-size.c' || echo '$(srcdir)/'`instruction-size.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-size.Tpo $(DEPDIR)/guacenc-instruction-size.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-size.c' object='guacenc-instruction-size.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-size.o `test -f 'instruction-size.c' || echo '$(srcdir)/'`instruction-size.c guacenc-instruction-size.obj: instruction-size.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-size.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-size.Tpo -c -o guacenc-instruction-size.obj `if test -f 'instruction-size.c'; then $(CYGPATH_W) 'instruction-size.c'; else $(CYGPATH_W) '$(srcdir)/instruction-size.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-size.Tpo $(DEPDIR)/guacenc-instruction-size.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-size.c' object='guacenc-instruction-size.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-size.obj `if test -f 'instruction-size.c'; then $(CYGPATH_W) 'instruction-size.c'; else $(CYGPATH_W) '$(srcdir)/instruction-size.c'; fi` guacenc-instruction-sync.o: instruction-sync.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-sync.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-sync.Tpo -c -o guacenc-instruction-sync.o `test -f 'instruction-sync.c' || echo '$(srcdir)/'`instruction-sync.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-sync.Tpo $(DEPDIR)/guacenc-instruction-sync.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-sync.c' object='guacenc-instruction-sync.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-sync.o `test -f 'instruction-sync.c' || echo '$(srcdir)/'`instruction-sync.c guacenc-instruction-sync.obj: instruction-sync.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-sync.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-sync.Tpo -c -o guacenc-instruction-sync.obj `if test -f 'instruction-sync.c'; then $(CYGPATH_W) 'instruction-sync.c'; else $(CYGPATH_W) '$(srcdir)/instruction-sync.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-sync.Tpo $(DEPDIR)/guacenc-instruction-sync.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-sync.c' object='guacenc-instruction-sync.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-sync.obj `if test -f 'instruction-sync.c'; then $(CYGPATH_W) 'instruction-sync.c'; else $(CYGPATH_W) '$(srcdir)/instruction-sync.c'; fi` guacenc-instruction-transfer.o: instruction-transfer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-transfer.o -MD -MP -MF $(DEPDIR)/guacenc-instruction-transfer.Tpo -c -o guacenc-instruction-transfer.o `test -f 'instruction-transfer.c' || echo '$(srcdir)/'`instruction-transfer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-transfer.Tpo $(DEPDIR)/guacenc-instruction-transfer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-transfer.c' object='guacenc-instruction-transfer.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-transfer.o `test -f 'instruction-transfer.c' || echo '$(srcdir)/'`instruction-transfer.c guacenc-instruction-transfer.obj: instruction-transfer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-instruction-transfer.obj -MD -MP -MF $(DEPDIR)/guacenc-instruction-transfer.Tpo -c -o guacenc-instruction-transfer.obj `if test -f 'instruction-transfer.c'; then $(CYGPATH_W) 'instruction-transfer.c'; else $(CYGPATH_W) '$(srcdir)/instruction-transfer.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-instruction-transfer.Tpo $(DEPDIR)/guacenc-instruction-transfer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='instruction-transfer.c' object='guacenc-instruction-transfer.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-instruction-transfer.obj `if test -f 'instruction-transfer.c'; then $(CYGPATH_W) 'instruction-transfer.c'; else $(CYGPATH_W) '$(srcdir)/instruction-transfer.c'; fi` guacenc-jpeg.o: jpeg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-jpeg.o -MD -MP -MF $(DEPDIR)/guacenc-jpeg.Tpo -c -o guacenc-jpeg.o `test -f 'jpeg.c' || echo '$(srcdir)/'`jpeg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-jpeg.Tpo $(DEPDIR)/guacenc-jpeg.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jpeg.c' object='guacenc-jpeg.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-jpeg.o `test -f 'jpeg.c' || echo '$(srcdir)/'`jpeg.c guacenc-jpeg.obj: jpeg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-jpeg.obj -MD -MP -MF $(DEPDIR)/guacenc-jpeg.Tpo -c -o guacenc-jpeg.obj `if test -f 'jpeg.c'; then $(CYGPATH_W) 'jpeg.c'; else $(CYGPATH_W) '$(srcdir)/jpeg.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-jpeg.Tpo $(DEPDIR)/guacenc-jpeg.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jpeg.c' object='guacenc-jpeg.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-jpeg.obj `if test -f 'jpeg.c'; then $(CYGPATH_W) 'jpeg.c'; else $(CYGPATH_W) '$(srcdir)/jpeg.c'; fi` guacenc-layer.o: layer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-layer.o -MD -MP -MF $(DEPDIR)/guacenc-layer.Tpo -c -o guacenc-layer.o `test -f 'layer.c' || echo '$(srcdir)/'`layer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-layer.Tpo $(DEPDIR)/guacenc-layer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='layer.c' object='guacenc-layer.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-layer.o `test -f 'layer.c' || echo '$(srcdir)/'`layer.c guacenc-layer.obj: layer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-layer.obj -MD -MP -MF $(DEPDIR)/guacenc-layer.Tpo -c -o guacenc-layer.obj `if test -f 'layer.c'; then $(CYGPATH_W) 'layer.c'; else $(CYGPATH_W) '$(srcdir)/layer.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-layer.Tpo $(DEPDIR)/guacenc-layer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='layer.c' object='guacenc-layer.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-layer.obj `if test -f 'layer.c'; then $(CYGPATH_W) 'layer.c'; else $(CYGPATH_W) '$(srcdir)/layer.c'; fi` guacenc-log.o: log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-log.o -MD -MP -MF $(DEPDIR)/guacenc-log.Tpo -c -o guacenc-log.o `test -f 'log.c' || echo '$(srcdir)/'`log.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-log.Tpo $(DEPDIR)/guacenc-log.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='log.c' object='guacenc-log.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-log.o `test -f 'log.c' || echo '$(srcdir)/'`log.c guacenc-log.obj: log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-log.obj -MD -MP -MF $(DEPDIR)/guacenc-log.Tpo -c -o guacenc-log.obj `if test -f 'log.c'; then $(CYGPATH_W) 'log.c'; else $(CYGPATH_W) '$(srcdir)/log.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-log.Tpo $(DEPDIR)/guacenc-log.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='log.c' object='guacenc-log.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-log.obj `if test -f 'log.c'; then $(CYGPATH_W) 'log.c'; else $(CYGPATH_W) '$(srcdir)/log.c'; fi` guacenc-parse.o: parse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-parse.o -MD -MP -MF $(DEPDIR)/guacenc-parse.Tpo -c -o guacenc-parse.o `test -f 'parse.c' || echo '$(srcdir)/'`parse.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-parse.Tpo $(DEPDIR)/guacenc-parse.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parse.c' object='guacenc-parse.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-parse.o `test -f 'parse.c' || echo '$(srcdir)/'`parse.c guacenc-parse.obj: parse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-parse.obj -MD -MP -MF $(DEPDIR)/guacenc-parse.Tpo -c -o guacenc-parse.obj `if test -f 'parse.c'; then $(CYGPATH_W) 'parse.c'; else $(CYGPATH_W) '$(srcdir)/parse.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-parse.Tpo $(DEPDIR)/guacenc-parse.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parse.c' object='guacenc-parse.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-parse.obj `if test -f 'parse.c'; then $(CYGPATH_W) 'parse.c'; else $(CYGPATH_W) '$(srcdir)/parse.c'; fi` guacenc-png.o: png.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-png.o -MD -MP -MF $(DEPDIR)/guacenc-png.Tpo -c -o guacenc-png.o `test -f 'png.c' || echo '$(srcdir)/'`png.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-png.Tpo $(DEPDIR)/guacenc-png.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='png.c' object='guacenc-png.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-png.o `test -f 'png.c' || echo '$(srcdir)/'`png.c guacenc-png.obj: png.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-png.obj -MD -MP -MF $(DEPDIR)/guacenc-png.Tpo -c -o guacenc-png.obj `if test -f 'png.c'; then $(CYGPATH_W) 'png.c'; else $(CYGPATH_W) '$(srcdir)/png.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-png.Tpo $(DEPDIR)/guacenc-png.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='png.c' object='guacenc-png.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-png.obj `if test -f 'png.c'; then $(CYGPATH_W) 'png.c'; else $(CYGPATH_W) '$(srcdir)/png.c'; fi` guacenc-video.o: video.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-video.o -MD -MP -MF $(DEPDIR)/guacenc-video.Tpo -c -o guacenc-video.o `test -f 'video.c' || echo '$(srcdir)/'`video.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-video.Tpo $(DEPDIR)/guacenc-video.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='video.c' object='guacenc-video.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-video.o `test -f 'video.c' || echo '$(srcdir)/'`video.c guacenc-video.obj: video.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-video.obj -MD -MP -MF $(DEPDIR)/guacenc-video.Tpo -c -o guacenc-video.obj `if test -f 'video.c'; then $(CYGPATH_W) 'video.c'; else $(CYGPATH_W) '$(srcdir)/video.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-video.Tpo $(DEPDIR)/guacenc-video.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='video.c' object='guacenc-video.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-video.obj `if test -f 'video.c'; then $(CYGPATH_W) 'video.c'; else $(CYGPATH_W) '$(srcdir)/video.c'; fi` guacenc-webp.o: webp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-webp.o -MD -MP -MF $(DEPDIR)/guacenc-webp.Tpo -c -o guacenc-webp.o `test -f 'webp.c' || echo '$(srcdir)/'`webp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-webp.Tpo $(DEPDIR)/guacenc-webp.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='webp.c' object='guacenc-webp.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-webp.o `test -f 'webp.c' || echo '$(srcdir)/'`webp.c guacenc-webp.obj: webp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -MT guacenc-webp.obj -MD -MP -MF $(DEPDIR)/guacenc-webp.Tpo -c -o guacenc-webp.obj `if test -f 'webp.c'; then $(CYGPATH_W) 'webp.c'; else $(CYGPATH_W) '$(srcdir)/webp.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/guacenc-webp.Tpo $(DEPDIR)/guacenc-webp.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='webp.c' object='guacenc-webp.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(guacenc_CFLAGS) $(CFLAGS) -c -o guacenc-webp.obj `if test -f 'webp.c'; then $(CYGPATH_W) 'webp.c'; else $(CYGPATH_W) '$(srcdir)/webp.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/guacenc-buffer.Po -rm -f ./$(DEPDIR)/guacenc-cursor.Po -rm -f ./$(DEPDIR)/guacenc-display-buffers.Po -rm -f ./$(DEPDIR)/guacenc-display-flatten.Po -rm -f ./$(DEPDIR)/guacenc-display-image-streams.Po -rm -f ./$(DEPDIR)/guacenc-display-layers.Po -rm -f ./$(DEPDIR)/guacenc-display-sync.Po -rm -f ./$(DEPDIR)/guacenc-display.Po -rm -f ./$(DEPDIR)/guacenc-encode.Po -rm -f ./$(DEPDIR)/guacenc-ffmpeg-compat.Po -rm -f ./$(DEPDIR)/guacenc-guacenc.Po -rm -f ./$(DEPDIR)/guacenc-image-stream.Po -rm -f ./$(DEPDIR)/guacenc-instruction-blob.Po -rm -f ./$(DEPDIR)/guacenc-instruction-cfill.Po -rm -f ./$(DEPDIR)/guacenc-instruction-copy.Po -rm -f ./$(DEPDIR)/guacenc-instruction-cursor.Po -rm -f ./$(DEPDIR)/guacenc-instruction-dispose.Po -rm -f ./$(DEPDIR)/guacenc-instruction-end.Po -rm -f ./$(DEPDIR)/guacenc-instruction-img.Po -rm -f ./$(DEPDIR)/guacenc-instruction-mouse.Po -rm -f ./$(DEPDIR)/guacenc-instruction-move.Po -rm -f ./$(DEPDIR)/guacenc-instruction-rect.Po -rm -f ./$(DEPDIR)/guacenc-instruction-shade.Po -rm -f ./$(DEPDIR)/guacenc-instruction-size.Po -rm -f ./$(DEPDIR)/guacenc-instruction-sync.Po -rm -f ./$(DEPDIR)/guacenc-instruction-transfer.Po -rm -f ./$(DEPDIR)/guacenc-instructions.Po -rm -f ./$(DEPDIR)/guacenc-jpeg.Po -rm -f ./$(DEPDIR)/guacenc-layer.Po -rm -f ./$(DEPDIR)/guacenc-log.Po -rm -f ./$(DEPDIR)/guacenc-parse.Po -rm -f ./$(DEPDIR)/guacenc-png.Po -rm -f ./$(DEPDIR)/guacenc-video.Po -rm -f ./$(DEPDIR)/guacenc-webp.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/guacenc-buffer.Po -rm -f ./$(DEPDIR)/guacenc-cursor.Po -rm -f ./$(DEPDIR)/guacenc-display-buffers.Po -rm -f ./$(DEPDIR)/guacenc-display-flatten.Po -rm -f ./$(DEPDIR)/guacenc-display-image-streams.Po -rm -f ./$(DEPDIR)/guacenc-display-layers.Po -rm -f ./$(DEPDIR)/guacenc-display-sync.Po -rm -f ./$(DEPDIR)/guacenc-display.Po -rm -f ./$(DEPDIR)/guacenc-encode.Po -rm -f ./$(DEPDIR)/guacenc-ffmpeg-compat.Po -rm -f ./$(DEPDIR)/guacenc-guacenc.Po -rm -f ./$(DEPDIR)/guacenc-image-stream.Po -rm -f ./$(DEPDIR)/guacenc-instruction-blob.Po -rm -f ./$(DEPDIR)/guacenc-instruction-cfill.Po -rm -f ./$(DEPDIR)/guacenc-instruction-copy.Po -rm -f ./$(DEPDIR)/guacenc-instruction-cursor.Po -rm -f ./$(DEPDIR)/guacenc-instruction-dispose.Po -rm -f ./$(DEPDIR)/guacenc-instruction-end.Po -rm -f ./$(DEPDIR)/guacenc-instruction-img.Po -rm -f ./$(DEPDIR)/guacenc-instruction-mouse.Po -rm -f ./$(DEPDIR)/guacenc-instruction-move.Po -rm -f ./$(DEPDIR)/guacenc-instruction-rect.Po -rm -f ./$(DEPDIR)/guacenc-instruction-shade.Po -rm -f ./$(DEPDIR)/guacenc-instruction-size.Po -rm -f ./$(DEPDIR)/guacenc-instruction-sync.Po -rm -f ./$(DEPDIR)/guacenc-instruction-transfer.Po -rm -f ./$(DEPDIR)/guacenc-instructions.Po -rm -f ./$(DEPDIR)/guacenc-jpeg.Po -rm -f ./$(DEPDIR)/guacenc-layer.Po -rm -f ./$(DEPDIR)/guacenc-log.Po -rm -f ./$(DEPDIR)/guacenc-parse.Po -rm -f ./$(DEPDIR)/guacenc-png.Po -rm -f ./$(DEPDIR)/guacenc-video.Po -rm -f ./$(DEPDIR)/guacenc-webp.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-man uninstall-man: uninstall-man1 .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-man1 \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-man uninstall-man1 .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/guacenc/cursor.c0000644000175100001440000000307413702142276015557 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "buffer.h" #include "cursor.h" #include guacenc_cursor* guacenc_cursor_alloc() { /* Allocate new cursor */ guacenc_cursor* cursor = (guacenc_cursor*) malloc(sizeof(guacenc_cursor)); if (cursor == NULL) return NULL; /* Allocate associated buffer (image) */ cursor->buffer = guacenc_buffer_alloc(); if (cursor->buffer == NULL) { free(cursor); return NULL; } /* Do not initially render cursor, unless it moves */ cursor->x = cursor->y = -1; return cursor; } void guacenc_cursor_free(guacenc_cursor* cursor) { /* Ignore NULL cursors */ if (cursor == NULL) return; /* Free underlying buffer */ guacenc_buffer_free(cursor->buffer); free(cursor); } guacamole-server-1.3.0/src/guacenc/buffer.h0000644000175100001440000001052713613156714015524 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_BUFFER_H #define GUACENC_BUFFER_H #include "config.h" #include #include /** * The image and size storage for either a buffer (a Guacamole layer with a * negative index) or a layer (a Guacamole layer with a non-negative index). */ typedef struct guacenc_buffer { /** * Whether this buffer should be automatically resized to fit any draw * operation. */ bool autosize; /** * The width of this buffer or layer, in pixels. */ int width; /** * The height of this buffer or layer, in pixels. */ int height; /** * The number of bytes in each row of image data. */ int stride; /** * The underlying image data of this surface. If the width or height of * this surface are 0, this will be NULL. */ unsigned char* image; /** * The Cairo surface wrapping the underlying image data of this surface. If * the width or height of this surface are 0, this will be NULL. */ cairo_surface_t* surface; /** * The current graphics context of the Cairo surface. If the width or * height of this surface are 0, this will be NULL. */ cairo_t* cairo; } guacenc_buffer; /** * Allocates and initializes a new buffer object. This allocation is * independent of the Guacamole video encoder display; the allocated * guacenc_buffer will not automatically be associated with the active display. * * @return * A newly-allocated and initialized guacenc_buffer, or NULL if allocation * fails. */ guacenc_buffer* guacenc_buffer_alloc(); /** * Frees all memory associated with the given buffer object. If the buffer * provided is NULL, this function has no effect. * * @param buffer * The buffer to free, which may be NULL. */ void guacenc_buffer_free(guacenc_buffer* buffer); /** * Resizes the given buffer to the given dimensions, allocating or freeing * memory as necessary, and updating the buffer's width, height, and stride * properties. * * @param buffer * The buffer to resize. * * @param width * The new width of the buffer, in pixels. * * @param height * The new height of the buffer, in pixels. * * @return * Zero if the resize operation is successful, non-zero on error. */ int guacenc_buffer_resize(guacenc_buffer* buffer, int width, int height); /** * Resizes the given buffer as necessary to contain at the given X/Y * coordinate, allocating or freeing memory as necessary, and updating the * buffer's width, height, and stride properties. If the buffer already * contains the given coordinate, this function has no effect. * * @param buffer * The buffer to resize. * * @param x * The X coordinate to ensure is within the buffer. * * @param y * The Y coordinate to ensure is within the buffer. * * @return * Zero if the resize operation is successful or no resize was performed, * non-zero if the resize operation failed. */ int guacenc_buffer_fit(guacenc_buffer* buffer, int x, int y); /** * Copies the entire contents of the given source buffer to the destination * buffer, ignoring the current contents of the destination. The destination * buffer's contents are entirely replaced. * * @param dst * The destination buffer whose contents should be replaced. * * @param src * The source buffer whose contents should replace those of the destination * buffer. * * @return * Zero if the copy operation was successful, non-zero on failure. */ int guacenc_buffer_copy(guacenc_buffer* dst, guacenc_buffer* src); #endif guacamole-server-1.3.0/src/guacenc/instructions.c0000644000175100001440000000475613702142276017016 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "instructions.h" #include "log.h" #include #include guacenc_instruction_handler_mapping guacenc_instruction_handler_map[] = { {"blob", guacenc_handle_blob}, {"img", guacenc_handle_img}, {"end", guacenc_handle_end}, {"mouse", guacenc_handle_mouse}, {"sync", guacenc_handle_sync}, {"cursor", guacenc_handle_cursor}, {"copy", guacenc_handle_copy}, {"transfer", guacenc_handle_transfer}, {"size", guacenc_handle_size}, {"rect", guacenc_handle_rect}, {"cfill", guacenc_handle_cfill}, {"move", guacenc_handle_move}, {"shade", guacenc_handle_shade}, {"dispose", guacenc_handle_dispose}, {NULL, NULL} }; int guacenc_handle_instruction(guacenc_display* display, const char* opcode, int argc, char** argv) { /* Search through mapping for instruction handler having given opcode */ guacenc_instruction_handler_mapping* current = guacenc_instruction_handler_map; while (current->opcode != NULL) { /* Invoke handler if opcode matches (if defined) */ if (strcmp(current->opcode, opcode) == 0) { /* Invoke defined handler */ guacenc_instruction_handler* handler = current->handler; if (handler != NULL) return handler(display, argc, argv); /* Log defined but unimplemented instructions */ guacenc_log(GUAC_LOG_DEBUG, "\"%s\" not implemented", opcode); return 0; } /* Next candidate handler */ current++; } /* end opcode search */ /* Ignore any unknown instructions */ return 0; } guacamole-server-1.3.0/src/guacenc/video.h0000644000175100001440000001435413764613616015371 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_VIDEO_H #define GUACENC_VIDEO_H #include "config.h" #include "buffer.h" #include #include #ifndef AVCODEC_AVCODEC_H #include #endif #ifndef AVFORMAT_AVFORMAT_H #include #endif #include #include /** * The framerate at which video should be encoded, in frames per second. */ #define GUACENC_VIDEO_FRAMERATE 25 /** * A video which is actively being encoded. Frames can be added to the video * as they are generated, along with their associated timestamps, and the * corresponding video will be continuously written as it is encoded. */ typedef struct guacenc_video { /** * AVStream for video output. * Frames sent to this stream are written into * the output file in the specified container format. */ AVStream* output_stream; /** * The open encoding context from libavcodec, created for the codec * specified when this guacenc_video was created. */ AVCodecContext* context; /** * The open format context from libavformat, created for the file * container specified when this guacenc_video was created. */ AVFormatContext* container_format_context; /** * The width of the video, in pixels. */ int width; /** * The height of the video, in pixels. */ int height; /** * The desired output bitrate of the video, in bits per second. */ int bitrate; /** * An image data area containing the next frame to be written, encoded as * YCbCr image data in the format required by avcodec_encode_video2(), for * use and re-use as frames are rendered. */ AVFrame* next_frame; /** * The presentation timestamp that should be used for the next frame. This * is equivalent to the frame number. */ int64_t next_pts; /** * The timestamp associated with the last frame, or 0 if no frames have yet * been added. */ guac_timestamp last_timestamp; } guacenc_video; /** * Allocates a new guacenc_video which encodes video according to the given * specifications, saving the output in the given file. If the output file * already exists, encoding will be aborted, and the original file contents * will be preserved. Frames will be scaled up or down as necessary to fit the * given width and height. * * @param path * The full path to the file in which encoded video should be written. * * @param codec_name * The name of the codec to use for the video encoding, as defined by * ffmpeg / libavcodec. * * @param width * The width of the desired video, in pixels. * * @param height * The height of the desired video, in pixels. * * @param bitrate * The desired overall bitrate of the resulting encoded video, in bits per * second. */ guacenc_video* guacenc_video_alloc(const char* path, const char* codec_name, int width, int height, int bitrate); /** * Advances the timeline of the encoding process to the given timestamp, such * that frames added via guacenc_video_prepare_frame() will be encoded at the * proper frame boundaries within the video. Duplicate frames will be encoded * as necessary to ensure that the output is correctly timed with respect to * the given timestamp. This is particularly important as Guacamole does not * have a framerate per se, and the time between each Guacamole "frame" will * vary significantly. * * This function MUST be called prior to invoking guacenc_video_prepare_frame() * to ensure the prepared frame will be encoded at the correct point in time. * * @param video * The video whose timeline should be adjusted. * * @param timestamp * The Guacamole timestamp denoting the point in time that the video * timeline should be advanced to, as dictated by a parsed "sync" * instruction. * * @return * Zero if the timeline was adjusted successfully, non-zero if an error * occurs (such as during the encoding of duplicate frames). */ int guacenc_video_advance_timeline(guacenc_video* video, guac_timestamp timestamp); /** * Stores the given buffer within the given video structure such that it will * be written if it falls within proper frame boundaries. If the timeline of * the video (as dictated by guacenc_video_advance_timeline()) is not at a * frame boundary with respect to the video framerate (it occurs between frame * boundaries), the prepared frame will only be written if another frame is not * prepared within the same pair of frame boundaries). The prepared frame will * not be written until it is implicitly flushed through updates to the video * timeline or through reaching the end of the encoding process * (guacenc_video_free()). * * @param video * The video in which the given buffer should be queued for possible * writing (depending on timing vs. video framerate). * * @param buffer * The guacenc_buffer representing the image data of the frame that should * be queued. */ void guacenc_video_prepare_frame(guacenc_video* video, guacenc_buffer* buffer); /** * Frees all resources associated with the given video, finalizing the encoding * process. Any buffered frames which have not yet been written will be written * at this point. * * @return * Zero if the video was successfully written and freed, non-zero if the * video could not be written due to an error. */ int guacenc_video_free(guacenc_video* video); #endif guacamole-server-1.3.0/src/guacenc/display.h0000644000175100001440000003014013702142276015706 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_DISPLAY_H #define GUACENC_DISPLAY_H #include "config.h" #include "buffer.h" #include "cursor.h" #include "image-stream.h" #include "layer.h" #include "video.h" #include #include #include /** * The maximum number of buffers that the Guacamole video encoder will handle * within a single Guacamole protocol dump. */ #define GUACENC_DISPLAY_MAX_BUFFERS 4096 /** * The maximum number of layers that the Guacamole video encoder will handle * within a single Guacamole protocol dump. */ #define GUACENC_DISPLAY_MAX_LAYERS 64 /** * The maximum number of streams that the Guacamole video encoder will handle * within a single Guacamole protocol dump. */ #define GUACENC_DISPLAY_MAX_STREAMS 64 /** * The current state of the Guacamole video encoder's internal display. */ typedef struct guacenc_display { /** * The current mouse cursor state. */ guacenc_cursor* cursor; /** * All currently-allocated buffers. The index of the buffer corresponds to * its position within this array, where -1 is the 0th entry. If a buffer * has not yet been allocated, or a buffer has been freed (due to a * "dispose" instruction), its entry here will be NULL. */ guacenc_buffer* buffers[GUACENC_DISPLAY_MAX_BUFFERS]; /** * All currently-allocated layers. The index of the layer corresponds to * its position within this array. If a layer has not yet been allocated, * or a layer has been freed (due to a "dispose" instruction), its entry * here will be NULL. */ guacenc_layer* layers[GUACENC_DISPLAY_MAX_LAYERS]; /** * All currently-allocated image streams. The index of the stream * corresponds to its position within this array. If a stream has not yet * been allocated, or a stream has been freed (due to an "end" * instruction), its entry here will be NULL. */ guacenc_image_stream* image_streams[GUACENC_DISPLAY_MAX_STREAMS]; /** * The timestamp of the last sync instruction handled, or 0 if no sync has * yet been read. */ guac_timestamp last_sync; /** * The video that this display is recording to. */ guacenc_video* output; } guacenc_display; /** * Handles a received "sync" instruction having the given timestamp, flushing * the current display to the in-progress video encoding. * * @param display * The display to flush to the video encoding as a new frame. * * @param timestamp * The timestamp of the new frame, as dictated by the "sync" instruction * sent at the end of the frame. * * @return * Zero if the frame was successfully written, non-zero if an error occurs. */ int guacenc_display_sync(guacenc_display* display, guac_timestamp timestamp); /** * Flattens the given display, rendering all child layers to the frame buffers * of their parent layers. The frame buffer of the default layer of the display * will thus contain the flattened, composited rendering of the entire display * state after this function succeeds. The contents of the frame buffers of * each layer are replaced by this function. * * @param display * The display to flatten. * * @return * Zero if the flatten operation succeeds, non-zero if an error occurs * preventing proper rendering. */ int guacenc_display_flatten(guacenc_display* display); /** * Allocates a new Guacamole video encoder display. This display serves as the * representation of encoding state, as well as the state of the Guacamole * display as instructions are read and handled. * * @param path * The full path to the file in which encoded video should be written. * * @param codec * The name of the codec to use for the video encoding, as defined by * ffmpeg / libavcodec. * * @param width * The width of the desired video, in pixels. * * @param height * The height of the desired video, in pixels. * * @param bitrate * The desired overall bitrate of the resulting encoded video, in bits per * second. * * @return * The newly-allocated Guacamole video encoder display, or NULL if the * display could not be allocated. */ guacenc_display* guacenc_display_alloc(const char* path, const char* codec, int width, int height, int bitrate); /** * Frees all memory associated with the given Guacamole video encoder display, * and finishes any underlying encoding process. If the given display is NULL, * this function has no effect. * * @param display * The Guacamole video encoder display to free, which may be NULL. * * @return * Zero if the encoding process completed successfully, non-zero otherwise. */ int guacenc_display_free(guacenc_display* display); /** * Returns the layer having the given index. A new layer will be allocated if * necessary. If the layer having the given index already exists, it will be * returned. * * @param display * The Guacamole video encoder display to retrieve the layer from. * * @param index * The index of the layer to retrieve. All valid layer indices are * non-negative. * * @return * The layer having the given index, or NULL if the index is invalid or * a new layer cannot be allocated. */ guacenc_layer* guacenc_display_get_layer(guacenc_display* display, int index); /** * Returns the depth of a given layer in terms of parent layers. The layer * depth is the number of layers above the given layer in hierarchy, where a * layer without any parent (such as the default layer) has a depth of 0. * * @param layer * The layer to check. * * @return * The depth of the layer. */ int guacenc_display_get_depth(guacenc_display* display, guacenc_layer* layer); /** * Frees all resources associated with the layer having the given index. If * the layer has not been allocated, this function has no effect. * * @param display * The Guacamole video encoder display associated with the layer being * freed. * * @param index * The index of the layer to free. All valid layer indices are * non-negative. * * @return * Zero if the layer was successfully freed or was not allocated, non-zero * if the layer could not be freed as the index was invalid. */ int guacenc_display_free_layer(guacenc_display* display, int index); /** * Returns the buffer having the given index. A new buffer will be allocated if * necessary. If the buffer having the given index already exists, it will be * returned. * * @param display * The Guacamole video encoder display to retrieve the buffer from. * * @param index * The index of the buffer to retrieve. All valid buffer indices are * negative. * * @return * The buffer having the given index, or NULL if the index is invalid or * a new buffer cannot be allocated. */ guacenc_buffer* guacenc_display_get_buffer(guacenc_display* display, int index); /** * Frees all resources associated with the buffer having the given index. If * the buffer has not been allocated, this function has no effect. * * @param display * The Guacamole video encoder display associated with the buffer being * freed. * * @param index * The index of the buffer to free. All valid buffer indices are negative. * * @return * Zero if the buffer was successfully freed or was not allocated, non-zero * if the buffer could not be freed as the index was invalid. */ int guacenc_display_free_buffer(guacenc_display* display, int index); /** * Returns the buffer associated with the layer or buffer having the given * index. A new buffer or layer will be allocated if necessary. If the given * index refers to a layer (is non-negative), the buffer underlying that layer * will be returned. If the given index refers to a buffer (is negative), that * buffer will be returned directly. * * @param display * The Guacamole video encoder display to retrieve the buffer from. * * @param index * The index of the buffer or layer whose associated buffer should be * retrieved. * * @return * The buffer associated with the buffer or layer having the given index, * or NULL if the index is invalid. */ guacenc_buffer* guacenc_display_get_related_buffer(guacenc_display* display, int index); /** * Creates a new image stream having the given index. If the stream having the * given index already exists, it will be freed and replaced. If the mimetype * specified is not supported, the image stream will still be allocated but * will have no associated decoder (blobs send to that stream will have no * effect). * * @param display * The Guacamole video encoder display to associate with the * newly-created image stream. * * @param index * The index of the stream to create. All valid stream indices are * non-negative. * * @param mask * The Guacamole protocol compositing operation (channel mask) to apply * when drawing the image. * * @param layer_index * The index of the layer or buffer that the image should be drawn to. * * @param mimetype * The mimetype of the image data that will be received along this stream. * * @param x * The X coordinate of the upper-left corner of the rectangle within the * destination layer or buffer that the image should be drawn to. * * @param y * The Y coordinate of the upper-left corner of the rectangle within the * destination layer or buffer that the image should be drawn to. * * @return * Zero if the image stream was successfully created, non-zero otherwise. */ int guacenc_display_create_image_stream(guacenc_display* display, int index, int mask, int layer_index, const char* mimetype, int x, int y); /** * Returns the stream having the given index. If no such stream exists, NULL * will be returned. * * @param display * The Guacamole video encoder display to retrieve the image stream from. * * @param index * The index of the stream to retrieve. All valid stream indices are * non-negative. * * @return * The stream having the given index, or NULL if the index is invalid or * a no such stream exists. */ guacenc_image_stream* guacenc_display_get_image_stream( guacenc_display* display, int index); /** * Frees all resources associated with the stream having the given index. If * the stream has not been allocated, this function has no effect. * * @param display * The Guacamole video encoder display associated with the image stream * being freed. * * @param index * The index of the stream to free. All valid stream indices are * non-negative. * * @return * Zero if the stream was successfully freed or was not allocated, non-zero * if the stream could not be freed as the index was invalid. */ int guacenc_display_free_image_stream(guacenc_display* display, int index); /** * Translates the given Guacamole protocol compositing mode (channel mask) to * the corresponding Cairo composition operator. If no such operator exists, * CAIRO_OPERATOR_OVER will be returned by default. * * @param mask * The Guacamole protocol compositing mode (channel mask) to translate. * * @return * The cairo_operator_t that corresponds to the given compositing mode * (channel mask). CAIRO_OPERATOR_OVER will be returned by default if no * such operator exists. */ cairo_operator_t guacenc_display_cairo_operator(guac_composite_mode mask); #endif guacamole-server-1.3.0/src/guacenc/instruction-transfer.c0000644000175100001440000000333413613156714020447 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "log.h" #include #include int guacenc_handle_transfer(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 9) { guacenc_log(GUAC_LOG_WARNING, "\"transform\" instruction incomplete"); return 1; } /* Parse arguments */ int src_index = atoi(argv[0]); int src_x = atoi(argv[1]); int src_y = atoi(argv[2]); int src_w = atoi(argv[3]); int src_h = atoi(argv[4]); int function = atoi(argv[5]); int dst_index = atoi(argv[6]); int dst_x = atoi(argv[7]); int dst_y = atoi(argv[8]); /* TODO: Unimplemented for now (rarely used) */ guacenc_log(GUAC_LOG_DEBUG, "transform: src_layer=%i (%i, %i) %ix%i " "function=0x%X dst_layer=%i (%i, %i)", src_index, src_x, src_y, src_w, src_h, function, dst_index, dst_x, dst_y); return 0; } guacamole-server-1.3.0/src/guacenc/display-buffers.c0000644000175100001440000000606513613156714017347 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "buffer.h" #include "layer.h" #include "log.h" #include #include guacenc_buffer* guacenc_display_get_buffer(guacenc_display* display, int index) { /* Transform index to buffer space */ int internal_index = -index - 1; /* Do not lookup / allocate if index is invalid */ if (internal_index < 0 || internal_index >= GUACENC_DISPLAY_MAX_BUFFERS) { guacenc_log(GUAC_LOG_WARNING, "Buffer index out of bounds: %i", index); return NULL; } /* Lookup buffer, allocating a new buffer if necessary */ guacenc_buffer* buffer = display->buffers[internal_index]; if (buffer == NULL) { /* Attempt to allocate buffer */ buffer = guacenc_buffer_alloc(); if (buffer == NULL) { guacenc_log(GUAC_LOG_WARNING, "Buffer allocation failed"); return NULL; } /* All non-layer buffers must autosize */ buffer->autosize = true; /* Store buffer within display for future retrieval / management */ display->buffers[internal_index] = buffer; } return buffer; } int guacenc_display_free_buffer(guacenc_display* display, int index) { /* Transform index to buffer space */ int internal_index = -index - 1; /* Do not lookup / free if index is invalid */ if (internal_index < 0 || internal_index >= GUACENC_DISPLAY_MAX_BUFFERS) { guacenc_log(GUAC_LOG_WARNING, "Buffer index out of bounds: %i", index); return 1; } /* Free buffer (if allocated) */ guacenc_buffer_free(display->buffers[internal_index]); /* Mark buffer as freed */ display->buffers[internal_index] = NULL; return 0; } guacenc_buffer* guacenc_display_get_related_buffer(guacenc_display* display, int index) { /* Retrieve underlying buffer of layer if a layer is requested */ if (index >= 0) { /* Retrieve / allocate layer (if possible */ guacenc_layer* layer = guacenc_display_get_layer(display, index); if (layer == NULL) return NULL; /* Return underlying buffer */ return layer->buffer; } /* Otherwise retrieve buffer directly */ return guacenc_display_get_buffer(display, index); } guacamole-server-1.3.0/src/guacenc/parse.h0000644000175100001440000000521713702142276015362 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_PARSE_H #define GUACENC_PARSE_H #include "config.h" #include /** * Parses a string into a single integer. Only positive integers are accepted. * The input string may be modified during parsing. A value will be stored in * the provided int pointer only if valid. * * @param arg * The string to parse. * * @param i * A pointer to the integer in which the parsed value of the given string * should be stored. * * @return * Zero if parsing was successful, non-zero if the provided string was * invalid. */ int guacenc_parse_int(char* arg, int* i); /** * Parses a string of the form WIDTHxHEIGHT into individual width and height * integers. The input string may be modified during parsing. Values will be * stored in the provided width and height pointers only if the given * dimensions are valid. * * @param arg * The string to parse. * * @param width * A pointer to the integer in which the parsed width component of the * given string should be stored. * * @param height * A pointer to the integer in which the parsed height component of the * given string should be stored. * * @return * Zero if parsing was successful, non-zero if the provided string was * invalid. */ int guacenc_parse_dimensions(char* arg, int* width, int* height); /** * Parses a guac_timestamp from the given string. The string is assumed to * consist solely of decimal digits with an optional leading minus sign. If the * given string contains other characters, the behavior of this function is * undefined. * * @param str * The string to parse, which must contain only decimal digits and an * optional leading minus sign. * * @return * A guac_timestamp having the same value as the provided string. */ guac_timestamp guacenc_parse_timestamp(const char* str); #endif guacamole-server-1.3.0/src/guacenc/ffmpeg-compat.h0000644000175100001440000001233213764613616017002 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_FFMPEG_COMPAT_H #define GUACENC_FFMPEG_COMPAT_H #include "config.h" #include "video.h" #include /* * For a full list of FFmpeg API changes over the years, see: * * https://github.com/FFmpeg/FFmpeg/blob/master/doc/APIchanges */ /* For libavcodec < 55.28.1: av_frame_*() was avcodec_*_frame(). */ #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1) #define av_frame_alloc avcodec_alloc_frame #define av_frame_free avcodec_free_frame #endif /* For libavcodec < 54.28.0: old avcodec_free_frame() did not exist. */ #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,28,0) #define avcodec_free_frame av_freep #endif /* For libavcodec < 55.52.0: avcodec_free_context did not exist */ #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,52,0) #define avcodec_free_context av_freep #endif /* For libavcodec < 57.7.0: av_packet_unref() was av_free_packet() */ #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,7,0) #define av_packet_unref av_free_packet #endif /* For libavcodec <= 56.41.100: Global header flag didn't have AV_ prefix. * Guacenc defines its own flag here to avoid conflicts with libavcodec * macros. */ #if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(56,41,100) #define GUACENC_FLAG_GLOBAL_HEADER CODEC_FLAG_GLOBAL_HEADER #else #define GUACENC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER #endif /* For libavutil < 51.42.0: AV_PIX_FMT_* was PIX_FMT_* */ #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51,42,0) #define AV_PIX_FMT_RGB32 PIX_FMT_RGB32 #define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P #endif /** * Writes the specied frame as a new frame of video. If pending frames of the * video are being flushed, the given frame may be NULL (as required by * avcodec_encode_video2()). If avcodec_encode_video2() does not exist, this * function will transparently use avcodec_encode_video(). * * @param video * The video to write the given frame to. * * @param frame * The frame to write to the video, or NULL if previously-written frames * are being flushed. * * @return * A positive value if the frame was successfully written, zero if the * frame has been saved for later writing / reordering, negative if an * error occurs. */ int guacenc_avcodec_encode_video(guacenc_video* video, AVFrame* frame); /** * Creates and sets up the AVCodecContext for the appropriate version of * libavformat installed. The AVCodecContext will be built, but the AVStream * will also be affected by having its time_base field set to the value passed * into this function. * * @param stream * The open AVStream. * * @param codec * The codec used on the AVStream. * * @param bitrate * The target bitrate for the encoded video * * @param width * The target width for the encoded video. * * @param height * The target height for the encoded video. * * @param gop_size * The size of the Group of Pictures. * * @param qmax * The max value of the quantizer. * * @param qmin * The min value of the quantizer. * * @param pix_fmt * The target pixel format for the encoded video. * * @param time_base * The target time base for the encoded video. * * @return * The pointer to the configured AVCodecContext. * */ AVCodecContext* guacenc_build_avcodeccontext(AVStream* stream, AVCodec* codec, int bitrate, int width, int height, int gop_size, int qmax, int qmin, int pix_fmt, AVRational time_base); /** * A wrapper for avcodec_open2(). Because libavformat ver 57.33.100 and greater * use stream->codecpar rather than stream->codec to handle information to the * codec, there needs to be an additional step in that version. So this * wrapper handles that. Otherwise, it's the same as avcodec_open2(). * * @param avcodec_context * The context to initialize. * * @param codec * The codec to open this context for. If a non-NULL codec has been * previously passed to avcodec_alloc_context3() or for this context, then * this parameter MUST be either NULL or equal to the previously passed * codec. * * @param options * A dictionary filled with AVCodecContext and codec-private options. On * return this object will be filled with options that were not found. * * @param stream * The stream for the codec context. * * @return * Zero on success, a negative value on error. */ int guacenc_open_avcodec(AVCodecContext *avcodec_context, AVCodec *codec, AVDictionary **options, AVStream* stream); #endif guacamole-server-1.3.0/src/guacenc/instruction-end.c0000644000175100001440000000323613613156714017372 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "image-stream.h" #include "log.h" #include #include int guacenc_handle_end(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 1) { guacenc_log(GUAC_LOG_WARNING, "\"end\" instruction incomplete"); return 1; } /* Parse arguments */ int index = atoi(argv[0]); /* Retrieve image stream */ guacenc_image_stream* stream = guacenc_display_get_image_stream(display, index); if (stream == NULL) return 1; /* Retrieve destination buffer */ guacenc_buffer* buffer = guacenc_display_get_related_buffer(display, stream->index); if (buffer == NULL) return 1; /* End image stream, drawing final image to the buffer */ return guacenc_image_stream_end(stream, buffer); } guacamole-server-1.3.0/src/guacenc/encode.h0000644000175100001440000000410113613156714015477 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUACENC_ENCODE_H #define GUACENC_ENCODE_H #include "config.h" #include /** * Encodes the given Guacamole protocol dump as video. A read lock will be * acquired on the input file to ensure that in-progress recordings are not * encoded. This behavior can be overridden by specifying true for the force * parameter. * * @param path * The path to the file containing the raw Guacamole protocol dump. * * @param out_path * The full path to the file in which encoded video should be written. * * @param codec * The name of the codec to use for the video encoding, as defined by * ffmpeg / libavcodec. * * @param width * The width of the desired video, in pixels. * * @param height * The height of the desired video, in pixels. * * @param bitrate * The desired overall bitrate of the resulting encoded video, in bits per * second. * * @param force * Perform the encoding, even if the input file appears to be an * in-progress recording (has an associated lock). * * @return * Zero on success, non-zero if an error prevented successful encoding of * the video. */ int guacenc_encode(const char* path, const char* out_path, const char* codec, int width, int height, int bitrate, bool force); #endif guacamole-server-1.3.0/src/guacenc/instruction-img.c0000644000175100001440000000275513613156714017405 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "log.h" #include #include int guacenc_handle_img(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 6) { guacenc_log(GUAC_LOG_WARNING, "\"img\" instruction incomplete"); return 1; } /* Parse arguments */ int stream_index = atoi(argv[0]); int mask = atoi(argv[1]); int layer_index = atoi(argv[2]); char* mimetype = argv[3]; int x = atoi(argv[4]); int y = atoi(argv[5]); /* Create requested stream */ return guacenc_display_create_image_stream(display, stream_index, mask, layer_index, mimetype, x, y); } guacamole-server-1.3.0/src/guacenc/instruction-cfill.c0000644000175100001440000000344113613156714017713 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "log.h" #include #include int guacenc_handle_cfill(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 6) { guacenc_log(GUAC_LOG_WARNING, "\"cfill\" instruction incomplete"); return 1; } /* Parse arguments */ int mask = atoi(argv[0]); int index = atoi(argv[1]); double r = atoi(argv[2]) / 255.0; double g = atoi(argv[3]) / 255.0; double b = atoi(argv[4]) / 255.0; double a = atoi(argv[5]) / 255.0; /* Pull buffer of requested layer/buffer */ guacenc_buffer* buffer = guacenc_display_get_related_buffer(display, index); if (buffer == NULL) return 1; /* Fill with RGBA color */ if (buffer->cairo != NULL) { cairo_set_operator(buffer->cairo, guacenc_display_cairo_operator(mask)); cairo_set_source_rgba(buffer->cairo, r, g, b, a); cairo_fill(buffer->cairo); } return 0; } guacamole-server-1.3.0/src/guacenc/encode.c0000644000175100001440000001131513702142276015474 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "instructions.h" #include "log.h" #include #include #include #include #include #include #include #include #include #include #include /** * Reads and handles all Guacamole instructions from the given guac_socket * until end-of-stream is reached. * * @param display * The current internal display of the Guacamole video encoder. * * @param path * The name of the file being parsed (for logging purposes). This file * must already be open and available through the given socket. * * @param socket * The guac_socket through which instructions should be read. * * @return * Zero on success, non-zero if parsing of Guacamole protocol data through * the given socket fails. */ static int guacenc_read_instructions(guacenc_display* display, const char* path, guac_socket* socket) { /* Obtain Guacamole protocol parser */ guac_parser* parser = guac_parser_alloc(); if (parser == NULL) return 1; /* Continuously read and handle all instructions */ while (!guac_parser_read(parser, socket, -1)) { if (guacenc_handle_instruction(display, parser->opcode, parser->argc, parser->argv)) { guacenc_log(GUAC_LOG_DEBUG, "Handling of \"%s\" instruction " "failed.", parser->opcode); } } /* Fail on read/parse error */ if (guac_error != GUAC_STATUS_CLOSED) { guacenc_log(GUAC_LOG_ERROR, "%s: %s", path, guac_status_string(guac_error)); guac_parser_free(parser); return 1; } /* Parse complete */ guac_parser_free(parser); return 0; } int guacenc_encode(const char* path, const char* out_path, const char* codec, int width, int height, int bitrate, bool force) { /* Open input file */ int fd = open(path, O_RDONLY); if (fd < 0) { guacenc_log(GUAC_LOG_ERROR, "%s: %s", path, strerror(errno)); return 1; } /* Lock entire input file for reading by the current process */ struct flock file_lock = { .l_type = F_RDLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0, .l_pid = getpid() }; /* Abort if file cannot be locked for reading */ if (!force && fcntl(fd, F_SETLK, &file_lock) == -1) { /* Warn if lock cannot be acquired */ if (errno == EACCES || errno == EAGAIN) guacenc_log(GUAC_LOG_WARNING, "Refusing to encode in-progress " "recording \"%s\" (specify the -f option to override " "this behavior).", path); /* Log an error if locking fails in an unexpected way */ else guacenc_log(GUAC_LOG_ERROR, "Cannot lock \"%s\" for reading: %s", path, strerror(errno)); close(fd); return 1; } /* Allocate display for encoding process */ guacenc_display* display = guacenc_display_alloc(out_path, codec, width, height, bitrate); if (display == NULL) { close(fd); return 1; } /* Obtain guac_socket wrapping file descriptor */ guac_socket* socket = guac_socket_open(fd); if (socket == NULL) { guacenc_log(GUAC_LOG_ERROR, "%s: %s", path, guac_status_string(guac_error)); close(fd); guacenc_display_free(display); return 1; } guacenc_log(GUAC_LOG_INFO, "Encoding \"%s\" to \"%s\" ...", path, out_path); /* Attempt to read all instructions in the file */ if (guacenc_read_instructions(display, path, socket)) { guac_socket_free(socket); guacenc_display_free(display); return 1; } /* Close input and finish encoding process */ guac_socket_free(socket); return guacenc_display_free(display); } guacamole-server-1.3.0/src/guacenc/image-stream.c0000644000175100001440000001117513702142276016616 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "image-stream.h" #include "jpeg.h" #include "log.h" #include "png.h" #ifdef ENABLE_WEBP #include "webp.h" #endif #include #include #include guacenc_decoder_mapping guacenc_decoder_map[] = { {"image/png", guacenc_png_decoder}, {"image/jpeg", guacenc_jpeg_decoder}, #ifdef ENABLE_WEBP {"image/webp", guacenc_webp_decoder}, #endif {NULL, NULL} }; guacenc_decoder* guacenc_get_decoder(const char* mimetype) { /* Search through mapping for the decoder having given mimetype */ guacenc_decoder_mapping* current = guacenc_decoder_map; while (current->mimetype != NULL) { /* Return decoder if mimetype matches */ if (strcmp(current->mimetype, mimetype) == 0) return current->decoder; /* Next candidate decoder */ current++; } /* No such decoder */ guacenc_log(GUAC_LOG_WARNING, "Support for \"%s\" not present", mimetype); return NULL; } guacenc_image_stream* guacenc_image_stream_alloc(int mask, int index, const char* mimetype, int x, int y) { /* Allocate stream */ guacenc_image_stream* stream = malloc(sizeof(guacenc_image_stream)); if (stream == NULL) return NULL; /* Init properties */ stream->index = index; stream->mask = mask; stream->x = x; stream->y = y; /* Associate with corresponding decoder */ stream->decoder = guacenc_get_decoder(mimetype); /* Allocate initial buffer */ stream->length = 0; stream->max_length = GUACENC_IMAGE_STREAM_INITIAL_LENGTH; stream->buffer = (unsigned char*) malloc(stream->max_length); return stream; } int guacenc_image_stream_receive(guacenc_image_stream* stream, unsigned char* data, int length) { /* Allocate more space if necessary */ if (stream->max_length - stream->length < length) { /* Calculate a reasonable new max length guaranteed to fit buffer */ int new_max_length = stream->max_length * 2 + length; /* Attempt to resize buffer */ unsigned char* new_buffer = (unsigned char*) realloc(stream->buffer, new_max_length); if (new_buffer == NULL) return 1; /* Store updated buffer and size */ stream->buffer = new_buffer; stream->max_length = new_max_length; } /* Append data */ memcpy(stream->buffer + stream->length, data, length); stream->length += length; return 0; } int guacenc_image_stream_end(guacenc_image_stream* stream, guacenc_buffer* buffer) { /* If there is no decoder, simply return success */ guacenc_decoder* decoder = stream->decoder; if (decoder == NULL) return 0; /* Decode received data to a Cairo surface */ cairo_surface_t* surface = stream->decoder(stream->buffer, stream->length); if (surface == NULL) return 1; /* Get surface dimensions */ int width = cairo_image_surface_get_width(surface); int height = cairo_image_surface_get_height(surface); /* Expand the buffer as necessary to fit the draw operation */ if (buffer->autosize) guacenc_buffer_fit(buffer, stream->x + width, stream->y + height); /* Draw surface to buffer */ if (buffer->cairo != NULL) { cairo_set_operator(buffer->cairo, guacenc_display_cairo_operator(stream->mask)); cairo_set_source_surface(buffer->cairo, surface, stream->x, stream->y); cairo_rectangle(buffer->cairo, stream->x, stream->y, width, height); cairo_fill(buffer->cairo); } cairo_surface_destroy(surface); return 0; } int guacenc_image_stream_free(guacenc_image_stream* stream) { /* Ignore NULL streams */ if (stream == NULL) return 0; /* Free image buffer */ free(stream->buffer); /* Free actual stream */ free(stream); return 0; } guacamole-server-1.3.0/src/guacenc/layer.c0000644000175100001440000000363413613156714015363 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "buffer.h" #include "layer.h" #include guacenc_layer* guacenc_layer_alloc() { /* Allocate new layer */ guacenc_layer* layer = (guacenc_layer*) calloc(1, sizeof(guacenc_layer)); if (layer == NULL) return NULL; /* Allocate associated buffer (width, height, and image storage) */ layer->buffer = guacenc_buffer_alloc(); if (layer->buffer == NULL) { free(layer); return NULL; } /* Allocate buffer for frame rendering */ layer->frame = guacenc_buffer_alloc(); if (layer->frame== NULL) { guacenc_buffer_free(layer->buffer); free(layer); return NULL; } /* Layers default to fully opaque */ layer->opacity = 0xFF; /* Default parented to default layer */ layer->parent_index = 0; return layer; } void guacenc_layer_free(guacenc_layer* layer) { /* Ignore NULL layers */ if (layer == NULL) return; /* Free internal frame buffer */ guacenc_buffer_free(layer->frame); /* Free underlying buffer */ guacenc_buffer_free(layer->buffer); free(layer); } guacamole-server-1.3.0/src/guacenc/display-layers.c0000644000175100001440000000550513613156714017210 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "layer.h" #include "log.h" #include #include guacenc_layer* guacenc_display_get_layer(guacenc_display* display, int index) { /* Do not lookup / allocate if index is invalid */ if (index < 0 || index >= GUACENC_DISPLAY_MAX_LAYERS) { guacenc_log(GUAC_LOG_WARNING, "Layer index out of bounds: %i", index); return NULL; } /* Lookup layer, allocating a new layer if necessary */ guacenc_layer* layer = display->layers[index]; if (layer == NULL) { /* Attempt to allocate layer */ layer = guacenc_layer_alloc(); if (layer == NULL) { guacenc_log(GUAC_LOG_WARNING, "Layer allocation failed"); return NULL; } /* The default layer has no parent */ if (index == 0) layer->parent_index = GUACENC_LAYER_NO_PARENT; /* Store layer within display for future retrieval / management */ display->layers[index] = layer; } return layer; } int guacenc_display_get_depth(guacenc_display* display, guacenc_layer* layer) { /* Non-existent layers have a depth of 0 */ if (layer == NULL) return 0; /* Layers with no parent have a depth of 0 */ if (layer->parent_index == GUACENC_LAYER_NO_PARENT) return 0; /* Retrieve parent layer */ guacenc_layer* parent = guacenc_display_get_layer(display, layer->parent_index); /* Current layer depth is the depth of the parent + 1 */ return guacenc_display_get_depth(display, parent) + 1; } int guacenc_display_free_layer(guacenc_display* display, int index) { /* Do not lookup / free if index is invalid */ if (index < 0 || index >= GUACENC_DISPLAY_MAX_LAYERS) { guacenc_log(GUAC_LOG_WARNING, "Layer index out of bounds: %i", index); return 1; } /* Free layer (if allocated) */ guacenc_layer_free(display->layers[index]); /* Mark layer as freed */ display->layers[index] = NULL; return 0; } guacamole-server-1.3.0/src/guacenc/display-image-streams.c0000644000175100001440000000502213613156714020441 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "image-stream.h" #include "log.h" #include #include int guacenc_display_create_image_stream(guacenc_display* display, int index, int mask, int layer_index, const char* mimetype, int x, int y) { /* Do not lookup / allocate if index is invalid */ if (index < 0 || index >= GUACENC_DISPLAY_MAX_STREAMS) { guacenc_log(GUAC_LOG_WARNING, "Stream index out of bounds: %i", index); return 1; } /* Free existing stream (if any) */ guacenc_image_stream_free(display->image_streams[index]); /* Associate new stream */ guacenc_image_stream* stream = display->image_streams[index] = guacenc_image_stream_alloc(mask, layer_index, mimetype, x, y); /* Return zero only if stream is not NULL */ return stream == NULL; } guacenc_image_stream* guacenc_display_get_image_stream( guacenc_display* display, int index) { /* Do not lookup / allocate if index is invalid */ if (index < 0 || index >= GUACENC_DISPLAY_MAX_STREAMS) { guacenc_log(GUAC_LOG_WARNING, "Stream index out of bounds: %i", index); return NULL; } /* Return existing stream (if any) */ return display->image_streams[index]; } int guacenc_display_free_image_stream(guacenc_display* display, int index) { /* Do not lookup / allocate if index is invalid */ if (index < 0 || index >= GUACENC_DISPLAY_MAX_STREAMS) { guacenc_log(GUAC_LOG_WARNING, "Stream index out of bounds: %i", index); return 1; } /* Free stream (if allocated) */ guacenc_image_stream_free(display->image_streams[index]); /* Mark stream as freed */ display->image_streams[index] = NULL; return 0; } guacamole-server-1.3.0/src/guacenc/parse.c0000644000175100001440000000423713702142276015356 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include #include #include #include #include int guacenc_parse_int(char* arg, int* i) { char* end; /* Parse string as an integer */ errno = 0; long int value = strtol(arg, &end, 10); /* Ignore number if invalid / non-positive */ if (errno != 0 || value <= 0 || value > INT_MAX || *end != '\0') return 1; /* Store value */ *i = value; /* Parsing successful */ return 0; } int guacenc_parse_dimensions(char* arg, int* width, int* height) { /* Locate the 'x' within the dimensions string */ char* x = strchr(arg, 'x'); if (x == NULL) return 1; /* Replace 'x' with a null terminator */ *x = '\0'; /* Parse width and height */ int w, h; if (guacenc_parse_int(arg, &w) || guacenc_parse_int(x+1, &h)) return 1; /* Width and height are both valid */ *width = w; *height = h; return 0; } guac_timestamp guacenc_parse_timestamp(const char* str) { int sign = 1; int64_t num = 0; for (; *str != '\0'; str++) { /* Flip sign for each '-' encountered */ if (*str == '-') sign = -sign; /* If not '-', assume the character is a digit */ else num = num * 10 + (*str - '0'); } return (guac_timestamp) (num * sign); } guacamole-server-1.3.0/src/guacenc/video.c0000644000175100001440000003664313764613616015371 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "buffer.h" #include "ffmpeg-compat.h" #include "log.h" #include "video.h" #include #include #ifndef AVFORMAT_AVFORMAT_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include guacenc_video* guacenc_video_alloc(const char* path, const char* codec_name, int width, int height, int bitrate) { AVOutputFormat *container_format; AVFormatContext *container_format_context; AVStream *video_stream; int ret; int failed_header = 0; /* allocate the output media context */ avformat_alloc_output_context2(&container_format_context, NULL, NULL, path); if (container_format_context == NULL) { guacenc_log(GUAC_LOG_ERROR, "Failed to determine container from output file name"); goto fail_codec; } container_format = container_format_context->oformat; /* Pull codec based on name */ AVCodec* codec = avcodec_find_encoder_by_name(codec_name); if (codec == NULL) { guacenc_log(GUAC_LOG_ERROR, "Failed to locate codec \"%s\".", codec_name); goto fail_codec; } /* create stream */ video_stream = NULL; video_stream = avformat_new_stream(container_format_context, codec); if (video_stream == NULL) { guacenc_log(GUAC_LOG_ERROR, "Could not allocate encoder stream. Cannot continue."); goto fail_format_context; } video_stream->id = container_format_context->nb_streams - 1; /* Retrieve encoding context */ AVCodecContext* avcodec_context = guacenc_build_avcodeccontext(video_stream, codec, bitrate, width, height, /*gop size*/ 10, /*qmax*/ 31, /*qmin*/ 2, /*pix fmt*/ AV_PIX_FMT_YUV420P, /*time base*/ (AVRational) { 1, GUACENC_VIDEO_FRAMERATE }); if (avcodec_context == NULL) { guacenc_log(GUAC_LOG_ERROR, "Failed to allocate context for " "codec \"%s\".", codec_name); goto fail_context; } /* If format needs global headers, write them */ if (container_format_context->oformat->flags & AVFMT_GLOBALHEADER) { avcodec_context->flags |= GUACENC_FLAG_GLOBAL_HEADER; } /* Open codec for use */ if (guacenc_open_avcodec(avcodec_context, codec, NULL, video_stream) < 0) { guacenc_log(GUAC_LOG_ERROR, "Failed to open codec \"%s\".", codec_name); goto fail_codec_open; } /* Allocate corresponding frame */ AVFrame* frame = av_frame_alloc(); if (frame == NULL) { goto fail_frame; } /* Copy necessary data for frame from context */ frame->format = avcodec_context->pix_fmt; frame->width = avcodec_context->width; frame->height = avcodec_context->height; /* Allocate actual backing data for frame */ if (av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, frame->format, 32) < 0) { goto fail_frame_data; } /* Open output file, if the container needs it */ if (!(container_format->flags & AVFMT_NOFILE)) { ret = avio_open(&container_format_context->pb, path, AVIO_FLAG_WRITE); if (ret < 0) { guacenc_log(GUAC_LOG_ERROR, "Error occurred while opening output file."); goto fail_output_avio; } } /* write the stream header, if needed */ ret = avformat_write_header(container_format_context, NULL); if (ret < 0) { guacenc_log(GUAC_LOG_ERROR, "Error occurred while writing output file header."); failed_header = true; goto fail_output_file; } /* Allocate video structure */ guacenc_video* video = malloc(sizeof(guacenc_video)); if (video == NULL) goto fail_alloc_video; /* Init properties of video */ video->output_stream = video_stream; video->context = avcodec_context; video->container_format_context = container_format_context; video->next_frame = frame; video->width = width; video->height = height; video->bitrate = bitrate; /* No frames have been written or prepared yet */ video->last_timestamp = 0; video->next_pts = 0; return video; /* Free all allocated data in case of failure */ fail_alloc_video: fail_output_file: avio_close(container_format_context->pb); /* Delete the file that was created if it was actually created */ if (unlink(path) == -1 && errno != ENOENT) guacenc_log(GUAC_LOG_WARNING, "Failed output file \"%s\" could not " "be automatically deleted: %s", path, strerror(errno)); fail_output_avio: av_freep(&frame->data[0]); fail_frame_data: av_frame_free(&frame); fail_frame: fail_codec_open: avcodec_free_context(&avcodec_context); fail_format_context: /* failing to write the container implicitly frees the context */ if (!failed_header) { avformat_free_context(container_format_context); } fail_context: fail_codec: return NULL; } /** * Flushes the specied frame as a new frame of video, updating the internal * video timestamp by one frame's worth of time. The pts member of the given * frame structure will be updated with the current presentation timestamp of * the video. If pending frames of the video are being flushed, the given frame * may be NULL (as required by avcodec_encode_video2()). * * @param video * The video to write the given frame to. * * @param frame * The frame to write to the video, or NULL if previously-written frames * are being flushed. * * @return * A positive value if the frame was successfully written, zero if the * frame has been saved for later writing / reordering, negative if an * error occurs. */ static int guacenc_video_write_frame(guacenc_video* video, AVFrame* frame) { /* Set timestamp of frame, if frame given */ if (frame != NULL) frame->pts = video->next_pts; /* Write frame to video */ int got_data = guacenc_avcodec_encode_video(video, frame); if (got_data < 0) return -1; /* Update presentation timestamp for next frame */ video->next_pts++; /* Write was successful */ return got_data; } /** * Flushes the frame previously specified by guacenc_video_prepare_frame() as a * new frame of video, updating the internal video timestamp by one frame's * worth of time. * * @param video * The video to flush. * * @return * Zero if flushing was successful, non-zero if an error occurs. */ static int guacenc_video_flush_frame(guacenc_video* video) { /* Write frame to video */ return guacenc_video_write_frame(video, video->next_frame) < 0; } int guacenc_video_advance_timeline(guacenc_video* video, guac_timestamp timestamp) { guac_timestamp next_timestamp = timestamp; /* Flush frames as necessary if previously updated */ if (video->last_timestamp != 0) { /* Calculate the number of frames that should have been written */ int elapsed = (timestamp - video->last_timestamp) * GUACENC_VIDEO_FRAMERATE / 1000; /* Keep previous timestamp if insufficient time has elapsed */ if (elapsed == 0) return 0; /* Use frame time as last_timestamp */ next_timestamp = video->last_timestamp + elapsed * 1000 / GUACENC_VIDEO_FRAMERATE; /* Flush frames to bring timeline in sync, duplicating if necessary */ do { if (guacenc_video_flush_frame(video)) { guacenc_log(GUAC_LOG_ERROR, "Unable to flush frame to video " "stream."); return 1; } } while (--elapsed != 0); } /* Update timestamp */ video->last_timestamp = next_timestamp; return 0; } /** * Converts the given Guacamole video encoder buffer to a frame in the format * required by libavcodec / libswscale. Black margins of the specified sizes * will be added. No scaling is performed; the image data is copied verbatim. * * @param buffer * The guacenc_buffer to copy as a new AVFrame. * * @param lsize * The size of the letterboxes to add, in pixels. Letterboxes are the * horizontal black boxes added to images which are scaled down to fit the * destination because they are too wide (the width is scaled to exactly * fit the destination, resulting in extra space at the top and bottom). * * @param psize * The size of the pillarboxes to add, in pixels. Pillarboxes are the * vertical black boxes added to images which are scaled down to fit the * destination because they are too tall (the height is scaled to exactly * fit the destination, resulting in extra space on the sides). * * @return * A pointer to a newly-allocated AVFrame containing exactly the same image * data as the given buffer. The image data within the frame and the frame * itself must be manually freed later. */ static AVFrame* guacenc_video_frame_convert(guacenc_buffer* buffer, int lsize, int psize) { /* Init size of left/right pillarboxes */ int left = psize; int right = psize; /* Init size of top/bottom letterboxes */ int top = lsize; int bottom = lsize; /* Prepare source frame for buffer */ AVFrame* frame = av_frame_alloc(); if (frame == NULL) return NULL; /* Copy buffer properties to frame */ frame->format = AV_PIX_FMT_RGB32; frame->width = buffer->width + left + right; frame->height = buffer->height + top + bottom; /* Allocate actual backing data for frame */ if (av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, frame->format, 32) < 0) { av_frame_free(&frame); return NULL; } /* Flush any pending operations */ cairo_surface_flush(buffer->surface); /* Get pointer to source image data */ unsigned char* src_data = buffer->image; int src_stride = buffer->stride; /* Get pointer to destination image data */ unsigned char* dst_data = frame->data[0]; int dst_stride = frame->linesize[0]; /* Get source/destination dimensions */ int width = buffer->width; int height = buffer->height; /* Source buffer is guaranteed to fit within destination buffer */ assert(width <= frame->width); assert(height <= frame->height); /* Add top margin */ while (top > 0) { memset(dst_data, 0, frame->width * 4); dst_data += dst_stride; top--; } /* Copy all data from source buffer to destination frame */ while (height > 0) { /* Calculate size of margin and data regions */ int left_size = left * 4; int data_size = width * 4; int right_size = right * 4; /* Add left margin */ memset(dst_data, 0, left_size); /* Copy data */ memcpy(dst_data + left_size, src_data, data_size); /* Add right margin */ memset(dst_data + left_size + data_size, 0, right_size); dst_data += dst_stride; src_data += src_stride; height--; } /* Add bottom margin */ while (bottom > 0) { memset(dst_data, 0, frame->width * 4); dst_data += dst_stride; bottom--; } /* Frame converted */ return frame; } void guacenc_video_prepare_frame(guacenc_video* video, guacenc_buffer* buffer) { int lsize; int psize; /* Ignore NULL buffers */ if (buffer == NULL || buffer->surface == NULL) return; /* Obtain destination frame */ AVFrame* dst = video->next_frame; /* Determine width of image if height is scaled to match destination */ int scaled_width = buffer->width * dst->height / buffer->height; /* Determine height of image if width is scaled to match destination */ int scaled_height = buffer->height * dst->width / buffer->width; /* If height-based scaling results in a fit width, add pillarboxes */ if (scaled_width <= dst->width) { lsize = 0; psize = (dst->width - scaled_width) * buffer->height / dst->height / 2; } /* If width-based scaling results in a fit width, add letterboxes */ else { assert(scaled_height <= dst->height); psize = 0; lsize = (dst->height - scaled_height) * buffer->width / dst->width / 2; } /* Prepare source frame for buffer */ AVFrame* src = guacenc_video_frame_convert(buffer, lsize, psize); if (src == NULL) { guacenc_log(GUAC_LOG_WARNING, "Failed to allocate source frame. " "Frame dropped."); return; } /* Prepare scaling context */ struct SwsContext* sws = sws_getContext(src->width, src->height, AV_PIX_FMT_RGB32, dst->width, dst->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); /* Abort if scaling context could not be created */ if (sws == NULL) { guacenc_log(GUAC_LOG_WARNING, "Failed to allocate software scaling " "context. Frame dropped."); av_freep(&src->data[0]); av_frame_free(&src); return; } /* Apply scaling, copying the source frame to the destination */ sws_scale(sws, (const uint8_t* const*) src->data, src->linesize, 0, src->height, dst->data, dst->linesize); /* Free scaling context */ sws_freeContext(sws); /* Free source frame */ av_freep(&src->data[0]); av_frame_free(&src); } int guacenc_video_free(guacenc_video* video) { /* Ignore NULL video */ if (video == NULL) return 0; /* Write final frame */ guacenc_video_flush_frame(video); /* Flush any unwritten frames */ int retval; do { retval = guacenc_video_write_frame(video, NULL); } while (retval > 0); /* write trailer, if needed */ if (video->container_format_context != NULL && video->output_stream != NULL) { guacenc_log(GUAC_LOG_DEBUG, "Writing trailer: %s", av_write_trailer(video->container_format_context) == 0 ? "success" : "failure"); } /* File is now completely written */ if (video->container_format_context != NULL) { avio_close(video->container_format_context->pb); } /* Free frame encoding data */ av_freep(&video->next_frame->data[0]); av_frame_free(&video->next_frame); /* Clean up encoding context */ if (video->context != NULL) { avcodec_close(video->context); avcodec_free_context(&(video->context)); } free(video); return 0; } guacamole-server-1.3.0/src/guacenc/instruction-move.c0000644000175100001440000000332313613156714017567 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "log.h" #include #include int guacenc_handle_move(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 5) { guacenc_log(GUAC_LOG_WARNING, "\"move\" instruction incomplete"); return 1; } /* Parse arguments */ int layer_index = atoi(argv[0]); int parent_index = atoi(argv[1]); int x = atoi(argv[2]); int y = atoi(argv[3]); int z = atoi(argv[4]); /* Retrieve requested layer */ guacenc_layer* layer = guacenc_display_get_layer(display, layer_index); if (layer == NULL) return 1; /* Validate parent layer */ if (guacenc_display_get_layer(display, parent_index) == NULL) return 1; /* Update layer properties */ layer->parent_index = parent_index; layer->x = x; layer->y = y; layer->z = z; return 0; } guacamole-server-1.3.0/src/guacenc/instruction-blob.c0000644000175100001440000000312713613156714017541 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "display.h" #include "log.h" #include #include #include int guacenc_handle_blob(guacenc_display* display, int argc, char** argv) { /* Verify argument count */ if (argc < 2) { guacenc_log(GUAC_LOG_WARNING, "\"blob\" instruction incomplete"); return 1; } /* Parse arguments */ int index = atoi(argv[0]); char* data = argv[1]; int length = guac_protocol_decode_base64(data); /* Retrieve image stream */ guacenc_image_stream* stream = guacenc_display_get_image_stream(display, index); if (stream == NULL) return 1; /* Send data to decoder within associated stream */ return guacenc_image_stream_receive(stream, (unsigned char*) data, length); } guacamole-server-1.3.0/src/guacenc/Makefile.am0000644000175100001440000000614513764613616016145 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign bin_PROGRAMS = guacenc man_MANS = \ man/guacenc.1 noinst_HEADERS = \ buffer.h \ cursor.h \ display.h \ encode.h \ ffmpeg-compat.h \ guacenc.h \ image-stream.h \ instructions.h \ jpeg.h \ layer.h \ log.h \ parse.h \ png.h \ video.h guacenc_SOURCES = \ buffer.c \ cursor.c \ display.c \ display-buffers.c \ display-image-streams.c \ display-flatten.c \ display-layers.c \ display-sync.c \ encode.c \ ffmpeg-compat.c \ guacenc.c \ image-stream.c \ instructions.c \ instruction-blob.c \ instruction-cfill.c \ instruction-copy.c \ instruction-cursor.c \ instruction-dispose.c \ instruction-end.c \ instruction-img.c \ instruction-mouse.c \ instruction-move.c \ instruction-rect.c \ instruction-shade.c \ instruction-size.c \ instruction-sync.c \ instruction-transfer.c \ jpeg.c \ layer.c \ log.c \ parse.c \ png.c \ video.c # Compile WebP support if available if ENABLE_WEBP guacenc_SOURCES += webp.c noinst_HEADERS += webp.h endif guacenc_CFLAGS = \ -Werror -Wall \ @AVCODEC_CFLAGS@ \ @AVFORMAT_CFLAGS@ \ @AVUTIL_CFLAGS@ \ @LIBGUAC_INCLUDE@ \ @SWSCALE_CFLAGS@ guacenc_LDADD = \ @LIBGUAC_LTLIB@ guacenc_LDFLAGS = \ @AVCODEC_LIBS@ \ @AVFORMAT_LIBS@ \ @AVUTIL_LIBS@ \ @CAIRO_LIBS@ \ @JPEG_LIBS@ \ @SWSCALE_LIBS@ \ @WEBP_LIBS@ EXTRA_DIST = \ man/guacenc.1.in guacamole-server-1.3.0/src/guacenc/buffer.c0000644000175100001440000001140113613156714015507 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "buffer.h" #include #include #include guacenc_buffer* guacenc_buffer_alloc() { return calloc(1, sizeof(guacenc_buffer)); } /** * Frees the underlying image data, surface, and graphics context of the given * buffer, marking each as unallocated. * * @param buffer * The guacenc_buffer whose image data, surface, and graphics context * should be freed. */ static void guacenc_buffer_free_image(guacenc_buffer* buffer) { /* Free graphics context */ if (buffer->cairo != NULL) { cairo_destroy(buffer->cairo); buffer->cairo = NULL; } /* Free Cairo surface */ if (buffer->surface != NULL) { cairo_surface_destroy(buffer->surface); buffer->surface = NULL; } /* Free image data (previously wrapped by Cairo surface */ free(buffer->image); buffer->image = NULL; } void guacenc_buffer_free(guacenc_buffer* buffer) { /* Ignore NULL buffer */ if (buffer == NULL) return; /* Free buffer and underlying image */ guacenc_buffer_free_image(buffer); free(buffer); } int guacenc_buffer_resize(guacenc_buffer* buffer, int width, int height) { /* Ignore requests which do not change the size */ if (buffer->width == width && buffer->height == height) return 0; /* Simply deallocate if new image has absolutely no pixels */ if (width == 0 || height == 0) { guacenc_buffer_free_image(buffer); buffer->width = width; buffer->height = height; buffer->stride = 0; return 0; } /* Allocate data for new image */ int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); unsigned char* image = calloc(1, stride*height); /* Wrap data in surface */ cairo_surface_t* surface = cairo_image_surface_create_for_data(image, CAIRO_FORMAT_ARGB32, width, height, stride); /* Obtain graphics context of new surface */ cairo_t* cairo = cairo_create(surface); /* Copy old surface, if defined */ if (buffer->surface != NULL) { cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(cairo, buffer->surface, 0, 0); cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); cairo_paint(cairo); } /* Update properties */ buffer->width = width; buffer->height = height; buffer->stride = stride; /* Replace old image */ guacenc_buffer_free_image(buffer); buffer->image = image; buffer->surface = surface; buffer->cairo = cairo; return 0; } int guacenc_buffer_fit(guacenc_buffer* buffer, int x, int y) { /* Increase width to fit X (if necessary) */ int new_width = buffer->width; if (new_width < x+1) new_width = x+1; /* Increase height to fit Y (if necessary) */ int new_height = buffer->height; if (new_height < y+1) new_height = y+1; /* Resize buffer if size needs to change to fit X/Y coordinate */ if (new_width != buffer->width || new_height != buffer->height) return guacenc_buffer_resize(buffer, new_width, new_height); /* No change necessary */ return 0; } int guacenc_buffer_copy(guacenc_buffer* dst, guacenc_buffer* src) { /* Resize destination to exactly fit source */ if (guacenc_buffer_resize(dst, src->width, src->height)) return 1; /* Copy surface contents identically */ if (src->surface != NULL) { /* Destination must be non-NULL as its size is that of the source */ assert(dst->cairo != NULL); /* Reset state of destination */ cairo_t* cairo = dst->cairo; cairo_reset_clip(cairo); /* Overwrite destination with contents of source */ cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(cairo, src->surface, 0, 0); cairo_paint(cairo); /* Reset operator of destination to default */ cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); } return 0; } guacamole-server-1.3.0/src/terminal/0000755000175100001440000000000013772471156014371 500000000000000guacamole-server-1.3.0/src/terminal/scrollbar.c0000644000175100001440000003756713613156714016454 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "terminal/scrollbar.h" #include #include #include #include #include guac_terminal_scrollbar* guac_terminal_scrollbar_alloc(guac_client* client, const guac_layer* parent, int parent_width, int parent_height, int visible_area) { /* Allocate scrollbar */ guac_terminal_scrollbar* scrollbar = malloc(sizeof(guac_terminal_scrollbar)); /* Associate client */ scrollbar->client = client; /* Init default min/max and value */ scrollbar->min = 0; scrollbar->max = 0; scrollbar->value = 0; /* Init parent data */ scrollbar->parent = parent; scrollbar->parent_width = 0; scrollbar->parent_height = 0; scrollbar->visible_area = 0; /* Init handle render state */ scrollbar->render_state.handle_x = 0; scrollbar->render_state.handle_y = 0; scrollbar->render_state.handle_width = 0; scrollbar->render_state.handle_height = 0; /* Init container render state */ scrollbar->render_state.container_x = 0; scrollbar->render_state.container_y = 0; scrollbar->render_state.container_width = 0; scrollbar->render_state.container_height = 0; /* Allocate and init layers */ scrollbar->container = guac_client_alloc_layer(client); scrollbar->handle = guac_client_alloc_layer(client); /* Init mouse event state tracking */ scrollbar->dragging_handle = 0; /* Reposition and resize to fit parent */ guac_terminal_scrollbar_parent_resized(scrollbar, parent_width, parent_height, visible_area); return scrollbar; } void guac_terminal_scrollbar_free(guac_terminal_scrollbar* scrollbar) { /* Free layers */ guac_client_free_layer(scrollbar->client, scrollbar->handle); guac_client_free_layer(scrollbar->client, scrollbar->container); /* Free scrollbar */ free(scrollbar); } /** * Moves the main scrollbar layer to the position indicated within the given * scrollbar render state, sending any necessary Guacamole instructions over * the given socket. * * @param scrollbar * The scrollbar to reposition. * * @param state * The guac_terminal_scrollbar_render_state describing the new scrollbar * position. * * @param socket * The guac_socket over which any instructions necessary to perform the * render operation should be sent. */ static void guac_terminal_scrollbar_move_container( guac_terminal_scrollbar* scrollbar, guac_terminal_scrollbar_render_state* state, guac_socket* socket) { /* Send scrollbar position */ guac_protocol_send_move(socket, scrollbar->container, scrollbar->parent, state->container_x, state->container_y, 0); } /** * Resizes and redraws the main scrollbar layer according to the given * scrollbar render state, sending any necessary Guacamole instructions over * the given socket. * * @param scrollbar * The scrollbar to resize and redraw. * * @param state * The guac_terminal_scrollbar_render_state describing the new scrollbar * size and appearance. * * @param socket * The guac_socket over which any instructions necessary to perform the * render operation should be sent. */ static void guac_terminal_scrollbar_draw_container( guac_terminal_scrollbar* scrollbar, guac_terminal_scrollbar_render_state* state, guac_socket* socket) { /* Set container size */ guac_protocol_send_size(socket, scrollbar->container, state->container_width, state->container_height); /* Fill container with solid color */ guac_protocol_send_rect(socket, scrollbar->container, 0, 0, state->container_width, state->container_height); guac_protocol_send_cfill(socket, GUAC_COMP_SRC, scrollbar->container, 0x80, 0x80, 0x80, 0x40); } /** * Moves the handle layer of the scrollbar to the position indicated within the * given scrollbar render state, sending any necessary Guacamole instructions * over the given socket. The handle is the portion of the scrollbar that * indicates the current scroll value and which the user can click and drag to * change the value. * * @param scrollbar * The scrollbar associated with the handle being repositioned. * * @param state * The guac_terminal_scrollbar_render_state describing the new scrollbar * handle position. * * @param socket * The guac_socket over which any instructions necessary to perform the * render operation should be sent. */ static void guac_terminal_scrollbar_move_handle( guac_terminal_scrollbar* scrollbar, guac_terminal_scrollbar_render_state* state, guac_socket* socket) { /* Send handle position */ guac_protocol_send_move(socket, scrollbar->handle, scrollbar->container, state->handle_x, state->handle_y, 0); } /** * Resizes and redraws the handle layer of the scrollbar according to the given * scrollbar render state, sending any necessary Guacamole instructions over * the given socket. The handle is the portion of the scrollbar that indicates * the current scroll value and which the user can click and drag to change the * value. * * @param scrollbar * The scrollbar associated with the handle being resized and redrawn. * * @param state * The guac_terminal_scrollbar_render_state describing the new scrollbar * handle size and appearance. * * @param socket * The guac_socket over which any instructions necessary to perform the * render operation should be sent. */ static void guac_terminal_scrollbar_draw_handle( guac_terminal_scrollbar* scrollbar, guac_terminal_scrollbar_render_state* state, guac_socket* socket) { /* Set handle size */ guac_protocol_send_size(socket, scrollbar->handle, state->handle_width, state->handle_height); /* Fill handle with solid color */ guac_protocol_send_rect(socket, scrollbar->handle, 0, 0, state->handle_width, state->handle_height); guac_protocol_send_cfill(socket, GUAC_COMP_SRC, scrollbar->handle, 0xA0, 0xA0, 0xA0, 0x8F); } /** * Calculates the state of the scroll bar, given its minimum, maximum, current * values, and the state of any dragging operation. The resulting render state * will not be reflected graphically unless the scrollbar is flushed, and any * resulting value will not be assigned to the scrollbar unless explicitly set * with guac_terminal_scrollbar_set_value(). * * @param scrollbar * The scrollbar whose state should be calculated. * * @param render_state * A pointer to an existing guac_terminal_scrollbar_render_state that will * be populated with the calculated result. * * @param value * A pointer to an existing int that will be populated with the updated * scrollbar value. */ static void calculate_state(guac_terminal_scrollbar* scrollbar, guac_terminal_scrollbar_render_state* render_state, int* value) { /* Use unchanged current value by default */ *value = scrollbar->value; /* Calculate container dimensions */ render_state->container_width = GUAC_TERMINAL_SCROLLBAR_WIDTH; render_state->container_height = scrollbar->parent_height; /* Calculate container position */ render_state->container_x = scrollbar->parent_width - render_state->container_width; render_state->container_y = 0; /* Calculate handle dimensions */ render_state->handle_width = render_state->container_width - GUAC_TERMINAL_SCROLLBAR_PADDING*2; /* Handle can be no bigger than the scrollbar itself */ int max_handle_height = render_state->container_height - GUAC_TERMINAL_SCROLLBAR_PADDING*2; /* Calculate legal delta between scroll values */ int scroll_delta; if (scrollbar->max > scrollbar->min) scroll_delta = scrollbar->max - scrollbar->min; else scroll_delta = 0; /* Scale handle relative to visible area vs. scrolling region size */ int proportional_height = max_handle_height * scrollbar->visible_area / (scroll_delta + scrollbar->visible_area); /* Ensure handle is no smaller than minimum height */ if (proportional_height > GUAC_TERMINAL_SCROLLBAR_MIN_HEIGHT) render_state->handle_height = proportional_height; else render_state->handle_height = GUAC_TERMINAL_SCROLLBAR_MIN_HEIGHT; /* Ensure handle is no larger than maximum height */ if (render_state->handle_height > max_handle_height) render_state->handle_height = max_handle_height; /* Calculate handle X position */ render_state->handle_x = GUAC_TERMINAL_SCROLLBAR_PADDING; /* Calculate handle Y range */ int min_handle_y = GUAC_TERMINAL_SCROLLBAR_PADDING; int max_handle_y = min_handle_y + max_handle_height - render_state->handle_height; /* Position handle relative to mouse if being dragged */ if (scrollbar->dragging_handle) { int dragged_handle_y = scrollbar->drag_current_y - scrollbar->drag_offset_y; /* Keep handle within bounds */ if (dragged_handle_y < min_handle_y) dragged_handle_y = min_handle_y; else if (dragged_handle_y > max_handle_y) dragged_handle_y = max_handle_y; render_state->handle_y = dragged_handle_y; /* Calculate scrollbar value */ if (max_handle_y > min_handle_y) { *value = scrollbar->min + (dragged_handle_y - min_handle_y) * scroll_delta / (max_handle_y - min_handle_y); } } /* Handle Y position is relative to current scroll value */ else if (scroll_delta > 0) render_state->handle_y = min_handle_y + (max_handle_y - min_handle_y) * (scrollbar->value - scrollbar->min) / scroll_delta; /* ... unless there is only one possible scroll value */ else render_state->handle_y = GUAC_TERMINAL_SCROLLBAR_PADDING; } void guac_terminal_scrollbar_dup(guac_terminal_scrollbar* scrollbar, guac_user* user, guac_socket* socket) { /* Get old state */ guac_terminal_scrollbar_render_state* state = &scrollbar->render_state; /* Send scrollbar container */ guac_terminal_scrollbar_draw_container(scrollbar, state, socket); guac_terminal_scrollbar_move_container(scrollbar, state, socket); /* Send handle */ guac_terminal_scrollbar_draw_handle(scrollbar, state, socket); guac_terminal_scrollbar_move_handle(scrollbar, state, socket); } void guac_terminal_scrollbar_flush(guac_terminal_scrollbar* scrollbar) { guac_socket* socket = scrollbar->client->socket; /* Get old state */ int old_value = scrollbar->value; guac_terminal_scrollbar_render_state* old_state = &scrollbar->render_state; /* Calculate new state */ int new_value; guac_terminal_scrollbar_render_state new_state; calculate_state(scrollbar, &new_state, &new_value); /* Notify of scroll if value is changing */ if (new_value != old_value && scrollbar->scroll_handler) scrollbar->scroll_handler(scrollbar, new_value); /* Reposition container if moved */ if (old_state->container_x != new_state.container_x || old_state->container_y != new_state.container_y) { guac_terminal_scrollbar_move_container(scrollbar, &new_state, socket); } /* Resize and redraw container if size changed */ if (old_state->container_width != new_state.container_width || old_state->container_height != new_state.container_height) { guac_terminal_scrollbar_draw_container(scrollbar, &new_state, socket); } /* Reposition handle if moved */ if (old_state->handle_x != new_state.handle_x || old_state->handle_y != new_state.handle_y) { guac_terminal_scrollbar_move_handle(scrollbar, &new_state, socket); } /* Resize and redraw handle if size changed */ if (old_state->handle_width != new_state.handle_width || old_state->handle_height != new_state.handle_height) { guac_terminal_scrollbar_draw_handle(scrollbar, &new_state, socket); } /* Store current render state */ scrollbar->render_state = new_state; } void guac_terminal_scrollbar_set_bounds(guac_terminal_scrollbar* scrollbar, int min, int max) { /* Fit value within bounds */ if (scrollbar->value > max) scrollbar->value = max; else if (scrollbar->value < min) scrollbar->value = min; /* Update bounds */ scrollbar->min = min; scrollbar->max = max; } void guac_terminal_scrollbar_set_value(guac_terminal_scrollbar* scrollbar, int value) { /* Fit value within bounds */ if (value > scrollbar->max) value = scrollbar->max; else if (value < scrollbar->min) value = scrollbar->min; /* Update value */ scrollbar->value = value; } void guac_terminal_scrollbar_parent_resized(guac_terminal_scrollbar* scrollbar, int parent_width, int parent_height, int visible_area) { /* Assign new dimensions */ scrollbar->parent_width = parent_width; scrollbar->parent_height = parent_height; scrollbar->visible_area = visible_area; } int guac_terminal_scrollbar_handle_mouse(guac_terminal_scrollbar* scrollbar, int x, int y, int mask) { /* Get container rectangle bounds */ int parent_left = scrollbar->render_state.container_x; int parent_top = scrollbar->render_state.container_y; int parent_right = parent_left + scrollbar->render_state.container_width; int parent_bottom = parent_top + scrollbar->render_state.container_height; /* Calculate handle rectangle bounds */ int handle_left = parent_left + scrollbar->render_state.handle_x; int handle_top = parent_top + scrollbar->render_state.handle_y; int handle_right = handle_left + scrollbar->render_state.handle_width; int handle_bottom = handle_top + scrollbar->render_state.handle_height; /* Handle click on handle */ if (scrollbar->dragging_handle) { /* Update drag while mouse button is held */ if (mask & GUAC_CLIENT_MOUSE_LEFT) scrollbar->drag_current_y = y; /* Stop drag if mouse button is released */ else scrollbar->dragging_handle = 0; /* Mouse event was handled by scrollbar */ return 1; } else if (mask == GUAC_CLIENT_MOUSE_LEFT && x >= handle_left && x < handle_right && y >= handle_top && y < handle_bottom) { /* Start drag */ scrollbar->dragging_handle = 1; scrollbar->drag_offset_y = y - handle_top; scrollbar->drag_current_y = y; /* Mouse event was handled by scrollbar */ return 1; } /* Eat any events that occur within the scrollbar */ return x >= parent_left && x < parent_right && y >= parent_top && y < parent_bottom; } guacamole-server-1.3.0/src/terminal/color-scheme.c0000644000175100001440000002130613764613616017037 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "terminal/color-scheme.h" #include "terminal/palette.h" #include "terminal/xparsecolor.h" #include #include #include #include #include /** * Compare a non-null-terminated string to a null-terminated literal, in the * same manner as strcmp(). * * @param str_start * Start of the non-null-terminated string. * * @param str_end * End of the non-null-terminated string, after the last character. * * @param literal * The null-terminated literal to compare against. * * @return * Zero if the two strings are equal and non-zero otherwise. */ static int guac_terminal_color_scheme_compare_token(const char* str_start, const char* str_end, const char* literal) { const int result = strncmp(literal, str_start, str_end - str_start); if (result != 0) return result; /* At this point, literal is same length or longer than * | str_end - str_start |, so if the two are equal, literal should * have its null-terminator at | str_end - str_start |. */ return (int) (unsigned char) literal[str_end - str_start]; } /** * Strip the leading and trailing spaces of a bounded string. * * @param[in,out] str_start * Address of a pointer to the start of the string. On return, the pointer * is advanced to after any leading spaces. * * @param[in,out] str_end * Address of a pointer to the end of the string, after the last character. * On return, the pointer is moved back to before any trailing spaces. */ static void guac_terminal_color_scheme_strip_spaces(const char** str_start, const char** str_end) { /* Strip leading spaces. */ while (*str_start < *str_end && isspace(**str_start)) (*str_start)++; /* Strip trailing spaces. */ while (*str_end > *str_start && isspace(*(*str_end - 1))) (*str_end)--; } /** * Parse the name part of the name-value pair within the color-scheme * configuration. * * @param client * The client that the terminal is connected to. * * @param name_start * Start of the name string. * * @param name_end * End of the name string, after the last character. * * @param foreground * Pointer to the foreground color. * * @param background * Pointer to the background color. * * @param palette * Pointer to the palette array. * * @param[out] target * On return, pointer to the color struct that corresponds to the name. * * @return * Zero if successful or non-zero otherwise. */ static int guac_terminal_parse_color_scheme_name(guac_client* client, const char* name_start, const char* name_end, guac_terminal_color* foreground, guac_terminal_color* background, guac_terminal_color (*palette)[256], guac_terminal_color** target) { guac_terminal_color_scheme_strip_spaces(&name_start, &name_end); if (!guac_terminal_color_scheme_compare_token( name_start, name_end, GUAC_TERMINAL_SCHEME_FOREGROUND)) { *target = foreground; return 0; } if (!guac_terminal_color_scheme_compare_token( name_start, name_end, GUAC_TERMINAL_SCHEME_BACKGROUND)) { *target = background; return 0; } /* Parse color value. */ int index = -1; if (sscanf(name_start, GUAC_TERMINAL_SCHEME_NUMBERED "%d", &index) && index >= 0 && index <= 255) { *target = &(*palette)[index]; return 0; } guac_client_log(client, GUAC_LOG_WARNING, "Unknown color name: \"%.*s\".", name_end - name_start, name_start); return 1; } /** * Parse the value part of the name-value pair within the color-scheme * configuration. * * @param client * The client that the terminal is connected to. * * @param value_start * Start of the value string. * * @param value_end * End of the value string, after the last character. * * @param palette * The current color palette. * * @param[out] target * On return, the parsed color. * * @return * Zero if successful or non-zero otherwise. */ static int guac_terminal_parse_color_scheme_value(guac_client* client, const char* value_start, const char* value_end, const guac_terminal_color (*palette)[256], guac_terminal_color* target) { guac_terminal_color_scheme_strip_spaces(&value_start, &value_end); /* Parse color value. */ int index = -1; if (sscanf(value_start, GUAC_TERMINAL_SCHEME_NUMBERED "%d", &index) && index >= 0 && index <= 255) { *target = (*palette)[index]; return 0; } /* Parse X11 value. */ if (!guac_terminal_xparsecolor(value_start, target)) return 0; guac_client_log(client, GUAC_LOG_WARNING, "Invalid color value: \"%.*s\".", value_end - value_start, value_start); return 1; } void guac_terminal_parse_color_scheme(guac_client* client, const char* color_scheme, guac_terminal_color* foreground, guac_terminal_color* background, guac_terminal_color (*palette)[256]) { /* Special cases. */ if (color_scheme[0] == '\0') { /* guac_terminal_parse_color_scheme defaults to gray-black */ } else if (strcmp(color_scheme, GUAC_TERMINAL_SCHEME_GRAY_BLACK) == 0) { color_scheme = "foreground:color7;background:color0"; } else if (strcmp(color_scheme, GUAC_TERMINAL_SCHEME_BLACK_WHITE) == 0) { color_scheme = "foreground:color0;background:color15"; } else if (strcmp(color_scheme, GUAC_TERMINAL_SCHEME_GREEN_BLACK) == 0) { color_scheme = "foreground:color2;background:color0"; } else if (strcmp(color_scheme, GUAC_TERMINAL_SCHEME_WHITE_BLACK) == 0) { color_scheme = "foreground:color15;background:color0"; } /* Set default gray-black color scheme and initial palette. */ *foreground = GUAC_TERMINAL_INITIAL_PALETTE[GUAC_TERMINAL_COLOR_GRAY]; *background = GUAC_TERMINAL_INITIAL_PALETTE[GUAC_TERMINAL_COLOR_BLACK]; memcpy(palette, GUAC_TERMINAL_INITIAL_PALETTE, sizeof(GUAC_TERMINAL_INITIAL_PALETTE)); /* Current char being parsed, or NULL if at end of parsing. */ const char* cursor = color_scheme; while (cursor) { /* Start of the current "name: value" pair. */ const char* pair_start = cursor; /* End of the current name-value pair. */ const char* pair_end = strchr(pair_start, ';'); if (pair_end) { cursor = pair_end + 1; } else { pair_end = pair_start + strlen(pair_start); cursor = NULL; } guac_terminal_color_scheme_strip_spaces(&pair_start, &pair_end); if (pair_start >= pair_end) /* Allow empty pairs, which happens, e.g., when the configuration * string ends in a semi-colon. */ continue; /* End of the name part of the pair. */ const char* name_end = memchr(pair_start, ':', pair_end - pair_start); if (name_end == NULL) { guac_client_log(client, GUAC_LOG_WARNING, "Expecting colon: \"%.*s\".", pair_end - pair_start, pair_start); return; } /* The color that the name corresponds to. */ guac_terminal_color* color_target = NULL; if (guac_terminal_parse_color_scheme_name( client, pair_start, name_end, foreground, background, palette, &color_target)) return; /* Parsing failed. */ if (guac_terminal_parse_color_scheme_value( client, name_end + 1, pair_end, (const guac_terminal_color(*)[256]) palette, color_target)) return; /* Parsing failed. */ } /* Persist pseudo-index for foreground/background colors */ foreground->palette_index = GUAC_TERMINAL_COLOR_FOREGROUND; background->palette_index = GUAC_TERMINAL_COLOR_BACKGROUND; } guacamole-server-1.3.0/src/terminal/display.c0000644000175100001440000010043213702142276016111 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/surface.h" #include "terminal/common.h" #include "terminal/display.h" #include "terminal/palette.h" #include "terminal/types.h" #include #include #include #include #include #include #include #include #include #include /* Maps any codepoint onto a number between 0 and 511 inclusive */ int __guac_terminal_hash_codepoint(int codepoint) { /* If within one byte, just return codepoint */ if (codepoint <= 0xFF) return codepoint; /* Otherwise, map to next 256 values */ return (codepoint & 0xFF) + 0x100; } /** * Sets the attributes of the display such that future glyphs will render as * expected. */ int __guac_terminal_set_colors(guac_terminal_display* display, guac_terminal_attributes* attributes) { const guac_terminal_color* background; const guac_terminal_color* foreground; /* Handle reverse video */ if (attributes->reverse != attributes->cursor) { background = &attributes->foreground; foreground = &attributes->background; } else { foreground = &attributes->foreground; background = &attributes->background; } /* Handle bold */ if (attributes->bold && !attributes->half_bright && foreground->palette_index >= GUAC_TERMINAL_FIRST_DARK && foreground->palette_index <= GUAC_TERMINAL_LAST_DARK) { foreground = &display->palette[foreground->palette_index + GUAC_TERMINAL_INTENSE_OFFSET]; } display->glyph_foreground = *foreground; guac_terminal_display_lookup_color(display, foreground->palette_index, &display->glyph_foreground); display->glyph_background = *background; guac_terminal_display_lookup_color(display, background->palette_index, &display->glyph_background); /* Modify color if half-bright (low intensity) */ if (attributes->half_bright && !attributes->bold) { display->glyph_foreground.red /= 2; display->glyph_foreground.green /= 2; display->glyph_foreground.blue /= 2; } return 0; } /** * Sends the given character to the terminal at the given row and column, * rendering the character immediately. This bypasses the guac_terminal_display * mechanism and is intended for flushing of updates only. */ int __guac_terminal_set(guac_terminal_display* display, int row, int col, int codepoint) { int width; int bytes; char utf8[4]; /* Use foreground color */ const guac_terminal_color* color = &display->glyph_foreground; /* Use background color */ const guac_terminal_color* background = &display->glyph_background; cairo_surface_t* surface; cairo_t* cairo; int surface_width, surface_height; PangoLayout* layout; int layout_width, layout_height; int ideal_layout_width, ideal_layout_height; /* Calculate width in columns */ width = wcwidth(codepoint); if (width < 0) width = 1; /* Do nothing if glyph is empty */ if (width == 0) return 0; /* Convert to UTF-8 */ bytes = guac_terminal_encode_utf8(codepoint, utf8); surface_width = width * display->char_width; surface_height = display->char_height; ideal_layout_width = surface_width * PANGO_SCALE; ideal_layout_height = surface_height * PANGO_SCALE; /* Prepare surface */ surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, surface_width, surface_height); cairo = cairo_create(surface); /* Fill background */ cairo_set_source_rgb(cairo, background->red / 255.0, background->green / 255.0, background->blue / 255.0); cairo_rectangle(cairo, 0, 0, surface_width, surface_height); cairo_fill(cairo); /* Get layout */ layout = pango_cairo_create_layout(cairo); pango_layout_set_font_description(layout, display->font_desc); pango_layout_set_text(layout, utf8, bytes); pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); pango_layout_get_size(layout, &layout_width, &layout_height); /* If layout bigger than available space, scale it back */ if (layout_width > ideal_layout_width || layout_height > ideal_layout_height) { double scale = fmin(ideal_layout_width / (double) layout_width, ideal_layout_height / (double) layout_height); cairo_scale(cairo, scale, scale); /* Update layout to reflect scaled surface */ pango_layout_set_width(layout, ideal_layout_width / scale); pango_layout_set_height(layout, ideal_layout_height / scale); pango_cairo_update_layout(cairo, layout); } /* Draw */ cairo_set_source_rgb(cairo, color->red / 255.0, color->green / 255.0, color->blue / 255.0); cairo_move_to(cairo, 0.0, 0.0); pango_cairo_show_layout(cairo, layout); /* Draw */ guac_common_surface_draw(display->display_surface, display->char_width * col, display->char_height * row, surface); /* Free all */ g_object_unref(layout); cairo_destroy(cairo); cairo_surface_destroy(surface); return 0; } guac_terminal_display* guac_terminal_display_alloc(guac_client* client, const char* font_name, int font_size, int dpi, guac_terminal_color* foreground, guac_terminal_color* background, guac_terminal_color (*palette)[256]) { /* Allocate display */ guac_terminal_display* display = malloc(sizeof(guac_terminal_display)); display->client = client; /* Initially no font loaded */ display->font_desc = NULL; display->char_width = 0; display->char_height = 0; /* Create default surface */ display->display_layer = guac_client_alloc_layer(client); display->select_layer = guac_client_alloc_layer(client); display->display_surface = guac_common_surface_alloc(client, client->socket, display->display_layer, 0, 0); /* Select layer is a child of the display layer */ guac_protocol_send_move(client->socket, display->select_layer, display->display_layer, 0, 0, 0); display->default_foreground = display->glyph_foreground = *foreground; display->default_background = display->glyph_background = *background; display->default_palette = palette; /* Initially empty */ display->width = 0; display->height = 0; display->operations = NULL; /* Initially nothing selected */ display->text_selected = false; /* Attempt to load font */ if (guac_terminal_display_set_font(display, font_name, font_size, dpi)) { guac_client_abort(display->client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to set initial font \"%s\"", font_name); free(display); return NULL; } return display; } void guac_terminal_display_free(guac_terminal_display* display) { /* Free font description */ pango_font_description_free(display->font_desc); /* Free default palette. */ free(display->default_palette); /* Free operations buffers */ free(display->operations); /* Free display */ free(display); } void guac_terminal_display_reset_palette(guac_terminal_display* display) { /* Reinitialize palette with default values */ if (display->default_palette) { memcpy(display->palette, *display->default_palette, sizeof(GUAC_TERMINAL_INITIAL_PALETTE)); return; } memcpy(display->palette, GUAC_TERMINAL_INITIAL_PALETTE, sizeof(GUAC_TERMINAL_INITIAL_PALETTE)); } int guac_terminal_display_assign_color(guac_terminal_display* display, int index, const guac_terminal_color* color) { /* Assignment fails if out-of-bounds */ if (index < 0 || index > 255) return 1; /* Copy color components */ display->palette[index].red = color->red; display->palette[index].green = color->green; display->palette[index].blue = color->blue; /* Color successfully stored */ return 0; } int guac_terminal_display_lookup_color(guac_terminal_display* display, int index, guac_terminal_color* color) { /* Use default foreground if foreground pseudo-index is given */ if (index == GUAC_TERMINAL_COLOR_FOREGROUND) { *color = display->default_foreground; return 0; } /* Use default background if background pseudo-index is given */ if (index == GUAC_TERMINAL_COLOR_BACKGROUND) { *color = display->default_background; return 0; } /* Lookup fails if out-of-bounds */ if (index < 0 || index > 255) return 1; /* Copy color definition */ *color = display->palette[index]; return 0; } void guac_terminal_display_copy_columns(guac_terminal_display* display, int row, int start_column, int end_column, int offset) { int i; guac_terminal_operation* src_current; guac_terminal_operation* current; /* Ignore operations outside display bounds */ if (row < 0 || row >= display->height) return; /* Fit range within bounds */ start_column = guac_terminal_fit_to_range(start_column, 0, display->width - 1); end_column = guac_terminal_fit_to_range(end_column, 0, display->width - 1); start_column = guac_terminal_fit_to_range(start_column + offset, 0, display->width - 1) - offset; end_column = guac_terminal_fit_to_range(end_column + offset, 0, display->width - 1) - offset; src_current = &(display->operations[row * display->width + start_column]); current = &(display->operations[row * display->width + start_column + offset]); /* Move data */ memmove(current, src_current, (end_column - start_column + 1) * sizeof(guac_terminal_operation)); /* Update operations */ for (i=start_column; i<=end_column; i++) { /* If no operation here, set as copy */ if (current->type == GUAC_CHAR_NOP) { current->type = GUAC_CHAR_COPY; current->row = row; current->column = i; } /* Next column */ current++; } } void guac_terminal_display_copy_rows(guac_terminal_display* display, int start_row, int end_row, int offset) { int row, col; guac_terminal_operation* src_current_row; guac_terminal_operation* current_row; /* Fit range within bounds */ start_row = guac_terminal_fit_to_range(start_row, 0, display->height - 1); end_row = guac_terminal_fit_to_range(end_row, 0, display->height - 1); start_row = guac_terminal_fit_to_range(start_row + offset, 0, display->height - 1) - offset; end_row = guac_terminal_fit_to_range(end_row + offset, 0, display->height - 1) - offset; src_current_row = &(display->operations[start_row * display->width]); current_row = &(display->operations[(start_row + offset) * display->width]); /* Move data */ memmove(current_row, src_current_row, (end_row - start_row + 1) * sizeof(guac_terminal_operation) * display->width); /* Update operations */ for (row=start_row; row<=end_row; row++) { guac_terminal_operation* current = current_row; for (col=0; colwidth; col++) { /* If no operation here, set as copy */ if (current->type == GUAC_CHAR_NOP) { current->type = GUAC_CHAR_COPY; current->row = row; current->column = col; } /* Next column */ current++; } /* Next row */ current_row += display->width; } } void guac_terminal_display_set_columns(guac_terminal_display* display, int row, int start_column, int end_column, guac_terminal_char* character) { int i; guac_terminal_operation* current; /* Do nothing if glyph is empty */ if (character->width == 0) return; /* Ignore operations outside display bounds */ if (row < 0 || row >= display->height) return; /* Fit range within bounds */ start_column = guac_terminal_fit_to_range(start_column, 0, display->width - 1); end_column = guac_terminal_fit_to_range(end_column, 0, display->width - 1); current = &(display->operations[row * display->width + start_column]); /* For each column in range */ for (i = start_column; i <= end_column; i += character->width) { /* Set operation */ current->type = GUAC_CHAR_SET; current->character = *character; /* Next character */ current += character->width; } } void guac_terminal_display_resize(guac_terminal_display* display, int width, int height) { guac_terminal_operation* current; int x, y; /* Fill with background color */ guac_terminal_char fill = { .value = 0, .attributes = { .foreground = display->default_background, .background = display->default_background }, .width = 1 }; /* Free old operations buffer */ if (display->operations != NULL) free(display->operations); /* Alloc operations */ display->operations = malloc(width * height * sizeof(guac_terminal_operation)); /* Init each operation buffer row */ current = display->operations; for (y=0; ywidth && y < display->height) current->type = GUAC_CHAR_NOP; /* Otherwise, clear contents first */ else { current->type = GUAC_CHAR_SET; current->character = fill; } current++; } } /* Set width and height */ display->width = width; display->height = height; /* Send display size */ guac_common_surface_resize( display->display_surface, display->char_width * width, display->char_height * height); guac_protocol_send_size(display->client->socket, display->select_layer, display->char_width * width, display->char_height * height); } void __guac_terminal_display_flush_copy(guac_terminal_display* display) { guac_terminal_operation* current = display->operations; int row, col; /* For each operation */ for (row=0; rowheight; row++) { for (col=0; colwidth; col++) { /* If operation is a copy operation */ if (current->type == GUAC_CHAR_COPY) { /* The determined bounds of the rectangle of contiguous * operations */ int detected_right = -1; int detected_bottom = row; /* The current row or column within a rectangle */ int rect_row, rect_col; /* The dimensions of the rectangle as determined */ int rect_width, rect_height; /* The expected row and column source for the next copy * operation (if adjacent to current) */ int expected_row, expected_col; /* Current row within a subrect */ guac_terminal_operation* rect_current_row; /* Determine bounds of rectangle */ rect_current_row = current; expected_row = current->row; for (rect_row=row; rect_rowheight; rect_row++) { guac_terminal_operation* rect_current = rect_current_row; expected_col = current->column; /* Find width */ for (rect_col=col; rect_colwidth; rect_col++) { /* If not identical operation, stop */ if (rect_current->type != GUAC_CHAR_COPY || rect_current->row != expected_row || rect_current->column != expected_col) break; /* Next column */ rect_current++; expected_col++; } /* If too small, cannot append row */ if (rect_col-1 < detected_right) break; /* As row has been accepted, update rect_row of rect */ detected_bottom = rect_row; /* For now, only set rect_col bound if uninitialized */ if (detected_right == -1) detected_right = rect_col - 1; /* Next row */ rect_current_row += display->width; expected_row++; } /* Calculate dimensions */ rect_width = detected_right - col + 1; rect_height = detected_bottom - row + 1; /* Mark rect as NOP (as it has been handled) */ rect_current_row = current; expected_row = current->row; for (rect_row=0; rect_rowcolumn; for (rect_col=0; rect_coltype == GUAC_CHAR_COPY && rect_current->row == expected_row && rect_current->column == expected_col) rect_current->type = GUAC_CHAR_NOP; /* Next column */ rect_current++; expected_col++; } /* Next row */ rect_current_row += display->width; expected_row++; } /* Send copy */ guac_common_surface_copy( display->display_surface, current->column * display->char_width, current->row * display->char_height, rect_width * display->char_width, rect_height * display->char_height, display->display_surface, col * display->char_width, row * display->char_height); } /* end if copy operation */ /* Next operation */ current++; } } } void __guac_terminal_display_flush_clear(guac_terminal_display* display) { guac_terminal_operation* current = display->operations; int row, col; /* For each operation */ for (row=0; rowheight; row++) { for (col=0; colwidth; col++) { /* If operation is a cler operation (set to space) */ if (current->type == GUAC_CHAR_SET && !guac_terminal_has_glyph(current->character.value)) { /* The determined bounds of the rectangle of contiguous * operations */ int detected_right = -1; int detected_bottom = row; /* The current row or column within a rectangle */ int rect_row, rect_col; /* The dimensions of the rectangle as determined */ int rect_width, rect_height; /* Color of the rectangle to draw */ guac_terminal_color color; if (current->character.attributes.reverse != current->character.attributes.cursor) color = current->character.attributes.foreground; else color = current->character.attributes.background; /* Rely only on palette index if defined */ guac_terminal_display_lookup_color(display, color.palette_index, &color); /* Current row within a subrect */ guac_terminal_operation* rect_current_row; /* Determine bounds of rectangle */ rect_current_row = current; for (rect_row=row; rect_rowheight; rect_row++) { guac_terminal_operation* rect_current = rect_current_row; /* Find width */ for (rect_col=col; rect_colwidth; rect_col++) { const guac_terminal_color* joining_color; if (rect_current->character.attributes.reverse != rect_current->character.attributes.cursor) joining_color = &rect_current->character.attributes.foreground; else joining_color = &rect_current->character.attributes.background; /* If not identical operation, stop */ if (rect_current->type != GUAC_CHAR_SET || guac_terminal_has_glyph(rect_current->character.value) || guac_terminal_colorcmp(joining_color, &color) != 0) break; /* Next column */ rect_current++; } /* If too small, cannot append row */ if (rect_col-1 < detected_right) break; /* As row has been accepted, update rect_row of rect */ detected_bottom = rect_row; /* For now, only set rect_col bound if uninitialized */ if (detected_right == -1) detected_right = rect_col - 1; /* Next row */ rect_current_row += display->width; } /* Calculate dimensions */ rect_width = detected_right - col + 1; rect_height = detected_bottom - row + 1; /* Mark rect as NOP (as it has been handled) */ rect_current_row = current; for (rect_row=0; rect_rowcharacter.attributes.reverse != rect_current->character.attributes.cursor) joining_color = &rect_current->character.attributes.foreground; else joining_color = &rect_current->character.attributes.background; /* Mark clear operations as NOP */ if (rect_current->type == GUAC_CHAR_SET && !guac_terminal_has_glyph(rect_current->character.value) && guac_terminal_colorcmp(joining_color, &color) == 0) rect_current->type = GUAC_CHAR_NOP; /* Next column */ rect_current++; } /* Next row */ rect_current_row += display->width; } /* Send rect */ guac_common_surface_set( display->display_surface, col * display->char_width, row * display->char_height, rect_width * display->char_width, rect_height * display->char_height, color.red, color.green, color.blue, 0xFF); } /* end if clear operation */ /* Next operation */ current++; } } } void __guac_terminal_display_flush_set(guac_terminal_display* display) { guac_terminal_operation* current = display->operations; int row, col; /* For each operation */ for (row=0; rowheight; row++) { for (col=0; colwidth; col++) { /* Perform given operation */ if (current->type == GUAC_CHAR_SET) { int codepoint = current->character.value; /* Use space if no glyph */ if (!guac_terminal_has_glyph(codepoint)) codepoint = ' '; /* Set attributes */ __guac_terminal_set_colors(display, &(current->character.attributes)); /* Send character */ __guac_terminal_set(display, row, col, codepoint); /* Mark operation as handled */ current->type = GUAC_CHAR_NOP; } /* Next operation */ current++; } } } void guac_terminal_display_flush(guac_terminal_display* display) { /* Flush operations, copies first, then clears, then sets. */ __guac_terminal_display_flush_copy(display); __guac_terminal_display_flush_clear(display); __guac_terminal_display_flush_set(display); /* Flush surface */ guac_common_surface_flush(display->display_surface); } void guac_terminal_display_dup(guac_terminal_display* display, guac_user* user, guac_socket* socket) { /* Create default surface */ guac_common_surface_dup(display->display_surface, user, socket); /* Select layer is a child of the display layer */ guac_protocol_send_move(socket, display->select_layer, display->display_layer, 0, 0, 0); /* Send select layer size */ guac_protocol_send_size(socket, display->select_layer, display->char_width * display->width, display->char_height * display->height); } void guac_terminal_display_select(guac_terminal_display* display, int start_row, int start_col, int end_row, int end_col) { guac_socket* socket = display->client->socket; guac_layer* select_layer = display->select_layer; /* Do nothing if selection is unchanged */ if (display->text_selected && display->selection_start_row == start_row && display->selection_start_column == start_col && display->selection_end_row == end_row && display->selection_end_column == end_col) return; /* Text is now selected */ display->text_selected = true; display->selection_start_row = start_row; display->selection_start_column = start_col; display->selection_end_row = end_row; display->selection_end_column = end_col; /* If single row, just need one rectangle */ if (start_row == end_row) { /* Ensure proper ordering of columns */ if (start_col > end_col) { int temp = start_col; start_col = end_col; end_col = temp; } /* Select characters between columns */ guac_protocol_send_rect(socket, select_layer, start_col * display->char_width, start_row * display->char_height, (end_col - start_col + 1) * display->char_width, display->char_height); } /* Otherwise, need three */ else { /* Ensure proper ordering of start and end coords */ if (start_row > end_row) { int temp; temp = start_row; start_row = end_row; end_row = temp; temp = start_col; start_col = end_col; end_col = temp; } /* First row */ guac_protocol_send_rect(socket, select_layer, start_col * display->char_width, start_row * display->char_height, display->width * display->char_width, display->char_height); /* Middle */ guac_protocol_send_rect(socket, select_layer, 0, (start_row + 1) * display->char_height, display->width * display->char_width, (end_row - start_row - 1) * display->char_height); /* Last row */ guac_protocol_send_rect(socket, select_layer, 0, end_row * display->char_height, (end_col + 1) * display->char_width, display->char_height); } /* Draw new selection, erasing old */ guac_protocol_send_cfill(socket, GUAC_COMP_SRC, select_layer, 0x00, 0x80, 0xFF, 0x60); } void guac_terminal_display_clear_select(guac_terminal_display* display) { /* Do nothing if nothing is selected */ if (!display->text_selected) return; guac_socket* socket = display->client->socket; guac_layer* select_layer = display->select_layer; guac_protocol_send_rect(socket, select_layer, 0, 0, 1, 1); guac_protocol_send_cfill(socket, GUAC_COMP_SRC, select_layer, 0x00, 0x00, 0x00, 0x00); /* Text is no longer selected */ display->text_selected = false; } int guac_terminal_display_set_font(guac_terminal_display* display, const char* font_name, int font_size, int dpi) { PangoFontDescription* font_desc; /* Build off existing font description if possible */ if (display->font_desc != NULL) font_desc = pango_font_description_copy(display->font_desc); /* Create new font description if there is nothing to copy */ else { font_desc = pango_font_description_new(); pango_font_description_set_weight(font_desc, PANGO_WEIGHT_NORMAL); } /* Optionally update font name */ if (font_name != NULL) pango_font_description_set_family(font_desc, font_name); /* Optionally update size */ if (font_size != -1) { pango_font_description_set_size(font_desc, font_size * PANGO_SCALE * dpi / 96); } PangoFontMap* font_map = pango_cairo_font_map_get_default(); PangoContext* context = pango_font_map_create_context(font_map); /* Load font from font map */ PangoFont* font = pango_font_map_load_font(font_map, context, font_desc); if (font == NULL) { guac_client_log(display->client, GUAC_LOG_INFO, "Unable to load " "font \"%s\"", pango_font_description_get_family(font_desc)); pango_font_description_free(font_desc); return 1; } /* Get metrics from loaded font */ PangoFontMetrics* metrics = pango_font_get_metrics(font, NULL); if (metrics == NULL) { guac_client_log(display->client, GUAC_LOG_INFO, "Unable to get font " "metrics for font \"%s\"", pango_font_description_get_family(font_desc)); pango_font_description_free(font_desc); return 1; } /* Save effective size of current display */ int pixel_width = display->width * display->char_width; int pixel_height = display->height * display->char_height; /* Calculate character dimensions using metrics */ display->char_width = pango_font_metrics_get_approximate_digit_width(metrics) / PANGO_SCALE; display->char_height = (pango_font_metrics_get_descent(metrics) + pango_font_metrics_get_ascent(metrics)) / PANGO_SCALE; /* Atomically replace old font description */ PangoFontDescription* old_font_desc = display->font_desc; display->font_desc = font_desc; pango_font_description_free(old_font_desc); /* Recalculate dimensions which will fit within current surface */ int new_width = pixel_width / display->char_width; int new_height = pixel_height / display->char_height; /* Resize display if dimensions have changed */ if (new_width != display->width || new_height != display->height) guac_terminal_display_resize(display, new_width, new_height); return 0; } guacamole-server-1.3.0/src/terminal/common.c0000644000175100001440000000470113613156714015741 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "terminal/types.h" #include #include int guac_terminal_fit_to_range(int value, int min, int max) { if (value < min) return min; if (value > max) return max; return value; } int guac_terminal_encode_utf8(int codepoint, char* utf8) { int i; int mask, bytes; /* Determine size and initial byte mask */ if (codepoint <= 0x007F) { mask = 0x00; bytes = 1; } else if (codepoint <= 0x7FF) { mask = 0xC0; bytes = 2; } else if (codepoint <= 0xFFFF) { mask = 0xE0; bytes = 3; } else if (codepoint <= 0x1FFFFF) { mask = 0xF0; bytes = 4; } /* Otherwise, invalid codepoint */ else { *(utf8++) = '?'; return 1; } /* Offset buffer by size */ utf8 += bytes - 1; /* Add trailing bytes, if any */ for (i=1; i>= 6; } /* Set initial byte */ *utf8 = mask | codepoint; /* Done */ return bytes; } bool guac_terminal_has_glyph(int codepoint) { return codepoint != 0 && codepoint != ' ' && codepoint != GUAC_CHAR_CONTINUATION; } int guac_terminal_write_all(int fd, const char* buffer, int size) { int remaining = size; while (remaining > 0) { /* Attempt to write data */ int ret_val = write(fd, buffer, remaining); if (ret_val <= 0) return -1; /* If successful, contine with what data remains (if any) */ remaining -= ret_val; buffer += ret_val; } return size; } guacamole-server-1.3.0/src/terminal/xparsecolor.c0000644000175100001440000000452013702142276017006 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "terminal/named-colors.h" #include "terminal/palette.h" #include int guac_terminal_xparsecolor(const char* spec, guac_terminal_color* color) { int red; int green; int blue; /* 12-bit RGB ("rgb:h/h/h"), zero-padded to 24-bit */ if (sscanf(spec, "rgb:%1x/%1x/%1x", &red, &green, &blue) == 3) { color->palette_index = -1; /* Not from palette. */ color->red = red << 4; color->green = green << 4; color->blue = blue << 4; return 0; } /* 24-bit RGB ("rgb:hh/hh/hh") */ if (sscanf(spec, "rgb:%2x/%2x/%2x", &red, &green, &blue) == 3) { color->palette_index = -1; /* Not from palette. */ color->red = red; color->green = green; color->blue = blue; return 0; } /* 36-bit RGB ("rgb:hhh/hhh/hhh"), truncated to 24-bit */ if (sscanf(spec, "rgb:%3x/%3x/%3x", &red, &green, &blue) == 3) { color->palette_index = -1; /* Not from palette. */ color->red = red >> 4; color->green = green >> 4; color->blue = blue >> 4; return 0; } /* 48-bit RGB ("rgb:hhhh/hhhh/hhhh"), truncated to 24-bit */ if (sscanf(spec, "rgb:%4x/%4x/%4x", &red, &green, &blue) == 3) { color->palette_index = -1; /* Not from palette. */ color->red = red >> 8; color->green = green >> 8; color->blue = blue >> 8; return 0; } /* If not RGB, search for color by name */ return guac_terminal_find_color(spec, color); } guacamole-server-1.3.0/src/terminal/terminal-stdin-stream.c0000644000175100001440000001230213702142276020665 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "terminal/common.h" #include "terminal/terminal.h" #include #include #include /** * Handler for "blob" instructions which writes the data of received * blobs to STDIN of the terminal associated with the stream. * * @see guac_user_blob_handler */ static int guac_terminal_input_stream_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { guac_terminal* term = (guac_terminal*) stream->data; /* Attempt to write received data */ guac_terminal_lock(term); int result = guac_terminal_write_all(term->stdin_pipe_fd[1], data, length); guac_terminal_unlock(term); /* Acknowledge receipt of data and result of write attempt */ if (result <= 0) { guac_user_log(user, GUAC_LOG_DEBUG, "Attempt to write to STDIN via an inbound stream failed."); guac_protocol_send_ack(user->socket, stream, "Attempt to write to STDIN failed.", GUAC_PROTOCOL_STATUS_SUCCESS); } else { guac_user_log(user, GUAC_LOG_DEBUG, "%i bytes successfully written to STDIN from an inbound stream.", length); guac_protocol_send_ack(user->socket, stream, "Data written to STDIN.", GUAC_PROTOCOL_STATUS_SUCCESS); } guac_socket_flush(user->socket); return 0; } /** * Handler for "end" instructions which disassociates the given * stream from the terminal, allowing user input to resume. * * @see guac_user_end_handler */ static int guac_terminal_input_stream_end_handler(guac_user* user, guac_stream* stream) { guac_terminal* term = (guac_terminal*) stream->data; /* Reset input stream, unblocking user input */ guac_terminal_lock(term); term->input_stream = NULL; guac_terminal_unlock(term); guac_user_log(user, GUAC_LOG_DEBUG, "Inbound stream closed. User input " "will now resume affecting STDIN."); return 0; } /** * Internal implementation of guac_terminal_send_stream() which assumes * that the guac_terminal has already been locked through a call to * guac_terminal_lock(). The semantics of all parameters and the return * value are identical to guac_terminal_send_stream(). * * @see guac_terminal_send_stream() */ static int __guac_terminal_send_stream(guac_terminal* term, guac_user* user, guac_stream* stream) { /* Deny redirecting STDIN if terminal is not started */ if (!term->started) { guac_user_log(user, GUAC_LOG_DEBUG, "Attempt to direct the contents " "of an inbound stream to STDIN denied. The terminal is not " "yet ready for input."); guac_protocol_send_ack(user->socket, stream, "Terminal not yet started.", GUAC_PROTOCOL_STATUS_RESOURCE_CONFLICT); guac_socket_flush(user->socket); return 1; } /* If a stream is already being used for STDIN, deny creation of * further streams */ if (term->input_stream != NULL) { guac_user_log(user, GUAC_LOG_DEBUG, "Attempt to direct the contents " "of an inbound stream to STDIN denied. STDIN is already " "being read from an inbound stream."); guac_protocol_send_ack(user->socket, stream, "STDIN is already being read from a stream.", GUAC_PROTOCOL_STATUS_RESOURCE_CONFLICT); guac_socket_flush(user->socket); return 1; } guac_user_log(user, GUAC_LOG_DEBUG, "Now reading STDIN from inbound " "stream. User input will no longer affect STDIN until the " "stream is closed."); stream->blob_handler = guac_terminal_input_stream_blob_handler; stream->end_handler = guac_terminal_input_stream_end_handler; stream->data = term; /* Block user input until stream is ended */ term->input_stream = stream; /* Acknowledge redirection from stream */ guac_protocol_send_ack(user->socket, stream, "Now reading STDIN from stream.", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(user->socket); return 0; } int guac_terminal_send_stream(guac_terminal* term, guac_user* user, guac_stream* stream) { int result; guac_terminal_lock(term); result = __guac_terminal_send_stream(term, user, stream); guac_terminal_unlock(term); return result; } guacamole-server-1.3.0/src/terminal/terminal.c0000644000175100001440000017610613764613616016303 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/clipboard.h" #include "common/cursor.h" #include "terminal/buffer.h" #include "terminal/color-scheme.h" #include "terminal/common.h" #include "terminal/display.h" #include "terminal/palette.h" #include "terminal/select.h" #include "terminal/terminal.h" #include "terminal/terminal_handlers.h" #include "terminal/types.h" #include "terminal/typescript.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** * Sets the given range of columns to the given character. */ static void __guac_terminal_set_columns(guac_terminal* terminal, int row, int start_column, int end_column, guac_terminal_char* character) { guac_terminal_display_set_columns(terminal->display, row + terminal->scroll_offset, start_column, end_column, character); guac_terminal_buffer_set_columns(terminal->buffer, row, start_column, end_column, character); /* Clear selection if region is modified */ guac_terminal_select_touch(terminal, row, start_column, row, end_column); } /** * Enforces a character break at the given edge, ensuring that the left side * of the edge is the final column of a character, and the right side of the * edge is the initial column of a DIFFERENT character. * * For a character in a column N, the left edge number is N, and the right * edge is N+1. */ static void __guac_terminal_force_break(guac_terminal* terminal, int row, int edge) { guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(terminal->buffer, row, 0); /* Ensure character to left of edge is unbroken */ if (edge > 0) { int end_column = edge - 1; int start_column = end_column; guac_terminal_char* start_char = &(buffer_row->characters[start_column]); /* Determine start column */ while (start_column > 0 && start_char->value == GUAC_CHAR_CONTINUATION) { start_char--; start_column--; } /* Advance to start of broken character if necessary */ if (start_char->value != GUAC_CHAR_CONTINUATION && start_char->width < end_column - start_column + 1) { start_column += start_char->width; start_char += start_char->width; } /* Clear character if broken */ if (start_char->value == GUAC_CHAR_CONTINUATION || start_char->width != end_column - start_column + 1) { guac_terminal_char cleared_char; cleared_char.value = ' '; cleared_char.attributes = start_char->attributes; cleared_char.width = 1; __guac_terminal_set_columns(terminal, row, start_column, end_column, &cleared_char); } } /* Ensure character to right of edge is unbroken */ if (edge >= 0 && edge < buffer_row->length) { int start_column = edge; int end_column = start_column; guac_terminal_char* start_char = &(buffer_row->characters[start_column]); guac_terminal_char* end_char = &(buffer_row->characters[end_column]); /* Determine end column */ while (end_column+1 < buffer_row->length && (end_char+1)->value == GUAC_CHAR_CONTINUATION) { end_char++; end_column++; } /* Advance to start of broken character if necessary */ if (start_char->value != GUAC_CHAR_CONTINUATION && start_char->width < end_column - start_column + 1) { start_column += start_char->width; start_char += start_char->width; } /* Clear character if broken */ if (start_char->value == GUAC_CHAR_CONTINUATION || start_char->width != end_column - start_column + 1) { guac_terminal_char cleared_char; cleared_char.value = ' '; cleared_char.attributes = start_char->attributes; cleared_char.width = 1; __guac_terminal_set_columns(terminal, row, start_column, end_column, &cleared_char); } } } /** * Returns the number of rows available within the terminal buffer, taking * changes to the desired scrollback size into account. Regardless of the * true buffer length, only the number of rows that should be made available * will be returned. * * @param term * The terminal whose effective buffer length should be retrieved. * * @return * The number of rows effectively available within the terminal buffer, * taking changes to the desired scrollback size into account. */ static int guac_terminal_effective_buffer_length(guac_terminal* term) { int scrollback = term->requested_scrollback; /* Limit available scrollback to defined maximum */ if (scrollback > term->max_scrollback) scrollback = term->max_scrollback; /* There must always be at least enough scrollback to cover the visible * terminal display */ else if (scrollback < term->term_height) scrollback = term->term_height; /* If the buffer contains more rows than requested, pretend it only * contains the requested number of rows */ int effective_length = term->buffer->length; if (effective_length > scrollback) effective_length = scrollback; return effective_length; } int guac_terminal_available_scroll(guac_terminal* term) { return guac_terminal_effective_buffer_length(term) - term->term_height; } void guac_terminal_reset(guac_terminal* term) { int row; /* Set current state */ term->char_handler = guac_terminal_echo; term->active_char_set = 0; term->char_mapping[0] = term->char_mapping[1] = NULL; /* Reset cursor location */ term->cursor_row = term->visible_cursor_row = term->saved_cursor_row = 0; term->cursor_col = term->visible_cursor_col = term->saved_cursor_col = 0; term->cursor_visible = true; /* Clear scrollback, buffer, and scroll region */ term->buffer->top = 0; term->buffer->length = 0; term->scroll_start = 0; term->scroll_end = term->term_height - 1; term->scroll_offset = 0; /* Reset scrollbar bounds */ guac_terminal_scrollbar_set_bounds(term->scrollbar, 0, 0); guac_terminal_scrollbar_set_value(term->scrollbar, -term->scroll_offset); /* Reset flags */ term->text_selected = false; term->selection_committed = false; term->application_cursor_keys = false; term->automatic_carriage_return = false; term->insert_mode = false; /* Reset tabs */ term->tab_interval = 8; memset(term->custom_tabs, 0, sizeof(term->custom_tabs)); /* Reset character attributes */ term->current_attributes = term->default_char.attributes; /* Reset display palette */ guac_terminal_display_reset_palette(term->display); /* Clear terminal */ for (row=0; rowterm_height; row++) guac_terminal_set_columns(term, row, 0, term->term_width, &(term->default_char)); } /** * Paints or repaints the background of the terminal display. This painting * occurs beneath the actual terminal and scrollbar layers, and thus will not * overwrite any text or other content currently on the screen. This is only * necessary to paint over parts of the terminal background which may otherwise * be transparent (the default layer background). * * @param terminal * The terminal whose background should be painted or repainted. * * @param socket * The socket over which instructions required to paint / repaint the * terminal background should be send. */ static void guac_terminal_repaint_default_layer(guac_terminal* terminal, guac_socket* socket) { int width = terminal->width; int height = terminal->height; guac_terminal_display* display = terminal->display; /* Get background color */ const guac_terminal_color* color = &display->default_background; /* Reset size */ guac_protocol_send_size(socket, GUAC_DEFAULT_LAYER, width, height); /* Paint background color */ guac_protocol_send_rect(socket, GUAC_DEFAULT_LAYER, 0, 0, width, height); guac_protocol_send_cfill(socket, GUAC_COMP_OVER, GUAC_DEFAULT_LAYER, color->red, color->green, color->blue, 0xFF); } /** * Automatically and continuously renders frames of terminal data while the * associated guac_client is running. * * @param data * A pointer to the guac_terminal that should be continuously rendered * while its associated guac_client is running. * * @return * Always NULL. */ void* guac_terminal_thread(void* data) { guac_terminal* terminal = (guac_terminal*) data; guac_client* client = terminal->client; /* Render frames only while client is running */ while (client->state == GUAC_CLIENT_RUNNING) { /* Stop rendering if an error occurs */ if (guac_terminal_render_frame(terminal)) break; /* Signal end of frame */ guac_client_end_frame(client); guac_socket_flush(client->socket); } /* The client has stopped or an error has occurred */ return NULL; } guac_terminal* guac_terminal_create(guac_client* client, guac_common_clipboard* clipboard, bool disable_copy, int max_scrollback, const char* font_name, int font_size, int dpi, int width, int height, const char* color_scheme, const int backspace) { /* Build default character using default colors */ guac_terminal_char default_char = { .value = 0, .attributes = { .bold = false, .half_bright = false, .reverse = false, .underscore = false }, .width = 1 }; /* Initialized by guac_terminal_parse_color_scheme. */ guac_terminal_color (*default_palette)[256] = (guac_terminal_color(*)[256]) malloc(sizeof(guac_terminal_color[256])); guac_terminal_parse_color_scheme(client, color_scheme, &default_char.attributes.foreground, &default_char.attributes.background, default_palette); /* Calculate available display area */ int available_width = width - GUAC_TERMINAL_SCROLLBAR_WIDTH; if (available_width < 0) available_width = 0; guac_terminal* term = malloc(sizeof(guac_terminal)); term->started = false; term->client = client; term->upload_path_handler = NULL; term->file_download_handler = NULL; /* Copy initially-provided color scheme and font details */ term->color_scheme = strdup(color_scheme); term->font_name = strdup(font_name); term->font_size = font_size; /* Set size of available screen area */ term->outer_width = width; term->outer_height = height; /* Init modified flag and conditional */ term->modified = 0; pthread_cond_init(&(term->modified_cond), NULL); pthread_mutex_init(&(term->modified_lock), NULL); /* Maximum and requested scrollback are initially the same */ term->max_scrollback = max_scrollback; term->requested_scrollback = max_scrollback; /* Allocate enough space for maximum scrollback, bumping up internal * storage as necessary to allow screen to be resized to maximum height */ int initial_scrollback = max_scrollback; if (initial_scrollback < GUAC_TERMINAL_MAX_ROWS) initial_scrollback = GUAC_TERMINAL_MAX_ROWS; /* Init buffer */ term->buffer = guac_terminal_buffer_alloc(initial_scrollback, &default_char); /* Init display */ term->display = guac_terminal_display_alloc(client, font_name, font_size, dpi, &default_char.attributes.foreground, &default_char.attributes.background, (guac_terminal_color(*)[256]) default_palette); /* Fail if display init failed */ if (term->display == NULL) { guac_client_log(client, GUAC_LOG_DEBUG, "Display initialization failed"); free(term); return NULL; } /* Init common cursor */ term->cursor = guac_common_cursor_alloc(client); /* Init terminal state */ term->current_attributes = default_char.attributes; term->default_char = default_char; term->clipboard = clipboard; term->disable_copy = disable_copy; /* Calculate character size */ int rows = height / term->display->char_height; int columns = available_width / term->display->char_width; /* Keep height within predefined maximum */ if (rows > GUAC_TERMINAL_MAX_ROWS) { rows = GUAC_TERMINAL_MAX_ROWS; height = rows * term->display->char_height; } /* Keep width within predefined maximum */ if (columns > GUAC_TERMINAL_MAX_COLUMNS) { columns = GUAC_TERMINAL_MAX_COLUMNS; available_width = columns * term->display->char_width; width = available_width + GUAC_TERMINAL_SCROLLBAR_WIDTH; } /* Set pixel size */ term->width = width; term->height = height; term->term_width = columns; term->term_height = rows; /* Open STDIN pipe */ if (pipe(term->stdin_pipe_fd)) { guac_error = GUAC_STATUS_SEE_ERRNO; guac_error_message = "Unable to open pipe for STDIN"; free(term); return NULL; } /* Read input from keyboard by default */ term->input_stream = NULL; /* Init pipe stream (output to display by default) */ term->pipe_stream = NULL; /* No typescript by default */ term->typescript = NULL; /* Init terminal lock */ pthread_mutex_init(&(term->lock), NULL); /* Repaint and resize overall display */ guac_terminal_repaint_default_layer(term, client->socket); guac_terminal_display_resize(term->display, term->term_width, term->term_height); /* Allocate scrollbar */ term->scrollbar = guac_terminal_scrollbar_alloc(client, GUAC_DEFAULT_LAYER, width, height, term->term_height); /* Associate scrollbar with this terminal */ term->scrollbar->data = term; term->scrollbar->scroll_handler = guac_terminal_scroll_handler; /* Init terminal */ guac_terminal_reset(term); term->mod_alt = term->mod_ctrl = term->mod_shift = 0; /* Initialize mouse cursor */ term->current_cursor = GUAC_TERMINAL_CURSOR_BLANK; guac_common_cursor_set_blank(term->cursor); /* Start terminal thread */ if (pthread_create(&(term->thread), NULL, guac_terminal_thread, (void*) term)) { guac_terminal_free(term); return NULL; } /* Configure backspace */ term->backspace = backspace; return term; } void guac_terminal_start(guac_terminal* term) { term->started = true; guac_terminal_notify(term); } void guac_terminal_stop(guac_terminal* term) { /* Close input pipe and set fds to invalid */ if (term->stdin_pipe_fd[1] != -1) { close(term->stdin_pipe_fd[1]); term->stdin_pipe_fd[1] = -1; } if (term->stdin_pipe_fd[0] != -1) { close(term->stdin_pipe_fd[0]); term->stdin_pipe_fd[0] = -1; } } void guac_terminal_free(guac_terminal* term) { /* Close user input pipe */ guac_terminal_stop(term); /* Wait for render thread to finish */ pthread_join(term->thread, NULL); /* Close and flush any open pipe stream */ guac_terminal_pipe_stream_close(term); /* Close and flush any active typescript */ guac_terminal_typescript_free(term->typescript); /* Free display */ guac_terminal_display_free(term->display); /* Free buffer */ guac_terminal_buffer_free(term->buffer); /* Free scrollbar */ guac_terminal_scrollbar_free(term->scrollbar); /* Free copies of font and color scheme information */ free((char*) term->color_scheme); free((char*) term->font_name); /* Free the terminal itself */ free(term); } /** * Populate the given timespec with the current time, plus the given offset. * * @param ts * The timespec structure to populate. * * @param offset_sec * The offset from the current time to use when populating the given * timespec, in seconds. * * @param offset_usec * The offset from the current time to use when populating the given * timespec, in microseconds. */ static void guac_terminal_get_absolute_time(struct timespec* ts, int offset_sec, int offset_usec) { /* Get timeval */ struct timeval tv; gettimeofday(&tv, NULL); /* Update with offset */ tv.tv_sec += offset_sec; tv.tv_usec += offset_usec; /* Wrap to next second if necessary */ if (tv.tv_usec >= 1000000) { tv.tv_sec++; tv.tv_usec -= 1000000; } /* Convert to timespec */ ts->tv_sec = tv.tv_sec; ts->tv_nsec = tv.tv_usec * 1000; } /** * Waits for the terminal state to be modified, returning only when the * specified timeout has elapsed or a frame flush is desired. Note that the * modified flag of the terminal will only be reset if no data remains to be * read from STDOUT. * * @param terminal * The terminal to wait on. * * @param msec_timeout * The maximum amount of time to wait, in milliseconds. * * @return * Non-zero if the terminal has been modified, zero if the timeout has * elapsed without the terminal being modified. */ static int guac_terminal_wait(guac_terminal* terminal, int msec_timeout) { int retval = 1; pthread_mutex_t* mod_lock = &(terminal->modified_lock); pthread_cond_t* mod_cond = &(terminal->modified_cond); /* Split provided milliseconds into microseconds and whole seconds */ int secs = msec_timeout / 1000; int usecs = (msec_timeout % 1000) * 1000; /* Calculate absolute timestamp from provided relative timeout */ struct timespec timeout; guac_terminal_get_absolute_time(&timeout, secs, usecs); /* Test for terminal modification */ pthread_mutex_lock(mod_lock); if (terminal->modified) goto wait_complete; /* If not yet modified, wait for modification condition to be signaled */ retval = pthread_cond_timedwait(mod_cond, mod_lock, &timeout) != ETIMEDOUT; wait_complete: /* Terminal is no longer modified */ terminal->modified = 0; pthread_mutex_unlock(mod_lock); return retval; } int guac_terminal_render_frame(guac_terminal* terminal) { guac_client* client = terminal->client; int wait_result; /* Wait for data to be available */ wait_result = guac_terminal_wait(terminal, 1000); if (wait_result || !terminal->started) { guac_timestamp frame_start = guac_timestamp_current(); do { /* Calculate time remaining in frame */ guac_timestamp frame_end = guac_timestamp_current(); int frame_remaining = frame_start + GUAC_TERMINAL_FRAME_DURATION - frame_end; /* Wait again if frame remaining */ if (frame_remaining > 0 || !terminal->started) wait_result = guac_terminal_wait(terminal, GUAC_TERMINAL_FRAME_TIMEOUT); else break; } while (client->state == GUAC_CLIENT_RUNNING && (wait_result > 0 || !terminal->started)); /* Flush terminal */ guac_terminal_lock(terminal); guac_terminal_flush(terminal); guac_terminal_unlock(terminal); } return 0; } int guac_terminal_read_stdin(guac_terminal* terminal, char* c, int size) { int stdin_fd = terminal->stdin_pipe_fd[0]; return read(stdin_fd, c, size); } void guac_terminal_notify(guac_terminal* terminal) { pthread_mutex_t* mod_lock = &(terminal->modified_lock); pthread_cond_t* mod_cond = &(terminal->modified_cond); pthread_mutex_lock(mod_lock); /* Signal modification */ terminal->modified = 1; pthread_cond_signal(mod_cond); pthread_mutex_unlock(mod_lock); } int guac_terminal_printf(guac_terminal* terminal, const char* format, ...) { int written; va_list ap; char buffer[1024]; /* Print to buffer */ va_start(ap, format); written = vsnprintf(buffer, sizeof(buffer)-1, format, ap); va_end(ap); if (written < 0) return written; /* Write to STDOUT */ return guac_terminal_write(terminal, buffer, written); } char* guac_terminal_prompt(guac_terminal* terminal, const char* title, bool echo) { char buffer[1024]; int pos; char in_byte; /* Prompting implicitly requires user input */ guac_terminal_start(terminal); /* Print title */ guac_terminal_printf(terminal, "%s", title); /* Read bytes until newline */ pos = 0; while (guac_terminal_read_stdin(terminal, &in_byte, 1) == 1) { /* Backspace */ if (in_byte == 0x7F) { if (pos > 0) { guac_terminal_printf(terminal, "\b \b"); pos--; } } /* CR (end of input */ else if (in_byte == 0x0D) { guac_terminal_printf(terminal, "\r\n"); break; } /* Otherwise, store byte if there is room */ else if (pos < sizeof(buffer) - 1) { /* Store character, update buffers */ buffer[pos++] = in_byte; /* Print character if echoing */ if (echo) guac_terminal_printf(terminal, "%c", in_byte); else guac_terminal_printf(terminal, "*"); } /* Ignore all other input */ } /* Terminate string */ buffer[pos] = 0; /* Return newly-allocated string containing result */ return strdup(buffer); } int guac_terminal_set(guac_terminal* term, int row, int col, int codepoint) { /* Calculate width in columns */ int width = wcwidth(codepoint); if (width < 0) width = 1; /* Do nothing if glyph is empty */ else if (width == 0) return 0; /* Build character with current attributes */ guac_terminal_char guac_char = { .value = codepoint, .attributes = term->current_attributes, .width = width }; guac_terminal_set_columns(term, row, col, col + width - 1, &guac_char); return 0; } void guac_terminal_commit_cursor(guac_terminal* term) { guac_terminal_char* guac_char; guac_terminal_buffer_row* row; /* If no change, done */ if (term->cursor_visible && term->visible_cursor_row == term->cursor_row && term->visible_cursor_col == term->cursor_col) return; /* Clear cursor if it was visible */ if (term->visible_cursor_row != -1 && term->visible_cursor_col != -1) { /* Get old row with cursor */ row = guac_terminal_buffer_get_row(term->buffer, term->visible_cursor_row, term->visible_cursor_col+1); guac_char = &(row->characters[term->visible_cursor_col]); guac_char->attributes.cursor = false; guac_terminal_display_set_columns(term->display, term->visible_cursor_row + term->scroll_offset, term->visible_cursor_col, term->visible_cursor_col, guac_char); } /* Set cursor if should be visible */ if (term->cursor_visible) { /* Get new row with cursor */ row = guac_terminal_buffer_get_row(term->buffer, term->cursor_row, term->cursor_col+1); guac_char = &(row->characters[term->cursor_col]); guac_char->attributes.cursor = true; guac_terminal_display_set_columns(term->display, term->cursor_row + term->scroll_offset, term->cursor_col, term->cursor_col, guac_char); term->visible_cursor_row = term->cursor_row; term->visible_cursor_col = term->cursor_col; } /* Otherwise set visible position to a sentinel value */ else { term->visible_cursor_row = -1; term->visible_cursor_col = -1; } return; } int guac_terminal_write(guac_terminal* term, const char* c, int size) { guac_terminal_lock(term); while (size > 0) { /* Read and advance to next character */ char current = *(c++); size--; /* Write character to typescript, if any */ if (term->typescript != NULL) guac_terminal_typescript_write(term->typescript, current); /* Handle character and its meaning */ term->char_handler(term, current); } guac_terminal_unlock(term); guac_terminal_notify(term); return 0; } int guac_terminal_scroll_up(guac_terminal* term, int start_row, int end_row, int amount) { /* If scrolling entire display, update scroll offset */ if (start_row == 0 && end_row == term->term_height - 1) { /* Scroll up visibly */ guac_terminal_display_copy_rows(term->display, start_row + amount, end_row, -amount); /* Advance by scroll amount */ term->buffer->top += amount; if (term->buffer->top >= term->buffer->available) term->buffer->top -= term->buffer->available; term->buffer->length += amount; if (term->buffer->length > term->buffer->available) term->buffer->length = term->buffer->available; /* Reset scrollbar bounds */ guac_terminal_scrollbar_set_bounds(term->scrollbar, -guac_terminal_available_scroll(term), 0); /* Update cursor location if within region */ if (term->visible_cursor_row >= start_row && term->visible_cursor_row <= end_row) term->visible_cursor_row -= amount; /* Update selected region */ if (term->text_selected) { term->selection_start_row -= amount; term->selection_end_row -= amount; } } /* Otherwise, just copy row data upwards */ else guac_terminal_copy_rows(term, start_row + amount, end_row, -amount); /* Clear new area */ guac_terminal_clear_range(term, end_row - amount + 1, 0, end_row, term->term_width - 1); return 0; } int guac_terminal_scroll_down(guac_terminal* term, int start_row, int end_row, int amount) { guac_terminal_copy_rows(term, start_row, end_row - amount, amount); /* Clear new area */ guac_terminal_clear_range(term, start_row, 0, start_row + amount - 1, term->term_width - 1); return 0; } int guac_terminal_clear_columns(guac_terminal* term, int row, int start_col, int end_col) { /* Build space */ guac_terminal_char blank; blank.value = 0; blank.attributes = term->current_attributes; blank.width = 1; /* Clear */ guac_terminal_set_columns(term, row, start_col, end_col, &blank); return 0; } int guac_terminal_clear_range(guac_terminal* term, int start_row, int start_col, int end_row, int end_col) { /* If not at far left, must clear sub-region to far right */ if (start_col > 0) { /* Clear from start_col to far right */ guac_terminal_clear_columns(term, start_row, start_col, term->term_width - 1); /* One less row to clear */ start_row++; } /* If not at far right, must clear sub-region to far left */ if (end_col < term->term_width - 1) { /* Clear from far left to end_col */ guac_terminal_clear_columns(term, end_row, 0, end_col); /* One less row to clear */ end_row--; } /* Remaining region now guaranteed rectangular. Clear, if possible */ if (start_row <= end_row) { int row; for (row=start_row; row<=end_row; row++) { /* Clear entire row */ guac_terminal_clear_columns(term, row, 0, term->term_width - 1); } } return 0; } /** * Returns whether the given character would be visible relative to the * background of the given terminal. * * @param term * The guac_terminal to test the character against. * * @param c * The character being tested. * * @return * true if the given character is different from the terminal background, * false otherwise. */ static bool guac_terminal_is_visible(guac_terminal* term, guac_terminal_char* c) { /* Continuation characters are NEVER visible */ if (c->value == GUAC_CHAR_CONTINUATION) return false; /* Characters with glyphs are ALWAYS visible */ if (guac_terminal_has_glyph(c->value)) return true; const guac_terminal_color* background; /* Determine actual background color of character */ if (c->attributes.reverse != c->attributes.cursor) background = &c->attributes.foreground; else background = &c->attributes.background; /* Blank characters are visible if their background color differs from that * of the terminal */ return guac_terminal_colorcmp(background, &term->default_char.attributes.background) != 0; } void guac_terminal_scroll_display_down(guac_terminal* terminal, int scroll_amount) { int start_row, end_row; int dest_row; int row, column; /* Limit scroll amount by size of scrollback buffer */ if (scroll_amount > terminal->scroll_offset) scroll_amount = terminal->scroll_offset; /* If not scrolling at all, don't bother trying */ if (scroll_amount <= 0) return; /* Shift screen up */ if (terminal->term_height > scroll_amount) guac_terminal_display_copy_rows(terminal->display, scroll_amount, terminal->term_height - 1, -scroll_amount); /* Advance by scroll amount */ terminal->scroll_offset -= scroll_amount; guac_terminal_scrollbar_set_value(terminal->scrollbar, -terminal->scroll_offset); /* Get row range */ end_row = terminal->term_height - terminal->scroll_offset - 1; start_row = end_row - scroll_amount + 1; dest_row = terminal->term_height - scroll_amount; /* Draw new rows from scrollback */ for (row=start_row; row<=end_row; row++) { /* Get row from scrollback */ guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(terminal->buffer, row, 0); /* Clear row */ guac_terminal_display_set_columns(terminal->display, dest_row, 0, terminal->display->width, &(terminal->default_char)); /* Draw row */ guac_terminal_char* current = buffer_row->characters; for (column=0; columnlength; column++) { /* Only draw if not blank */ if (guac_terminal_is_visible(terminal, current)) guac_terminal_display_set_columns(terminal->display, dest_row, column, column, current); current++; } /* Next row */ dest_row++; } guac_terminal_notify(terminal); } void guac_terminal_scroll_display_up(guac_terminal* terminal, int scroll_amount) { int start_row, end_row; int dest_row; int row, column; /* Limit scroll amount by size of scrollback buffer */ int available_scroll = guac_terminal_available_scroll(terminal); if (terminal->scroll_offset + scroll_amount > available_scroll) scroll_amount = available_scroll - terminal->scroll_offset; /* If not scrolling at all, don't bother trying */ if (scroll_amount <= 0) return; /* Shift screen down */ if (terminal->term_height > scroll_amount) guac_terminal_display_copy_rows(terminal->display, 0, terminal->term_height - scroll_amount - 1, scroll_amount); /* Advance by scroll amount */ terminal->scroll_offset += scroll_amount; guac_terminal_scrollbar_set_value(terminal->scrollbar, -terminal->scroll_offset); /* Get row range */ start_row = -terminal->scroll_offset; end_row = start_row + scroll_amount - 1; dest_row = 0; /* Draw new rows from scrollback */ for (row=start_row; row<=end_row; row++) { /* Get row from scrollback */ guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(terminal->buffer, row, 0); /* Clear row */ guac_terminal_display_set_columns(terminal->display, dest_row, 0, terminal->display->width, &(terminal->default_char)); /* Draw row */ guac_terminal_char* current = buffer_row->characters; for (column=0; columnlength; column++) { /* Only draw if not blank */ if (guac_terminal_is_visible(terminal, current)) guac_terminal_display_set_columns(terminal->display, dest_row, column, column, current); current++; } /* Next row */ dest_row++; } guac_terminal_notify(terminal); } void guac_terminal_copy_columns(guac_terminal* terminal, int row, int start_column, int end_column, int offset) { guac_terminal_display_copy_columns(terminal->display, row + terminal->scroll_offset, start_column, end_column, offset); guac_terminal_buffer_copy_columns(terminal->buffer, row, start_column, end_column, offset); /* Clear selection if region is modified */ guac_terminal_select_touch(terminal, row, start_column, row, end_column); /* Update cursor location if within region */ if (row == terminal->visible_cursor_row && terminal->visible_cursor_col >= start_column && terminal->visible_cursor_col <= end_column) terminal->visible_cursor_col += offset; /* Force breaks around destination region */ __guac_terminal_force_break(terminal, row, start_column + offset); __guac_terminal_force_break(terminal, row, end_column + offset + 1); } void guac_terminal_copy_rows(guac_terminal* terminal, int start_row, int end_row, int offset) { guac_terminal_display_copy_rows(terminal->display, start_row + terminal->scroll_offset, end_row + terminal->scroll_offset, offset); guac_terminal_buffer_copy_rows(terminal->buffer, start_row, end_row, offset); /* Clear selection if region is modified */ guac_terminal_select_touch(terminal, start_row, 0, end_row, terminal->term_width); /* Update cursor location if within region */ if (terminal->visible_cursor_row >= start_row && terminal->visible_cursor_row <= end_row) terminal->visible_cursor_row += offset; } void guac_terminal_set_columns(guac_terminal* terminal, int row, int start_column, int end_column, guac_terminal_char* character) { __guac_terminal_set_columns(terminal, row, start_column, end_column, character); /* If visible cursor in current row, preserve state */ if (row == terminal->visible_cursor_row && terminal->visible_cursor_col >= start_column && terminal->visible_cursor_col <= end_column) { /* Create copy of character with cursor attribute set */ guac_terminal_char cursor_character = *character; cursor_character.attributes.cursor = true; __guac_terminal_set_columns(terminal, row, terminal->visible_cursor_col, terminal->visible_cursor_col, &cursor_character); } /* Force breaks around destination region */ __guac_terminal_force_break(terminal, row, start_column); __guac_terminal_force_break(terminal, row, end_column + 1); } static void __guac_terminal_redraw_rect(guac_terminal* term, int start_row, int start_col, int end_row, int end_col) { int row, col; /* Redraw region */ for (row=start_row; row<=end_row; row++) { guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(term->buffer, row - term->scroll_offset, 0); /* Clear row */ guac_terminal_display_set_columns(term->display, row, start_col, end_col, &(term->default_char)); /* Copy characters */ for (col=start_col; col <= end_col && col < buffer_row->length; col++) { /* Only redraw if not blank */ guac_terminal_char* c = &(buffer_row->characters[col]); if (guac_terminal_is_visible(term, c)) guac_terminal_display_set_columns(term->display, row, col, col, c); } } } /** * Internal terminal resize routine. Accepts width/height in CHARACTERS * (not pixels like the public function). */ static void __guac_terminal_resize(guac_terminal* term, int width, int height) { /* If height is decreasing, shift display up */ if (height < term->term_height) { int shift_amount; /* Get number of rows actually occupying terminal space */ int used_height = guac_terminal_effective_buffer_length(term); if (used_height > term->term_height) used_height = term->term_height; shift_amount = used_height - height; /* If the new terminal bottom covers N rows, shift up N rows */ if (shift_amount > 0) { guac_terminal_display_copy_rows(term->display, shift_amount, term->display->height - 1, -shift_amount); /* Update buffer top and cursor row based on shift */ term->buffer->top += shift_amount; term->cursor_row -= shift_amount; if (term->visible_cursor_row != -1) term->visible_cursor_row -= shift_amount; /* Redraw characters within old region */ __guac_terminal_redraw_rect(term, height - shift_amount, 0, height-1, width-1); } } /* Resize display */ guac_terminal_display_flush(term->display); guac_terminal_display_resize(term->display, width, height); /* Reraw any characters on right if widening */ if (width > term->term_width) __guac_terminal_redraw_rect(term, 0, term->term_width-1, height-1, width-1); /* If height is increasing, shift display down */ if (height > term->term_height) { /* If undisplayed rows exist in the buffer, shift them into view */ int available_scroll = guac_terminal_available_scroll(term); if (available_scroll > 0) { /* If the new terminal bottom reveals N rows, shift down N rows */ int shift_amount = height - term->term_height; /* The maximum amount we can shift is the number of undisplayed rows */ if (shift_amount > available_scroll) shift_amount = available_scroll; /* Update buffer top and cursor row based on shift */ term->buffer->top -= shift_amount; term->cursor_row += shift_amount; if (term->visible_cursor_row != -1) term->visible_cursor_row += shift_amount; /* If scrolled enough, use scroll to fulfill entire resize */ if (term->scroll_offset >= shift_amount) { term->scroll_offset -= shift_amount; guac_terminal_scrollbar_set_value(term->scrollbar, -term->scroll_offset); /* Draw characters from scroll at bottom */ __guac_terminal_redraw_rect(term, term->term_height, 0, term->term_height + shift_amount - 1, width-1); } /* Otherwise, fulfill with as much scroll as possible */ else { /* Draw characters from scroll at bottom */ __guac_terminal_redraw_rect(term, term->term_height, 0, term->term_height + term->scroll_offset - 1, width-1); /* Update shift_amount and scroll based on new rows */ shift_amount -= term->scroll_offset; term->scroll_offset = 0; guac_terminal_scrollbar_set_value(term->scrollbar, -term->scroll_offset); /* If anything remains, move screen as necessary */ if (shift_amount > 0) { guac_terminal_display_copy_rows(term->display, 0, term->display->height - shift_amount - 1, shift_amount); /* Draw characters at top from scroll */ __guac_terminal_redraw_rect(term, 0, 0, shift_amount - 1, width-1); } } } /* end if undisplayed rows exist */ } /* Keep cursor on screen */ if (term->cursor_row < 0) term->cursor_row = 0; if (term->cursor_row >= height) term->cursor_row = height-1; if (term->cursor_col < 0) term->cursor_col = 0; if (term->cursor_col >= width) term->cursor_col = width-1; /* Commit new dimensions */ term->term_width = width; term->term_height = height; } int guac_terminal_resize(guac_terminal* terminal, int width, int height) { guac_terminal_display* display = terminal->display; guac_client* client = display->client; /* Acquire exclusive access to terminal */ guac_terminal_lock(terminal); /* Set size of available screen area */ terminal->outer_width = width; terminal->outer_height = height; /* Calculate available display area */ int available_width = width - GUAC_TERMINAL_SCROLLBAR_WIDTH; if (available_width < 0) available_width = 0; /* Calculate dimensions */ int rows = height / display->char_height; int columns = available_width / display->char_width; /* Keep height within predefined maximum */ if (rows > GUAC_TERMINAL_MAX_ROWS) { rows = GUAC_TERMINAL_MAX_ROWS; height = rows * display->char_height; } /* Keep width within predefined maximum */ if (columns > GUAC_TERMINAL_MAX_COLUMNS) { columns = GUAC_TERMINAL_MAX_COLUMNS; available_width = columns * display->char_width; width = available_width + GUAC_TERMINAL_SCROLLBAR_WIDTH; } /* Set pixel sizes */ terminal->width = width; terminal->height = height; /* Resize default layer to given pixel dimensions */ guac_terminal_repaint_default_layer(terminal, client->socket); /* Resize terminal if row/column dimensions have changed */ if (columns != terminal->term_width || rows != terminal->term_height) { guac_client_log(client, GUAC_LOG_DEBUG, "Resizing terminal to %ix%i", rows, columns); /* Resize terminal */ __guac_terminal_resize(terminal, columns, rows); /* Reset scroll region */ terminal->scroll_end = rows - 1; } /* Notify scrollbar of resize */ guac_terminal_scrollbar_parent_resized(terminal->scrollbar, width, height, rows); guac_terminal_scrollbar_set_bounds(terminal->scrollbar, -guac_terminal_available_scroll(terminal), 0); /* Release terminal */ guac_terminal_unlock(terminal); guac_terminal_notify(terminal); return 0; } void guac_terminal_flush(guac_terminal* terminal) { /* Flush typescript if in use */ if (terminal->typescript != NULL) guac_terminal_typescript_flush(terminal->typescript); /* Flush pipe stream if automatic flushing is enabled */ if (terminal->pipe_stream_flags & GUAC_TERMINAL_PIPE_AUTOFLUSH) guac_terminal_pipe_stream_flush(terminal); /* Flush display state */ guac_terminal_select_redraw(terminal); guac_terminal_commit_cursor(terminal); guac_terminal_display_flush(terminal->display); guac_terminal_scrollbar_flush(terminal->scrollbar); } void guac_terminal_lock(guac_terminal* terminal) { pthread_mutex_lock(&(terminal->lock)); } void guac_terminal_unlock(guac_terminal* terminal) { pthread_mutex_unlock(&(terminal->lock)); } int guac_terminal_send_data(guac_terminal* term, const char* data, int length) { /* Block all other sources of input if input is coming from a stream */ if (term->input_stream != NULL) return 0; return guac_terminal_write_all(term->stdin_pipe_fd[1], data, length); } int guac_terminal_send_string(guac_terminal* term, const char* data) { /* Block all other sources of input if input is coming from a stream */ if (term->input_stream != NULL) return 0; return guac_terminal_write_all(term->stdin_pipe_fd[1], data, strlen(data)); } static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed) { /* Ignore user input if terminal is not started */ if (!term->started) { guac_client_log(term->client, GUAC_LOG_DEBUG, "Ignoring user input " "while terminal has not yet started."); return 0; } /* Hide mouse cursor if not already hidden */ if (term->current_cursor != GUAC_TERMINAL_CURSOR_BLANK) { term->current_cursor = GUAC_TERMINAL_CURSOR_BLANK; guac_common_cursor_set_blank(term->cursor); guac_terminal_notify(term); } /* Track modifiers */ if (keysym == 0xFFE3) term->mod_ctrl = pressed; else if (keysym == 0xFFE9) term->mod_alt = pressed; else if (keysym == 0xFFE1) term->mod_shift = pressed; /* If key pressed */ else if (pressed) { /* Ctrl+Shift+V shortcut for paste */ if (keysym == 'V' && term->mod_ctrl) return guac_terminal_send_data(term, term->clipboard->buffer, term->clipboard->length); /* Shift+PgUp / Shift+PgDown shortcuts for scrolling */ if (term->mod_shift) { /* Page up */ if (keysym == 0xFF55) { guac_terminal_scroll_display_up(term, term->term_height); return 0; } /* Page down */ if (keysym == 0xFF56) { guac_terminal_scroll_display_down(term, term->term_height); return 0; } } /* Reset scroll */ if (term->scroll_offset != 0) guac_terminal_scroll_display_down(term, term->scroll_offset); /* If alt being held, also send escape character */ if (term->mod_alt) guac_terminal_send_string(term, "\x1B"); /* Translate Ctrl+letter to control code */ if (term->mod_ctrl) { char data; /* Keysyms for '@' through '_' are all conveniently in C0 order */ if (keysym >= '@' && keysym <= '_') data = (char) (keysym - '@'); /* Handle lowercase as well */ else if (keysym >= 'a' && keysym <= 'z') data = (char) (keysym - 'a' + 1); /* Ctrl+? is DEL (0x7f) */ else if (keysym == '?') data = 0x7F; /* Map Ctrl+2 to same result as Ctrl+@ */ else if (keysym == '2') data = 0x00; /* Map Ctrl+3 through Ctrl-7 to the remaining C0 characters such that Ctrl+6 is the same as Ctrl+^ */ else if (keysym >= '3' && keysym <= '7') data = (char) (keysym - '3' + 0x1B); /* Otherwise ignore */ else return 0; return guac_terminal_send_data(term, &data, 1); } /* Translate Unicode to UTF-8 */ else if ((keysym >= 0x00 && keysym <= 0xFF) || ((keysym & 0xFFFF0000) == 0x01000000)) { int length; char data[5]; length = guac_terminal_encode_utf8(keysym & 0xFFFF, data); return guac_terminal_send_data(term, data, length); } /* Typeable keys of number pad */ else if (keysym >= 0xFFAA && keysym <= 0xFFB9) { char value = keysym - 0xFF80; guac_terminal_send_data(term, &value, sizeof(value)); } /* Non-printable keys */ else { /* Backspace can vary based on configuration of terminal by client. */ if (keysym == 0xFF08) { char backspace_str[] = { term->backspace, '\0' }; return guac_terminal_send_string(term, backspace_str); } if (keysym == 0xFF09 || keysym == 0xFF89) return guac_terminal_send_string(term, "\x09"); /* Tab */ if (keysym == 0xFF0D || keysym == 0xFF8D) return guac_terminal_send_string(term, "\x0D"); /* Enter */ if (keysym == 0xFF1B) return guac_terminal_send_string(term, "\x1B"); /* Esc */ if (keysym == 0xFF50 || keysym == 0xFF95) return guac_terminal_send_string(term, "\x1B[1~"); /* Home */ /* Arrow keys w/ application cursor */ if (term->application_cursor_keys) { if (keysym == 0xFF51 || keysym == 0xFF96) return guac_terminal_send_string(term, "\x1BOD"); /* Left */ if (keysym == 0xFF52 || keysym == 0xFF97) return guac_terminal_send_string(term, "\x1BOA"); /* Up */ if (keysym == 0xFF53 || keysym == 0xFF98) return guac_terminal_send_string(term, "\x1BOC"); /* Right */ if (keysym == 0xFF54 || keysym == 0xFF99) return guac_terminal_send_string(term, "\x1BOB"); /* Down */ } else { if (keysym == 0xFF51 || keysym == 0xFF96) return guac_terminal_send_string(term, "\x1B[D"); /* Left */ if (keysym == 0xFF52 || keysym == 0xFF97) return guac_terminal_send_string(term, "\x1B[A"); /* Up */ if (keysym == 0xFF53 || keysym == 0xFF98) return guac_terminal_send_string(term, "\x1B[C"); /* Right */ if (keysym == 0xFF54 || keysym == 0xFF99) return guac_terminal_send_string(term, "\x1B[B"); /* Down */ } if (keysym == 0xFF55 || keysym == 0xFF9A) return guac_terminal_send_string(term, "\x1B[5~"); /* Page up */ if (keysym == 0xFF56 || keysym == 0xFF9B) return guac_terminal_send_string(term, "\x1B[6~"); /* Page down */ if (keysym == 0xFF57 || keysym == 0xFF9C) return guac_terminal_send_string(term, "\x1B[4~"); /* End */ if (keysym == 0xFF63 || keysym == 0xFF9E) return guac_terminal_send_string(term, "\x1B[2~"); /* Insert */ if (keysym == 0xFFBE || keysym == 0xFF91) return guac_terminal_send_string(term, "\x1B[[A"); /* F1 */ if (keysym == 0xFFBF || keysym == 0xFF92) return guac_terminal_send_string(term, "\x1B[[B"); /* F2 */ if (keysym == 0xFFC0 || keysym == 0xFF93) return guac_terminal_send_string(term, "\x1B[[C"); /* F3 */ if (keysym == 0xFFC1 || keysym == 0xFF94) return guac_terminal_send_string(term, "\x1B[[D"); /* F4 */ if (keysym == 0xFFC2) return guac_terminal_send_string(term, "\x1B[[E"); /* F5 */ if (keysym == 0xFFC3) return guac_terminal_send_string(term, "\x1B[17~"); /* F6 */ if (keysym == 0xFFC4) return guac_terminal_send_string(term, "\x1B[18~"); /* F7 */ if (keysym == 0xFFC5) return guac_terminal_send_string(term, "\x1B[19~"); /* F8 */ if (keysym == 0xFFC6) return guac_terminal_send_string(term, "\x1B[20~"); /* F9 */ if (keysym == 0xFFC7) return guac_terminal_send_string(term, "\x1B[21~"); /* F10 */ if (keysym == 0xFFC8) return guac_terminal_send_string(term, "\x1B[22~"); /* F11 */ if (keysym == 0xFFC9) return guac_terminal_send_string(term, "\x1B[23~"); /* F12 */ if (keysym == 0xFFFF || keysym == 0xFF9F) return guac_terminal_send_string(term, "\x1B[3~"); /* Delete */ /* Ignore unknown keys */ guac_client_log(term->client, GUAC_LOG_DEBUG, "Ignoring unknown keysym: 0x%X", keysym); } } return 0; } int guac_terminal_send_key(guac_terminal* term, int keysym, int pressed) { int result; guac_terminal_lock(term); result = __guac_terminal_send_key(term, keysym, pressed); guac_terminal_unlock(term); return result; } static int __guac_terminal_send_mouse(guac_terminal* term, guac_user* user, int x, int y, int mask) { /* Ignore user input if terminal is not started */ if (!term->started) { guac_client_log(term->client, GUAC_LOG_DEBUG, "Ignoring user input " "while terminal has not yet started."); return 0; } /* Determine which buttons were just released and pressed */ int released_mask = term->mouse_mask & ~mask; int pressed_mask = ~term->mouse_mask & mask; /* Store current mouse location/state */ guac_common_cursor_update(term->cursor, user, x, y, mask); /* Notify scrollbar, do not handle anything handled by scrollbar */ if (guac_terminal_scrollbar_handle_mouse(term->scrollbar, x, y, mask)) { /* Set pointer cursor if mouse is over scrollbar */ if (term->current_cursor != GUAC_TERMINAL_CURSOR_POINTER) { term->current_cursor = GUAC_TERMINAL_CURSOR_POINTER; guac_common_cursor_set_pointer(term->cursor); guac_terminal_notify(term); } guac_terminal_notify(term); return 0; } term->mouse_mask = mask; /* Show mouse cursor if not already shown */ if (term->current_cursor != GUAC_TERMINAL_CURSOR_IBAR) { term->current_cursor = GUAC_TERMINAL_CURSOR_IBAR; guac_common_cursor_set_ibar(term->cursor); guac_terminal_notify(term); } /* Paste contents of clipboard on right or middle mouse button up */ if ((released_mask & GUAC_CLIENT_MOUSE_RIGHT) || (released_mask & GUAC_CLIENT_MOUSE_MIDDLE)) return guac_terminal_send_data(term, term->clipboard->buffer, term->clipboard->length); /* If left mouse button was just released, stop selection */ if (released_mask & GUAC_CLIENT_MOUSE_LEFT) guac_terminal_select_end(term); /* Update selection state contextually while the left mouse button is * pressed */ else if (mask & GUAC_CLIENT_MOUSE_LEFT) { int row = y / term->display->char_height - term->scroll_offset; int col = x / term->display->char_width; /* If mouse button was already just pressed, start a new selection or * resume the existing selection depending on whether shift is held */ if (pressed_mask & GUAC_CLIENT_MOUSE_LEFT) { if (term->mod_shift) guac_terminal_select_resume(term, row, col); else guac_terminal_select_start(term, row, col); } /* In all other cases, simply update the existing selection as long as * the mouse button is pressed */ else guac_terminal_select_update(term, row, col); } /* Scroll up if wheel moved up */ if (released_mask & GUAC_CLIENT_MOUSE_SCROLL_UP) guac_terminal_scroll_display_up(term, GUAC_TERMINAL_WHEEL_SCROLL_AMOUNT); /* Scroll down if wheel moved down */ if (released_mask & GUAC_CLIENT_MOUSE_SCROLL_DOWN) guac_terminal_scroll_display_down(term, GUAC_TERMINAL_WHEEL_SCROLL_AMOUNT); return 0; } int guac_terminal_send_mouse(guac_terminal* term, guac_user* user, int x, int y, int mask) { int result; guac_terminal_lock(term); result = __guac_terminal_send_mouse(term, user, x, y, mask); guac_terminal_unlock(term); return result; } void guac_terminal_scroll_handler(guac_terminal_scrollbar* scrollbar, int value) { guac_terminal* terminal = (guac_terminal*) scrollbar->data; /* Calculate change in scroll offset */ int delta = -value - terminal->scroll_offset; /* Update terminal based on change in scroll offset */ if (delta < 0) guac_terminal_scroll_display_down(terminal, -delta); else if (delta > 0) guac_terminal_scroll_display_up(terminal, delta); /* Update scrollbar value */ guac_terminal_scrollbar_set_value(scrollbar, value); } int guac_terminal_sendf(guac_terminal* term, const char* format, ...) { int written; va_list ap; char buffer[1024]; /* Block all other sources of input if input is coming from a stream */ if (term->input_stream != NULL) return 0; /* Print to buffer */ va_start(ap, format); written = vsnprintf(buffer, sizeof(buffer)-1, format, ap); va_end(ap); if (written < 0) return written; /* Write to STDIN */ return guac_terminal_write_all(term->stdin_pipe_fd[1], buffer, written); } void guac_terminal_set_tab(guac_terminal* term, int column) { int i; /* Search for available space, set if available */ for (i=0; icustom_tabs[i] == 0) { term->custom_tabs[i] = column+1; break; } } } void guac_terminal_unset_tab(guac_terminal* term, int column) { int i; /* Search for given tab, unset if found */ for (i=0; icustom_tabs[i] == column+1) { term->custom_tabs[i] = 0; break; } } } void guac_terminal_clear_tabs(guac_terminal* term) { term->tab_interval = 0; memset(term->custom_tabs, 0, sizeof(term->custom_tabs)); } int guac_terminal_next_tab(guac_terminal* term, int column) { int i; /* Determine tab stop from interval */ int tabstop; if (term->tab_interval != 0) tabstop = (column / term->tab_interval + 1) * term->tab_interval; else tabstop = term->term_width - 1; /* Walk custom tabs, trying to find an earlier occurrence */ for (i=0; icustom_tabs[i] - 1; if (custom_tabstop != -1 && custom_tabstop > column && custom_tabstop < tabstop) tabstop = custom_tabstop; } return tabstop; } void guac_terminal_pipe_stream_open(guac_terminal* term, const char* name, int flags) { guac_client* client = term->client; guac_socket* socket = client->socket; /* Close existing stream, if any */ guac_terminal_pipe_stream_close(term); /* Allocate and assign new pipe stream */ term->pipe_stream = guac_client_alloc_stream(client); term->pipe_buffer_length = 0; term->pipe_stream_flags = flags; /* Open new pipe stream */ guac_protocol_send_pipe(socket, term->pipe_stream, "text/plain", name); /* Log redirect at debug level */ guac_client_log(client, GUAC_LOG_DEBUG, "Terminal output now directed to " "pipe \"%s\" (flags=%i).", name, flags); } void guac_terminal_pipe_stream_write(guac_terminal* term, char c) { /* Append byte to buffer only if pipe is open */ if (term->pipe_stream != NULL) { /* Flush buffer if no space is available */ if (term->pipe_buffer_length == sizeof(term->pipe_buffer)) guac_terminal_pipe_stream_flush(term); /* Append single byte to buffer */ term->pipe_buffer[term->pipe_buffer_length++] = c; } } void guac_terminal_pipe_stream_flush(guac_terminal* term) { guac_client* client = term->client; guac_socket* socket = client->socket; guac_stream* pipe_stream = term->pipe_stream; /* Write blob if data exists in buffer */ if (pipe_stream != NULL && term->pipe_buffer_length > 0) { guac_protocol_send_blob(socket, pipe_stream, term->pipe_buffer, term->pipe_buffer_length); term->pipe_buffer_length = 0; } } void guac_terminal_pipe_stream_close(guac_terminal* term) { guac_client* client = term->client; guac_socket* socket = client->socket; guac_stream* pipe_stream = term->pipe_stream; /* Close any existing pipe */ if (pipe_stream != NULL) { /* Write end of stream */ guac_terminal_pipe_stream_flush(term); guac_protocol_send_end(socket, pipe_stream); /* Destroy stream */ guac_client_free_stream(client, pipe_stream); term->pipe_stream = NULL; /* Log redirect at debug level */ guac_client_log(client, GUAC_LOG_DEBUG, "Terminal output now redirected to display."); } } int guac_terminal_create_typescript(guac_terminal* term, const char* path, const char* name, int create_path) { /* Create typescript */ term->typescript = guac_terminal_typescript_alloc(path, name, create_path); /* Log failure */ if (term->typescript == NULL) { guac_client_log(term->client, GUAC_LOG_ERROR, "Creation of typescript failed: %s", strerror(errno)); return 1; } /* If typescript was successfully created, log filenames */ guac_client_log(term->client, GUAC_LOG_INFO, "Typescript of terminal session will be saved to \"%s\". " "Timing file is \"%s\".", term->typescript->data_filename, term->typescript->timing_filename); /* Typescript creation succeeded */ return 0; } void guac_terminal_dup(guac_terminal* term, guac_user* user, guac_socket* socket) { /* Synchronize display state with new user */ guac_terminal_repaint_default_layer(term, socket); guac_terminal_display_dup(term->display, user, socket); /* Synchronize mouse cursor */ guac_common_cursor_dup(term->cursor, user, socket); /* Paint scrollbar for joining user */ guac_terminal_scrollbar_dup(term->scrollbar, user, socket); } void guac_terminal_apply_color_scheme(guac_terminal* terminal, const char* color_scheme) { guac_client* client = terminal->client; guac_terminal_char* default_char = &terminal->default_char; guac_terminal_display* display = terminal->display; /* Reinitialize default terminal colors with values from color scheme */ guac_terminal_parse_color_scheme(client, color_scheme, &default_char->attributes.foreground, &default_char->attributes.background, display->default_palette); /* Reinitialize default attributes of buffer and display */ guac_terminal_display_reset_palette(display); display->default_foreground = default_char->attributes.foreground; display->default_background = default_char->attributes.background; /* Redraw terminal text and background */ guac_terminal_repaint_default_layer(terminal, client->socket); __guac_terminal_redraw_rect(terminal, 0, 0, terminal->term_height - 1, terminal->term_width - 1); /* Acquire exclusive access to terminal */ guac_terminal_lock(terminal); /* Update stored copy of color scheme */ free((char*) terminal->color_scheme); terminal->color_scheme = strdup(color_scheme); /* Release terminal */ guac_terminal_unlock(terminal); guac_terminal_notify(terminal); } void guac_terminal_apply_font(guac_terminal* terminal, const char* font_name, int font_size, int dpi) { guac_client* client = terminal->client; guac_terminal_display* display = terminal->display; if (guac_terminal_display_set_font(display, font_name, font_size, dpi)) return; /* Resize terminal to fit available region, now that font metrics may be * different */ guac_terminal_resize(terminal, terminal->outer_width, terminal->outer_height); /* Redraw terminal text and background */ guac_terminal_repaint_default_layer(terminal, client->socket); __guac_terminal_redraw_rect(terminal, 0, 0, terminal->term_height - 1, terminal->term_width - 1); /* Acquire exclusive access to terminal */ guac_terminal_lock(terminal); /* Update stored copy of font name, if changed */ if (font_name != NULL) terminal->font_name = strdup(font_name); /* Update stored copy of font size, if changed */ if (font_size != -1) terminal->font_size = font_size; /* Release terminal */ guac_terminal_unlock(terminal); guac_terminal_notify(terminal); } guacamole-server-1.3.0/src/terminal/Makefile.in0000644000175100001440000012402613772471103016353 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/terminal ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libguac_terminal_la_DEPENDENCIES = am_libguac_terminal_la_OBJECTS = libguac_terminal_la-buffer.lo \ libguac_terminal_la-char_mappings.lo \ libguac_terminal_la-color-scheme.lo \ libguac_terminal_la-common.lo libguac_terminal_la-display.lo \ libguac_terminal_la-named-colors.lo \ libguac_terminal_la-palette.lo \ libguac_terminal_la-scrollbar.lo libguac_terminal_la-select.lo \ libguac_terminal_la-terminal.lo \ libguac_terminal_la-terminal_handlers.lo \ libguac_terminal_la-terminal-stdin-stream.lo \ libguac_terminal_la-typescript.lo \ libguac_terminal_la-xparsecolor.lo libguac_terminal_la_OBJECTS = $(am_libguac_terminal_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libguac_terminal_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libguac_terminal_la_CFLAGS) $(CFLAGS) \ $(libguac_terminal_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libguac_terminal_la-buffer.Plo \ ./$(DEPDIR)/libguac_terminal_la-char_mappings.Plo \ ./$(DEPDIR)/libguac_terminal_la-color-scheme.Plo \ ./$(DEPDIR)/libguac_terminal_la-common.Plo \ ./$(DEPDIR)/libguac_terminal_la-display.Plo \ ./$(DEPDIR)/libguac_terminal_la-named-colors.Plo \ ./$(DEPDIR)/libguac_terminal_la-palette.Plo \ ./$(DEPDIR)/libguac_terminal_la-scrollbar.Plo \ ./$(DEPDIR)/libguac_terminal_la-select.Plo \ ./$(DEPDIR)/libguac_terminal_la-terminal-stdin-stream.Plo \ ./$(DEPDIR)/libguac_terminal_la-terminal.Plo \ ./$(DEPDIR)/libguac_terminal_la-terminal_handlers.Plo \ ./$(DEPDIR)/libguac_terminal_la-typescript.Plo \ ./$(DEPDIR)/libguac_terminal_la-xparsecolor.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libguac_terminal_la_SOURCES) DIST_SOURCES = $(libguac_terminal_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 noinst_LTLIBRARIES = libguac_terminal.la noinst_HEADERS = \ terminal/buffer.h \ terminal/char_mappings.h \ terminal/common.h \ terminal/color-scheme.h \ terminal/display.h \ terminal/named-colors.h \ terminal/palette.h \ terminal/scrollbar.h \ terminal/select.h \ terminal/terminal.h \ terminal/terminal_handlers.h \ terminal/types.h \ terminal/typescript.h \ terminal/xparsecolor.h libguac_terminal_la_SOURCES = \ buffer.c \ char_mappings.c \ color-scheme.c \ common.c \ display.c \ named-colors.c \ palette.c \ scrollbar.c \ select.c \ terminal.c \ terminal_handlers.c \ terminal-stdin-stream.c \ typescript.c \ xparsecolor.c libguac_terminal_la_CFLAGS = \ -Werror -Wall \ @COMMON_INCLUDE@ \ @LIBGUAC_INCLUDE@ \ @PANGO_CFLAGS@ \ @PANGOCAIRO_CFLAGS@ libguac_terminal_la_LIBADD = \ @LIBGUAC_LTLIB@ libguac_terminal_la_LDFLAGS = \ @CAIRO_LIBS@ \ @MATH_LIBS@ \ @PANGO_LIBS@ \ @PANGOCAIRO_LIBS@ \ @PTHREAD_LIBS@ all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/terminal/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/terminal/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libguac_terminal.la: $(libguac_terminal_la_OBJECTS) $(libguac_terminal_la_DEPENDENCIES) $(EXTRA_libguac_terminal_la_DEPENDENCIES) $(AM_V_CCLD)$(libguac_terminal_la_LINK) $(libguac_terminal_la_OBJECTS) $(libguac_terminal_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-buffer.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-char_mappings.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-color-scheme.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-common.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-display.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-named-colors.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-palette.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-scrollbar.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-select.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-terminal-stdin-stream.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-terminal.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-terminal_handlers.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-typescript.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_terminal_la-xparsecolor.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libguac_terminal_la-buffer.lo: buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-buffer.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-buffer.Tpo -c -o libguac_terminal_la-buffer.lo `test -f 'buffer.c' || echo '$(srcdir)/'`buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-buffer.Tpo $(DEPDIR)/libguac_terminal_la-buffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='buffer.c' object='libguac_terminal_la-buffer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-buffer.lo `test -f 'buffer.c' || echo '$(srcdir)/'`buffer.c libguac_terminal_la-char_mappings.lo: char_mappings.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-char_mappings.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-char_mappings.Tpo -c -o libguac_terminal_la-char_mappings.lo `test -f 'char_mappings.c' || echo '$(srcdir)/'`char_mappings.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-char_mappings.Tpo $(DEPDIR)/libguac_terminal_la-char_mappings.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='char_mappings.c' object='libguac_terminal_la-char_mappings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-char_mappings.lo `test -f 'char_mappings.c' || echo '$(srcdir)/'`char_mappings.c libguac_terminal_la-color-scheme.lo: color-scheme.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-color-scheme.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-color-scheme.Tpo -c -o libguac_terminal_la-color-scheme.lo `test -f 'color-scheme.c' || echo '$(srcdir)/'`color-scheme.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-color-scheme.Tpo $(DEPDIR)/libguac_terminal_la-color-scheme.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='color-scheme.c' object='libguac_terminal_la-color-scheme.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-color-scheme.lo `test -f 'color-scheme.c' || echo '$(srcdir)/'`color-scheme.c libguac_terminal_la-common.lo: common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-common.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-common.Tpo -c -o libguac_terminal_la-common.lo `test -f 'common.c' || echo '$(srcdir)/'`common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-common.Tpo $(DEPDIR)/libguac_terminal_la-common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common.c' object='libguac_terminal_la-common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-common.lo `test -f 'common.c' || echo '$(srcdir)/'`common.c libguac_terminal_la-display.lo: display.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-display.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-display.Tpo -c -o libguac_terminal_la-display.lo `test -f 'display.c' || echo '$(srcdir)/'`display.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-display.Tpo $(DEPDIR)/libguac_terminal_la-display.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display.c' object='libguac_terminal_la-display.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-display.lo `test -f 'display.c' || echo '$(srcdir)/'`display.c libguac_terminal_la-named-colors.lo: named-colors.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-named-colors.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-named-colors.Tpo -c -o libguac_terminal_la-named-colors.lo `test -f 'named-colors.c' || echo '$(srcdir)/'`named-colors.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-named-colors.Tpo $(DEPDIR)/libguac_terminal_la-named-colors.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='named-colors.c' object='libguac_terminal_la-named-colors.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-named-colors.lo `test -f 'named-colors.c' || echo '$(srcdir)/'`named-colors.c libguac_terminal_la-palette.lo: palette.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-palette.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-palette.Tpo -c -o libguac_terminal_la-palette.lo `test -f 'palette.c' || echo '$(srcdir)/'`palette.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-palette.Tpo $(DEPDIR)/libguac_terminal_la-palette.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='palette.c' object='libguac_terminal_la-palette.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-palette.lo `test -f 'palette.c' || echo '$(srcdir)/'`palette.c libguac_terminal_la-scrollbar.lo: scrollbar.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-scrollbar.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-scrollbar.Tpo -c -o libguac_terminal_la-scrollbar.lo `test -f 'scrollbar.c' || echo '$(srcdir)/'`scrollbar.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-scrollbar.Tpo $(DEPDIR)/libguac_terminal_la-scrollbar.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='scrollbar.c' object='libguac_terminal_la-scrollbar.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-scrollbar.lo `test -f 'scrollbar.c' || echo '$(srcdir)/'`scrollbar.c libguac_terminal_la-select.lo: select.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-select.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-select.Tpo -c -o libguac_terminal_la-select.lo `test -f 'select.c' || echo '$(srcdir)/'`select.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-select.Tpo $(DEPDIR)/libguac_terminal_la-select.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='select.c' object='libguac_terminal_la-select.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-select.lo `test -f 'select.c' || echo '$(srcdir)/'`select.c libguac_terminal_la-terminal.lo: terminal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-terminal.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-terminal.Tpo -c -o libguac_terminal_la-terminal.lo `test -f 'terminal.c' || echo '$(srcdir)/'`terminal.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-terminal.Tpo $(DEPDIR)/libguac_terminal_la-terminal.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal.c' object='libguac_terminal_la-terminal.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-terminal.lo `test -f 'terminal.c' || echo '$(srcdir)/'`terminal.c libguac_terminal_la-terminal_handlers.lo: terminal_handlers.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-terminal_handlers.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-terminal_handlers.Tpo -c -o libguac_terminal_la-terminal_handlers.lo `test -f 'terminal_handlers.c' || echo '$(srcdir)/'`terminal_handlers.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-terminal_handlers.Tpo $(DEPDIR)/libguac_terminal_la-terminal_handlers.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal_handlers.c' object='libguac_terminal_la-terminal_handlers.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-terminal_handlers.lo `test -f 'terminal_handlers.c' || echo '$(srcdir)/'`terminal_handlers.c libguac_terminal_la-terminal-stdin-stream.lo: terminal-stdin-stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-terminal-stdin-stream.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-terminal-stdin-stream.Tpo -c -o libguac_terminal_la-terminal-stdin-stream.lo `test -f 'terminal-stdin-stream.c' || echo '$(srcdir)/'`terminal-stdin-stream.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-terminal-stdin-stream.Tpo $(DEPDIR)/libguac_terminal_la-terminal-stdin-stream.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='terminal-stdin-stream.c' object='libguac_terminal_la-terminal-stdin-stream.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-terminal-stdin-stream.lo `test -f 'terminal-stdin-stream.c' || echo '$(srcdir)/'`terminal-stdin-stream.c libguac_terminal_la-typescript.lo: typescript.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-typescript.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-typescript.Tpo -c -o libguac_terminal_la-typescript.lo `test -f 'typescript.c' || echo '$(srcdir)/'`typescript.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-typescript.Tpo $(DEPDIR)/libguac_terminal_la-typescript.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='typescript.c' object='libguac_terminal_la-typescript.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-typescript.lo `test -f 'typescript.c' || echo '$(srcdir)/'`typescript.c libguac_terminal_la-xparsecolor.lo: xparsecolor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -MT libguac_terminal_la-xparsecolor.lo -MD -MP -MF $(DEPDIR)/libguac_terminal_la-xparsecolor.Tpo -c -o libguac_terminal_la-xparsecolor.lo `test -f 'xparsecolor.c' || echo '$(srcdir)/'`xparsecolor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_terminal_la-xparsecolor.Tpo $(DEPDIR)/libguac_terminal_la-xparsecolor.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xparsecolor.c' object='libguac_terminal_la-xparsecolor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_terminal_la_CFLAGS) $(CFLAGS) -c -o libguac_terminal_la-xparsecolor.lo `test -f 'xparsecolor.c' || echo '$(srcdir)/'`xparsecolor.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/libguac_terminal_la-buffer.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-char_mappings.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-color-scheme.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-common.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-display.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-named-colors.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-palette.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-scrollbar.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-select.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-terminal-stdin-stream.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-terminal.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-terminal_handlers.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-typescript.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-xparsecolor.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libguac_terminal_la-buffer.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-char_mappings.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-color-scheme.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-common.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-display.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-named-colors.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-palette.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-scrollbar.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-select.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-terminal-stdin-stream.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-terminal.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-terminal_handlers.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-typescript.Plo -rm -f ./$(DEPDIR)/libguac_terminal_la-xparsecolor.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/terminal/named-colors.c0000644000175100001440000010321613702142276017032 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "terminal/palette.h" #include #include /** * A guac_terminal_color definition associated with a descriptive name. */ typedef struct guac_terminal_named_color { /** * The color associated with the name. */ guac_terminal_color color; /** * The name of the color. Each name must be lowercase and may not contain * any whitespace. */ const char* name; } guac_terminal_named_color; /** * An array of several colors and their corresponding names. This array must at * least contain the color names accepted by xterm. */ const guac_terminal_named_color GUAC_TERMINAL_NAMED_COLORS[] = { /* Color names supported by xterm */ {{ -1, 0xF0, 0xF8, 0xFF }, "aliceblue" }, {{ -1, 0xFA, 0xEB, 0xD7 }, "antiquewhite" }, {{ -1, 0xFF, 0xEF, 0xDB }, "antiquewhite1" }, {{ -1, 0xEE, 0xDF, 0xCC }, "antiquewhite2" }, {{ -1, 0xCD, 0xC0, 0xB0 }, "antiquewhite3" }, {{ -1, 0x8B, 0x83, 0x78 }, "antiquewhite4" }, {{ -1, 0x00, 0xFF, 0xFF }, "aqua" }, {{ -1, 0x7F, 0xFF, 0xD4 }, "aquamarine" }, {{ -1, 0x7F, 0xFF, 0xD4 }, "aquamarine1" }, {{ -1, 0x76, 0xEE, 0xC6 }, "aquamarine2" }, {{ -1, 0x66, 0xCD, 0xAA }, "aquamarine3" }, {{ -1, 0x45, 0x8B, 0x74 }, "aquamarine4" }, {{ -1, 0xF0, 0xFF, 0xFF }, "azure" }, {{ -1, 0xF0, 0xFF, 0xFF }, "azure1" }, {{ -1, 0xE0, 0xEE, 0xEE }, "azure2" }, {{ -1, 0xC1, 0xCD, 0xCD }, "azure3" }, {{ -1, 0x83, 0x8B, 0x8B }, "azure4" }, {{ -1, 0xF5, 0xF5, 0xDC }, "beige" }, {{ -1, 0xFF, 0xE4, 0xC4 }, "bisque" }, {{ -1, 0xFF, 0xE4, 0xC4 }, "bisque1" }, {{ -1, 0xEE, 0xD5, 0xB7 }, "bisque2" }, {{ -1, 0xCD, 0xB7, 0x9E }, "bisque3" }, {{ -1, 0x8B, 0x7D, 0x6B }, "bisque4" }, {{ -1, 0x00, 0x00, 0x00 }, "black" }, {{ -1, 0xFF, 0xEB, 0xCD }, "blanchedalmond" }, {{ -1, 0x00, 0x00, 0xFF }, "blue" }, {{ -1, 0x00, 0x00, 0xFF }, "blue1" }, {{ -1, 0x00, 0x00, 0xEE }, "blue2" }, {{ -1, 0x00, 0x00, 0xCD }, "blue3" }, {{ -1, 0x00, 0x00, 0x8B }, "blue4" }, {{ -1, 0x8A, 0x2B, 0xE2 }, "blueviolet" }, {{ -1, 0xA5, 0x2A, 0x2A }, "brown" }, {{ -1, 0xFF, 0x40, 0x40 }, "brown1" }, {{ -1, 0xEE, 0x3B, 0x3B }, "brown2" }, {{ -1, 0xCD, 0x33, 0x33 }, "brown3" }, {{ -1, 0x8B, 0x23, 0x23 }, "brown4" }, {{ -1, 0xDE, 0xB8, 0x87 }, "burlywood" }, {{ -1, 0xFF, 0xD3, 0x9B }, "burlywood1" }, {{ -1, 0xEE, 0xC5, 0x91 }, "burlywood2" }, {{ -1, 0xCD, 0xAA, 0x7D }, "burlywood3" }, {{ -1, 0x8B, 0x73, 0x55 }, "burlywood4" }, {{ -1, 0x5F, 0x9E, 0xA0 }, "cadetblue" }, {{ -1, 0x98, 0xF5, 0xFF }, "cadetblue1" }, {{ -1, 0x8E, 0xE5, 0xEE }, "cadetblue2" }, {{ -1, 0x7A, 0xC5, 0xCD }, "cadetblue3" }, {{ -1, 0x53, 0x86, 0x8B }, "cadetblue4" }, {{ -1, 0x7F, 0xFF, 0x00 }, "chartreuse" }, {{ -1, 0x7F, 0xFF, 0x00 }, "chartreuse1" }, {{ -1, 0x76, 0xEE, 0x00 }, "chartreuse2" }, {{ -1, 0x66, 0xCD, 0x00 }, "chartreuse3" }, {{ -1, 0x45, 0x8B, 0x00 }, "chartreuse4" }, {{ -1, 0xD2, 0x69, 0x1E }, "chocolate" }, {{ -1, 0xFF, 0x7F, 0x24 }, "chocolate1" }, {{ -1, 0xEE, 0x76, 0x21 }, "chocolate2" }, {{ -1, 0xCD, 0x66, 0x1D }, "chocolate3" }, {{ -1, 0x8B, 0x45, 0x13 }, "chocolate4" }, {{ -1, 0xFF, 0x7F, 0x50 }, "coral" }, {{ -1, 0xFF, 0x72, 0x56 }, "coral1" }, {{ -1, 0xEE, 0x6A, 0x50 }, "coral2" }, {{ -1, 0xCD, 0x5B, 0x45 }, "coral3" }, {{ -1, 0x8B, 0x3E, 0x2F }, "coral4" }, {{ -1, 0x64, 0x95, 0xED }, "cornflowerblue" }, {{ -1, 0xFF, 0xF8, 0xDC }, "cornsilk" }, {{ -1, 0xFF, 0xF8, 0xDC }, "cornsilk1" }, {{ -1, 0xEE, 0xE8, 0xCD }, "cornsilk2" }, {{ -1, 0xCD, 0xC8, 0xB1 }, "cornsilk3" }, {{ -1, 0x8B, 0x88, 0x78 }, "cornsilk4" }, {{ -1, 0xDC, 0x14, 0x3C }, "crimson" }, {{ -1, 0x00, 0xFF, 0xFF }, "cyan" }, {{ -1, 0x00, 0xFF, 0xFF }, "cyan1" }, {{ -1, 0x00, 0xEE, 0xEE }, "cyan2" }, {{ -1, 0x00, 0xCD, 0xCD }, "cyan3" }, {{ -1, 0x00, 0x8B, 0x8B }, "cyan4" }, {{ -1, 0x00, 0x00, 0x8B }, "darkblue" }, {{ -1, 0x00, 0x8B, 0x8B }, "darkcyan" }, {{ -1, 0xB8, 0x86, 0x0B }, "darkgoldenrod" }, {{ -1, 0xFF, 0xB9, 0x0F }, "darkgoldenrod1" }, {{ -1, 0xEE, 0xAD, 0x0E }, "darkgoldenrod2" }, {{ -1, 0xCD, 0x95, 0x0C }, "darkgoldenrod3" }, {{ -1, 0x8B, 0x65, 0x08 }, "darkgoldenrod4" }, {{ -1, 0xA9, 0xA9, 0xA9 }, "darkgray" }, {{ -1, 0x00, 0x64, 0x00 }, "darkgreen" }, {{ -1, 0xA9, 0xA9, 0xA9 }, "darkgrey" }, {{ -1, 0xBD, 0xB7, 0x6B }, "darkkhaki" }, {{ -1, 0x8B, 0x00, 0x8B }, "darkmagenta" }, {{ -1, 0x55, 0x6B, 0x2F }, "darkolivegreen" }, {{ -1, 0xCA, 0xFF, 0x70 }, "darkolivegreen1" }, {{ -1, 0xBC, 0xEE, 0x68 }, "darkolivegreen2" }, {{ -1, 0xA2, 0xCD, 0x5A }, "darkolivegreen3" }, {{ -1, 0x6E, 0x8B, 0x3D }, "darkolivegreen4" }, {{ -1, 0xFF, 0x8C, 0x00 }, "darkorange" }, {{ -1, 0xFF, 0x7F, 0x00 }, "darkorange1" }, {{ -1, 0xEE, 0x76, 0x00 }, "darkorange2" }, {{ -1, 0xCD, 0x66, 0x00 }, "darkorange3" }, {{ -1, 0x8B, 0x45, 0x00 }, "darkorange4" }, {{ -1, 0x99, 0x32, 0xCC }, "darkorchid" }, {{ -1, 0xBF, 0x3E, 0xFF }, "darkorchid1" }, {{ -1, 0xB2, 0x3A, 0xEE }, "darkorchid2" }, {{ -1, 0x9A, 0x32, 0xCD }, "darkorchid3" }, {{ -1, 0x68, 0x22, 0x8B }, "darkorchid4" }, {{ -1, 0x8B, 0x00, 0x00 }, "darkred" }, {{ -1, 0xE9, 0x96, 0x7A }, "darksalmon" }, {{ -1, 0x8F, 0xBC, 0x8F }, "darkseagreen" }, {{ -1, 0xC1, 0xFF, 0xC1 }, "darkseagreen1" }, {{ -1, 0xB4, 0xEE, 0xB4 }, "darkseagreen2" }, {{ -1, 0x9B, 0xCD, 0x9B }, "darkseagreen3" }, {{ -1, 0x69, 0x8B, 0x69 }, "darkseagreen4" }, {{ -1, 0x48, 0x3D, 0x8B }, "darkslateblue" }, {{ -1, 0x2F, 0x4F, 0x4F }, "darkslategray" }, {{ -1, 0x97, 0xFF, 0xFF }, "darkslategray1" }, {{ -1, 0x8D, 0xEE, 0xEE }, "darkslategray2" }, {{ -1, 0x79, 0xCD, 0xCD }, "darkslategray3" }, {{ -1, 0x52, 0x8B, 0x8B }, "darkslategray4" }, {{ -1, 0x2F, 0x4F, 0x4F }, "darkslategrey" }, {{ -1, 0x00, 0xCE, 0xD1 }, "darkturquoise" }, {{ -1, 0x94, 0x00, 0xD3 }, "darkviolet" }, {{ -1, 0xFF, 0x14, 0x93 }, "deeppink" }, {{ -1, 0xFF, 0x14, 0x93 }, "deeppink1" }, {{ -1, 0xEE, 0x12, 0x89 }, "deeppink2" }, {{ -1, 0xCD, 0x10, 0x76 }, "deeppink3" }, {{ -1, 0x8B, 0x0A, 0x50 }, "deeppink4" }, {{ -1, 0x00, 0xBF, 0xFF }, "deepskyblue" }, {{ -1, 0x00, 0xBF, 0xFF }, "deepskyblue1" }, {{ -1, 0x00, 0xB2, 0xEE }, "deepskyblue2" }, {{ -1, 0x00, 0x9A, 0xCD }, "deepskyblue3" }, {{ -1, 0x00, 0x68, 0x8B }, "deepskyblue4" }, {{ -1, 0x69, 0x69, 0x69 }, "dimgray" }, {{ -1, 0x69, 0x69, 0x69 }, "dimgrey" }, {{ -1, 0x1E, 0x90, 0xFF }, "dodgerblue" }, {{ -1, 0x1E, 0x90, 0xFF }, "dodgerblue1" }, {{ -1, 0x1C, 0x86, 0xEE }, "dodgerblue2" }, {{ -1, 0x18, 0x74, 0xCD }, "dodgerblue3" }, {{ -1, 0x10, 0x4E, 0x8B }, "dodgerblue4" }, {{ -1, 0xB2, 0x22, 0x22 }, "firebrick" }, {{ -1, 0xFF, 0x30, 0x30 }, "firebrick1" }, {{ -1, 0xEE, 0x2C, 0x2C }, "firebrick2" }, {{ -1, 0xCD, 0x26, 0x26 }, "firebrick3" }, {{ -1, 0x8B, 0x1A, 0x1A }, "firebrick4" }, {{ -1, 0xFF, 0xFA, 0xF0 }, "floralwhite" }, {{ -1, 0x22, 0x8B, 0x22 }, "forestgreen" }, {{ -1, 0xFF, 0x00, 0xFF }, "fuchsia" }, {{ -1, 0xDC, 0xDC, 0xDC }, "gainsboro" }, {{ -1, 0xF8, 0xF8, 0xFF }, "ghostwhite" }, {{ -1, 0xFF, 0xD7, 0x00 }, "gold" }, {{ -1, 0xFF, 0xD7, 0x00 }, "gold1" }, {{ -1, 0xEE, 0xC9, 0x00 }, "gold2" }, {{ -1, 0xCD, 0xAD, 0x00 }, "gold3" }, {{ -1, 0x8B, 0x75, 0x00 }, "gold4" }, {{ -1, 0xDA, 0xA5, 0x20 }, "goldenrod" }, {{ -1, 0xFF, 0xC1, 0x25 }, "goldenrod1" }, {{ -1, 0xEE, 0xB4, 0x22 }, "goldenrod2" }, {{ -1, 0xCD, 0x9B, 0x1D }, "goldenrod3" }, {{ -1, 0x8B, 0x69, 0x14 }, "goldenrod4" }, {{ -1, 0xBE, 0xBE, 0xBE }, "gray" }, {{ -1, 0x00, 0x00, 0x00 }, "gray0" }, {{ -1, 0x03, 0x03, 0x03 }, "gray1" }, {{ -1, 0x1A, 0x1A, 0x1A }, "gray10" }, {{ -1, 0xFF, 0xFF, 0xFF }, "gray100" }, {{ -1, 0x1C, 0x1C, 0x1C }, "gray11" }, {{ -1, 0x1F, 0x1F, 0x1F }, "gray12" }, {{ -1, 0x21, 0x21, 0x21 }, "gray13" }, {{ -1, 0x24, 0x24, 0x24 }, "gray14" }, {{ -1, 0x26, 0x26, 0x26 }, "gray15" }, {{ -1, 0x29, 0x29, 0x29 }, "gray16" }, {{ -1, 0x2B, 0x2B, 0x2B }, "gray17" }, {{ -1, 0x2E, 0x2E, 0x2E }, "gray18" }, {{ -1, 0x30, 0x30, 0x30 }, "gray19" }, {{ -1, 0x05, 0x05, 0x05 }, "gray2" }, {{ -1, 0x33, 0x33, 0x33 }, "gray20" }, {{ -1, 0x36, 0x36, 0x36 }, "gray21" }, {{ -1, 0x38, 0x38, 0x38 }, "gray22" }, {{ -1, 0x3B, 0x3B, 0x3B }, "gray23" }, {{ -1, 0x3D, 0x3D, 0x3D }, "gray24" }, {{ -1, 0x40, 0x40, 0x40 }, "gray25" }, {{ -1, 0x42, 0x42, 0x42 }, "gray26" }, {{ -1, 0x45, 0x45, 0x45 }, "gray27" }, {{ -1, 0x47, 0x47, 0x47 }, "gray28" }, {{ -1, 0x4A, 0x4A, 0x4A }, "gray29" }, {{ -1, 0x08, 0x08, 0x08 }, "gray3" }, {{ -1, 0x4D, 0x4D, 0x4D }, "gray30" }, {{ -1, 0x4F, 0x4F, 0x4F }, "gray31" }, {{ -1, 0x52, 0x52, 0x52 }, "gray32" }, {{ -1, 0x54, 0x54, 0x54 }, "gray33" }, {{ -1, 0x57, 0x57, 0x57 }, "gray34" }, {{ -1, 0x59, 0x59, 0x59 }, "gray35" }, {{ -1, 0x5C, 0x5C, 0x5C }, "gray36" }, {{ -1, 0x5E, 0x5E, 0x5E }, "gray37" }, {{ -1, 0x61, 0x61, 0x61 }, "gray38" }, {{ -1, 0x63, 0x63, 0x63 }, "gray39" }, {{ -1, 0x0A, 0x0A, 0x0A }, "gray4" }, {{ -1, 0x66, 0x66, 0x66 }, "gray40" }, {{ -1, 0x69, 0x69, 0x69 }, "gray41" }, {{ -1, 0x6B, 0x6B, 0x6B }, "gray42" }, {{ -1, 0x6E, 0x6E, 0x6E }, "gray43" }, {{ -1, 0x70, 0x70, 0x70 }, "gray44" }, {{ -1, 0x73, 0x73, 0x73 }, "gray45" }, {{ -1, 0x75, 0x75, 0x75 }, "gray46" }, {{ -1, 0x78, 0x78, 0x78 }, "gray47" }, {{ -1, 0x7A, 0x7A, 0x7A }, "gray48" }, {{ -1, 0x7D, 0x7D, 0x7D }, "gray49" }, {{ -1, 0x0D, 0x0D, 0x0D }, "gray5" }, {{ -1, 0x7F, 0x7F, 0x7F }, "gray50" }, {{ -1, 0x82, 0x82, 0x82 }, "gray51" }, {{ -1, 0x85, 0x85, 0x85 }, "gray52" }, {{ -1, 0x87, 0x87, 0x87 }, "gray53" }, {{ -1, 0x8A, 0x8A, 0x8A }, "gray54" }, {{ -1, 0x8C, 0x8C, 0x8C }, "gray55" }, {{ -1, 0x8F, 0x8F, 0x8F }, "gray56" }, {{ -1, 0x91, 0x91, 0x91 }, "gray57" }, {{ -1, 0x94, 0x94, 0x94 }, "gray58" }, {{ -1, 0x96, 0x96, 0x96 }, "gray59" }, {{ -1, 0x0F, 0x0F, 0x0F }, "gray6" }, {{ -1, 0x99, 0x99, 0x99 }, "gray60" }, {{ -1, 0x9C, 0x9C, 0x9C }, "gray61" }, {{ -1, 0x9E, 0x9E, 0x9E }, "gray62" }, {{ -1, 0xA1, 0xA1, 0xA1 }, "gray63" }, {{ -1, 0xA3, 0xA3, 0xA3 }, "gray64" }, {{ -1, 0xA6, 0xA6, 0xA6 }, "gray65" }, {{ -1, 0xA8, 0xA8, 0xA8 }, "gray66" }, {{ -1, 0xAB, 0xAB, 0xAB }, "gray67" }, {{ -1, 0xAD, 0xAD, 0xAD }, "gray68" }, {{ -1, 0xB0, 0xB0, 0xB0 }, "gray69" }, {{ -1, 0x12, 0x12, 0x12 }, "gray7" }, {{ -1, 0xB3, 0xB3, 0xB3 }, "gray70" }, {{ -1, 0xB5, 0xB5, 0xB5 }, "gray71" }, {{ -1, 0xB8, 0xB8, 0xB8 }, "gray72" }, {{ -1, 0xBA, 0xBA, 0xBA }, "gray73" }, {{ -1, 0xBD, 0xBD, 0xBD }, "gray74" }, {{ -1, 0xBF, 0xBF, 0xBF }, "gray75" }, {{ -1, 0xC2, 0xC2, 0xC2 }, "gray76" }, {{ -1, 0xC4, 0xC4, 0xC4 }, "gray77" }, {{ -1, 0xC7, 0xC7, 0xC7 }, "gray78" }, {{ -1, 0xC9, 0xC9, 0xC9 }, "gray79" }, {{ -1, 0x14, 0x14, 0x14 }, "gray8" }, {{ -1, 0xCC, 0xCC, 0xCC }, "gray80" }, {{ -1, 0xCF, 0xCF, 0xCF }, "gray81" }, {{ -1, 0xD1, 0xD1, 0xD1 }, "gray82" }, {{ -1, 0xD4, 0xD4, 0xD4 }, "gray83" }, {{ -1, 0xD6, 0xD6, 0xD6 }, "gray84" }, {{ -1, 0xD9, 0xD9, 0xD9 }, "gray85" }, {{ -1, 0xDB, 0xDB, 0xDB }, "gray86" }, {{ -1, 0xDE, 0xDE, 0xDE }, "gray87" }, {{ -1, 0xE0, 0xE0, 0xE0 }, "gray88" }, {{ -1, 0xE3, 0xE3, 0xE3 }, "gray89" }, {{ -1, 0x17, 0x17, 0x17 }, "gray9" }, {{ -1, 0xE5, 0xE5, 0xE5 }, "gray90" }, {{ -1, 0xE8, 0xE8, 0xE8 }, "gray91" }, {{ -1, 0xEB, 0xEB, 0xEB }, "gray92" }, {{ -1, 0xED, 0xED, 0xED }, "gray93" }, {{ -1, 0xF0, 0xF0, 0xF0 }, "gray94" }, {{ -1, 0xF2, 0xF2, 0xF2 }, "gray95" }, {{ -1, 0xF5, 0xF5, 0xF5 }, "gray96" }, {{ -1, 0xF7, 0xF7, 0xF7 }, "gray97" }, {{ -1, 0xFA, 0xFA, 0xFA }, "gray98" }, {{ -1, 0xFC, 0xFC, 0xFC }, "gray99" }, {{ -1, 0x00, 0xFF, 0x00 }, "green" }, {{ -1, 0x00, 0xFF, 0x00 }, "green1" }, {{ -1, 0x00, 0xEE, 0x00 }, "green2" }, {{ -1, 0x00, 0xCD, 0x00 }, "green3" }, {{ -1, 0x00, 0x8B, 0x00 }, "green4" }, {{ -1, 0xAD, 0xFF, 0x2F }, "greenyellow" }, {{ -1, 0xBE, 0xBE, 0xBE }, "grey" }, {{ -1, 0x00, 0x00, 0x00 }, "grey0" }, {{ -1, 0x03, 0x03, 0x03 }, "grey1" }, {{ -1, 0x1A, 0x1A, 0x1A }, "grey10" }, {{ -1, 0xFF, 0xFF, 0xFF }, "grey100" }, {{ -1, 0x1C, 0x1C, 0x1C }, "grey11" }, {{ -1, 0x1F, 0x1F, 0x1F }, "grey12" }, {{ -1, 0x21, 0x21, 0x21 }, "grey13" }, {{ -1, 0x24, 0x24, 0x24 }, "grey14" }, {{ -1, 0x26, 0x26, 0x26 }, "grey15" }, {{ -1, 0x29, 0x29, 0x29 }, "grey16" }, {{ -1, 0x2B, 0x2B, 0x2B }, "grey17" }, {{ -1, 0x2E, 0x2E, 0x2E }, "grey18" }, {{ -1, 0x30, 0x30, 0x30 }, "grey19" }, {{ -1, 0x05, 0x05, 0x05 }, "grey2" }, {{ -1, 0x33, 0x33, 0x33 }, "grey20" }, {{ -1, 0x36, 0x36, 0x36 }, "grey21" }, {{ -1, 0x38, 0x38, 0x38 }, "grey22" }, {{ -1, 0x3B, 0x3B, 0x3B }, "grey23" }, {{ -1, 0x3D, 0x3D, 0x3D }, "grey24" }, {{ -1, 0x40, 0x40, 0x40 }, "grey25" }, {{ -1, 0x42, 0x42, 0x42 }, "grey26" }, {{ -1, 0x45, 0x45, 0x45 }, "grey27" }, {{ -1, 0x47, 0x47, 0x47 }, "grey28" }, {{ -1, 0x4A, 0x4A, 0x4A }, "grey29" }, {{ -1, 0x08, 0x08, 0x08 }, "grey3" }, {{ -1, 0x4D, 0x4D, 0x4D }, "grey30" }, {{ -1, 0x4F, 0x4F, 0x4F }, "grey31" }, {{ -1, 0x52, 0x52, 0x52 }, "grey32" }, {{ -1, 0x54, 0x54, 0x54 }, "grey33" }, {{ -1, 0x57, 0x57, 0x57 }, "grey34" }, {{ -1, 0x59, 0x59, 0x59 }, "grey35" }, {{ -1, 0x5C, 0x5C, 0x5C }, "grey36" }, {{ -1, 0x5E, 0x5E, 0x5E }, "grey37" }, {{ -1, 0x61, 0x61, 0x61 }, "grey38" }, {{ -1, 0x63, 0x63, 0x63 }, "grey39" }, {{ -1, 0x0A, 0x0A, 0x0A }, "grey4" }, {{ -1, 0x66, 0x66, 0x66 }, "grey40" }, {{ -1, 0x69, 0x69, 0x69 }, "grey41" }, {{ -1, 0x6B, 0x6B, 0x6B }, "grey42" }, {{ -1, 0x6E, 0x6E, 0x6E }, "grey43" }, {{ -1, 0x70, 0x70, 0x70 }, "grey44" }, {{ -1, 0x73, 0x73, 0x73 }, "grey45" }, {{ -1, 0x75, 0x75, 0x75 }, "grey46" }, {{ -1, 0x78, 0x78, 0x78 }, "grey47" }, {{ -1, 0x7A, 0x7A, 0x7A }, "grey48" }, {{ -1, 0x7D, 0x7D, 0x7D }, "grey49" }, {{ -1, 0x0D, 0x0D, 0x0D }, "grey5" }, {{ -1, 0x7F, 0x7F, 0x7F }, "grey50" }, {{ -1, 0x82, 0x82, 0x82 }, "grey51" }, {{ -1, 0x85, 0x85, 0x85 }, "grey52" }, {{ -1, 0x87, 0x87, 0x87 }, "grey53" }, {{ -1, 0x8A, 0x8A, 0x8A }, "grey54" }, {{ -1, 0x8C, 0x8C, 0x8C }, "grey55" }, {{ -1, 0x8F, 0x8F, 0x8F }, "grey56" }, {{ -1, 0x91, 0x91, 0x91 }, "grey57" }, {{ -1, 0x94, 0x94, 0x94 }, "grey58" }, {{ -1, 0x96, 0x96, 0x96 }, "grey59" }, {{ -1, 0x0F, 0x0F, 0x0F }, "grey6" }, {{ -1, 0x99, 0x99, 0x99 }, "grey60" }, {{ -1, 0x9C, 0x9C, 0x9C }, "grey61" }, {{ -1, 0x9E, 0x9E, 0x9E }, "grey62" }, {{ -1, 0xA1, 0xA1, 0xA1 }, "grey63" }, {{ -1, 0xA3, 0xA3, 0xA3 }, "grey64" }, {{ -1, 0xA6, 0xA6, 0xA6 }, "grey65" }, {{ -1, 0xA8, 0xA8, 0xA8 }, "grey66" }, {{ -1, 0xAB, 0xAB, 0xAB }, "grey67" }, {{ -1, 0xAD, 0xAD, 0xAD }, "grey68" }, {{ -1, 0xB0, 0xB0, 0xB0 }, "grey69" }, {{ -1, 0x12, 0x12, 0x12 }, "grey7" }, {{ -1, 0xB3, 0xB3, 0xB3 }, "grey70" }, {{ -1, 0xB5, 0xB5, 0xB5 }, "grey71" }, {{ -1, 0xB8, 0xB8, 0xB8 }, "grey72" }, {{ -1, 0xBA, 0xBA, 0xBA }, "grey73" }, {{ -1, 0xBD, 0xBD, 0xBD }, "grey74" }, {{ -1, 0xBF, 0xBF, 0xBF }, "grey75" }, {{ -1, 0xC2, 0xC2, 0xC2 }, "grey76" }, {{ -1, 0xC4, 0xC4, 0xC4 }, "grey77" }, {{ -1, 0xC7, 0xC7, 0xC7 }, "grey78" }, {{ -1, 0xC9, 0xC9, 0xC9 }, "grey79" }, {{ -1, 0x14, 0x14, 0x14 }, "grey8" }, {{ -1, 0xCC, 0xCC, 0xCC }, "grey80" }, {{ -1, 0xCF, 0xCF, 0xCF }, "grey81" }, {{ -1, 0xD1, 0xD1, 0xD1 }, "grey82" }, {{ -1, 0xD4, 0xD4, 0xD4 }, "grey83" }, {{ -1, 0xD6, 0xD6, 0xD6 }, "grey84" }, {{ -1, 0xD9, 0xD9, 0xD9 }, "grey85" }, {{ -1, 0xDB, 0xDB, 0xDB }, "grey86" }, {{ -1, 0xDE, 0xDE, 0xDE }, "grey87" }, {{ -1, 0xE0, 0xE0, 0xE0 }, "grey88" }, {{ -1, 0xE3, 0xE3, 0xE3 }, "grey89" }, {{ -1, 0x17, 0x17, 0x17 }, "grey9" }, {{ -1, 0xE5, 0xE5, 0xE5 }, "grey90" }, {{ -1, 0xE8, 0xE8, 0xE8 }, "grey91" }, {{ -1, 0xEB, 0xEB, 0xEB }, "grey92" }, {{ -1, 0xED, 0xED, 0xED }, "grey93" }, {{ -1, 0xF0, 0xF0, 0xF0 }, "grey94" }, {{ -1, 0xF2, 0xF2, 0xF2 }, "grey95" }, {{ -1, 0xF5, 0xF5, 0xF5 }, "grey96" }, {{ -1, 0xF7, 0xF7, 0xF7 }, "grey97" }, {{ -1, 0xFA, 0xFA, 0xFA }, "grey98" }, {{ -1, 0xFC, 0xFC, 0xFC }, "grey99" }, {{ -1, 0xF0, 0xFF, 0xF0 }, "honeydew" }, {{ -1, 0xF0, 0xFF, 0xF0 }, "honeydew1" }, {{ -1, 0xE0, 0xEE, 0xE0 }, "honeydew2" }, {{ -1, 0xC1, 0xCD, 0xC1 }, "honeydew3" }, {{ -1, 0x83, 0x8B, 0x83 }, "honeydew4" }, {{ -1, 0xFF, 0x69, 0xB4 }, "hotpink" }, {{ -1, 0xFF, 0x6E, 0xB4 }, "hotpink1" }, {{ -1, 0xEE, 0x6A, 0xA7 }, "hotpink2" }, {{ -1, 0xCD, 0x60, 0x90 }, "hotpink3" }, {{ -1, 0x8B, 0x3A, 0x62 }, "hotpink4" }, {{ -1, 0xCD, 0x5C, 0x5C }, "indianred" }, {{ -1, 0xFF, 0x6A, 0x6A }, "indianred1" }, {{ -1, 0xEE, 0x63, 0x63 }, "indianred2" }, {{ -1, 0xCD, 0x55, 0x55 }, "indianred3" }, {{ -1, 0x8B, 0x3A, 0x3A }, "indianred4" }, {{ -1, 0x4B, 0x00, 0x82 }, "indigo" }, {{ -1, 0xFF, 0xFF, 0xF0 }, "ivory" }, {{ -1, 0xFF, 0xFF, 0xF0 }, "ivory1" }, {{ -1, 0xEE, 0xEE, 0xE0 }, "ivory2" }, {{ -1, 0xCD, 0xCD, 0xC1 }, "ivory3" }, {{ -1, 0x8B, 0x8B, 0x83 }, "ivory4" }, {{ -1, 0xF0, 0xE6, 0x8C }, "khaki" }, {{ -1, 0xFF, 0xF6, 0x8F }, "khaki1" }, {{ -1, 0xEE, 0xE6, 0x85 }, "khaki2" }, {{ -1, 0xCD, 0xC6, 0x73 }, "khaki3" }, {{ -1, 0x8B, 0x86, 0x4E }, "khaki4" }, {{ -1, 0xE6, 0xE6, 0xFA }, "lavender" }, {{ -1, 0xFF, 0xF0, 0xF5 }, "lavenderblush" }, {{ -1, 0xFF, 0xF0, 0xF5 }, "lavenderblush1" }, {{ -1, 0xEE, 0xE0, 0xE5 }, "lavenderblush2" }, {{ -1, 0xCD, 0xC1, 0xC5 }, "lavenderblush3" }, {{ -1, 0x8B, 0x83, 0x86 }, "lavenderblush4" }, {{ -1, 0x7C, 0xFC, 0x00 }, "lawngreen" }, {{ -1, 0xFF, 0xFA, 0xCD }, "lemonchiffon" }, {{ -1, 0xFF, 0xFA, 0xCD }, "lemonchiffon1" }, {{ -1, 0xEE, 0xE9, 0xBF }, "lemonchiffon2" }, {{ -1, 0xCD, 0xC9, 0xA5 }, "lemonchiffon3" }, {{ -1, 0x8B, 0x89, 0x70 }, "lemonchiffon4" }, {{ -1, 0xAD, 0xD8, 0xE6 }, "lightblue" }, {{ -1, 0xBF, 0xEF, 0xFF }, "lightblue1" }, {{ -1, 0xB2, 0xDF, 0xEE }, "lightblue2" }, {{ -1, 0x9A, 0xC0, 0xCD }, "lightblue3" }, {{ -1, 0x68, 0x83, 0x8B }, "lightblue4" }, {{ -1, 0xF0, 0x80, 0x80 }, "lightcoral" }, {{ -1, 0xE0, 0xFF, 0xFF }, "lightcyan" }, {{ -1, 0xE0, 0xFF, 0xFF }, "lightcyan1" }, {{ -1, 0xD1, 0xEE, 0xEE }, "lightcyan2" }, {{ -1, 0xB4, 0xCD, 0xCD }, "lightcyan3" }, {{ -1, 0x7A, 0x8B, 0x8B }, "lightcyan4" }, {{ -1, 0xEE, 0xDD, 0x82 }, "lightgoldenrod" }, {{ -1, 0xFF, 0xEC, 0x8B }, "lightgoldenrod1" }, {{ -1, 0xEE, 0xDC, 0x82 }, "lightgoldenrod2" }, {{ -1, 0xCD, 0xBE, 0x70 }, "lightgoldenrod3" }, {{ -1, 0x8B, 0x81, 0x4C }, "lightgoldenrod4" }, {{ -1, 0xFA, 0xFA, 0xD2 }, "lightgoldenrodyellow" }, {{ -1, 0xD3, 0xD3, 0xD3 }, "lightgray" }, {{ -1, 0x90, 0xEE, 0x90 }, "lightgreen" }, {{ -1, 0xD3, 0xD3, 0xD3 }, "lightgrey" }, {{ -1, 0xFF, 0xB6, 0xC1 }, "lightpink" }, {{ -1, 0xFF, 0xAE, 0xB9 }, "lightpink1" }, {{ -1, 0xEE, 0xA2, 0xAD }, "lightpink2" }, {{ -1, 0xCD, 0x8C, 0x95 }, "lightpink3" }, {{ -1, 0x8B, 0x5F, 0x65 }, "lightpink4" }, {{ -1, 0xFF, 0xA0, 0x7A }, "lightsalmon" }, {{ -1, 0xFF, 0xA0, 0x7A }, "lightsalmon1" }, {{ -1, 0xEE, 0x95, 0x72 }, "lightsalmon2" }, {{ -1, 0xCD, 0x81, 0x62 }, "lightsalmon3" }, {{ -1, 0x8B, 0x57, 0x42 }, "lightsalmon4" }, {{ -1, 0x20, 0xB2, 0xAA }, "lightseagreen" }, {{ -1, 0x87, 0xCE, 0xFA }, "lightskyblue" }, {{ -1, 0xB0, 0xE2, 0xFF }, "lightskyblue1" }, {{ -1, 0xA4, 0xD3, 0xEE }, "lightskyblue2" }, {{ -1, 0x8D, 0xB6, 0xCD }, "lightskyblue3" }, {{ -1, 0x60, 0x7B, 0x8B }, "lightskyblue4" }, {{ -1, 0x84, 0x70, 0xFF }, "lightslateblue" }, {{ -1, 0x77, 0x88, 0x99 }, "lightslategray" }, {{ -1, 0x77, 0x88, 0x99 }, "lightslategrey" }, {{ -1, 0xB0, 0xC4, 0xDE }, "lightsteelblue" }, {{ -1, 0xCA, 0xE1, 0xFF }, "lightsteelblue1" }, {{ -1, 0xBC, 0xD2, 0xEE }, "lightsteelblue2" }, {{ -1, 0xA2, 0xB5, 0xCD }, "lightsteelblue3" }, {{ -1, 0x6E, 0x7B, 0x8B }, "lightsteelblue4" }, {{ -1, 0xFF, 0xFF, 0xE0 }, "lightyellow" }, {{ -1, 0xFF, 0xFF, 0xE0 }, "lightyellow1" }, {{ -1, 0xEE, 0xEE, 0xD1 }, "lightyellow2" }, {{ -1, 0xCD, 0xCD, 0xB4 }, "lightyellow3" }, {{ -1, 0x8B, 0x8B, 0x7A }, "lightyellow4" }, {{ -1, 0x00, 0xFF, 0x00 }, "lime" }, {{ -1, 0x32, 0xCD, 0x32 }, "limegreen" }, {{ -1, 0xFA, 0xF0, 0xE6 }, "linen" }, {{ -1, 0xFF, 0x00, 0xFF }, "magenta" }, {{ -1, 0xFF, 0x00, 0xFF }, "magenta1" }, {{ -1, 0xEE, 0x00, 0xEE }, "magenta2" }, {{ -1, 0xCD, 0x00, 0xCD }, "magenta3" }, {{ -1, 0x8B, 0x00, 0x8B }, "magenta4" }, {{ -1, 0xB0, 0x30, 0x60 }, "maroon" }, {{ -1, 0xFF, 0x34, 0xB3 }, "maroon1" }, {{ -1, 0xEE, 0x30, 0xA7 }, "maroon2" }, {{ -1, 0xCD, 0x29, 0x90 }, "maroon3" }, {{ -1, 0x8B, 0x1C, 0x62 }, "maroon4" }, {{ -1, 0x66, 0xCD, 0xAA }, "mediumaquamarine" }, {{ -1, 0x00, 0x00, 0xCD }, "mediumblue" }, {{ -1, 0xBA, 0x55, 0xD3 }, "mediumorchid" }, {{ -1, 0xE0, 0x66, 0xFF }, "mediumorchid1" }, {{ -1, 0xD1, 0x5F, 0xEE }, "mediumorchid2" }, {{ -1, 0xB4, 0x52, 0xCD }, "mediumorchid3" }, {{ -1, 0x7A, 0x37, 0x8B }, "mediumorchid4" }, {{ -1, 0x93, 0x70, 0xDB }, "mediumpurple" }, {{ -1, 0xAB, 0x82, 0xFF }, "mediumpurple1" }, {{ -1, 0x9F, 0x79, 0xEE }, "mediumpurple2" }, {{ -1, 0x89, 0x68, 0xCD }, "mediumpurple3" }, {{ -1, 0x5D, 0x47, 0x8B }, "mediumpurple4" }, {{ -1, 0x3C, 0xB3, 0x71 }, "mediumseagreen" }, {{ -1, 0x7B, 0x68, 0xEE }, "mediumslateblue" }, {{ -1, 0x00, 0xFA, 0x9A }, "mediumspringgreen" }, {{ -1, 0x48, 0xD1, 0xCC }, "mediumturquoise" }, {{ -1, 0xC7, 0x15, 0x85 }, "mediumvioletred" }, {{ -1, 0x19, 0x19, 0x70 }, "midnightblue" }, {{ -1, 0xF5, 0xFF, 0xFA }, "mintcream" }, {{ -1, 0xFF, 0xE4, 0xE1 }, "mistyrose" }, {{ -1, 0xFF, 0xE4, 0xE1 }, "mistyrose1" }, {{ -1, 0xEE, 0xD5, 0xD2 }, "mistyrose2" }, {{ -1, 0xCD, 0xB7, 0xB5 }, "mistyrose3" }, {{ -1, 0x8B, 0x7D, 0x7B }, "mistyrose4" }, {{ -1, 0xFF, 0xE4, 0xB5 }, "moccasin" }, {{ -1, 0xFF, 0xDE, 0xAD }, "navajowhite" }, {{ -1, 0xFF, 0xDE, 0xAD }, "navajowhite1" }, {{ -1, 0xEE, 0xCF, 0xA1 }, "navajowhite2" }, {{ -1, 0xCD, 0xB3, 0x8B }, "navajowhite3" }, {{ -1, 0x8B, 0x79, 0x5E }, "navajowhite4" }, {{ -1, 0x00, 0x00, 0x80 }, "navy" }, {{ -1, 0x00, 0x00, 0x80 }, "navyblue" }, {{ -1, 0xFD, 0xF5, 0xE6 }, "oldlace" }, {{ -1, 0x80, 0x80, 0x00 }, "olive" }, {{ -1, 0x6B, 0x8E, 0x23 }, "olivedrab" }, {{ -1, 0xC0, 0xFF, 0x3E }, "olivedrab1" }, {{ -1, 0xB3, 0xEE, 0x3A }, "olivedrab2" }, {{ -1, 0x9A, 0xCD, 0x32 }, "olivedrab3" }, {{ -1, 0x69, 0x8B, 0x22 }, "olivedrab4" }, {{ -1, 0xFF, 0xA5, 0x00 }, "orange" }, {{ -1, 0xFF, 0xA5, 0x00 }, "orange1" }, {{ -1, 0xEE, 0x9A, 0x00 }, "orange2" }, {{ -1, 0xCD, 0x85, 0x00 }, "orange3" }, {{ -1, 0x8B, 0x5A, 0x00 }, "orange4" }, {{ -1, 0xFF, 0x45, 0x00 }, "orangered" }, {{ -1, 0xFF, 0x45, 0x00 }, "orangered1" }, {{ -1, 0xEE, 0x40, 0x00 }, "orangered2" }, {{ -1, 0xCD, 0x37, 0x00 }, "orangered3" }, {{ -1, 0x8B, 0x25, 0x00 }, "orangered4" }, {{ -1, 0xDA, 0x70, 0xD6 }, "orchid" }, {{ -1, 0xFF, 0x83, 0xFA }, "orchid1" }, {{ -1, 0xEE, 0x7A, 0xE9 }, "orchid2" }, {{ -1, 0xCD, 0x69, 0xC9 }, "orchid3" }, {{ -1, 0x8B, 0x47, 0x89 }, "orchid4" }, {{ -1, 0xEE, 0xE8, 0xAA }, "palegoldenrod" }, {{ -1, 0x98, 0xFB, 0x98 }, "palegreen" }, {{ -1, 0x9A, 0xFF, 0x9A }, "palegreen1" }, {{ -1, 0x90, 0xEE, 0x90 }, "palegreen2" }, {{ -1, 0x7C, 0xCD, 0x7C }, "palegreen3" }, {{ -1, 0x54, 0x8B, 0x54 }, "palegreen4" }, {{ -1, 0xAF, 0xEE, 0xEE }, "paleturquoise" }, {{ -1, 0xBB, 0xFF, 0xFF }, "paleturquoise1" }, {{ -1, 0xAE, 0xEE, 0xEE }, "paleturquoise2" }, {{ -1, 0x96, 0xCD, 0xCD }, "paleturquoise3" }, {{ -1, 0x66, 0x8B, 0x8B }, "paleturquoise4" }, {{ -1, 0xDB, 0x70, 0x93 }, "palevioletred" }, {{ -1, 0xFF, 0x82, 0xAB }, "palevioletred1" }, {{ -1, 0xEE, 0x79, 0x9F }, "palevioletred2" }, {{ -1, 0xCD, 0x68, 0x89 }, "palevioletred3" }, {{ -1, 0x8B, 0x47, 0x5D }, "palevioletred4" }, {{ -1, 0xFF, 0xEF, 0xD5 }, "papayawhip" }, {{ -1, 0xFF, 0xDA, 0xB9 }, "peachpuff" }, {{ -1, 0xFF, 0xDA, 0xB9 }, "peachpuff1" }, {{ -1, 0xEE, 0xCB, 0xAD }, "peachpuff2" }, {{ -1, 0xCD, 0xAF, 0x95 }, "peachpuff3" }, {{ -1, 0x8B, 0x77, 0x65 }, "peachpuff4" }, {{ -1, 0xCD, 0x85, 0x3F }, "peru" }, {{ -1, 0xFF, 0xC0, 0xCB }, "pink" }, {{ -1, 0xFF, 0xB5, 0xC5 }, "pink1" }, {{ -1, 0xEE, 0xA9, 0xB8 }, "pink2" }, {{ -1, 0xCD, 0x91, 0x9E }, "pink3" }, {{ -1, 0x8B, 0x63, 0x6C }, "pink4" }, {{ -1, 0xDD, 0xA0, 0xDD }, "plum" }, {{ -1, 0xFF, 0xBB, 0xFF }, "plum1" }, {{ -1, 0xEE, 0xAE, 0xEE }, "plum2" }, {{ -1, 0xCD, 0x96, 0xCD }, "plum3" }, {{ -1, 0x8B, 0x66, 0x8B }, "plum4" }, {{ -1, 0xB0, 0xE0, 0xE6 }, "powderblue" }, {{ -1, 0xA0, 0x20, 0xF0 }, "purple" }, {{ -1, 0x9B, 0x30, 0xFF }, "purple1" }, {{ -1, 0x91, 0x2C, 0xEE }, "purple2" }, {{ -1, 0x7D, 0x26, 0xCD }, "purple3" }, {{ -1, 0x55, 0x1A, 0x8B }, "purple4" }, {{ -1, 0x66, 0x33, 0x99 }, "rebeccapurple" }, {{ -1, 0xFF, 0x00, 0x00 }, "red" }, {{ -1, 0xFF, 0x00, 0x00 }, "red1" }, {{ -1, 0xEE, 0x00, 0x00 }, "red2" }, {{ -1, 0xCD, 0x00, 0x00 }, "red3" }, {{ -1, 0x8B, 0x00, 0x00 }, "red4" }, {{ -1, 0xBC, 0x8F, 0x8F }, "rosybrown" }, {{ -1, 0xFF, 0xC1, 0xC1 }, "rosybrown1" }, {{ -1, 0xEE, 0xB4, 0xB4 }, "rosybrown2" }, {{ -1, 0xCD, 0x9B, 0x9B }, "rosybrown3" }, {{ -1, 0x8B, 0x69, 0x69 }, "rosybrown4" }, {{ -1, 0x41, 0x69, 0xE1 }, "royalblue" }, {{ -1, 0x48, 0x76, 0xFF }, "royalblue1" }, {{ -1, 0x43, 0x6E, 0xEE }, "royalblue2" }, {{ -1, 0x3A, 0x5F, 0xCD }, "royalblue3" }, {{ -1, 0x27, 0x40, 0x8B }, "royalblue4" }, {{ -1, 0x8B, 0x45, 0x13 }, "saddlebrown" }, {{ -1, 0xFA, 0x80, 0x72 }, "salmon" }, {{ -1, 0xFF, 0x8C, 0x69 }, "salmon1" }, {{ -1, 0xEE, 0x82, 0x62 }, "salmon2" }, {{ -1, 0xCD, 0x70, 0x54 }, "salmon3" }, {{ -1, 0x8B, 0x4C, 0x39 }, "salmon4" }, {{ -1, 0xF4, 0xA4, 0x60 }, "sandybrown" }, {{ -1, 0x2E, 0x8B, 0x57 }, "seagreen" }, {{ -1, 0x54, 0xFF, 0x9F }, "seagreen1" }, {{ -1, 0x4E, 0xEE, 0x94 }, "seagreen2" }, {{ -1, 0x43, 0xCD, 0x80 }, "seagreen3" }, {{ -1, 0x2E, 0x8B, 0x57 }, "seagreen4" }, {{ -1, 0xFF, 0xF5, 0xEE }, "seashell" }, {{ -1, 0xFF, 0xF5, 0xEE }, "seashell1" }, {{ -1, 0xEE, 0xE5, 0xDE }, "seashell2" }, {{ -1, 0xCD, 0xC5, 0xBF }, "seashell3" }, {{ -1, 0x8B, 0x86, 0x82 }, "seashell4" }, {{ -1, 0xA0, 0x52, 0x2D }, "sienna" }, {{ -1, 0xFF, 0x82, 0x47 }, "sienna1" }, {{ -1, 0xEE, 0x79, 0x42 }, "sienna2" }, {{ -1, 0xCD, 0x68, 0x39 }, "sienna3" }, {{ -1, 0x8B, 0x47, 0x26 }, "sienna4" }, {{ -1, 0xC0, 0xC0, 0xC0 }, "silver" }, {{ -1, 0x87, 0xCE, 0xEB }, "skyblue" }, {{ -1, 0x87, 0xCE, 0xFF }, "skyblue1" }, {{ -1, 0x7E, 0xC0, 0xEE }, "skyblue2" }, {{ -1, 0x6C, 0xA6, 0xCD }, "skyblue3" }, {{ -1, 0x4A, 0x70, 0x8B }, "skyblue4" }, {{ -1, 0x6A, 0x5A, 0xCD }, "slateblue" }, {{ -1, 0x83, 0x6F, 0xFF }, "slateblue1" }, {{ -1, 0x7A, 0x67, 0xEE }, "slateblue2" }, {{ -1, 0x69, 0x59, 0xCD }, "slateblue3" }, {{ -1, 0x47, 0x3C, 0x8B }, "slateblue4" }, {{ -1, 0x70, 0x80, 0x90 }, "slategray" }, {{ -1, 0xC6, 0xE2, 0xFF }, "slategray1" }, {{ -1, 0xB9, 0xD3, 0xEE }, "slategray2" }, {{ -1, 0x9F, 0xB6, 0xCD }, "slategray3" }, {{ -1, 0x6C, 0x7B, 0x8B }, "slategray4" }, {{ -1, 0x70, 0x80, 0x90 }, "slategrey" }, {{ -1, 0xFF, 0xFA, 0xFA }, "snow" }, {{ -1, 0xFF, 0xFA, 0xFA }, "snow1" }, {{ -1, 0xEE, 0xE9, 0xE9 }, "snow2" }, {{ -1, 0xCD, 0xC9, 0xC9 }, "snow3" }, {{ -1, 0x8B, 0x89, 0x89 }, "snow4" }, {{ -1, 0x00, 0xFF, 0x7F }, "springgreen" }, {{ -1, 0x00, 0xFF, 0x7F }, "springgreen1" }, {{ -1, 0x00, 0xEE, 0x76 }, "springgreen2" }, {{ -1, 0x00, 0xCD, 0x66 }, "springgreen3" }, {{ -1, 0x00, 0x8B, 0x45 }, "springgreen4" }, {{ -1, 0x46, 0x82, 0xB4 }, "steelblue" }, {{ -1, 0x63, 0xB8, 0xFF }, "steelblue1" }, {{ -1, 0x5C, 0xAC, 0xEE }, "steelblue2" }, {{ -1, 0x4F, 0x94, 0xCD }, "steelblue3" }, {{ -1, 0x36, 0x64, 0x8B }, "steelblue4" }, {{ -1, 0xD2, 0xB4, 0x8C }, "tan" }, {{ -1, 0xFF, 0xA5, 0x4F }, "tan1" }, {{ -1, 0xEE, 0x9A, 0x49 }, "tan2" }, {{ -1, 0xCD, 0x85, 0x3F }, "tan3" }, {{ -1, 0x8B, 0x5A, 0x2B }, "tan4" }, {{ -1, 0x00, 0x80, 0x80 }, "teal" }, {{ -1, 0xD8, 0xBF, 0xD8 }, "thistle" }, {{ -1, 0xFF, 0xE1, 0xFF }, "thistle1" }, {{ -1, 0xEE, 0xD2, 0xEE }, "thistle2" }, {{ -1, 0xCD, 0xB5, 0xCD }, "thistle3" }, {{ -1, 0x8B, 0x7B, 0x8B }, "thistle4" }, {{ -1, 0xFF, 0x63, 0x47 }, "tomato" }, {{ -1, 0xFF, 0x63, 0x47 }, "tomato1" }, {{ -1, 0xEE, 0x5C, 0x42 }, "tomato2" }, {{ -1, 0xCD, 0x4F, 0x39 }, "tomato3" }, {{ -1, 0x8B, 0x36, 0x26 }, "tomato4" }, {{ -1, 0x40, 0xE0, 0xD0 }, "turquoise" }, {{ -1, 0x00, 0xF5, 0xFF }, "turquoise1" }, {{ -1, 0x00, 0xE5, 0xEE }, "turquoise2" }, {{ -1, 0x00, 0xC5, 0xCD }, "turquoise3" }, {{ -1, 0x00, 0x86, 0x8B }, "turquoise4" }, {{ -1, 0xEE, 0x82, 0xEE }, "violet" }, {{ -1, 0xD0, 0x20, 0x90 }, "violetred" }, {{ -1, 0xFF, 0x3E, 0x96 }, "violetred1" }, {{ -1, 0xEE, 0x3A, 0x8C }, "violetred2" }, {{ -1, 0xCD, 0x32, 0x78 }, "violetred3" }, {{ -1, 0x8B, 0x22, 0x52 }, "violetred4" }, {{ -1, 0x80, 0x80, 0x80 }, "webgray" }, {{ -1, 0x00, 0x80, 0x00 }, "webgreen" }, {{ -1, 0x80, 0x80, 0x80 }, "webgrey" }, {{ -1, 0x80, 0x00, 0x00 }, "webmaroon" }, {{ -1, 0x80, 0x00, 0x80 }, "webpurple" }, {{ -1, 0xF5, 0xDE, 0xB3 }, "wheat" }, {{ -1, 0xFF, 0xE7, 0xBA }, "wheat1" }, {{ -1, 0xEE, 0xD8, 0xAE }, "wheat2" }, {{ -1, 0xCD, 0xBA, 0x96 }, "wheat3" }, {{ -1, 0x8B, 0x7E, 0x66 }, "wheat4" }, {{ -1, 0xFF, 0xFF, 0xFF }, "white" }, {{ -1, 0xF5, 0xF5, 0xF5 }, "whitesmoke" }, {{ -1, 0xBE, 0xBE, 0xBE }, "x11gray" }, {{ -1, 0x00, 0xFF, 0x00 }, "x11green" }, {{ -1, 0xBE, 0xBE, 0xBE }, "x11grey" }, {{ -1, 0xB0, 0x30, 0x60 }, "x11maroon" }, {{ -1, 0xA0, 0x20, 0xF0 }, "x11purple" }, {{ -1, 0xFF, 0xFF, 0x00 }, "yellow" }, {{ -1, 0xFF, 0xFF, 0x00 }, "yellow1" }, {{ -1, 0xEE, 0xEE, 0x00 }, "yellow2" }, {{ -1, 0xCD, 0xCD, 0x00 }, "yellow3" }, {{ -1, 0x8B, 0x8B, 0x00 }, "yellow4" }, {{ -1, 0x9A, 0xCD, 0x32 }, "yellowgreen" } }; /** * The number of elements within the GUAC_TERMINAL_NAMED_COLORS array. */ #define GUAC_TERMINAL_NAMED_COLORS_LENGTH \ (sizeof(GUAC_TERMINAL_NAMED_COLORS) / sizeof(guac_terminal_named_color)) /** * Compares the string search key given to bsearch() with the name of a * guac_terminal_named_color, ignoring case and whitespace. * * @param a * A pointer to a string containing the search key (color name). * * @param b * A pointer to a guac_terminal_named_color structure whose name should be * compared against the search key. * * @returns * Zero if the search key and color name are identical, a negative value if * the search key sorts before the color name, or a positive value if the * search key sorts after the color name. */ static int guac_terminal_named_color_search(const void* a, const void* b) { const char* key = (const char*) a; const char* name = ((const guac_terminal_named_color*) b)->name; /* For each corresponding character pair in each string */ for (; *key && *name; key++, name++) { /* Skip any spaces in key (name will never have spaces) */ while (*key && isspace(*key)) key++; /* Treat semi-colon as string terminator, to support parsing color names within a larger string (e.g. within the terminal color-scheme configuration string). */ const int keyChar = (*key == ';') ? '\0' : tolower(*key); /* Compare, ignoring case (name is already known to be lowercase) */ int difference = keyChar - *name; if (difference) return difference; } /* If we haven't reached the end of name yet, key is shorter */ if (*name) return -1; /* The strings are identical */ return 0; } int guac_terminal_find_color(const char* name, guac_terminal_color* color) { /* Search for the color having the given name */ guac_terminal_named_color* found = bsearch(name, GUAC_TERMINAL_NAMED_COLORS, GUAC_TERMINAL_NAMED_COLORS_LENGTH, sizeof(guac_terminal_named_color), guac_terminal_named_color_search); /* Fail if no such color is found */ if (found == NULL) return 1; /* Otherwise copy the found color */ *color = found->color; return 0; } guacamole-server-1.3.0/src/terminal/palette.c0000644000175100001440000002211513702142276016103 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "terminal/palette.h" const guac_terminal_color GUAC_TERMINAL_INITIAL_PALETTE[256] = { /* Normal colors */ {0, 0x00, 0x00, 0x00}, /* Black */ {1, 0x99, 0x3E, 0x3E}, /* Red */ {2, 0x3E, 0x99, 0x3E}, /* Green */ {3, 0x99, 0x99, 0x3E}, /* Brown */ {4, 0x3E, 0x3E, 0x99}, /* Blue */ {5, 0x99, 0x3E, 0x99}, /* Magenta */ {6, 0x3E, 0x99, 0x99}, /* Cyan */ {7, 0x99, 0x99, 0x99}, /* White */ /* Intense colors */ {8, 0x3E, 0x3E, 0x3E}, /* Black */ {9, 0xFF, 0x67, 0x67}, /* Red */ {10, 0x67, 0xFF, 0x67}, /* Green */ {11, 0xFF, 0xFF, 0x67}, /* Brown */ {12, 0x67, 0x67, 0xFF}, /* Blue */ {13, 0xFF, 0x67, 0xFF}, /* Magenta */ {14, 0x67, 0xFF, 0xFF}, /* Cyan */ {15, 0xFF, 0xFF, 0xFF}, /* White */ /* Remainder of xterm's 256-color palette */ {16, 0x00, 0x00, 0x00}, {17, 0x00, 0x00, 0x5F}, {18, 0x00, 0x00, 0x87}, {19, 0x00, 0x00, 0xAF}, {20, 0x00, 0x00, 0xD7}, {21, 0x00, 0x00, 0xFF}, {22, 0x00, 0x5F, 0x00}, {23, 0x00, 0x5F, 0x5F}, {24, 0x00, 0x5F, 0x87}, {25, 0x00, 0x5F, 0xAF}, {26, 0x00, 0x5F, 0xD7}, {27, 0x00, 0x5F, 0xFF}, {28, 0x00, 0x87, 0x00}, {29, 0x00, 0x87, 0x5F}, {30, 0x00, 0x87, 0x87}, {31, 0x00, 0x87, 0xAF}, {32, 0x00, 0x87, 0xD7}, {33, 0x00, 0x87, 0xFF}, {34, 0x00, 0xAF, 0x00}, {35, 0x00, 0xAF, 0x5F}, {36, 0x00, 0xAF, 0x87}, {37, 0x00, 0xAF, 0xAF}, {38, 0x00, 0xAF, 0xD7}, {39, 0x00, 0xAF, 0xFF}, {40, 0x00, 0xD7, 0x00}, {41, 0x00, 0xD7, 0x5F}, {42, 0x00, 0xD7, 0x87}, {43, 0x00, 0xD7, 0xAF}, {44, 0x00, 0xD7, 0xD7}, {45, 0x00, 0xD7, 0xFF}, {46, 0x00, 0xFF, 0x00}, {47, 0x00, 0xFF, 0x5F}, {48, 0x00, 0xFF, 0x87}, {49, 0x00, 0xFF, 0xAF}, {50, 0x00, 0xFF, 0xD7}, {51, 0x00, 0xFF, 0xFF}, {52, 0x5F, 0x00, 0x00}, {53, 0x5F, 0x00, 0x5F}, {54, 0x5F, 0x00, 0x87}, {55, 0x5F, 0x00, 0xAF}, {56, 0x5F, 0x00, 0xD7}, {57, 0x5F, 0x00, 0xFF}, {58, 0x5F, 0x5F, 0x00}, {59, 0x5F, 0x5F, 0x5F}, {60, 0x5F, 0x5F, 0x87}, {61, 0x5F, 0x5F, 0xAF}, {62, 0x5F, 0x5F, 0xD7}, {63, 0x5F, 0x5F, 0xFF}, {64, 0x5F, 0x87, 0x00}, {65, 0x5F, 0x87, 0x5F}, {66, 0x5F, 0x87, 0x87}, {67, 0x5F, 0x87, 0xAF}, {68, 0x5F, 0x87, 0xD7}, {69, 0x5F, 0x87, 0xFF}, {70, 0x5F, 0xAF, 0x00}, {71, 0x5F, 0xAF, 0x5F}, {72, 0x5F, 0xAF, 0x87}, {73, 0x5F, 0xAF, 0xAF}, {74, 0x5F, 0xAF, 0xD7}, {75, 0x5F, 0xAF, 0xFF}, {76, 0x5F, 0xD7, 0x00}, {77, 0x5F, 0xD7, 0x5F}, {78, 0x5F, 0xD7, 0x87}, {79, 0x5F, 0xD7, 0xAF}, {80, 0x5F, 0xD7, 0xD7}, {81, 0x5F, 0xD7, 0xFF}, {82, 0x5F, 0xFF, 0x00}, {83, 0x5F, 0xFF, 0x5F}, {84, 0x5F, 0xFF, 0x87}, {85, 0x5F, 0xFF, 0xAF}, {86, 0x5F, 0xFF, 0xD7}, {87, 0x5F, 0xFF, 0xFF}, {88, 0x87, 0x00, 0x00}, {89, 0x87, 0x00, 0x5F}, {90, 0x87, 0x00, 0x87}, {91, 0x87, 0x00, 0xAF}, {92, 0x87, 0x00, 0xD7}, {93, 0x87, 0x00, 0xFF}, {94, 0x87, 0x5F, 0x00}, {95, 0x87, 0x5F, 0x5F}, {96, 0x87, 0x5F, 0x87}, {97, 0x87, 0x5F, 0xAF}, {98, 0x87, 0x5F, 0xD7}, {99, 0x87, 0x5F, 0xFF}, {100, 0x87, 0x87, 0x00}, {101, 0x87, 0x87, 0x5F}, {102, 0x87, 0x87, 0x87}, {103, 0x87, 0x87, 0xAF}, {104, 0x87, 0x87, 0xD7}, {105, 0x87, 0x87, 0xFF}, {106, 0x87, 0xAF, 0x00}, {107, 0x87, 0xAF, 0x5F}, {108, 0x87, 0xAF, 0x87}, {109, 0x87, 0xAF, 0xAF}, {110, 0x87, 0xAF, 0xD7}, {111, 0x87, 0xAF, 0xFF}, {112, 0x87, 0xD7, 0x00}, {113, 0x87, 0xD7, 0x5F}, {114, 0x87, 0xD7, 0x87}, {115, 0x87, 0xD7, 0xAF}, {116, 0x87, 0xD7, 0xD7}, {117, 0x87, 0xD7, 0xFF}, {118, 0x87, 0xFF, 0x00}, {119, 0x87, 0xFF, 0x5F}, {120, 0x87, 0xFF, 0x87}, {121, 0x87, 0xFF, 0xAF}, {122, 0x87, 0xFF, 0xD7}, {123, 0x87, 0xFF, 0xFF}, {124, 0xAF, 0x00, 0x00}, {125, 0xAF, 0x00, 0x5F}, {126, 0xAF, 0x00, 0x87}, {127, 0xAF, 0x00, 0xAF}, {128, 0xAF, 0x00, 0xD7}, {129, 0xAF, 0x00, 0xFF}, {130, 0xAF, 0x5F, 0x00}, {131, 0xAF, 0x5F, 0x5F}, {132, 0xAF, 0x5F, 0x87}, {133, 0xAF, 0x5F, 0xAF}, {134, 0xAF, 0x5F, 0xD7}, {135, 0xAF, 0x5F, 0xFF}, {136, 0xAF, 0x87, 0x00}, {137, 0xAF, 0x87, 0x5F}, {138, 0xAF, 0x87, 0x87}, {139, 0xAF, 0x87, 0xAF}, {140, 0xAF, 0x87, 0xD7}, {141, 0xAF, 0x87, 0xFF}, {142, 0xAF, 0xAF, 0x00}, {143, 0xAF, 0xAF, 0x5F}, {144, 0xAF, 0xAF, 0x87}, {145, 0xAF, 0xAF, 0xAF}, {146, 0xAF, 0xAF, 0xD7}, {147, 0xAF, 0xAF, 0xFF}, {148, 0xAF, 0xD7, 0x00}, {149, 0xAF, 0xD7, 0x5F}, {150, 0xAF, 0xD7, 0x87}, {151, 0xAF, 0xD7, 0xAF}, {152, 0xAF, 0xD7, 0xD7}, {153, 0xAF, 0xD7, 0xFF}, {154, 0xAF, 0xFF, 0x00}, {155, 0xAF, 0xFF, 0x5F}, {156, 0xAF, 0xFF, 0x87}, {157, 0xAF, 0xFF, 0xAF}, {158, 0xAF, 0xFF, 0xD7}, {159, 0xAF, 0xFF, 0xFF}, {160, 0xD7, 0x00, 0x00}, {161, 0xD7, 0x00, 0x5F}, {162, 0xD7, 0x00, 0x87}, {163, 0xD7, 0x00, 0xAF}, {164, 0xD7, 0x00, 0xD7}, {165, 0xD7, 0x00, 0xFF}, {166, 0xD7, 0x5F, 0x00}, {167, 0xD7, 0x5F, 0x5F}, {168, 0xD7, 0x5F, 0x87}, {169, 0xD7, 0x5F, 0xAF}, {170, 0xD7, 0x5F, 0xD7}, {171, 0xD7, 0x5F, 0xFF}, {172, 0xD7, 0x87, 0x00}, {173, 0xD7, 0x87, 0x5F}, {174, 0xD7, 0x87, 0x87}, {175, 0xD7, 0x87, 0xAF}, {176, 0xD7, 0x87, 0xD7}, {177, 0xD7, 0x87, 0xFF}, {178, 0xD7, 0xAF, 0x00}, {179, 0xD7, 0xAF, 0x5F}, {180, 0xD7, 0xAF, 0x87}, {181, 0xD7, 0xAF, 0xAF}, {182, 0xD7, 0xAF, 0xD7}, {183, 0xD7, 0xAF, 0xFF}, {184, 0xD7, 0xD7, 0x00}, {185, 0xD7, 0xD7, 0x5F}, {186, 0xD7, 0xD7, 0x87}, {187, 0xD7, 0xD7, 0xAF}, {188, 0xD7, 0xD7, 0xD7}, {189, 0xD7, 0xD7, 0xFF}, {190, 0xD7, 0xFF, 0x00}, {191, 0xD7, 0xFF, 0x5F}, {192, 0xD7, 0xFF, 0x87}, {193, 0xD7, 0xFF, 0xAF}, {194, 0xD7, 0xFF, 0xD7}, {195, 0xD7, 0xFF, 0xFF}, {196, 0xFF, 0x00, 0x00}, {197, 0xFF, 0x00, 0x5F}, {198, 0xFF, 0x00, 0x87}, {199, 0xFF, 0x00, 0xAF}, {200, 0xFF, 0x00, 0xD7}, {201, 0xFF, 0x00, 0xFF}, {202, 0xFF, 0x5F, 0x00}, {203, 0xFF, 0x5F, 0x5F}, {204, 0xFF, 0x5F, 0x87}, {205, 0xFF, 0x5F, 0xAF}, {206, 0xFF, 0x5F, 0xD7}, {207, 0xFF, 0x5F, 0xFF}, {208, 0xFF, 0x87, 0x00}, {209, 0xFF, 0x87, 0x5F}, {210, 0xFF, 0x87, 0x87}, {211, 0xFF, 0x87, 0xAF}, {212, 0xFF, 0x87, 0xD7}, {213, 0xFF, 0x87, 0xFF}, {214, 0xFF, 0xAF, 0x00}, {215, 0xFF, 0xAF, 0x5F}, {216, 0xFF, 0xAF, 0x87}, {217, 0xFF, 0xAF, 0xAF}, {218, 0xFF, 0xAF, 0xD7}, {219, 0xFF, 0xAF, 0xFF}, {220, 0xFF, 0xD7, 0x00}, {221, 0xFF, 0xD7, 0x5F}, {222, 0xFF, 0xD7, 0x87}, {223, 0xFF, 0xD7, 0xAF}, {224, 0xFF, 0xD7, 0xD7}, {225, 0xFF, 0xD7, 0xFF}, {226, 0xFF, 0xFF, 0x00}, {227, 0xFF, 0xFF, 0x5F}, {228, 0xFF, 0xFF, 0x87}, {229, 0xFF, 0xFF, 0xAF}, {230, 0xFF, 0xFF, 0xD7}, {231, 0xFF, 0xFF, 0xFF}, {232, 0x08, 0x08, 0x08}, {233, 0x12, 0x12, 0x12}, {234, 0x1C, 0x1C, 0x1C}, {235, 0x26, 0x26, 0x26}, {236, 0x30, 0x30, 0x30}, {237, 0x3A, 0x3A, 0x3A}, {238, 0x44, 0x44, 0x44}, {239, 0x4E, 0x4E, 0x4E}, {240, 0x58, 0x58, 0x58}, {241, 0x62, 0x62, 0x62}, {242, 0x6C, 0x6C, 0x6C}, {243, 0x76, 0x76, 0x76}, {244, 0x80, 0x80, 0x80}, {245, 0x8A, 0x8A, 0x8A}, {246, 0x94, 0x94, 0x94}, {247, 0x9E, 0x9E, 0x9E}, {248, 0xA8, 0xA8, 0xA8}, {249, 0xB2, 0xB2, 0xB2}, {250, 0xBC, 0xBC, 0xBC}, {251, 0xC6, 0xC6, 0xC6}, {252, 0xD0, 0xD0, 0xD0}, {253, 0xDA, 0xDA, 0xDA}, {254, 0xE4, 0xE4, 0xE4}, {255, 0xEE, 0xEE, 0xEE} }; int guac_terminal_colorcmp(const guac_terminal_color* a, const guac_terminal_color* b) { /* Compare palette index alone if not unknown */ if (a->palette_index != -1 && b->palette_index != -1) return a->palette_index - b->palette_index; /* Consider red component highest order ... */ if (a->red != b->red) return a->red - b->red; /* ... followed by green ... */ if (a->green != b->green) return a->green - b->green; /* ... followed by blue */ if (a->blue != b->blue) return a->blue - b->blue; /* If all components match, colors are equal */ return 0; } guacamole-server-1.3.0/src/terminal/typescript.c0000644000175100001440000001665613702142276016670 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/io.h" #include "terminal/typescript.h" #include #include #include #include #include #include #include #include /** * Attempts to open a new typescript data file within the given path and having * the given name. If such a file already exists, sequential numeric suffixes * (.1, .2, .3, etc.) are appended until a filename is found which does not * exist (or until the maximum number of numeric suffixes has been tried). If * the file absolutely cannot be opened due to an error, -1 is returned and * errno is set appropriately. * * @param path * The full path to the directory in which the data file should be created. * * @param name * The name of the data file which should be crated within the given path. * * @param basename * A buffer in which the path, a path separator, the filename, any * necessary suffix, and a NULL terminator will be stored. If insufficient * space is available, -1 will be returned, and errno will be set to * ENAMETOOLONG. * * @param basename_size * The number of bytes available within the provided basename buffer. * * @return * The file descriptor of the open data file if open succeeded, or -1 on * failure. */ static int guac_terminal_typescript_open_data_file(const char* path, const char* name, char* basename, int basename_size) { int i; /* Concatenate path and name (separated by a single slash) */ int basename_length = snprintf(basename, basename_size - GUAC_TERMINAL_TYPESCRIPT_MAX_SUFFIX_LENGTH, "%s/%s", path, name); /* Abort if maximum length reached */ if (basename_length == basename_size - GUAC_TERMINAL_TYPESCRIPT_MAX_SUFFIX_LENGTH) { errno = ENAMETOOLONG; return -1; } /* Attempt to open typescript data file */ int data_fd = open(basename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); /* Continuously retry with alternate names on failure */ if (data_fd == -1) { /* Prepare basename for additional suffix */ basename[basename_length] = '.'; char* suffix = &(basename[basename_length + 1]); /* Continue retrying alternative suffixes if file already exists */ for (i = 1; data_fd == -1 && errno == EEXIST && i <= GUAC_TERMINAL_TYPESCRIPT_MAX_SUFFIX; i++) { /* Append new suffix */ sprintf(suffix, "%i", i); /* Retry with newly-suffixed filename */ data_fd = open(basename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); } } return data_fd; } guac_terminal_typescript* guac_terminal_typescript_alloc(const char* path, const char* name, int create_path) { /* Create path if it does not exist, fail if impossible */ if (create_path && mkdir(path, S_IRWXU) && errno != EEXIST) return NULL; /* Allocate space for new typescript */ guac_terminal_typescript* typescript = malloc(sizeof(guac_terminal_typescript)); /* Attempt to open typescript data file */ typescript->data_fd = guac_terminal_typescript_open_data_file( path, name, typescript->data_filename, sizeof(typescript->data_filename) - sizeof(GUAC_TERMINAL_TYPESCRIPT_TIMING_SUFFIX)); if (typescript->data_fd == -1) { free(typescript); return NULL; } /* Append suffix to basename */ if (snprintf(typescript->timing_filename, sizeof(typescript->timing_filename), "%s.%s", typescript->data_filename, GUAC_TERMINAL_TYPESCRIPT_TIMING_SUFFIX) >= sizeof(typescript->timing_filename)) { close(typescript->data_fd); free(typescript); return NULL; } /* Attempt to open typescript timing file */ typescript->timing_fd = open(typescript->timing_filename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); if (typescript->timing_fd == -1) { close(typescript->data_fd); free(typescript); return NULL; } /* Typescript starts out flushed */ typescript->length = 0; typescript->last_flush = guac_timestamp_current(); /* Write header */ guac_common_write(typescript->data_fd, GUAC_TERMINAL_TYPESCRIPT_HEADER, sizeof(GUAC_TERMINAL_TYPESCRIPT_HEADER) - 1); return typescript; } void guac_terminal_typescript_write(guac_terminal_typescript* typescript, char c) { /* Flush buffer if no space is available */ if (typescript->length == sizeof(typescript->buffer)) guac_terminal_typescript_flush(typescript); /* Append single byte to buffer */ typescript->buffer[typescript->length++] = c; } void guac_terminal_typescript_flush(guac_terminal_typescript* typescript) { /* Do nothing if nothing to flush */ if (typescript->length == 0) return; /* Get timestamps of previous and current flush */ guac_timestamp this_flush = guac_timestamp_current(); guac_timestamp last_flush = typescript->last_flush; /* Calculate time since last flush */ int elapsed_time = this_flush - last_flush; if (elapsed_time > GUAC_TERMINAL_TYPESCRIPT_MAX_DELAY) elapsed_time = GUAC_TERMINAL_TYPESCRIPT_MAX_DELAY; /* Produce single line of timestamp output */ char timestamp_buffer[32]; int timestamp_length = snprintf(timestamp_buffer, sizeof(timestamp_buffer), "%0.6f %i\n", elapsed_time / 1000.0, typescript->length); /* Calculate actual length of timestamp line */ if (timestamp_length > sizeof(timestamp_buffer)) timestamp_length = sizeof(timestamp_buffer); /* Write timestamp to timing file */ guac_common_write(typescript->timing_fd, timestamp_buffer, timestamp_length); /* Empty buffer into data file */ guac_common_write(typescript->data_fd, typescript->buffer, typescript->length); /* Buffer is now flushed */ typescript->length = 0; typescript->last_flush = this_flush; } void guac_terminal_typescript_free(guac_terminal_typescript* typescript) { /* Do nothing if no typescript provided */ if (typescript == NULL) return; /* Flush any pending data */ guac_terminal_typescript_flush(typescript); /* Write footer */ guac_common_write(typescript->data_fd, GUAC_TERMINAL_TYPESCRIPT_FOOTER, sizeof(GUAC_TERMINAL_TYPESCRIPT_FOOTER) - 1); /* Close file descriptors */ close(typescript->data_fd); close(typescript->timing_fd); /* Free allocated typescript data */ free(typescript); } guacamole-server-1.3.0/src/terminal/terminal/0000755000175100001440000000000013772471156016204 500000000000000guacamole-server-1.3.0/src/terminal/terminal/select.h0000644000175100001440000001545313702142276017553 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TERMINAL_SELECT_H #define GUAC_TERMINAL_SELECT_H #include "config.h" #include "terminal.h" #include /** * Forwards the visible portion of the text selection rectangle to the * underlying terminal display, requesting that it be redrawn. If no * visible change would result from redrawing the selection rectangle, * this function may have no effect. * * @param terminal * The guac_terminal whose text selection rectangle should be * redrawn. */ void guac_terminal_select_redraw(guac_terminal* terminal); /** * Marks the start of text selection at the given row and column. Any existing * selection is cleared. This function should only be invoked while the * guac_terminal is locked through a call to guac_terminal_lock(). * * @param terminal * The guac_terminal instance associated with the text being selected. * * @param row * The row number of the character at the start of the text selection, * where the first (top-most) row in the terminal is row 0. Rows within * the scrollback buffer (above the top-most row of the terminal) will be * negative. * * @param column * The column number of the character at the start of the text selection, * where the first (left-most) column in the terminal is column 0. */ void guac_terminal_select_start(guac_terminal* terminal, int row, int column); /** * Updates the end of text selection at the given row and column. This function * should only be invoked while the guac_terminal is locked through a call to * guac_terminal_lock(). * * @param terminal * The guac_terminal instance associated with the text being selected. * * @param row * The row number of the character at the current end of the text * selection, where the first (top-most) row in the terminal is row 0. Rows * within the scrollback buffer (above the top-most row of the terminal) * will be negative. * * @param column * The column number of the character at the current end of the text * selection, where the first (left-most) column in the terminal is * column 0. */ void guac_terminal_select_update(guac_terminal* terminal, int row, int column); /** * Resumes selecting text, expanding the existing selected region from the * closest end to additionally contain the given character. This function * should only be invoked while the guac_terminal is locked through a call to * guac_terminal_lock(). * * @param terminal * The guac_terminal instance associated with the text being selected. * * @param row * The row number of the character to include within the text selection, * where the first (top-most) row in the terminal is row 0. Rows within the * scrollback buffer (above the top-most row of the terminal) will be * negative. * * @param column * The column number of the character to include within the text selection, * where the first (left-most) column in the terminal is column 0. */ void guac_terminal_select_resume(guac_terminal* terminal, int row, int column); /** * Ends text selection, removing any highlight and storing the selected * character data within the clipboard associated with the given terminal. If * more text is selected than can fit within the clipboard, text at the end of * the selected area will be dropped as necessary. This function should only be * invoked while the guac_terminal is locked through a call to * guac_terminal_lock(). * * @param terminal * The guac_terminal instance associated with the text being selected. */ void guac_terminal_select_end(guac_terminal* terminal); /** * Returns whether at least one character within the given range is currently * selected. * * @param terminal * The guac_terminal instance associated with the text being selected. * * @param start_row * The first row of the region to test, inclusive, where the first * (top-most) row in the terminal is row 0. Rows within the scrollback * buffer (above the top-most row of the terminal) will be negative. * * @param start_column * The first column of the region to test, inclusive, where the first * (left-most) column in the terminal is column 0. * * @param end_row * The last row of the region to test, inclusive, where the first * (top-most) row in the terminal is row 0. Rows within the scrollback * buffer (above the top-most row of the terminal) will be negative. * * @param end_column * The last column of the region to test, inclusive, where the first * (left-most) column in the terminal is column 0. * * @return * true if at least one character within the given range is currently * selected, false otherwise. */ bool guac_terminal_select_contains(guac_terminal* terminal, int start_row, int start_column, int end_row, int end_column); /** * Clears the current selection if it contains at least one character within * the given region. If no text is currently selected, the selection has not * yet been committed, or the region does not contain at least one selected * character, this function has no effect. * * @param terminal * The guac_terminal instance associated with the text being selected. * * @param start_row * The first row of the region, inclusive, where the first (top-most) row * in the terminal is row 0. Rows within the scrollback buffer (above the * top-most row of the terminal) will be negative. * * @param start_column * The first column of the region, inclusive, where the first (left-most) * column in the terminal is column 0. * * @param end_row * The last row of the region, inclusive, where the first (top-most) row in * the terminal is row 0. Rows within the scrollback buffer (above the * top-most row of the terminal) will be negative. * * @param end_column * The last column of the region, inclusive, where the first (left-most) * column in the terminal is column 0. */ void guac_terminal_select_touch(guac_terminal* terminal, int start_row, int start_column, int end_row, int end_column); #endif guacamole-server-1.3.0/src/terminal/terminal/terminal_handlers.h0000644000175100001440000001546613702142276021773 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_TERMINAL_HANDLERS #define _GUAC_TERMINAL_HANDLERS #include "config.h" #include "terminal.h" /** * The default mode of the terminal. This character handler simply echoes * received characters to the terminal display, entering other terminal modes * if control characters are received. * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_echo(guac_terminal* term, unsigned char c); /** * Handles any characters which follow an ANSI ESC (0x1B) character. * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_escape(guac_terminal* term, unsigned char c); /** * Selects the G0 character mapping from the provided character mapping * specifier (such as B, 0, U, or K). * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_g0_charset(guac_terminal* term, unsigned char c); /** * Selects the G1 character mapping from the provided character mapping * specifier (such as B, 0, U, or K). * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_g1_charset(guac_terminal* term, unsigned char c); /** * Handles characters within a CSI sequence. CSI sequences are most often * introduced with "ESC [". * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_csi(guac_terminal* term, unsigned char c); /** * Parses the remainder of the download initiation OSC specific to the * Guacamole terminal emulator. A download will be initiated for the specified * file once the OSC sequence is complete. * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_download(guac_terminal* term, unsigned char c); /** * Parses the remainder of the set directory OSC specific to the Guacamole * terminal emulator. The upload directory will be set to the specified path * once the OSC sequence is complete. * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_set_directory(guac_terminal* term, unsigned char c); /** * Parses the remainder of the open pipe OSC specific to the * Guacamole terminal emulator. Terminal output will be redirected to a new * named pipe having the given name once the OSC sequence is complete. * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_open_pipe_stream(guac_terminal* term, unsigned char c); /** * Parses the remainder of the close pipe OSC specific to the Guacamole * terminal emulator. Terminal output will be redirected back to the terminal * display and any open named pipe will be closed once the OSC sequence is * complete. * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_close_pipe_stream(guac_terminal* term, unsigned char c); /** * Parses the remainder of the OSC sequence specific to the Guacamole terminal * emulator which requests that the scrollback buffer size be set to the given * number of rows. The desired scrollback buffer size will immediately be set, * however the manner in which that size is applied (or whether the size is * applied at all) depends on (1) whether the requested size exceeds the * maximum size set when the terminal emulator was created and (2) whether the * size does not reduce the scrollback below the number of rows required for * the current display. * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_set_scrollback(guac_terminal* term, unsigned char c); /** * Parses the remainder of an OSC sequence setting the window title. The * window title is everything after the window title sequence begins, up to * the end of the OSC sequence itself. * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_window_title(guac_terminal* term, unsigned char c); /** * Parses the remainder of xterm's OSC sequence for redefining the terminal * emulator's palette. * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_xterm_palette(guac_terminal* term, unsigned char c); /** * Handles the remaining characters of an Operating System Code (OSC) sequence, * typically initiated with "ESC ]". * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_osc(guac_terminal* term, unsigned char c); /** * Handles terminal control function sequences initiated with "ESC #". * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_ctrl_func(guac_terminal* term, unsigned char c); /** * Handles terminal control function sequences initiated with "ESC _". * * @param term * The terminal that received the given character of data. * * @param c * The character that was received by the given terminal. */ int guac_terminal_apc(guac_terminal* term, unsigned char c); #endif guacamole-server-1.3.0/src/terminal/terminal/named-colors.h0000644000175100001440000000305313676434704020662 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TERMINAL_NAMED_COLORS_H #define GUAC_TERMINAL_NAMED_COLORS_H #include "config.h" #include "terminal/palette.h" /** * Searches for the color having the given name, storing that color within the * given guac_terminal_color structure if found. If the color cannot be found, * the guac_terminal_color structure is not touched. All color names supported * by xterm are recognized by this function. * * @param name * The name of the color to search for. * * @param color * A pointer to the guac_terminal_color structure in which the found color * should be stored. * * @returns * Zero if the color was successfully found, non-zero otherwise. */ int guac_terminal_find_color(const char* name, guac_terminal_color* color); #endif guacamole-server-1.3.0/src/terminal/terminal/xparsecolor.h0000644000175100001440000000306213676434704020640 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TERMINAL_XPARSECOLOR_H #define GUAC_TERMINAL_XPARSECOLOR_H #include "config.h" #include "terminal/palette.h" /** * Parses an X11 color spec, as defined by Xlib's XParseColor(), storing the * result in the provided guac_terminal_color structure. If the color spec is * not valid, the provided guac_terminal_color is not touched. * * Currently, only the "rgb:*" format color specs are supported. * * @param spec * The X11 color spec to parse. * * @param color * A pointer to the guac_terminal_color structure which should receive the * parsed result. * * @returns * Zero if the color spec was successfully parsed, non-zero otherwise. */ int guac_terminal_xparsecolor(const char* spec, guac_terminal_color* color); #endif guacamole-server-1.3.0/src/terminal/terminal/color-scheme.h0000644000175100001440000000610013764613616020652 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TERMINAL_COLOR_SCHEME_H #define GUAC_TERMINAL_COLOR_SCHEME_H #include "config.h" #include "terminal/palette.h" #include #include #include /** * The name of the color scheme having black foreground and white background. */ #define GUAC_TERMINAL_SCHEME_BLACK_WHITE "black-white" /** * The name of the color scheme having gray foreground and black background. */ #define GUAC_TERMINAL_SCHEME_GRAY_BLACK "gray-black" /** * The name of the color scheme having green foreground and black background. */ #define GUAC_TERMINAL_SCHEME_GREEN_BLACK "green-black" /** * The name of the color scheme having white foreground and black background. */ #define GUAC_TERMINAL_SCHEME_WHITE_BLACK "white-black" /** * Color name representing the foreground color. */ #define GUAC_TERMINAL_SCHEME_FOREGROUND "foreground" /** * Color name representing the background color. */ #define GUAC_TERMINAL_SCHEME_BACKGROUND "background" /** * Color name representing a numbered color. */ #define GUAC_TERMINAL_SCHEME_NUMBERED "color" /** * Parse a color-scheme configuration string, and return specified * foreground/background colors and color palette. * * @param client * The client that the terminal is connected to. * * @param color_scheme * The name of a pre-defined color scheme (one of the * names defined by the GUAC_TERMINAL_SCHEME_* constants), or * semicolon-separated list of name-value pairs, i.e. ": [; * : [; ...]]". For example, "color2: rgb:cc/33/22; * background: color5". * * If blank, the default scheme of GUAC_TERMINAL_SCHEME_GRAY_BLACK will be * used. If invalid, a warning will be logged, and * GUAC_TERMINAL_SCHEME_GRAY_BLACK will be used. * * @param[out] foreground * Parsed foreground color. * * @param[out] background * Parsed background color. * * @param[in,out] palette * Parsed color palette. The caller is responsible for allocating a mutable * array on entry. On return, the array contains the parsed palette. */ void guac_terminal_parse_color_scheme(guac_client* client, const char* color_scheme, guac_terminal_color* foreground, guac_terminal_color* background, guac_terminal_color (*palette)[256]); #endif guacamole-server-1.3.0/src/terminal/terminal/common.h0000644000175100001440000000312413613156714017557 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_TERMINAL_COMMON_H #define _GUAC_TERMINAL_COMMON_H #include "config.h" #include "types.h" #include /** * Returns the closest value to the value given that is also * within the given range. */ int guac_terminal_fit_to_range(int value, int min, int max); /** * Encodes the given codepoint as UTF-8, storing the result within the * provided buffer, and returning the number of bytes stored. */ int guac_terminal_encode_utf8(int codepoint, char* utf8); /** * Returns whether a codepoint has a corresponding glyph, or is rendered * as a blank space. */ bool guac_terminal_has_glyph(int codepoint); /** * Similar to write, but automatically retries the write operation until * an error occurs. */ int guac_terminal_write_all(int fd, const char* buffer, int size); #endif guacamole-server-1.3.0/src/terminal/terminal/palette.h0000644000175100001440000001270413702142276017726 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TERMINAL_PALETTE_H #define GUAC_TERMINAL_PALETTE_H #include "config.h" #include /** * The pseudo-index of the color set as the the default foreground color for * the terminal. Regardless of what changes are made to the palette, this index * will always return the current default foreground color. */ #define GUAC_TERMINAL_COLOR_FOREGROUND -2 /** * The pseudo-index of the color set as the the default background color for * the terminal. Regardless of what changes are made to the palette, this index * will always return the current default background color. */ #define GUAC_TERMINAL_COLOR_BACKGROUND -3 /** * The index of black within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_BLACK 0 /** * The index of low-intensity red within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_DARK_RED 1 /** * The index of low-intensity green within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_DARK_GREEN 2 /** * The index of brown within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_BROWN 3 /** * The index of low-intensity blue within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_DARK_BLUE 4 /** * The index of low-intensity magenta (purple) within the terminal color * palette. */ #define GUAC_TERMINAL_COLOR_PURPLE 5 /** * The index of low-intensity cyan (teal) within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_TEAL 6 /** * The index of low-intensity white (gray) within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_GRAY 7 /** * The index of bright black (dark gray) within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_DARK_GRAY 8 /** * The index of bright red within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_RED 9 /** * The index of bright green within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_GREEN 10 /** * The index of bright brown (yellow) within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_YELLOW 11 /** * The index of bright blue within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_BLUE 12 /** * The index of bright magenta within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_MAGENTA 13 /** * The index of bright cyan within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_CYAN 14 /** * The index of bright white within the terminal color palette. */ #define GUAC_TERMINAL_COLOR_WHITE 15 /** * The index of the first low-intensity color in the 16-color portion of the * palette. */ #define GUAC_TERMINAL_FIRST_DARK 0 /** * The index of the last low-intensity color in the 16-color portion of the * palette. */ #define GUAC_TERMINAL_LAST_DARK 7 /** * The index of the first high-intensity color in the 16-color portion of the * palette. */ #define GUAC_TERMINAL_FIRST_INTENSE 8 /** * The index of the last high-intensity color in the 16-color portion of the * palette. */ #define GUAC_TERMINAL_LAST_INTENSE 15 /** * The distance between the palette indices of the dark colors (0 through 7) * and the bright colors (8 - 15) in the 16-color portion of the palette. */ #define GUAC_TERMINAL_INTENSE_OFFSET 8 /** * An RGB color, where each component ranges from 0 to 255. */ typedef struct guac_terminal_color { /** * The index of this color within the terminal palette, or -1 if the color * does not exist within the terminal palette. */ int palette_index; /** * The red component of this color. */ uint8_t red; /** * The green component of this color. */ uint8_t green; /** * The blue component of this color. */ uint8_t blue; } guac_terminal_color; /** * Compares two colors, returning a negative value if the first color is less * than the second, a positive value if the first color is greater than the * second, and zero if the colors are identical. Only the color components are * compared (not the palette index). The red component is considered the * highest order component, followed by green, followed by blue. * * @param a * The first color to compare. * * @param b * The second color to compare. * * @return * A negative value if the first color is less than the second, a positive * value if the first color is greater than the second, and zero if the * colors are identical. */ int guac_terminal_colorcmp(const guac_terminal_color* a, const guac_terminal_color* b); /** * The initial state of the terminal color palette. The color palette used by * the terminal may modified after the terminal is created through console * codes. */ extern const guac_terminal_color GUAC_TERMINAL_INITIAL_PALETTE[256]; #endif guacamole-server-1.3.0/src/terminal/terminal/terminal.h0000644000175100001440000011155613764613616020121 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_TERMINAL_H #define _GUAC_TERMINAL_H #include "config.h" #include "buffer.h" #include "common/clipboard.h" #include "common/cursor.h" #include "display.h" #include "scrollbar.h" #include "types.h" #include "typescript.h" #include #include #include #include /** * The absolute maximum number of rows to allow within the display. */ #define GUAC_TERMINAL_MAX_ROWS 1024 /** * The absolute maximum number of columns to allow within the display. This * implicitly limits the number of columns allowed within the buffer. */ #define GUAC_TERMINAL_MAX_COLUMNS 1024 /** * The maximum duration of a single frame, in milliseconds. */ #define GUAC_TERMINAL_FRAME_DURATION 40 /** * The maximum amount of time to wait for more data before declaring a frame * complete, in milliseconds. */ #define GUAC_TERMINAL_FRAME_TIMEOUT 10 /** * The maximum number of custom tab stops. */ #define GUAC_TERMINAL_MAX_TABS 16 /** * The number of rows to scroll per scroll wheel event. */ #define GUAC_TERMINAL_WHEEL_SCROLL_AMOUNT 3 /** * Flag which specifies that terminal output should be sent to both the current * pipe stream and the user's display. By default, terminal output will be sent * only to the open pipe. */ #define GUAC_TERMINAL_PIPE_INTERPRET_OUTPUT 1 /** * Flag which forces the open pipe stream to be flushed automatically, whenever * a new frame would be rendered, with only minimal buffering performed between * frames. By default, the contents of the pipe stream will be flushed only * when the buffer is full or the pipe stream is being closed. */ #define GUAC_TERMINAL_PIPE_AUTOFLUSH 2 typedef struct guac_terminal guac_terminal; /** * All possible mouse cursors used by the terminal emulator. */ typedef enum guac_terminal_cursor_type { /** * A transparent (blank) cursor. */ GUAC_TERMINAL_CURSOR_BLANK, /** * A standard I-bar cursor for selecting text, etc. */ GUAC_TERMINAL_CURSOR_IBAR, /** * A standard triangular mouse pointer for manipulating non-text objects. */ GUAC_TERMINAL_CURSOR_POINTER } guac_terminal_cursor_type; /** * Handler for characters printed to the terminal. When a character is printed, * the current char handler for the terminal is called and given that * character. */ typedef int guac_terminal_char_handler(guac_terminal* term, unsigned char c); /** * Handler for setting the destination path for file uploads. */ typedef void guac_terminal_upload_path_handler(guac_client* client, char* path); /** * Handler for creating an outbound file download stream for a specified file. */ typedef guac_stream* guac_terminal_file_download_handler(guac_client* client, char* filename); /** * Represents a terminal emulator which uses a given Guacamole client to * render itself. */ struct guac_terminal { /** * The Guacamole client associated with this terminal emulator. */ guac_client* client; /** * Whether user input should be handled and this terminal should render * frames. Initially, this will be false, user input will be ignored, and * rendering of frames will be withheld until guac_terminal_start() has * been invoked. The data within frames will still be rendered, and text * data received will still be handled, however actual frame boundaries * will not be sent. */ bool started; /** * The terminal render thread. */ pthread_t thread; /** * Called whenever the necessary terminal codes are sent to change * the path for future file uploads. */ guac_terminal_upload_path_handler* upload_path_handler; /** * Called whenever the necessary terminal codes are sent to initiate * a download of a given remote file. */ guac_terminal_file_download_handler* file_download_handler; /** * Lock which restricts simultaneous access to this terminal via the root * guac_terminal_* functions. */ pthread_mutex_t lock; /** * The mutex associated with the modified condition and flag, locked * whenever a thread is waiting on the modified condition, the modified * condition is being signalled, or the modified flag is being changed. */ pthread_mutex_t modified_lock; /** * Flag set whenever an operation has affected the terminal in a way that * will require a frame flush. When this flag is set, the modified_cond * condition will be signalled. The modified_lock will always be * acquired before this flag is altered. */ int modified; /** * Condition which is signalled when the modified flag has been set */ pthread_cond_t modified_cond; /** * Pipe which will be the source of user input. When a terminal code * generates synthesized user input, that data will be written to * this pipe. */ int stdin_pipe_fd[2]; /** * The currently-open pipe stream from which all terminal input should be * read, if any. If no pipe stream is open, terminal input will be received * through keyboard, clipboard, and mouse events, and this value will be * NULL. */ guac_stream* input_stream; /** * The currently-open pipe stream to which all terminal output should be * written, if any. If no pipe stream is open, terminal output will be * written to the terminal display, and this value will be NULL. */ guac_stream* pipe_stream; /** * Bitwise OR of all flags which apply to the currently-open pipe stream. * If no pipe stream is open, this value has no meaning, and its contents * are undefined. * * @see GUAC_TERMINAL_PIPE_INTERPRET_OUTPUT * @see GUAC_TERMINAL_PIPE_AUTOFLUSH */ int pipe_stream_flags; /** * Buffer of data pending write to the pipe_stream. Data within this buffer * will be flushed to the pipe_stream when either (1) the buffer is full * and another character needs to be written or (2) the pipe_stream is * closed. */ char pipe_buffer[6048]; /** * The number of bytes currently stored within the pipe_buffer. */ int pipe_buffer_length; /** * The currently-active typescript recording all terminal output, or NULL * if no typescript is being used for the terminal session. */ guac_terminal_typescript* typescript; /** * Terminal-wide mouse cursor, synchronized across all users. */ guac_common_cursor* cursor; /** * Graphical representation of the current scroll state. */ guac_terminal_scrollbar* scrollbar; /** * The relative offset of the display. A positive value indicates that * many rows have been scrolled into view, zero indicates that no * scrolling has occurred. Negative values are illegal. */ int scroll_offset; /** * The maximum number of rows to allow within the terminal buffer. Note * that while this value is traditionally referred to as the scrollback * size, it actually encompasses both the display and the off-screen * region. The terminal will ensure enough buffer space is allocated for * the on-screen rows, even if this exceeds the defined maximum, however * additional rows for off-screen data will only be available if the * display is smaller than this value. */ int max_scrollback; /** * The number of rows that the user has requested be avalable within the * terminal buffer. This value may be adjusted by the user while the * terminal is running through console codes, and will adjust the number * of rows available within the terminal buffer, subject to the maximum * defined at terminal creation and stored within max_scrollback. */ int requested_scrollback; /** * The width of the space available to all components of the terminal, in * pixels. This may include space which will not actually be used for * character rendering. */ int outer_width; /** * The height of the space available to all components of the terminal, in * pixels. This may include space which will not actually be used for * character rendering. */ int outer_height; /** * The width of the terminal, in pixels. */ int width; /** * The height of the terminal, in pixels. */ int height; /** * The width of the terminal, in characters. */ int term_width; /** * The height of the terminal, in characters. */ int term_height; /** * The index of the first row in the scrolling region. */ int scroll_start; /** * The index of the last row in the scrolling region. */ int scroll_end; /** * The current row location of the cursor. Note that while most terminal * operations will clip the cursor location within the bounds of the * terminal, this is not guaranteed. */ int cursor_row; /** * The current column location of the cursor. Note that while most * terminal operations will clip the cursor location within the bounds * of the terminal, this is not guaranteed. There are times when the * cursor is legitimately outside the terminal bounds (such as when the * end of a line is reached, but it is not yet necessary to scroll up). */ int cursor_col; /** * The desired visibility state of the cursor. */ bool cursor_visible; /** * The row of the rendered cursor. * Will be set to -1 if the cursor is not visible. */ int visible_cursor_row; /** * The column of the rendered cursor. * Will be set to -1 if the cursor is not visible. */ int visible_cursor_col; /** * The row of the saved cursor (ESC 7). */ int saved_cursor_row; /** * The column of the saved cursor (ESC 7). */ int saved_cursor_col; /** * The attributes which will be applied to future characters. */ guac_terminal_attributes current_attributes; /** * The character whose attributes dictate the default attributes * of all characters. When new screen space is allocated, this * character fills the gaps. */ guac_terminal_char default_char; /** * Handler which will receive all printed characters, updating the terminal * accordingly. */ guac_terminal_char_handler* char_handler; /** * The difference between the currently-rendered screen and the current * state of the terminal, and the contextual information necessary to * interpret and render those differences. */ guac_terminal_display* display; /** * Current terminal display state. All characters present on the screen * are within this buffer. This has nothing to do with the display, which * facilitates transfer of a set of changes to the remote display. */ guac_terminal_buffer* buffer; /** * Automatically place a tabstop every N characters. If zero, then no * tabstops exist automatically. */ int tab_interval; /** * Array of all tabs set. Each entry is the column number of a tab + 1, * or 0 if that tab cell is unset. */ int custom_tabs[GUAC_TERMINAL_MAX_TABS]; /** * Array of arrays of mapped characters, where the character N is located at the N-32 * position within the array. Each element in a contained array is the corresponding Unicode * codepoint. If NULL, a direct mapping from Unicode is used. The entries of the main array * correspond to the character set in use (G0, G1, etc.) */ const int* char_mapping[2]; /** * The active character set. For example, 0 for G0, 1 for G1, etc. */ int active_char_set; /** * Whether text is currently selected. */ bool text_selected; /** * Whether the selection is finished, and will no longer be modified. A * committed selection remains highlighted for reference, but the * highlight will be removed if characters within the selected region are * modified. */ bool selection_committed; /** * The row that the selection starts at. */ int selection_start_row; /** * The column that the selection starts at. */ int selection_start_column; /** * The width of the character at selection start. */ int selection_start_width; /** * The row that the selection ends at. */ int selection_end_row; /** * The column that the selection ends at. */ int selection_end_column; /** * The width of the character at selection end. */ int selection_end_width; /** * Whether the cursor (arrow) keys should send cursor sequences * or application sequences (DECCKM). */ bool application_cursor_keys; /** * Whether a CR should automatically follow a LF, VT, or FF. */ bool automatic_carriage_return; /** * Whether insert mode is enabled (DECIM). */ bool insert_mode; /** * Whether the alt key is currently being held down. */ int mod_alt; /** * Whether the control key is currently being held down. */ int mod_ctrl; /** * Whether the shift key is currently being held down. */ int mod_shift; /** * The current mouse button state. */ int mouse_mask; /** * The current mouse cursor, to avoid re-setting the cursor image. */ guac_terminal_cursor_type current_cursor; /** * The current contents of the clipboard. This clipboard instance is * maintained externally (will not be freed when this terminal is freed) * and will be updated both internally by the terminal and externally * through received clipboard instructions. */ guac_common_clipboard* clipboard; /** * The name of the font to use when rendering glyphs, as requested at * creation time or via guac_terminal_apply_font(). */ const char* font_name; /** * The size of each glyph, in points, as requested at creation time or via * guac_terminal_apply_font(). */ int font_size; /** * The name of the color scheme to use, as requested at creation time or * via guac_terminal_apply_color_scheme(). This string must be in the * format accepted by guac_terminal_parse_color_scheme(). */ const char* color_scheme; /** * ASCII character to send when backspace is pressed. */ char backspace; /** * Whether copying from the terminal clipboard should be blocked. If set, * the contents of the terminal can still be copied, but will be usable * only within the terminal itself. The clipboard contents will not be * automatically streamed to the client. */ bool disable_copy; }; /** * Creates a new guac_terminal, having the given width and height, and * rendering to the given client. As failover mechanisms and the Guacamole * client implementation typically use the receipt of a "sync" message to * denote successful connection, rendering of frames (sending of "sync") will * be withheld until guac_terminal_start() is called, and user input will be * ignored. The guac_terminal_start() function should be invoked only after * either the underlying connection has truly succeeded, or until visible * terminal output or user input is required. * * @param client * The client to which the terminal will be rendered. * * @param clipboard * The guac_common_clipboard which will contain the current clipboard * state. It is expected that this clipboard instance will be updated * both internally by the terminal and externally through received * clipboard instructions. This clipboard will not be automatically * freed when this terminal is freed. * * @param disable_copy * Whether copying from the terminal clipboard should be blocked. If set, * the contents of the terminal can still be copied, but will be usable * only within the terminal itself. The clipboard contents will not be * automatically streamed to the client. * * @param max_scrollback * The maximum number of rows to allow within the scrollback buffer. The * user may still alter the size of the scrollback buffer using terminal * codes, however the size can never exceed the maximum size given here. * Note that this space is shared with the display, with the scrollable * area actually only containing the given number of rows less the number * of rows currently displayed, and sufficient buffer space will always be * allocated to represent the display area of the terminal regardless of * the value given here. * * @param font_name * The name of the font to use when rendering glyphs. * * @param font_size * The size of each glyph, in points. * * @param dpi * The DPI of the display. The given font size will be adjusted to produce * glyphs at the given DPI. * * @param width * The width of the terminal, in pixels. * * @param height * The height of the terminal, in pixels. * * @param color_scheme * The name of the color scheme to use. This string must be in the format * accepted by guac_terminal_parse_color_scheme(). * * @param backspace * The integer ASCII code to send when backspace is pressed in * this terminal. * * @return * A new guac_terminal having the given font, dimensions, and attributes * which renders all text to the given client. */ guac_terminal* guac_terminal_create(guac_client* client, guac_common_clipboard* clipboard, bool disable_copy, int max_scrollback, const char* font_name, int font_size, int dpi, int width, int height, const char* color_scheme, const int backspace); /** * Frees all resources associated with the given terminal. */ void guac_terminal_free(guac_terminal* term); /** * Renders a single frame of terminal data. If data is not yet available, * this function will block until data is written. */ int guac_terminal_render_frame(guac_terminal* terminal); /** * Reads from this terminal's STDIN. Input comes from key and mouse events * supplied by calls to guac_terminal_send_key(), * guac_terminal_send_mouse(), and guac_terminal_send_stream(). If input is not * yet available, this function will block. */ int guac_terminal_read_stdin(guac_terminal* terminal, char* c, int size); /** * Notifies the terminal that rendering should begin and that user input should * now be accepted. This function must be invoked following terminal creation * for the end of frames to be signalled with "sync" messages. Until this * function is invoked, "sync" messages will be withheld. * * @param term * The terminal to start. */ void guac_terminal_start(guac_terminal* term); /** * Manually stop the terminal to forcibly unblock any pending reads/writes, * e.g. forcing guac_terminal_read_stdin() to return and cease all terminal I/O. * * @param term * The terminal to stop. */ void guac_terminal_stop(guac_terminal* term); /** * Notifies the terminal that an event has occurred and the terminal should * flush itself when reasonable. * * @param terminal * The terminal to notify. */ void guac_terminal_notify(guac_terminal* terminal); /** * Reads a single line from this terminal's STDIN, storing the result in a * newly-allocated string. Input is retrieved in the same manner as * guac_terminal_read_stdin() and the same restrictions apply. As reading input * naturally requires user interaction, this function will implicitly invoke * guac_terminal_start(). * * @param terminal * The terminal to which the provided title should be output, and from * whose STDIN the single line of input should be read. * * @param title * The human-readable title to output to the terminal just prior to reading * from STDIN. * * @param echo * Non-zero if the characters read from STDIN should be echoed back as * terminal output, or zero if asterisks should be displayed instead. * * @return * A newly-allocated string containing a single line of input read from the * provided terminal's STDIN. This string must eventually be manually * freed with a call to free(). */ char* guac_terminal_prompt(guac_terminal* terminal, const char* title, bool echo); /** * Writes the given format string and arguments to this terminal's STDOUT in * the same manner as printf(). This function may block until space is * freed in the output buffer by guac_terminal_render_frame(). */ int guac_terminal_printf(guac_terminal* terminal, const char* format, ...); /** * Handles the given key event, sending data, scrolling, pasting clipboard * data, etc. as necessary. If terminal input is currently coming from a * stream due to a prior call to guac_terminal_send_stream(), any input * which would normally result from the key event is dropped. * * @param term * The terminal which should receive the given data on STDIN. * * @param keysym * The X11 keysym of the key that was pressed or released. * * @param pressed * Non-zero if the key represented by the given keysym is currently * pressed, zero if it is released. * * @return * Zero if the key event was handled successfully, non-zero otherwise. */ int guac_terminal_send_key(guac_terminal* term, int keysym, int pressed); /** * Handles the given mouse event, sending data, scrolling, pasting clipboard * data, etc. as necessary. If terminal input is currently coming from a * stream due to a prior call to guac_terminal_send_stream(), any input * which would normally result from the mouse event is dropped. * * @param term * The terminal which should receive the given data on STDIN. * * @param user * The user that originated the mouse event. * * @param x * The X coordinate of the mouse within the display when the event * occurred, in pixels. This value is not guaranteed to be within the * bounds of the display area. * * @param y * The Y coordinate of the mouse within the display when the event * occurred, in pixels. This value is not guaranteed to be within the * bounds of the display area. * * @param mask * An integer value representing the current state of each button, where * the Nth bit within the integer is set to 1 if and only if the Nth mouse * button is currently pressed. The lowest-order bit is the left mouse * button, followed by the middle button, right button, and finally the up * and down buttons of the scroll wheel. * * @see GUAC_CLIENT_MOUSE_LEFT * @see GUAC_CLIENT_MOUSE_MIDDLE * @see GUAC_CLIENT_MOUSE_RIGHT * @see GUAC_CLIENT_MOUSE_SCROLL_UP * @see GUAC_CLIENT_MOUSE_SCROLL_DOWN * * @return * Zero if the mouse event was handled successfully, non-zero otherwise. */ int guac_terminal_send_mouse(guac_terminal* term, guac_user* user, int x, int y, int mask); /** * Initializes the handlers of the given guac_stream such that it serves as the * source of input to the terminal. Other input sources will be temporarily * ignored until the stream is closed through receiving an "end" instruction. * If input is already being read from a stream due to a prior call to * guac_terminal_send_stream(), the prior call will remain in effect and this * call will fail. * * Calling this function will overwrite the data member of the given * guac_stream. * * @param term * The terminal emulator which should receive input from the given stream. * * @param user * The user that opened the stream. * * @param stream * The guac_stream which should serve as the source of input for the * terminal. * * @return * Zero if the terminal input has successfully been configured to read from * the given stream, non-zero otherwise. */ int guac_terminal_send_stream(guac_terminal* term, guac_user* user, guac_stream* stream); /** * Handles a scroll event received from the scrollbar associated with a * terminal. * * @param scrollbar * The scrollbar that has been scrolled. * * @param value * The new value that should be stored within the scrollbar, and * represented within the terminal display. */ void guac_terminal_scroll_handler(guac_terminal_scrollbar* scrollbar, int value); /** * Replicates the current display state to a user that has just joined the * connection. All instructions necessary to replicate state are sent over the * given socket. * * @param term * The terminal emulator associated with the connection being joined. * * @param user * The user joining the connection. * * @param socket * The guac_socket specific to the joining user and across which messages * synchronizing the current display state should be sent. */ void guac_terminal_dup(guac_terminal* term, guac_user* user, guac_socket* socket); /* INTERNAL FUNCTIONS */ /** * Acquires exclusive access to the terminal. Note that enforcing this * exclusive access requires that ALL users of the terminal call this * function before making further calls to the terminal. */ void guac_terminal_lock(guac_terminal* terminal); /** * Releases exclusive access to the terminal. */ void guac_terminal_unlock(guac_terminal* terminal); /** * Resets the state of the given terminal, as if it were just allocated. */ void guac_terminal_reset(guac_terminal* term); /** * Writes the given string of characters to the terminal. */ int guac_terminal_write(guac_terminal* term, const char* c, int size); /** * Sets the character at the given row and column to the specified value. */ int guac_terminal_set(guac_terminal* term, int row, int col, int codepoint); /** * Clears the given region within a single row. */ int guac_terminal_clear_columns(guac_terminal* term, int row, int start_col, int end_col); /** * Clears the given region from right-to-left, top-to-bottom, replacing * all characters with the current background color and attributes. */ int guac_terminal_clear_range(guac_terminal* term, int start_row, int start_col, int end_row, int end_col); /** * Scrolls the terminal's current scroll region up by one row. */ int guac_terminal_scroll_up(guac_terminal* term, int start_row, int end_row, int amount); /** * Scrolls the terminal's current scroll region down by one row. */ int guac_terminal_scroll_down(guac_terminal* term, int start_row, int end_row, int amount); /** * Commits the current cursor location, updating the visible cursor * on the screen. */ void guac_terminal_commit_cursor(guac_terminal* term); /** * Scroll down the display by the given amount, replacing the new space with * data from the buffer. If not enough data is available, the maximum * amount will be scrolled. */ void guac_terminal_scroll_display_down(guac_terminal* terminal, int amount); /** * Scroll up the display by the given amount, replacing the new space with data * from either the buffer or the terminal buffer. If not enough data is * available, the maximum amount will be scrolled. */ void guac_terminal_scroll_display_up(guac_terminal* terminal, int amount); /* LOW-LEVEL TERMINAL OPERATIONS */ /** * Copies the given range of columns to a new location, offset from * the original by the given number of columns. */ void guac_terminal_copy_columns(guac_terminal* terminal, int row, int start_column, int end_column, int offset); /** * Copies the given range of rows to a new location, offset from the * original by the given number of rows. */ void guac_terminal_copy_rows(guac_terminal* terminal, int start_row, int end_row, int offset); /** * Sets the given range of columns within the given row to the given * character. */ void guac_terminal_set_columns(guac_terminal* terminal, int row, int start_column, int end_column, guac_terminal_char* character); /** * Resize the terminal to the given dimensions. */ int guac_terminal_resize(guac_terminal* term, int width, int height); /** * Flushes all pending operations within the given guac_terminal. */ void guac_terminal_flush(guac_terminal* terminal); /** * Sends the given string as if typed by the user. If terminal input is * currently coming from a stream due to a prior call to * guac_terminal_send_stream(), any input which would normally result from * invoking this function is dropped. * * @param term * The terminal which should receive the given data on STDIN. * * @param data * The data the terminal should receive on STDIN. * * @param length * The size of the given data, in bytes. * * @return * The number of bytes written to STDIN, or a negative value if an error * occurs preventing the data from being written. This should always be * the size of the data given unless data is intentionally dropped. */ int guac_terminal_send_data(guac_terminal* term, const char* data, int length); /** * Sends the given string as if typed by the user. If terminal input is * currently coming from a stream due to a prior call to * guac_terminal_send_stream(), any input which would normally result from * invoking this function is dropped. * * @param term * The terminal which should receive the given data on STDIN. * * @param data * The data the terminal should receive on STDIN. * * @return * The number of bytes written to STDIN, or a negative value if an error * occurs preventing the data from being written. This should always be * the size of the data given unless data is intentionally dropped. */ int guac_terminal_send_string(guac_terminal* term, const char* data); /** * Sends data through STDIN as if typed by the user, using the format string * given and any args (similar to printf). If terminal input is currently * coming from a stream due to a prior call to guac_terminal_send_stream(), any * input which would normally result from invoking this function is dropped. * * @param term * The terminal which should receive the given data on STDIN. * * @param format * A printf-style format string describing the data to be received on * STDIN. * * @param ... * Any srguments to use when filling the format string. * * @return * The number of bytes written to STDIN, or a negative value if an error * occurs preventing the data from being written. This should always be * the size of the data given unless data is intentionally dropped. */ int guac_terminal_sendf(guac_terminal* term, const char* format, ...); /** * Sets a tabstop in the given column. */ void guac_terminal_set_tab(guac_terminal* term, int column); /** * Removes the tabstop at the given column. */ void guac_terminal_unset_tab(guac_terminal* term, int column); /** * Removes all tabstops. */ void guac_terminal_clear_tabs(guac_terminal* term); /** * Given a column within the given terminal, returns the location of the * next tabstop (or the rightmost character, if no more tabstops exist). */ int guac_terminal_next_tab(guac_terminal* term, int column); /** * Opens a new pipe stream, redirecting all output from the given terminal to * that pipe stream. If a pipe stream is already open, that pipe stream will * be flushed and closed prior to opening the new pipe stream. * * @param term * The terminal which should redirect output to a new pipe stream having * the given name. * * @param name * The name of the pipe stream to open. * * @param flags * A bitwise OR of all integer flags which should apply to the new pipe * stream. * * @see GUAC_TERMINAL_PIPE_INTERPRET_OUTPUT * @see GUAC_TERMINAL_PIPE_AUTOFLUSH */ void guac_terminal_pipe_stream_open(guac_terminal* term, const char* name, int flags); /** * Writes a single byte of data to the pipe stream currently open and * associated with the given terminal. The pipe stream must already have been * opened via guac_terminal_pipe_stream_open(). If no pipe stream is currently * open, this function has no effect. Data written through this function may * be buffered. * * @param term * The terminal whose currently-open pipe stream should be written to. * * @param c * The byte of data to write to the pipe stream. */ void guac_terminal_pipe_stream_write(guac_terminal* term, char c); /** * Flushes any data currently buffered for the currently-open pipe stream * associated with the given terminal. The pipe stream must already have been * opened via guac_terminal_pipe_stream_open(). If no pipe stream is currently * open or no data is in the buffer, this function has no effect. * * @param term * The terminal whose pipe stream buffer should be flushed. */ void guac_terminal_pipe_stream_flush(guac_terminal* term); /** * Closes the currently-open pipe stream associated with the given terminal, * redirecting all output back to the terminal display. Any data currently * buffered for output to the pipe stream will be flushed prior to closure. The * pipe stream must already have been opened via * guac_terminal_pipe_stream_open(). If no pipe stream is currently open, this * function has no effect. * * @param term * The terminal whose currently-open pipe stream should be closed. */ void guac_terminal_pipe_stream_close(guac_terminal* term); /** * Requests that the terminal write all output to a new pair of typescript * files within the given path and using the given base name. Terminal output * will be written to these new files, along with timing information. If the * create_path flag is non-zero, the given path will be created if it does not * yet exist. If creation of the typescript files or path fails, error messages * will automatically be logged, and no typescript will be written. The * typescript will automatically be closed once the terminal is freed. * * @param term * The terminal whose output should be written to a typescript. * * @param path * The full absolute path to a directory in which the typescript files * should be created. * * @param name * The base name to use for the typescript files created within the * specified path. * * @param create_path * Zero if the specified path MUST exist for typescript files to be * written, or non-zero if the path should be created if it does not yet * exist. * * @return * Zero if the typescript files have been successfully created and a * typescript will be written, non-zero otherwise. */ int guac_terminal_create_typescript(guac_terminal* term, const char* path, const char* name, int create_path); /** * Returns the number of rows within the buffer of the given terminal which are * not currently displayed on screen. Adjustments to the desired scrollback * size are taken into account, and rows which are within the buffer but * unavailable due to being outside the desired scrollback range are ignored. * * @param term * The terminal whose off-screen row count should be determined. * * @return * The number of rows within the buffer which are not currently displayed * on screen. */ int guac_terminal_available_scroll(guac_terminal* term); /** * Immediately applies the given color scheme to the given terminal, overriding * the color scheme provided when the terminal was created. Valid color schemes * are those accepted by guac_terminal_parse_color_scheme(). * * @param terminal * The terminal to apply the color scheme to. * * @param color_scheme * The color scheme to apply. */ void guac_terminal_apply_color_scheme(guac_terminal* terminal, const char* color_scheme); /** * Alters the font of the terminal. The terminal will automatically be redrawn * and resized as necessary. If the terminal size changes, the remote side of * the terminal session must be manually informed of that change or graphical * artifacts may result. * * @param terminal * The terminal whose font family and/or size are being changed. * * @param font_name * The name of the new font family, or NULL if the font family should * remain unchanged. * * @param font_size * The new font size, in points, or -1 if the font size should remain * unchanged. * * @param dpi * The resolution of the display in DPI. If the font size will not be * changed (the font size given is -1), this value is ignored. */ void guac_terminal_apply_font(guac_terminal* terminal, const char* font_name, int font_size, int dpi); #endif guacamole-server-1.3.0/src/terminal/terminal/types.h0000644000175100001440000000556613613156714017447 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_TERMINAL_TYPES_H #define _GUAC_TERMINAL_TYPES_H #include "config.h" #include "palette.h" #include #include /** * A character which is not truly a character, but rather part of an * existing character which spans multiple columns. The original * character will be somewhere earlier in the row, separated from * this character by a contiguous string of zero of more * GUAC_CHAR_CONTINUATION characters. */ #define GUAC_CHAR_CONTINUATION -1 /** * Terminal attributes, as can be applied to a single character. */ typedef struct guac_terminal_attributes { /** * Whether the character should be rendered bold. */ bool bold; /** * Whether the character should be rendered with half brightness (faint * or low intensity). */ bool half_bright; /** * Whether the character should be rendered with reversed colors * (background becomes foreground and vice-versa). */ bool reverse; /** * Whether the associated character is highlighted by the cursor. */ bool cursor; /** * Whether to render the character with underscore. */ bool underscore; /** * The foreground color of this character. */ guac_terminal_color foreground; /** * The background color of this character. */ guac_terminal_color background; } guac_terminal_attributes; /** * Represents a single character for display in a terminal, including actual * character value, foreground color, and background color. */ typedef struct guac_terminal_char { /** * The Unicode codepoint of the character to display, or * GUAC_CHAR_CONTINUATION if this character is part of * another character which spans multiple columns. */ int value; /** * The attributes of the character to display. */ guac_terminal_attributes attributes; /** * The number of columns this character occupies. If the character is * GUAC_CHAR_CONTINUATION, this value is undefined and not applicable. */ int width; } guac_terminal_char; #endif guacamole-server-1.3.0/src/terminal/terminal/buffer.h0000644000175100001440000000760013702142276017540 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_TERMINAL_BUFFER_H #define _GUAC_TERMINAL_BUFFER_H #include "config.h" #include "types.h" /** * A single variable-length row of terminal data. */ typedef struct guac_terminal_buffer_row { /** * Array of guac_terminal_char representing the contents of the row. */ guac_terminal_char* characters; /** * The length of this row in characters. This is the number of initialized * characters in the buffer, usually equal to the number of characters * in the screen width at the time this row was created. */ int length; /** * The number of elements in the characters array. After the length * equals this value, the array must be resized. */ int available; } guac_terminal_buffer_row; /** * A buffer containing a constant number of arbitrary-length rows. * New rows can be appended to the buffer, with the oldest row replaced with * the new row. */ typedef struct guac_terminal_buffer { /** * The character to assign to newly-allocated cells. */ guac_terminal_char default_character; /** * Array of buffer rows. This array functions as a ring buffer. * When a new row needs to be appended, the top reference is moved down * and the old top row is replaced. */ guac_terminal_buffer_row* rows; /** * The index of the first row in the buffer (the row which represents row 0 * with respect to the terminal display). This is also the index of the row * to replace when insufficient space remains in the buffer to add a new * row. */ int top; /** * The number of rows currently stored in the buffer. */ int length; /** * The number of rows in the buffer. This is the total capacity * of the buffer. */ int available; } guac_terminal_buffer; /** * Allocates a new buffer having the given maximum number of rows. New character cells will * be initialized to the given character. */ guac_terminal_buffer* guac_terminal_buffer_alloc(int rows, guac_terminal_char* default_character); /** * Frees the given buffer. */ void guac_terminal_buffer_free(guac_terminal_buffer* buffer); /** * Returns the row at the given location. The row returned is guaranteed to be at least the given * width. */ guac_terminal_buffer_row* guac_terminal_buffer_get_row(guac_terminal_buffer* buffer, int row, int width); /** * Copies the given range of columns to a new location, offset from * the original by the given number of columns. */ void guac_terminal_buffer_copy_columns(guac_terminal_buffer* buffer, int row, int start_column, int end_column, int offset); /** * Copies the given range of rows to a new location, offset from the * original by the given number of rows. */ void guac_terminal_buffer_copy_rows(guac_terminal_buffer* buffer, int start_row, int end_row, int offset); /** * Sets the given range of columns within the given row to the given * character. */ void guac_terminal_buffer_set_columns(guac_terminal_buffer* buffer, int row, int start_column, int end_column, guac_terminal_char* character); #endif guacamole-server-1.3.0/src/terminal/terminal/display.h0000644000175100001440000002345013702142276017735 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_TERMINAL_DISPLAY_H #define _GUAC_TERMINAL_DISPLAY_H #include "config.h" #include "common/surface.h" #include "palette.h" #include "types.h" #include #include #include #include #include /** * The maximum width of any character, in columns. */ #define GUAC_TERMINAL_MAX_CHAR_WIDTH 2 /** * All available terminal operations which affect character cells. */ typedef enum guac_terminal_operation_type { /** * Operation which does nothing. */ GUAC_CHAR_NOP, /** * Operation which copies a character from a given row/column coordinate. */ GUAC_CHAR_COPY, /** * Operation which sets the character and attributes. */ GUAC_CHAR_SET } guac_terminal_operation_type; /** * A pairing of a guac_terminal_operation_type and all parameters required by * that operation type. */ typedef struct guac_terminal_operation { /** * The type of operation to perform. */ guac_terminal_operation_type type; /** * The character (and attributes) to set the current location to. This is * only applicable to GUAC_CHAR_SET. */ guac_terminal_char character; /** * The row to copy a character from. This is only applicable to * GUAC_CHAR_COPY. */ int row; /** * The column to copy a character from. This is only applicable to * GUAC_CHAR_COPY. */ int column; } guac_terminal_operation; /** * Set of all pending operations for the currently-visible screen area, and the * contextual information necessary to interpret and render those changes. */ typedef struct guac_terminal_display { /** * The Guacamole client this display will use for rendering. */ guac_client* client; /** * Array of all operations pending for the visible screen area. */ guac_terminal_operation* operations; /** * The width of the screen, in characters. */ int width; /** * The height of the screen, in characters. */ int height; /** * The description of the font to use for rendering. */ PangoFontDescription* font_desc; /** * The width of each character, in pixels. */ int char_width; /** * The height of each character, in pixels. */ int char_height; /** * The current palette. */ guac_terminal_color palette[256]; /** * The default palette. Use GUAC_TERMINAL_INITIAL_PALETTE if null. * Must free on destruction if not null. */ guac_terminal_color (*default_palette)[256]; /** * Default foreground color for all glyphs. */ guac_terminal_color default_foreground; /** * Default background color for all glyphs and the terminal itself. */ guac_terminal_color default_background; /** * The foreground color to be used for the next glyph rendered to the * terminal. */ guac_terminal_color glyph_foreground; /** * The background color to be used for the next glyph rendered to the * terminal. */ guac_terminal_color glyph_background; /** * The surface containing the actual terminal. */ guac_common_surface* display_surface; /** * Layer which contains the actual terminal. */ guac_layer* display_layer; /** * Sub-layer of display layer which highlights selected text. */ guac_layer* select_layer; /** * Whether text is currently selected. */ bool text_selected; /** * The row that the selection starts at. */ int selection_start_row; /** * The column that the selection starts at. */ int selection_start_column; /** * The row that the selection ends at. */ int selection_end_row; /** * The column that the selection ends at. */ int selection_end_column; } guac_terminal_display; /** * Allocates a new display having the given default foreground and background * colors. */ guac_terminal_display* guac_terminal_display_alloc(guac_client* client, const char* font_name, int font_size, int dpi, guac_terminal_color* foreground, guac_terminal_color* background, guac_terminal_color (*palette)[256]); /** * Frees the given display. */ void guac_terminal_display_free(guac_terminal_display* display); /** * Resets the palette of the given display to the initial, default color * values, as defined by default_palette or GUAC_TERMINAL_INITIAL_PALETTE. * * @param display * The display to reset. */ void guac_terminal_display_reset_palette(guac_terminal_display* display); /** * Replaces the color in the palette at the given index with the given color. * If the index is invalid, the assignment is ignored. * * @param display * The display whose palette is being changed. * * @param index * The index of the palette entry to change. * * @param color * The color to assign to the palette entry having the given index. * * @returns * Zero if the assignment was successful, non-zero if the assignment * failed. */ int guac_terminal_display_assign_color(guac_terminal_display* display, int index, const guac_terminal_color* color); /** * Retrieves the color within the palette at the given index, if such a color * exists. If the index is invalid, no color is retrieved. * * @param display * The display whose palette contains the color to be retrieved. * * @param index * The index of the palette entry to retrieve. * * @param color * A pointer to a guac_terminal_color structure which should receive the * color retrieved from the palette. * * @returns * Zero if the color was successfully retrieved, non-zero otherwise. */ int guac_terminal_display_lookup_color(guac_terminal_display* display, int index, guac_terminal_color* color); /** * Copies the given range of columns to a new location, offset from * the original by the given number of columns. */ void guac_terminal_display_copy_columns(guac_terminal_display* display, int row, int start_column, int end_column, int offset); /** * Copies the given range of rows to a new location, offset from the * original by the given number of rows. */ void guac_terminal_display_copy_rows(guac_terminal_display* display, int start_row, int end_row, int offset); /** * Sets the given range of columns within the given row to the given * character. */ void guac_terminal_display_set_columns(guac_terminal_display* display, int row, int start_column, int end_column, guac_terminal_char* character); /** * Resize the terminal to the given dimensions. */ void guac_terminal_display_resize(guac_terminal_display* display, int width, int height); /** * Flushes all pending operations within the given guac_terminal_display. */ void guac_terminal_display_flush(guac_terminal_display* display); /** * Initializes and syncs the current terminal display state for the given user * that has just joined the connection, sending the necessary instructions to * completely recreate and redraw the terminal rendering over the given socket. * * @param display * The terminal display to sync to the given user. * * @param user * The user that has just joined the connection. * * @param socket * The socket over which any necessary instructions should be sent. */ void guac_terminal_display_dup(guac_terminal_display* display, guac_user* user, guac_socket* socket); /** * Draws the text selection rectangle from the given coordinates to the given end coordinates. */ void guac_terminal_display_select(guac_terminal_display* display, int start_row, int start_col, int end_row, int end_col); /** * Clears the currently-selected region, removing the highlight. * * @param display * The guac_terminal_display whose currently-selected region should be * cleared. */ void guac_terminal_display_clear_select(guac_terminal_display* display); /** * Alters the font of the terminal display. The available display area and the * regular grid of character cells will be resized as necessary to compensate * for any changes in font metrics. * * If successful, the terminal itself MUST be manually resized to take into * account the new character dimensions, and MUST be manually redrawn. Failing * to do so will result in graphical artifacts. * * @param display * The display whose font family and/or size are being changed. * * @param font_name * The name of the new font family, or NULL if the font family should * remain unchanged. * * @param font_size * The new font size, in points, or -1 if the font size should remain * unchanged. * * @param dpi * The resolution of the display in DPI. If the font size will not be * changed (the font size given is -1), this value is ignored. * * @return * Zero if the font was successfully changed, non-zero otherwise. */ int guac_terminal_display_set_font(guac_terminal_display* display, const char* font_name, int font_size, int dpi); #endif guacamole-server-1.3.0/src/terminal/terminal/typescript.h0000644000175100001440000001330413613156714020476 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TERMINAL_TYPESCRIPT_H #define GUAC_TERMINAL_TYPESCRIPT_H #include "config.h" #include /** * A NULL-terminated string of raw bytes which should be written at the * beginning of any typescript. */ #define GUAC_TERMINAL_TYPESCRIPT_HEADER "[BEGIN TYPESCRIPT]\n" /** * A NULL-terminated string of raw bytes which should be written at the * end of any typescript. */ #define GUAC_TERMINAL_TYPESCRIPT_FOOTER "\n[END TYPESCRIPT]\n" /** * The maximum amount of time to allow for a particular timing entry, in * milliseconds. Any timing entries exceeding this value will be written as * exactly this value instead. */ #define GUAC_TERMINAL_TYPESCRIPT_MAX_DELAY 86400000 /** * The maximum numeric value allowed for the .1, .2, .3, etc. suffix appended * to the end of the typescript filename if a typescript having the requested * name already exists. */ #define GUAC_TERMINAL_TYPESCRIPT_MAX_SUFFIX 255 /** * The maximum length of the string containing a sequential numeric suffix * between 1 and GUAC_TERMINAL_TYPESCRIPT_MAX_SUFFIX inclusive, in bytes, * including NULL terminator. */ #define GUAC_TERMINAL_TYPESCRIPT_MAX_SUFFIX_LENGTH 4 /** * The maximum overall length of the full path to the typescript file, * including any additional suffix and NULL terminator, in bytes. */ #define GUAC_TERMINAL_TYPESCRIPT_MAX_NAME_LENGTH 2048 /** * The suffix which will be appended to the typescript data file's name to * produce the name of the timing file. */ #define GUAC_TERMINAL_TYPESCRIPT_TIMING_SUFFIX "timing" /** * An active typescript, consisting of a data file (raw terminal output) and * timing file (related timestamps and byte counts). */ typedef struct guac_terminal_typescript { /** * Buffer of raw terminal output which has not yet been written to the * data file. */ char buffer[4096]; /** * The number of bytes currently stored in the buffer. */ int length; /** * The full path to the file which will contain the raw terminal output for * this typescript. */ char data_filename[GUAC_TERMINAL_TYPESCRIPT_MAX_NAME_LENGTH]; /** * The full path to the file which will contain the timing information for * this typescript. */ char timing_filename[GUAC_TERMINAL_TYPESCRIPT_MAX_NAME_LENGTH]; /** * The file descriptor of the file into which raw terminal output should be * written. */ int data_fd; /** * The file descriptor of the file into which timing information * (timestamps and byte counts) related to the raw terminal output in the * data file should be written. */ int timing_fd; /** * The last time that this typescript was flushed. If this typescript was * never flushed, this will be the time the typescripe was created. */ guac_timestamp last_flush; } guac_terminal_typescript; /** * Creates a new pair of typescript files within the given path and using the * given base name, returning an abstraction which represents those files. * Terminal output will be written to these new files, along with timing * information. If the create_path flag is non-zero, the given path will be * created if it does not yet exist. * * @param path * The full absolute path to a directory in which the typescript files * should be created. * * @param name * The base name to use for the typescript files created within the * specified path. * * @param create_path * Zero if the specified path MUST exist for typescript files to be * written, or non-zero if the path should be created if it does not yet * exist. * * @return * A new guac_terminal_typescript representing the typescript files * requested, or NULL if creation of the typescript files failed. */ guac_terminal_typescript* guac_terminal_typescript_alloc(const char* path, const char* name, int create_path); /** * Writes a single byte of terminal data to the typescript, flushing and * writing a new timestamp if necessary. * * @param typescript * The typescript that the given byte of raw terminal data should be * written to. * * @param c * The single byte of raw terminal data to write to the typescript. */ void guac_terminal_typescript_write(guac_terminal_typescript* typescript, char c); /** * Flushes any pending data to the typescript, writing a new timestamp to the * timing file if any data was flushed. * * @param typescript * The typescript which should be flushed. */ void guac_terminal_typescript_flush(guac_terminal_typescript* typescript); /** * Frees all resources associated with the given typescript, flushing and * closing the data and timing files and freeing all related memory. If the * provided typescript is NULL, this function has no effect. * * @param typescript * The typescript to free. */ void guac_terminal_typescript_free(guac_terminal_typescript* typescript); #endif guacamole-server-1.3.0/src/terminal/terminal/char_mappings.h0000644000175100001440000000324413613156714021105 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_TERMINAL_CHAR_MAPPINGS_H #define _GUAC_TERMINAL_CHAR_MAPPINGS_H #include "config.h" /** * VT100 graphics mapping. Each entry is the corresponding Unicode codepoint * for the character N+32, where N is the index of the element in the array. * All characters less than 32 are universally mapped to themselves. */ extern const int vt100_map[]; /** * Null graphics mapping. Each entry is the corresponding Unicode codepoint * for the character N+32, where N is the index of the element in the array. * All characters less than 32 are universally mapped to themselves. */ extern const int null_map[]; /** * User graphics mapping. Each entry is the corresponding Unicode codepoint * for the character N+32, where N is the index of the element in the array. * All characters less than 32 are universally mapped to themselves. */ extern const int user_map[]; #endif guacamole-server-1.3.0/src/terminal/terminal/scrollbar.h0000644000175100001440000002376213613156714020264 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_TERMINAL_SCROLLBAR_H #define GUAC_TERMINAL_SCROLLBAR_H #include "config.h" #include #include /** * The width of the scrollbar, in pixels. */ #define GUAC_TERMINAL_SCROLLBAR_WIDTH 16 /** * The number of pixels between the draggable handle of the scrollbar and the * boundary of the containing layer. */ #define GUAC_TERMINAL_SCROLLBAR_PADDING 2 /** * The minimum height of the draggable handle of the scrollbar, in pixels. */ #define GUAC_TERMINAL_SCROLLBAR_MIN_HEIGHT 64 /** * The state of all scrollbar components, describing all variable aspects of * the scrollbar's appearance. */ typedef struct guac_terminal_scrollbar_render_state { /** * The current X-coordinate of the upper-left corner of the scrollbar's * handle. This value will be relative to the scrollbar's containing layer. */ int handle_x; /** * The current Y-coordinate of the upper-left corner of the scrollbar's * handle. This value will be relative to the scrollbar's containing layer. */ int handle_y; /** * The width of the scrollbar's handle. */ int handle_width; /** * The height of the scrollbar's handle. */ int handle_height; /** * The current X-coordinate of the upper-left corner of the scrollbar's * containing layer. */ int container_x; /** * The current Y-coordinate of the upper-left corner of the scrollbar's * containing layer. */ int container_y; /** * The width of the scrollbar's containing layer. */ int container_width; /** * The height of the scrollbar's containing layer. */ int container_height; } guac_terminal_scrollbar_render_state; typedef struct guac_terminal_scrollbar guac_terminal_scrollbar; /** * Handler which is called whenever the scrollbar value changes outside a call * to guac_terminal_scrollbar_set_value(). */ typedef void guac_terminal_scrollbar_scroll_handler( guac_terminal_scrollbar* scrollbar, int value); /** * A scrollbar, made up of a containing layer and inner draggable handle. The * position of the handle within the layer represents the value of the * scrollbar. */ struct guac_terminal_scrollbar { /** * The client associated with this scrollbar. */ guac_client* client; /** * The layer containing the scrollbar. */ const guac_layer* parent; /** * The width of the parent layer, in pixels. */ int parent_width; /** * The height of the parent layer, in pixels. */ int parent_height; /** * The scrollbar itself. */ guac_layer* container; /** * The draggable handle within the scrollbar, representing the current * scroll value. */ guac_layer* handle; /** * The minimum scroll value. */ int min; /** * The maximum scroll value. */ int max; /** * The size of the visible area, in the same units as min and max. */ int visible_area; /** * The current scroll value. */ int value; /** * The current state of all variable, visible parts of the scrollbar. */ guac_terminal_scrollbar_render_state render_state; /** * Whether the scrollbar handle is currently being dragged. */ int dragging_handle; /** * The offset of the Y location of the mouse pointer when the dragging * began, relative to the top of the scrollbar handle. If dragging is not * in progress, this value is undefined. */ int drag_offset_y; /** * The current Y location of the mouse pointer if dragging is in progress. * If dragging is not in progress, this value is undefined. */ int drag_current_y; /** * The function to call when the scrollbar handle is being dragged, and * the new scrollbar value needs to be handled and assigned. */ guac_terminal_scrollbar_scroll_handler* scroll_handler; /** * Arbitrary reference to data related to this scrollbar. */ void* data; }; /** * Allocates a new scrollbar, associating that scrollbar with the given client * and parent layer. The dimensions of the parent layer dictate the initial * position of the scrollbar. Currently, the scrollbar is always anchored to * the right edge of the parent layer. * * This will cause instructions to be written to the client's socket, but the * client's socket will not be automatically flushed. * * @param client * The client to associate with the new scrollbar. * * @param parent * The layer which will contain the newly-allocated scrollbar. * * @param parent_width * The width of the parent layer, in pixels. * * @param parent_height * The height of the parent layer, in pixels. * * @param visible_area * The amount of scrollable data that can be shown within the parent layer * at any given time. This value uses the same units as min, max, and the * current scroll value. * * @return * A newly allocated scrollbar. */ guac_terminal_scrollbar* guac_terminal_scrollbar_alloc(guac_client* client, const guac_layer* parent, int parent_width, int parent_height, int visible_area); /** * Frees the given scrollbar. * * @param scrollbar * The scrollbar to free. */ void guac_terminal_scrollbar_free(guac_terminal_scrollbar* scrollbar); /** * Flushes the render state of the given scrollbar, updating the remote display * accordingly. * * This may cause instructions to be written to the client's socket, but the * client's socket will not be automatically flushed. * * @param scrollbar * The scrollbar whose render state is to be flushed. */ void guac_terminal_scrollbar_flush(guac_terminal_scrollbar* scrollbar); /** * Forces a complete redraw / resync of scrollbar state for the given user that * has just joined the connection, sending the necessary instructions to * completely recreate and redraw the scrollbar rendering over the given * socket. * * @param scrollbar * The scrollbar to sync to the given user. * * @param user * The user that has just joined the connection. * * @param socket * The socket over which any necessary instructions should be sent. */ void guac_terminal_scrollbar_dup(guac_terminal_scrollbar* scrollbar, guac_user* user, guac_socket* socket); /** * Sets the minimum and maximum allowed scroll values of the given scrollbar * to the given values. If necessary, the current value of the scrollbar will * be adjusted to fit within the new bounds. * * This may cause instructions to be written to the client's socket, but the * client's socket will not be automatically flushed. * * @param scrollbar * The scrollbar whose bounds are changing. * * @param min * The new minimum value of the scrollbar. * * @param max * The new maximum value of the scrollbar. */ void guac_terminal_scrollbar_set_bounds(guac_terminal_scrollbar* scrollbar, int min, int max); /** * Sets the current value of the given scrollbar. If the value specified does * not fall within the scrollbar's defined minimum and maximum values, the * value will be adjusted to fit. * * This may cause instructions to be written to the client's socket, but the * client's socket will not be automatically flushed. * * @param scrollbar * The scrollbar whose value is changing. * * @param value * The value to assign to the scrollbar. If the value if out of bounds, it * will be automatically adjusted to fit. */ void guac_terminal_scrollbar_set_value(guac_terminal_scrollbar* scrollbar, int value); /** * Notifies the scrollbar that the parent layer has been resized, and that the * scrollbar may need to be repositioned or resized accordingly. * * This may cause instructions to be written to the client's socket, but the * client's socket will not be automatically flushed. * * @param scrollbar * The scrollbar whose parent layer has been resized. * * @param parent_width * The new width of the parent layer, in pixels. * * @param parent_height * The new height of the parent layer, in pixels. * * @param visible_area * The amount of scrollable data that can be shown within the parent layer * at any given time. This value uses the same units as min, max, and the * current scroll value. */ void guac_terminal_scrollbar_parent_resized(guac_terminal_scrollbar* scrollbar, int parent_width, int parent_height, int visible_area); /** * Notifies the scrollbar of the current mouse state, allowing it to update * itself with respect to button state and dragging. * * @param scrollbar * The scrollbar to notify of the current mouse state. * * @param x * The X coordinate of the mouse pointer. * * @param y * The Y coordinate of the mouse pointer. * * @param mask * The button mask, where the Nth bit of the button mask represents the * pressed state of the Nth mouse button, where button 0 is the left * mouse button, button 1 is the middle button, etc. * * @return * Zero if the mouse event was not handled by the scrollbar, non-zero * otherwise. */ int guac_terminal_scrollbar_handle_mouse(guac_terminal_scrollbar* scrollbar, int x, int y, int mask); #endif guacamole-server-1.3.0/src/terminal/select.c0000644000175100001440000003611013764613616015735 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/clipboard.h" #include "terminal/buffer.h" #include "terminal/display.h" #include "terminal/select.h" #include "terminal/terminal.h" #include "terminal/types.h" #include #include #include #include /** * Returns the coordinates for the currently-selected range of text within the * given terminal, normalized such that the start coordinate is before the end * coordinate and the end coordinate takes into account character width. If no * text is currently selected, the behavior of this function is undefined. * * @param terminal * The guac_terminal instance whose selected text coordinates should be * retrieved in normalized form. * * @param start_row * A pointer to an int which should receive the row number of the first * character of text selected within the terminal, where the first * (top-most) row in the terminal is row 0. Rows within the scrollback * buffer (above the top-most row of the terminal) will be negative. * * @param start_col * A pointer to an int which should receive the column number of the first * character of text selected within terminal, where 0 is the first * (left-most) column within the row. * * @param end_row * A pointer to an int which should receive the row number of the last * character of text selected within the terminal, where the first * (top-most) row in the terminal is row 0. Rows within the scrollback * buffer (above the top-most row of the terminal) will be negative. * * @param end_col * A pointer to an int which should receive the column number of the first * character of text selected within terminal, taking into account the * width of that character, where 0 is the first (left-most) column within * the row. */ static void guac_terminal_select_normalized_range(guac_terminal* terminal, int* start_row, int* start_col, int* end_row, int* end_col) { /* Pass through start/end coordinates if they are already in the expected * order, adjusting only for final character width */ if (terminal->selection_start_row < terminal->selection_end_row || (terminal->selection_start_row == terminal->selection_end_row && terminal->selection_start_column < terminal->selection_end_column)) { *start_row = terminal->selection_start_row; *start_col = terminal->selection_start_column; *end_row = terminal->selection_end_row; *end_col = terminal->selection_end_column + terminal->selection_end_width - 1; } /* Coordinates must otherwise be swapped in addition to adjusting for * final character width */ else { *end_row = terminal->selection_start_row; *end_col = terminal->selection_start_column + terminal->selection_start_width - 1; *start_row = terminal->selection_end_row; *start_col = terminal->selection_end_column; } } void guac_terminal_select_redraw(guac_terminal* terminal) { /* Update the selected region of the display if text is currently * selected */ if (terminal->text_selected) { int start_row = terminal->selection_start_row + terminal->scroll_offset; int start_column = terminal->selection_start_column; int end_row = terminal->selection_end_row + terminal->scroll_offset; int end_column = terminal->selection_end_column; /* Update start/end columns to include character width */ if (start_row > end_row || (start_row == end_row && start_column > end_column)) start_column += terminal->selection_start_width - 1; else end_column += terminal->selection_end_width - 1; guac_terminal_display_select(terminal->display, start_row, start_column, end_row, end_column); } /* Clear the display selection if no text is currently selected */ else guac_terminal_display_clear_select(terminal->display); } /** * Locates the beginning of the character at the given row and column, updating * the column to the starting column of that character. The width, if available, * is returned. If the character has no defined width, 1 is returned. * * @param terminal * The guac_terminal in which the character should be located. * * @param row * The row number of the desired character, where the first (top-most) row * in the terminal is row 0. Rows within the scrollback buffer (above the * top-most row of the terminal) will be negative. * * @param column * A pointer to an int containing the column number of the desired * character, where 0 is the first (left-most) column within the row. If * the character is a multi-column character, the value of this int will be * adjusted as necessary such that it contains the column number of the * first column containing the character. * * @return * The width of the specified character, in columns, or 1 if the character * has no defined width. */ static int guac_terminal_find_char(guac_terminal* terminal, int row, int* column) { int start_column = *column; guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(terminal->buffer, row, 0); if (start_column < buffer_row->length) { /* Find beginning of character */ guac_terminal_char* start_char = &(buffer_row->characters[start_column]); while (start_column > 0 && start_char->value == GUAC_CHAR_CONTINUATION) { start_char--; start_column--; } /* Use width, if available */ if (start_char->value != GUAC_CHAR_CONTINUATION) { *column = start_column; return start_char->width; } } /* Default to one column wide */ return 1; } void guac_terminal_select_start(guac_terminal* terminal, int row, int column) { int width = guac_terminal_find_char(terminal, row, &column); terminal->selection_start_row = terminal->selection_end_row = row; terminal->selection_start_column = terminal->selection_end_column = column; terminal->selection_start_width = terminal->selection_end_width = width; terminal->text_selected = false; terminal->selection_committed = false; guac_terminal_notify(terminal); } void guac_terminal_select_update(guac_terminal* terminal, int row, int column) { /* Only update if selection has changed */ if (row != terminal->selection_end_row || column < terminal->selection_end_column || column >= terminal->selection_end_column + terminal->selection_end_width) { int width = guac_terminal_find_char(terminal, row, &column); terminal->selection_end_row = row; terminal->selection_end_column = column; terminal->selection_end_width = width; terminal->text_selected = true; guac_terminal_notify(terminal); } } void guac_terminal_select_resume(guac_terminal* terminal, int row, int column) { int selection_start_row; int selection_start_column; int selection_end_row; int selection_end_column; /* No need to test coordinates if no text is selected at all */ if (!terminal->text_selected) return; /* Use normalized coordinates for sake of simple comparison */ guac_terminal_select_normalized_range(terminal, &selection_start_row, &selection_start_column, &selection_end_row, &selection_end_column); /* Prefer to expand from start, such that attempting to resume a selection * within the existing selection preserves the top-most portion of the * selection */ if (row > selection_start_row || (row == selection_start_row && column > selection_start_column)) { terminal->selection_start_row = selection_start_row; terminal->selection_start_column = selection_start_column; } /* Expand from bottom-most portion of selection if doing otherwise would * reduce the size of the selection */ else { terminal->selection_start_row = selection_end_row; terminal->selection_start_column = selection_end_column; } /* Selection is again in-progress */ terminal->selection_committed = false; /* Update selection to contain given character */ guac_terminal_select_update(terminal, row, column); } /** * Appends the text within the given subsection of a terminal row to the * clipboard. The provided coordinates are considered inclusiveley (the * characters at the start and end column are included in the copied * text). Any out-of-bounds coordinates will be automatically clipped within * the bounds of the given row. * * @param terminal * The guac_terminal instance associated with the buffer containing the * text being copied and the clipboard receiving the copied text. * * @param row * The row number of the text within the terminal to be copied into the * clipboard, where the first (top-most) row in the terminal is row 0. Rows * within the scrollback buffer (above the top-most row of the terminal) * will be negative. * * @param start * The first column of the text to be copied from the given row into the * clipboard associated with the given terminal, where 0 is the first * (left-most) column within the row. * * @param end * The last column of the text to be copied from the given row into the * clipboard associated with the given terminal, where 0 is the first * (left-most) column within the row, or a negative value to denote that * the last column in the row should be used. */ static void guac_terminal_clipboard_append_row(guac_terminal* terminal, int row, int start, int end) { char buffer[1024]; int i = start; guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(terminal->buffer, row, 0); /* If selection is entirely outside the bounds of the row, then there is * nothing to append */ if (start < 0 || start > buffer_row->length - 1) return; /* Clip given range to actual bounds of row */ if (end < 0 || end > buffer_row->length - 1) end = buffer_row->length - 1; /* Repeatedly convert chunks of terminal buffer rows until entire specified * region has been appended to clipboard */ while (i <= end) { int remaining = sizeof(buffer); char* current = buffer; /* Convert as many codepoints within the given range as possible */ for (i = start; i <= end; i++) { int codepoint = buffer_row->characters[i].value; /* Ignore null (blank) characters */ if (codepoint == 0 || codepoint == GUAC_CHAR_CONTINUATION) continue; /* Encode current codepoint as UTF-8 */ int bytes = guac_utf8_write(codepoint, current, remaining); if (bytes == 0) break; current += bytes; remaining -= bytes; } /* Append converted buffer to clipboard */ guac_common_clipboard_append(terminal->clipboard, buffer, current - buffer); } } void guac_terminal_select_end(guac_terminal* terminal) { guac_client* client = terminal->client; guac_socket* socket = client->socket; /* If no text is selected, nothing to do */ if (!terminal->text_selected) return; /* Selection is now committed */ terminal->selection_committed = true; /* Reset current clipboard contents */ guac_common_clipboard_reset(terminal->clipboard, "text/plain"); int start_row, start_col; int end_row, end_col; /* Ensure proper ordering of start and end coords */ guac_terminal_select_normalized_range(terminal, &start_row, &start_col, &end_row, &end_col); /* If only one row, simply copy */ if (end_row == start_row) guac_terminal_clipboard_append_row(terminal, start_row, start_col, end_col); /* Otherwise, copy multiple rows */ else { /* Store first row */ guac_terminal_clipboard_append_row(terminal, start_row, start_col, -1); /* Store all middle rows */ for (int row = start_row + 1; row < end_row; row++) { guac_common_clipboard_append(terminal->clipboard, "\n", 1); guac_terminal_clipboard_append_row(terminal, row, 0, -1); } /* Store last row */ guac_common_clipboard_append(terminal->clipboard, "\n", 1); guac_terminal_clipboard_append_row(terminal, end_row, 0, end_col); } /* Send data */ if (!terminal->disable_copy) { guac_common_clipboard_send(terminal->clipboard, client); guac_socket_flush(socket); } guac_terminal_notify(terminal); } bool guac_terminal_select_contains(guac_terminal* terminal, int start_row, int start_column, int end_row, int end_column) { int selection_start_row; int selection_start_column; int selection_end_row; int selection_end_column; /* No need to test coordinates if no text is selected at all */ if (!terminal->text_selected) return false; /* Use normalized coordinates for sake of simple comparison */ guac_terminal_select_normalized_range(terminal, &selection_start_row, &selection_start_column, &selection_end_row, &selection_end_column); /* If test range starts after highlight ends, does not intersect */ if (start_row > selection_end_row) return false; if (start_row == selection_end_row && start_column > selection_end_column) return false; /* If test range ends before highlight starts, does not intersect */ if (end_row < selection_start_row) return false; if (end_row == selection_start_row && end_column < selection_start_column) return false; /* Otherwise, does intersect */ return true; } void guac_terminal_select_touch(guac_terminal* terminal, int start_row, int start_column, int end_row, int end_column) { /* Only clear selection if selection is committed */ if (!terminal->selection_committed) return; /* Clear selection if it contains any characters within the given region */ if (guac_terminal_select_contains(terminal, start_row, start_column, end_row, end_column)) { /* Text is no longer selected */ terminal->text_selected = false; terminal->selection_committed = false; guac_terminal_notify(terminal); } } guacamole-server-1.3.0/src/terminal/char_mappings.c0000644000175100001440000001442113613156714017264 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" const int vt100_map[] = { ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', 0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x00B0, 0x00B1, 0x2424, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA, 0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00B7, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF }; const int null_map[] = { ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0x007F, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x000A }; const int user_map[] = { ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', 0x00A7, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0x00C4, 0x00D6, 0x00DC, '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0x00E4, 0x00F6, 0x00FC, 0x00DF, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF }; guacamole-server-1.3.0/src/terminal/terminal_handlers.c0000644000175100001440000012224613764613616020157 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "terminal/char_mappings.h" #include "terminal/palette.h" #include "terminal/terminal.h" #include "terminal/terminal_handlers.h" #include "terminal/types.h" #include "terminal/xparsecolor.h" #include #include #include #include #include #include /** * Response string sent when identification is requested. */ #define GUAC_TERMINAL_VT102_ID "\x1B[?6c" /** * Arbitrary response to ENQ control character. */ #define GUAC_TERMINAL_ANSWERBACK "GUACAMOLE" /** * Response which indicates the terminal is alive. */ #define GUAC_TERMINAL_OK "\x1B[0n" /** * Advances the cursor to the next row, scrolling if the cursor would otherwise * leave the scrolling region. If the cursor is already outside the scrolling * region, the cursor is prevented from leaving the terminal bounds. * * @param term * The guac_terminal whose cursor should be advanced to the next row. */ static void guac_terminal_linefeed(guac_terminal* term) { /* Scroll up if necessary */ if (term->cursor_row == term->scroll_end) guac_terminal_scroll_up(term, term->scroll_start, term->scroll_end, 1); /* Otherwise, just advance to next row if space remains */ else if (term->cursor_row < term->term_height - 1) term->cursor_row++; } /** * Moves the cursor backward to the previous row, scrolling if the cursor would * otherwise leave the scrolling region. If the cursor is already outside the * scrolling region, the cursor is prevented from leaving the terminal bounds. * * @param term * The guac_terminal whose cursor should be moved backward by one row. */ static void guac_terminal_reverse_linefeed(guac_terminal* term) { /* Scroll down if necessary */ if (term->cursor_row == term->scroll_start) guac_terminal_scroll_down(term, term->scroll_start, term->scroll_end, 1); /* Otherwise, move back one row if space remains */ else if (term->cursor_row > 0) term->cursor_row--; } /** * Sets the position of the cursor without exceeding terminal bounds. Values * which are out of bounds will be shifted to the nearest legal boundary. * * @param term * The guac_terminal whose cursor position is being set. * * @param row * The desired new row position. * * @param col * The desired new column position. */ static void guac_terminal_move_cursor(guac_terminal* term, int row, int col) { /* Ensure cursor row is within terminal bounds */ if (row >= term->term_height) row = term->term_height - 1; else if (row < 0) row = 0; /* Ensure cursor column is within terminal bounds */ if (col >= term->term_width) col = term->term_width - 1; else if (col < 0) col = 0; /* Update cursor position */ term->cursor_row = row; term->cursor_col = col; } int guac_terminal_echo(guac_terminal* term, unsigned char c) { int width; static int bytes_remaining = 0; static int codepoint = 0; const int* char_mapping = term->char_mapping[term->active_char_set]; /* Echo to pipe stream if open and not starting an ESC sequence */ if (term->pipe_stream != NULL && c != 0x1B) { guac_terminal_pipe_stream_write(term, c); /* Do not render output while pipe is open unless explicitly requested * via flags */ if (!(term->pipe_stream_flags & GUAC_TERMINAL_PIPE_INTERPRET_OUTPUT)) return 0; } /* If using non-Unicode mapping, just map straight bytes */ if (char_mapping != NULL) { codepoint = c; bytes_remaining = 0; } /* 1-byte UTF-8 codepoint */ else if ((c & 0x80) == 0x00) { /* 0xxxxxxx */ codepoint = c & 0x7F; bytes_remaining = 0; } /* 2-byte UTF-8 codepoint */ else if ((c & 0xE0) == 0xC0) { /* 110xxxxx */ codepoint = c & 0x1F; bytes_remaining = 1; } /* 3-byte UTF-8 codepoint */ else if ((c & 0xF0) == 0xE0) { /* 1110xxxx */ codepoint = c & 0x0F; bytes_remaining = 2; } /* 4-byte UTF-8 codepoint */ else if ((c & 0xF8) == 0xF0) { /* 11110xxx */ codepoint = c & 0x07; bytes_remaining = 3; } /* Continuation of UTF-8 codepoint */ else if ((c & 0xC0) == 0x80) { /* 10xxxxxx */ codepoint = (codepoint << 6) | (c & 0x3F); bytes_remaining--; } /* Unrecognized prefix */ else { codepoint = '?'; bytes_remaining = 0; } /* If we need more bytes, wait for more bytes */ if (bytes_remaining != 0) return 0; switch (codepoint) { /* Enquiry */ case 0x05: guac_terminal_send_string(term, GUAC_TERMINAL_ANSWERBACK); break; /* Bell */ case 0x07: break; /* Backspace */ case 0x08: guac_terminal_move_cursor(term, term->cursor_row, term->cursor_col - 1); break; /* Tab */ case 0x09: guac_terminal_move_cursor(term, term->cursor_row, guac_terminal_next_tab(term, term->cursor_col)); break; /* Line feed / VT / FF */ case '\n': case 0x0B: /* VT */ case 0x0C: /* FF */ /* Advance to next row */ guac_terminal_linefeed(term); /* If automatic carriage return, fall through to CR handler */ if (!term->automatic_carriage_return) break; /* Carriage return */ case '\r': guac_terminal_move_cursor(term, term->cursor_row, 0); break; /* SO (activates character set G1) */ case 0x0E: term->active_char_set = 1; break; /* SI (activates character set G0) */ case 0x0F: term->active_char_set = 0; break; /* ESC */ case 0x1B: term->char_handler = guac_terminal_escape; break; /* CSI */ case 0x9B: term->char_handler = guac_terminal_csi; break; /* DEL (ignored) */ case 0x7F: break; /* Displayable chars */ default: /* Don't bother handling control chars if unknown */ if (codepoint < 0x20) break; /* Translate mappable codepoints to whatever codepoint is mapped */ if (codepoint >= 0x20 && codepoint <= 0xFF && char_mapping != NULL) codepoint = char_mapping[codepoint - 0x20]; /* Wrap if necessary */ if (term->cursor_col >= term->term_width) { term->cursor_col = 0; guac_terminal_linefeed(term); } /* If insert mode, shift other characters right by 1 */ if (term->insert_mode) guac_terminal_copy_columns(term, term->cursor_row, term->cursor_col, term->term_width-2, 1); /* Write character */ guac_terminal_set(term, term->cursor_row, term->cursor_col, codepoint); width = wcwidth(codepoint); if (width < 0) width = 1; /* Advance cursor */ term->cursor_col += width; } return 0; } int guac_terminal_escape(guac_terminal* term, unsigned char c) { switch (c) { case '(': term->char_handler = guac_terminal_g0_charset; break; case ')': term->char_handler = guac_terminal_g1_charset; break; case ']': term->char_handler = guac_terminal_osc; break; case '[': term->char_handler = guac_terminal_csi; break; case '#': term->char_handler = guac_terminal_ctrl_func; break; /* Save Cursor (DECSC) */ case '7': term->saved_cursor_row = term->cursor_row; term->saved_cursor_col = term->cursor_col; term->char_handler = guac_terminal_echo; break; /* Restore Cursor (DECRC) */ case '8': guac_terminal_move_cursor(term, term->saved_cursor_row, term->saved_cursor_col); term->char_handler = guac_terminal_echo; break; /* Index (IND) */ case 'D': guac_terminal_linefeed(term); term->char_handler = guac_terminal_echo; break; /* Next Line (NEL) */ case 'E': guac_terminal_move_cursor(term, term->cursor_row, 0); guac_terminal_linefeed(term); term->char_handler = guac_terminal_echo; break; /* Set Tab (HTS) */ case 'H': guac_terminal_set_tab(term, term->cursor_col); term->char_handler = guac_terminal_echo; break; /* Reverse Linefeed */ case 'M': guac_terminal_reverse_linefeed(term); term->char_handler = guac_terminal_echo; break; /* DEC Identify */ case 'Z': guac_terminal_send_string(term, GUAC_TERMINAL_VT102_ID); term->char_handler = guac_terminal_echo; break; /* Reset */ case 'c': guac_terminal_reset(term); break; case '_': term->char_handler = guac_terminal_apc; break; default: guac_client_log(term->client, GUAC_LOG_DEBUG, "Unhandled ESC sequence: %c", c); term->char_handler = guac_terminal_echo; } return 0; } /** * Given a character mapping specifier (such as B, 0, U, or K), * returns the corresponding character mapping. */ static const int* __guac_terminal_get_char_mapping(char c) { /* Translate character specifier to actual mapping */ switch (c) { case 'B': return NULL; case '0': return vt100_map; case 'U': return null_map; case 'K': return user_map; } /* Default to Unicode */ return NULL; } int guac_terminal_g0_charset(guac_terminal* term, unsigned char c) { term->char_mapping[0] = __guac_terminal_get_char_mapping(c); term->char_handler = guac_terminal_echo; return 0; } int guac_terminal_g1_charset(guac_terminal* term, unsigned char c) { term->char_mapping[1] = __guac_terminal_get_char_mapping(c); term->char_handler = guac_terminal_echo; return 0; } /** * Looks up the flag specified by the given number and mode. Used by the Set/Reset Mode * functions of the terminal. */ static bool* __guac_terminal_get_flag(guac_terminal* term, int num, char private_mode) { if (private_mode == '?') { switch (num) { case 1: return &(term->application_cursor_keys); /* DECCKM */ case 25: return &(term->cursor_visible); /* DECTECM */ } } else if (private_mode == 0) { switch (num) { case 4: return &(term->insert_mode); /* DECIM */ case 20: return &(term->automatic_carriage_return); /* LF/NL */ } } /* Unknown flag */ return NULL; } /** * Parses an xterm SGR sequence specifying the RGB values of a color. * * @param argc * The number of arguments within the argv array. * * @param argv * The SGR arguments to parse, with the first relevant argument the * red component of the RGB color. * * @param color * The guac_terminal_color structure which should receive the parsed * color values. * * @return * The number of arguments parsed, or zero if argv does not contain * enough elements to represent an RGB color. */ static int guac_terminal_parse_xterm256_rgb(int argc, const int* argv, guac_terminal_color* color) { /* RGB color palette entries require three arguments */ if (argc < 3) return 0; /* Read RGB components from arguments */ int red = argv[0]; int green = argv[1]; int blue = argv[2]; /* Ignore if components are out of range */ if ( red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) return 3; /* Store RGB components */ color->red = (uint8_t) red; color->green = (uint8_t) green; color->blue = (uint8_t) blue; /* Color is not from the palette */ color->palette_index = -1; /* Done */ return 3; } /** * Parses an xterm SGR sequence specifying the index of a color within the * 256-color palette. * * @param terminal * The terminal associated with the palette. * * @param argc * The number of arguments within the argv array. * * @param argv * The SGR arguments to parse, with the first relevant argument being * the index of the color. * * @param color * The guac_terminal_color structure which should receive the parsed * color values. * * @return * The number of arguments parsed, or zero if the palette index is * absent. */ static int guac_terminal_parse_xterm256_index(guac_terminal* terminal, int argc, const int* argv, guac_terminal_color* color) { /* 256-color palette entries require only one argument */ if (argc < 1) return 0; /* Copy palette entry */ guac_terminal_display_lookup_color(terminal->display, argv[0], color); /* Done */ return 1; } /** * Parses an xterm SGR sequence specifying the index of a color within the * 256-color palette, or specfying the RGB values of a color. The number of * arguments required by these sequences varies. If a 256-color sequence is * recognized, the number of arguments parsed is returned. * * @param terminal * The terminal whose palette state should be used when parsing the xterm * 256-color SGR sequence. * * @param argc * The number of arguments within the argv array. * * @param argv * The SGR arguments to parse, with the first relevant argument being * the first element of the array. In the case of an xterm 256-color * SGR sequence, the first element here will be either 2, for an * RGB color, or 5, for a 256-color palette index. All other values * are invalid and will not be parsed. * * @param color * The guac_terminal_color structure which should receive the parsed * color values. * * @return * The number of arguments parsed, or zero if argv does not point to * the first element of an xterm 256-color SGR sequence. */ static int guac_terminal_parse_xterm256(guac_terminal* terminal, int argc, const int* argv, guac_terminal_color* color) { /* All 256-color codes must have at least a type */ if (argc < 1) return 0; switch (argv[0]) { /* RGB */ case 2: return guac_terminal_parse_xterm256_rgb( argc - 1, &argv[1], color) + 1; /* Palette index */ case 5: return guac_terminal_parse_xterm256_index(terminal, argc - 1, &argv[1], color) + 1; } /* Invalid type */ return 0; } int guac_terminal_csi(guac_terminal* term, unsigned char c) { /* CSI function arguments */ static int argc = 0; static int argv[16] = {0}; /* Sequence prefix, if any */ static char private_mode_character = 0; /* Argument building counter and buffer */ static int argv_length = 0; static char argv_buffer[256]; /* Digits get concatenated into argv */ if (c >= '0' && c <= '9') { /* Concatenate digit if there is space in buffer */ if (argv_length < sizeof(argv_buffer)-1) argv_buffer[argv_length++] = c; } /* Specific non-digits stop the parameter, and possibly the sequence */ else if ((c >= 0x40 && c <= 0x7E) || c == ';') { int i, row, col, amount; bool* flag; /* At most 16 parameters */ if (argc < 16) { /* Finish parameter */ argv_buffer[argv_length] = 0; argv[argc++] = atoi(argv_buffer); /* Prepare for next parameter */ argv_length = 0; } /* Handle CSI functions */ switch (c) { /* @: Insert characters (scroll right) */ case '@': amount = argv[0]; if (amount == 0) amount = 1; /* Scroll right by amount */ if (term->cursor_col + amount < term->term_width) guac_terminal_copy_columns(term, term->cursor_row, term->cursor_col, term->term_width - amount - 1, amount); /* Clear left */ guac_terminal_clear_columns(term, term->cursor_row, term->cursor_col, term->cursor_col + amount - 1); break; /* A: Move up */ case 'A': /* Get move amount */ amount = argv[0]; if (amount == 0) amount = 1; /* Move cursor */ guac_terminal_move_cursor(term, term->cursor_row - amount, term->cursor_col); break; /* B: Move down */ case 'e': case 'B': /* Get move amount */ amount = argv[0]; if (amount == 0) amount = 1; /* Move cursor */ guac_terminal_move_cursor(term, term->cursor_row + amount, term->cursor_col); break; /* C: Move right */ case 'a': case 'C': /* Get move amount */ amount = argv[0]; if (amount == 0) amount = 1; /* Move cursor */ guac_terminal_move_cursor(term, term->cursor_row, term->cursor_col + amount); break; /* D: Move left */ case 'D': /* Get move amount */ amount = argv[0]; if (amount == 0) amount = 1; /* Move cursor */ guac_terminal_move_cursor(term, term->cursor_row, term->cursor_col - amount); break; /* E: Move cursor down given number rows, column 1 */ case 'E': /* Get move amount */ amount = argv[0]; if (amount == 0) amount = 1; /* Move cursor down, reset to column 1 */ guac_terminal_move_cursor(term, term->cursor_row + amount, 0); break; /* F: Move cursor up given number rows, column 1 */ case 'F': /* Get move amount */ amount = argv[0]; if (amount == 0) amount = 1; /* Move cursor up , reset to column 1 */ guac_terminal_move_cursor(term, term->cursor_row - amount, 0); break; /* G: Move cursor, current row */ case '`': case 'G': col = argv[0]; if (col != 0) col--; guac_terminal_move_cursor(term, term->cursor_row, col); break; /* H: Move cursor */ case 'f': case 'H': row = argv[0]; if (row != 0) row--; col = argv[1]; if (col != 0) col--; guac_terminal_move_cursor(term, row, col); break; /* J: Erase display */ case 'J': /* Erase from cursor to end of display */ if (argv[0] == 0) guac_terminal_clear_range(term, term->cursor_row, term->cursor_col, term->term_height-1, term->term_width-1); /* Erase from start to cursor */ else if (argv[0] == 1) guac_terminal_clear_range(term, 0, 0, term->cursor_row, term->cursor_col); /* Entire screen */ else if (argv[0] == 2 || argv[0] == 3) guac_terminal_clear_range(term, 0, 0, term->term_height - 1, term->term_width - 1); break; /* K: Erase line */ case 'K': /* Erase from cursor to end of line */ if (argv[0] == 0) guac_terminal_clear_columns(term, term->cursor_row, term->cursor_col, term->term_width - 1); /* Erase from start to cursor */ else if (argv[0] == 1) guac_terminal_clear_columns(term, term->cursor_row, 0, term->cursor_col); /* Erase line */ else if (argv[0] == 2) guac_terminal_clear_columns(term, term->cursor_row, 0, term->term_width - 1); break; /* L: Insert blank lines (scroll down) */ case 'L': amount = argv[0]; if (amount == 0) amount = 1; guac_terminal_scroll_down(term, term->cursor_row, term->scroll_end, amount); break; /* M: Delete lines (scroll up) */ case 'M': amount = argv[0]; if (amount == 0) amount = 1; guac_terminal_scroll_up(term, term->cursor_row, term->scroll_end, amount); break; /* P: Delete characters (scroll left) */ case 'P': amount = argv[0]; if (amount == 0) amount = 1; /* Scroll left by amount */ if (term->cursor_col + amount < term->term_width) guac_terminal_copy_columns(term, term->cursor_row, term->cursor_col + amount, term->term_width - 1, -amount); /* Clear right */ guac_terminal_clear_columns(term, term->cursor_row, term->term_width - amount, term->term_width - 1); break; /* X: Erase characters (no scroll) */ case 'X': amount = argv[0]; if (amount == 0) amount = 1; /* Clear characters */ guac_terminal_clear_columns(term, term->cursor_row, term->cursor_col, term->cursor_col + amount - 1); break; /* ]: Linux Private CSI */ case ']': /* Explicitly ignored */ break; /* c: Identify */ case 'c': if (argv[0] == 0 && private_mode_character == 0) guac_terminal_send_string(term, GUAC_TERMINAL_VT102_ID); break; /* d: Move cursor, current col */ case 'd': row = argv[0]; if (row != 0) row--; guac_terminal_move_cursor(term, row, term->cursor_col); break; /* g: Clear tab */ case 'g': /* Clear tab at current location */ if (argv[0] == 0) guac_terminal_unset_tab(term, term->cursor_col); /* Clear all tabs */ else if (argv[0] == 3) guac_terminal_clear_tabs(term); break; /* h: Set Mode */ case 'h': /* Look up flag and set */ flag = __guac_terminal_get_flag(term, argv[0], private_mode_character); if (flag != NULL) *flag = true; break; /* l: Reset Mode */ case 'l': /* Look up flag and clear */ flag = __guac_terminal_get_flag(term, argv[0], private_mode_character); if (flag != NULL) *flag = false; break; /* m: Set graphics rendition */ case 'm': for (i=0; icurrent_attributes = term->default_char.attributes; /* Bold */ else if (value == 1) term->current_attributes.bold = true; /* Faint (low intensity) */ else if (value == 2) term->current_attributes.half_bright = true; /* Underscore on */ else if (value == 4) term->current_attributes.underscore = true; /* Reverse video */ else if (value == 7) term->current_attributes.reverse = true; /* Normal intensity (not bold) */ else if (value == 21 || value == 22) { term->current_attributes.bold = false; term->current_attributes.half_bright = false; } /* Reset underscore */ else if (value == 24) term->current_attributes.underscore = false; /* Reset reverse video */ else if (value == 27) term->current_attributes.reverse = false; /* Foreground */ else if (value >= 30 && value <= 37) guac_terminal_display_lookup_color(term->display, value - 30, &term->current_attributes.foreground); /* Underscore on, default foreground OR 256-color * foreground */ else if (value == 38) { /* Attempt to set foreground with 256-color entry */ int xterm256_length = guac_terminal_parse_xterm256(term, argc - i - 1, &argv[i + 1], &term->current_attributes.foreground); /* If valid 256-color entry, foreground has been set */ if (xterm256_length > 0) i += xterm256_length; /* Otherwise interpret as underscore and default * foreground */ else { term->current_attributes.underscore = true; term->current_attributes.foreground = term->default_char.attributes.foreground; } } /* Underscore off, default foreground */ else if (value == 39) { term->current_attributes.underscore = false; term->current_attributes.foreground = term->default_char.attributes.foreground; } /* Background */ else if (value >= 40 && value <= 47) guac_terminal_display_lookup_color(term->display, value - 40, &term->current_attributes.background); /* 256-color background */ else if (value == 48) i += guac_terminal_parse_xterm256(term, argc - i - 1, &argv[i + 1], &term->current_attributes.background); /* Reset background */ else if (value == 49) term->current_attributes.background = term->default_char.attributes.background; /* Intense foreground */ else if (value >= 90 && value <= 97) guac_terminal_display_lookup_color(term->display, value - 90 + GUAC_TERMINAL_FIRST_INTENSE, &term->current_attributes.foreground); /* Intense background */ else if (value >= 100 && value <= 107) guac_terminal_display_lookup_color(term->display, value - 100 + GUAC_TERMINAL_FIRST_INTENSE, &term->current_attributes.background); } break; /* n: Status report */ case 'n': /* Device status report */ if (argv[0] == 5 && private_mode_character == 0) guac_terminal_send_string(term, GUAC_TERMINAL_OK); /* Cursor position report */ else if (argv[0] == 6 && private_mode_character == 0) guac_terminal_sendf(term, "\x1B[%i;%iR", term->cursor_row+1, term->cursor_col+1); break; /* q: Set keyboard LEDs */ case 'q': /* Explicitly ignored */ break; /* r: Set scrolling region */ case 'r': /* If parameters given, set region */ if (argc == 2) { term->scroll_start = argv[0]-1; term->scroll_end = argv[1]-1; } /* Otherwise, reset scrolling region */ else { term->scroll_start = 0; term->scroll_end = term->term_height - 1; } break; /* Save Cursor */ case 's': term->saved_cursor_row = term->cursor_row; term->saved_cursor_col = term->cursor_col; break; /* Restore Cursor */ case 'u': guac_terminal_move_cursor(term, term->saved_cursor_row, term->saved_cursor_col); break; /* Warn of unhandled codes */ default: if (c != ';') { guac_client_log(term->client, GUAC_LOG_DEBUG, "Unhandled CSI sequence: %c", c); for (i=0; iclient, GUAC_LOG_DEBUG, " -> argv[%i] = %i", i, argv[i]); } } /* If not a semicolon, end of CSI sequence */ if (c != ';') { term->char_handler = guac_terminal_echo; /* Reset parameters */ for (i=0; i= 0x3A && c <= 0x3F && private_mode_character == 0) private_mode_character = c; return 0; } int guac_terminal_set_directory(guac_terminal* term, unsigned char c) { static char filename[2048]; static int length = 0; /* Stop on ECMA-48 ST (String Terminator */ if (c == 0x9C || c == 0x5C || c == 0x07) { filename[length++] = '\0'; term->char_handler = guac_terminal_echo; if (term->upload_path_handler) term->upload_path_handler(term->client, filename); else guac_client_log(term->client, GUAC_LOG_DEBUG, "Cannot set upload path. File transfer is not enabled."); length = 0; } /* Otherwise, store character */ else if (length < sizeof(filename)-1) filename[length++] = c; return 0; } int guac_terminal_download(guac_terminal* term, unsigned char c) { static char filename[2048]; static int length = 0; /* Stop on ECMA-48 ST (String Terminator */ if (c == 0x9C || c == 0x5C || c == 0x07) { filename[length++] = '\0'; term->char_handler = guac_terminal_echo; if (term->file_download_handler) term->file_download_handler(term->client, filename); else guac_client_log(term->client, GUAC_LOG_DEBUG, "Cannot send file. File transfer is not enabled."); length = 0; } /* Otherwise, store character */ else if (length < sizeof(filename)-1) filename[length++] = c; return 0; } int guac_terminal_open_pipe_stream(guac_terminal* term, unsigned char c) { static char param[2048]; static int length = 0; static int flags = 0; /* Open pipe on ECMA-48 ST (String Terminator) */ if (c == 0x9C || c == 0x5C || c == 0x07) { /* End parameter string */ param[length++] = '\0'; length = 0; /* Open new pipe stream using final parameter as name */ guac_terminal_pipe_stream_open(term, param, flags); /* Return to echo mode */ term->char_handler = guac_terminal_echo; /* Reset tracked flags for sake of any future pipe streams */ flags = 0; } /* Interpret all parameters prior to the final parameter as integer * flags which should affect the pipe stream when opened */ else if (c == ';') { /* End parameter string */ param[length++] = '\0'; length = 0; /* Parse parameter string as integer flags */ flags |= atoi(param); } /* Otherwise, store character within parameter */ else if (length < sizeof(param)-1) param[length++] = c; return 0; } int guac_terminal_close_pipe_stream(guac_terminal* term, unsigned char c) { /* Handle closure on ECMA-48 ST (String Terminator) */ if (c == 0x9C || c == 0x5C || c == 0x07) { /* Close any existing pipe */ guac_terminal_pipe_stream_close(term); /* Return to echo mode */ term->char_handler = guac_terminal_echo; } /* Ignore all other characters */ return 0; } int guac_terminal_set_scrollback(guac_terminal* term, unsigned char c) { static char param[16]; static int length = 0; /* Open pipe on ECMA-48 ST (String Terminator) */ if (c == 0x9C || c == 0x5C || c == 0x07) { /* End parameter string */ param[length++] = '\0'; length = 0; /* Assign scrollback size */ term->requested_scrollback = atoi(param); /* Update scrollbar bounds */ guac_terminal_scrollbar_set_bounds(term->scrollbar, -guac_terminal_available_scroll(term), 0); /* Return to echo mode */ term->char_handler = guac_terminal_echo; } /* Otherwise, store character within parameter */ else if (length < sizeof(param) - 1) param[length++] = c; return 0; } int guac_terminal_window_title(guac_terminal* term, unsigned char c) { static int position = 0; static char title[4096]; guac_socket* socket = term->client->socket; /* Stop on ECMA-48 ST (String Terminator */ if (c == 0x9C || c == 0x5C || c == 0x07) { /* Terminate and reset stored title */ title[position] = '\0'; position = 0; /* Send title as connection name */ guac_protocol_send_name(socket, title); guac_socket_flush(socket); term->char_handler = guac_terminal_echo; } /* Store all other characters within title, space permitting */ else if (position < sizeof(title) - 1) title[position++] = (char) c; return 0; } int guac_terminal_xterm_palette(guac_terminal* term, unsigned char c) { /** * Whether we are currently reading the color spec. If false, we are * currently reading the color index. */ static bool read_color_spec = false; /** * The index of the palette entry being modified. */ static int index = 0; /** * The color spec string, valid only if read_color_spec is true. */ static char color_spec[256]; /** * The current position within the color spec string, valid only if * read_color_spec is true. */ static int color_spec_pos = 0; /* If not reading the color spec, parse the index */ if (!read_color_spec) { /* If digit, append to index */ if (c >= '0' && c <= '9') index = index * 10 + c - '0'; /* If end of parameter, switch to reading the color */ else if (c == ';') { read_color_spec = true; color_spec_pos = 0; } } /* Once the index has been parsed, read the color spec */ else { /* Modify palette once index/spec pair has been read */ if (c == ';' || c == 0x9C || c == 0x5C || c == 0x07) { guac_terminal_color color; /* Terminate color spec string */ color_spec[color_spec_pos] = '\0'; /* Modify palette if color spec is valid */ if (!guac_terminal_xparsecolor(color_spec, &color)) guac_terminal_display_assign_color(term->display, index, &color); else guac_client_log(term->client, GUAC_LOG_DEBUG, "Invalid XParseColor() color spec: \"%s\"", color_spec); /* Resume parsing index */ read_color_spec = false; index = 0; } /* Append characters to color spec as long as available space is not * exceeded */ else if (color_spec_pos < 255) { color_spec[color_spec_pos++] = c; } } /* Stop on ECMA-48 ST (String Terminator */ if (c == 0x9C || c == 0x5C || c == 0x07) term->char_handler = guac_terminal_echo; return 0; } int guac_terminal_osc(guac_terminal* term, unsigned char c) { static int operation = 0; /* If digit, append to operation */ if (c >= '0' && c <= '9') operation = operation * 10 + c - '0'; /* If end of parameter, check value */ else if (c == ';') { /* Download OSC */ if (operation == 482200) term->char_handler = guac_terminal_download; /* Set upload directory OSC */ else if (operation == 482201) term->char_handler = guac_terminal_set_directory; /* Open and redirect output to pipe stream OSC */ else if (operation == 482202) term->char_handler = guac_terminal_open_pipe_stream; /* Close pipe stream OSC */ else if (operation == 482203) term->char_handler = guac_terminal_close_pipe_stream; /* Set scrollback size OSC */ else if (operation == 482204) term->char_handler = guac_terminal_set_scrollback; /* Set window title OSC */ else if (operation == 0 || operation == 2) term->char_handler = guac_terminal_window_title; /* xterm 256-color palette redefinition */ else if (operation == 4) term->char_handler = guac_terminal_xterm_palette; /* Reset parameter for next OSC */ operation = 0; } /* Stop on ECMA-48 ST (String Terminator */ else if (c == 0x9C || c == 0x5C || c == 0x07) term->char_handler = guac_terminal_echo; /* Stop on unrecognized character */ else { guac_client_log(term->client, GUAC_LOG_DEBUG, "Unexpected character in OSC: 0x%X", c); term->char_handler = guac_terminal_echo; } return 0; } int guac_terminal_ctrl_func(guac_terminal* term, unsigned char c) { int row; /* Build character with current attributes */ guac_terminal_char guac_char; guac_char.value = 'E'; guac_char.attributes = term->current_attributes; switch (c) { /* Alignment test (fill screen with E's) */ case '8': for (row=0; rowterm_height; row++) guac_terminal_set_columns(term, row, 0, term->term_width-1, &guac_char); break; } term->char_handler = guac_terminal_echo; return 0; } int guac_terminal_apc(guac_terminal* term, unsigned char c) { /* xterm does not implement APC functions and neither do we. Look for the * "ESC \" (string terminator) sequence, while ignoring other chars. */ static bool escaping = false; if (escaping) { if (c == '\\') term->char_handler = guac_terminal_echo; escaping = false; } if (c == 0x1B) escaping = true; return 0; } guacamole-server-1.3.0/src/terminal/Makefile.am0000644000175100001440000000522213702142276016335 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 noinst_LTLIBRARIES = libguac_terminal.la noinst_HEADERS = \ terminal/buffer.h \ terminal/char_mappings.h \ terminal/common.h \ terminal/color-scheme.h \ terminal/display.h \ terminal/named-colors.h \ terminal/palette.h \ terminal/scrollbar.h \ terminal/select.h \ terminal/terminal.h \ terminal/terminal_handlers.h \ terminal/types.h \ terminal/typescript.h \ terminal/xparsecolor.h libguac_terminal_la_SOURCES = \ buffer.c \ char_mappings.c \ color-scheme.c \ common.c \ display.c \ named-colors.c \ palette.c \ scrollbar.c \ select.c \ terminal.c \ terminal_handlers.c \ terminal-stdin-stream.c \ typescript.c \ xparsecolor.c libguac_terminal_la_CFLAGS = \ -Werror -Wall \ @COMMON_INCLUDE@ \ @LIBGUAC_INCLUDE@ \ @PANGO_CFLAGS@ \ @PANGOCAIRO_CFLAGS@ libguac_terminal_la_LIBADD = \ @LIBGUAC_LTLIB@ libguac_terminal_la_LDFLAGS = \ @CAIRO_LIBS@ \ @MATH_LIBS@ \ @PANGO_LIBS@ \ @PANGOCAIRO_LIBS@ \ @PTHREAD_LIBS@ guacamole-server-1.3.0/src/terminal/buffer.c0000644000175100001440000001432613702142276015723 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "terminal/buffer.h" #include "terminal/common.h" #include #include guac_terminal_buffer* guac_terminal_buffer_alloc(int rows, guac_terminal_char* default_character) { /* Allocate scrollback */ guac_terminal_buffer* buffer = malloc(sizeof(guac_terminal_buffer)); int i; guac_terminal_buffer_row* row; /* Init scrollback data */ buffer->default_character = *default_character; buffer->available = rows; buffer->top = 0; buffer->length = 0; buffer->rows = malloc(sizeof(guac_terminal_buffer_row) * buffer->available); /* Init scrollback rows */ row = buffer->rows; for (i=0; iavailable = 256; row->length = 0; row->characters = malloc(sizeof(guac_terminal_char) * row->available); /* Next row */ row++; } return buffer; } void guac_terminal_buffer_free(guac_terminal_buffer* buffer) { int i; guac_terminal_buffer_row* row = buffer->rows; /* Free all rows */ for (i=0; iavailable; i++) { free(row->characters); row++; } /* Free actual buffer */ free(buffer->rows); free(buffer); } guac_terminal_buffer_row* guac_terminal_buffer_get_row(guac_terminal_buffer* buffer, int row, int width) { int i; guac_terminal_char* first; guac_terminal_buffer_row* buffer_row; /* Normalize row index into a scrollback buffer index */ int index = (buffer->top + row) % buffer->available; if (index < 0) index += buffer->available; /* Get row */ buffer_row = &(buffer->rows[index]); /* If resizing is needed */ if (width >= buffer_row->length) { /* Expand if necessary */ if (width > buffer_row->available) { buffer_row->available = width*2; buffer_row->characters = realloc(buffer_row->characters, sizeof(guac_terminal_char) * buffer_row->available); } /* Initialize new part of row */ first = &(buffer_row->characters[buffer_row->length]); for (i=buffer_row->length; idefault_character; buffer_row->length = width; } /* Return found row */ return buffer_row; } void guac_terminal_buffer_copy_columns(guac_terminal_buffer* buffer, int row, int start_column, int end_column, int offset) { guac_terminal_char* src; guac_terminal_char* dst; /* Get row */ guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(buffer, row, end_column + offset + 1); /* Fit range within bounds */ start_column = guac_terminal_fit_to_range(start_column, 0, buffer_row->length - 1); end_column = guac_terminal_fit_to_range(end_column, 0, buffer_row->length - 1); start_column = guac_terminal_fit_to_range(start_column + offset, 0, buffer_row->length - 1) - offset; end_column = guac_terminal_fit_to_range(end_column + offset, 0, buffer_row->length - 1) - offset; /* Determine source and destination locations */ src = &(buffer_row->characters[start_column]); dst = &(buffer_row->characters[start_column + offset]); /* Copy data */ memmove(dst, src, sizeof(guac_terminal_char) * (end_column - start_column + 1)); } void guac_terminal_buffer_copy_rows(guac_terminal_buffer* buffer, int start_row, int end_row, int offset) { int i, current_row; int step; /* If shifting down, copy in reverse */ if (offset > 0) { current_row = end_row; step = -1; } /* Otherwise, copy forwards */ else { current_row = start_row; step = 1; } /* Copy each current_row individually */ for (i = start_row; i <= end_row; i++) { /* Get source and destination rows */ guac_terminal_buffer_row* src_row = guac_terminal_buffer_get_row(buffer, current_row, 0); guac_terminal_buffer_row* dst_row = guac_terminal_buffer_get_row(buffer, current_row + offset, src_row->length); /* Copy data */ memcpy(dst_row->characters, src_row->characters, sizeof(guac_terminal_char) * src_row->length); dst_row->length = src_row->length; /* Next current_row */ current_row += step; } } void guac_terminal_buffer_set_columns(guac_terminal_buffer* buffer, int row, int start_column, int end_column, guac_terminal_char* character) { int i, j; guac_terminal_char* current; /* Do nothing if glyph is empty */ if (character->width == 0) return; /* Build continuation char (for multicolumn characters) */ guac_terminal_char continuation_char; continuation_char.value = GUAC_CHAR_CONTINUATION; continuation_char.attributes = character->attributes; continuation_char.width = 0; /* Not applicable for GUAC_CHAR_CONTINUATION */ /* Get and expand row */ guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(buffer, row, end_column+1); /* Set values */ current = &(buffer_row->characters[start_column]); for (i = start_column; i <= end_column; i += character->width) { *(current++) = *character; /* Store any required continuation characters */ for (j=1; j < character->width; j++) *(current++) = continuation_char; } /* Update length depending on row written */ if (character->value != 0 && row >= buffer->length) buffer->length = row+1; } guacamole-server-1.3.0/src/common/0000755000175100001440000000000013772471155014045 500000000000000guacamole-server-1.3.0/src/common/iconv.c0000644000175100001440000001116013613156714015241 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/iconv.h" #include #include /** * Lookup table for Unicode code points, indexed by CP-1252 codepoint. */ const static int __GUAC_RDP_CP1252_CODEPOINT[32] = { 0x20AC, /* 0x80 */ 0xFFFD, /* 0x81 */ 0x201A, /* 0x82 */ 0x0192, /* 0x83 */ 0x201E, /* 0x84 */ 0x2026, /* 0x85 */ 0x2020, /* 0x86 */ 0x2021, /* 0x87 */ 0x02C6, /* 0x88 */ 0x2030, /* 0x89 */ 0x0160, /* 0x8A */ 0x2039, /* 0x8B */ 0x0152, /* 0x8C */ 0xFFFD, /* 0x8D */ 0x017D, /* 0x8E */ 0xFFFD, /* 0x8F */ 0xFFFD, /* 0x90 */ 0x2018, /* 0x91 */ 0x2019, /* 0x92 */ 0x201C, /* 0x93 */ 0x201D, /* 0x94 */ 0x2022, /* 0x95 */ 0x2013, /* 0x96 */ 0x2014, /* 0x97 */ 0x02DC, /* 0x98 */ 0x2122, /* 0x99 */ 0x0161, /* 0x9A */ 0x203A, /* 0x9B */ 0x0153, /* 0x9C */ 0xFFFD, /* 0x9D */ 0x017E, /* 0x9E */ 0x0178, /* 0x9F */ }; int guac_iconv(guac_iconv_read* reader, const char** input, int in_remaining, guac_iconv_write* writer, char** output, int out_remaining) { while (in_remaining > 0 && out_remaining > 0) { int value; const char* read_start; char* write_start; /* Read character */ read_start = *input; value = reader(input, in_remaining); in_remaining -= *input - read_start; /* Write character */ write_start = *output; writer(output, out_remaining, value); out_remaining -= *output - write_start; /* Stop if null terminator reached */ if (value == 0) return 1; } /* Null terminator not reached */ return 0; } int GUAC_READ_UTF8(const char** input, int remaining) { int value; *input += guac_utf8_read(*input, remaining, &value); return value; } int GUAC_READ_UTF16(const char** input, int remaining) { int value; /* Bail if not enough data */ if (remaining < 2) return 0; /* Read two bytes as integer */ value = *((uint16_t*) *input); *input += 2; return value; } int GUAC_READ_CP1252(const char** input, int remaining) { int value = *((unsigned char*) *input); /* Replace value with exception if not identical to ISO-8859-1 */ if (value >= 0x80 && value <= 0x9F) value = __GUAC_RDP_CP1252_CODEPOINT[value - 0x80]; (*input)++; return value; } int GUAC_READ_ISO8859_1(const char** input, int remaining) { int value = *((unsigned char*) *input); (*input)++; return value; } void GUAC_WRITE_UTF8(char** output, int remaining, int value) { *output += guac_utf8_write(value, *output, remaining); } void GUAC_WRITE_UTF16(char** output, int remaining, int value) { /* Bail if not enough data */ if (remaining < 2) return; /* Write two bytes as integer */ *((uint16_t*) *output) = value; *output += 2; } void GUAC_WRITE_CP1252(char** output, int remaining, int value) { /* If not in ISO-8859-1 part of CP1252, check lookup table */ if ((value >= 0x80 && value <= 0x9F) || value > 0xFF) { int i; int replacement_value = '?'; const int* codepoint = __GUAC_RDP_CP1252_CODEPOINT; /* Search lookup table for value */ for (i=0x80; i<=0x9F; i++, codepoint++) { if (*codepoint == value) { replacement_value = i; break; } } /* Replace value with discovered value (or question mark) */ value = replacement_value; } *((unsigned char*) *output) = (unsigned char) value; (*output)++; } void GUAC_WRITE_ISO8859_1(char** output, int remaining, int value) { /* Translate to question mark if out of range */ if (value > 0xFF) value = '?'; *((unsigned char*) *output) = (unsigned char) value; (*output)++; } guacamole-server-1.3.0/src/common/clipboard.c0000644000175100001440000001116413770536337016075 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/clipboard.h" #include #include #include #include #include #include #include #include guac_common_clipboard* guac_common_clipboard_alloc(int size) { guac_common_clipboard* clipboard = malloc(sizeof(guac_common_clipboard)); /* Init clipboard */ clipboard->mimetype[0] = '\0'; clipboard->buffer = malloc(size); clipboard->length = 0; clipboard->available = size; pthread_mutex_init(&(clipboard->lock), NULL); return clipboard; } void guac_common_clipboard_free(guac_common_clipboard* clipboard) { /* Destroy lock */ pthread_mutex_destroy(&(clipboard->lock)); /* Free buffer */ free(clipboard->buffer); /* Free base structure */ free(clipboard); } /** * Callback for guac_client_foreach_user() which sends clipboard data to each * connected client. * * @param user * The user to send the clipboard data to. * * @param * A pointer to the guac_common_clipboard structure containing the * clipboard data that should be sent to the given user. * * @return * Always NULL. */ static void* __send_user_clipboard(guac_user* user, void* data) { guac_common_clipboard* clipboard = (guac_common_clipboard*) data; char* current = clipboard->buffer; int remaining = clipboard->length; /* Begin stream */ guac_stream* stream = guac_user_alloc_stream(user); guac_protocol_send_clipboard(user->socket, stream, clipboard->mimetype); guac_user_log(user, GUAC_LOG_DEBUG, "Created stream %i for %s clipboard data.", stream->index, clipboard->mimetype); /* Split clipboard into chunks */ while (remaining > 0) { /* Calculate size of next block */ int block_size = GUAC_COMMON_CLIPBOARD_BLOCK_SIZE; if (remaining < block_size) block_size = remaining; /* Send block */ guac_protocol_send_blob(user->socket, stream, current, block_size); guac_user_log(user, GUAC_LOG_DEBUG, "Sent %i bytes of clipboard data on stream %i.", block_size, stream->index); /* Next block */ remaining -= block_size; current += block_size; } guac_user_log(user, GUAC_LOG_DEBUG, "Clipboard stream %i complete.", stream->index); /* End stream */ guac_protocol_send_end(user->socket, stream); guac_user_free_stream(user, stream); return NULL; } void guac_common_clipboard_send(guac_common_clipboard* clipboard, guac_client* client) { pthread_mutex_lock(&(clipboard->lock)); guac_client_log(client, GUAC_LOG_DEBUG, "Broadcasting clipboard to all connected users."); guac_client_foreach_user(client, __send_user_clipboard, clipboard); guac_client_log(client, GUAC_LOG_DEBUG, "Broadcast of clipboard complete."); pthread_mutex_unlock(&(clipboard->lock)); } void guac_common_clipboard_reset(guac_common_clipboard* clipboard, const char* mimetype) { pthread_mutex_lock(&(clipboard->lock)); /* Clear clipboard contents */ clipboard->length = 0; /* Assign given mimetype */ guac_strlcpy(clipboard->mimetype, mimetype, sizeof(clipboard->mimetype)); pthread_mutex_unlock(&(clipboard->lock)); } void guac_common_clipboard_append(guac_common_clipboard* clipboard, const char* data, int length) { pthread_mutex_lock(&(clipboard->lock)); /* Truncate data to available length */ int remaining = clipboard->available - clipboard->length; if (remaining < length) length = remaining; /* Append to buffer */ memcpy(clipboard->buffer + clipboard->length, data, length); /* Update length */ clipboard->length += length; pthread_mutex_unlock(&(clipboard->lock)); } guacamole-server-1.3.0/src/common/blank_cursor.c0000644000175100001440000000447413613156714016621 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include #include #include #include #include #include /* Dimensions */ const int guac_common_blank_cursor_width = 1; const int guac_common_blank_cursor_height = 1; /* Format */ const cairo_format_t guac_common_blank_cursor_format = CAIRO_FORMAT_ARGB32; const int guac_common_blank_cursor_stride = 4; /* Embedded blank cursor graphic */ unsigned char guac_common_blank_cursor[] = { 0x00,0x00,0x00,0x00 }; void guac_common_set_blank_cursor(guac_user* user) { guac_client* client = user->client; guac_socket* socket = user->socket; /* Draw to buffer */ guac_layer* cursor = guac_client_alloc_buffer(client); cairo_surface_t* graphic = cairo_image_surface_create_for_data( guac_common_blank_cursor, guac_common_blank_cursor_format, guac_common_blank_cursor_width, guac_common_blank_cursor_height, guac_common_blank_cursor_stride); guac_user_stream_png(user, socket, GUAC_COMP_SRC, cursor, 0, 0, graphic); cairo_surface_destroy(graphic); /* Set cursor */ guac_protocol_send_cursor(socket, 0, 0, cursor, 0, 0, guac_common_blank_cursor_width, guac_common_blank_cursor_height); /* Free buffer */ guac_client_free_buffer(client, cursor); guac_client_log(client, GUAC_LOG_DEBUG, "Client cursor image set to generic transparent (blank) cursor."); } guacamole-server-1.3.0/src/common/dot_cursor.c0000644000175100001440000000475713613156714016324 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include #include #include #include #include #include /* Macros for prettying up the embedded image. */ #define X 0x00,0x00,0x00,0xFF #define O 0xFF,0xFF,0xFF,0xFF #define _ 0x00,0x00,0x00,0x00 /* Dimensions */ const int guac_common_dot_cursor_width = 5; const int guac_common_dot_cursor_height = 5; /* Format */ const cairo_format_t guac_common_dot_cursor_format = CAIRO_FORMAT_ARGB32; const int guac_common_dot_cursor_stride = 20; /* Embedded pointer graphic */ unsigned char guac_common_dot_cursor[] = { _,O,O,O,_, O,X,X,X,O, O,X,X,X,O, O,X,X,X,O, _,O,O,O,_ }; void guac_common_set_dot_cursor(guac_user* user) { guac_client* client = user->client; guac_socket* socket = user->socket; /* Draw to buffer */ guac_layer* cursor = guac_client_alloc_buffer(client); cairo_surface_t* graphic = cairo_image_surface_create_for_data( guac_common_dot_cursor, guac_common_dot_cursor_format, guac_common_dot_cursor_width, guac_common_dot_cursor_height, guac_common_dot_cursor_stride); guac_user_stream_png(user, socket, GUAC_COMP_SRC, cursor, 0, 0, graphic); cairo_surface_destroy(graphic); /* Set cursor */ guac_protocol_send_cursor(socket, 2, 2, cursor, 0, 0, guac_common_dot_cursor_width, guac_common_dot_cursor_height); /* Free buffer */ guac_client_free_buffer(client, cursor); guac_client_log(client, GUAC_LOG_DEBUG, "Client cursor image set to generic built-in dot."); } guacamole-server-1.3.0/src/common/pointer_cursor.c0000644000175100001440000000567213613156714017213 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include #include #include #include #include #include /* Macros for prettying up the embedded image. */ #define X 0x00,0x00,0x00,0xFF #define O 0xFF,0xFF,0xFF,0xFF #define _ 0x00,0x00,0x00,0x00 /* Dimensions */ const int guac_common_pointer_cursor_width = 11; const int guac_common_pointer_cursor_height = 16; /* Format */ const cairo_format_t guac_common_pointer_cursor_format = CAIRO_FORMAT_ARGB32; const int guac_common_pointer_cursor_stride = 44; /* Embedded pointer graphic */ unsigned char guac_common_pointer_cursor[] = { O,_,_,_,_,_,_,_,_,_,_, O,O,_,_,_,_,_,_,_,_,_, O,X,O,_,_,_,_,_,_,_,_, O,X,X,O,_,_,_,_,_,_,_, O,X,X,X,O,_,_,_,_,_,_, O,X,X,X,X,O,_,_,_,_,_, O,X,X,X,X,X,O,_,_,_,_, O,X,X,X,X,X,X,O,_,_,_, O,X,X,X,X,X,X,X,O,_,_, O,X,X,X,X,X,X,X,X,O,_, O,X,X,X,X,X,O,O,O,O,O, O,X,X,O,X,X,O,_,_,_,_, O,X,O,_,O,X,X,O,_,_,_, O,O,_,_,O,X,X,O,_,_,_, O,_,_,_,_,O,X,X,O,_,_, _,_,_,_,_,O,O,O,O,_,_ }; void guac_common_set_pointer_cursor(guac_user* user) { guac_client* client = user->client; guac_socket* socket = user->socket; /* Draw to buffer */ guac_layer* cursor = guac_client_alloc_buffer(client); cairo_surface_t* graphic = cairo_image_surface_create_for_data( guac_common_pointer_cursor, guac_common_pointer_cursor_format, guac_common_pointer_cursor_width, guac_common_pointer_cursor_height, guac_common_pointer_cursor_stride); guac_user_stream_png(user, socket, GUAC_COMP_SRC, cursor, 0, 0, graphic); cairo_surface_destroy(graphic); /* Set cursor */ guac_protocol_send_cursor(socket, 0, 0, cursor, 0, 0, guac_common_pointer_cursor_width, guac_common_pointer_cursor_height); /* Free buffer */ guac_client_free_buffer(client, cursor); guac_client_log(client, GUAC_LOG_DEBUG, "Client cursor image set to generic built-in pointer."); } guacamole-server-1.3.0/src/common/display.c0000644000175100001440000002462313676434704015607 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/cursor.h" #include "common/display.h" #include "common/surface.h" #include #include #include #include #include /** * Synchronizes all surfaces within the given linked list to the given socket. * If the provided pointer to the linked list is NULL, this function has no * effect. * * @param layers * The head element of the linked list of layers to synchronize, which may * be NULL if the list is currently empty. * * @param user * The user receiving the layers. * * @param socket * The socket over which each layer should be sent. */ static void guac_common_display_dup_layers(guac_common_display_layer* layers, guac_user* user, guac_socket* socket) { guac_common_display_layer* current = layers; /* Synchronize all surfaces in given list */ while (current != NULL) { guac_common_surface_dup(current->surface, user, socket); current = current->next; } } /** * Frees all layers and associated surfaces within the given list, as well as * their corresponding list elements. If the provided pointer to the linked * list is NULL, this function has no effect. * * @param layers * The head element of the linked list of layers to free, which may be NULL * if the list is currently empty. * * @param client * The client owning the layers wrapped by each of the layers in the list. */ static void guac_common_display_free_layers(guac_common_display_layer* layers, guac_client* client) { guac_common_display_layer* current = layers; /* Free each surface in given list */ while (current != NULL) { guac_common_display_layer* next = current->next; guac_layer* layer = current->layer; /* Free surface */ guac_common_surface_free(current->surface); /* Destroy layer within remotely-connected client */ guac_protocol_send_dispose(client->socket, layer); /* Free layer or buffer depending on index */ if (layer->index < 0) guac_client_free_buffer(client, layer); else if (layer->index > 0) guac_client_free_layer(client, layer); /* Free current element and advance to next */ free(current); current = next; } } /** * Allocates a display and a cursor which are used to represent the remote * display and cursor. * * @param client * The client owning the cursor. * * @param width * The desired width of the display. * * @param height * The desired height of the display. * * @return * The newly-allocated display or NULL if display cannot be allocated. */ guac_common_display* guac_common_display_alloc(guac_client* client, int width, int height) { /* Allocate display */ guac_common_display* display = malloc(sizeof(guac_common_display)); if (display == NULL) return NULL; /* Allocate shared cursor */ display->cursor = guac_common_cursor_alloc(client); if (display->cursor == NULL) { free(display); return NULL; } pthread_mutex_init(&display->_lock, NULL); /* Associate display with given client */ display->client = client; display->default_surface = guac_common_surface_alloc(client, client->socket, GUAC_DEFAULT_LAYER, width, height); /* No initial layers or buffers */ display->layers = NULL; display->buffers = NULL; return display; } void guac_common_display_free(guac_common_display* display) { /* Free shared cursor */ guac_common_cursor_free(display->cursor); /* Free default surface */ guac_common_surface_free(display->default_surface); /* Free all layers and buffers */ guac_common_display_free_layers(display->buffers, display->client); guac_common_display_free_layers(display->layers, display->client); pthread_mutex_destroy(&display->_lock); free(display); } void guac_common_display_dup(guac_common_display* display, guac_user* user, guac_socket* socket) { pthread_mutex_lock(&display->_lock); /* Sunchronize shared cursor */ guac_common_cursor_dup(display->cursor, user, socket); /* Synchronize default surface */ guac_common_surface_dup(display->default_surface, user, socket); /* Synchronize all layers and buffers */ guac_common_display_dup_layers(display->layers, user, socket); guac_common_display_dup_layers(display->buffers, user, socket); pthread_mutex_unlock(&display->_lock); } void guac_common_display_flush(guac_common_display* display) { pthread_mutex_lock(&display->_lock); guac_common_display_layer* current = display->layers; /* Flush all surfaces */ while (current != NULL) { guac_common_surface_flush(current->surface); current = current->next; } guac_common_surface_flush(display->default_surface); pthread_mutex_unlock(&display->_lock); } /** * Allocates and inserts a new element into the given linked list of display * layers, associating it with the given layer and surface. * * @param head * A pointer to the head pointer of the list of layers. The head pointer * will be updated by this function to point to the newly-allocated * display layer. * * @param layer * The Guacamole layer to associated with the new display layer. * * @param surface * The surface associated with the given Guacamole layer and which should * be associated with the new display layer. * * @return * The newly-allocated display layer, which has been associated with the * provided layer and surface. */ static guac_common_display_layer* guac_common_display_add_layer( guac_common_display_layer** head, guac_layer* layer, guac_common_surface* surface) { guac_common_display_layer* old_head = *head; guac_common_display_layer* display_layer = malloc(sizeof(guac_common_display_layer)); /* Init layer/surface pair */ display_layer->layer = layer; display_layer->surface = surface; /* Insert list element as the new head */ display_layer->prev = NULL; display_layer->next = old_head; *head = display_layer; /* Update old head to point to new element, if it existed */ if (old_head != NULL) old_head->prev = display_layer; return display_layer; } /** * Removes the given display layer from the linked list whose head pointer is * provided. * * @param head * A pointer to the head pointer of the list of layers. The head pointer * will be updated by this function if necessary, and will be set to NULL * if the display layer being removed is the only layer in the list. * * @param display_layer * The display layer to remove from the given list. */ static void guac_common_display_remove_layer(guac_common_display_layer** head, guac_common_display_layer* display_layer) { /* Update previous element, if it exists */ if (display_layer->prev != NULL) display_layer->prev->next = display_layer->next; /* If there is no previous element, update the list head */ else *head = display_layer->next; /* Update next element, if it exists */ if (display_layer->next != NULL) display_layer->next->prev = display_layer->prev; } guac_common_display_layer* guac_common_display_alloc_layer( guac_common_display* display, int width, int height) { pthread_mutex_lock(&display->_lock); /* Allocate Guacamole layer */ guac_layer* layer = guac_client_alloc_layer(display->client); /* Allocate corresponding surface */ guac_common_surface* surface = guac_common_surface_alloc(display->client, display->client->socket, layer, width, height); /* Add layer and surface to list */ guac_common_display_layer* display_layer = guac_common_display_add_layer(&display->layers, layer, surface); pthread_mutex_unlock(&display->_lock); return display_layer; } guac_common_display_layer* guac_common_display_alloc_buffer( guac_common_display* display, int width, int height) { pthread_mutex_lock(&display->_lock); /* Allocate Guacamole buffer */ guac_layer* buffer = guac_client_alloc_buffer(display->client); /* Allocate corresponding surface */ guac_common_surface* surface = guac_common_surface_alloc(display->client, display->client->socket, buffer, width, height); /* Add buffer and surface to list */ guac_common_display_layer* display_layer = guac_common_display_add_layer(&display->buffers, buffer, surface); pthread_mutex_unlock(&display->_lock); return display_layer; } void guac_common_display_free_layer(guac_common_display* display, guac_common_display_layer* display_layer) { pthread_mutex_lock(&display->_lock); /* Remove list element from list */ guac_common_display_remove_layer(&display->layers, display_layer); /* Free associated layer and surface */ guac_common_surface_free(display_layer->surface); guac_client_free_layer(display->client, display_layer->layer); /* Free list element */ free(display_layer); pthread_mutex_unlock(&display->_lock); } void guac_common_display_free_buffer(guac_common_display* display, guac_common_display_layer* display_buffer) { pthread_mutex_lock(&display->_lock); /* Remove list element from list */ guac_common_display_remove_layer(&display->buffers, display_buffer); /* Free associated layer and surface */ guac_common_surface_free(display_buffer->surface); guac_client_free_buffer(display->client, display_buffer->layer); /* Free list element */ free(display_buffer); pthread_mutex_unlock(&display->_lock); } guacamole-server-1.3.0/src/common/rect.c0000644000175100001440000001715713613156714015074 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/rect.h" void guac_common_rect_init(guac_common_rect* rect, int x, int y, int width, int height) { rect->x = x; rect->y = y; rect->width = width; rect->height = height; } void guac_common_rect_extend(guac_common_rect* rect, const guac_common_rect* min) { /* Calculate extents of existing dirty rect */ int left = rect->x; int top = rect->y; int right = left + rect->width; int bottom = top + rect->height; /* Calculate missing extents of given new rect */ int min_left = min->x; int min_top = min->y; int min_right = min_left + min->width; int min_bottom = min_top + min->height; /* Update minimums */ if (min_left < left) left = min_left; if (min_top < top) top = min_top; if (min_right > right) right = min_right; if (min_bottom > bottom) bottom = min_bottom; /* Commit rect */ guac_common_rect_init(rect, left, top, right - left, bottom - top); } void guac_common_rect_constrain(guac_common_rect* rect, const guac_common_rect* max) { /* Calculate extents of existing dirty rect */ int left = rect->x; int top = rect->y; int right = left + rect->width; int bottom = top + rect->height; /* Calculate missing extents of given new rect */ int max_left = max->x; int max_top = max->y; int max_right = max_left + max->width; int max_bottom = max_top + max->height; /* Update maximums */ if (max_left > left) left = max_left; if (max_top > top) top = max_top; if (max_right < right) right = max_right; if (max_bottom < bottom) bottom = max_bottom; /* Commit rect */ guac_common_rect_init(rect, left, top, right - left, bottom - top); } int guac_common_rect_expand_to_grid(int cell_size, guac_common_rect* rect, const guac_common_rect* max_rect) { /* Invalid cell_size received */ if (cell_size <= 0) return -1; /* Nothing to do */ if (cell_size == 1) return 0; /* Calculate how much the rectangle must be adjusted to fit within the * given cell size. */ int dw = cell_size - rect->width % cell_size; int dh = cell_size - rect->height % cell_size; int dx = dw / 2; int dy = dh / 2; /* Set initial extents of adjusted rectangle. */ int top = rect->y - dy; int left = rect->x - dx; int bottom = top + rect->height + dh; int right = left + rect->width + dw; /* The max rectangle */ int max_left = max_rect->x; int max_top = max_rect->y; int max_right = max_left + max_rect->width; int max_bottom = max_top + max_rect->height; /* If the adjusted rectangle has sides beyond the max rectangle, or is larger * in any direction; shift or adjust the rectangle while trying to fit in * the grid */ /* Adjust left/right */ if (right > max_right) { /* shift to left */ dw = right - max_right; right -= dw; left -= dw; /* clamp left if too far */ if (left < max_left) { left = max_left; } } else if (left < max_left) { /* shift to right */ dw = max_left - left; left += dw; right += dw; /* clamp right if too far */ if (right > max_right) { right = max_right; } } /* Adjust top/bottom */ if (bottom > max_bottom) { /* shift up */ dh = bottom - max_bottom; bottom -= dh; top -= dh; /* clamp top if too far */ if (top < max_top) { top = max_top; } } else if (top < max_top) { /* shift down */ dh = max_top - top; top += dh; bottom += dh; /* clamp bottom if too far */ if (bottom > max_bottom) { bottom = max_bottom; } } /* Commit rect */ guac_common_rect_init(rect, left, top, right - left, bottom - top); return 0; } int guac_common_rect_intersects(const guac_common_rect* rect, const guac_common_rect* other) { /* Empty (no intersection) */ if (other->x + other->width < rect->x || rect->x + rect->width < other->x || other->y + other->height < rect->y || rect->y + rect->height < other->y) { return 0; } /* Complete */ else if (other->x <= rect->x && (other->x + other->width) >= (rect->x + rect->width) && other->y <= rect->y && (other->y + other->height) >= (rect->y + rect->height)) { return 2; } /* Partial intersection */ return 1; } int guac_common_rect_clip_and_split(guac_common_rect* rect, const guac_common_rect* hole, guac_common_rect* split_rect) { /* Only continue if the rectangles intersects */ if (!guac_common_rect_intersects(rect, hole)) return 0; int top, left, bottom, right; /* Clip and split top */ if (rect->y < hole->y) { top = rect->y; left = rect->x; bottom = hole->y; right = rect->x + rect->width; guac_common_rect_init(split_rect, left, top, right - left, bottom - top); /* Re-initialize original rect */ top = hole->y; bottom = rect->y + rect->height; guac_common_rect_init(rect, left, top, right - left, bottom - top); return 1; } /* Clip and split left */ else if (rect->x < hole->x) { top = rect->y; left = rect->x; bottom = rect->y + rect->height; right = hole->x; guac_common_rect_init(split_rect, left, top, right - left, bottom - top); /* Re-initialize original rect */ left = hole->x; right = rect->x + rect->width; guac_common_rect_init(rect, left, top, right - left, bottom - top); return 1; } /* Clip and split bottom */ else if (rect->y + rect->height > hole->y + hole->height) { top = hole->y + hole->height; left = rect->x; bottom = rect->y + rect->height; right = rect->x + rect->width; guac_common_rect_init(split_rect, left, top, right - left, bottom - top); /* Re-initialize original rect */ top = rect->y; bottom = hole->y + hole->height; guac_common_rect_init(rect, left, top, right - left, bottom - top); return 1; } /* Clip and split right */ else if (rect->x + rect->width > hole->x + hole->width) { top = rect->y; left = hole->x + hole->width; bottom = rect->y + rect->height; right = rect->x + rect->width; guac_common_rect_init(split_rect, left, top, right - left, bottom - top); /* Re-initialize original rect */ left = rect->x; right = hole->x + hole->width; guac_common_rect_init(rect, left, top, right - left, bottom - top); return 1; } return 0; } guacamole-server-1.3.0/src/common/tests/0000755000175100001440000000000013772471155015207 500000000000000guacamole-server-1.3.0/src/common/tests/rect/0000755000175100001440000000000013772471155016144 500000000000000guacamole-server-1.3.0/src/common/tests/rect/init.c0000644000175100001440000000224613726006252017166 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/rect.h" #include /** * Test which verifies rectangle initialization via guac_common_rect_init(). */ void test_rect__init() { guac_common_rect max; guac_common_rect_init(&max, 0, 0, 100, 100); CU_ASSERT_EQUAL(0, max.x); CU_ASSERT_EQUAL(0, max.y); CU_ASSERT_EQUAL(100, max.width); CU_ASSERT_EQUAL(100, max.height); } guacamole-server-1.3.0/src/common/tests/rect/constrain.c0000644000175100001440000000251513726006252020222 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/rect.h" #include /** * Test which verifies that guac_common_rect_constrain() restricts a given * rectangle to arbitrary bounds. */ void test_rect__constrain() { guac_common_rect max; guac_common_rect rect; guac_common_rect_init(&rect, -10, -10, 110, 110); guac_common_rect_init(&max, 0, 0, 100, 100); guac_common_rect_constrain(&rect, &max); CU_ASSERT_EQUAL(0, rect.x); CU_ASSERT_EQUAL(0, rect.y); CU_ASSERT_EQUAL(100, rect.width); CU_ASSERT_EQUAL(100, rect.height); } guacamole-server-1.3.0/src/common/tests/rect/clip_and_split.c0000644000175100001440000001123413726006252021204 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/rect.h" #include /** * Test which verifies that guac_common_rect_clip_and_split() divides a * rectangle into subrectangles after removing a "hole" rectangle. */ void test_rect__clip_and_split() { int res; guac_common_rect cut; guac_common_rect min; guac_common_rect rect; guac_common_rect_init(&min, 10, 10, 10, 10); /* Clip top */ guac_common_rect_init(&rect, 10, 5, 10, 10); res = guac_common_rect_clip_and_split(&rect, &min, &cut); CU_ASSERT_EQUAL(1, res); CU_ASSERT_EQUAL(10, cut.x); CU_ASSERT_EQUAL(5, cut.y); CU_ASSERT_EQUAL(10, cut.width); CU_ASSERT_EQUAL(5, cut.height); CU_ASSERT_EQUAL(10, rect.x); CU_ASSERT_EQUAL(10, rect.y); CU_ASSERT_EQUAL(10, rect.width); CU_ASSERT_EQUAL(5, rect.height); /* Clip bottom */ guac_common_rect_init(&rect, 10, 15, 10, 10); res = guac_common_rect_clip_and_split(&rect, &min, &cut); CU_ASSERT_EQUAL(1, res); CU_ASSERT_EQUAL(10, cut.x); CU_ASSERT_EQUAL(20, cut.y); CU_ASSERT_EQUAL(10, cut.width); CU_ASSERT_EQUAL(5, cut.height); CU_ASSERT_EQUAL(10, rect.x); CU_ASSERT_EQUAL(15, rect.y); CU_ASSERT_EQUAL(10, rect.width); CU_ASSERT_EQUAL(5, rect.height); /* Clip left */ guac_common_rect_init(&rect, 5, 10, 10, 10); res = guac_common_rect_clip_and_split(&rect, &min, &cut); CU_ASSERT_EQUAL(1, res); CU_ASSERT_EQUAL(5, cut.x); CU_ASSERT_EQUAL(10, cut.y); CU_ASSERT_EQUAL(5, cut.width); CU_ASSERT_EQUAL(10, cut.height); CU_ASSERT_EQUAL(10, rect.x); CU_ASSERT_EQUAL(10, rect.y); CU_ASSERT_EQUAL(5, rect.width); CU_ASSERT_EQUAL(10, rect.height); /* Clip right */ guac_common_rect_init(&rect, 15, 10, 10, 10); res = guac_common_rect_clip_and_split(&rect, &min, &cut); CU_ASSERT_EQUAL(1, res); CU_ASSERT_EQUAL(20, cut.x); CU_ASSERT_EQUAL(10, cut.y); CU_ASSERT_EQUAL(5, cut.width); CU_ASSERT_EQUAL(10, cut.height); CU_ASSERT_EQUAL(15, rect.x); CU_ASSERT_EQUAL(10, rect.y); CU_ASSERT_EQUAL(5, rect.width); CU_ASSERT_EQUAL(10, rect.height); /* * Test a rectangle which completely covers the hole. * Clip and split until done. */ guac_common_rect_init(&rect, 5, 5, 20, 20); /* Clip top */ res = guac_common_rect_clip_and_split(&rect, &min, &cut); CU_ASSERT_EQUAL(1, res); CU_ASSERT_EQUAL(5, cut.x); CU_ASSERT_EQUAL(5, cut.y); CU_ASSERT_EQUAL(20, cut.width); CU_ASSERT_EQUAL(5, cut.height); CU_ASSERT_EQUAL(5, rect.x); CU_ASSERT_EQUAL(10, rect.y); CU_ASSERT_EQUAL(20, rect.width); CU_ASSERT_EQUAL(15, rect.height); /* Clip left */ res = guac_common_rect_clip_and_split(&rect, &min, &cut); CU_ASSERT_EQUAL(1, res); CU_ASSERT_EQUAL(5, cut.x); CU_ASSERT_EQUAL(10, cut.y); CU_ASSERT_EQUAL(5, cut.width); CU_ASSERT_EQUAL(15, cut.height); CU_ASSERT_EQUAL(10, rect.x); CU_ASSERT_EQUAL(10, rect.y); CU_ASSERT_EQUAL(15, rect.width); CU_ASSERT_EQUAL(15, rect.height); /* Clip bottom */ res = guac_common_rect_clip_and_split(&rect, &min, &cut); CU_ASSERT_EQUAL(1, res); CU_ASSERT_EQUAL(10, cut.x); CU_ASSERT_EQUAL(20, cut.y); CU_ASSERT_EQUAL(15, cut.width); CU_ASSERT_EQUAL(5, cut.height); CU_ASSERT_EQUAL(10, rect.x); CU_ASSERT_EQUAL(10, rect.y); CU_ASSERT_EQUAL(15, rect.width); CU_ASSERT_EQUAL(10, rect.height); /* Clip right */ res = guac_common_rect_clip_and_split(&rect, &min, &cut); CU_ASSERT_EQUAL(20, cut.x); CU_ASSERT_EQUAL(10, cut.y); CU_ASSERT_EQUAL(5, cut.width); CU_ASSERT_EQUAL(10, cut.height); CU_ASSERT_EQUAL(10, rect.x); CU_ASSERT_EQUAL(10, rect.y); CU_ASSERT_EQUAL(10, rect.width); CU_ASSERT_EQUAL(10, rect.height); /* Make sure nothing is left to do */ res = guac_common_rect_clip_and_split(&rect, &min, &cut); CU_ASSERT_EQUAL(0, res); } guacamole-server-1.3.0/src/common/tests/rect/intersects.c0000644000175100001440000000575213726006252020413 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/rect.h" #include /** * Test which verifies intersection testing via guac_common_rect_intersects(). */ void test_rect__intersects() { int res; guac_common_rect min; guac_common_rect rect; guac_common_rect_init(&min, 10, 10, 10, 10); /* Rectangle intersection - empty * rectangle is outside */ guac_common_rect_init(&rect, 25, 25, 5, 5); res = guac_common_rect_intersects(&rect, &min); CU_ASSERT_EQUAL(0, res); /* Rectangle intersection - complete * rectangle is completely inside */ guac_common_rect_init(&rect, 11, 11, 5, 5); res = guac_common_rect_intersects(&rect, &min); CU_ASSERT_EQUAL(2, res); /* Rectangle intersection - partial * rectangle intersects UL */ guac_common_rect_init(&rect, 8, 8, 5, 5); res = guac_common_rect_intersects(&rect, &min); CU_ASSERT_EQUAL(1, res); /* Rectangle intersection - partial * rectangle intersects LR */ guac_common_rect_init(&rect, 18, 18, 5, 5); res = guac_common_rect_intersects(&rect, &min); CU_ASSERT_EQUAL(1, res); /* Rectangle intersection - complete * rect intersects along UL but inside */ guac_common_rect_init(&rect, 10, 10, 5, 5); res = guac_common_rect_intersects(&rect, &min); CU_ASSERT_EQUAL(2, res); /* Rectangle intersection - partial * rectangle intersects along L but outside */ guac_common_rect_init(&rect, 5, 10, 5, 5); res = guac_common_rect_intersects(&rect, &min); CU_ASSERT_EQUAL(1, res); /* Rectangle intersection - complete * rectangle intersects along LR but rest is inside */ guac_common_rect_init(&rect, 15, 15, 5, 5); res = guac_common_rect_intersects(&rect, &min); CU_ASSERT_EQUAL(2, res); /* Rectangle intersection - partial * rectangle intersects along R but rest is outside */ guac_common_rect_init(&rect, 20, 10, 5, 5); res = guac_common_rect_intersects(&rect, &min); CU_ASSERT_EQUAL(1, res); /* Rectangle intersection - partial * rectangle encloses min; which is a partial intersection */ guac_common_rect_init(&rect, 5, 5, 20, 20); res = guac_common_rect_intersects(&rect, &min); CU_ASSERT_EQUAL(1, res); } guacamole-server-1.3.0/src/common/tests/rect/extend.c0000644000175100001440000000253513726006252017513 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/rect.h" #include /** * Test which verifies that guac_common_rect_extend() expands the given * rectangle as necessary to contain at least the given bounds. */ void test_rect__extend() { guac_common_rect max; guac_common_rect rect; guac_common_rect_init(&rect, 10, 10, 90, 90); guac_common_rect_init(&max, 0, 0, 100, 100); guac_common_rect_extend(&rect, &max); CU_ASSERT_EQUAL(0, rect.x); CU_ASSERT_EQUAL(0, rect.y); CU_ASSERT_EQUAL(100, rect.width); CU_ASSERT_EQUAL(100, rect.height); } guacamole-server-1.3.0/src/common/tests/rect/expand_to_grid.c0000644000175100001440000000465113726006252021213 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/rect.h" #include /** * Test which verifies guac_common_rect_expand_to_grid() properly shifts and * resizes rectangles to fit an NxN grid. */ void test_rect__expand_to_grid() { int cell_size = 16; guac_common_rect max; guac_common_rect rect; /* Simple adjustment */ guac_common_rect_init(&rect, 0, 0, 25, 25); guac_common_rect_init(&max, 0, 0, 100, 100); guac_common_rect_expand_to_grid(cell_size, &rect, &max); CU_ASSERT_EQUAL(0, rect.x); CU_ASSERT_EQUAL(0, rect.y); CU_ASSERT_EQUAL(32, rect.width); CU_ASSERT_EQUAL(32, rect.height); /* Adjustment with moving of rect */ guac_common_rect_init(&rect, 75, 75, 25, 25); guac_common_rect_init(&max, 0, 0, 100, 100); guac_common_rect_expand_to_grid(cell_size, &rect, &max); CU_ASSERT_EQUAL(max.width - 32, rect.x); CU_ASSERT_EQUAL(max.height - 32, rect.y); CU_ASSERT_EQUAL(32, rect.width); CU_ASSERT_EQUAL(32, rect.height); guac_common_rect_init(&rect, -5, -5, 25, 25); guac_common_rect_init(&max, 0, 0, 100, 100); guac_common_rect_expand_to_grid(cell_size, &rect, &max); CU_ASSERT_EQUAL(0, rect.x); CU_ASSERT_EQUAL(0, rect.y); CU_ASSERT_EQUAL(32, rect.width); CU_ASSERT_EQUAL(32, rect.height); /* Adjustment with moving and clamping of rect */ guac_common_rect_init(&rect, 0, 0, 25, 15); guac_common_rect_init(&max, 0, 5, 32, 15); guac_common_rect_expand_to_grid(cell_size, &rect, &max); CU_ASSERT_EQUAL(max.x, rect.x); CU_ASSERT_EQUAL(max.y, rect.y); CU_ASSERT_EQUAL(max.width, rect.width); CU_ASSERT_EQUAL(max.height, rect.height); } guacamole-server-1.3.0/src/common/tests/Makefile.in0000644000175100001440000016731013772471101017173 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ check_PROGRAMS = test_common$(EXEEXT) subdir = src/common/tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__dirstamp = $(am__leading_dot)dirstamp am_test_common_OBJECTS = iconv/test_common-convert.$(OBJEXT) \ rect/test_common-clip_and_split.$(OBJEXT) \ rect/test_common-constrain.$(OBJEXT) \ rect/test_common-expand_to_grid.$(OBJEXT) \ rect/test_common-extend.$(OBJEXT) \ rect/test_common-init.$(OBJEXT) \ rect/test_common-intersects.$(OBJEXT) \ string/test_common-count_occurrences.$(OBJEXT) \ string/test_common-split.$(OBJEXT) nodist_test_common_OBJECTS = test_common-_generated_runner.$(OBJEXT) test_common_OBJECTS = $(am_test_common_OBJECTS) \ $(nodist_test_common_OBJECTS) test_common_DEPENDENCIES = AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = test_common_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_common_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/test_common-_generated_runner.Po \ iconv/$(DEPDIR)/test_common-convert.Po \ rect/$(DEPDIR)/test_common-clip_and_split.Po \ rect/$(DEPDIR)/test_common-constrain.Po \ rect/$(DEPDIR)/test_common-expand_to_grid.Po \ rect/$(DEPDIR)/test_common-extend.Po \ rect/$(DEPDIR)/test_common-init.Po \ rect/$(DEPDIR)/test_common-intersects.Po \ string/$(DEPDIR)/test_common-count_occurrences.Po \ string/$(DEPDIR)/test_common-split.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(test_common_SOURCES) $(nodist_test_common_SOURCES) DIST_SOURCES = $(test_common_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp \ $(top_srcdir)/build-aux/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 TESTS = $(check_PROGRAMS) test_common_SOURCES = \ iconv/convert.c \ rect/clip_and_split.c \ rect/constrain.c \ rect/expand_to_grid.c \ rect/extend.c \ rect/init.c \ rect/intersects.c \ string/count_occurrences.c \ string/split.c test_common_CFLAGS = \ -Werror -Wall -pedantic \ @COMMON_INCLUDE@ test_common_LDADD = \ @COMMON_LTLIB@ \ @CUNIT_LIBS@ # # Autogenerate test runner # GEN_RUNNER = $(top_srcdir)/util/generate-test-runner.pl CLEANFILES = _generated_runner.c nodist_test_common_SOURCES = \ _generated_runner.c # Use automake's TAP test driver for running any tests LOG_DRIVER = \ env AM_TAP_AWK='$(AWK)' \ $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/common/tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/common/tests/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list iconv/$(am__dirstamp): @$(MKDIR_P) iconv @: > iconv/$(am__dirstamp) iconv/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) iconv/$(DEPDIR) @: > iconv/$(DEPDIR)/$(am__dirstamp) iconv/test_common-convert.$(OBJEXT): iconv/$(am__dirstamp) \ iconv/$(DEPDIR)/$(am__dirstamp) rect/$(am__dirstamp): @$(MKDIR_P) rect @: > rect/$(am__dirstamp) rect/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) rect/$(DEPDIR) @: > rect/$(DEPDIR)/$(am__dirstamp) rect/test_common-clip_and_split.$(OBJEXT): rect/$(am__dirstamp) \ rect/$(DEPDIR)/$(am__dirstamp) rect/test_common-constrain.$(OBJEXT): rect/$(am__dirstamp) \ rect/$(DEPDIR)/$(am__dirstamp) rect/test_common-expand_to_grid.$(OBJEXT): rect/$(am__dirstamp) \ rect/$(DEPDIR)/$(am__dirstamp) rect/test_common-extend.$(OBJEXT): rect/$(am__dirstamp) \ rect/$(DEPDIR)/$(am__dirstamp) rect/test_common-init.$(OBJEXT): rect/$(am__dirstamp) \ rect/$(DEPDIR)/$(am__dirstamp) rect/test_common-intersects.$(OBJEXT): rect/$(am__dirstamp) \ rect/$(DEPDIR)/$(am__dirstamp) string/$(am__dirstamp): @$(MKDIR_P) string @: > string/$(am__dirstamp) string/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) string/$(DEPDIR) @: > string/$(DEPDIR)/$(am__dirstamp) string/test_common-count_occurrences.$(OBJEXT): \ string/$(am__dirstamp) string/$(DEPDIR)/$(am__dirstamp) string/test_common-split.$(OBJEXT): string/$(am__dirstamp) \ string/$(DEPDIR)/$(am__dirstamp) test_common$(EXEEXT): $(test_common_OBJECTS) $(test_common_DEPENDENCIES) $(EXTRA_test_common_DEPENDENCIES) @rm -f test_common$(EXEEXT) $(AM_V_CCLD)$(test_common_LINK) $(test_common_OBJECTS) $(test_common_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f iconv/*.$(OBJEXT) -rm -f rect/*.$(OBJEXT) -rm -f string/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_common-_generated_runner.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@iconv/$(DEPDIR)/test_common-convert.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@rect/$(DEPDIR)/test_common-clip_and_split.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@rect/$(DEPDIR)/test_common-constrain.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@rect/$(DEPDIR)/test_common-expand_to_grid.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@rect/$(DEPDIR)/test_common-extend.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@rect/$(DEPDIR)/test_common-init.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@rect/$(DEPDIR)/test_common-intersects.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@string/$(DEPDIR)/test_common-count_occurrences.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@string/$(DEPDIR)/test_common-split.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< iconv/test_common-convert.o: iconv/convert.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT iconv/test_common-convert.o -MD -MP -MF iconv/$(DEPDIR)/test_common-convert.Tpo -c -o iconv/test_common-convert.o `test -f 'iconv/convert.c' || echo '$(srcdir)/'`iconv/convert.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) iconv/$(DEPDIR)/test_common-convert.Tpo iconv/$(DEPDIR)/test_common-convert.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iconv/convert.c' object='iconv/test_common-convert.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o iconv/test_common-convert.o `test -f 'iconv/convert.c' || echo '$(srcdir)/'`iconv/convert.c iconv/test_common-convert.obj: iconv/convert.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT iconv/test_common-convert.obj -MD -MP -MF iconv/$(DEPDIR)/test_common-convert.Tpo -c -o iconv/test_common-convert.obj `if test -f 'iconv/convert.c'; then $(CYGPATH_W) 'iconv/convert.c'; else $(CYGPATH_W) '$(srcdir)/iconv/convert.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) iconv/$(DEPDIR)/test_common-convert.Tpo iconv/$(DEPDIR)/test_common-convert.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iconv/convert.c' object='iconv/test_common-convert.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o iconv/test_common-convert.obj `if test -f 'iconv/convert.c'; then $(CYGPATH_W) 'iconv/convert.c'; else $(CYGPATH_W) '$(srcdir)/iconv/convert.c'; fi` rect/test_common-clip_and_split.o: rect/clip_and_split.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT rect/test_common-clip_and_split.o -MD -MP -MF rect/$(DEPDIR)/test_common-clip_and_split.Tpo -c -o rect/test_common-clip_and_split.o `test -f 'rect/clip_and_split.c' || echo '$(srcdir)/'`rect/clip_and_split.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rect/$(DEPDIR)/test_common-clip_and_split.Tpo rect/$(DEPDIR)/test_common-clip_and_split.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect/clip_and_split.c' object='rect/test_common-clip_and_split.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o rect/test_common-clip_and_split.o `test -f 'rect/clip_and_split.c' || echo '$(srcdir)/'`rect/clip_and_split.c rect/test_common-clip_and_split.obj: rect/clip_and_split.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT rect/test_common-clip_and_split.obj -MD -MP -MF rect/$(DEPDIR)/test_common-clip_and_split.Tpo -c -o rect/test_common-clip_and_split.obj `if test -f 'rect/clip_and_split.c'; then $(CYGPATH_W) 'rect/clip_and_split.c'; else $(CYGPATH_W) '$(srcdir)/rect/clip_and_split.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rect/$(DEPDIR)/test_common-clip_and_split.Tpo rect/$(DEPDIR)/test_common-clip_and_split.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect/clip_and_split.c' object='rect/test_common-clip_and_split.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o rect/test_common-clip_and_split.obj `if test -f 'rect/clip_and_split.c'; then $(CYGPATH_W) 'rect/clip_and_split.c'; else $(CYGPATH_W) '$(srcdir)/rect/clip_and_split.c'; fi` rect/test_common-constrain.o: rect/constrain.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT rect/test_common-constrain.o -MD -MP -MF rect/$(DEPDIR)/test_common-constrain.Tpo -c -o rect/test_common-constrain.o `test -f 'rect/constrain.c' || echo '$(srcdir)/'`rect/constrain.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rect/$(DEPDIR)/test_common-constrain.Tpo rect/$(DEPDIR)/test_common-constrain.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect/constrain.c' object='rect/test_common-constrain.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o rect/test_common-constrain.o `test -f 'rect/constrain.c' || echo '$(srcdir)/'`rect/constrain.c rect/test_common-constrain.obj: rect/constrain.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT rect/test_common-constrain.obj -MD -MP -MF rect/$(DEPDIR)/test_common-constrain.Tpo -c -o rect/test_common-constrain.obj `if test -f 'rect/constrain.c'; then $(CYGPATH_W) 'rect/constrain.c'; else $(CYGPATH_W) '$(srcdir)/rect/constrain.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rect/$(DEPDIR)/test_common-constrain.Tpo rect/$(DEPDIR)/test_common-constrain.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect/constrain.c' object='rect/test_common-constrain.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o rect/test_common-constrain.obj `if test -f 'rect/constrain.c'; then $(CYGPATH_W) 'rect/constrain.c'; else $(CYGPATH_W) '$(srcdir)/rect/constrain.c'; fi` rect/test_common-expand_to_grid.o: rect/expand_to_grid.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT rect/test_common-expand_to_grid.o -MD -MP -MF rect/$(DEPDIR)/test_common-expand_to_grid.Tpo -c -o rect/test_common-expand_to_grid.o `test -f 'rect/expand_to_grid.c' || echo '$(srcdir)/'`rect/expand_to_grid.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rect/$(DEPDIR)/test_common-expand_to_grid.Tpo rect/$(DEPDIR)/test_common-expand_to_grid.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect/expand_to_grid.c' object='rect/test_common-expand_to_grid.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o rect/test_common-expand_to_grid.o `test -f 'rect/expand_to_grid.c' || echo '$(srcdir)/'`rect/expand_to_grid.c rect/test_common-expand_to_grid.obj: rect/expand_to_grid.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT rect/test_common-expand_to_grid.obj -MD -MP -MF rect/$(DEPDIR)/test_common-expand_to_grid.Tpo -c -o rect/test_common-expand_to_grid.obj `if test -f 'rect/expand_to_grid.c'; then $(CYGPATH_W) 'rect/expand_to_grid.c'; else $(CYGPATH_W) '$(srcdir)/rect/expand_to_grid.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rect/$(DEPDIR)/test_common-expand_to_grid.Tpo rect/$(DEPDIR)/test_common-expand_to_grid.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect/expand_to_grid.c' object='rect/test_common-expand_to_grid.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o rect/test_common-expand_to_grid.obj `if test -f 'rect/expand_to_grid.c'; then $(CYGPATH_W) 'rect/expand_to_grid.c'; else $(CYGPATH_W) '$(srcdir)/rect/expand_to_grid.c'; fi` rect/test_common-extend.o: rect/extend.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT rect/test_common-extend.o -MD -MP -MF rect/$(DEPDIR)/test_common-extend.Tpo -c -o rect/test_common-extend.o `test -f 'rect/extend.c' || echo '$(srcdir)/'`rect/extend.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rect/$(DEPDIR)/test_common-extend.Tpo rect/$(DEPDIR)/test_common-extend.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect/extend.c' object='rect/test_common-extend.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o rect/test_common-extend.o `test -f 'rect/extend.c' || echo '$(srcdir)/'`rect/extend.c rect/test_common-extend.obj: rect/extend.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT rect/test_common-extend.obj -MD -MP -MF rect/$(DEPDIR)/test_common-extend.Tpo -c -o rect/test_common-extend.obj `if test -f 'rect/extend.c'; then $(CYGPATH_W) 'rect/extend.c'; else $(CYGPATH_W) '$(srcdir)/rect/extend.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rect/$(DEPDIR)/test_common-extend.Tpo rect/$(DEPDIR)/test_common-extend.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect/extend.c' object='rect/test_common-extend.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o rect/test_common-extend.obj `if test -f 'rect/extend.c'; then $(CYGPATH_W) 'rect/extend.c'; else $(CYGPATH_W) '$(srcdir)/rect/extend.c'; fi` rect/test_common-init.o: rect/init.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT rect/test_common-init.o -MD -MP -MF rect/$(DEPDIR)/test_common-init.Tpo -c -o rect/test_common-init.o `test -f 'rect/init.c' || echo '$(srcdir)/'`rect/init.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rect/$(DEPDIR)/test_common-init.Tpo rect/$(DEPDIR)/test_common-init.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect/init.c' object='rect/test_common-init.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o rect/test_common-init.o `test -f 'rect/init.c' || echo '$(srcdir)/'`rect/init.c rect/test_common-init.obj: rect/init.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT rect/test_common-init.obj -MD -MP -MF rect/$(DEPDIR)/test_common-init.Tpo -c -o rect/test_common-init.obj `if test -f 'rect/init.c'; then $(CYGPATH_W) 'rect/init.c'; else $(CYGPATH_W) '$(srcdir)/rect/init.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rect/$(DEPDIR)/test_common-init.Tpo rect/$(DEPDIR)/test_common-init.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect/init.c' object='rect/test_common-init.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o rect/test_common-init.obj `if test -f 'rect/init.c'; then $(CYGPATH_W) 'rect/init.c'; else $(CYGPATH_W) '$(srcdir)/rect/init.c'; fi` rect/test_common-intersects.o: rect/intersects.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT rect/test_common-intersects.o -MD -MP -MF rect/$(DEPDIR)/test_common-intersects.Tpo -c -o rect/test_common-intersects.o `test -f 'rect/intersects.c' || echo '$(srcdir)/'`rect/intersects.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rect/$(DEPDIR)/test_common-intersects.Tpo rect/$(DEPDIR)/test_common-intersects.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect/intersects.c' object='rect/test_common-intersects.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o rect/test_common-intersects.o `test -f 'rect/intersects.c' || echo '$(srcdir)/'`rect/intersects.c rect/test_common-intersects.obj: rect/intersects.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT rect/test_common-intersects.obj -MD -MP -MF rect/$(DEPDIR)/test_common-intersects.Tpo -c -o rect/test_common-intersects.obj `if test -f 'rect/intersects.c'; then $(CYGPATH_W) 'rect/intersects.c'; else $(CYGPATH_W) '$(srcdir)/rect/intersects.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rect/$(DEPDIR)/test_common-intersects.Tpo rect/$(DEPDIR)/test_common-intersects.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect/intersects.c' object='rect/test_common-intersects.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o rect/test_common-intersects.obj `if test -f 'rect/intersects.c'; then $(CYGPATH_W) 'rect/intersects.c'; else $(CYGPATH_W) '$(srcdir)/rect/intersects.c'; fi` string/test_common-count_occurrences.o: string/count_occurrences.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT string/test_common-count_occurrences.o -MD -MP -MF string/$(DEPDIR)/test_common-count_occurrences.Tpo -c -o string/test_common-count_occurrences.o `test -f 'string/count_occurrences.c' || echo '$(srcdir)/'`string/count_occurrences.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) string/$(DEPDIR)/test_common-count_occurrences.Tpo string/$(DEPDIR)/test_common-count_occurrences.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string/count_occurrences.c' object='string/test_common-count_occurrences.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o string/test_common-count_occurrences.o `test -f 'string/count_occurrences.c' || echo '$(srcdir)/'`string/count_occurrences.c string/test_common-count_occurrences.obj: string/count_occurrences.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT string/test_common-count_occurrences.obj -MD -MP -MF string/$(DEPDIR)/test_common-count_occurrences.Tpo -c -o string/test_common-count_occurrences.obj `if test -f 'string/count_occurrences.c'; then $(CYGPATH_W) 'string/count_occurrences.c'; else $(CYGPATH_W) '$(srcdir)/string/count_occurrences.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) string/$(DEPDIR)/test_common-count_occurrences.Tpo string/$(DEPDIR)/test_common-count_occurrences.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string/count_occurrences.c' object='string/test_common-count_occurrences.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o string/test_common-count_occurrences.obj `if test -f 'string/count_occurrences.c'; then $(CYGPATH_W) 'string/count_occurrences.c'; else $(CYGPATH_W) '$(srcdir)/string/count_occurrences.c'; fi` string/test_common-split.o: string/split.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT string/test_common-split.o -MD -MP -MF string/$(DEPDIR)/test_common-split.Tpo -c -o string/test_common-split.o `test -f 'string/split.c' || echo '$(srcdir)/'`string/split.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) string/$(DEPDIR)/test_common-split.Tpo string/$(DEPDIR)/test_common-split.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string/split.c' object='string/test_common-split.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o string/test_common-split.o `test -f 'string/split.c' || echo '$(srcdir)/'`string/split.c string/test_common-split.obj: string/split.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT string/test_common-split.obj -MD -MP -MF string/$(DEPDIR)/test_common-split.Tpo -c -o string/test_common-split.obj `if test -f 'string/split.c'; then $(CYGPATH_W) 'string/split.c'; else $(CYGPATH_W) '$(srcdir)/string/split.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) string/$(DEPDIR)/test_common-split.Tpo string/$(DEPDIR)/test_common-split.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string/split.c' object='string/test_common-split.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o string/test_common-split.obj `if test -f 'string/split.c'; then $(CYGPATH_W) 'string/split.c'; else $(CYGPATH_W) '$(srcdir)/string/split.c'; fi` test_common-_generated_runner.o: _generated_runner.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT test_common-_generated_runner.o -MD -MP -MF $(DEPDIR)/test_common-_generated_runner.Tpo -c -o test_common-_generated_runner.o `test -f '_generated_runner.c' || echo '$(srcdir)/'`_generated_runner.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_common-_generated_runner.Tpo $(DEPDIR)/test_common-_generated_runner.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='_generated_runner.c' object='test_common-_generated_runner.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o test_common-_generated_runner.o `test -f '_generated_runner.c' || echo '$(srcdir)/'`_generated_runner.c test_common-_generated_runner.obj: _generated_runner.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -MT test_common-_generated_runner.obj -MD -MP -MF $(DEPDIR)/test_common-_generated_runner.Tpo -c -o test_common-_generated_runner.obj `if test -f '_generated_runner.c'; then $(CYGPATH_W) '_generated_runner.c'; else $(CYGPATH_W) '$(srcdir)/_generated_runner.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_common-_generated_runner.Tpo $(DEPDIR)/test_common-_generated_runner.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='_generated_runner.c' object='test_common-_generated_runner.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_common_CFLAGS) $(CFLAGS) -c -o test_common-_generated_runner.obj `if test -f '_generated_runner.c'; then $(CYGPATH_W) '_generated_runner.c'; else $(CYGPATH_W) '$(srcdir)/_generated_runner.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: $(check_PROGRAMS) @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_common.log: test_common$(EXEEXT) @p='test_common$(EXEEXT)'; \ b='test_common'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f iconv/$(DEPDIR)/$(am__dirstamp) -rm -f iconv/$(am__dirstamp) -rm -f rect/$(DEPDIR)/$(am__dirstamp) -rm -f rect/$(am__dirstamp) -rm -f string/$(DEPDIR)/$(am__dirstamp) -rm -f string/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/test_common-_generated_runner.Po -rm -f iconv/$(DEPDIR)/test_common-convert.Po -rm -f rect/$(DEPDIR)/test_common-clip_and_split.Po -rm -f rect/$(DEPDIR)/test_common-constrain.Po -rm -f rect/$(DEPDIR)/test_common-expand_to_grid.Po -rm -f rect/$(DEPDIR)/test_common-extend.Po -rm -f rect/$(DEPDIR)/test_common-init.Po -rm -f rect/$(DEPDIR)/test_common-intersects.Po -rm -f string/$(DEPDIR)/test_common-count_occurrences.Po -rm -f string/$(DEPDIR)/test_common-split.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/test_common-_generated_runner.Po -rm -f iconv/$(DEPDIR)/test_common-convert.Po -rm -f rect/$(DEPDIR)/test_common-clip_and_split.Po -rm -f rect/$(DEPDIR)/test_common-constrain.Po -rm -f rect/$(DEPDIR)/test_common-expand_to_grid.Po -rm -f rect/$(DEPDIR)/test_common-extend.Po -rm -f rect/$(DEPDIR)/test_common-init.Po -rm -f rect/$(DEPDIR)/test_common-intersects.Po -rm -f string/$(DEPDIR)/test_common-count_occurrences.Po -rm -f string/$(DEPDIR)/test_common-split.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am .PRECIOUS: Makefile _generated_runner.c: $(test_common_SOURCES) $(AM_V_GEN) $(GEN_RUNNER) $(test_common_SOURCES) > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/common/tests/string/0000755000175100001440000000000013772471155016515 500000000000000guacamole-server-1.3.0/src/common/tests/string/count_occurrences.c0000644000175100001440000000236613726006252022322 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/string.h" #include /** * Test which verifies that guac_count_occurrences() counts the number of * occurrences of an arbitrary character within a given string. */ void test_string__guac_count_occurrences() { CU_ASSERT_EQUAL(4, guac_count_occurrences("this is a test string", 's')); CU_ASSERT_EQUAL(3, guac_count_occurrences("this is a test string", 'i')); CU_ASSERT_EQUAL(0, guac_count_occurrences("", 's')); } guacamole-server-1.3.0/src/common/tests/string/split.c0000644000175100001440000000343613726006252017731 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/string.h" #include #include /** * Test which verifies that guac_split() splits a string on occurrences of a * given character. */ void test_string__split() { /* Split test string */ char** tokens = guac_split("this is a test string", ' '); CU_ASSERT_PTR_NOT_NULL(tokens); /* Check resulting tokens */ CU_ASSERT_PTR_NOT_NULL_FATAL(tokens[0]); CU_ASSERT_STRING_EQUAL("this", tokens[0]); CU_ASSERT_PTR_NOT_NULL_FATAL(tokens[1]); CU_ASSERT_STRING_EQUAL("is", tokens[1]); CU_ASSERT_PTR_NOT_NULL_FATAL(tokens[2]); CU_ASSERT_STRING_EQUAL("a", tokens[2]); CU_ASSERT_PTR_NOT_NULL_FATAL(tokens[3]); CU_ASSERT_STRING_EQUAL("test", tokens[3]); CU_ASSERT_PTR_NOT_NULL_FATAL(tokens[4]); CU_ASSERT_STRING_EQUAL("string", tokens[4]); CU_ASSERT_PTR_NULL(tokens[5]); /* Clean up */ free(tokens[0]); free(tokens[1]); free(tokens[2]); free(tokens[3]); free(tokens[4]); free(tokens); } guacamole-server-1.3.0/src/common/tests/iconv/0000755000175100001440000000000013772471155016325 500000000000000guacamole-server-1.3.0/src/common/tests/iconv/convert.c0000644000175100001440000001241013726006252020056 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/iconv.h" #include /** * UTF8 for "papà è bello". */ unsigned char test_string_utf8[] = { 'p', 'a', 'p', 0xC3, 0xA0, ' ', 0xC3, 0xA8, ' ', 'b', 'e', 'l', 'l', 'o', 0x00 }; /** * UTF16 for "papà è bello". */ unsigned char test_string_utf16[] = { 'p', 0x00, 'a', 0x00, 'p', 0x00, 0xE0, 0x00, ' ', 0x00, 0xE8, 0x00, ' ', 0x00, 'b', 0x00, 'e', 0x00, 'l', 0x00, 'l', 0x00, 'o', 0x00, 0x00, 0x00 }; /** * ISO-8859-1 for "papà è bello". */ unsigned char test_string_iso8859_1[] = { 'p', 'a', 'p', 0xE0, ' ', 0xE8, ' ', 'b', 'e', 'l', 'l', 'o', 0x00 }; /** * CP1252 for "papà è bello". */ unsigned char test_string_cp1252[] = { 'p', 'a', 'p', 0xE0, ' ', 0xE8, ' ', 'b', 'e', 'l', 'l', 'o', 0x00 }; /** * Tests that conversion between character sets using the given guac_iconv_read * and guac_iconv_write implementations matches expectations. * * @param reader * The guac_iconv_read implementation to use to read the input string. * * @param in_string * A pointer to the beginning of the input string. * * @param in_length * The size of the input string in bytes. * * @param writer * The guac_iconv_write implementation to use to write the output string * (the converted input string). * * @param out_string * A pointer to the beginning of a string which contains the expected * result of the conversion. * * @param out_length * The size of the expected result in bytes. */ static void verify_conversion( guac_iconv_read* reader, unsigned char* in_string, int in_length, guac_iconv_write* writer, unsigned char* out_string, int out_length) { char output[4096]; char input[4096]; const char* current_input = input; char* current_output = output; memcpy(input, in_string, in_length); guac_iconv(reader, ¤t_input, sizeof(input), writer, ¤t_output, sizeof(output)); /* Verify output length */ CU_ASSERT_EQUAL(out_length, current_output - output); /* Verify entire input read */ CU_ASSERT_EQUAL(in_length, current_input - input); /* Verify output content */ CU_ASSERT_EQUAL(0, memcmp(output, out_string, out_length)); } /** * Tests which verifies conversion of UTF-8 to itself. */ void test_iconv__utf8_to_utf8() { verify_conversion( GUAC_READ_UTF8, test_string_utf8, sizeof(test_string_utf8), GUAC_WRITE_UTF8, test_string_utf8, sizeof(test_string_utf8)); } /** * Tests which verifies conversion of UTF-16 to UTF-8. */ void test_iconv__utf8_to_utf16() { verify_conversion( GUAC_READ_UTF8, test_string_utf8, sizeof(test_string_utf8), GUAC_WRITE_UTF16, test_string_utf16, sizeof(test_string_utf16)); } /** * Tests which verifies conversion of UTF-16 to itself. */ void test_iconv__utf16_to_utf16() { verify_conversion( GUAC_READ_UTF16, test_string_utf16, sizeof(test_string_utf16), GUAC_WRITE_UTF16, test_string_utf16, sizeof(test_string_utf16)); } /** * Tests which verifies conversion of UTF-8 to UTF-16. */ void test_iconv__utf16_to_utf8() { verify_conversion( GUAC_READ_UTF16, test_string_utf16, sizeof(test_string_utf16), GUAC_WRITE_UTF8, test_string_utf8, sizeof(test_string_utf8)); } /** * Tests which verifies conversion of UTF-16 to ISO 8859-1. */ void test_iconv__utf16_to_iso8859_1() { verify_conversion( GUAC_READ_UTF16, test_string_utf16, sizeof(test_string_utf16), GUAC_WRITE_ISO8859_1, test_string_iso8859_1, sizeof(test_string_iso8859_1)); } /** * Tests which verifies conversion of UTF-16 to CP1252. */ void test_iconv__utf16_to_cp1252() { verify_conversion( GUAC_READ_UTF16, test_string_utf16, sizeof(test_string_utf16), GUAC_WRITE_CP1252, test_string_cp1252, sizeof(test_string_cp1252)); } /** * Tests which verifies conversion of CP1252 to UTF-8. */ void test_iconv__cp1252_to_utf8() { verify_conversion( GUAC_READ_CP1252, test_string_cp1252, sizeof(test_string_cp1252), GUAC_WRITE_UTF8, test_string_utf8, sizeof(test_string_utf8)); } /** * Tests which verifies conversion of ISO 8859-1 to UTF-8. */ void test_iconv__iso8859_1_to_utf8() { verify_conversion( GUAC_READ_ISO8859_1, test_string_iso8859_1, sizeof(test_string_iso8859_1), GUAC_WRITE_UTF8, test_string_utf8, sizeof(test_string_utf8)); } guacamole-server-1.3.0/src/common/tests/Makefile.am0000644000175100001440000000430013764613616017161 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 # # Unit tests for libguac_common # check_PROGRAMS = test_common TESTS = $(check_PROGRAMS) test_common_SOURCES = \ iconv/convert.c \ rect/clip_and_split.c \ rect/constrain.c \ rect/expand_to_grid.c \ rect/extend.c \ rect/init.c \ rect/intersects.c \ string/count_occurrences.c \ string/split.c test_common_CFLAGS = \ -Werror -Wall -pedantic \ @COMMON_INCLUDE@ test_common_LDADD = \ @COMMON_LTLIB@ \ @CUNIT_LIBS@ # # Autogenerate test runner # GEN_RUNNER = $(top_srcdir)/util/generate-test-runner.pl CLEANFILES = _generated_runner.c _generated_runner.c: $(test_common_SOURCES) $(AM_V_GEN) $(GEN_RUNNER) $(test_common_SOURCES) > $@ nodist_test_common_SOURCES = \ _generated_runner.c # Use automake's TAP test driver for running any tests LOG_DRIVER = \ env AM_TAP_AWK='$(AWK)' \ $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh guacamole-server-1.3.0/src/common/list.c0000644000175100001440000000420413613156714015077 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/list.h" #include #include guac_common_list* guac_common_list_alloc() { guac_common_list* list = malloc(sizeof(guac_common_list)); pthread_mutex_init(&list->_lock, NULL); list->head = NULL; return list; } void guac_common_list_free(guac_common_list* list) { free(list); } guac_common_list_element* guac_common_list_add(guac_common_list* list, void* data) { /* Allocate element, initialize as new head */ guac_common_list_element* element = malloc(sizeof(guac_common_list_element)); element->data = data; element->next = list->head; element->_ptr = &(list->head); /* If head already existed, point it at this element */ if (list->head != NULL) list->head->_ptr = &(element->next); /* Set as new head */ list->head = element; return element; } void guac_common_list_remove(guac_common_list* list, guac_common_list_element* element) { /* Point previous (or head) to next */ *(element->_ptr) = element->next; if (element->next != NULL) element->next->_ptr = element->_ptr; free(element); } void guac_common_list_lock(guac_common_list* list) { pthread_mutex_lock(&list->_lock); } void guac_common_list_unlock(guac_common_list* list) { pthread_mutex_unlock(&list->_lock); } guacamole-server-1.3.0/src/common/surface.c0000644000175100001440000017022013764613616015564 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/rect.h" #include "common/surface.h" #include #include #include #include #include #include #include #include #include #include #include /** * The width of an update which should be considered negible and thus * trivial overhead compared ot the cost of two updates. */ #define GUAC_SURFACE_NEGLIGIBLE_WIDTH 64 /** * The height of an update which should be considered negible and thus * trivial overhead compared ot the cost of two updates. */ #define GUAC_SURFACE_NEGLIGIBLE_HEIGHT 64 /** * The proportional increase in cost contributed by transfer and processing of * image data, compared to processing an equivalent amount of client-side * data. */ #define GUAC_SURFACE_DATA_FACTOR 16 /** * The base cost of every update. Each update should be considered to have * this starting cost, plus any additional cost estimated from its * content. */ #define GUAC_SURFACE_BASE_COST 4096 /** * An increase in cost is negligible if it is less than * 1/GUAC_SURFACE_NEGLIGIBLE_INCREASE of the old cost. */ #define GUAC_SURFACE_NEGLIGIBLE_INCREASE 4 /** * If combining an update because it appears to be follow a fill pattern, * the combined cost must not exceed * GUAC_SURFACE_FILL_PATTERN_FACTOR * (total uncombined cost). */ #define GUAC_SURFACE_FILL_PATTERN_FACTOR 3 /* Define cairo_format_stride_for_width() if missing */ #ifndef HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH #define cairo_format_stride_for_width(format, width) (width*4) #endif /** * The framerate which, if exceeded, indicates that JPEG is preferred. */ #define GUAC_COMMON_SURFACE_JPEG_FRAMERATE 3 /** * Minimum JPEG bitmap size (area). If the bitmap is smaller than this threshold, * it should be compressed as a PNG image to avoid the JPEG compression tax. */ #define GUAC_SURFACE_JPEG_MIN_BITMAP_SIZE 4096 /** * The JPEG compression min block size. This defines the optimal rectangle block * size factor for JPEG compression. Usually 8x8 would suffice, but use 16 to * reduce the occurrence of ringing artifacts further. */ #define GUAC_SURFACE_JPEG_BLOCK_SIZE 16 /** * The WebP compression min block size. This defines the optimal rectangle block * size factor for WebP compression. WebP does utilize variable block size, but * ensuring a block size factor reduces any noise on the image edges. */ #define GUAC_SURFACE_WEBP_BLOCK_SIZE 8 void guac_common_surface_move(guac_common_surface* surface, int x, int y) { pthread_mutex_lock(&surface->_lock); surface->x = x; surface->y = y; surface->location_dirty = 1; pthread_mutex_unlock(&surface->_lock); } void guac_common_surface_stack(guac_common_surface* surface, int z) { pthread_mutex_lock(&surface->_lock); surface->z = z; surface->location_dirty = 1; pthread_mutex_unlock(&surface->_lock); } void guac_common_surface_set_parent(guac_common_surface* surface, const guac_layer* parent) { pthread_mutex_lock(&surface->_lock); surface->parent = parent; surface->location_dirty = 1; pthread_mutex_unlock(&surface->_lock); } void guac_common_surface_set_opacity(guac_common_surface* surface, int opacity) { pthread_mutex_lock(&surface->_lock); surface->opacity = opacity; surface->opacity_dirty = 1; pthread_mutex_unlock(&surface->_lock); } /** * Updates the coordinates of the given rectangle to be within the bounds of * the given surface. * * @param surface The surface to use for clipping. * @param rect The rectangle to clip. * @param sx The X coordinate of the source rectangle, if any. * @param sy The Y coordinate of the source rectangle, if any. */ static void __guac_common_bound_rect(guac_common_surface* surface, guac_common_rect* rect, int* sx, int* sy) { guac_common_rect bounds_rect = { .x = 0, .y = 0, .width = surface->width, .height = surface->height }; int orig_x = rect->x; int orig_y = rect->y; guac_common_rect_constrain(rect, &bounds_rect); /* Update source X/Y if given */ if (sx != NULL) *sx += rect->x - orig_x; if (sy != NULL) *sy += rect->y - orig_y; } /** * Updates the coordinates of the given rectangle to be within the clipping * rectangle of the given surface, which must always be within the bounding * rectangle of the given surface. * * @param surface The surface to use for clipping. * @param rect The rectangle to clip. * @param sx The X coordinate of the source rectangle, if any. * @param sy The Y coordinate of the source rectangle, if any. */ static void __guac_common_clip_rect(guac_common_surface* surface, guac_common_rect* rect, int* sx, int* sy) { int orig_x = rect->x; int orig_y = rect->y; /* Just bound within surface if no clipping rectangle applied */ if (!surface->clipped) { __guac_common_bound_rect(surface, rect, sx, sy); return; } guac_common_rect_constrain(rect, &surface->clip_rect); /* Update source X/Y if given */ if (sx != NULL) *sx += rect->x - orig_x; if (sy != NULL) *sy += rect->y - orig_y; } /** * Returns whether a rectangle within the given surface contains only fully * opaque pixels. * * @param surface * The surface to check. * * @param rect * The rectangle to check. * * @return * Non-zero if the rectangle contains only fully opaque pixels, zero * otherwise. */ static int __guac_common_surface_is_opaque(guac_common_surface* surface, guac_common_rect* rect) { int x, y; int stride = surface ->stride; unsigned char* buffer = surface->buffer + (stride * rect->y) + (4 * rect->x); /* For each row */ for (y = 0; y < rect->height; y++) { /* Search for a non-opaque pixel */ uint32_t* current = (uint32_t*) buffer; for (x=0; x < rect->width; x++) { /* Rectangle is non-opaque if a single non-opaque pixel is found */ uint32_t color = *(current++); if ((color & 0xFF000000) != 0xFF000000) return 0; } /* Next row */ buffer += stride; } /* Rectangle is opaque */ return 1; } /** * Returns whether the given rectangle should be combined into the existing * dirty rectangle, to be eventually flushed as image data, or would be best * kept independent of the current rectangle. * * @param surface * The surface being updated. * * @param rect * The bounding rectangle of the update being made to the surface. * * @param rect_only * Non-zero if this update, by its nature, contains only metainformation * about the update's bounding rectangle, zero if the update also contains * image data. * * @return * Non-zero if the update should be combined with any existing update, zero * otherwise. */ static int __guac_common_should_combine(guac_common_surface* surface, const guac_common_rect* rect, int rect_only) { /* Always favor combining updates if surface is currently a purely * server-side scratch area */ if (!surface->realized) return 1; if (surface->dirty) { int combined_cost, dirty_cost, update_cost; /* Simulate combination */ guac_common_rect combined = surface->dirty_rect; guac_common_rect_extend(&combined, rect); /* Combine if result is still small */ if (combined.width <= GUAC_SURFACE_NEGLIGIBLE_WIDTH && combined.height <= GUAC_SURFACE_NEGLIGIBLE_HEIGHT) return 1; /* Estimate costs of the existing update, new update, and both combined */ combined_cost = GUAC_SURFACE_BASE_COST + combined.width * combined.height; dirty_cost = GUAC_SURFACE_BASE_COST + surface->dirty_rect.width * surface->dirty_rect.height; update_cost = GUAC_SURFACE_BASE_COST + rect->width * rect->height; /* Reduce cost if no image data */ if (rect_only) update_cost /= GUAC_SURFACE_DATA_FACTOR; /* Combine if cost estimate shows benefit */ if (combined_cost <= update_cost + dirty_cost) return 1; /* Combine if increase in cost is negligible */ if (combined_cost - dirty_cost <= dirty_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE) return 1; if (combined_cost - update_cost <= update_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE) return 1; /* Combine if we anticipate further updates, as this update follows a common fill pattern */ if (rect->x == surface->dirty_rect.x && rect->y == surface->dirty_rect.y + surface->dirty_rect.height) { if (combined_cost <= (dirty_cost + update_cost) * GUAC_SURFACE_FILL_PATTERN_FACTOR) return 1; } } /* Otherwise, do not combine */ return 0; } /** * Expands the dirty rect of the given surface to contain the rect described by the given * coordinates. * * @param surface The surface to mark as dirty. * @param rect The rectangle of the update which is dirtying the surface. */ static void __guac_common_mark_dirty(guac_common_surface* surface, const guac_common_rect* rect) { /* Ignore empty rects */ if (rect->width <= 0 || rect->height <= 0) return; /* If already dirty, update existing rect */ if (surface->dirty) guac_common_rect_extend(&surface->dirty_rect, rect); /* Otherwise init dirty rect */ else { surface->dirty_rect = *rect; surface->dirty = 1; } } /** * Calculate the current average framerate for a given area on the surface. * * @param surface * The surface on which the framerate will be calculated. * * @param rect * The rect containing the area for which the average framerate will be * calculated. * * @return * The average framerate of the given area, in frames per second. */ static unsigned int __guac_common_surface_calculate_framerate( guac_common_surface* surface, const guac_common_rect* rect) { int x, y; /* Calculate heat map dimensions */ int heat_width = GUAC_COMMON_SURFACE_HEAT_DIMENSION(surface->width); /* Calculate minimum X/Y coordinates intersecting given rect */ int min_x = rect->x / GUAC_COMMON_SURFACE_HEAT_CELL_SIZE; int min_y = rect->y / GUAC_COMMON_SURFACE_HEAT_CELL_SIZE; /* Calculate maximum X/Y coordinates intersecting given rect */ int max_x = min_x + (rect->width - 1) / GUAC_COMMON_SURFACE_HEAT_CELL_SIZE; int max_y = min_y + (rect->height - 1) / GUAC_COMMON_SURFACE_HEAT_CELL_SIZE; unsigned int sum_framerate = 0; unsigned int count = 0; /* Get start of buffer at given coordinates */ const guac_common_surface_heat_cell* heat_row = surface->heat_map + min_y * heat_width + min_x; /* Iterate over all the heat map cells for the area * and calculate the average framerate */ for (y = min_y; y < max_y; y++) { /* Get current row of heat map */ const guac_common_surface_heat_cell* heat_cell = heat_row; /* For each cell in subset of row */ for (x = min_x; x < max_x; x++) { /* Calculate indicies for latest and oldest history entries */ int oldest_entry = heat_cell->oldest_entry; int latest_entry = oldest_entry - 1; if (latest_entry < 0) latest_entry = GUAC_COMMON_SURFACE_HEAT_CELL_HISTORY_SIZE - 1; /* Calculate elapsed time covering entire history for this cell */ int elapsed_time = heat_cell->history[latest_entry] - heat_cell->history[oldest_entry]; /* Calculate and add framerate */ if (elapsed_time) sum_framerate += GUAC_COMMON_SURFACE_HEAT_CELL_HISTORY_SIZE * 1000 / elapsed_time; /* Next heat map cell */ heat_cell++; count++; } /* Next heat map row */ heat_row += heat_width; } /* Calculate the average framerate over entire rect */ if (count) return sum_framerate / count; return 0; } /** * Guesses whether a rectangle within a particular surface would be better * compressed as PNG or using a lossy format like JPEG. Positive values * indicate PNG is likely to be superior, while negative values indicate the * opposite. * * @param surface * The surface containing the image data to check. * * @param rect * The rect to check within the given surface. * * @return * Positive values if PNG compression is likely to perform better than * lossy alternatives, or negative values if PNG is likely to perform * worse. */ static int __guac_common_surface_png_optimality(guac_common_surface* surface, const guac_common_rect* rect) { int x, y; int num_same = 0; int num_different = 1; /* Get image/buffer metrics */ int width = rect->width; int height = rect->height; int stride = surface->stride; /* Get buffer from surface */ unsigned char* buffer = surface->buffer + rect->y * stride + rect->x * 4; /* Image must be at least 1x1 */ if (width < 1 || height < 1) return 0; /* For each row */ for (y = 0; y < height; y++) { uint32_t* row = (uint32_t*) buffer; uint32_t last_pixel = *(row++) | 0xFF000000; /* For each pixel in current row */ for (x = 1; x < width; x++) { /* Get next pixel */ uint32_t current_pixel = *(row++) | 0xFF000000; /* Update same/different counts according to pixel value */ if (current_pixel == last_pixel) num_same++; else num_different++; last_pixel = current_pixel; } /* Advance to next row */ buffer += stride; } /* Return rough approximation of optimality for PNG compression */ return 0x100 * num_same / num_different - 0x400; } /** * Returns whether the given rectangle would be optimally encoded as JPEG * rather than PNG. * * @param surface * The surface to be queried. * * @param rect * The rectangle to check. * * @return * Non-zero if the rectangle would be optimally encoded as JPEG, zero * otherwise. */ static int __guac_common_surface_should_use_jpeg(guac_common_surface* surface, const guac_common_rect* rect) { /* Calculate the average framerate for the given rect */ int framerate = __guac_common_surface_calculate_framerate(surface, rect); int rect_size = rect->width * rect->height; /* JPEG is preferred if: * - frame rate is high enough * - image size is large enough * - PNG is not more optimal based on image contents */ return framerate >= GUAC_COMMON_SURFACE_JPEG_FRAMERATE && rect_size > GUAC_SURFACE_JPEG_MIN_BITMAP_SIZE && __guac_common_surface_png_optimality(surface, rect) < 0; } /** * Returns whether the given rectangle would be optimally encoded as WebP * rather than PNG. * * @param surface * The surface to be queried. * * @param rect * The rectangle to check. * * @return * Non-zero if the rectangle would be optimally encoded as WebP, zero * otherwise. */ static int __guac_common_surface_should_use_webp(guac_common_surface* surface, const guac_common_rect* rect) { /* Do not use WebP if not supported */ if (!guac_client_supports_webp(surface->client)) return 0; /* Calculate the average framerate for the given rect */ int framerate = __guac_common_surface_calculate_framerate(surface, rect); /* WebP is preferred if: * - frame rate is high enough * - PNG is not more optimal based on image contents */ return framerate >= GUAC_COMMON_SURFACE_JPEG_FRAMERATE && __guac_common_surface_png_optimality(surface, rect) < 0; } /** * Updates the heat map cells which intersect the given rectangle using the * given timestamp. This timestamp, along with timestamps from past updates, * is used to calculate the framerate of each heat cell. * * @param surface * The surface containing the heat map cells to be updated. * * @param rect * The rectangle containing the heat map cells to be updated. * * @param time * The timestamp to use when updating the heat map cells which intersect * the given rectangle. */ static void __guac_common_surface_touch_rect(guac_common_surface* surface, guac_common_rect* rect, guac_timestamp time) { int x, y; /* Calculate heat map dimensions */ int heat_width = GUAC_COMMON_SURFACE_HEAT_DIMENSION(surface->width); /* Calculate minimum X/Y coordinates intersecting given rect */ int min_x = rect->x / GUAC_COMMON_SURFACE_HEAT_CELL_SIZE; int min_y = rect->y / GUAC_COMMON_SURFACE_HEAT_CELL_SIZE; /* Calculate maximum X/Y coordinates intersecting given rect */ int max_x = min_x + (rect->width - 1) / GUAC_COMMON_SURFACE_HEAT_CELL_SIZE; int max_y = min_y + (rect->height - 1) / GUAC_COMMON_SURFACE_HEAT_CELL_SIZE; /* Get start of buffer at given coordinates */ guac_common_surface_heat_cell* heat_row = surface->heat_map + min_y * heat_width + min_x; /* Update all heat map cells which intersect with rectangle */ for (y = min_y; y <= max_y; y++) { /* Get current row of heat map */ guac_common_surface_heat_cell* heat_cell = heat_row; /* For each cell in subset of row */ for (x = min_x; x <= max_x; x++) { /* Replace oldest entry with new timestamp */ heat_cell->history[heat_cell->oldest_entry] = time; /* Update to next oldest entry */ heat_cell->oldest_entry++; if (heat_cell->oldest_entry >= GUAC_COMMON_SURFACE_HEAT_CELL_HISTORY_SIZE) heat_cell->oldest_entry = 0; /* Advance to next heat map cell */ heat_cell++; } /* Next heat map row */ heat_row += heat_width; } } /** * Flushes the bitmap update currently described by the dirty rectangle within the * given surface to that surface's bitmap queue. There MUST be space within the * queue. * * @param surface The surface to flush. */ static void __guac_common_surface_flush_to_queue(guac_common_surface* surface) { guac_common_surface_bitmap_rect* rect; /* Do not flush if not dirty */ if (!surface->dirty) return; /* Add new rect to queue */ rect = &(surface->bitmap_queue[surface->bitmap_queue_length++]); rect->rect = surface->dirty_rect; rect->flushed = 0; /* Surface now flushed */ surface->dirty = 0; } /** * Flushes the given surface, drawing any pending operations on the remote * display. Surface properties are not flushed. * * @param surface * The surface to flush. */ static void __guac_common_surface_flush(guac_common_surface* surface); /** * Schedules a deferred flush of the given surface. This will not immediately * flush the surface to the client. Instead, the result of the flush is * added to a queue which is reinspected and combined (if possible) with other * deferred flushes during the call to guac_common_surface_flush(). * * @param surface The surface to flush. */ static void __guac_common_surface_flush_deferred(guac_common_surface* surface) { /* Do not flush if not dirty */ if (!surface->dirty) return; /* Flush if queue size has reached maximum (space is reserved for the final * dirty rect, as __guac_common_surface_flush() MAY add an additional rect * to the queue */ if (surface->bitmap_queue_length == GUAC_COMMON_SURFACE_QUEUE_SIZE-1) __guac_common_surface_flush(surface); /* Append dirty rect to queue */ __guac_common_surface_flush_to_queue(surface); } /** * Transfers a single uint32_t using the given transfer function. * * @param op The transfer function to use. * @param src The source of the uint32_t value. * @param dst THe destination which will hold the result of the transfer. * @return Non-zero if the destination value was changed, zero otherwise. */ static int __guac_common_surface_transfer_int(guac_transfer_function op, uint32_t* src, uint32_t* dst) { uint32_t orig = *dst; switch (op) { case GUAC_TRANSFER_BINARY_BLACK: *dst = 0xFF000000; break; case GUAC_TRANSFER_BINARY_WHITE: *dst = 0xFFFFFFFF; break; case GUAC_TRANSFER_BINARY_SRC: *dst = *src; break; case GUAC_TRANSFER_BINARY_DEST: /* NOP */ break; case GUAC_TRANSFER_BINARY_NSRC: *dst = *src ^ 0x00FFFFFF; break; case GUAC_TRANSFER_BINARY_NDEST: *dst = *dst ^ 0x00FFFFFF; break; case GUAC_TRANSFER_BINARY_AND: *dst = ((*dst) & (0xFF000000 | *src)); break; case GUAC_TRANSFER_BINARY_NAND: *dst = ((*dst) & (0xFF000000 | *src)) ^ 0x00FFFFFF; break; case GUAC_TRANSFER_BINARY_OR: *dst = ((*dst) | (0x00FFFFFF & *src)); break; case GUAC_TRANSFER_BINARY_NOR: *dst = ((*dst) | (0x00FFFFFF & *src)) ^ 0x00FFFFFF; break; case GUAC_TRANSFER_BINARY_XOR: *dst = ((*dst) ^ (0x00FFFFFF & *src)); break; case GUAC_TRANSFER_BINARY_XNOR: *dst = ((*dst) ^ (0x00FFFFFF & *src)) ^ 0x00FFFFFF; break; case GUAC_TRANSFER_BINARY_NSRC_AND: *dst = ((*dst) & (0xFF000000 | (*src ^ 0x00FFFFFF))); break; case GUAC_TRANSFER_BINARY_NSRC_NAND: *dst = ((*dst) & (0xFF000000 | (*src ^ 0x00FFFFFF))) ^ 0x00FFFFFF; break; case GUAC_TRANSFER_BINARY_NSRC_OR: *dst = ((*dst) | (0x00FFFFFF & (*src ^ 0x00FFFFFF))); break; case GUAC_TRANSFER_BINARY_NSRC_NOR: *dst = ((*dst) | (0x00FFFFFF & (*src ^ 0x00FFFFFF))) ^ 0x00FFFFFF; break; } return *dst != orig; } /** * Assigns the given value to all pixels within a rectangle of the backing * surface of the given destination surface. The color of all pixels within the * rectangle, including the alpha component, is entirely replaced. * * @param dst * The destination surface. * * @param rect * The rectangle to draw. * * @param red * The red component of the color value to assign to all pixels within the * rectangle. * * @param green * The green component of the color value to assign to all pixels within * the rectangle. * * @param blue * The blue component of the color value to assign to all pixels within the * rectangle. * * @param alpha * The alpha component of the color value to assign to all pixels within * the rectangle. */ static void __guac_common_surface_set(guac_common_surface* dst, guac_common_rect* rect, int red, int green, int blue, int alpha) { int x, y; int dst_stride; unsigned char* dst_buffer; uint32_t color = (alpha << 24) | (red << 16) | (green << 8) | blue; int min_x = rect->width - 1; int min_y = rect->height - 1; int max_x = 0; int max_y = 0; dst_stride = dst->stride; dst_buffer = dst->buffer + (dst_stride * rect->y) + (4 * rect->x); /* For each row */ for (y=0; y < rect->height; y++) { uint32_t* dst_current = (uint32_t*) dst_buffer; /* Set row */ for (x=0; x < rect->width; x++) { uint32_t old_color = *dst_current; if (old_color != color) { if (x < min_x) min_x = x; if (y < min_y) min_y = y; if (x > max_x) max_x = x; if (y > max_y) max_y = y; *dst_current = color; } dst_current++; } /* Next row */ dst_buffer += dst_stride; } /* Restrict destination rect to only updated pixels */ if (max_x >= min_x && max_y >= min_y) { rect->x += min_x; rect->y += min_y; rect->width = max_x - min_x + 1; rect->height = max_y - min_y + 1; } else { rect->width = 0; rect->height = 0; } } /** * Applies the Porter-Duff "over" composite operator, blending the two given * color components using the given alpha value. * * @param dst * The destination color component. * * @param src * The source color component. * * @param alpha * The alpha value which applies to the blending operation. * * @return * The result of applying the Porter-Duff "over" composite operator to the * given source and destination components. */ static int guac_common_surface_blend_component(int dst, int src, int alpha) { int blended = src + dst * (0xFF - alpha); /* Do not exceed maximum component value */ if (blended > 0xFF) return 0xFF; return blended; } /** * Applies the Porter-Duff "over" composite operator, blending each component * of the two given ARGB colors. * * @param dst * The destination ARGB color. * * @param src * The source ARGB color. * * @return * The result of applying the Porter-Duff "over" composite operator to the * given source and destination colors. */ static uint32_t guac_common_surface_argb_blend(uint32_t dst, uint32_t src) { /* Separate destination ARGB color into its components */ int dst_a = (dst >> 24) & 0xFF; int dst_r = (dst >> 16) & 0xFF; int dst_g = (dst >> 8) & 0xFF; int dst_b = dst & 0xFF; /* Separate source ARGB color into its components */ int src_a = (src >> 24) & 0xFF; int src_r = (src >> 16) & 0xFF; int src_g = (src >> 8) & 0xFF; int src_b = src & 0xFF; /* If source is fully opaque (or destination is fully transparent), the * blended result is the source */ if (src_a == 0xFF || dst_a == 0x00) return src; /* If source is fully transparent, the blended result is the destination */ if (src_a == 0x00) return dst; /* Otherwise, blend each ARGB component, assuming pre-multiplied alpha */ int r = guac_common_surface_blend_component(dst_r, src_r, src_a); int g = guac_common_surface_blend_component(dst_g, src_g, src_a); int b = guac_common_surface_blend_component(dst_b, src_b, src_a); int a = guac_common_surface_blend_component(dst_a, src_a, src_a); /* Recombine blended components */ return (a << 24) | (r << 16) | (g << 8) | b; } /** * Copies data from the given buffer to the surface at the given coordinates. * The dimensions and location of the destination rectangle will be altered * to remove as many unchanged pixels as possible. * * @param src_buffer The buffer to copy. * @param src_stride The number of bytes in each row of the source buffer. * @param sx The X coordinate of the source rectangle. * @param sy The Y coordinate of the source rectangle. * @param dst The destination surface. * @param rect The destination rectangle. * @param opaque Non-zero if the source surface is opaque (its alpha channel * should be ignored), zero otherwise. */ static void __guac_common_surface_put(unsigned char* src_buffer, int src_stride, int* sx, int* sy, guac_common_surface* dst, guac_common_rect* rect, int opaque) { unsigned char* dst_buffer = dst->buffer; int dst_stride = dst->stride; int x, y; int min_x = rect->width; int min_y = rect->height; int max_x = 0; int max_y = 0; int orig_x = rect->x; int orig_y = rect->y; src_buffer += src_stride * (*sy) + 4 * (*sx); dst_buffer += (dst_stride * rect->y) + (4 * rect->x); /* For each row */ for (y=0; y < rect->height; y++) { uint32_t* src_current = (uint32_t*) src_buffer; uint32_t* dst_current = (uint32_t*) dst_buffer; /* Copy row */ for (x=0; x < rect->width; x++) { uint32_t color; /* Get source and destination color values */ uint32_t src_color = *src_current; uint32_t dst_color = *dst_current; /* Ignore alpha channel if opaque */ if (opaque) color = src_color | 0xFF000000; /* Otherwise, perform alpha blending operation */ else color = guac_common_surface_argb_blend(dst_color, src_color); /* If the destination color is changing, update rectangle bounds * and store the new color */ if (dst_color != color) { if (x < min_x) min_x = x; if (y < min_y) min_y = y; if (x > max_x) max_x = x; if (y > max_y) max_y = y; *dst_current = color; } /* Advance to next pixel */ src_current++; dst_current++; } /* Next row */ src_buffer += src_stride; dst_buffer += dst_stride; } /* Restrict destination rect to only updated pixels */ if (max_x >= min_x && max_y >= min_y) { rect->x += min_x; rect->y += min_y; rect->width = max_x - min_x + 1; rect->height = max_y - min_y + 1; } else { rect->width = 0; rect->height = 0; } /* Update source X/Y */ *sx += rect->x - orig_x; *sy += rect->y - orig_y; } /** * Fills the given surface with color, using the given buffer as a mask. Color * will be added to the given surface iff the corresponding pixel within the * buffer is opaque. * * @param src_buffer The buffer to use as a mask. * @param src_stride The number of bytes in each row of the source buffer. * @param sx The X coordinate of the source rectangle. * @param sy The Y coordinate of the source rectangle. * @param dst The destination surface. * @param rect The destination rectangle. * @param red The red component of the color of the fill. * @param green The green component of the color of the fill. * @param blue The blue component of the color of the fill. */ static void __guac_common_surface_fill_mask(unsigned char* src_buffer, int src_stride, int sx, int sy, guac_common_surface* dst, guac_common_rect* rect, int red, int green, int blue) { unsigned char* dst_buffer = dst->buffer; int dst_stride = dst->stride; uint32_t color = 0xFF000000 | (red << 16) | (green << 8) | blue; int x, y; src_buffer += src_stride*sy + 4*sx; dst_buffer += (dst_stride * rect->y) + (4 * rect->x); /* For each row */ for (y=0; y < rect->height; y++) { uint32_t* src_current = (uint32_t*) src_buffer; uint32_t* dst_current = (uint32_t*) dst_buffer; /* Stencil row */ for (x=0; x < rect->width; x++) { /* Fill with color if opaque */ if (*src_current & 0xFF000000) *dst_current = color; src_current++; dst_current++; } /* Next row */ src_buffer += src_stride; dst_buffer += dst_stride; } } /** * Copies data from the given surface to the given destination surface using * the specified transfer function. * * @param src_buffer The buffer to copy. * @param src_stride The number of bytes in each row of the source buffer. * @param sx The X coordinate of the source rectangle. * @param sy The Y coordinate of the source rectangle. * @param op The transfer function to use. * @param dst The destination surface. * @param rect The destination rectangle. */ static void __guac_common_surface_transfer(guac_common_surface* src, int* sx, int* sy, guac_transfer_function op, guac_common_surface* dst, guac_common_rect* rect) { unsigned char* src_buffer = src->buffer; unsigned char* dst_buffer = dst->buffer; int x, y; int src_stride, dst_stride; int step = 1; int min_x = rect->width - 1; int min_y = rect->height - 1; int max_x = 0; int max_y = 0; int orig_x = rect->x; int orig_y = rect->y; /* Copy forwards only if destination is in a different surface or is before source */ if (src != dst || rect->y < *sy || (rect->y == *sy && rect->x < *sx)) { src_buffer += src->stride * (*sy) + 4 * (*sx); dst_buffer += (dst->stride * rect->y) + (4 * rect->x); src_stride = src->stride; dst_stride = dst->stride; step = 1; } /* Otherwise, copy backwards */ else { src_buffer += src->stride * (*sy + rect->height - 1) + 4 * (*sx + rect->width - 1); dst_buffer += dst->stride * (rect->y + rect->height - 1) + 4 * (rect->x + rect->width - 1); src_stride = -src->stride; dst_stride = -dst->stride; step = -1; } /* For each row */ for (y=0; y < rect->height; y++) { uint32_t* src_current = (uint32_t*) src_buffer; uint32_t* dst_current = (uint32_t*) dst_buffer; /* Transfer each pixel in row */ for (x=0; x < rect->width; x++) { if (__guac_common_surface_transfer_int(op, src_current, dst_current)) { if (x < min_x) min_x = x; if (y < min_y) min_y = y; if (x > max_x) max_x = x; if (y > max_y) max_y = y; } src_current += step; dst_current += step; } /* Next row */ src_buffer += src_stride; dst_buffer += dst_stride; } /* Translate X coordinate space of moving backwards */ if (step < 0) { int old_max_x = max_x; max_x = rect->width - 1 - min_x; min_x = rect->width - 1 - old_max_x; } /* Translate Y coordinate space of moving backwards */ if (dst_stride < 0) { int old_max_y = max_y; max_y = rect->height - 1 - min_y; min_y = rect->height - 1 - old_max_y; } /* Restrict destination rect to only updated pixels */ if (max_x >= min_x && max_y >= min_y) { rect->x += min_x; rect->y += min_y; rect->width = max_x - min_x + 1; rect->height = max_y - min_y + 1; } else { rect->width = 0; rect->height = 0; } /* Update source X/Y */ *sx += rect->x - orig_x; *sy += rect->y - orig_y; } guac_common_surface* guac_common_surface_alloc(guac_client* client, guac_socket* socket, const guac_layer* layer, int w, int h) { /* Calculate heat map dimensions */ int heat_width = GUAC_COMMON_SURFACE_HEAT_DIMENSION(w); int heat_height = GUAC_COMMON_SURFACE_HEAT_DIMENSION(h); /* Init surface */ guac_common_surface* surface = calloc(1, sizeof(guac_common_surface)); surface->client = client; surface->socket = socket; surface->layer = layer; surface->parent = GUAC_DEFAULT_LAYER; surface->opacity = 0xFF; surface->width = w; surface->height = h; pthread_mutex_init(&surface->_lock, NULL); /* Create corresponding Cairo surface */ surface->stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w); surface->buffer = calloc(h, surface->stride); /* Create corresponding heat map */ surface->heat_map = calloc(heat_width * heat_height, sizeof(guac_common_surface_heat_cell)); /* Reset clipping rect */ guac_common_surface_reset_clip(surface); /* Layers must initially exist */ if (layer->index >= 0) { guac_protocol_send_size(socket, layer, w, h); surface->realized = 1; } /* Defer creation of buffers */ else surface->realized = 0; return surface; } void guac_common_surface_free(guac_common_surface* surface) { /* Only dispose of surface if it exists */ if (surface->realized) guac_protocol_send_dispose(surface->socket, surface->layer); pthread_mutex_destroy(&surface->_lock); free(surface->heat_map); free(surface->buffer); free(surface); } void guac_common_surface_resize(guac_common_surface* surface, int w, int h) { pthread_mutex_lock(&surface->_lock); /* Ignore if resize will have no effect */ if (w == surface->width && h == surface->height) goto complete; guac_socket* socket = surface->socket; const guac_layer* layer = surface->layer; unsigned char* old_buffer; int old_stride; guac_common_rect old_rect; int sx = 0; int sy = 0; /* Calculate heat map dimensions */ int heat_width = GUAC_COMMON_SURFACE_HEAT_DIMENSION(w); int heat_height = GUAC_COMMON_SURFACE_HEAT_DIMENSION(h); /* Copy old surface data */ old_buffer = surface->buffer; old_stride = surface->stride; guac_common_rect_init(&old_rect, 0, 0, surface->width, surface->height); /* Re-initialize at new size */ surface->width = w; surface->height = h; surface->stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w); surface->buffer = calloc(h, surface->stride); __guac_common_bound_rect(surface, &surface->clip_rect, NULL, NULL); /* Copy relevant old data */ __guac_common_bound_rect(surface, &old_rect, NULL, NULL); __guac_common_surface_put(old_buffer, old_stride, &sx, &sy, surface, &old_rect, 1); /* Free old data */ free(old_buffer); /* Allocate completely new heat map (can safely discard old stats) */ free(surface->heat_map); surface->heat_map = calloc(heat_width * heat_height, sizeof(guac_common_surface_heat_cell)); /* Resize dirty rect to fit new surface dimensions */ if (surface->dirty) { __guac_common_bound_rect(surface, &surface->dirty_rect, NULL, NULL); if (surface->dirty_rect.width <= 0 || surface->dirty_rect.height <= 0) surface->dirty = 0; } /* Update Guacamole layer */ if (surface->realized) guac_protocol_send_size(socket, layer, w, h); complete: pthread_mutex_unlock(&surface->_lock); } void guac_common_surface_draw(guac_common_surface* surface, int x, int y, cairo_surface_t* src) { pthread_mutex_lock(&surface->_lock); unsigned char* buffer = cairo_image_surface_get_data(src); cairo_format_t format = cairo_image_surface_get_format(src); int stride = cairo_image_surface_get_stride(src); int w = cairo_image_surface_get_width(src); int h = cairo_image_surface_get_height(src); int sx = 0; int sy = 0; guac_common_rect rect; guac_common_rect_init(&rect, x, y, w, h); /* Clip operation */ __guac_common_clip_rect(surface, &rect, &sx, &sy); if (rect.width <= 0 || rect.height <= 0) goto complete; /* Update backing surface */ __guac_common_surface_put(buffer, stride, &sx, &sy, surface, &rect, format != CAIRO_FORMAT_ARGB32); if (rect.width <= 0 || rect.height <= 0) goto complete; /* Update the heat map for the update rectangle. */ guac_timestamp time = guac_timestamp_current(); __guac_common_surface_touch_rect(surface, &rect, time); /* Flush if not combining */ if (!__guac_common_should_combine(surface, &rect, 0)) __guac_common_surface_flush_deferred(surface); /* Always defer draws */ __guac_common_mark_dirty(surface, &rect); complete: pthread_mutex_unlock(&surface->_lock); } void guac_common_surface_paint(guac_common_surface* surface, int x, int y, cairo_surface_t* src, int red, int green, int blue) { pthread_mutex_lock(&surface->_lock); unsigned char* buffer = cairo_image_surface_get_data(src); int stride = cairo_image_surface_get_stride(src); int w = cairo_image_surface_get_width(src); int h = cairo_image_surface_get_height(src); int sx = 0; int sy = 0; guac_common_rect rect; guac_common_rect_init(&rect, x, y, w, h); /* Clip operation */ __guac_common_clip_rect(surface, &rect, &sx, &sy); if (rect.width <= 0 || rect.height <= 0) goto complete; /* Update backing surface */ __guac_common_surface_fill_mask(buffer, stride, sx, sy, surface, &rect, red, green, blue); /* Flush if not combining */ if (!__guac_common_should_combine(surface, &rect, 0)) __guac_common_surface_flush_deferred(surface); /* Always defer draws */ __guac_common_mark_dirty(surface, &rect); complete: pthread_mutex_unlock(&surface->_lock); } void guac_common_surface_copy(guac_common_surface* src, int sx, int sy, int w, int h, guac_common_surface* dst, int dx, int dy) { /* Lock both surfaces */ pthread_mutex_lock(&dst->_lock); if (src != dst) pthread_mutex_lock(&src->_lock); guac_socket* socket = dst->socket; const guac_layer* src_layer = src->layer; const guac_layer* dst_layer = dst->layer; guac_common_rect srect; guac_common_rect_init(&srect, sx, sy, w, h); /* Clip operation source rect to bounds */ __guac_common_bound_rect(src, &srect, &dx, &dy); if (srect.width <= 0 || srect.height <= 0) goto complete; guac_common_rect drect; guac_common_rect_init(&drect, dx, dy, srect.width, srect.height); /* Clip operation destination rect */ __guac_common_clip_rect(dst, &drect, &srect.x, &srect.y); if (drect.width <= 0 || drect.height <= 0) goto complete; /* NOTE: Being the last rectangle to be adjusted, only the width/height of * drect is now correct! */ /* Update backing surface first only if drect cannot intersect srect */ if (src != dst) { __guac_common_surface_transfer(src, &srect.x, &srect.y, GUAC_TRANSFER_BINARY_SRC, dst, &drect); if (drect.width <= 0 || drect.height <= 0) goto complete; } /* Defer if combining */ if (__guac_common_should_combine(dst, &drect, 1)) __guac_common_mark_dirty(dst, &drect); /* Otherwise, flush and draw immediately */ else { __guac_common_surface_flush(dst); __guac_common_surface_flush(src); guac_protocol_send_copy(socket, src_layer, srect.x, srect.y, drect.width, drect.height, GUAC_COMP_OVER, dst_layer, drect.x, drect.y); dst->realized = 1; } /* Update backing surface last if drect can intersect srect */ if (src == dst) __guac_common_surface_transfer(src, &srect.x, &srect.y, GUAC_TRANSFER_BINARY_SRC, dst, &drect); complete: /* Unlock both surfaces */ pthread_mutex_unlock(&dst->_lock); if (src != dst) pthread_mutex_unlock(&src->_lock); } void guac_common_surface_transfer(guac_common_surface* src, int sx, int sy, int w, int h, guac_transfer_function op, guac_common_surface* dst, int dx, int dy) { /* Lock both surfaces */ pthread_mutex_lock(&dst->_lock); if (src != dst) pthread_mutex_lock(&src->_lock); guac_socket* socket = dst->socket; const guac_layer* src_layer = src->layer; const guac_layer* dst_layer = dst->layer; guac_common_rect srect; guac_common_rect_init(&srect, sx, sy, w, h); /* Clip operation source rect to bounds */ __guac_common_bound_rect(src, &srect, &dx, &dy); if (srect.width <= 0 || srect.height <= 0) goto complete; guac_common_rect drect; guac_common_rect_init(&drect, dx, dy, srect.width, srect.height); /* Clip operation destination rect */ __guac_common_clip_rect(dst, &drect, &srect.x, &srect.y); if (drect.width <= 0 || drect.height <= 0) goto complete; /* NOTE: Being the last rectangle to be adjusted, only the width/height of * drect is now correct! */ /* Update backing surface first only if drect cannot intersect srect */ if (src != dst) { __guac_common_surface_transfer(src, &srect.x, &srect.y, op, dst, &drect); if (drect.width <= 0 || drect.height <= 0) goto complete; } /* Defer if combining */ if (__guac_common_should_combine(dst, &drect, 1)) __guac_common_mark_dirty(dst, &drect); /* Otherwise, flush and draw immediately */ else { __guac_common_surface_flush(dst); __guac_common_surface_flush(src); guac_protocol_send_transfer(socket, src_layer, srect.x, srect.y, drect.width, drect.height, op, dst_layer, drect.x, drect.y); dst->realized = 1; } /* Update backing surface last if drect can intersect srect */ if (src == dst) __guac_common_surface_transfer(src, &srect.x, &srect.y, op, dst, &drect); complete: /* Unlock both surfaces */ pthread_mutex_unlock(&dst->_lock); if (src != dst) pthread_mutex_unlock(&src->_lock); } void guac_common_surface_set(guac_common_surface* surface, int x, int y, int w, int h, int red, int green, int blue, int alpha) { pthread_mutex_lock(&surface->_lock); guac_socket* socket = surface->socket; const guac_layer* layer = surface->layer; guac_common_rect rect; guac_common_rect_init(&rect, x, y, w, h); /* Clip operation */ __guac_common_clip_rect(surface, &rect, NULL, NULL); if (rect.width <= 0 || rect.height <= 0) goto complete; /* Update backing surface */ __guac_common_surface_set(surface, &rect, red, green, blue, alpha); if (rect.width <= 0 || rect.height <= 0) goto complete; /* Handle as normal draw if non-opaque */ if (alpha != 0xFF) { /* Flush if not combining */ if (!__guac_common_should_combine(surface, &rect, 0)) __guac_common_surface_flush_deferred(surface); /* Always defer draws */ __guac_common_mark_dirty(surface, &rect); } /* Defer if combining */ else if (__guac_common_should_combine(surface, &rect, 1)) __guac_common_mark_dirty(surface, &rect); /* Otherwise, flush and draw immediately */ else { __guac_common_surface_flush(surface); guac_protocol_send_rect(socket, layer, rect.x, rect.y, rect.width, rect.height); guac_protocol_send_cfill(socket, GUAC_COMP_OVER, layer, red, green, blue, alpha); surface->realized = 1; } complete: pthread_mutex_unlock(&surface->_lock); } void guac_common_surface_clip(guac_common_surface* surface, int x, int y, int w, int h) { pthread_mutex_lock(&surface->_lock); guac_common_rect clip; /* Init clipping rectangle if clipping not already applied */ if (!surface->clipped) { guac_common_rect_init(&surface->clip_rect, 0, 0, surface->width, surface->height); surface->clipped = 1; } guac_common_rect_init(&clip, x, y, w, h); guac_common_rect_constrain(&surface->clip_rect, &clip); pthread_mutex_unlock(&surface->_lock); } void guac_common_surface_reset_clip(guac_common_surface* surface) { pthread_mutex_lock(&surface->_lock); surface->clipped = 0; pthread_mutex_unlock(&surface->_lock); } /** * Flushes the bitmap update currently described by the dirty rectangle within * the given surface directly via an "img" instruction as PNG data. The * resulting instructions will be sent over the socket associated with the * given surface. * * @param surface * The surface to flush. * * @param opaque * Whether the rectangle being flushed contains only fully-opaque pixels. */ static void __guac_common_surface_flush_to_png(guac_common_surface* surface, int opaque) { if (surface->dirty) { guac_socket* socket = surface->socket; const guac_layer* layer = surface->layer; /* Get Cairo surface for specified rect */ unsigned char* buffer = surface->buffer + surface->dirty_rect.y * surface->stride + surface->dirty_rect.x * 4; cairo_surface_t* rect; /* Use RGB24 if the image is fully opaque */ if (opaque) rect = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_RGB24, surface->dirty_rect.width, surface->dirty_rect.height, surface->stride); /* Otherwise ARGB32 is needed */ else { rect = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32, surface->dirty_rect.width, surface->dirty_rect.height, surface->stride); /* Clear destination rect first */ guac_protocol_send_rect(socket, layer, surface->dirty_rect.x, surface->dirty_rect.y, surface->dirty_rect.width, surface->dirty_rect.height); guac_protocol_send_cfill(socket, GUAC_COMP_ROUT, layer, 0x00, 0x00, 0x00, 0xFF); } /* Send PNG for rect */ guac_client_stream_png(surface->client, socket, GUAC_COMP_OVER, layer, surface->dirty_rect.x, surface->dirty_rect.y, rect); cairo_surface_destroy(rect); surface->realized = 1; /* Surface is no longer dirty */ surface->dirty = 0; } } /** * Returns an appropriate quality between 0 and 100 for lossy encoding * depending on the current processing lag calculated for the given client. * * @param client * The client for which the lossy quality is being calculated. * * @return * A value between 0 and 100 inclusive which seems appropriate for the * client based on lag measurements. */ static int guac_common_surface_suggest_quality(guac_client* client) { int lag = guac_client_get_processing_lag(client); /* Scale quality linearly from 90 to 30 as lag varies from 20ms to 80ms */ int quality = 90 - (lag - 20); /* Do not exceed 90 for quality */ if (quality > 90) return 90; /* Do not go below 30 for quality */ if (quality < 30) return 30; return quality; } /** * Flushes the bitmap update currently described by the dirty rectangle within * the given surface directly via an "img" instruction as JPEG data. The * resulting instructions will be sent over the socket associated with the * given surface. * * @param surface * The surface to flush. */ static void __guac_common_surface_flush_to_jpeg(guac_common_surface* surface) { if (surface->dirty) { guac_socket* socket = surface->socket; const guac_layer* layer = surface->layer; guac_common_rect max; guac_common_rect_init(&max, 0, 0, surface->width, surface->height); /* Expand the dirty rect size to fit in a grid with cells equal to the * minimum JPEG block size */ guac_common_rect_expand_to_grid(GUAC_SURFACE_JPEG_BLOCK_SIZE, &surface->dirty_rect, &max); /* Get Cairo surface for specified rect */ unsigned char* buffer = surface->buffer + surface->dirty_rect.y * surface->stride + surface->dirty_rect.x * 4; cairo_surface_t* rect = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_RGB24, surface->dirty_rect.width, surface->dirty_rect.height, surface->stride); /* Send JPEG for rect */ guac_client_stream_jpeg(surface->client, socket, GUAC_COMP_OVER, layer, surface->dirty_rect.x, surface->dirty_rect.y, rect, guac_common_surface_suggest_quality(surface->client)); cairo_surface_destroy(rect); surface->realized = 1; /* Surface is no longer dirty */ surface->dirty = 0; } } /** * Flushes the bitmap update currently described by the dirty rectangle within * the given surface directly via an "img" instruction as WebP data. The * resulting instructions will be sent over the socket associated with the * given surface. * * @param surface * The surface to flush. * * @param opaque * Whether the rectangle being flushed contains only fully-opaque pixels. */ static void __guac_common_surface_flush_to_webp(guac_common_surface* surface, int opaque) { if (surface->dirty) { guac_socket* socket = surface->socket; const guac_layer* layer = surface->layer; guac_common_rect max; guac_common_rect_init(&max, 0, 0, surface->width, surface->height); /* Expand the dirty rect size to fit in a grid with cells equal to the * minimum WebP block size */ guac_common_rect_expand_to_grid(GUAC_SURFACE_WEBP_BLOCK_SIZE, &surface->dirty_rect, &max); /* Get Cairo surface for specified rect */ unsigned char* buffer = surface->buffer + surface->dirty_rect.y * surface->stride + surface->dirty_rect.x * 4; cairo_surface_t* rect; /* Use RGB24 if the image is fully opaque */ if (opaque) rect = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_RGB24, surface->dirty_rect.width, surface->dirty_rect.height, surface->stride); /* Otherwise ARGB32 is needed */ else rect = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32, surface->dirty_rect.width, surface->dirty_rect.height, surface->stride); /* Send WebP for rect */ guac_client_stream_webp(surface->client, socket, GUAC_COMP_OVER, layer, surface->dirty_rect.x, surface->dirty_rect.y, rect, guac_common_surface_suggest_quality(surface->client), 0); cairo_surface_destroy(rect); surface->realized = 1; /* Surface is no longer dirty */ surface->dirty = 0; } } /** * Comparator for instances of guac_common_surface_bitmap_rect, the elements * which make up a surface's bitmap buffer. * * @see qsort */ static int __guac_common_surface_bitmap_rect_compare(const void* a, const void* b) { guac_common_surface_bitmap_rect* ra = (guac_common_surface_bitmap_rect*) a; guac_common_surface_bitmap_rect* rb = (guac_common_surface_bitmap_rect*) b; /* Order roughly top to bottom, left to right */ if (ra->rect.y != rb->rect.y) return ra->rect.y - rb->rect.y; if (ra->rect.x != rb->rect.x) return ra->rect.x - rb->rect.x; /* Wider updates should come first (more likely to intersect later) */ if (ra->rect.width != rb->rect.width) return rb->rect.width - ra->rect.width; /* Shorter updates should come first (less likely to increase cost) */ return ra->rect.height - rb->rect.height; } /** * Flushes only the properties of the given surface, such as layer location or * opacity. Image state is not flushed. If the surface represents a buffer or * the default layer, this function has no effect. * * @param surface * The surface to flush. */ static void __guac_common_surface_flush_properties( guac_common_surface* surface) { guac_socket* socket = surface->socket; /* Only applicable to non-default visible layers */ if (surface->layer->index <= 0) return; /* Flush opacity */ if (surface->opacity_dirty) { guac_protocol_send_shade(socket, surface->layer, surface->opacity); surface->opacity_dirty = 0; } /* Flush location and hierarchy */ if (surface->location_dirty) { guac_protocol_send_move(socket, surface->layer, surface->parent, surface->x, surface->y, surface->z); surface->location_dirty = 0; } } static void __guac_common_surface_flush(guac_common_surface* surface) { /* Flush final dirty rectangle to queue. */ __guac_common_surface_flush_to_queue(surface); guac_common_surface_bitmap_rect* current = surface->bitmap_queue; int i, j; int original_queue_length; int flushed = 0; original_queue_length = surface->bitmap_queue_length; /* Sort updates to make combination less costly */ qsort(surface->bitmap_queue, surface->bitmap_queue_length, sizeof(guac_common_surface_bitmap_rect), __guac_common_surface_bitmap_rect_compare); /* Flush all rects in queue */ for (i=0; i < surface->bitmap_queue_length; i++) { /* Get next unflushed candidate */ guac_common_surface_bitmap_rect* candidate = current; if (!candidate->flushed) { int combined = 0; /* Build up rect as much as possible */ for (j=i; j < surface->bitmap_queue_length; j++) { if (!candidate->flushed) { /* Clip candidate within current bounds */ __guac_common_bound_rect(surface, &candidate->rect, NULL, NULL); if (candidate->rect.width <= 0 || candidate->rect.height <= 0) candidate->flushed = 1; /* Combine if reasonable */ else if (__guac_common_should_combine(surface, &candidate->rect, 0) || !surface->dirty) { __guac_common_mark_dirty(surface, &candidate->rect); candidate->flushed = 1; combined++; } } candidate++; } /* Re-add to queue if there's room and this update was modified or we expect others might be */ if ((combined > 1 || i < original_queue_length) && surface->bitmap_queue_length < GUAC_COMMON_SURFACE_QUEUE_SIZE) __guac_common_surface_flush_to_queue(surface); /* Flush as bitmap otherwise */ else if (surface->dirty) { flushed++; int opaque = __guac_common_surface_is_opaque(surface, &surface->dirty_rect); /* Prefer WebP when reasonable */ if (__guac_common_surface_should_use_webp(surface, &surface->dirty_rect)) __guac_common_surface_flush_to_webp(surface, opaque); /* If not WebP, JPEG is the next best (lossy) choice */ else if (opaque && __guac_common_surface_should_use_jpeg( surface, &surface->dirty_rect)) __guac_common_surface_flush_to_jpeg(surface); /* Use PNG if no lossy formats are appropriate */ else __guac_common_surface_flush_to_png(surface, opaque); } } current++; } /* Flush complete */ surface->bitmap_queue_length = 0; } void guac_common_surface_flush(guac_common_surface* surface) { pthread_mutex_lock(&surface->_lock); /* Flush any applicable layer properties */ __guac_common_surface_flush_properties(surface); /* Flush surface contents */ __guac_common_surface_flush(surface); pthread_mutex_unlock(&surface->_lock); } void guac_common_surface_dup(guac_common_surface* surface, guac_user* user, guac_socket* socket) { pthread_mutex_lock(&surface->_lock); /* Do nothing if not realized */ if (!surface->realized) goto complete; /* Synchronize layer-specific properties if applicable */ if (surface->layer->index > 0) { /* Synchronize opacity */ guac_protocol_send_shade(socket, surface->layer, surface->opacity); /* Synchronize location and hierarchy */ guac_protocol_send_move(socket, surface->layer, surface->parent, surface->x, surface->y, surface->z); } /* Sync size to new socket */ guac_protocol_send_size(socket, surface->layer, surface->width, surface->height); /* Send contents of layer, if non-empty */ if (surface->width > 0 && surface->height > 0) { /* Get entire surface */ cairo_surface_t* rect = cairo_image_surface_create_for_data( surface->buffer, CAIRO_FORMAT_ARGB32, surface->width, surface->height, surface->stride); /* Send PNG for rect */ guac_user_stream_png(user, socket, GUAC_COMP_OVER, surface->layer, 0, 0, rect); cairo_surface_destroy(rect); } complete: pthread_mutex_unlock(&surface->_lock); } guacamole-server-1.3.0/src/common/json.c0000644000175100001440000001213213613156714015074 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/json.h" #include #include #include #include #include #include #include void guac_common_json_flush(guac_user* user, guac_stream* stream, guac_common_json_state* json_state) { /* If JSON buffer is non-empty, write contents to blob and reset */ if (json_state->size > 0) { guac_protocol_send_blob(user->socket, stream, json_state->buffer, json_state->size); /* Reset JSON buffer size */ json_state->size = 0; } } int guac_common_json_write(guac_user* user, guac_stream* stream, guac_common_json_state* json_state, const char* buffer, int length) { int blob_written = 0; /* * Append to and flush the JSON buffer as necessary to write the given * data */ while (length > 0) { /* Ensure provided data does not exceed size of buffer */ int blob_length = length; if (blob_length > sizeof(json_state->buffer)) blob_length = sizeof(json_state->buffer); /* Flush if more room is needed */ if (json_state->size + blob_length > sizeof(json_state->buffer)) { guac_common_json_flush(user, stream, json_state); blob_written = 1; } /* Append data to JSON buffer */ memcpy(json_state->buffer + json_state->size, buffer, blob_length); json_state->size += blob_length; /* Advance to next blob of data */ buffer += blob_length; length -= blob_length; } return blob_written; } int guac_common_json_write_string(guac_user* user, guac_stream* stream, guac_common_json_state* json_state, const char* str) { int blob_written = 0; /* Write starting quote */ blob_written |= guac_common_json_write(user, stream, json_state, "\"", 1); /* Write given string, escaping as necessary */ const char* current = str; for (; *current != '\0'; current++) { /* Escape all quotes */ if (*current == '"') { /* Write any string content up to current character */ if (current != str) blob_written |= guac_common_json_write(user, stream, json_state, str, current - str); /* Escape the quote that was just read */ blob_written |= guac_common_json_write(user, stream, json_state, "\\", 1); /* Reset string */ str = current; } } /* Write any remaining string content */ if (current != str) blob_written |= guac_common_json_write(user, stream, json_state, str, current - str); /* Write ending quote */ blob_written |= guac_common_json_write(user, stream, json_state, "\"", 1); return blob_written; } int guac_common_json_write_property(guac_user* user, guac_stream* stream, guac_common_json_state* json_state, const char* name, const char* value) { int blob_written = 0; /* Write leading comma if not first property */ if (json_state->properties_written != 0) blob_written |= guac_common_json_write(user, stream, json_state, ",", 1); /* Write property name */ blob_written |= guac_common_json_write_string(user, stream, json_state, name); /* Separate name from value with colon */ blob_written |= guac_common_json_write(user, stream, json_state, ":", 1); /* Write property value */ blob_written |= guac_common_json_write_string(user, stream, json_state, value); json_state->properties_written++; return blob_written; } void guac_common_json_begin_object(guac_user* user, guac_stream* stream, guac_common_json_state* json_state) { /* Init JSON state */ json_state->size = 0; json_state->properties_written = 0; /* Write leading brace - no blob can possibly be written by this */ assert(!guac_common_json_write(user, stream, json_state, "{", 1)); } int guac_common_json_end_object(guac_user* user, guac_stream* stream, guac_common_json_state* json_state) { /* Write final brace of JSON object */ return guac_common_json_write(user, stream, json_state, "}", 1); } guacamole-server-1.3.0/src/common/Makefile.in0000644000175100001440000013410713772471101016027 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/common ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libguac_common_la_DEPENDENCIES = am_libguac_common_la_OBJECTS = libguac_common_la-io.lo \ libguac_common_la-blank_cursor.lo \ libguac_common_la-clipboard.lo libguac_common_la-cursor.lo \ libguac_common_la-display.lo libguac_common_la-dot_cursor.lo \ libguac_common_la-ibar_cursor.lo libguac_common_la-iconv.lo \ libguac_common_la-json.lo libguac_common_la-list.lo \ libguac_common_la-pointer_cursor.lo \ libguac_common_la-recording.lo libguac_common_la-rect.lo \ libguac_common_la-string.lo libguac_common_la-surface.lo libguac_common_la_OBJECTS = $(am_libguac_common_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libguac_common_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libguac_common_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libguac_common_la-blank_cursor.Plo \ ./$(DEPDIR)/libguac_common_la-clipboard.Plo \ ./$(DEPDIR)/libguac_common_la-cursor.Plo \ ./$(DEPDIR)/libguac_common_la-display.Plo \ ./$(DEPDIR)/libguac_common_la-dot_cursor.Plo \ ./$(DEPDIR)/libguac_common_la-ibar_cursor.Plo \ ./$(DEPDIR)/libguac_common_la-iconv.Plo \ ./$(DEPDIR)/libguac_common_la-io.Plo \ ./$(DEPDIR)/libguac_common_la-json.Plo \ ./$(DEPDIR)/libguac_common_la-list.Plo \ ./$(DEPDIR)/libguac_common_la-pointer_cursor.Plo \ ./$(DEPDIR)/libguac_common_la-recording.Plo \ ./$(DEPDIR)/libguac_common_la-rect.Plo \ ./$(DEPDIR)/libguac_common_la-string.Plo \ ./$(DEPDIR)/libguac_common_la-surface.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libguac_common_la_SOURCES) DIST_SOURCES = $(libguac_common_la_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir distdir-am am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 noinst_LTLIBRARIES = libguac_common.la SUBDIRS = . tests noinst_HEADERS = \ common/io.h \ common/blank_cursor.h \ common/clipboard.h \ common/cursor.h \ common/defaults.h \ common/display.h \ common/dot_cursor.h \ common/ibar_cursor.h \ common/iconv.h \ common/json.h \ common/list.h \ common/pointer_cursor.h \ common/recording.h \ common/rect.h \ common/string.h \ common/surface.h libguac_common_la_SOURCES = \ io.c \ blank_cursor.c \ clipboard.c \ cursor.c \ display.c \ dot_cursor.c \ ibar_cursor.c \ iconv.c \ json.c \ list.c \ pointer_cursor.c \ recording.c \ rect.c \ string.c \ surface.c libguac_common_la_CFLAGS = \ -Werror -Wall -pedantic \ @LIBGUAC_INCLUDE@ libguac_common_la_LIBADD = \ @LIBGUAC_LTLIB@ all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/common/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/common/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libguac_common.la: $(libguac_common_la_OBJECTS) $(libguac_common_la_DEPENDENCIES) $(EXTRA_libguac_common_la_DEPENDENCIES) $(AM_V_CCLD)$(libguac_common_la_LINK) $(libguac_common_la_OBJECTS) $(libguac_common_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-blank_cursor.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-clipboard.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-cursor.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-display.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-dot_cursor.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-ibar_cursor.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-iconv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-io.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-json.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-pointer_cursor.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-recording.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-rect.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-string.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libguac_common_la-surface.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libguac_common_la-io.lo: io.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-io.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-io.Tpo -c -o libguac_common_la-io.lo `test -f 'io.c' || echo '$(srcdir)/'`io.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-io.Tpo $(DEPDIR)/libguac_common_la-io.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='io.c' object='libguac_common_la-io.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-io.lo `test -f 'io.c' || echo '$(srcdir)/'`io.c libguac_common_la-blank_cursor.lo: blank_cursor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-blank_cursor.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-blank_cursor.Tpo -c -o libguac_common_la-blank_cursor.lo `test -f 'blank_cursor.c' || echo '$(srcdir)/'`blank_cursor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-blank_cursor.Tpo $(DEPDIR)/libguac_common_la-blank_cursor.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='blank_cursor.c' object='libguac_common_la-blank_cursor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-blank_cursor.lo `test -f 'blank_cursor.c' || echo '$(srcdir)/'`blank_cursor.c libguac_common_la-clipboard.lo: clipboard.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-clipboard.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-clipboard.Tpo -c -o libguac_common_la-clipboard.lo `test -f 'clipboard.c' || echo '$(srcdir)/'`clipboard.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-clipboard.Tpo $(DEPDIR)/libguac_common_la-clipboard.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='clipboard.c' object='libguac_common_la-clipboard.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-clipboard.lo `test -f 'clipboard.c' || echo '$(srcdir)/'`clipboard.c libguac_common_la-cursor.lo: cursor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-cursor.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-cursor.Tpo -c -o libguac_common_la-cursor.lo `test -f 'cursor.c' || echo '$(srcdir)/'`cursor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-cursor.Tpo $(DEPDIR)/libguac_common_la-cursor.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cursor.c' object='libguac_common_la-cursor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-cursor.lo `test -f 'cursor.c' || echo '$(srcdir)/'`cursor.c libguac_common_la-display.lo: display.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-display.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-display.Tpo -c -o libguac_common_la-display.lo `test -f 'display.c' || echo '$(srcdir)/'`display.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-display.Tpo $(DEPDIR)/libguac_common_la-display.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display.c' object='libguac_common_la-display.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-display.lo `test -f 'display.c' || echo '$(srcdir)/'`display.c libguac_common_la-dot_cursor.lo: dot_cursor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-dot_cursor.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-dot_cursor.Tpo -c -o libguac_common_la-dot_cursor.lo `test -f 'dot_cursor.c' || echo '$(srcdir)/'`dot_cursor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-dot_cursor.Tpo $(DEPDIR)/libguac_common_la-dot_cursor.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dot_cursor.c' object='libguac_common_la-dot_cursor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-dot_cursor.lo `test -f 'dot_cursor.c' || echo '$(srcdir)/'`dot_cursor.c libguac_common_la-ibar_cursor.lo: ibar_cursor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-ibar_cursor.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-ibar_cursor.Tpo -c -o libguac_common_la-ibar_cursor.lo `test -f 'ibar_cursor.c' || echo '$(srcdir)/'`ibar_cursor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-ibar_cursor.Tpo $(DEPDIR)/libguac_common_la-ibar_cursor.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ibar_cursor.c' object='libguac_common_la-ibar_cursor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-ibar_cursor.lo `test -f 'ibar_cursor.c' || echo '$(srcdir)/'`ibar_cursor.c libguac_common_la-iconv.lo: iconv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-iconv.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-iconv.Tpo -c -o libguac_common_la-iconv.lo `test -f 'iconv.c' || echo '$(srcdir)/'`iconv.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-iconv.Tpo $(DEPDIR)/libguac_common_la-iconv.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iconv.c' object='libguac_common_la-iconv.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-iconv.lo `test -f 'iconv.c' || echo '$(srcdir)/'`iconv.c libguac_common_la-json.lo: json.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-json.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-json.Tpo -c -o libguac_common_la-json.lo `test -f 'json.c' || echo '$(srcdir)/'`json.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-json.Tpo $(DEPDIR)/libguac_common_la-json.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='json.c' object='libguac_common_la-json.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-json.lo `test -f 'json.c' || echo '$(srcdir)/'`json.c libguac_common_la-list.lo: list.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-list.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-list.Tpo -c -o libguac_common_la-list.lo `test -f 'list.c' || echo '$(srcdir)/'`list.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-list.Tpo $(DEPDIR)/libguac_common_la-list.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='list.c' object='libguac_common_la-list.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-list.lo `test -f 'list.c' || echo '$(srcdir)/'`list.c libguac_common_la-pointer_cursor.lo: pointer_cursor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-pointer_cursor.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-pointer_cursor.Tpo -c -o libguac_common_la-pointer_cursor.lo `test -f 'pointer_cursor.c' || echo '$(srcdir)/'`pointer_cursor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-pointer_cursor.Tpo $(DEPDIR)/libguac_common_la-pointer_cursor.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pointer_cursor.c' object='libguac_common_la-pointer_cursor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-pointer_cursor.lo `test -f 'pointer_cursor.c' || echo '$(srcdir)/'`pointer_cursor.c libguac_common_la-recording.lo: recording.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-recording.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-recording.Tpo -c -o libguac_common_la-recording.lo `test -f 'recording.c' || echo '$(srcdir)/'`recording.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-recording.Tpo $(DEPDIR)/libguac_common_la-recording.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='recording.c' object='libguac_common_la-recording.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-recording.lo `test -f 'recording.c' || echo '$(srcdir)/'`recording.c libguac_common_la-rect.lo: rect.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-rect.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-rect.Tpo -c -o libguac_common_la-rect.lo `test -f 'rect.c' || echo '$(srcdir)/'`rect.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-rect.Tpo $(DEPDIR)/libguac_common_la-rect.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rect.c' object='libguac_common_la-rect.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-rect.lo `test -f 'rect.c' || echo '$(srcdir)/'`rect.c libguac_common_la-string.lo: string.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-string.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-string.Tpo -c -o libguac_common_la-string.lo `test -f 'string.c' || echo '$(srcdir)/'`string.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-string.Tpo $(DEPDIR)/libguac_common_la-string.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string.c' object='libguac_common_la-string.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-string.lo `test -f 'string.c' || echo '$(srcdir)/'`string.c libguac_common_la-surface.lo: surface.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -MT libguac_common_la-surface.lo -MD -MP -MF $(DEPDIR)/libguac_common_la-surface.Tpo -c -o libguac_common_la-surface.lo `test -f 'surface.c' || echo '$(srcdir)/'`surface.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libguac_common_la-surface.Tpo $(DEPDIR)/libguac_common_la-surface.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='surface.c' object='libguac_common_la-surface.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libguac_common_la_CFLAGS) $(CFLAGS) -c -o libguac_common_la-surface.lo `test -f 'surface.c' || echo '$(srcdir)/'`surface.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-recursive -rm -f ./$(DEPDIR)/libguac_common_la-blank_cursor.Plo -rm -f ./$(DEPDIR)/libguac_common_la-clipboard.Plo -rm -f ./$(DEPDIR)/libguac_common_la-cursor.Plo -rm -f ./$(DEPDIR)/libguac_common_la-display.Plo -rm -f ./$(DEPDIR)/libguac_common_la-dot_cursor.Plo -rm -f ./$(DEPDIR)/libguac_common_la-ibar_cursor.Plo -rm -f ./$(DEPDIR)/libguac_common_la-iconv.Plo -rm -f ./$(DEPDIR)/libguac_common_la-io.Plo -rm -f ./$(DEPDIR)/libguac_common_la-json.Plo -rm -f ./$(DEPDIR)/libguac_common_la-list.Plo -rm -f ./$(DEPDIR)/libguac_common_la-pointer_cursor.Plo -rm -f ./$(DEPDIR)/libguac_common_la-recording.Plo -rm -f ./$(DEPDIR)/libguac_common_la-rect.Plo -rm -f ./$(DEPDIR)/libguac_common_la-string.Plo -rm -f ./$(DEPDIR)/libguac_common_la-surface.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/libguac_common_la-blank_cursor.Plo -rm -f ./$(DEPDIR)/libguac_common_la-clipboard.Plo -rm -f ./$(DEPDIR)/libguac_common_la-cursor.Plo -rm -f ./$(DEPDIR)/libguac_common_la-display.Plo -rm -f ./$(DEPDIR)/libguac_common_la-dot_cursor.Plo -rm -f ./$(DEPDIR)/libguac_common_la-ibar_cursor.Plo -rm -f ./$(DEPDIR)/libguac_common_la-iconv.Plo -rm -f ./$(DEPDIR)/libguac_common_la-io.Plo -rm -f ./$(DEPDIR)/libguac_common_la-json.Plo -rm -f ./$(DEPDIR)/libguac_common_la-list.Plo -rm -f ./$(DEPDIR)/libguac_common_la-pointer_cursor.Plo -rm -f ./$(DEPDIR)/libguac_common_la-recording.Plo -rm -f ./$(DEPDIR)/libguac_common_la-rect.Plo -rm -f ./$(DEPDIR)/libguac_common_la-string.Plo -rm -f ./$(DEPDIR)/libguac_common_la-surface.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--depfiles check check-am clean clean-generic clean-libtool \ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/src/common/cursor.c0000644000175100001440000002161613702142276015444 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/blank_cursor.h" #include "common/dot_cursor.h" #include "common/cursor.h" #include "common/ibar_cursor.h" #include "common/pointer_cursor.h" #include "common/surface.h" #include #include #include #include #include #include #include #include #include /** * Allocates a cursor as well as an image buffer where the cursor is rendered. * * @param client * The client owning the cursor. * * @return * The newly-allocated cursor or NULL if cursor cannot be allocated. */ guac_common_cursor* guac_common_cursor_alloc(guac_client* client) { guac_common_cursor* cursor = malloc(sizeof(guac_common_cursor)); if (cursor == NULL) return NULL; /* Associate cursor with client and allocate cursor buffer */ cursor->client = client; cursor->buffer = guac_client_alloc_buffer(client); /* Allocate initial image buffer */ cursor->image_buffer_size = GUAC_COMMON_CURSOR_DEFAULT_SIZE; cursor->image_buffer = malloc(cursor->image_buffer_size); /* No cursor image yet */ cursor->width = 0; cursor->height = 0; cursor->surface = NULL; cursor->hotspot_x = 0; cursor->hotspot_y = 0; /* No user has moved the mouse yet */ cursor->user = NULL; cursor->timestamp = guac_timestamp_current(); /* Start cursor in upper-left */ cursor->x = 0; cursor->y = 0; return cursor; } void guac_common_cursor_free(guac_common_cursor* cursor) { guac_client* client = cursor->client; guac_layer* buffer = cursor->buffer; cairo_surface_t* surface = cursor->surface; /* Free image buffer and surface */ free(cursor->image_buffer); if (surface != NULL) cairo_surface_destroy(surface); /* Destroy buffer within remotely-connected client */ guac_protocol_send_dispose(client->socket, buffer); /* Return buffer to pool */ guac_client_free_buffer(client, buffer); free(cursor); } void guac_common_cursor_dup(guac_common_cursor* cursor, guac_user* user, guac_socket* socket) { /* Synchronize location */ guac_protocol_send_mouse(socket, cursor->x, cursor->y, cursor->button_mask, cursor->timestamp); /* Synchronize cursor image */ if (cursor->surface != NULL) { guac_protocol_send_size(socket, cursor->buffer, cursor->width, cursor->height); guac_user_stream_png(user, socket, GUAC_COMP_SRC, cursor->buffer, 0, 0, cursor->surface); guac_protocol_send_cursor(socket, cursor->hotspot_x, cursor->hotspot_y, cursor->buffer, 0, 0, cursor->width, cursor->height); } guac_socket_flush(socket); } /** * Callback for guac_client_foreach_user() which sends the current cursor * position and button state to any given user except the user that moved the * cursor last. * * @param data * A pointer to the guac_common_cursor whose state should be broadcast to * all users except the user that moved the cursor last. * * @return * Always NULL. */ static void* guac_common_cursor_broadcast_state(guac_user* user, void* data) { guac_common_cursor* cursor = (guac_common_cursor*) data; /* Send cursor state only if the user is not moving the cursor */ if (user != cursor->user) { guac_protocol_send_mouse(user->socket, cursor->x, cursor->y, cursor->button_mask, cursor->timestamp); guac_socket_flush(user->socket); } return NULL; } void guac_common_cursor_update(guac_common_cursor* cursor, guac_user* user, int x, int y, int button_mask) { /* Update current user of cursor */ cursor->user = user; /* Update cursor state */ cursor->x = x; cursor->y = y; cursor->button_mask = button_mask; /* Store time at which cursor was updated */ cursor->timestamp = guac_timestamp_current(); /* Notify all other users of change in cursor state */ guac_client_foreach_user(cursor->client, guac_common_cursor_broadcast_state, cursor); } /** * Ensures the cursor image buffer has enough room to fit an image with the * given characteristics. Existing image buffer data may be destroyed. * * @param cursor * The cursor whose buffer size should be checked. If this cursor lacks * sufficient space to contain a cursor image of the specified width, * height, and stride, the current contents of this cursor will be * destroyed and replaced with an new buffer having sufficient space. * * @param width * The required cursor width, in pixels. * * @param height * The required cursor height, in pixels. * * @param stride * The number of bytes in each row of image data. */ static void guac_common_cursor_resize(guac_common_cursor* cursor, int width, int height, int stride) { int minimum_size = height * stride; /* Grow image buffer if necessary */ if (cursor->image_buffer_size < minimum_size) { /* Calculate new size */ cursor->image_buffer_size = minimum_size*2; /* Destructively reallocate image buffer */ free(cursor->image_buffer); cursor->image_buffer = malloc(cursor->image_buffer_size); } } void guac_common_cursor_set_argb(guac_common_cursor* cursor, int hx, int hy, unsigned const char* data, int width, int height, int stride) { /* Copy image data */ guac_common_cursor_resize(cursor, width, height, stride); memcpy(cursor->image_buffer, data, height * stride); if (cursor->surface != NULL) cairo_surface_destroy(cursor->surface); cursor->surface = cairo_image_surface_create_for_data(cursor->image_buffer, CAIRO_FORMAT_ARGB32, width, height, stride); /* Set new cursor parameters */ cursor->width = width; cursor->height = height; cursor->hotspot_x = hx; cursor->hotspot_y = hy; /* Broadcast new cursor image to all users */ guac_protocol_send_size(cursor->client->socket, cursor->buffer, width, height); guac_client_stream_png(cursor->client, cursor->client->socket, GUAC_COMP_SRC, cursor->buffer, 0, 0, cursor->surface); /* Update cursor image */ guac_protocol_send_cursor(cursor->client->socket, cursor->hotspot_x, cursor->hotspot_y, cursor->buffer, 0, 0, cursor->width, cursor->height); guac_socket_flush(cursor->client->socket); } void guac_common_cursor_set_surface(guac_common_cursor* cursor, int hx, int hy, guac_common_surface* surface) { /* Set cursor to surface contents */ guac_common_cursor_set_argb(cursor, hx, hy, surface->buffer, surface->width, surface->height, surface->stride); } void guac_common_cursor_set_pointer(guac_common_cursor* cursor) { guac_common_cursor_set_argb(cursor, 0, 0, guac_common_pointer_cursor, guac_common_pointer_cursor_width, guac_common_pointer_cursor_height, guac_common_pointer_cursor_stride); } void guac_common_cursor_set_dot(guac_common_cursor* cursor) { guac_common_cursor_set_argb(cursor, 2, 2, guac_common_dot_cursor, guac_common_dot_cursor_width, guac_common_dot_cursor_height, guac_common_dot_cursor_stride); } void guac_common_cursor_set_ibar(guac_common_cursor* cursor) { guac_common_cursor_set_argb(cursor, guac_common_ibar_cursor_width / 2, guac_common_ibar_cursor_height / 2, guac_common_ibar_cursor, guac_common_ibar_cursor_width, guac_common_ibar_cursor_height, guac_common_ibar_cursor_stride); } void guac_common_cursor_set_blank(guac_common_cursor* cursor) { guac_common_cursor_set_argb(cursor, 0, 0, guac_common_blank_cursor, guac_common_blank_cursor_width, guac_common_blank_cursor_height, guac_common_blank_cursor_stride); } void guac_common_cursor_remove_user(guac_common_cursor* cursor, guac_user* user) { /* Disassociate from given user */ if (cursor->user == user) cursor->user = NULL; } guacamole-server-1.3.0/src/common/ibar_cursor.c0000644000175100001440000000557113613156714016446 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include #include #include #include #include #include /* Macros for prettying up the embedded image. */ #define X 0x00,0x00,0x00,0xFF #define U 0x80,0x80,0x80,0xFF #define O 0xFF,0xFF,0xFF,0xFF #define _ 0x00,0x00,0x00,0x00 /* Dimensions */ const int guac_common_ibar_cursor_width = 7; const int guac_common_ibar_cursor_height = 16; /* Format */ const cairo_format_t guac_common_ibar_cursor_format = CAIRO_FORMAT_ARGB32; const int guac_common_ibar_cursor_stride = 28; /* Embedded I-bar graphic */ unsigned char guac_common_ibar_cursor[] = { X,X,X,X,X,X,X, X,O,O,U,O,O,X, X,X,X,O,X,X,X, _,_,X,O,X,_,_, _,_,X,O,X,_,_, _,_,X,O,X,_,_, _,_,X,O,X,_,_, _,_,X,O,X,_,_, _,_,X,O,X,_,_, _,_,X,O,X,_,_, _,_,X,O,X,_,_, _,_,X,O,X,_,_, _,_,X,O,X,_,_, X,X,X,O,X,X,X, X,O,O,U,O,O,X, X,X,X,X,X,X,X }; void guac_common_set_ibar_cursor(guac_user* user) { guac_client* client = user->client; guac_socket* socket = user->socket; /* Draw to buffer */ guac_layer* cursor = guac_client_alloc_buffer(client); cairo_surface_t* graphic = cairo_image_surface_create_for_data( guac_common_ibar_cursor, guac_common_ibar_cursor_format, guac_common_ibar_cursor_width, guac_common_ibar_cursor_height, guac_common_ibar_cursor_stride); guac_user_stream_png(user, socket, GUAC_COMP_SRC, cursor, 0, 0, graphic); cairo_surface_destroy(graphic); /* Set cursor */ guac_protocol_send_cursor(socket, 0, 0, cursor, guac_common_ibar_cursor_width / 2, guac_common_ibar_cursor_height / 2, guac_common_ibar_cursor_width, guac_common_ibar_cursor_height); /* Free buffer */ guac_client_free_buffer(client, cursor); guac_client_log(client, GUAC_LOG_DEBUG, "Client cursor image set to generic built-in I-bar."); } guacamole-server-1.3.0/src/common/string.c0000644000175100001440000000412513613156714015434 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/string.h" #include #include int guac_count_occurrences(const char* string, char c) { int count = 0; while (*string != 0) { /* Count each occurrence */ if (*string == c) count++; /* Next character */ string++; } return count; } char** guac_split(const char* string, char delim) { int i = 0; int token_count = guac_count_occurrences(string, delim) + 1; const char* token_start = string; /* Allocate space for tokens */ char** tokens = malloc(sizeof(char*) * (token_count+1)); do { int length; char* token; /* Find end of token */ while (*string != 0 && *string != delim) string++; /* Calculate token length */ length = string - token_start; /* Allocate space for token and NULL terminator */ tokens[i++] = token = malloc(length + 1); /* Copy token, store null */ memcpy(token, token_start, length); token[length] = 0; /* Stop at end of string */ if (*string == 0) break; /* Next token */ token_start = ++string; } while (i < token_count); /* NULL terminator */ tokens[i] = NULL; return tokens; } guacamole-server-1.3.0/src/common/io.c0000644000175100001440000000326413613156714014540 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "common/io.h" #include int guac_common_write(int fd, void* buffer, int length) { unsigned char* bytes = (unsigned char*) buffer; while (length > 0) { /* Attempt write */ int bytes_written = write(fd, bytes, length); if (bytes_written < 0) return bytes_written; /* Update buffer */ length -= bytes_written; bytes += bytes_written; } /* Success */ return length; } int guac_common_read(int fd, void* buffer, int length) { unsigned char* bytes = (unsigned char*) buffer; while (length > 0) { /* Attempt read */ int bytes_read = read(fd, bytes, length); if (bytes_read < 0) return bytes_read; /* Update buffer */ length -= bytes_read; bytes += bytes_read; } /* Success */ return length; } guacamole-server-1.3.0/src/common/common/0000755000175100001440000000000013772471155015335 500000000000000guacamole-server-1.3.0/src/common/common/list.h0000644000175100001440000000606513613156714016403 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_LIST_H #define __GUAC_LIST_H #include "config.h" #include /** * Generic linked list element. */ typedef struct guac_common_list_element guac_common_list_element; struct guac_common_list_element { /** * The next element in the list, or NULL if none. */ guac_common_list_element* next; /** * Generic data. */ void* data; /** * The pointer which points to this element, whether another element's * next pointer, or the entire list's head pointer. */ guac_common_list_element** _ptr; }; /** * Generic linked list. */ typedef struct guac_common_list { /** * The first element in the list. */ guac_common_list_element* head; /** * Mutex which is locked when exclusive access to the list is required. * Possession of the lock is not enforced outside the * guac_common_list_lock() function. */ pthread_mutex_t _lock; } guac_common_list; /** * Creates a new list. * * @return A newly-allocated list. */ guac_common_list* guac_common_list_alloc(); /** * Frees the given list. * * @param list The list to free. */ void guac_common_list_free(guac_common_list* list); /** * Adds the given data to the list as a new element, returning the created * element. * * @param list The list to add an element to. * @param data The data to associate with the newly-created element. * @param The newly-created element. */ guac_common_list_element* guac_common_list_add(guac_common_list* list, void* data); /** * Removes the given element from the list. * * @param list The list to remove the element from. * @param element The element to remove. */ void guac_common_list_remove(guac_common_list* list, guac_common_list_element* element); /** * Acquires exclusive access to the list. No list functions implicitly lock or * unlock the list, so any list access which must be threadsafe must use * guac_common_list_lock() and guac_common_list_unlock() manually. * * @param list The list to acquire exclusive access to. */ void guac_common_list_lock(guac_common_list* list); /** * Releases exclusive access to the list. * * @param list The list to release from exclusive access. */ void guac_common_list_unlock(guac_common_list* list); #endif guacamole-server-1.3.0/src/common/common/cursor.h0000644000175100001440000002056113702142276016737 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_CURSOR_H #define GUAC_COMMON_CURSOR_H #include "surface.h" #include #include #include #include /** * The default size of the cursor image buffer. */ #define GUAC_COMMON_CURSOR_DEFAULT_SIZE 64*64*4 /** * Cursor object which maintains and synchronizes the current mouse cursor * state across all users of a specific client. */ typedef struct guac_common_cursor { /** * The client to maintain the mouse cursor for. */ guac_client* client; /** * The buffer containing the current cursor image. */ guac_layer* buffer; /** * The width of the cursor image, in pixels. */ int width; /** * The height of the cursor image, in pixels. */ int height; /** * Arbitrary image data buffer, backing the Cairo surface used to store * the cursor image. */ unsigned char* image_buffer; /** * The size of the image data buffer, in bytes. */ int image_buffer_size; /** * The current cursor image, if any. If the mouse cursor has not yet been * set, this will be NULL. */ cairo_surface_t* surface; /** * The X coordinate of the hotspot of the mouse cursor. */ int hotspot_x; /** * The Y coordinate of the hotspot of the mouse cursor. */ int hotspot_y; /** * The last user to move the mouse, or NULL if no user has moved the * mouse yet. */ guac_user* user; /** * The X coordinate of the current mouse cursor location. */ int x; /** * The Y coordinate of the current mouse cursor location. */ int y; /** * An integer value representing the current state of each button, where * the Nth bit within the integer is set to 1 if and only if the Nth mouse * button is currently pressed. The lowest-order bit is the left mouse * button, followed by the middle button, right button, and finally the up * and down buttons of the scroll wheel. * * @see GUAC_CLIENT_MOUSE_LEFT * @see GUAC_CLIENT_MOUSE_MIDDLE * @see GUAC_CLIENT_MOUSE_RIGHT * @see GUAC_CLIENT_MOUSE_SCROLL_UP * @see GUAC_CLIENT_MOUSE_SCROLL_DOWN */ int button_mask; /** * The server timestamp representing the point in time when the mousr * location was last updated. */ guac_timestamp timestamp; } guac_common_cursor; /** * Allocates a new cursor object which maintains and synchronizes the current * mouse cursor state across all users of the given client. * * @param client * The client for which this object shall maintain the mouse cursor. * * @return * The newly-allocated mouse cursor. */ guac_common_cursor* guac_common_cursor_alloc(guac_client* client); /** * Frees the given cursor. * * @param cursor * The cursor to free. */ void guac_common_cursor_free(guac_common_cursor* cursor); /** * Sends the current state of this cursor across the given socket, including * the current cursor image. The resulting cursor on the remote display will * be visible. * * @param cursor * The cursor to send. * * @param user * The user receiving the updated cursor. * * @param socket * The socket over which the updated cursor should be sent. */ void guac_common_cursor_dup(guac_common_cursor* cursor, guac_user* user, guac_socket* socket); /** * Updates the current position and button state of the mouse cursor, marking * the given user as the most recent user of the mouse. The remote mouse cursor * will be hidden for this user and shown for all others. * * @param cursor * The cursor being updated. * * @param user * The user that moved the cursor. * * @param x * The new X coordinate of the cursor. * * @param y * The new Y coordinate of the cursor. * * @param button_mask * An integer value representing the current state of each button, where * the Nth bit within the integer is set to 1 if and only if the Nth mouse * button is currently pressed. The lowest-order bit is the left mouse * button, followed by the middle button, right button, and finally the up * and down buttons of the scroll wheel. * * @see GUAC_CLIENT_MOUSE_LEFT * @see GUAC_CLIENT_MOUSE_MIDDLE * @see GUAC_CLIENT_MOUSE_RIGHT * @see GUAC_CLIENT_MOUSE_SCROLL_UP * @see GUAC_CLIENT_MOUSE_SCROLL_DOWN */ void guac_common_cursor_update(guac_common_cursor* cursor, guac_user* user, int x, int y, int button_mask); /** * Sets the cursor image to the given raw image data. This raw image data must * be in 32-bit ARGB format, having 8 bits per color component, where the * alpha component is stored in the high-order 8 bits, and blue is stored * in the low-order 8 bits. * * @param cursor * The cursor to set the image of. * * @param hx * The X coordinate of the hotspot of the new cursor image. * * @param hy * The Y coordinate of the hotspot of the new cursor image. * * @param data * A pointer to raw 32-bit ARGB image data. * * @param width * The width of the given image data, in pixels. * * @param height * The height of the given image data, in pixels. * * @param stride * The number of bytes in a single row of image data. */ void guac_common_cursor_set_argb(guac_common_cursor* cursor, int hx, int hy, unsigned const char* data, int width, int height, int stride); /** * Sets the cursor image to the contents of the given surface. The entire * contents of the surface are used, and the dimensions of the resulting * cursor will be the dimensions of the given surface. * * @param cursor * The cursor to set the image of. * * @param hx * The X coordinate of the hotspot of the new cursor image. * * @param hy * The Y coordinate of the hotspot of the new cursor image. * * @param surface * The surface containing the cursor image. */ void guac_common_cursor_set_surface(guac_common_cursor* cursor, int hx, int hy, guac_common_surface* surface); /** * Set the cursor of the remote display to the embedded "pointer" graphic. The * pointer graphic is a black arrow with white border. * * @param cursor * The cursor to set the image of. */ void guac_common_cursor_set_pointer(guac_common_cursor* cursor); /** * Set the cursor of the remote display to the embedded "dot" graphic. The dot * graphic is a small black square with white border. * * @param cursor * The cursor to set the image of. */ void guac_common_cursor_set_dot(guac_common_cursor* cursor); /** * Sets the cursor of the remote display to the embedded "I-bar" graphic. The * I-bar graphic is a small black "I" shape with white border, used to indicate * the presence of selectable or editable text. * * @param cursor * The cursor to set the image of. */ void guac_common_cursor_set_ibar(guac_common_cursor* cursor); /** * Sets the cursor of the remote display to the embedded transparent (blank) * graphic, effectively hiding the mouse cursor. * * @param cursor * The cursor to set the image of. */ void guac_common_cursor_set_blank(guac_common_cursor* cursor); /** * Removes the given user, such that future synchronization will not occur. * This is necessary when a user leaves the connection. If a user leaves the * connection and this is not called, the mouse cursor state may not update * correctly in response to mouse events. * * @param cursor * The cursor to remove the user from. * * @param user * The user to remove. */ void guac_common_cursor_remove_user(guac_common_cursor* cursor, guac_user* user); #endif guacamole-server-1.3.0/src/common/common/blank_cursor.h0000644000175100001440000000346313613156714020113 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_BLANK_CURSOR_H #define GUAC_COMMON_BLANK_CURSOR_H #include "config.h" #include #include /** * Width of the embedded transparent (blank) mouse cursor graphic. */ extern const int guac_common_blank_cursor_width; /** * Height of the embedded transparent (blank) mouse cursor graphic. */ extern const int guac_common_blank_cursor_height; /** * Number of bytes in each row of the embedded transparent (blank) mouse cursor * graphic. */ extern const int guac_common_blank_cursor_stride; /** * The Cairo grapic format of the transparent (blank) mouse cursor graphic. */ extern const cairo_format_t guac_common_blank_cursor_format; /** * Embedded transparent (blank) mouse cursor graphic. */ extern unsigned char guac_common_blank_cursor[]; /** * Sets the cursor of the remote display to the embedded transparent (blank) * cursor graphic. * * @param user * The guac_user to send the cursor to. */ void guac_common_set_blank_cursor(guac_user* user); #endif guacamole-server-1.3.0/src/common/common/defaults.h0000644000175100001440000000210013764613616017227 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_DEFAULTS_H #define GUAC_COMMON_DEFAULTS_H /** * The default number of seconds to wait after sending the Wake-on-LAN packet * for the destination host to start responding. */ #define GUAC_WOL_DEFAULT_BOOT_WAIT_TIME 0 #endif /* GUAC_COMMON_DEFAULTS_H */ guacamole-server-1.3.0/src/common/common/ibar_cursor.h0000644000175100001440000000332113613156714017732 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_IBAR_CURSOR_H #define GUAC_COMMON_IBAR_CURSOR_H #include "config.h" #include #include /** * Width of the embedded I-bar mouse cursor graphic. */ extern const int guac_common_ibar_cursor_width; /** * Height of the embedded I-bar mouse cursor graphic. */ extern const int guac_common_ibar_cursor_height; /** * Number of bytes in each row of the embedded I-bar mouse cursor graphic. */ extern const int guac_common_ibar_cursor_stride; /** * The Cairo grapic format of the I-bar mouse cursor graphic. */ extern const cairo_format_t guac_common_ibar_cursor_format; /** * Embedded I-bar mouse cursor graphic. */ extern unsigned char guac_common_ibar_cursor[]; /** * Sets the cursor of the remote display to the embedded I-bar cursor graphic. * * @param user * The guac_user to send the cursor to. */ void guac_common_set_ibar_cursor(guac_user* user); #endif guacamole-server-1.3.0/src/common/common/json.h0000644000175100001440000001435013613156714016375 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_JSON_H #define GUAC_COMMON_JSON_H #include "config.h" #include #include /** * The current streaming state of an arbitrary JSON object, consisting of * any number of property name/value pairs. */ typedef struct guac_common_json_state { /** * Buffer of partial JSON data. The individual blobs which make up the JSON * body of the object being sent over the Guacamole protocol will be * built here. */ char buffer[4096]; /** * The number of bytes currently used within the JSON buffer. */ int size; /** * The number of property name/value pairs written to the JSON object thus * far. */ int properties_written; } guac_common_json_state; /** * Given a stream, the user to which it belongs, and the current stream state * of a JSON object, flushes the contents of the JSON buffer to a blob * instruction. Note that this will flush the JSON buffer only, and will not * necessarily flush the underlying guac_socket of the user. * * @param user * The user to which the data will be flushed. * * @param stream * The stream through which the flushed data should be sent as a blob. * * @param json_state * The state object whose buffer should be flushed. */ void guac_common_json_flush(guac_user* user, guac_stream* stream, guac_common_json_state* json_state); /** * Given a stream, the user to which it belongs, and the current stream state * of a JSON object, writes the contents of the given buffer to the JSON buffer * of the stream state, flushing as necessary. * * @param user * The user to which the data will be flushed as necessary. * * @param stream * The stream through which the flushed data should be sent as a blob, if * data must be flushed at all. * * @param json_state * The state object containing the JSON buffer to which the given buffer * should be written. * * @param buffer * The buffer to write. * * @param length * The number of bytes in the buffer. * * @return * Non-zero if at least one blob was written, zero otherwise. */ int guac_common_json_write(guac_user* user, guac_stream* stream, guac_common_json_state* json_state, const char* buffer, int length); /** * Given a stream, the user to which it belongs, and the current stream state * of a JSON object state, writes the given string as a proper JSON string, * including starting and ending quotes. The contents of the string will be * escaped as necessary. * * @param user * The user to which the data will be flushed as necessary. * * @param stream * The stream through which the flushed data should be sent as a blob, if * data must be flushed at all. * * @param json_state * The state object containing the JSON buffer to which the given string * should be written as a JSON name/value pair. * * @param str * The string to write. * * @return * Non-zero if at least one blob was written, zero otherwise. */ int guac_common_json_write_string(guac_user* user, guac_stream* stream, guac_common_json_state* json_state, const char* str); /** * Given a stream, the user to which it belongs, and the current stream state * of a JSON object, writes the given JSON property name/value pair. The * name and value will be written as proper JSON strings separated by a colon. * * @param user * The user to which the data will be flushed as necessary. * * @param stream * The stream through which the flushed data should be sent as a blob, if * data must be flushed at all. * * @param json_state * The state object containing the JSON buffer to which the given strings * should be written as a JSON name/value pair. * * @param name * The name of the property to write. * * @param value * The value of the property to write. * * @return * Non-zero if at least one blob was written, zero otherwise. */ int guac_common_json_write_property(guac_user* user, guac_stream* stream, guac_common_json_state* json_state, const char* name, const char* value); /** * Given a stream, the user to which it belongs, and the current stream state * of a JSON object, initializes the state for writing a new JSON object. Note * that although the user and stream must be provided, no instruction or * blobs will be written due to any call to this function. * * @param user * The user associated with the given stream. * * @param stream * The stream associated with the JSON object being written. * * @param json_state * The state object to initialize. */ void guac_common_json_begin_object(guac_user* user, guac_stream* stream, guac_common_json_state* json_state); /** * Given a stream, the user to which it belongs, and the current stream state * of a JSON object, completes writing that JSON object by writing the final * terminating brace. This function must only be called following a * corresponding call to guac_common_json_begin_object(). * * @param user * The user associated with the given stream. * * @param stream * The stream associated with the JSON object being written. * * @param json_state * The state object whose in-progress JSON object should be terminated. * * @return * Non-zero if at least one blob was written, zero otherwise. */ int guac_common_json_end_object(guac_user* user, guac_stream* stream, guac_common_json_state* json_state); #endif guacamole-server-1.3.0/src/common/common/recording.h0000644000175100001440000001626213702142276017401 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_RECORDING_H #define GUAC_COMMON_RECORDING_H #include /** * The maximum numeric value allowed for the .1, .2, .3, etc. suffix appended * to the end of the session recording filename if a recording having the * requested name already exists. */ #define GUAC_COMMON_RECORDING_MAX_SUFFIX 255 /** * The maximum length of the string containing a sequential numeric suffix * between 1 and GUAC_COMMON_RECORDING_MAX_SUFFIX inclusive, in bytes, * including NULL terminator. */ #define GUAC_COMMON_RECORDING_MAX_SUFFIX_LENGTH 4 /** * The maximum overall length of the full path to the session recording file, * including any additional suffix and NULL terminator, in bytes. */ #define GUAC_COMMON_RECORDING_MAX_NAME_LENGTH 2048 /** * An in-progress session recording, attached to a guac_client instance such * that output Guacamole instructions may be dynamically intercepted and * written to a file. */ typedef struct guac_common_recording { /** * The guac_socket which writes directly to the recording file, rather than * to any particular user. */ guac_socket* socket; /** * Non-zero if output which is broadcast to each connected client * (graphics, streams, etc.) should be included in the session recording, * zero otherwise. Including output is necessary for any recording which * must later be viewable as video. */ int include_output; /** * Non-zero if changes to mouse state, such as position and buttons pressed * or released, should be included in the session recording, zero * otherwise. Including mouse state is necessary for the mouse cursor to be * rendered in any resulting video. */ int include_mouse; /** * Non-zero if keys pressed and released should be included in the session * recording, zero otherwise. Including key events within the recording may * be necessary in certain auditing contexts, but should only be done with * caution. Key events can easily contain sensitive information, such as * passwords, credit card numbers, etc. */ int include_keys; } guac_common_recording; /** * Replaces the socket of the given client such that all further Guacamole * protocol output will be copied into a file within the given path and having * the given name. If the create_path flag is non-zero, the given path will be * created if it does not yet exist. If creation of the recording file or path * fails, error messages will automatically be logged, and no recording will be * written. The recording will automatically be closed once the client is * freed. * * @param client * The client whose output should be copied to a recording file. * * @param path * The full absolute path to a directory in which the recording file should * be created. * * @param name * The base name to use for the recording file created within the specified * path. * * @param create_path * Zero if the specified path MUST exist for the recording file to be * written, or non-zero if the path should be created if it does not yet * exist. * * @param include_output * Non-zero if output which is broadcast to each connected client * (graphics, streams, etc.) should be included in the session recording, * zero otherwise. Including output is necessary for any recording which * must later be viewable as video. * * @param include_mouse * Non-zero if changes to mouse state, such as position and buttons pressed * or released, should be included in the session recording, zero * otherwise. Including mouse state is necessary for the mouse cursor to be * rendered in any resulting video. * * @param include_keys * Non-zero if keys pressed and released should be included in the session * recording, zero otherwise. Including key events within the recording may * be necessary in certain auditing contexts, but should only be done with * caution. Key events can easily contain sensitive information, such as * passwords, credit card numbers, etc. * * @return * A new guac_common_recording structure representing the in-progress * recording if the recording file has been successfully created and a * recording will be written, NULL otherwise. */ guac_common_recording* guac_common_recording_create(guac_client* client, const char* path, const char* name, int create_path, int include_output, int include_mouse, int include_keys); /** * Frees the resources associated with the given in-progress recording. Note * that, due to the manner that recordings are attached to the guac_client, the * underlying guac_socket is not freed. The guac_socket will be automatically * freed when the guac_client is freed. * * @param recording * The guac_common_recording to free. */ void guac_common_recording_free(guac_common_recording* recording); /** * Reports the current mouse position and button state within the recording. * * @param recording * The guac_common_recording associated with the mouse that has moved. * * @param x * The new X coordinate of the mouse cursor, in pixels. * * @param y * The new Y coordinate of the mouse cursor, in pixels. * * @param button_mask * An integer value representing the current state of each button, where * the Nth bit within the integer is set to 1 if and only if the Nth mouse * button is currently pressed. The lowest-order bit is the left mouse * button, followed by the middle button, right button, and finally the up * and down buttons of the scroll wheel. * * @see GUAC_CLIENT_MOUSE_LEFT * @see GUAC_CLIENT_MOUSE_MIDDLE * @see GUAC_CLIENT_MOUSE_RIGHT * @see GUAC_CLIENT_MOUSE_SCROLL_UP * @see GUAC_CLIENT_MOUSE_SCROLL_DOWN */ void guac_common_recording_report_mouse(guac_common_recording* recording, int x, int y, int button_mask); /** * Reports a change in the state of an individual key within the recording. * * @param recording * The guac_common_recording associated with the key that was pressed or * released. * * @param keysym * The X11 keysym of the key that was pressed or released. * * @param pressed * Non-zero if the key represented by the given keysym is currently * pressed, zero if it is released. */ void guac_common_recording_report_key(guac_common_recording* recording, int keysym, int pressed); #endif guacamole-server-1.3.0/src/common/common/iconv.h0000644000175100001440000000601513613156714016541 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_COMMON_ICONV_H #define __GUAC_COMMON_ICONV_H #include "config.h" /** * Function which reads a character from the given string data, returning * the Unicode codepoint read, updating the string pointer to point to the * byte immediately after the character read. */ typedef int guac_iconv_read(const char** input, int remaining); /** * Function writes the character having the given Unicode codepoint value to * the given string data, updating the string pointer to point to the byte * immediately after the character written. */ typedef void guac_iconv_write(char** output, int remaining, int value); /** * Converts characters within a given string from one encoding to another, * as defined by the reader/writer functions specified. The input and output * string pointers will be updated based on the number of bytes read or * written. * * @param reader The reader function to use when reading the input string. * @param input Pointer to the beginning of the input string. * @param in_remaining The number of bytes remaining after the pointer to the * input string. * @param writer The writer function to use when writing the output string. * @param output Pointer to the beginning of the output string. * @param out_remaining The number of bytes remaining after the pointer to the * output string. * @return Non-zero if the NULL terminator of the input string was read and * copied into the destination string, zero otherwise. */ int guac_iconv(guac_iconv_read* reader, const char** input, int in_remaining, guac_iconv_write* writer, char** output, int out_remaining); /** * Read function for UTF8. */ guac_iconv_read GUAC_READ_UTF8; /** * Read function for UTF16. */ guac_iconv_read GUAC_READ_UTF16; /** * Read function for CP-1252. */ guac_iconv_read GUAC_READ_CP1252; /** * Read function for ISO-8859-1 */ guac_iconv_read GUAC_READ_ISO8859_1; /** * Write function for UTF8. */ guac_iconv_write GUAC_WRITE_UTF8; /** * Write function for UTF16. */ guac_iconv_write GUAC_WRITE_UTF16; /** * Write function for CP-1252. */ guac_iconv_write GUAC_WRITE_CP1252; /** * Write function for ISO-8859-1 */ guac_iconv_write GUAC_WRITE_ISO8859_1; #endif guacamole-server-1.3.0/src/common/common/pointer_cursor.h0000644000175100001440000000327713613156714020507 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_COMMON_POINTER_CURSOR_H #define _GUAC_COMMON_POINTER_CURSOR_H #include "config.h" #include #include /** * Width of the embedded mouse cursor graphic. */ extern const int guac_common_pointer_cursor_width; /** * Height of the embedded mouse cursor graphic. */ extern const int guac_common_pointer_cursor_height; /** * Number of bytes in each row of the embedded mouse cursor graphic. */ extern const int guac_common_pointer_cursor_stride; /** * The Cairo grapic format of the mouse cursor graphic. */ extern const cairo_format_t guac_common_pointer_cursor_format; /** * Embedded mouse cursor graphic. */ extern unsigned char guac_common_pointer_cursor[]; /** * Set the cursor of the remote display to the embedded cursor graphic. * * @param user The guac_user to send the cursor to. */ void guac_common_set_pointer_cursor(guac_user* user); #endif guacamole-server-1.3.0/src/common/common/surface.h0000644000175100001440000003465313721010341017045 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_COMMON_SURFACE_H #define __GUAC_COMMON_SURFACE_H #include "config.h" #include "rect.h" #include #include #include #include #include #include /** * The maximum number of updates to allow within the bitmap queue. */ #define GUAC_COMMON_SURFACE_QUEUE_SIZE 256 /** * Heat map cell size in pixels. Each side of each heat map cell will consist * of this many pixels. */ #define GUAC_COMMON_SURFACE_HEAT_CELL_SIZE 64 /** * The width or height of the heat map (in cells) given the width or height of * the image (in pixels). */ #define GUAC_COMMON_SURFACE_HEAT_DIMENSION(x) ( \ (x + GUAC_COMMON_SURFACE_HEAT_CELL_SIZE - 1) \ / GUAC_COMMON_SURFACE_HEAT_CELL_SIZE \ ) /** * The number of entries to collect within each heat map cell. Collected * history entries are used to determine the framerate of the region associated * with that cell. */ #define GUAC_COMMON_SURFACE_HEAT_CELL_HISTORY_SIZE 5 /** * Representation of a cell in the refresh heat map. This cell is used to keep * track of how often an area on a surface is refreshed. */ typedef struct guac_common_surface_heat_cell { /** * Timestamps of each of the last N updates covering the location * associated with this heat map cell. This is used to calculate the * framerate. This array is structured as a ring buffer containing history * entries in chronologically-ascending order, starting at the entry * pointed to by oldest_entry and proceeding through all other entries, * wrapping around if the end of the array is reached. */ guac_timestamp history[GUAC_COMMON_SURFACE_HEAT_CELL_HISTORY_SIZE]; /** * Index of the oldest entry within the history. */ int oldest_entry; } guac_common_surface_heat_cell; /** * Representation of a bitmap update, having a rectangle of image data (stored * elsewhere) and a flushed/not-flushed state. */ typedef struct guac_common_surface_bitmap_rect { /** * Whether this rectangle has been flushed. */ int flushed; /** * The rectangle containing the bitmap update. */ guac_common_rect rect; } guac_common_surface_bitmap_rect; /** * Surface which backs a Guacamole buffer or layer, automatically * combining updates when possible. */ typedef struct guac_common_surface { /** * The layer this surface will draw to. */ const guac_layer* layer; /** * The client associated with this surface. */ guac_client* client; /** * The socket to send instructions on when flushing. */ guac_socket* socket; /** * The X coordinate of the upper-left corner of this layer, in pixels, * relative to its parent layer. This is only applicable to visible * (non-buffer) layers which are not the default layer. */ int x; /** * The Y coordinate of the upper-left corner of this layer, in pixels, * relative to its parent layer. This is only applicable to visible * (non-buffer) layers which are not the default layer. */ int y; /** * The Z-order of this layer, relative to sibling layers. This is only * applicable to visible (non-buffer) layers which are not the default * layer. */ int z; /** * The level of opacity applied to this layer. Fully opaque is 255, while * fully transparent is 0. This is only applicable to visible (non-buffer) * layers which are not the default layer. */ int opacity; /** * The layer which contains this layer. This is only applicable to visible * (non-buffer) layers which are not the default layer. */ const guac_layer* parent; /** * The width of this layer, in pixels. */ int width; /** * The height of this layer, in pixels. */ int height; /** * The size of each image row, in bytes. */ int stride; /** * The underlying buffer of the Cairo surface. */ unsigned char* buffer; /** * Non-zero if the location or parent layer of this surface has been * changed and needs to be flushed, 0 otherwise. */ int location_dirty; /** * Non-zero if the opacity of this surface has been changed and needs to be * flushed, 0 otherwise. */ int opacity_dirty; /** * Non-zero if this surface is dirty and needs to be flushed, 0 otherwise. */ int dirty; /** * The dirty rectangle. */ guac_common_rect dirty_rect; /** * Whether the surface actually exists on the client. */ int realized; /** * Whether drawing operations are currently clipped by the clipping * rectangle. */ int clipped; /** * The clipping rectangle. */ guac_common_rect clip_rect; /** * The number of updates in the bitmap queue. */ int bitmap_queue_length; /** * All queued bitmap updates. */ guac_common_surface_bitmap_rect bitmap_queue[GUAC_COMMON_SURFACE_QUEUE_SIZE]; /** * A heat map keeping track of the refresh frequency of * the areas of the screen. */ guac_common_surface_heat_cell* heat_map; /** * Mutex which is locked internally when access to the surface must be * synchronized. All public functions of guac_common_surface should be * considered threadsafe. */ pthread_mutex_t _lock; } guac_common_surface; /** * Allocates a new guac_common_surface, assigning it to the given layer. * * @param client * The client associated with the given layer. * * @param socket * The socket to send instructions on when flushing. * * @param layer * The layer to associate with the new surface. * * @param w * The width of the surface. * * @param h * The height of the surface. * * @return * A newly-allocated guac_common_surface. */ guac_common_surface* guac_common_surface_alloc(guac_client* client, guac_socket* socket, const guac_layer* layer, int w, int h); /** * Frees the given guac_common_surface. Beware that this will NOT free any * associated layers, which must be freed manually. * * @param surface The surface to free. */ void guac_common_surface_free(guac_common_surface* surface); /** * Resizes the given surface to the given size. * * @param surface The surface to resize. * @param w The width of the surface. * @param h The height of the surface. */ void guac_common_surface_resize(guac_common_surface* surface, int w, int h); /** * Draws the given data to the given guac_common_surface. If the source surface * is ARGB, the draw operation will be performed using the Porter-Duff "over" * composite operator. If the source surface is RGB (no alpha channel), no * compositing is performed and destination pixels are ignored. * * @param surface * The surface to draw to. * * @param x * The X coordinate of the draw location. * * @param y * The Y coordinate of the draw location. * * @param src * The Cairo surface to retrieve data from. */ void guac_common_surface_draw(guac_common_surface* surface, int x, int y, cairo_surface_t* src); /** * Paints to the given guac_common_surface using the given data as a stencil, * filling opaque regions with the specified color, and leaving transparent * regions untouched. * * @param surface The surface to draw to. * @param x The X coordinate of the draw location. * @param y The Y coordinate of the draw location. * @param src The Cairo surface to retrieve data from. * @param red The red component of the fill color. * @param green The green component of the fill color. * @param blue The blue component of the fill color. */ void guac_common_surface_paint(guac_common_surface* surface, int x, int y, cairo_surface_t* src, int red, int green, int blue); /** * Copies a rectangle of data between two surfaces. * * @param src The source surface. * @param sx The X coordinate of the upper-left corner of the source rect. * @param sy The Y coordinate of the upper-left corner of the source rect. * @param w The width of the source rect. * @param h The height of the source rect. * @param dst The destination surface. * @param dx The X coordinate of the upper-left corner of the destination rect. * @param dy The Y coordinate of the upper-left corner of the destination rect. */ void guac_common_surface_copy(guac_common_surface* src, int sx, int sy, int w, int h, guac_common_surface* dst, int dx, int dy); /** * Transfers a rectangle of data between two surfaces. * * @param src The source surface. * @param sx The X coordinate of the upper-left corner of the source rect. * @param sy The Y coordinate of the upper-left corner of the source rect. * @param w The width of the source rect. * @param h The height of the source rect. * @param op The transfer function. * @param dst The destination surface. * @param dx The X coordinate of the upper-left corner of the destination rect. * @param dy The Y coordinate of the upper-left corner of the destination rect. */ void guac_common_surface_transfer(guac_common_surface* src, int sx, int sy, int w, int h, guac_transfer_function op, guac_common_surface* dst, int dx, int dy); /** * Assigns the given value to all pixels within a rectangle of the given * surface. The color of all pixels within the rectangle, including the alpha * component, is entirely replaced. * * @param surface * The surface to draw upon. * * @param x * The X coordinate of the upper-left corner of the rectangle. * * @param y * The Y coordinate of the upper-left corner of the rectangle. * * @param w * The width of the rectangle. * * @param h * The height of the rectangle. * * @param red * The red component of the color value to assign to all pixels within the * rectangle. * * @param green * The green component of the color value to assign to all pixels within * the rectangle. * * @param blue * The blue component of the color value to assign to all pixels within the * rectangle. * * @param alpha * The alpha component of the color value to assign to all pixels within * the rectangle. */ void guac_common_surface_set(guac_common_surface* surface, int x, int y, int w, int h, int red, int green, int blue, int alpha); /** * Given the coordinates and dimensions of a rectangle, clips all future * operations within that rectangle. * * @param surface The surface whose clipping rectangle should be changed. * @param x The X coordinate of the upper-left corner of the bounding rectangle. * @param y The Y coordinate of the upper-left corner of the bounding rectangle. * @param w The width of the bounding rectangle. * @param h The height of the bounding rectangle. */ void guac_common_surface_clip(guac_common_surface* surface, int x, int y, int w, int h); /** * Resets the clipping rectangle, allowing drawing operations throughout the * entire surface. * * @param surface The surface whose clipping rectangle should be reset. */ void guac_common_surface_reset_clip(guac_common_surface* surface); /** * Changes the location of the surface relative to its parent layer. If the * surface does not represent a non-default visible layer, then this function * has no effect. * * @param surface * The surface to move relative to its parent layer. * * @param x * The new X coordinate for the upper-left corner of the layer, in pixels. * * @param y * The new Y coordinate for the upper-left corner of the layer, in pixels. */ void guac_common_surface_move(guac_common_surface* surface, int x, int y); /** * Changes the stacking order of the surface relative to other surfaces within * the same parent layer. If the surface does not represent a non-default * visible layer, then this function has no effect. * * @param surface * The surface to reorder relative to sibling layers. * * @param z * The new Z-order for this layer, relative to sibling layers. */ void guac_common_surface_stack(guac_common_surface* surface, int z); /** * Changes the parent layer of ths given surface. By default, layers will be * children of the default layer. If the surface does not represent a * non-default visible layer, then this function has no effect. * * @param surface * The surface whose parent layer should be changed. * * @param parent * The layer which should be set as the new parent of the given surface. */ void guac_common_surface_set_parent(guac_common_surface* surface, const guac_layer* parent); /** * Sets the opacity of the surface. If the surface does not represent a * non-default visible layer, then this function has no effect. * * @param surface * The surface whose opacity should be changed. * * @param opacity * The level of opacity applied to this surface, where fully opaque is 255, * and fully transparent is 0. */ void guac_common_surface_set_opacity(guac_common_surface* surface, int opacity); /** * Flushes the given surface, including any applicable properties, drawing any * pending operations on the remote display. * * @param surface * The surface to flush. */ void guac_common_surface_flush(guac_common_surface* surface); /** * Duplicates the contents of the current surface to the given socket. Pending * changes are not flushed. * * @param surface * The surface to duplicate. * * @param user * The user receiving the surface. * * @param socket * The socket over which the surface contents should be sent. */ void guac_common_surface_dup(guac_common_surface* surface, guac_user* user, guac_socket* socket); #endif guacamole-server-1.3.0/src/common/common/string.h0000644000175100001440000000314713613156714016734 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_COMMON_STRING_H #define __GUAC_COMMON_STRING_H #include "config.h" /** * Counts the number of occurrences of a given character in a string. * * @param string The string to count occurrences within. * @param c The character to count occurrences of. * @return The number of occurrences. */ int guac_count_occurrences(const char* string, char c); /** * Splits a string into a newly-allocated array of strings. The array itself * and each string within the array will eventually need to be freed. The array * is NULL-terminated. * * @param string The string to split. * @param delim The character which separates individual substrings within the * given string. * @return A newly-allocated, NULL-terminated array of strings. */ char** guac_split(const char* string, char delim); #endif guacamole-server-1.3.0/src/common/common/clipboard.h0000644000175100001440000000635713702142276017370 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_CLIPBOARD_H #define __GUAC_CLIPBOARD_H #include "config.h" #include #include /** * The maximum number of bytes to send in an individual blob when * transmitting the clipboard contents to a connected client. */ #define GUAC_COMMON_CLIPBOARD_BLOCK_SIZE 4096 /** * Generic clipboard structure. */ typedef struct guac_common_clipboard { /** * Lock which restricts simultaneous access to the clipboard, guaranteeing * ordered modifications to the clipboard and that changes to the clipboard * are not allowed while the clipboard is being broadcast to all users. */ pthread_mutex_t lock; /** * The mimetype of the contained clipboard data. */ char mimetype[256]; /** * Arbitrary clipboard data. */ char* buffer; /** * The number of bytes currently stored in the clipboard buffer. */ int length; /** * The total number of bytes available in the clipboard buffer. */ int available; } guac_common_clipboard; /** * Creates a new clipboard having the given initial size. * * @param size The maximum number of bytes to allow within the clipboard. * @return A newly-allocated clipboard. */ guac_common_clipboard* guac_common_clipboard_alloc(int size); /** * Frees the given clipboard. * * @param clipboard The clipboard to free. */ void guac_common_clipboard_free(guac_common_clipboard* clipboard); /** * Sends the contents of the clipboard along the given client, splitting * the contents as necessary. * * @param clipboard The clipboard whose contents should be sent. * @param client The client to send the clipboard contents on. */ void guac_common_clipboard_send(guac_common_clipboard* clipboard, guac_client* client); /** * Clears the clipboard contents and assigns a new mimetype for future data. * * @param clipboard The clipboard to reset. * @param mimetype The mimetype of future data. */ void guac_common_clipboard_reset(guac_common_clipboard* clipboard, const char* mimetype); /** * Appends the given data to the current clipboard contents. The data must * match the mimetype chosen for the clipboard data by * guac_common_clipboard_reset(). * * @param clipboard The clipboard to append data to. * @param data The data to append. * @param length The number of bytes to append from the data given. */ void guac_common_clipboard_append(guac_common_clipboard* clipboard, const char* data, int length); #endif guacamole-server-1.3.0/src/common/common/rect.h0000644000175100001440000001000413613156714016351 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_COMMON_RECT_H #define __GUAC_COMMON_RECT_H #include "config.h" /** * Simple representation of a rectangle, having a defined corner and dimensions. */ typedef struct guac_common_rect { /** * The X coordinate of the upper-left corner of this rectangle. */ int x; /** * The Y coordinate of the upper-left corner of this rectangle. */ int y; /** * The width of this rectangle. */ int width; /** * The height of this rectangle. */ int height; } guac_common_rect; /** * Initialize the given rect with the given coordinates and dimensions. * * @param rect The rect to initialize. * @param x The X coordinate of the upper-left corner of the rect. * @param y The Y coordinate of the upper-left corner of the rect. * @param width The width of the rect. * @param height The height of the rect. */ void guac_common_rect_init(guac_common_rect* rect, int x, int y, int width, int height); /** * Expand the rectangle to fit an NxN grid. * * The rectangle will be shifted to the left and up, expanded and adjusted to * fit within the max bounding rect. * * @param cell_size * The (NxN) grid cell size. * * @param rect * The rectangle to adjust. * * @param max_rect * The bounding area in which the given rect can exist. * * @return * Zero on success, non-zero on error. */ int guac_common_rect_expand_to_grid(int cell_size, guac_common_rect* rect, const guac_common_rect* max_rect); /** * Extend the given rect such that it contains at least the specified minimum * rect. * * @param rect The rect to extend. * @param min The minimum area which must be contained within the given rect. */ void guac_common_rect_extend(guac_common_rect* rect, const guac_common_rect* min); /** * Collapse the given rect such that it exists only within the given maximum * rect. * * @param rect The rect to extend. * @param max The maximum area in which the given rect can exist. */ void guac_common_rect_constrain(guac_common_rect* rect, const guac_common_rect* max); /** * Check whether a rectangle intersects another. * * @param rect * Rectangle to check for intersection. * * @param other * The other rectangle. * * @return * Zero if no intersection, 1 if partial intersection, * 2 if first rect is completely inside the other. */ int guac_common_rect_intersects(const guac_common_rect* rect, const guac_common_rect* other); /** * Clip and split a rectangle into rectangles which are not covered by the * hole rectangle. * * This function will clip and split single edges when executed and must be * invoked until it returns zero. The edges are handled counter-clockwise * starting at the top edge. * * @param rect * The rectangle to be split. This rectangle will be clipped by the * split_rect. * * @param hole * The rectangle which represents the hole. * * @param split_rect * Resulting split rectangle. * * @return * Zero when no splits were done, non-zero when the rectangle was split. */ int guac_common_rect_clip_and_split(guac_common_rect* rect, const guac_common_rect* hole, guac_common_rect* split_rect); #endif guacamole-server-1.3.0/src/common/common/dot_cursor.h0000644000175100001440000000323713613156714017611 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GUAC_COMMON_DOT_CURSOR_H #define _GUAC_COMMON_DOT_CURSOR_H #include "config.h" #include #include /** * Width of the embedded mouse cursor graphic. */ extern const int guac_common_dot_cursor_width; /** * Height of the embedded mouse cursor graphic. */ extern const int guac_common_dot_cursor_height; /** * Number of bytes in each row of the embedded mouse cursor graphic. */ extern const int guac_common_dot_cursor_stride; /** * The Cairo grapic format of the mouse cursor graphic. */ extern const cairo_format_t guac_common_dot_cursor_format; /** * Embedded mouse cursor graphic. */ extern unsigned char guac_common_dot_cursor[]; /** * Set the cursor of the remote display to the embedded cursor graphic. * * @param user The guac_user to send the cursor to. */ void guac_common_set_dot_cursor(guac_user* user); #endif guacamole-server-1.3.0/src/common/common/display.h0000644000175100001440000001515513613156714017075 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef GUAC_COMMON_DISPLAY_H #define GUAC_COMMON_DISPLAY_H #include "cursor.h" #include "surface.h" #include #include #include /** * A list element representing a pairing of a Guacamole layer with a * corresponding guac_common_surface which wraps that layer. Adjacent layers * within the same list are pointed to with traditional prev/next pointers. The * order of layers in lists need not correspond in any way to the natural * ordering of those layers' indexes nor their stacking order (Z-order) within * the display. */ typedef struct guac_common_display_layer guac_common_display_layer; struct guac_common_display_layer { /** * A Guacamole layer. */ guac_layer* layer; /** * The surface which wraps the associated layer. */ guac_common_surface* surface; /** * The layer immediately prior to this layer within the list containing * this layer, or NULL if this is the first layer/buffer in the list. */ guac_common_display_layer* prev; /** * The layer immediately following this layer within the list containing * this layer, or NULL if this is the last layer/buffer in the list. */ guac_common_display_layer* next; }; /** * Abstracts a remote Guacamole display, having an associated client, * default surface, mouse cursor, and various allocated buffers and layers. */ typedef struct guac_common_display { /** * The client associate with this display. */ guac_client* client; /** * The default surface of the client display. */ guac_common_surface* default_surface; /** * Client-wide cursor, synchronized across all users. */ guac_common_cursor* cursor; /** * The first element within a linked list of all currently-allocated * layers, or NULL if no layers are currently allocated. The default layer, * layer #0, is stored within default_surface and will not have a * corresponding element within this list. */ guac_common_display_layer* layers; /** * The first element within a linked list of all currently-allocated * buffers, or NULL if no buffers are currently allocated. */ guac_common_display_layer* buffers; /** * Mutex which is locked internally when access to the display must be * synchronized. All public functions of guac_common_display should be * considered threadsafe. */ pthread_mutex_t _lock; } guac_common_display; /** * Allocates a new display, abstracting the cursor and buffer/layer allocation * operations of the given guac_client such that client state can be easily * synchronized to joining users. * * @param client * The guac_client to associate with this display. * * @param width * The initial width of the display, in pixels. * * @param height * The initial height of the display, in pixels. * * @return * The newly-allocated display. */ guac_common_display* guac_common_display_alloc(guac_client* client, int width, int height); /** * Frees the given display, and any associated resources, including any * allocated buffers/layers. * * @param display * The display to free. */ void guac_common_display_free(guac_common_display* display); /** * Duplicates the state of the given display to the given socket. Any pending * changes to buffers, layers, or the default layer are not flushed. * * @param display * The display whose state should be sent along the given socket. * * @param user * The user receiving the display state. * * @param socket * The socket over which the display state should be sent. */ void guac_common_display_dup(guac_common_display* display, guac_user* user, guac_socket* socket); /** * Flushes pending changes to the given display. All pending operations will * become visible to any connected users. * * @param display * The display to flush. */ void guac_common_display_flush(guac_common_display* display); /** * Allocates a new layer, returning a new wrapped layer and corresponding * surface. The layer may be reused from a previous allocation, if that layer * has since been freed. * * @param display * The display to allocate a new layer from. * * @param width * The width of the layer to allocate, in pixels. * * @param height * The height of the layer to allocate, in pixels. * * @return * A newly-allocated layer. */ guac_common_display_layer* guac_common_display_alloc_layer( guac_common_display* display, int width, int height); /** * Allocates a new buffer, returning a new wrapped buffer and corresponding * surface. The buffer may be reused from a previous allocation, if that buffer * has since been freed. * * @param display * The display to allocate a new buffer from. * * @param width * The width of the buffer to allocate, in pixels. * * @param height * The height of the buffer to allocate, in pixels. * * @return * A newly-allocated buffer. */ guac_common_display_layer* guac_common_display_alloc_buffer( guac_common_display* display, int width, int height); /** * Frees the given surface and associated layer, returning the layer to the * given display for future use. * * @param display * The display originally allocating the layer. * * @param display_layer * The layer to free. */ void guac_common_display_free_layer(guac_common_display* display, guac_common_display_layer* display_layer); /** * Frees the given surface and associated buffer, returning the buffer to the * given display for future use. * * @param display * The display originally allocating the buffer. * * @param display_buffer * The buffer to free. */ void guac_common_display_free_buffer(guac_common_display* display, guac_common_display_layer* display_buffer); #endif guacamole-server-1.3.0/src/common/common/io.h0000644000175100001440000000330413613156714016030 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef __GUAC_COMMON_IO_H #define __GUAC_COMMON_IO_H #include "config.h" /** * Writes absolutely all bytes from within the given buffer, returning an error * only if the required writes fail. * * @param fd The file descriptor to write to. * @param buffer The buffer containing the data to write. * @param length The number of bytes to write. * @return The number of bytes written, or a value less than zero if an error * occurs. */ int guac_common_write(int fd, void* buffer, int length); /** * Reads enough bytes to fill the given buffer, returning an error only if the * required reads fail. * * @param fd The file descriptor to read from. * @param buffer The buffer to read data into. * @param length The number of bytes to read. * @return The number of bytes read, or a value less than zero if an error * occurs. */ int guac_common_read(int fd, void* buffer, int length); #endif guacamole-server-1.3.0/src/common/recording.c0000644000175100001440000001542013702142276016077 00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "common/recording.h" #include #include #include #include #ifdef __MINGW32__ #include #endif #include #include #include #include #include #include #include #include /** * Attempts to open a new recording within the given path and having the given * name. If such a file already exists, sequential numeric suffixes (.1, .2, * .3, etc.) are appended until a filename is found which does not exist (or * until the maximum number of numeric suffixes has been tried). If the file * absolutely cannot be opened due to an error, -1 is returned and errno is set * appropriately. * * @param path * The full path to the directory in which the data file should be created. * * @param name * The name of the data file which should be crated within the given path. * * @param basename * A buffer in which the path, a path separator, the filename, any * necessary suffix, and a NULL terminator will be stored. If insufficient * space is available, -1 will be returned, and errno will be set to * ENAMETOOLONG. * * @param basename_size * The number of bytes available within the provided basename buffer. * * @return * The file descriptor of the open data file if open succeeded, or -1 on * failure. */ static int guac_common_recording_open(const char* path, const char* name, char* basename, int basename_size) { int i; /* Concatenate path and name (separated by a single slash) */ int basename_length = snprintf(basename, basename_size - GUAC_COMMON_RECORDING_MAX_SUFFIX_LENGTH, "%s/%s", path, name); /* Abort if maximum length reached */ if (basename_length == basename_size - GUAC_COMMON_RECORDING_MAX_SUFFIX_LENGTH) { errno = ENAMETOOLONG; return -1; } /* Attempt to open recording */ int fd = open(basename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); /* Continuously retry with alternate names on failure */ if (fd == -1) { /* Prepare basename for additional suffix */ basename[basename_length] = '.'; char* suffix = &(basename[basename_length + 1]); /* Continue retrying alternative suffixes if file already exists */ for (i = 1; fd == -1 && errno == EEXIST && i <= GUAC_COMMON_RECORDING_MAX_SUFFIX; i++) { /* Append new suffix */ sprintf(suffix, "%i", i); /* Retry with newly-suffixed filename */ fd = open(basename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); } /* Abort if we've run out of filenames */ if (fd == -1) return -1; } /* end if open succeeded */ /* Explicit file locks are required only on POSIX platforms */ #ifndef __MINGW32__ /* Lock entire output file for writing by the current process */ struct flock file_lock = { .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0, .l_pid = getpid() }; /* Abort if file cannot be locked for reading */ if (fcntl(fd, F_SETLK, &file_lock) == -1) { close(fd); return -1; } #endif return fd; } guac_common_recording* guac_common_recording_create(guac_client* client, const char* path, const char* name, int create_path, int include_output, int include_mouse, int include_keys) { char filename[GUAC_COMMON_RECORDING_MAX_NAME_LENGTH]; /* Create path if it does not exist, fail if impossible */ #ifndef __MINGW32__ if (create_path && mkdir(path, S_IRWXU) && errno != EEXIST) { #else if (create_path && _mkdir(path) && errno != EEXIST) { #endif guac_client_log(client, GUAC_LOG_ERROR, "Creation of recording failed: %s", strerror(errno)); return NULL; } /* Attempt to open recording file */ int fd = guac_common_recording_open(path, name, filename, sizeof(filename)); if (fd == -1) { guac_client_log(client, GUAC_LOG_ERROR, "Creation of recording failed: %s", strerror(errno)); return NULL; } /* Create recording structure with reference to underlying socket */ guac_common_recording* recording = malloc(sizeof(guac_common_recording)); recording->socket = guac_socket_open(fd); recording->include_output = include_output; recording->include_mouse = include_mouse; recording->include_keys = include_keys; /* Replace client socket with wrapped recording socket only if including * output within the recording */ if (include_output) client->socket = guac_socket_tee(client->socket, recording->socket); /* Recording creation succeeded */ guac_client_log(client, GUAC_LOG_INFO, "Recording of session will be saved to \"%s\".", filename); return recording; } void guac_common_recording_free(guac_common_recording* recording) { /* If not including broadcast output, the output socket is not associated * with the client, and must be freed manually */ if (!recording->include_output) guac_socket_free(recording->socket); /* Free recording itself */ free(recording); } void guac_common_recording_report_mouse(guac_common_recording* recording, int x, int y, int button_mask) { /* Report mouse location only if recording should contain mouse events */ if (recording->include_mouse) guac_protocol_send_mouse(recording->socket, x, y, button_mask, guac_timestamp_current()); } void guac_common_recording_report_key(guac_common_recording* recording, int keysym, int pressed) { /* Report key state only if recording should contain key events */ if (recording->include_keys) guac_protocol_send_key(recording->socket, keysym, pressed, guac_timestamp_current()); } guacamole-server-1.3.0/src/common/Makefile.am0000644000175100001440000000453513764613616016031 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 noinst_LTLIBRARIES = libguac_common.la SUBDIRS = . tests noinst_HEADERS = \ common/io.h \ common/blank_cursor.h \ common/clipboard.h \ common/cursor.h \ common/defaults.h \ common/display.h \ common/dot_cursor.h \ common/ibar_cursor.h \ common/iconv.h \ common/json.h \ common/list.h \ common/pointer_cursor.h \ common/recording.h \ common/rect.h \ common/string.h \ common/surface.h libguac_common_la_SOURCES = \ io.c \ blank_cursor.c \ clipboard.c \ cursor.c \ display.c \ dot_cursor.c \ ibar_cursor.c \ iconv.c \ json.c \ list.c \ pointer_cursor.c \ recording.c \ rect.c \ string.c \ surface.c libguac_common_la_CFLAGS = \ -Werror -Wall -pedantic \ @LIBGUAC_INCLUDE@ libguac_common_la_LIBADD = \ @LIBGUAC_LTLIB@ guacamole-server-1.3.0/NOTICE0000644000175100001440000000024513764613616012614 00000000000000Apache Guacamole Copyright 2020 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). guacamole-server-1.3.0/Makefile.in0000644000175100001440000007434213772471101013754 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @ENABLE_COMMON_SSH_TRUE@am__append_1 = src/common-ssh @ENABLE_TERMINAL_TRUE@am__append_2 = src/terminal @ENABLE_PULSE_TRUE@am__append_3 = src/pulse @ENABLE_KUBERNETES_TRUE@am__append_4 = src/protocols/kubernetes @ENABLE_RDP_TRUE@am__append_5 = src/protocols/rdp @ENABLE_SSH_TRUE@am__append_6 = src/protocols/ssh @ENABLE_TELNET_TRUE@am__append_7 = src/protocols/telnet @ENABLE_VNC_TRUE@am__append_8 = src/protocols/vnc @ENABLE_GUACD_TRUE@am__append_9 = src/guacd @ENABLE_GUACENC_TRUE@am__append_10 = src/guacenc @ENABLE_GUACLOG_TRUE@am__append_11 = src/guaclog subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = doc/Doxyfile src/guacd/man/guacd.8 \ src/guacd/man/guacd.conf.5 src/guacenc/man/guacenc.1 \ src/guaclog/man/guaclog.1 CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir distdir-am dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(top_srcdir)/build-aux/compile \ $(top_srcdir)/build-aux/config.guess \ $(top_srcdir)/build-aux/config.sub \ $(top_srcdir)/build-aux/install-sh \ $(top_srcdir)/build-aux/ltmain.sh \ $(top_srcdir)/build-aux/missing \ $(top_srcdir)/build-aux/tap-driver.sh \ $(top_srcdir)/doc/Doxyfile.in \ $(top_srcdir)/src/guacd/man/guacd.8.in \ $(top_srcdir)/src/guacd/man/guacd.conf.5.in \ $(top_srcdir)/src/guacenc/man/guacenc.1.in \ $(top_srcdir)/src/guaclog/man/guaclog.1.in README \ build-aux/compile build-aux/config.guess build-aux/config.sub \ build-aux/install-sh build-aux/ltmain.sh build-aux/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVCODEC_CFLAGS = @AVCODEC_CFLAGS@ AVCODEC_LIBS = @AVCODEC_LIBS@ AVFORMAT_CFLAGS = @AVFORMAT_CFLAGS@ AVFORMAT_LIBS = @AVFORMAT_LIBS@ AVUTIL_CFLAGS = @AVUTIL_CFLAGS@ AVUTIL_LIBS = @AVUTIL_LIBS@ AWK = @AWK@ CAIRO_LIBS = @CAIRO_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COMMON_INCLUDE = @COMMON_INCLUDE@ COMMON_LTLIB = @COMMON_LTLIB@ COMMON_SSH_INCLUDE = @COMMON_SSH_INCLUDE@ COMMON_SSH_LTLIB = @COMMON_SSH_LTLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FREERDP2_PLUGIN_DIR = @FREERDP2_PLUGIN_DIR@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JPEG_LIBS = @JPEG_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGUAC_CLIENT_RDP_INCLUDE = @LIBGUAC_CLIENT_RDP_INCLUDE@ LIBGUAC_CLIENT_RDP_LTLIB = @LIBGUAC_CLIENT_RDP_LTLIB@ LIBGUAC_INCLUDE = @LIBGUAC_INCLUDE@ LIBGUAC_LTLIB = @LIBGUAC_LTLIB@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIBS = @MATH_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ PANGO_CFLAGS = @PANGO_CFLAGS@ PANGO_LIBS = @PANGO_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PULSE_INCLUDE = @PULSE_INCLUDE@ PULSE_LIBS = @PULSE_LIBS@ PULSE_LTLIB = @PULSE_LTLIB@ RANLIB = @RANLIB@ RDP_CFLAGS = @RDP_CFLAGS@ RDP_LIBS = @RDP_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SSH_LIBS = @SSH_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ SWSCALE_CFLAGS = @SWSCALE_CFLAGS@ SWSCALE_LIBS = @SWSCALE_LIBS@ TELNET_LIBS = @TELNET_LIBS@ TERMINAL_INCLUDE = @TERMINAL_INCLUDE@ TERMINAL_LTLIB = @TERMINAL_LTLIB@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ VNC_LIBS = @VNC_LIBS@ VORBIS_LIBS = @VORBIS_LIBS@ WEBP_LIBS = @WEBP_LIBS@ WEBSOCKETS_LIBS = @WEBSOCKETS_LIBS@ WINSOCK_LIBS = @WINSOCK_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ init_dir = @init_dir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemd_dir = @systemd_dir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 # Subprojects DIST_SUBDIRS = \ src/libguac \ src/common \ src/common-ssh \ src/terminal \ src/guacd \ src/guacenc \ src/guaclog \ src/pulse \ src/protocols/kubernetes \ src/protocols/rdp \ src/protocols/ssh \ src/protocols/telnet \ src/protocols/vnc SUBDIRS = src/libguac src/common $(am__append_1) $(am__append_2) \ $(am__append_3) $(am__append_4) $(am__append_5) \ $(am__append_6) $(am__append_7) $(am__append_8) \ $(am__append_9) $(am__append_10) $(am__append_11) EXTRA_DIST = \ .dockerignore \ CONTRIBUTING \ Dockerfile \ LICENSE \ NOTICE \ bin/guacctl \ doc/Doxyfile.in \ src/guacd-docker \ util/generate-test-runner.pl all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 doc/Doxyfile: $(top_builddir)/config.status $(top_srcdir)/doc/Doxyfile.in cd $(top_builddir) && $(SHELL) ./config.status $@ src/guacd/man/guacd.8: $(top_builddir)/config.status $(top_srcdir)/src/guacd/man/guacd.8.in cd $(top_builddir) && $(SHELL) ./config.status $@ src/guacd/man/guacd.conf.5: $(top_builddir)/config.status $(top_srcdir)/src/guacd/man/guacd.conf.5.in cd $(top_builddir) && $(SHELL) ./config.status $@ src/guacenc/man/guacenc.1: $(top_builddir)/config.status $(top_srcdir)/src/guacenc/man/guacenc.1.in cd $(top_builddir) && $(SHELL) ./config.status $@ src/guaclog/man/guaclog.1: $(top_builddir)/config.status $(top_srcdir)/src/guaclog/man/guaclog.1.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip distcheck distclean distclean-generic \ distclean-hdr distclean-libtool distclean-tags distcleancheck \ distdir distuninstallcheck dvi dvi-am html html-am info \ info-am install install-am install-data install-data-am \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: guacamole-server-1.3.0/Dockerfile0000644000175100001440000001370413772470243013702 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Dockerfile for guacamole-server # # The Debian image that should be used as the basis for the guacd image ARG DEBIAN_BASE_IMAGE=buster-slim # Use Debian as base for the build FROM debian:${DEBIAN_BASE_IMAGE} AS builder # # The Debian repository that should be preferred for dependencies (this will be # added to /etc/apt/sources.list if not already present) # # NOTE: Due to limitations of the Docker image build process, this value is # duplicated in an ARG in the second stage of the build. # ARG DEBIAN_RELEASE=buster-backports # Add repository for specified Debian release if not already present in # sources.list RUN grep " ${DEBIAN_RELEASE} " /etc/apt/sources.list || echo >> /etc/apt/sources.list \ "deb http://deb.debian.org/debian ${DEBIAN_RELEASE} main contrib non-free" # # Base directory for installed build artifacts. # # NOTE: Due to limitations of the Docker image build process, this value is # duplicated in an ARG in the second stage of the build. # ARG PREFIX_DIR=/usr/local/guacamole # Build arguments ARG BUILD_DIR=/tmp/guacd-docker-BUILD ARG BUILD_DEPENDENCIES=" \ autoconf \ automake \ freerdp2-dev \ gcc \ libcairo2-dev \ libjpeg62-turbo-dev \ libossp-uuid-dev \ libpango1.0-dev \ libpulse-dev \ libssh2-1-dev \ libssl-dev \ libtelnet-dev \ libtool \ libvncserver-dev \ libwebsockets-dev \ libwebp-dev \ make" # Do not require interaction during build ARG DEBIAN_FRONTEND=noninteractive # Bring build environment up to date and install build dependencies RUN apt-get update && \ apt-get install -t ${DEBIAN_RELEASE} -y $BUILD_DEPENDENCIES && \ rm -rf /var/lib/apt/lists/* # Add configuration scripts COPY src/guacd-docker/bin "${PREFIX_DIR}/bin/" # Copy source to container for sake of build COPY . "$BUILD_DIR" # Build guacamole-server from local source RUN ${PREFIX_DIR}/bin/build-guacd.sh "$BUILD_DIR" "$PREFIX_DIR" # Record the packages of all runtime library dependencies RUN ${PREFIX_DIR}/bin/list-dependencies.sh \ ${PREFIX_DIR}/sbin/guacd \ ${PREFIX_DIR}/lib/libguac-client-*.so \ ${PREFIX_DIR}/lib/freerdp2/*guac*.so \ > ${PREFIX_DIR}/DEPENDENCIES # Use same Debian as the base for the runtime image FROM debian:${DEBIAN_BASE_IMAGE} # # The Debian repository that should be preferred for dependencies (this will be # added to /etc/apt/sources.list if not already present) # # NOTE: Due to limitations of the Docker image build process, this value is # duplicated in an ARG in the first stage of the build. # ARG DEBIAN_RELEASE=buster-backports # Add repository for specified Debian release if not already present in # sources.list RUN grep " ${DEBIAN_RELEASE} " /etc/apt/sources.list || echo >> /etc/apt/sources.list \ "deb http://deb.debian.org/debian ${DEBIAN_RELEASE} main contrib non-free" # # Base directory for installed build artifacts. See also the # CMD directive at the end of this build stage. # # NOTE: Due to limitations of the Docker image build process, this value is # duplicated in an ARG in the first stage of the build. # ARG PREFIX_DIR=/usr/local/guacamole # Runtime environment ENV LC_ALL=C.UTF-8 ENV LD_LIBRARY_PATH=${PREFIX_DIR}/lib ENV GUACD_LOG_LEVEL=info ARG RUNTIME_DEPENDENCIES=" \ netcat-openbsd \ ca-certificates \ ghostscript \ fonts-liberation \ fonts-dejavu \ xfonts-terminus" # Do not require interaction during build ARG DEBIAN_FRONTEND=noninteractive # Copy build artifacts into this stage COPY --from=builder ${PREFIX_DIR} ${PREFIX_DIR} # Bring runtime environment up to date and install runtime dependencies RUN apt-get update && \ apt-get install -t ${DEBIAN_RELEASE} -y --no-install-recommends $RUNTIME_DEPENDENCIES && \ apt-get install -t ${DEBIAN_RELEASE} -y --no-install-recommends $(cat "${PREFIX_DIR}"/DEPENDENCIES) && \ rm -rf /var/lib/apt/lists/* # Link FreeRDP plugins into proper path RUN ${PREFIX_DIR}/bin/link-freerdp-plugins.sh \ ${PREFIX_DIR}/lib/freerdp2/libguac*.so # Checks the operating status every 5 minutes with a timeout of 5 seconds HEALTHCHECK --interval=5m --timeout=5s CMD nc -z 127.0.0.1 4822 || exit 1 # Create a new user guacd ARG UID=1000 ARG GID=1000 RUN groupadd --gid $GID guacd RUN useradd --system --create-home --shell /usr/sbin/nologin --uid $UID --gid $GID guacd # Run with user guacd USER guacd # Expose the default listener port EXPOSE 4822 # Start guacd, listening on port 0.0.0.0:4822 # # Note the path here MUST correspond to the value specified in the # PREFIX_DIR build argument. # CMD /usr/local/guacamole/sbin/guacd -b 0.0.0.0 -L $GUACD_LOG_LEVEL -f guacamole-server-1.3.0/CONTRIBUTING0000644000175100001440000000370013676721353013541 00000000000000 ------------------------------------------------------------ Contributing to Apache Guacamole ------------------------------------------------------------ Thank you for contributing to the Apache Guacamole project! There are certain procedures that must be followed for all contributions. These procedures are necessary to allow us to allocate resources for reviewing and testing your contribution, as well as communicate effectively with you during the review process. 1) Create an issue in our JIRA All changes to Guacamole must have corresponding issues in JIRA so the change can be properly tracked: https://issues.apache.org/jira/browse/GUACAMOLE/ If you do not already have an account on the Apache Software Foundation's JIRA, you will need to create one before creating your new issue. 2) Make and test your changes locally The Guacamole source is maintained in git repositories hosted on GitHub: https://github.com/apache/guacamole-client https://github.com/apache/guacamole-manual https://github.com/apache/guacamole-server https://github.com/apache/guacamole-website To make your changes, fork the applicable repositories and make commits to a topic branch in your fork. Commits should be made in logical units and must reference the JIRA issue number: $ git commit -m "GUACAMOLE-123: High-level message describing the changes." Avoid commits which cover multiple, distinct goals that could (and should) be handled separately. If you do not already have an account on GitHub, you will need to create one before making your changes. 3) Submit your changes via a pull request on GitHub Once your changes are ready, submit them by creating a pull request for the corresponding topic branch you created when you began working on your changes. The Guacamole team will then review your changes and, if they pass review, your changes will be merged. guacamole-server-1.3.0/m4/0000755000175100001440000000000013772471154012305 500000000000000guacamole-server-1.3.0/m4/lt~obsolete.m40000644000175100001440000001377413772471072015054 00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) guacamole-server-1.3.0/m4/ltversion.m40000644000175100001440000000127313772471072014516 00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) guacamole-server-1.3.0/m4/ltsugar.m40000644000175100001440000001044013772471072014146 00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) guacamole-server-1.3.0/m4/ltoptions.m40000644000175100001440000003426213772471072014530 00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) guacamole-server-1.3.0/m4/libtool.m40000644000175100001440000112530613772471072014142 00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool 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 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool 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, see . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS guacamole-server-1.3.0/configure0000755000175100001440000207561513772471077013640 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for guacamole-server 1.3.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='guacamole-server' PACKAGE_TARNAME='guacamole-server' PACKAGE_VERSION='1.3.0' PACKAGE_STRING='guacamole-server 1.3.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS ENABLE_GUACLOG_FALSE ENABLE_GUACLOG_TRUE ENABLE_GUACENC_FALSE ENABLE_GUACENC_TRUE ENABLE_GUACD_FALSE ENABLE_GUACD_TRUE ENABLE_KUBERNETES_FALSE ENABLE_KUBERNETES_TRUE WEBSOCKETS_LIBS ENABLE_WEBSOCKETS_FALSE ENABLE_WEBSOCKETS_TRUE WEBP_LIBS ENABLE_WEBP_FALSE ENABLE_WEBP_TRUE TELNET_LIBS ENABLE_TELNET_FALSE ENABLE_TELNET_TRUE ENABLE_SSH_AGENT_FALSE ENABLE_SSH_AGENT_TRUE SSH_LIBS ENABLE_SSH_FALSE ENABLE_SSH_TRUE ENABLE_COMMON_SSH_FALSE ENABLE_COMMON_SSH_TRUE ENABLE_RDP_FALSE ENABLE_RDP_TRUE FREERDP2_PLUGIN_DIR RDP_LIBS RDP_CFLAGS VNC_LIBS ENABLE_VNC_FALSE ENABLE_VNC_TRUE ENABLE_TERMINAL_FALSE ENABLE_TERMINAL_TRUE PANGOCAIRO_LIBS PANGOCAIRO_CFLAGS PANGO_LIBS PANGO_CFLAGS PULSE_LIBS ENABLE_PULSE_FALSE ENABLE_PULSE_TRUE VORBIS_LIBS ENABLE_OGG_FALSE ENABLE_OGG_TRUE WINSOCK_LIBS ENABLE_WINSOCK_FALSE ENABLE_WINSOCK_TRUE SSL_LIBS ENABLE_SSL_FALSE ENABLE_SSL_TRUE ENABLE_SWSCALE_FALSE ENABLE_SWSCALE_TRUE SWSCALE_LIBS SWSCALE_CFLAGS ENABLE_AVUTIL_FALSE ENABLE_AVUTIL_TRUE AVUTIL_LIBS AVUTIL_CFLAGS ENABLE_AVFORMAT_FALSE ENABLE_AVFORMAT_TRUE AVFORMAT_LIBS AVFORMAT_CFLAGS ENABLE_AVCODEC_FALSE ENABLE_AVCODEC_TRUE AVCODEC_LIBS AVCODEC_CFLAGS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG systemd_dir ENABLE_SYSTEMD_FALSE ENABLE_SYSTEMD_TRUE init_dir ENABLE_INIT_FALSE ENABLE_INIT_TRUE TERMINAL_INCLUDE TERMINAL_LTLIB LIBGUAC_CLIENT_RDP_INCLUDE LIBGUAC_CLIENT_RDP_LTLIB COMMON_SSH_INCLUDE COMMON_SSH_LTLIB PULSE_INCLUDE PULSE_LTLIB COMMON_INCLUDE COMMON_LTLIB LIBGUAC_INCLUDE LIBGUAC_LTLIB CUNIT_LIBS UUID_LIBS PTHREAD_LIBS CAIRO_LIBS JPEG_LIBS PNG_LIBS MATH_LIBS DL_LIBS CPP LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_shared enable_static with_pic enable_fast_install with_aix_soname enable_dependency_tracking with_gnu_ld with_sysroot enable_libtool_lock with_init_dir with_systemd_dir with_guacd_conf with_libavcodec with_libavformat with_libavutil with_libswscale with_ssl with_winsock with_vorbis with_pulse with_pango with_terminal with_vnc with_rdp with_freerdp_plugin_dir enable_allow_freerdp_snapshots with_ssh enable_ssh_agent with_telnet with_webp with_websockets enable_kubernetes enable_guacd enable_guacenc enable_guaclog ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS LT_SYS_LIBRARY_PATH CPP PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR AVCODEC_CFLAGS AVCODEC_LIBS AVFORMAT_CFLAGS AVFORMAT_LIBS AVUTIL_CFLAGS AVUTIL_LIBS SWSCALE_CFLAGS SWSCALE_LIBS PANGO_CFLAGS PANGO_LIBS PANGOCAIRO_CFLAGS PANGOCAIRO_LIBS RDP_CFLAGS RDP_LIBS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures guacamole-server 1.3.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/guacamole-server] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of guacamole-server 1.3.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --disable-libtool-lock avoid locking (might break parallel builds) --enable-allow-freerdp-snapshots allow building against unknown development snapshots of FreeRDP --enable-ssh-agent enable built-in ssh-agent --disable-kubernetes do not build support for attaching to Kubernetes pods --disable-guacd do not build the Guacamole proxy daemon --disable-guacenc do not build the Guacamole video encoding tool --disable-guaclog do not build the Guacamole input logging tool Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-aix-soname=aix|svr4|both shared library versioning (aka "SONAME") variant to provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-init-dir= install init scripts to the given directory --with-systemd-dir= install systemd units to the given directory --with-guacd-conf= the full path to the guacd config file [default=/etc/guacamole/guacd.conf] --with-libavcodec use libavcodec when encoding video [default=check] --with-libavformat use libavformat when encoding video [default=check] --with-libavutil use libavutil when encoding video [default=check] --with-libswscale use libswscale when encoding video [default=check] --with-ssl support SSL encryption [default=check] --with-winsock support Windows Sockets API [default=check] --with-vorbis support Ogg Vorbis [default=check] --with-pulse support PulseAudio [default=check] --with-pango support Pango text layout [default=check] --with-terminal support text-based protocols [default=check] --with-vnc support VNC [default=check] --with-rdp support RDP [default=check] --with-freerdp-plugin-dir= install FreeRDP plugins to the given directory [default=check] --with-ssh support SSH [default=check] --with-telnet support Telnet [default=check] --with-webp support WebP image encoding [default=check] --with-websockets support WebSockets [default=check] Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory LT_SYS_LIBRARY_PATH User-defined run-time library search path. CPP C preprocessor PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path AVCODEC_CFLAGS C compiler flags for AVCODEC, overriding pkg-config AVCODEC_LIBS linker flags for AVCODEC, overriding pkg-config AVFORMAT_CFLAGS C compiler flags for AVFORMAT, overriding pkg-config AVFORMAT_LIBS linker flags for AVFORMAT, overriding pkg-config AVUTIL_CFLAGS C compiler flags for AVUTIL, overriding pkg-config AVUTIL_LIBS linker flags for AVUTIL, overriding pkg-config SWSCALE_CFLAGS C compiler flags for SWSCALE, overriding pkg-config SWSCALE_LIBS linker flags for SWSCALE, overriding pkg-config PANGO_CFLAGS C compiler flags for PANGO, overriding pkg-config PANGO_LIBS linker flags for PANGO, overriding pkg-config PANGOCAIRO_CFLAGS C compiler flags for PANGOCAIRO, overriding pkg-config PANGOCAIRO_LIBS linker flags for PANGOCAIRO, overriding pkg-config RDP_CFLAGS C compiler flags for RDP, overriding pkg-config RDP_LIBS linker flags for RDP, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF guacamole-server configure 1.3.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 $as_echo_n "checking whether $as_decl_name is declared... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by guacamole-server $as_me 1.3.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in build-aux "$srcdir"/build-aux; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. am__api_version='1.16' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='guacamole-server' VERSION='1.3.0' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.6' macro_revision='2.4.6' ltmain=$ac_aux_dir/ltmain.sh # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case $ECHO in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 $as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } case $?:`cat confinc.out 2>/dev/null` in #( '0:this is the am__doit target') : case $s in #( BSD) : am__include='.include' am__quote='"' ;; #( *) : am__include='include' am__quote='' ;; esac ;; #( *) : ;; esac if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 $as_echo "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n "$lt_cv_sys_max_cmd_len"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) if test yes = "$GCC"; then reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 $as_echo "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 $as_echo_n "checking for a working dd... " >&6; } if ${ac_cv_path_lt_DD+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} if test -z "$lt_DD"; then ac_path_lt_DD_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in dd; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_lt_DD" || continue if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi $ac_path_lt_DD_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_lt_DD"; then : fi else ac_cv_path_lt_DD=$lt_DD fi rm -f conftest.i conftest2.i conftest.out fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 $as_echo "$ac_cv_path_lt_DD" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 $as_echo_n "checking how to truncate binary pipes... " >&6; } if ${lt_cv_truncate_bin+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 $as_echo "$lt_cv_truncate_bin" >&6; } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[012][,.]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=yes enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac else pic_mode=default fi # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac else enable_fast_install=yes fi shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[5-9]*,yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 $as_echo_n "checking which variant of shared library versioning to provide... " >&6; } # Check whether --with-aix-soname was given. if test "${with_aix_soname+set}" = set; then : withval=$with_aix_soname; case $withval in aix|svr4|both) ;; *) as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 ;; esac lt_cv_with_aix_soname=$with_aix_soname else if ${lt_cv_with_aix_soname+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_with_aix_soname=aix fi with_aix_soname=$lt_cv_with_aix_soname fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 $as_echo "$with_aix_soname" >&6; } if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o func_cc_basename $compiler cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/${ac_tool_prefix}file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi lt_prog_compiler_pic='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) export_dynamic_flag_spec='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct=no hardcode_direct_absolute=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' allow_undefined_flag=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test yes = "$GCC"; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test yes = "$lt_cv_prog_compiler__b"; then archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler ld_shlibs=yes archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' else archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; osf3*) if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test yes = "$GCC"; then wlarc='$wl' archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='$wl-z,text' allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test relink = "$hardcode_action" || test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen=shl_load else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen=dlopen else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi fi fi fi fi fi ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report what library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC ac_config_commands="$ac_config_commands libtool" # Only expand once: ac_config_headers="$ac_config_headers config.h" # Use TAP test driver for tests (part of automake) # Programs ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 $as_echo_n "checking for $CC option to accept ISO C99... " >&6; } if ${ac_cv_prog_cc_c99+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include // Check varargs macros. These examples are taken from C99 6.10.3.5. #define debug(...) fprintf (stderr, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK your preprocessor is broken; #endif #if BIG_OK #else your preprocessor is broken; #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\0'; ++i) continue; return 0; } // Check varargs and va_copy. static void test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str; int number; float fnumber; while (*format) { switch (*format++) { case 's': // string str = va_arg (args_copy, const char *); break; case 'd': // int number = va_arg (args_copy, int); break; case 'f': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); } int main () { // Check bool. _Bool success = false; // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. test_varargs ("s, d' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' || dynamic_array[ni.number - 1] != 543); ; return 0; } _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c99" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c99" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 $as_echo "$ac_cv_prog_cc_c99" >&6; } ;; esac if test "x$ac_cv_prog_cc_c99" != xno; then : fi # Headers for ac_header in fcntl.h stdlib.h string.h sys/socket.h time.h sys/time.h syslog.h unistd.h cairo/cairo.h pngstruct.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Source characteristics $as_echo "#define _XOPEN_SOURCE 700" >>confdefs.h $as_echo "#define __BSD_VISIBLE 1" >>confdefs.h # Check for whether math library is required { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 $as_echo_n "checking for cos in -lm... " >&6; } if ${ac_cv_lib_m_cos+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char cos (); int main () { return cos (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_m_cos=yes else ac_cv_lib_m_cos=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5 $as_echo "$ac_cv_lib_m_cos" >&6; } if test "x$ac_cv_lib_m_cos" = xyes; then : MATH_LIBS=-lm else ac_fn_c_check_decl "$LINENO" "cos" "ac_cv_have_decl_cos" "$ac_includes_default" if test "x$ac_cv_have_decl_cos" = xyes; then : else as_fn_error $? "\"Complex math functions are missing and no libm was found\"" "$LINENO" 5 #include fi fi # libpng { $as_echo "$as_me:${as_lineno-$LINENO}: checking for png_write_png in -lpng" >&5 $as_echo_n "checking for png_write_png in -lpng... " >&6; } if ${ac_cv_lib_png_png_write_png+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpng $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char png_write_png (); int main () { return png_write_png (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_png_png_write_png=yes else ac_cv_lib_png_png_write_png=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_png_png_write_png" >&5 $as_echo "$ac_cv_lib_png_png_write_png" >&6; } if test "x$ac_cv_lib_png_png_write_png" = xyes; then : PNG_LIBS=-lpng else as_fn_error $? "\"libpng is required for writing png messages\"" "$LINENO" 5 fi # libjpeg { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jpeg_start_compress in -ljpeg" >&5 $as_echo_n "checking for jpeg_start_compress in -ljpeg... " >&6; } if ${ac_cv_lib_jpeg_jpeg_start_compress+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ljpeg $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char jpeg_start_compress (); int main () { return jpeg_start_compress (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_jpeg_jpeg_start_compress=yes else ac_cv_lib_jpeg_jpeg_start_compress=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jpeg_jpeg_start_compress" >&5 $as_echo "$ac_cv_lib_jpeg_jpeg_start_compress" >&6; } if test "x$ac_cv_lib_jpeg_jpeg_start_compress" = xyes; then : JPEG_LIBS=-ljpeg else as_fn_error $? "\"libjpeg is required for writing jpeg messages\"" "$LINENO" 5 fi # Cairo { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cairo_create in -lcairo" >&5 $as_echo_n "checking for cairo_create in -lcairo... " >&6; } if ${ac_cv_lib_cairo_cairo_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcairo $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char cairo_create (); int main () { return cairo_create (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_cairo_cairo_create=yes else ac_cv_lib_cairo_cairo_create=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cairo_cairo_create" >&5 $as_echo "$ac_cv_lib_cairo_cairo_create" >&6; } if test "x$ac_cv_lib_cairo_cairo_create" = xyes; then : CAIRO_LIBS=-lcairo else as_fn_error $? "\"Cairo is required for drawing instructions\"" "$LINENO" 5 fi # libpthread { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5 $as_echo_n "checking for pthread_create in -lpthread... " >&6; } if ${ac_cv_lib_pthread_pthread_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_pthread_create=yes else ac_cv_lib_pthread_pthread_create=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5 $as_echo "$ac_cv_lib_pthread_pthread_create" >&6; } if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then : PTHREAD_LIBS=-lpthread $as_echo "#define HAVE_LIBPTHREAD /**/" >>confdefs.h fi # Include libdl for dlopen() if necessary { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : DL_LIBS=-ldl else ac_fn_c_check_decl "$LINENO" "dlopen" "ac_cv_have_decl_dlopen" "#include " if test "x$ac_cv_have_decl_dlopen" = xyes; then : else as_fn_error $? "\"libdl is required on systems which do not otherwise provide dlopen()\"" "$LINENO" 5 fi fi # OSSP UUID { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_make in -lossp-uuid" >&5 $as_echo_n "checking for uuid_make in -lossp-uuid... " >&6; } if ${ac_cv_lib_ossp_uuid_uuid_make+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lossp-uuid $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char uuid_make (); int main () { return uuid_make (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ossp_uuid_uuid_make=yes else ac_cv_lib_ossp_uuid_uuid_make=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ossp_uuid_uuid_make" >&5 $as_echo "$ac_cv_lib_ossp_uuid_uuid_make" >&6; } if test "x$ac_cv_lib_ossp_uuid_uuid_make" = xyes; then : UUID_LIBS=-lossp-uuid else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_make in -luuid" >&5 $as_echo_n "checking for uuid_make in -luuid... " >&6; } if ${ac_cv_lib_uuid_uuid_make+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-luuid $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char uuid_make (); int main () { return uuid_make (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_uuid_uuid_make=yes else ac_cv_lib_uuid_uuid_make=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_make" >&5 $as_echo "$ac_cv_lib_uuid_uuid_make" >&6; } if test "x$ac_cv_lib_uuid_uuid_make" = xyes; then : UUID_LIBS=-luuid else as_fn_error $? "\"The OSSP UUID library is required\"" "$LINENO" 5 fi fi # Check for and validate OSSP uuid.h header for ac_header in ossp/uuid.h do : ac_fn_c_check_header_mongrel "$LINENO" "ossp/uuid.h" "ac_cv_header_ossp_uuid_h" "$ac_includes_default" if test "x$ac_cv_header_ossp_uuid_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_OSSP_UUID_H 1 _ACEOF fi done ac_fn_c_check_decl "$LINENO" "uuid_make" "ac_cv_have_decl_uuid_make" "#ifdef HAVE_OSSP_UUID_H #include #else #include #endif " if test "x$ac_cv_have_decl_uuid_make" = xyes; then : else as_fn_error $? "\"No OSSP uuid.h found in include path\"" "$LINENO" 5 fi # cunit { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CU_run_test in -lcunit" >&5 $as_echo_n "checking for CU_run_test in -lcunit... " >&6; } if ${ac_cv_lib_cunit_CU_run_test+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcunit $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char CU_run_test (); int main () { return CU_run_test (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_cunit_CU_run_test=yes else ac_cv_lib_cunit_CU_run_test=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cunit_CU_run_test" >&5 $as_echo "$ac_cv_lib_cunit_CU_run_test" >&6; } if test "x$ac_cv_lib_cunit_CU_run_test" = xyes; then : CUNIT_LIBS=-lcunit fi # Library functions for ac_func in clock_gettime gettimeofday memmove memset select strdup nanosleep do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_decl "$LINENO" "png_get_io_ptr" "ac_cv_have_decl_png_get_io_ptr" "#include " if test "x$ac_cv_have_decl_png_get_io_ptr" = xyes; then : $as_echo "#define HAVE_PNG_GET_IO_PTR /**/" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "cairo_format_stride_for_width" "ac_cv_have_decl_cairo_format_stride_for_width" "#include " if test "x$ac_cv_have_decl_cairo_format_stride_for_width" = xyes; then : $as_echo "#define HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH /**/" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "poll" "ac_cv_have_decl_poll" "#include " if test "x$ac_cv_have_decl_poll" = xyes; then : $as_echo "#define HAVE_POLL /**/" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "strlcpy" "ac_cv_have_decl_strlcpy" "#include " if test "x$ac_cv_have_decl_strlcpy" = xyes; then : $as_echo "#define HAVE_STRLCPY /**/" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "strlcat" "ac_cv_have_decl_strlcat" "#include " if test "x$ac_cv_have_decl_strlcat" = xyes; then : $as_echo "#define HAVE_STRLCAT /**/" >>confdefs.h fi # Typedefs ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" if test "x$ac_cv_type_ssize_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define ssize_t int _ACEOF fi # Bundled libguac LIBGUAC_LTLIB='$(top_builddir)/src/libguac/libguac.la' LIBGUAC_INCLUDE='-I$(top_srcdir)/src/libguac' # Common non-libguac utility library COMMON_LTLIB='$(top_builddir)/src/common/libguac_common.la' COMMON_INCLUDE='-I$(top_srcdir)/src/common' # Common PulseAudio utility library PULSE_LTLIB='$(top_builddir)/src/pulse/libguac_pulse.la' PULSE_INCLUDE='-I$(top_srcdir)/src/pulse' # Common base SSH client COMMON_SSH_LTLIB='$(top_builddir)/src/common-ssh/libguac_common_ssh.la' COMMON_SSH_INCLUDE='-I$(top_srcdir)/src/common-ssh' # RDP support LIBGUAC_CLIENT_RDP_LTLIB='$(top_builddir)/src/protocols/rdp/libguac-client-rdp.la' LIBGUAC_CLIENT_RDP_INCLUDE='-I$(top_srcdir)/src/protocols/rdp' # Terminal emulator TERMINAL_LTLIB='$(top_builddir)/src/terminal/libguac_terminal.la' TERMINAL_INCLUDE='-I$(top_srcdir)/src/terminal $(PANGO_CFLAGS) $(PANGOCAIRO_CFLAGS) $(COMMON_INCLUDE)' # Init directory # Check whether --with-init_dir was given. if test "${with_init_dir+set}" = set; then : withval=$with_init_dir; init_dir=$withval fi if test "x${init_dir}" != "x"; then ENABLE_INIT_TRUE= ENABLE_INIT_FALSE='#' else ENABLE_INIT_TRUE='#' ENABLE_INIT_FALSE= fi # Systemd directory # Check whether --with-systemd_dir was given. if test "${with_systemd_dir+set}" = set; then : withval=$with_systemd_dir; systemd_dir=$withval fi if test "x${systemd_dir}" != "x"; then ENABLE_SYSTEMD_TRUE= ENABLE_SYSTEMD_FALSE='#' else ENABLE_SYSTEMD_TRUE='#' ENABLE_SYSTEMD_FALSE= fi # guacd config file # Check whether --with-guacd_conf was given. if test "${with_guacd_conf+set}" = set; then : withval=$with_guacd_conf; guacd_conf=$withval else guacd_conf=/etc/guacamole/guacd.conf fi cat >>confdefs.h <<_ACEOF #define GUACD_CONF_FILE "$guacd_conf" _ACEOF # # libavcodec # have_libavcodec=disabled # Check whether --with-libavcodec was given. if test "${with_libavcodec+set}" = set; then : withval=$with_libavcodec; else with_libavcodec=check fi if test "x$with_libavcodec" != "xno" then have_libavcodec=yes if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AVCODEC" >&5 $as_echo_n "checking for AVCODEC... " >&6; } if test -n "$AVCODEC_CFLAGS"; then pkg_cv_AVCODEC_CFLAGS="$AVCODEC_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec\""; } >&5 ($PKG_CONFIG --exists --print-errors "libavcodec") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_AVCODEC_CFLAGS=`$PKG_CONFIG --cflags "libavcodec" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$AVCODEC_LIBS"; then pkg_cv_AVCODEC_LIBS="$AVCODEC_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec\""; } >&5 ($PKG_CONFIG --exists --print-errors "libavcodec") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_AVCODEC_LIBS=`$PKG_CONFIG --libs "libavcodec" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then AVCODEC_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libavcodec" 2>&1` else AVCODEC_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libavcodec" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$AVCODEC_PKG_ERRORS" >&5 have_libavcodec=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_libavcodec=no else AVCODEC_CFLAGS=$pkg_cv_AVCODEC_CFLAGS AVCODEC_LIBS=$pkg_cv_AVCODEC_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi; fi if test "x${have_libavcodec}" = "xyes"; then ENABLE_AVCODEC_TRUE= ENABLE_AVCODEC_FALSE='#' else ENABLE_AVCODEC_TRUE='#' ENABLE_AVCODEC_FALSE= fi # # libavformat # have_libavformat=disabled # Check whether --with-libavformat was given. if test "${with_libavformat+set}" = set; then : withval=$with_libavformat; . with_libavformat=check fi if test "x$with_libavformat" != "xno" then have_libavformat=yes pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AVFORMAT" >&5 $as_echo_n "checking for AVFORMAT... " >&6; } if test -n "$AVFORMAT_CFLAGS"; then pkg_cv_AVFORMAT_CFLAGS="$AVFORMAT_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavformat\""; } >&5 ($PKG_CONFIG --exists --print-errors "libavformat") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_AVFORMAT_CFLAGS=`$PKG_CONFIG --cflags "libavformat" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$AVFORMAT_LIBS"; then pkg_cv_AVFORMAT_LIBS="$AVFORMAT_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavformat\""; } >&5 ($PKG_CONFIG --exists --print-errors "libavformat") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_AVFORMAT_LIBS=`$PKG_CONFIG --libs "libavformat" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then AVFORMAT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libavformat" 2>&1` else AVFORMAT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libavformat" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$AVFORMAT_PKG_ERRORS" >&5 have_libavformat=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_libavformat=no else AVFORMAT_CFLAGS=$pkg_cv_AVFORMAT_CFLAGS AVFORMAT_LIBS=$pkg_cv_AVFORMAT_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi; fi if test "x${have_libavformat}" = "xyes"; then ENABLE_AVFORMAT_TRUE= ENABLE_AVFORMAT_FALSE='#' else ENABLE_AVFORMAT_TRUE='#' ENABLE_AVFORMAT_FALSE= fi # # libavutil # have_libavutil=disabled # Check whether --with-libavutil was given. if test "${with_libavutil+set}" = set; then : withval=$with_libavutil; else with_libavutil=check fi if test "x$with_libavutil" != "xno" then have_libavutil=yes pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AVUTIL" >&5 $as_echo_n "checking for AVUTIL... " >&6; } if test -n "$AVUTIL_CFLAGS"; then pkg_cv_AVUTIL_CFLAGS="$AVUTIL_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavutil\""; } >&5 ($PKG_CONFIG --exists --print-errors "libavutil") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_AVUTIL_CFLAGS=`$PKG_CONFIG --cflags "libavutil" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$AVUTIL_LIBS"; then pkg_cv_AVUTIL_LIBS="$AVUTIL_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavutil\""; } >&5 ($PKG_CONFIG --exists --print-errors "libavutil") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_AVUTIL_LIBS=`$PKG_CONFIG --libs "libavutil" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then AVUTIL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libavutil" 2>&1` else AVUTIL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libavutil" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$AVUTIL_PKG_ERRORS" >&5 have_libavutil=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_libavutil=no else AVUTIL_CFLAGS=$pkg_cv_AVUTIL_CFLAGS AVUTIL_LIBS=$pkg_cv_AVUTIL_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi; fi if test "x${have_libavutil}" = "xyes"; then ENABLE_AVUTIL_TRUE= ENABLE_AVUTIL_FALSE='#' else ENABLE_AVUTIL_TRUE='#' ENABLE_AVUTIL_FALSE= fi # # libswscale # have_libswscale=disabled # Check whether --with-libswscale was given. if test "${with_libswscale+set}" = set; then : withval=$with_libswscale; else with_libswscale=check fi if test "x$with_libswscale" != "xno" then have_libswscale=yes pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SWSCALE" >&5 $as_echo_n "checking for SWSCALE... " >&6; } if test -n "$SWSCALE_CFLAGS"; then pkg_cv_SWSCALE_CFLAGS="$SWSCALE_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libswscale\""; } >&5 ($PKG_CONFIG --exists --print-errors "libswscale") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SWSCALE_CFLAGS=`$PKG_CONFIG --cflags "libswscale" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$SWSCALE_LIBS"; then pkg_cv_SWSCALE_LIBS="$SWSCALE_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libswscale\""; } >&5 ($PKG_CONFIG --exists --print-errors "libswscale") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SWSCALE_LIBS=`$PKG_CONFIG --libs "libswscale" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then SWSCALE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libswscale" 2>&1` else SWSCALE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libswscale" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$SWSCALE_PKG_ERRORS" >&5 have_libswscale=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_libswscale=no else SWSCALE_CFLAGS=$pkg_cv_SWSCALE_CFLAGS SWSCALE_LIBS=$pkg_cv_SWSCALE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi; fi if test "x${have_libswscale}" = "xyes"; then ENABLE_SWSCALE_TRUE= ENABLE_SWSCALE_FALSE='#' else ENABLE_SWSCALE_TRUE='#' ENABLE_SWSCALE_FALSE= fi # # libssl # have_ssl=disabled SSL_LIBS= # Check whether --with-ssl was given. if test "${with_ssl+set}" = set; then : withval=$with_ssl; else with_ssl=check fi if test "x$with_ssl" != "xno" then have_ssl=yes ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default" if test "x$ac_cv_header_openssl_ssl_h" = xyes; then : else have_ssl=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_CTX_new in -lssl" >&5 $as_echo_n "checking for SSL_CTX_new in -lssl... " >&6; } if ${ac_cv_lib_ssl_SSL_CTX_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lssl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char SSL_CTX_new (); int main () { return SSL_CTX_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ssl_SSL_CTX_new=yes else ac_cv_lib_ssl_SSL_CTX_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_CTX_new" >&5 $as_echo "$ac_cv_lib_ssl_SSL_CTX_new" >&6; } if test "x$ac_cv_lib_ssl_SSL_CTX_new" = xyes; then : SSL_LIBS="$SSL_LIBS -lssl -lcrypto" else have_ssl=no fi if test "x${have_ssl}" = "xno" then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -------------------------------------------- Unable to find libssl. guacd will not support SSL connections. --------------------------------------------" >&5 $as_echo "$as_me: WARNING: -------------------------------------------- Unable to find libssl. guacd will not support SSL connections. --------------------------------------------" >&2;} else $as_echo "#define ENABLE_SSL /**/" >>confdefs.h # OpenSSL 1.1 accessor function for DSA signature values ac_fn_c_check_decl "$LINENO" "DSA_SIG_get0" "ac_cv_have_decl_DSA_SIG_get0" "#include " if test "x$ac_cv_have_decl_DSA_SIG_get0" = xyes; then : $as_echo "#define HAVE_DSA_SIG_GET0 /**/" >>confdefs.h fi # OpenSSL 1.1 accessor function for DSA public key parameters ac_fn_c_check_decl "$LINENO" "DSA_get0_pqg" "ac_cv_have_decl_DSA_get0_pqg" "#include " if test "x$ac_cv_have_decl_DSA_get0_pqg" = xyes; then : $as_echo "#define HAVE_DSA_GET0_PQG /**/" >>confdefs.h fi # OpenSSL 1.1 accessor function for DSA public/private key values ac_fn_c_check_decl "$LINENO" "DSA_get0_key" "ac_cv_have_decl_DSA_get0_key" "#include " if test "x$ac_cv_have_decl_DSA_get0_key" = xyes; then : $as_echo "#define HAVE_DSA_GET0_KEY /**/" >>confdefs.h fi # OpenSSL 1.1 accessor function for RSA public/private key values ac_fn_c_check_decl "$LINENO" "RSA_get0_key" "ac_cv_have_decl_RSA_get0_key" "#include " if test "x$ac_cv_have_decl_RSA_get0_key" = xyes; then : $as_echo "#define HAVE_RSA_GET0_KEY /**/" >>confdefs.h fi # OpenSSL 1.1 does away with explicit threading callbacks { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libssl requires threading callbacks" >&5 $as_echo_n "checking whether libssl requires threading callbacks... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if OPENSSL_VERSION_NUMBER < 0x10100000L #error Threading callbacks required. #endif int main() { return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define OPENSSL_REQUIRES_THREADING_CALLBACKS /**/" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi fi if test "x${have_ssl}" = "xyes"; then ENABLE_SSL_TRUE= ENABLE_SSL_FALSE='#' else ENABLE_SSL_TRUE='#' ENABLE_SSL_FALSE= fi # # Winsock # have_winsock=disabled WINSOCK_LIBS= # Check whether --with-winsock was given. if test "${with_winsock+set}" = set; then : withval=$with_winsock; else with_winsock=check fi if test "x$with_winsock" != "xno" then have_winsock=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lwsock32" >&5 $as_echo_n "checking for main in -lwsock32... " >&6; } if ${ac_cv_lib_wsock32_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lwsock32 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_wsock32_main=yes else ac_cv_lib_wsock32_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_wsock32_main" >&5 $as_echo "$ac_cv_lib_wsock32_main" >&6; } if test "x$ac_cv_lib_wsock32_main" = xyes; then : WINSOCK_LIBS="-lwsock32" $as_echo "#define ENABLE_WINSOCK /**/" >>confdefs.h else have_winsock=no fi fi if test "x${have_winsock}" = "xyes"; then ENABLE_WINSOCK_TRUE= ENABLE_WINSOCK_FALSE='#' else ENABLE_WINSOCK_TRUE='#' ENABLE_WINSOCK_FALSE= fi # # Ogg Vorbis # have_vorbis=disabled VORBIS_LIBS= # Check whether --with-vorbis was given. if test "${with_vorbis+set}" = set; then : withval=$with_vorbis; else with_vorbis=check fi if test "x$with_vorbis" != "xno" then have_vorbis=yes ac_fn_c_check_header_mongrel "$LINENO" "vorbis/vorbisenc.h" "ac_cv_header_vorbis_vorbisenc_h" "$ac_includes_default" if test "x$ac_cv_header_vorbis_vorbisenc_h" = xyes; then : else have_vorbis=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ogg_stream_init in -logg" >&5 $as_echo_n "checking for ogg_stream_init in -logg... " >&6; } if ${ac_cv_lib_ogg_ogg_stream_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-logg $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ogg_stream_init (); int main () { return ogg_stream_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ogg_ogg_stream_init=yes else ac_cv_lib_ogg_ogg_stream_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ogg_ogg_stream_init" >&5 $as_echo "$ac_cv_lib_ogg_ogg_stream_init" >&6; } if test "x$ac_cv_lib_ogg_ogg_stream_init" = xyes; then : VORBIS_LIBS="$VORBIS_LIBS -logg" else have_vorbis=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for vorbis_block_init in -lvorbis" >&5 $as_echo_n "checking for vorbis_block_init in -lvorbis... " >&6; } if ${ac_cv_lib_vorbis_vorbis_block_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lvorbis $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char vorbis_block_init (); int main () { return vorbis_block_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_vorbis_vorbis_block_init=yes else ac_cv_lib_vorbis_vorbis_block_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vorbis_vorbis_block_init" >&5 $as_echo "$ac_cv_lib_vorbis_vorbis_block_init" >&6; } if test "x$ac_cv_lib_vorbis_vorbis_block_init" = xyes; then : VORBIS_LIBS="$VORBIS_LIBS -lvorbis" else have_vorbis=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for vorbis_encode_init in -lvorbisenc" >&5 $as_echo_n "checking for vorbis_encode_init in -lvorbisenc... " >&6; } if ${ac_cv_lib_vorbisenc_vorbis_encode_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lvorbisenc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char vorbis_encode_init (); int main () { return vorbis_encode_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_vorbisenc_vorbis_encode_init=yes else ac_cv_lib_vorbisenc_vorbis_encode_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vorbisenc_vorbis_encode_init" >&5 $as_echo "$ac_cv_lib_vorbisenc_vorbis_encode_init" >&6; } if test "x$ac_cv_lib_vorbisenc_vorbis_encode_init" = xyes; then : VORBIS_LIBS="$VORBIS_LIBS -lvorbisenc" else have_vorbis=no fi if test "x${have_vorbis}" = "xno" then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -------------------------------------------- Unable to find libogg / libvorbis / libvorbisenc. Sound will not be encoded with Ogg Vorbis. --------------------------------------------" >&5 $as_echo "$as_me: WARNING: -------------------------------------------- Unable to find libogg / libvorbis / libvorbisenc. Sound will not be encoded with Ogg Vorbis. --------------------------------------------" >&2;} else $as_echo "#define ENABLE_OGG /**/" >>confdefs.h fi fi if test "x${have_vorbis}" = "xyes"; then ENABLE_OGG_TRUE= ENABLE_OGG_FALSE='#' else ENABLE_OGG_TRUE='#' ENABLE_OGG_FALSE= fi # # PulseAudio # have_pulse=disabled PULSE_LIBS= # Check whether --with-pulse was given. if test "${with_pulse+set}" = set; then : withval=$with_pulse; else with_pulse=check fi if test "x$with_pulse" != "xno" then have_pulse=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pa_context_new in -lpulse" >&5 $as_echo_n "checking for pa_context_new in -lpulse... " >&6; } if ${ac_cv_lib_pulse_pa_context_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpulse $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pa_context_new (); int main () { return pa_context_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pulse_pa_context_new=yes else ac_cv_lib_pulse_pa_context_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pulse_pa_context_new" >&5 $as_echo "$ac_cv_lib_pulse_pa_context_new" >&6; } if test "x$ac_cv_lib_pulse_pa_context_new" = xyes; then : PULSE_LIBS="$PULSE_LIBS -lpulse" else have_pulse=no fi if test "x${have_pulse}" = "xno" then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -------------------------------------------- Unable to find libpulse Sound support for VNC will be disabled --------------------------------------------" >&5 $as_echo "$as_me: WARNING: -------------------------------------------- Unable to find libpulse Sound support for VNC will be disabled --------------------------------------------" >&2;} else $as_echo "#define ENABLE_PULSE /**/" >>confdefs.h fi fi if test "x${have_pulse}" = "xyes"; then ENABLE_PULSE_TRUE= ENABLE_PULSE_FALSE='#' else ENABLE_PULSE_TRUE='#' ENABLE_PULSE_FALSE= fi # # PANGO # have_pango=disabled # Check whether --with-pango was given. if test "${with_pango+set}" = set; then : withval=$with_pango; else with_pango=check fi if test "x$with_pango" != "xno" then have_pango=yes pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PANGO" >&5 $as_echo_n "checking for PANGO... " >&6; } if test -n "$PANGO_CFLAGS"; then pkg_cv_PANGO_CFLAGS="$PANGO_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pango\""; } >&5 ($PKG_CONFIG --exists --print-errors "pango") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_PANGO_CFLAGS=`$PKG_CONFIG --cflags "pango" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$PANGO_LIBS"; then pkg_cv_PANGO_LIBS="$PANGO_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pango\""; } >&5 ($PKG_CONFIG --exists --print-errors "pango") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_PANGO_LIBS=`$PKG_CONFIG --libs "pango" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then PANGO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "pango" 2>&1` else PANGO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "pango" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$PANGO_PKG_ERRORS" >&5 have_pango=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_pango=no else PANGO_CFLAGS=$pkg_cv_PANGO_CFLAGS PANGO_LIBS=$pkg_cv_PANGO_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi; pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PANGOCAIRO" >&5 $as_echo_n "checking for PANGOCAIRO... " >&6; } if test -n "$PANGOCAIRO_CFLAGS"; then pkg_cv_PANGOCAIRO_CFLAGS="$PANGOCAIRO_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pangocairo\""; } >&5 ($PKG_CONFIG --exists --print-errors "pangocairo") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_PANGOCAIRO_CFLAGS=`$PKG_CONFIG --cflags "pangocairo" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$PANGOCAIRO_LIBS"; then pkg_cv_PANGOCAIRO_LIBS="$PANGOCAIRO_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pangocairo\""; } >&5 ($PKG_CONFIG --exists --print-errors "pangocairo") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_PANGOCAIRO_LIBS=`$PKG_CONFIG --libs "pangocairo" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then PANGOCAIRO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "pangocairo" 2>&1` else PANGOCAIRO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "pangocairo" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$PANGOCAIRO_PKG_ERRORS" >&5 have_pango=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_pango=no else PANGOCAIRO_CFLAGS=$pkg_cv_PANGOCAIRO_CFLAGS PANGOCAIRO_LIBS=$pkg_cv_PANGOCAIRO_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi; fi # # Terminal emulator # have_terminal=disabled # Check whether --with-terminal was given. if test "${with_terminal+set}" = set; then : withval=$with_terminal; else with_terminal=check fi if test "x$with_terminal" != "xno" then have_terminal=yes if test "x${have_pango}" != "xyes" then have_terminal=no fi fi if test "x${have_terminal}" = "xyes"; then ENABLE_TERMINAL_TRUE= ENABLE_TERMINAL_FALSE='#' else ENABLE_TERMINAL_TRUE='#' ENABLE_TERMINAL_FALSE= fi # # libVNCServer # have_libvncserver=disabled VNC_LIBS= # Check whether --with-vnc was given. if test "${with_vnc+set}" = set; then : withval=$with_vnc; else with_vnc=check fi if test "x$with_vnc" != "xno" then have_libvncserver=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rfbInitClient in -lvncclient" >&5 $as_echo_n "checking for rfbInitClient in -lvncclient... " >&6; } if ${ac_cv_lib_vncclient_rfbInitClient+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lvncclient $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char rfbInitClient (); int main () { return rfbInitClient (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_vncclient_rfbInitClient=yes else ac_cv_lib_vncclient_rfbInitClient=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vncclient_rfbInitClient" >&5 $as_echo "$ac_cv_lib_vncclient_rfbInitClient" >&6; } if test "x$ac_cv_lib_vncclient_rfbInitClient" = xyes; then : VNC_LIBS="$VNC_LIBS -lvncclient" else have_libvncserver=no fi fi if test "x${have_libvncserver}" = "xyes"; then ENABLE_VNC_TRUE= ENABLE_VNC_FALSE='#' else ENABLE_VNC_TRUE='#' ENABLE_VNC_FALSE= fi # # Repeater support within libVNCServer # if test "x${have_libvncserver}" = "xyes" then have_vnc_repeater=yes ac_fn_c_check_member "$LINENO" "rfbClient" "destHost" "ac_cv_member_rfbClient_destHost" "#include " if test "x$ac_cv_member_rfbClient_destHost" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_RFBCLIENT_DESTHOST 1 _ACEOF else have_vnc_repeater=no fi ac_fn_c_check_member "$LINENO" "rfbClient" "destPort" "ac_cv_member_rfbClient_destPort" "#include " if test "x$ac_cv_member_rfbClient_destPort" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_RFBCLIENT_DESTPORT 1 _ACEOF else have_vnc_repeater=no fi if test "x${have_vnc_repeater}" = "xno" then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -------------------------------------------- No repeater support found in libvncclient. Support for VNC repeaters will not be built. --------------------------------------------" >&5 $as_echo "$as_me: WARNING: -------------------------------------------- No repeater support found in libvncclient. Support for VNC repeaters will not be built. --------------------------------------------" >&2;} else $as_echo "#define ENABLE_VNC_REPEATER /**/" >>confdefs.h fi fi # # Listening support within libVNCServer # if test "x${have_libvncserver}" = "xyes" then have_vnc_listen=yes ac_fn_c_check_decl "$LINENO" "listenForIncomingConnectionsNoFork" "ac_cv_have_decl_listenForIncomingConnectionsNoFork" "#include " if test "x$ac_cv_have_decl_listenForIncomingConnectionsNoFork" = xyes; then : else have_vnc_listen=no fi if test "x${have_vnc_listen}" = "xno" then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -------------------------------------------- No listening support found in libvncclient. Support for listen-mode connections will not be built. --------------------------------------------" >&5 $as_echo "$as_me: WARNING: -------------------------------------------- No listening support found in libvncclient. Support for listen-mode connections will not be built. --------------------------------------------" >&2;} else $as_echo "#define ENABLE_VNC_LISTEN /**/" >>confdefs.h fi fi # # TLS Locking Support within libVNCServer # if test "x${have_libvncserver}" = "xyes" then have_vnc_tls_locking=yes ac_fn_c_check_member "$LINENO" "rfbClient" "LockWriteToTLS" "ac_cv_member_rfbClient_LockWriteToTLS" "#include " if test "x$ac_cv_member_rfbClient_LockWriteToTLS" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_RFBCLIENT_LOCKWRITETOTLS 1 _ACEOF else have_vnc_tls_locking=no fi ac_fn_c_check_member "$LINENO" "rfbClient" "UnlockWriteToTLS" "ac_cv_member_rfbClient_UnlockWriteToTLS" "#include " if test "x$ac_cv_member_rfbClient_UnlockWriteToTLS" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_RFBCLIENT_UNLOCKWRITETOTLS 1 _ACEOF else have_vnc_tls_locking=no fi if test "x${have_vnc_tls_locking}" = "xno" then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -------------------------------------------- This version of libvncclient lacks support for TLS locking. VNC connections that use TLS may experience instability as documented in GUACAMOLE-414" >&5 $as_echo "$as_me: WARNING: -------------------------------------------- This version of libvncclient lacks support for TLS locking. VNC connections that use TLS may experience instability as documented in GUACAMOLE-414" >&2;} else $as_echo "#define ENABLE_VNC_TLS_LOCKING /**/" >>confdefs.h fi fi # # FreeRDP 2 (libfreerdp2, libfreerdp-client2, and libwinpr2) # have_freerdp2=disabled FREERDP2_PLUGIN_DIR= # Check whether --with-rdp was given. if test "${with_rdp+set}" = set; then : withval=$with_rdp; else with_rdp=check fi # FreeRDP plugin directory # Check whether --with-freerdp_plugin_dir was given. if test "${with_freerdp_plugin_dir+set}" = set; then : withval=$with_freerdp_plugin_dir; FREERDP2_PLUGIN_DIR=$withval fi # Preserve CPPFLAGS so it can be restored later, following the addition of # options specific to FreeRDP tests OLDCPPFLAGS="$CPPFLAGS" if test "x$with_rdp" != "xno" then have_freerdp2=yes pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for RDP" >&5 $as_echo_n "checking for RDP... " >&6; } if test -n "$RDP_CFLAGS"; then pkg_cv_RDP_CFLAGS="$RDP_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"freerdp2 freerdp-client2 winpr2\""; } >&5 ($PKG_CONFIG --exists --print-errors "freerdp2 freerdp-client2 winpr2") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_RDP_CFLAGS=`$PKG_CONFIG --cflags "freerdp2 freerdp-client2 winpr2" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$RDP_LIBS"; then pkg_cv_RDP_LIBS="$RDP_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"freerdp2 freerdp-client2 winpr2\""; } >&5 ($PKG_CONFIG --exists --print-errors "freerdp2 freerdp-client2 winpr2") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_RDP_LIBS=`$PKG_CONFIG --libs "freerdp2 freerdp-client2 winpr2" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then RDP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "freerdp2 freerdp-client2 winpr2" 2>&1` else RDP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "freerdp2 freerdp-client2 winpr2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$RDP_PKG_ERRORS" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -------------------------------------------- Unable to find FreeRDP (libfreerdp2 / libfreerdp-client2 / libwinpr2) RDP will be disabled. --------------------------------------------" >&5 $as_echo "$as_me: WARNING: -------------------------------------------- Unable to find FreeRDP (libfreerdp2 / libfreerdp-client2 / libwinpr2) RDP will be disabled. --------------------------------------------" >&2;} have_freerdp2=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -------------------------------------------- Unable to find FreeRDP (libfreerdp2 / libfreerdp-client2 / libwinpr2) RDP will be disabled. --------------------------------------------" >&5 $as_echo "$as_me: WARNING: -------------------------------------------- Unable to find FreeRDP (libfreerdp2 / libfreerdp-client2 / libwinpr2) RDP will be disabled. --------------------------------------------" >&2;} have_freerdp2=no else RDP_CFLAGS=$pkg_cv_RDP_CFLAGS RDP_LIBS=$pkg_cv_RDP_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CPPFLAGS="${RDP_CFLAGS} -Werror $CPPFLAGS" if test "x${FREERDP2_PLUGIN_DIR}" = "x"; then : FREERDP2_PLUGIN_DIR="`$PKG_CONFIG --variable=libdir freerdp2`/freerdp2" fi fi fi # Available color conversion functions if test "x$have_freerdp2" = "xyes" then # FreeRDP 2.0.0-rc3 and older referred to FreeRDPConvertColor() as # ConvertColor() ac_fn_c_check_decl "$LINENO" "FreeRDPConvertColor" "ac_cv_have_decl_FreeRDPConvertColor" "#include " if test "x$ac_cv_have_decl_FreeRDPConvertColor" = xyes; then : $as_echo "#define HAVE_FREERDPCONVERTCOLOR /**/" >>confdefs.h fi fi # It is difficult or impossible to test for variations in FreeRDP behavior in # between releases, as the change in behavior may not (yet) be associated with # a corresponding change in version number and may not have any detectable # effect on the FreeRDP API # Check whether --enable-allow_freerdp_snapshots was given. if test "${enable_allow_freerdp_snapshots+set}" = set; then : enableval=$enable_allow_freerdp_snapshots; allow_freerdp_snapshots=yes fi if test "x${have_freerdp2}" = "xyes" -a "x${allow_freerdp_snapshots}" != "xyes" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether FreeRDP appears to be a development version" >&5 $as_echo_n "checking whether FreeRDP appears to be a development version... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include FREERDP_VERSION_FULL _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "\"[0-9]+\\.[0-9]+\\.[0-9]+(-rc[0-9]+)?\"" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } as_fn_error $? " -------------------------------------------- You are building against a development version of FreeRDP. Non-release versions of FreeRDP may have differences in behavior that are impossible to check for at build time. This may result in memory leaks or other strange behavior. *** PLEASE USE A RELEASED VERSION OF FREERDP IF POSSIBLE *** If you are ABSOLUTELY CERTAIN that building against this version of FreeRDP is OK, rerun configure with the --enable-allow-freerdp-snapshots --------------------------------------------" "$LINENO" 5 fi rm -f conftest* fi # Variation in memory internal allocation/free behavior for bitmaps if test "x${have_freerdp2}" = "xyes" then # FreeRDP 2.0.0-rc0 and older automatically free rdpBitmap and its # associated data member within Bitmap_Free(), relying on the # implementation-specific free handler to free only implementation-specific # data. This changed in commit 2cf10cc, and implementations must now # manually free all data associated with the rdpBitmap, even data which # was not allocated by the implementation. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Bitmap_Free() frees the rdpBitmap and its image data" >&5 $as_echo_n "checking whether Bitmap_Free() frees the rdpBitmap and its image data... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include FREERDP_VERSION_FULL _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "\"2\\.0\\.0-dev\"" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define FREERDP_BITMAP_FREE_FREES_BITMAP /**/" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f conftest* fi # Variation in memory internal allocation/free behavior for channel streams if test "x${have_freerdp2}" = "xyes" then # FreeRDP 2.0.0-rc3 through 2.0.0-rc4 automatically free the wStream # provided to pVirtualChannelWriteEx(). This changed in commit 1b78b59, and # implementations must manually free the wStream after it is no longer # needed (after the write is complete or cancelled). { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pVirtualChannelWriteEx() frees the wStream upon completion" >&5 $as_echo_n "checking whether pVirtualChannelWriteEx() frees the wStream upon completion... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include FREERDP_VERSION_FULL _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "\"2\\.0\\.0-(rc|dev)[3-4]\"" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define FREERDP_SVC_CORE_FREES_WSTREAM /**/" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f conftest* fi # Glyph callback variants if test "x${have_freerdp2}" = "xyes" then # FreeRDP 2.0.0-rc3 and older used UINT32 for integer parameters to all # rdpGlyph callbacks { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether rdpGlyph callbacks accept INT32 integer parameters" >&5 $as_echo_n "checking whether rdpGlyph callbacks accept INT32 integer parameters... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include BOOL test_begindraw(rdpContext* context, INT32 x, INT32 y, INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor, BOOL redundant); rdpGlyph glyph = { .BeginDraw = test_begindraw }; int main() { return (int) glyph.BeginDraw(NULL, 0, 0, 0, 0, 0, 0, FALSE); } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define FREERDP_GLYPH_CALLBACKS_ACCEPT_INT32 /**/" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi # CLIPRDR callback variants if test "x${have_freerdp2}" = "xyes" then # FreeRDP 2.0.0-rc3 and older did not use const for CLIPRDR callbacks { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether CLIPRDR callbacks require const for their final parameter" >&5 $as_echo_n "checking whether CLIPRDR callbacks require const for their final parameter... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include UINT test_monitor_ready(CliprdrClientContext* cliprdr, const CLIPRDR_MONITOR_READY* monitor_ready); CliprdrClientContext context = { .MonitorReady = test_monitor_ready }; int main() { return (int) context.MonitorReady(NULL, NULL); } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define FREERDP_CLIPRDR_CALLBACKS_REQUIRE_CONST /**/" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi # RAIL callback variants if test "x${have_freerdp2}" = "xyes" then # FreeRDP 2.0.0-rc3 and older did not use const for RAIL callbacks { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether RAIL callbacks require const for their final parameter" >&5 $as_echo_n "checking whether RAIL callbacks require const for their final parameter... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include UINT test_server_handshake(RailClientContext* rail, const RAIL_HANDSHAKE_ORDER* handshake); RailClientContext context = { .ServerHandshake = test_server_handshake }; int main() { return (int) context.ServerHandshake(NULL, NULL); } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define FREERDP_RAIL_CALLBACKS_REQUIRE_CONST /**/" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi # Support for receiving unannounced orders from the RDP server if test "x${have_freerdp2}" = "xyes" then ac_fn_c_check_member "$LINENO" "rdpSettings" "AllowUnanouncedOrdersFromServer" "ac_cv_member_rdpSettings_AllowUnanouncedOrdersFromServer" "#include " if test "x$ac_cv_member_rdpSettings_AllowUnanouncedOrdersFromServer" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_RDPSETTINGS_ALLOWUNANOUNCEDORDERSFROMSERVER 1 _ACEOF else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -------------------------------------------- This version of FreeRDP does not support relaxed order checks. RDP servers that send orders that the client did not announce as supported (such as the VirtualBox RDP server) will likely not be usable. See: https://issues.apache.org/jira/browse/GUACAMOLE-962 --------------------------------------------" >&5 $as_echo "$as_me: WARNING: -------------------------------------------- This version of FreeRDP does not support relaxed order checks. RDP servers that send orders that the client did not announce as supported (such as the VirtualBox RDP server) will likely not be usable. See: https://issues.apache.org/jira/browse/GUACAMOLE-962 --------------------------------------------" >&2;} fi fi # Restore CPPFLAGS, removing FreeRDP-specific options needed for testing CPPFLAGS="$OLDCPPFLAGS" if test "x${have_freerdp2}" = "xyes"; then ENABLE_RDP_TRUE= ENABLE_RDP_FALSE='#' else ENABLE_RDP_TRUE='#' ENABLE_RDP_FALSE= fi # # libssh2 # have_libssh2=disabled SSH_LIBS= # Check whether --with-ssh was given. if test "${with_ssh+set}" = set; then : withval=$with_ssh; else with_ssh=check fi # Check whether --enable-ssh_agent was given. if test "${enable_ssh_agent+set}" = set; then : enableval=$enable_ssh_agent; enable_ssh_agent=yes fi if test "x$with_ssh" != "xno" then have_libssh2=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libssh2_session_init_ex in -lssh2" >&5 $as_echo_n "checking for libssh2_session_init_ex in -lssh2... " >&6; } if ${ac_cv_lib_ssh2_libssh2_session_init_ex+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lssh2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char libssh2_session_init_ex (); int main () { return libssh2_session_init_ex (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ssh2_libssh2_session_init_ex=yes else ac_cv_lib_ssh2_libssh2_session_init_ex=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssh2_libssh2_session_init_ex" >&5 $as_echo "$ac_cv_lib_ssh2_libssh2_session_init_ex" >&6; } if test "x$ac_cv_lib_ssh2_libssh2_session_init_ex" = xyes; then : SSH_LIBS="$SSH_LIBS -lssh2" else have_libssh2=no fi fi if test "x${have_libssh2}" = "xyes" \ -a "x${have_ssl}" = "xyes"; then ENABLE_COMMON_SSH_TRUE= ENABLE_COMMON_SSH_FALSE='#' else ENABLE_COMMON_SSH_TRUE='#' ENABLE_COMMON_SSH_FALSE= fi if test -z "$ENABLE_COMMON_SSH_TRUE"; then : $as_echo "#define ENABLE_COMMON_SSH /**/" >>confdefs.h fi if test "x${have_libssh2}" = "xyes" \ -a "x${have_terminal}" = "xyes" \ -a "x${have_ssl}" = "xyes"; then ENABLE_SSH_TRUE= ENABLE_SSH_FALSE='#' else ENABLE_SSH_TRUE='#' ENABLE_SSH_FALSE= fi # # Underlying crypto library usage of libssh2 # if test "x${have_libssh2}" = "xyes" then # Whether libssh2 was built against libgcrypt { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcry_control in -lssh2" >&5 $as_echo_n "checking for gcry_control in -lssh2... " >&6; } if ${ac_cv_lib_ssh2_gcry_control+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lssh2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gcry_control (); int main () { return gcry_control (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ssh2_gcry_control=yes else ac_cv_lib_ssh2_gcry_control=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssh2_gcry_control" >&5 $as_echo "$ac_cv_lib_ssh2_gcry_control" >&6; } if test "x$ac_cv_lib_ssh2_gcry_control" = xyes; then : ac_fn_c_check_header_mongrel "$LINENO" "gcrypt.h" "ac_cv_header_gcrypt_h" "$ac_includes_default" if test "x$ac_cv_header_gcrypt_h" = xyes; then : $as_echo "#define LIBSSH2_USES_GCRYPT /**/" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -------------------------------------------- libssh2 appears to be built against libgcrypt, but the libgcrypt headers could not be found. SSH will be disabled. --------------------------------------------" >&5 $as_echo "$as_me: WARNING: -------------------------------------------- libssh2 appears to be built against libgcrypt, but the libgcrypt headers could not be found. SSH will be disabled. --------------------------------------------" >&2;} have_libssh2=no fi fi fi # # Agent forwarding support within libssh2 # have_ssh_agent=no if test "x${have_libssh2}" = "xyes" -a "x${enable_ssh_agent}" = "xyes" then ac_fn_c_check_decl "$LINENO" "libssh2_channel_request_auth_agent" "ac_cv_have_decl_libssh2_channel_request_auth_agent" "#include " if test "x$ac_cv_have_decl_libssh2_channel_request_auth_agent" = xyes; then : have_ssh_agent=yes fi if test "x${have_ssh_agent}" = "xno" then as_fn_error $? " -------------------------------------------- Agent forwarding support was requested but no such support was found in libssh2. --------------------------------------------" "$LINENO" 5 else $as_echo "#define ENABLE_SSH_AGENT /**/" >>confdefs.h fi fi if test "x${have_ssh_agent}" = "xyes" \ -a "x${enable_ssh_agent}" = "xyes"; then ENABLE_SSH_AGENT_TRUE= ENABLE_SSH_AGENT_FALSE='#' else ENABLE_SSH_AGENT_TRUE='#' ENABLE_SSH_AGENT_FALSE= fi # # libtelnet # have_libtelnet=disabled TELNET_LIBS= # Check whether --with-telnet was given. if test "${with_telnet+set}" = set; then : withval=$with_telnet; else with_telnet=check fi if test "x$with_telnet" != "xno" then have_libtelnet=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking for telnet_init in -ltelnet" >&5 $as_echo_n "checking for telnet_init in -ltelnet... " >&6; } if ${ac_cv_lib_telnet_telnet_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ltelnet $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char telnet_init (); int main () { return telnet_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_telnet_telnet_init=yes else ac_cv_lib_telnet_telnet_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_telnet_telnet_init" >&5 $as_echo "$ac_cv_lib_telnet_telnet_init" >&6; } if test "x$ac_cv_lib_telnet_telnet_init" = xyes; then : TELNET_LIBS="$TELNET_LIBS -ltelnet" else have_libtelnet=no fi fi if test "x${have_libtelnet}" = "xyes" \ -a "x${have_terminal}" = "xyes"; then ENABLE_TELNET_TRUE= ENABLE_TELNET_FALSE='#' else ENABLE_TELNET_TRUE='#' ENABLE_TELNET_FALSE= fi # # libwebp # have_webp=disabled WEBP_LIBS= # Check whether --with-webp was given. if test "${with_webp+set}" = set; then : withval=$with_webp; else with_webp=check fi if test "x$with_webp" != "xno" then have_webp=yes ac_fn_c_check_header_mongrel "$LINENO" "webp/encode.h" "ac_cv_header_webp_encode_h" "$ac_includes_default" if test "x$ac_cv_header_webp_encode_h" = xyes; then : else have_webp=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for WebPEncode in -lwebp" >&5 $as_echo_n "checking for WebPEncode in -lwebp... " >&6; } if ${ac_cv_lib_webp_WebPEncode+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lwebp $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char WebPEncode (); int main () { return WebPEncode (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_webp_WebPEncode=yes else ac_cv_lib_webp_WebPEncode=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_webp_WebPEncode" >&5 $as_echo "$ac_cv_lib_webp_WebPEncode" >&6; } if test "x$ac_cv_lib_webp_WebPEncode" = xyes; then : WEBP_LIBS="$WEBP_LIBS -lwebp" else have_webp=no fi if test "x${have_webp}" = "xno" then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -------------------------------------------- Unable to find libwebp. Images will not be encoded using WebP. --------------------------------------------" >&5 $as_echo "$as_me: WARNING: -------------------------------------------- Unable to find libwebp. Images will not be encoded using WebP. --------------------------------------------" >&2;} else $as_echo "#define ENABLE_WEBP /**/" >>confdefs.h fi fi if test "x${have_webp}" = "xyes"; then ENABLE_WEBP_TRUE= ENABLE_WEBP_FALSE='#' else ENABLE_WEBP_TRUE='#' ENABLE_WEBP_FALSE= fi # # libwebsockets # have_libwebsockets=disabled WEBSOCKETS_LIBS= # Check whether --with-websockets was given. if test "${with_websockets+set}" = set; then : withval=$with_websockets; else with_websockets=check fi if test "x$with_websockets" != "xno" then have_libwebsockets=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lws_create_context in -lwebsockets" >&5 $as_echo_n "checking for lws_create_context in -lwebsockets... " >&6; } if ${ac_cv_lib_websockets_lws_create_context+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lwebsockets $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char lws_create_context (); int main () { return lws_create_context (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_websockets_lws_create_context=yes else ac_cv_lib_websockets_lws_create_context=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_websockets_lws_create_context" >&5 $as_echo "$ac_cv_lib_websockets_lws_create_context" >&6; } if test "x$ac_cv_lib_websockets_lws_create_context" = xyes; then : WEBSOCKETS_LIBS="$WEBSOCKETS_LIBS -lwebsockets" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -------------------------------------------- Unable to find libwebsockets. Support for Kubernetes will be disabled. --------------------------------------------" >&5 $as_echo "$as_me: WARNING: -------------------------------------------- Unable to find libwebsockets. Support for Kubernetes will be disabled. --------------------------------------------" >&2;} have_libwebsockets=no fi fi if test "x$with_websockets" != "xno" then # Check for client-specific closed event, which must be used in favor of # the generic closed event if libwebsockets is recent enough to provide # this ac_fn_c_check_decl "$LINENO" "LWS_CALLBACK_CLIENT_CLOSED" "ac_cv_have_decl_LWS_CALLBACK_CLIENT_CLOSED" "#include " if test "x$ac_cv_have_decl_LWS_CALLBACK_CLIENT_CLOSED" = xyes; then : $as_echo "#define HAVE_LWS_CALLBACK_CLIENT_CLOSED /**/" >>confdefs.h fi # Older versions of libwebsockets may not define a flag for requesting # global initialization of OpenSSL, instead performing that initialization # by default ac_fn_c_check_decl "$LINENO" "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT" "ac_cv_have_decl_LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT" "#include " if test "x$ac_cv_have_decl_LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT" = xyes; then : $as_echo "#define HAVE_LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT /**/" >>confdefs.h fi # Older versions of libwebsockets do not define special macros for SSL # connection flags, instead relying on documented integer values ac_fn_c_check_decl "$LINENO" "LCCSCF_USE_SSL" "ac_cv_have_decl_LCCSCF_USE_SSL" "#include " if test "x$ac_cv_have_decl_LCCSCF_USE_SSL" = xyes; then : $as_echo "#define HAVE_LCCSCF_USE_SSL /**/" >>confdefs.h fi # Older versions of libwebsockets do not define a dummy callback which # must be invoked after the main event callback is invoked; the main event # callback must instead manually return zero ac_fn_c_check_decl "$LINENO" "lws_callback_http_dummy" "ac_cv_have_decl_lws_callback_http_dummy" "#include " if test "x$ac_cv_have_decl_lws_callback_http_dummy" = xyes; then : $as_echo "#define HAVE_LWS_CALLBACK_HTTP_DUMMY /**/" >>confdefs.h fi fi if test "x${have_libwebsockets}" = "xyes"; then ENABLE_WEBSOCKETS_TRUE= ENABLE_WEBSOCKETS_FALSE='#' else ENABLE_WEBSOCKETS_TRUE='#' ENABLE_WEBSOCKETS_FALSE= fi # # Kubernetes # # Check whether --enable-kubernetes was given. if test "${enable_kubernetes+set}" = set; then : enableval=$enable_kubernetes; else enable_kubernetes=yes fi if test "x${enable_kubernetes}" = "xyes" \ -a "x${have_libwebsockets}" = "xyes" \ -a "x${have_ssl}" = "xyes" \ -a "x${have_terminal}" = "xyes"; then ENABLE_KUBERNETES_TRUE= ENABLE_KUBERNETES_FALSE='#' else ENABLE_KUBERNETES_TRUE='#' ENABLE_KUBERNETES_FALSE= fi # # guacd # # Check whether --enable-guacd was given. if test "${enable_guacd+set}" = set; then : enableval=$enable_guacd; else enable_guacd=yes fi if test "x${enable_guacd}" = "xyes"; then ENABLE_GUACD_TRUE= ENABLE_GUACD_FALSE='#' else ENABLE_GUACD_TRUE='#' ENABLE_GUACD_FALSE= fi # # guacenc # # Check whether --enable-guacenc was given. if test "${enable_guacenc+set}" = set; then : enableval=$enable_guacenc; else enable_guacenc=yes fi if test "x${enable_guacenc}" = "xyes" \ -a "x${have_libavcodec}" = "xyes" \ -a "x${have_libavutil}" = "xyes" \ -a "x${have_libswscale}" = "xyes" \ -a "x${have_libavformat}" = "xyes"; then ENABLE_GUACENC_TRUE= ENABLE_GUACENC_FALSE='#' else ENABLE_GUACENC_TRUE='#' ENABLE_GUACENC_FALSE= fi # # guaclog # # Check whether --enable-guaclog was given. if test "${enable_guaclog+set}" = set; then : enableval=$enable_guaclog; else enable_guaclog=yes fi if test "x${enable_guaclog}" = "xyes"; then ENABLE_GUACLOG_TRUE= ENABLE_GUACLOG_FALSE='#' else ENABLE_GUACLOG_TRUE='#' ENABLE_GUACLOG_FALSE= fi # # Output Makefiles # ac_config_files="$ac_config_files Makefile doc/Doxyfile src/common/Makefile src/common/tests/Makefile src/common-ssh/Makefile src/common-ssh/tests/Makefile src/terminal/Makefile src/libguac/Makefile src/libguac/tests/Makefile src/guacd/Makefile src/guacd/man/guacd.8 src/guacd/man/guacd.conf.5 src/guacenc/Makefile src/guacenc/man/guacenc.1 src/guaclog/Makefile src/guaclog/man/guaclog.1 src/pulse/Makefile src/protocols/kubernetes/Makefile src/protocols/rdp/Makefile src/protocols/rdp/tests/Makefile src/protocols/ssh/Makefile src/protocols/telnet/Makefile src/protocols/vnc/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_INIT_TRUE}" && test -z "${ENABLE_INIT_FALSE}"; then as_fn_error $? "conditional \"ENABLE_INIT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_SYSTEMD_TRUE}" && test -z "${ENABLE_SYSTEMD_FALSE}"; then as_fn_error $? "conditional \"ENABLE_SYSTEMD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_AVCODEC_TRUE}" && test -z "${ENABLE_AVCODEC_FALSE}"; then as_fn_error $? "conditional \"ENABLE_AVCODEC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_AVFORMAT_TRUE}" && test -z "${ENABLE_AVFORMAT_FALSE}"; then as_fn_error $? "conditional \"ENABLE_AVFORMAT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_AVUTIL_TRUE}" && test -z "${ENABLE_AVUTIL_FALSE}"; then as_fn_error $? "conditional \"ENABLE_AVUTIL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_SWSCALE_TRUE}" && test -z "${ENABLE_SWSCALE_FALSE}"; then as_fn_error $? "conditional \"ENABLE_SWSCALE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_SSL_TRUE}" && test -z "${ENABLE_SSL_FALSE}"; then as_fn_error $? "conditional \"ENABLE_SSL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_WINSOCK_TRUE}" && test -z "${ENABLE_WINSOCK_FALSE}"; then as_fn_error $? "conditional \"ENABLE_WINSOCK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_OGG_TRUE}" && test -z "${ENABLE_OGG_FALSE}"; then as_fn_error $? "conditional \"ENABLE_OGG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_PULSE_TRUE}" && test -z "${ENABLE_PULSE_FALSE}"; then as_fn_error $? "conditional \"ENABLE_PULSE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_TERMINAL_TRUE}" && test -z "${ENABLE_TERMINAL_FALSE}"; then as_fn_error $? "conditional \"ENABLE_TERMINAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_VNC_TRUE}" && test -z "${ENABLE_VNC_FALSE}"; then as_fn_error $? "conditional \"ENABLE_VNC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_RDP_TRUE}" && test -z "${ENABLE_RDP_FALSE}"; then as_fn_error $? "conditional \"ENABLE_RDP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_COMMON_SSH_TRUE}" && test -z "${ENABLE_COMMON_SSH_FALSE}"; then as_fn_error $? "conditional \"ENABLE_COMMON_SSH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_SSH_TRUE}" && test -z "${ENABLE_SSH_FALSE}"; then as_fn_error $? "conditional \"ENABLE_SSH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_SSH_AGENT_TRUE}" && test -z "${ENABLE_SSH_AGENT_FALSE}"; then as_fn_error $? "conditional \"ENABLE_SSH_AGENT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_TELNET_TRUE}" && test -z "${ENABLE_TELNET_FALSE}"; then as_fn_error $? "conditional \"ENABLE_TELNET\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_WEBP_TRUE}" && test -z "${ENABLE_WEBP_FALSE}"; then as_fn_error $? "conditional \"ENABLE_WEBP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_WEBSOCKETS_TRUE}" && test -z "${ENABLE_WEBSOCKETS_FALSE}"; then as_fn_error $? "conditional \"ENABLE_WEBSOCKETS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_KUBERNETES_TRUE}" && test -z "${ENABLE_KUBERNETES_FALSE}"; then as_fn_error $? "conditional \"ENABLE_KUBERNETES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_GUACD_TRUE}" && test -z "${ENABLE_GUACD_FALSE}"; then as_fn_error $? "conditional \"ENABLE_GUACD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_GUACENC_TRUE}" && test -z "${ENABLE_GUACENC_FALSE}"; then as_fn_error $? "conditional \"ENABLE_GUACENC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_GUACLOG_TRUE}" && test -z "${ENABLE_GUACLOG_FALSE}"; then as_fn_error $? "conditional \"ENABLE_GUACLOG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by guacamole-server $as_me 1.3.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ guacamole-server config.status 1.3.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ lt_cv_nm_interface \ nm_file_list_spec \ lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ configure_time_dlsearch_path \ configure_time_lt_sys_library_path; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "doc/Doxyfile") CONFIG_FILES="$CONFIG_FILES doc/Doxyfile" ;; "src/common/Makefile") CONFIG_FILES="$CONFIG_FILES src/common/Makefile" ;; "src/common/tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/common/tests/Makefile" ;; "src/common-ssh/Makefile") CONFIG_FILES="$CONFIG_FILES src/common-ssh/Makefile" ;; "src/common-ssh/tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/common-ssh/tests/Makefile" ;; "src/terminal/Makefile") CONFIG_FILES="$CONFIG_FILES src/terminal/Makefile" ;; "src/libguac/Makefile") CONFIG_FILES="$CONFIG_FILES src/libguac/Makefile" ;; "src/libguac/tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/libguac/tests/Makefile" ;; "src/guacd/Makefile") CONFIG_FILES="$CONFIG_FILES src/guacd/Makefile" ;; "src/guacd/man/guacd.8") CONFIG_FILES="$CONFIG_FILES src/guacd/man/guacd.8" ;; "src/guacd/man/guacd.conf.5") CONFIG_FILES="$CONFIG_FILES src/guacd/man/guacd.conf.5" ;; "src/guacenc/Makefile") CONFIG_FILES="$CONFIG_FILES src/guacenc/Makefile" ;; "src/guacenc/man/guacenc.1") CONFIG_FILES="$CONFIG_FILES src/guacenc/man/guacenc.1" ;; "src/guaclog/Makefile") CONFIG_FILES="$CONFIG_FILES src/guaclog/Makefile" ;; "src/guaclog/man/guaclog.1") CONFIG_FILES="$CONFIG_FILES src/guaclog/man/guaclog.1" ;; "src/pulse/Makefile") CONFIG_FILES="$CONFIG_FILES src/pulse/Makefile" ;; "src/protocols/kubernetes/Makefile") CONFIG_FILES="$CONFIG_FILES src/protocols/kubernetes/Makefile" ;; "src/protocols/rdp/Makefile") CONFIG_FILES="$CONFIG_FILES src/protocols/rdp/Makefile" ;; "src/protocols/rdp/tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/protocols/rdp/tests/Makefile" ;; "src/protocols/ssh/Makefile") CONFIG_FILES="$CONFIG_FILES src/protocols/ssh/Makefile" ;; "src/protocols/telnet/Makefile") CONFIG_FILES="$CONFIG_FILES src/protocols/telnet/Makefile" ;; "src/protocols/vnc/Makefile") CONFIG_FILES="$CONFIG_FILES src/protocols/vnc/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. case $CONFIG_FILES in #( *\'*) : eval set x "$CONFIG_FILES" ;; #( *) : set x $CONFIG_FILES ;; #( *) : ;; esac shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`$as_dirname -- "$am_mf" || $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$am_mf" : 'X\(//\)[^/]' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` am_filepart=`$as_basename -- "$am_mf" || $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$am_mf" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` { echo "$as_me:$LINENO: cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles" >&5 (cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } || am_rc=$? done if test $am_rc -ne 0; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "Something went wrong bootstrapping makefile fragments for automatic dependency tracking. Try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking). See \`config.log' for more details" "$LINENO" 5; } fi { am_dirpart=; unset am_dirpart;} { am_filepart=; unset am_filepart;} { am_mf=; unset am_mf;} { am_rc=; unset am_rc;} rm -f conftest-deps.mk } ;; "libtool":C) # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool 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 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool 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, see . # The names of the tagged configurations supported by this script. available_tags='' # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shared archive member basename,for filename based shared library versioning on AIX. shared_archive_member_spec=$shared_archive_member_spec # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm into a list of symbols to manually relocate. global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name lister interface. nm_interface=$lt_lt_cv_nm_interface # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot # Command to truncate a binary pipe. lt_truncate_bin=$lt_lt_cv_truncate_bin # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Detected run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path # Explicit LT_SYS_LIBRARY_PATH set during ./configure time. configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi # # Protocol build status # if test -z "$ENABLE_KUBERNETES_TRUE"; then : build_kubernetes=yes else build_kubernetes=no fi if test -z "$ENABLE_RDP_TRUE"; then : build_rdp=yes else build_rdp=no fi if test -z "$ENABLE_SSH_TRUE"; then : build_ssh=yes else build_ssh=no fi if test -z "$ENABLE_TELNET_TRUE"; then : build_telnet=yes else build_telnet=no fi if test -z "$ENABLE_VNC_TRUE"; then : build_vnc=yes else build_vnc=no fi # # Service / tool build status # if test -z "$ENABLE_GUACD_TRUE"; then : build_guacd=yes else build_guacd=no fi if test -z "$ENABLE_GUACENC_TRUE"; then : build_guacenc=yes else build_guacenc=no fi if test -z "$ENABLE_GUACLOG_TRUE"; then : build_guaclog=yes else build_guaclog=no fi # # Init scripts # if test -z "$ENABLE_INIT_TRUE"; then : build_init="${init_dir}" else build_init=no fi # # Systemd units # if test -z "$ENABLE_SYSTEMD_TRUE"; then : build_systemd="${systemd_dir}" else build_systemd=no fi # # FreeRDP plugins # if test -z "$ENABLE_RDP_TRUE"; then : build_rdp_plugins="${FREERDP2_PLUGIN_DIR}" else build_rdp_plugins=no fi # # Display summary # echo " ------------------------------------------------ $PACKAGE_NAME version $PACKAGE_VERSION ------------------------------------------------ Library status: freerdp2 ............ ${have_freerdp2} pango ............... ${have_pango} libavcodec .......... ${have_libavcodec} libavformat.......... ${have_libavformat} libavutil ........... ${have_libavutil} libssh2 ............. ${have_libssh2} libssl .............. ${have_ssl} libswscale .......... ${have_libswscale} libtelnet ........... ${have_libtelnet} libVNCServer ........ ${have_libvncserver} libvorbis ........... ${have_vorbis} libpulse ............ ${have_pulse} libwebsockets ....... ${have_libwebsockets} libwebp ............. ${have_webp} wsock32 ............. ${have_winsock} Protocol support: Kubernetes .... ${build_kubernetes} RDP ........... ${build_rdp} SSH ........... ${build_ssh} Telnet ........ ${build_telnet} VNC ........... ${build_vnc} Services / tools: guacd ...... ${build_guacd} guacenc .... ${build_guacenc} guaclog .... ${build_guaclog} FreeRDP plugins: ${build_rdp_plugins} Init scripts: ${build_init} Systemd units: ${build_systemd} Type \"make\" to compile $PACKAGE_NAME. " guacamole-server-1.3.0/Makefile.am0000644000175100001440000000506413770226763013750 00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim # into Makefile.in. Though the build system (GNU Autotools) automatically adds # its own license boilerplate to the generated Makefile.in, that boilerplate # does not apply to the transcluded portions of Makefile.am which are licensed # to you by the ASF under the Apache License, Version 2.0, as described above. # ACLOCAL_AMFLAGS = -I m4 # Subprojects DIST_SUBDIRS = \ src/libguac \ src/common \ src/common-ssh \ src/terminal \ src/guacd \ src/guacenc \ src/guaclog \ src/pulse \ src/protocols/kubernetes \ src/protocols/rdp \ src/protocols/ssh \ src/protocols/telnet \ src/protocols/vnc SUBDIRS = \ src/libguac \ src/common if ENABLE_COMMON_SSH SUBDIRS += src/common-ssh endif if ENABLE_TERMINAL SUBDIRS += src/terminal endif if ENABLE_PULSE SUBDIRS += src/pulse endif if ENABLE_KUBERNETES SUBDIRS += src/protocols/kubernetes endif if ENABLE_RDP SUBDIRS += src/protocols/rdp endif if ENABLE_SSH SUBDIRS += src/protocols/ssh endif if ENABLE_TELNET SUBDIRS += src/protocols/telnet endif if ENABLE_VNC SUBDIRS += src/protocols/vnc endif if ENABLE_GUACD SUBDIRS += src/guacd endif if ENABLE_GUACENC SUBDIRS += src/guacenc endif if ENABLE_GUACLOG SUBDIRS += src/guaclog endif EXTRA_DIST = \ .dockerignore \ CONTRIBUTING \ Dockerfile \ LICENSE \ NOTICE \ bin/guacctl \ doc/Doxyfile.in \ src/guacd-docker \ util/generate-test-runner.pl guacamole-server-1.3.0/LICENSE0000644000175100001440000002613613613156714012716 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.