pax_global_header00006660000000000000000000000064144174660670014531gustar00rootroot0000000000000052 comment=8c89a9225ea898b67c5a067d1a7f8e78f0a458aa xsel-1.2.1/000077500000000000000000000000001441746606700125055ustar00rootroot00000000000000xsel-1.2.1/AUTHORS000066400000000000000000000005511441746606700135560ustar00rootroot00000000000000Conrad Parker - General implementation, ICCCM wrangling Sergey Kogan - UTF-8 support Sergey Mironov - Zeroflush support, follow bugfix Taylan Ulrich B. - input/output non-tty logic fix Hans de Groede - fix overflow of supported_targets array xsel-1.2.1/COPYING000066400000000000000000000007621441746606700135450ustar00rootroot00000000000000Copyright (C) 2001 Conrad Parker Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. No representations are made about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. xsel-1.2.1/ChangeLog000066400000000000000000000014461441746606700142640ustar00rootroot00000000000000Sun Jan 13 00:11:01 JST 2008 Conrad Parker * Version 1.0.0 * Support for retrieving and serving UTF8_STRING atoms. When retrieving a selection, xsel determines whether or not the current selection owner supports UTF8_STRING and uses that if possible. + Debian bug #231413: Doesn't work correctly in a UTF-8 environment * Fixes for the following bugs: + Segfault when attempting to delete the selection that xsel owns, eg: echo "hello, world" | ./xsel -i && ./xsel -d + Debian bug #444638: xsel clears buffer instead of outputting when backgrounded. + Debian bug #203925: xsel manpage double option Thu Oct 25 13:52:36 EST 2001 Conrad Parker * Ported build to use automake+autoconf * Added README etc. xsel-1.2.1/INSTALL.md000066400000000000000000000165741441746606700141520ustar00rootroot00000000000000# Basic Installation #### These are generic installation instructions. The `configure` shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile` in each directory of the package. It may also create one or more `.h` files containing system-dependent definitions. Finally, it creates a shell script `config.status` that you can run in the future to recreate the current configuration, a file `config.cache` that saves the results of its tests to speed up reconfiguring, and a file `config.log` containing compiler output (useful mainly for debugging `configure`). If you need to do unusual things to compile the package, please try to figure out how `configure` could check whether to do them, and mail diffs or instructions to the address given in the `README` so they can be considered for the next release. If at some point `config.cache` contains results you don't want to keep, you may remove or edit it. The file `configure.in` is used to create `configure` by a program called `autoconf`. You only need `configure.in` if you want to change it or regenerate `configure` using a newer version of `autoconf`. #### The simplest way to compile this package is: 1. `cd` to the directory containing the package's source code and type `./configure` to configure the package for your system. If you're using `csh` on an old version of System V, you might need to type `sh ./configure` instead to prevent `csh` from trying to execute `configure` itself. Running `configure` takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make` to compile the package. 3. Optionally, type `make check` to run any self-tests that come with the package. 4. Type `make install` to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean`. To also remove the files that `configure` created (so you can compile the package for a different kind of computer), type `make distclean`. There is also a `make maintainer-clean` target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. #### Compilers and Options Some systems require unusual options for compilation or linking that the `configure` script does not know about. You can give `configure` initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: > CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env` program, you can do it like this: > env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure ### Compiling For Multiple Architectures You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make` that supports the `VPATH` variable, such as GNU `make`. `cd` to the directory where you want the object files and executables to go and run the `configure` script. `configure` automatically checks for the source code in the directory that `configure' is in and in `..`. If you have to use a `make` that does not supports the `VPATH` variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean` before reconfiguring for another architecture. ### Installation Names By default, `make install` will install the package's files in `/usr/local/bin`, `/usr/local/man`, etc. You can specify an installation prefix other than `/usr/local` by giving `configure` the option `--prefix=PATH`. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure` the option `--exec-prefix=PATH`, the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH` to specify different values for particular kinds of files. Run `configure --help` for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure` the option `--program-prefix=PREFIX` or `--program-suffix=SUFFIX`. ### Optional Features Some packages pay attention to `--enable-FEATURE` options to `configure`, where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE` options, where PACKAGE is something like `gnu-as` or `x` (for the X Window System). The `README` should mention any `--enable-` and `--with-` options that the package recognizes. For packages that use the X Window System, `configure` can usually find the X include and library files automatically, but if it doesn't, you can use the `configure` options `--x-includes=DIR` and `--x-libraries=DIR` to specify their locations. ### Specifying the System Type There may be some features `configure` can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure` can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE` option. TYPE can either be a short name for the system type, such as `sun4`, or a canonical name with three fields: > CPU-COMPANY-SYSTEM See the file `config.sub` for the possible values of each field. If `config.sub` isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE` option to select the type of system they will produce code for and the `--build=TYPE` option to select the type of system on which you are compiling the package. ### Sharing Defaults If you want to set default values for `configure` scripts to share, you can create a site shell script called `config.site` that gives default values for variables like `CC`, `cache_file`, and `prefix`. `configure` looks for `PREFIX/share/config.site` if it exists, then `PREFIX/etc/config.site` if it exists. Or, you can set the `CONFIG_SITE` environment variable to the location of the site script. > *Warning*: not all `configure` scripts look for a site script. ### Operation Controls `configure` recognizes the following options to control how it operates. ##### `--cache-file=FILE` > Use and save the results of the tests in FILE instead of `./config.cache`. Set FILE to `/dev/null` to disable caching, for debugging `configure`. ##### `--help' > Print a summary of the options to `configure`, and exit. ##### `--quiet' ##### `--silent' ##### `-q' > Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null` (any error messages will still be shown). ##### `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure` can determine that directory automatically. ##### `--version' > Print the version of Autoconf used to generate the `configure` script, and exit. `configure` also accepts some other, not widely useful, options. xsel-1.2.1/Makefile.am000066400000000000000000000002631441746606700145420ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in AM_CPPFLAGS = $(X_CFLAGS) LDADD = $(X_LIBS) bin_PROGRAMS = xsel xsel_SOURCES = xsel.c xsel.h dist_man_MANS = xsel.1x xsel-1.2.1/NEWS000066400000000000000000000000001441746606700131720ustar00rootroot00000000000000xsel-1.2.1/README000066400000000000000000000106741441746606700133750ustar00rootroot00000000000000XSel -- manipulate the X selection. Copyright (C) 2001 Conrad Parker For updates see http://www.vergenet.net/~conrad/software/xsel/ INTRODUCTION ============ XSel is a command-line program for getting and setting the contents of the X selection. Normally this is only accessible by manually highlighting information and pasting it with the middle mouse button. To read a file into the X selection: ------------------------------------ xsel < file after which you can paste the file's contents into any X application with the middle mouse button, as though you had highlighted its text. XSel will read in the file contents exactly, whereas manual highlighting invariably breaks lines and transforms tabs into spaces. This is especially handy for copying in large files. To write the X selection to a file: ----------------------------------- xsel > file after which file will contain exactly the contents of the X selection, without trailing newlines and spaces and crap. XSel is more than just cat for the X selection. Append to the X selection: -------------------------- xsel --append < file To follow a growing file: ------------------------- xsel --follow < file to make the X selection follow standard input as it grows (like tail -f). ADVANCED FEATURES ================= XSel also lets you access some of the more esoteric features of the X selection: Delete the contents of the selection ------------------------------------ xsel --delete Will cause the program in which text is selected to delete that text. This really works, you can try it on xedit to remotely delete text in the editor window. Manipulate the secondary selection ---------------------------------- The X Window System maintains two selections, the usual primary selection and a secondary, which isn't used much ... XSel lets you use the secondary selection, for example: To get and set the secondary selection: --------------------------------------- xsel --secondary < file xsel --secondary > file To swap the primary and secondary selections: --------------------------------------------- xsel --exchange So for example you can store useful text in the secondary selection and retrieve it later. Manipulate the clipboard selection ---------------------------------- Similarly, X has a clipboard selection. You can use the standard xclipboard program to manage a history of selected text, and you can use xsel to actually get text into that clipboard: xsel --clipboard < file Make the selection contents persist in memory --------------------------------------------- Normally the X selection only exists as long as the program it was selected in is running. Further, some buggy applications tend to forget their selection text after a little while. If you run: xsel --keep after selecting some important text, xsel will copy the text into its own memory so you can paste it elsewhere even if the original program exits or crashes. Further information =================== Naturally all these options have single character equivalents, and xsel --help provides usage information. For complete details, see the xsel(1x) man page. DOWNLOAD ======== New versions of XSel are distributed in source form from: http://www.vergenet.net/~conrad/software/xsel/ STANDARDS ========= X11 ICCCM2 ---------- XSel conforms to the X Window System Inter-Client Communication Conventions Manual Version 2.0 (ICCCM2), including correct handling of TARGETS, MULTIPLE, TIMESTAMP, and DELETE targets, INCR properties and large data transfers. My thoughts on ICCCM are available at: https://web.archive.org/web/20110720132303/https://lists.slug.org.au/archives/slug-chat/2001/July/msg00054.html (Warning: explicit language). LICENSE ======= Copyright (C) 2001 Conrad Parker Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. No representations are made about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. CONTACT ======= Please direct any queries, bug reports etc. about XSel to the author, Conrad Parker conrad@vergenet.net . xsel-1.2.1/aclocal.m4000066400000000000000000001236701441746606700143560ustar00rootroot00000000000000# generated automatically by aclocal 1.14.1 -*- Autoconf -*- # Copyright (C) 1996-2013 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'.])]) # Copyright (C) 2002-2013 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.14' 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.14.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.14.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-2013 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], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2013 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-2013 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-2013 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. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _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. FIXME. This creates each '.P' file that we will # 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" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2013 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. 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 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-2013 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}" != 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-2013 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-2013 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 to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 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 ]) # -*- Autoconf -*- # Obsolete and "removed" macros, that must however still report explicit # error messages when used, to smooth transition. # # Copyright (C) 1996-2013 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. AC_DEFUN([AM_CONFIG_HEADER], [AC_DIAGNOSE([obsolete], ['$0': this macro is obsolete. You should use the 'AC][_CONFIG_HEADERS' macro instead.])dnl AC_CONFIG_HEADERS($@)]) AC_DEFUN([AM_PROG_CC_STDC], [AC_PROG_CC am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc AC_DIAGNOSE([obsolete], ['$0': this macro is obsolete. You should simply use the 'AC][_PROG_CC' macro instead. Also, your code should no longer depend upon 'am_cv_prog_cc_stdc', but upon 'ac_cv_prog_cc_stdc'.])]) AC_DEFUN([AM_C_PROTOTYPES], [AC_FATAL([automatic de-ANSI-fication support has been removed])]) AU_DEFUN([fp_C_PROTOTYPES], [AM_C_PROTOTYPES]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2013 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-2013 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-2013 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-2013 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-2013 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-2013 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-2013 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-2013 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 xsel-1.2.1/autogen.sh000077500000000000000000000072251441746606700145140ustar00rootroot00000000000000#!/bin/sh # Run this to set up the build system: configure, makefiles, etc. # (based on the version in enlightenment's cvs) package="xsel" olddir=`pwd` srcdir=`dirname $0` test -z "$srcdir" && srcdir=. cd "$srcdir" DIE=0 echo "checking for autoconf... " (autoconf --version) < /dev/null > /dev/null 2>&1 || { echo echo "You must have autoconf installed to compile $package." echo "Download the appropriate package for your distribution," echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" DIE=1 } VERSIONGREP="sed -e s/.*[^0-9\.]\([0-9]\.[0-9]\).*/\1/" VERSIONMKINT="sed -e s/[^0-9]//" # do we need automake? if test -r Makefile.am; then AM_OPTIONS=`fgrep AUTOMAKE_OPTIONS Makefile.am` AM_NEEDED=`echo $AM_OPTIONS | $VERSIONGREP` if test x"$AM_NEEDED" = "x$AM_OPTIONS"; then AM_NEEDED="" fi if test -z $AM_NEEDED; then echo -n "checking for automake... " AUTOMAKE=automake ACLOCAL=aclocal if ($AUTOMAKE --version < /dev/null > /dev/null 2>&1); then echo "yes" else echo "no" AUTOMAKE= fi else echo -n "checking for automake $AM_NEEDED or later... " for am in automake-$AM_NEEDED automake$AM_NEEDED \ automake automake-1.7 automake-1.8 automake-1.9; do ($am --version < /dev/null > /dev/null 2>&1) || continue ver=`$am --version < /dev/null | head -n 1 | $VERSIONGREP | $VERSIONMKINT` verneeded=`echo $AM_NEEDED | $VERSIONMKINT` if test $ver -ge $verneeded; then AUTOMAKE=$am echo $AUTOMAKE break fi done test -z $AUTOMAKE && echo "no" echo -n "checking for aclocal $AM_NEEDED or later... " for ac in aclocal-$AM_NEEDED aclocal$AM_NEEDED \ aclocal aclocal-1.7 aclocal-1.8 aclocal-1.9; do ($ac --version < /dev/null > /dev/null 2>&1) || continue ver=`$ac --version < /dev/null | head -n 1 | $VERSIONGREP | $VERSIONMKINT` verneeded=`echo $AM_NEEDED | $VERSIONMKINT` if test $ver -ge $verneeded; then ACLOCAL=$ac echo $ACLOCAL break fi done test -z $ACLOCAL && echo "no" fi test -z $AUTOMAKE || test -z $ACLOCAL && { echo echo "You must have automake installed to compile $package." echo "Download the appropriate package for your distribution," echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" exit 1 } fi echo -n "checking for libtool... " for LIBTOOLIZE in libtoolize glibtoolize nope; do ($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 && break done if test x$LIBTOOLIZE = xnope; then echo "nope." LIBTOOLIZE=libtoolize else echo $LIBTOOLIZE fi ($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || { echo echo "You must have libtool installed to compile $package." echo "Download the appropriate package for your system," echo "or get the source from one of the GNU ftp sites" echo "listed in http://www.gnu.org/order/ftp.html" DIE=1 } if test "$DIE" -eq 1; then exit 1 fi if test -z "$*"; then echo "I am going to run ./configure with no arguments - if you wish " echo "to pass any to it, please specify them on the $0 command line." fi echo "Generating configuration files for $package, please wait...." echo " $ACLOCAL $ACLOCAL_FLAGS" $ACLOCAL $ACLOCAL_FLAGS || exit 1 echo " $LIBTOOLIZE --automake" $LIBTOOLIZE --automake || exit 1 echo " autoheader" autoheader || exit 1 echo " $AUTOMAKE --add-missing $AUTOMAKE_FLAGS" $AUTOMAKE --add-missing $AUTOMAKE_FLAGS || exit 1 echo " autoconf" autoconf || exit 1 cd $olddir $srcdir/configure --enable-maintainer-mode "$@" && echo xsel-1.2.1/config.h.in000066400000000000000000000065161441746606700145400ustar00rootroot00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the `dup2' function. */ #undef HAVE_DUP2 /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #undef HAVE_MALLOC /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* 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 `strerror' function. */ #undef HAVE_STRERROR /* 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 /* Define to 1 if you have the `strtol' function. */ #undef HAVE_STRTOL /* Define to 1 if `st_blksize' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_BLKSIZE /* 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_UNISTD_H /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK /* Define to 1 if you have the header file. */ #undef HAVE_VFORK_H /* Define to 1 if `fork' works. */ #undef HAVE_WORKING_FORK /* Define to 1 if `vfork' works. */ #undef HAVE_WORKING_VFORK /* 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 as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Version number of package */ #undef VERSION /* Define to 1 if the X Window System is missing or not being used. */ #undef X_DISPLAY_MISSING /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `int' if doesn't define. */ #undef gid_t /* Define to rpl_malloc if the replacement function should be used. */ #undef malloc /* Define to `int' if does not define. */ #undef pid_t /* Define to `unsigned int' if does not define. */ #undef size_t /* Define to `int' if doesn't define. */ #undef uid_t /* Define as `fork' if `vfork' does not work. */ #undef vfork xsel-1.2.1/configure.ac000066400000000000000000000017721441746606700150020ustar00rootroot00000000000000# Process this file with autoconf to produce a configure script. AC_INIT([xsel],[1.2.1]) AM_INIT_AUTOMAKE([1.14 foreign dist-xz subdir-objects]) AC_CONFIG_SRCDIR([xsel.c]) AC_CONFIG_HEADERS([config.h]) # Checks for programs. AC_PROG_CC AC_PROG_CPP AC_PROG_INSTALL AC_PROG_MAKE_SET # Checks for libraries. PKG_CHECK_MODULES([X], [x11]) # Error out on compile warnings dnl Add some useful warnings if we have gcc. dnl changequote(,)dnl AS_IF([test "x$ac_cv_c_compiler_gnu" = xyes], [ CFLAGS="$CFLAGS -fno-strict-aliasing -Wall -Wdeclaration-after-statement -Wno-unused" ]) dnl changequote([,])dnl # Checks for header files. AC_CHECK_HEADERS([errno.h fcntl.h stdlib.h string.h sys/time.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_PID_T AC_TYPE_SIZE_T AC_CHECK_MEMBERS([struct stat.st_blksize]) AC_TYPE_UID_T # Checks for library functions. AC_FUNC_FORK AC_FUNC_MALLOC AC_CHECK_FUNCS([dup2 select strdup strerror strtol]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT xsel-1.2.1/install-sh000077500000000000000000000224411441746606700145140ustar00rootroot00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2004-04-01.17 # 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. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename= transform_arg= instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd= chgrpcmd= stripcmd= rmcmd="$rmprog -f" mvcmd="$mvprog" src= dst= dir_arg= usage="Usage: $0 [OPTION]... SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 -d DIRECTORIES... In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default. In the second, create the directory path DIR. Options: -b=TRANSFORMBASENAME -c copy source (using $cpprog) instead of moving (using $mvprog). -d create directories instead of installing files. -g GROUP $chgrp installed files to GROUP. -m MODE $chmod installed files to MODE. -o USER $chown installed files to USER. -s strip installed files (using $stripprog). -t=TRANSFORM --help display this help and exit. --version display version info and exit. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test -n "$1"; do case $1 in -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; -c) instcmd=$cpprog shift continue;; -d) dir_arg=true shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; --help) echo "$usage"; exit 0;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -s) stripcmd=$stripprog shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; --version) echo "$0 $scriptversion"; exit 0;; *) # When -d is used, all remaining arguments are directories to create. test -n "$dir_arg" && break # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dstarg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dstarg" shift # fnord fi shift # arg dstarg=$arg done break;; esac done if test -z "$1"; 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 for src do # Protect names starting with `-'. case $src in -*) src=./$src ;; esac if test -n "$dir_arg"; then dst=$src src= if test -d "$dst"; then instcmd=: chmodcmd= else instcmd=$mkdirprog fi else # Waiting for this to be detected by the "$instcmd $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 "$dstarg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dstarg # Protect names starting with `-'. case $dst in -*) dst=./$dst ;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then dst=$dst/`basename "$src"` fi fi # This sed command emulates the dirname command. dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # Skip lots of stat calls in the usual case. if test ! -d "$dstdir"; then defaultIFS=' ' IFS="${IFS-$defaultIFS}" oIFS=$IFS # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` IFS=$oIFS pathcomp= while test $# -ne 0 ; do pathcomp=$pathcomp$1 shift if test ! -d "$pathcomp"; then $mkdirprog "$pathcomp" || lasterr=$? # mkdir can fail with a `File exist' error in case several # install-sh are creating the directory concurrently. This # is OK. test ! -d "$pathcomp" && { (exit ${lasterr-1}); exit; } fi pathcomp=$pathcomp/ done fi if test -n "$dir_arg"; then $doit $instcmd "$dst" \ && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } else # If we're going to rename the final executable, determine the name now. if test -z "$transformarg"; then dstfile=`basename "$dst"` else dstfile=`basename "$dst" $transformbasename \ | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename. test -z "$dstfile" && dstfile=`basename "$dst"` # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 trap '(exit $?); exit' 1 2 13 15 # Move or copy the file name to the temp name $doit $instcmd "$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 $instcmd $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 "$dsttmp"; } && # Now rename the file to the real destination. { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 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. { if test -f "$dstdir/$dstfile"; then $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ || { echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 (exit 1); exit } else : fi } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" } } fi || { (exit 1); exit; } done # The final little trick to "correctly" pass the exit status to the exit trap. { (exit 0); exit } # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: xsel-1.2.1/missing000077500000000000000000000246661441746606700141220ustar00rootroot00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2003-09-02.23 # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 # Free Software Foundation, Inc. # Originally 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # 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 run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Send bug reports to ." ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; aclocal*) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then # We have makeinfo, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` fi touch $file ;; tar) shift if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 fi # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: xsel-1.2.1/mkinstalldirs000077500000000000000000000013221441746606700153110ustar00rootroot00000000000000#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here xsel-1.2.1/rant.txt000066400000000000000000000137031441746606700142160ustar00rootroot00000000000000To: Sean Neakums Subject: [chat] Re: [SLUG] Ximian / Gnome and Xalf From: Conrad Parker Date: Thu Jul 12 21:14:01 2001 Cc: slug-chat@xxxxxxxxxxx User-agent: Mutt/1.2.5i On Thu, Jul 12, 2001 at 09:32:45AM +0100, Sean Neakums wrote: > >>>>> "JW" == Jeff Waugh writes: > > JW> (The cynical prat in me says: Did you honestly expect a global > JW> option, and software to interact and cooperate correctly on > JW> this platform?) > > Go read the ICCCM. Come back when you're done crying. d00d, that document is devilspawn. I've recently spent my nights in pain implementing the selection mechanism. WHY OH WHY OH WHY? why me? why did I choose to do this? and what sick evil twisted mind wrote this damn spec? I don't know why I'm working with it, I just wanted to make a useful program. I didn't know what I was getting myself in to. Nobody knows until they try it. And once you start, you're unable to stop. You can't stop, if you stop then you haven't completed it to spec. You can't fail on this, it's just a few pages of text, how can that be so hard? So what if they use Atoms for everything. So what if there's no explicit correlation between the target type of a SelectionNotify event and the type of the property it indicates? So what if the distinction is ambiguous? So what if the document is littered with such atrocities? It's not the spec's fault, the spec is authoritative. It's obviously YOUR (the implementor's) fault for misunderstanding it. If you didn't misunderstand it, you wouldn't be here complaining about it would you? It's all about understanding. Obviously, once you come to understand how the Atoms all fit together and exactly what the sequence of events for an incremental transfer is, and once you come to APPRECIATE how Atoms are so guilelessly delicately cast and communicated, its BEAUTIFUL it really is, I'm like SO GLAD I spent my last few evenings bashing my head against this damn document because now I can SEE CLEARLY and it all fits into place and you know what, it damn well better because you just know that if one Atom is out of place or you mistake the requestor's property's window with your property's requestor's window or you forget to delete an empty property at the right time, then, well, you're screwed and the whole thing is going to come tumbling down and then who's going to look like a fool, huh? The malicious bastards who designed ICCCM? NO! YOU you idiot fool coder for misunderstanding such a seemingly benign (maligned) document. It all makes perfect sense and who ever heard of synchronous error handling anyway? Name one fucking program in the whole world that uses MULTIPLE selections by choice? "ooh, for performance" well kiss my ass, if no other program is going to fucking care about my packet then why the fuck would I send such a thing? Optimize ZERO you fucking overengineered piece of shit. And XA_SECONDARY? Who the fuck uses the SECONDARY selection? and who actually queries TARGETS? All anyone ever fucking does with the selection is COPY TEXT!! That's what its fucking used for, that's what its good for so why is it such a fucking pain in the date to just share a fucking STRING? How about HOSTNAME? ooh I want to find a random HOSTNAME. I'll just ask whichever random process happens to be the selection owner right now to tell me it's fucking HOSTNAME! Yes, that sounds like a worthwhile bit of behaviour, let's just stick it in Xmu and hope noone notices for the next fucking 30 years. Same goes for the fricking IP_ADDRESS. Oh yeah, and the user's name. getenv("USER")? Nooooooooo! primitive idiot. Let's just query a random selection owner and hope it feels like telling us. Yes, yes, remind me to put THAT into production code; about as reliable as cleaning your motherboard with fried eel and it smells bad too. Can I have mine in Motif please? The ICCCM is the coding equivalent of the Medieval rack, except its advertised as some kind of X11 swingers party. "Wanna see hot sexy X applications getting it on with each other live? Wanna join in the action? Come and lie down here, we're all waiting for you!" ZZZZZZZZZZZzzzzzzzzip! Then they close the handcuffs and you realise you're lying in a cold dark room and all you can see are Atoms blocking you in and every time you think you understand CCRRreeeeeeeaAACK! they turn the rack a notch and you turn the page to find another 20 paragraphs of hellborne protocol fantasy. I've seen more elegant protocols in unlikely places. When blowflies fight over a pile of elephant shit, their pecking order is a more elegant protocol than ICCCM. You should watch it some time; if you're an X hacker, you'll see the beauty. You'll wanna dig right in there and get your hands dirty. Italian cabbies. English football hooligans -- if I want to get a short message to the other side of the field, do I use my ICCCM-based X Window PDA? no, I tell it to a random hooligan, poke him in the ribs and hope he gets riled up enough to start a riot. Will my message get to the other side? who knows? at least the resulting carnage will be more orderly than that fucking Interclient protocol. ALL OR NOTHING! ALL OR NOTHING! Either you understand it ALL, or you are NOTHING! OR BOTH! I. C. C. C. M. Inter- Client Communications Conventions Manual! Manual, like in "manual labour", like in "pain" Conventions, like in "not required, just do ALL OF IT or you SUCK!" Communications, like in "fucking overengineered carrier pigeons" Client, like in "see that guy with the limp, he was one of my ``clients''" Inter-, like in "Inter-nal bleeding" A million monkeys hacking at a million protocol hammers couldn't come up with this shit in a million years, that's because it's EVIL, E-V-I-L, it's irrational, it's discontinuous, it is a truth within our codebase that cannot be derived from the axioms, it's OUT THERE, it was given to us to degrade us and as a warning to our children. We may have been stupid enough to work with the ICCCM but what of humanity? the humanity! oh! K. xsel-1.2.1/release_notes/000077500000000000000000000000001441746606700153355ustar00rootroot00000000000000xsel-1.2.1/release_notes/xsel-1.0.0.txt000066400000000000000000000037361441746606700175140ustar00rootroot00000000000000xsel 1.0.0 Release ------------------ XSel is a command-line program for getting and setting the contents of the X selection. Normally this is only accessible by manually highlighting information and pasting it with the middle mouse button. This release is available as a source tarball at: http://www.vergenet.net/~conrad/software/xsel/download/xsel-1.0.0.tar.gz New in this release ------------------- This release adds UTF-8 support and fixes various bugs. Details: * Support for retrieving and serving UTF8_STRING atoms. When retrieving a selection, xsel determines whether or not the current selection owner supports UTF8_STRING and uses that if possible. + Debian bug #231413: Doesn't work correctly in a UTF-8 environment * Fixes for the following bugs: + Segfault when attempting to delete the selection that xsel owns, eg: echo "hello, world" | ./xsel -i && ./xsel -d + Debian bug #444638: xsel clears buffer instead of outputting when backgrounded. + Debian bug #203925: xsel manpage double option About XSel ---------- XSel's most common use is to set or get the X selection: * To read a file into the X selection: xsel < file * To write the X selection to a file: xsel > file You can use xsel in shell scripts and desktop keybindings, so that the contents of the X selection are available to command arguments: mozilla --remote "openurl(`xsel`)" XSel can also be used for some more complicated tasks: * To append to the X selection: xsel --append < file * To follow a growing file: xsel --follow < file You can even tell applications to delete their selected text: * To delete the contents of the selection: xsel --delete Other options include various ways of manipulating the secondary and clipboard selections, and of making the selection contents persist in memory. For full details see: http://www.vergenet.net/~conrad/software/xsel/ enjoy :-) Conrad Parker. xsel-1.2.1/release_notes/xsel-1.1.0.txt000066400000000000000000000040171441746606700175060ustar00rootroot00000000000000xsel 1.1.0 Release ------------------ XSel is a command-line program for getting and setting the contents of the X selection. Normally this is only accessible by manually highlighting information and pasting it with the middle mouse button. This release is available as a source tarball at: http://www.vergenet.net/~conrad/software/xsel/download/xsel-1.1.0.tar.gz New in this release ------------------- This release adds basic support for COMPOUND_TEXT and fixes a configuration bug. Details: * Support for retrieving COMPOUND_TEXT atoms. The COMPOUND_TEXT atom in ICCCM is an earlier method of handling international text; most modern applications use UTF8_STRING instead. The level of support included here allows xsel to retrieve a COMPOUND_TEXT selection verbatim, without performing charset conversion. When maintaining the selection, xsel does not currently attempt to serve COMPOUND_TEXT, but handles UTF8 requests where possible. Thanks to Richard Zidlicky for reporting this bug and testing the fix. * Fixed missing configuration checks for X11 libraries. Reported by Samuel Saint-Pettersen. About XSel ---------- XSel's most common use is to set or get the X selection: * To read a file into the X selection: xsel < file * To write the X selection to a file: xsel > file You can use xsel in shell scripts and desktop keybindings, so that the contents of the X selection are available to command arguments: mozilla --remote "openurl(`xsel`)" XSel can also be used for some more complicated tasks: * To append to the X selection: xsel --append < file * To follow a growing file: xsel --follow < file You can even tell applications to delete their selected text: * To delete the contents of the selection: xsel --delete Other options include various ways of manipulating the secondary and clipboard selections, and of making the selection contents persist in memory. For full details see: http://www.vergenet.net/~conrad/software/xsel/ enjoy :-) Conrad Parker. xsel-1.2.1/release_notes/xsel-1.2.0.txt000066400000000000000000000034171441746606700175120ustar00rootroot00000000000000xsel 1.2.0 Release ------------------ XSel is a command-line program for getting and setting the contents of the X selection. Normally this is only accessible by manually highlighting information and pasting it with the middle mouse button. This release is available as a source tarball at: http://www.vergenet.net/~conrad/software/xsel/download/xsel-1.2.0.tar.gz New in this release ------------------- This is a maintenance release, improving argument handling, documentation and X11 library detection. Details: * Added handling of combined single-letter arguments, so "xsel -ao" is equivalent to "xsel -a -o". Patch by Christopher Wellons. * Corrected man page section numbers, updated URLs in source comments, added ICCCM rant to source repository. * Removed hardcoded X11 libraries in Makefile.am, and use only those discovered by autoconf. Reported by Yair K. About XSel ---------- XSel's most common use is to set or get the X selection: * To read a file into the X selection: xsel < file * To write the X selection to a file: xsel > file You can use xsel in shell scripts and desktop keybindings, so that the contents of the X selection are available to command arguments: mozilla --remote "openurl(`xsel`)" XSel can also be used for some more complicated tasks: * To append to the X selection: xsel --append < file * To follow a growing file: xsel --follow < file You can even tell applications to delete their selected text: * To delete the contents of the selection: xsel --delete Other options include various ways of manipulating the secondary and clipboard selections, and of making the selection contents persist in memory. For full details see: http://www.vergenet.net/~conrad/software/xsel/ enjoy :-) Conrad Parker. xsel-1.2.1/stamp-h.in000066400000000000000000000000121441746606700143770ustar00rootroot00000000000000timestamp xsel-1.2.1/xsel.1x000066400000000000000000000107211441746606700137330ustar00rootroot00000000000000.TH XSEL 1x "January 2008" .SH NAME xsel \- manipulate the X selection. .SH SYNOPSIS .B xsel [\fIOPTION\fR]... .SH DESCRIPTION .PP Retrieve and set the X selection. .PP The X server maintains three selections, called \fIPRIMARY\fR, \fISECONDARY\fR and \fICLIPBOARD\fR. The PRIMARY selection is conventionally used to implement copying and pasting via the middle mouse button. The SECONDARY and CLIPBOARD selections are less frequently used by application programs. This program operates on the PRIMARY selection unless otherwise specified. .PP By default, this program outputs the selection without modification if both standard input and standard output are terminals (ttys). Otherwise, the current selection is output if standard output is not a terminal (tty), and the selection is set from standard input if standard input is not a terminal (tty). If any input or output options are given then the program behaves only in the requested mode. .PP If both input and output is required then the previous selection is output before being replaced by the contents of standard input. .PP \fBInput options\fR .TP \fB\-a\fR, \fB\-\-append\fR append standard input to the selection. Implies \fB\-i\fR. .TP \fB\-f\fR, \fB\-\-follow\fR append to selection as standard input grows. Implies \fB\-i\fR. .TP \fB\-i\fR, \fB\-\-input\fR read standard input into the selection. .PP \fBOutput options\fR .TP \fB\-o\fR, \fB\-\-output\fR write the selection to standard output. .PP \fBAction options\fR .TP \fB\-c\fR, \fB\-\-clear\fR clear the selection. Overrides all \fIinput\fR options. .TP \fB\-d\fR, \fB\-\-delete\fR Request that the current selection be deleted. This not only clears the selection, but also requests to the program in which the selection resides that the selected contents be deleted. Overrides all \fIinput\fR options. .PP \fBSelection options\fR .TP \fB\-p\fR, \fB\-\-primary\fR operate on the PRIMARY selection (default). .TP \fB\-s\fR, \fB\-\-secondary\fR operate on the SECONDARY selection. .TP \fB\-b\fR, \fB\-\-clipboard\fR operate on the CLIPBOARD selection. .TP \fB\-k\fR, \fB\-\-keep\fR Do not modify the selections, but make the PRIMARY and SECONDARY selections persist even after the programs they were selected in exit. (Conventionally, the CLIPBOARD selection is persisted by a separate special purpose program such as \fIxclipboard(1)\fR). Ignores all \fIinput\fR and \fIoutput\fR options. .TP \fB\-x\fR, \fB\-\-exchange\fR exchange the PRIMARY and SECONDARY selections. Ignores all \fIinput\fR and \fIoutput\fR options. .PP \fBX options\fR .TP \fB\-\-display\fR \fIdisplayname\fR specify the server to use; see \fIX(1)\fP. .TP \fB\-\-windowName\fR \fIwindowName\fR specify the X WM_NAME window property; default is "xsel". .TP \fB\-t\fR \fIms\fR, \fB\-\-selectionTimeout\fR \fIms\fR Specify the timeout in milliseconds within which the selection must be retrieved. In \fB\-\-input\fR mode, the background process exits after this amount of time. A value of \fB0\fR (zero) specifies no timeout (default). .PP \fBMiscellaneous options\fR .TP \fB\-l\fR \fIfilename\fR, \fB\-\-logfile\fR \fIfilename\fR Specify the file to log errors to when detached. (Default \fI$HOME/.xsel.log\fR) .TP \fB\-n\fR, \fB\-\-nodetach\fR Do not detach from the controlling terminal. Without this option, xsel will fork to become a background process in \fIinput\fR, \fIexchange\fR and \fIkeep\fR modes. .TP \fB\-h\fR, \fB\-\-help\fR display usage information and exit .TP \fB\-v\fR, \fB\-\-verbose\fR Print informative messages. Additional instances of \fI\-v\fR raise the debugging level, ie. print more information. .TP \fB\-\-version\fR output version information and exit .PP .SH NOTES .PP \fIThere is no X selection buffer.\fR The selection mechanism in X11 is an interclient communication mediated by the X server each time any program wishes to know the selection contents, eg. to perform a middle mouse button paste. In order to implement modification of the selection(s) (in \fIinput\fR, \fIkeep\fR and \fIexchange\fR modes) this program detaches from the terminal, spawning a child process to supply the new selection(s) on demand. This child exits immediately when any other program takes over the selection(s), eg. when the user next selects some text in a terminal window or by running \fBxsel \-c\fR. .PP .SH STANDARDS xsel conforms to the Inter\-Client Communication Conventions Manual Version 2.0 (ICCCM2). .PP .SH "SEE ALSO" X(7), Xserver(1), xset(1), xclipboard(1), xpaste(1) .PP .SH AUTHOR Conrad Parker , July 2001 xsel-1.2.1/xsel.c000066400000000000000000002016771441746606700136410ustar00rootroot00000000000000/* * xsel -- manipulate the X selection * Copyright (C) 2001 Conrad Parker * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. No representations are made about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "xsel.h" /* The name we were invoked as (argv[0]) */ static char * progname; /* Verbosity level for debugging */ static int debug_level = DEBUG_LEVEL; /* Our X Display and Window */ static Display * display; static Window window; /* Maxmimum request size supported by this X server */ static long max_req; /* Our timestamp for all operations */ static Time timestamp; static Atom timestamp_atom; /* The TIMESTAMP atom */ static Atom multiple_atom; /* The MULTIPLE atom */ static Atom targets_atom; /* The TARGETS atom */ static Atom delete_atom; /* The DELETE atom */ static Atom incr_atom; /* The INCR atom */ static Atom null_atom; /* The NULL atom */ static Atom text_atom; /* The TEXT atom */ static Atom utf8_atom; /* The UTF8 atom */ static Atom compound_text_atom; /* The COMPOUND_TEXT atom */ /* Number of selection targets served by this. * (MULTIPLE, INCR, TARGETS, TIMESTAMP, DELETE, TEXT, UTF8_STRING and STRING) * NB. We do not currently serve COMPOUND_TEXT; we can retrieve it but do not * perform charset conversion. */ #define MAX_NUM_TARGETS 9 static int NUM_TARGETS; static Atom supported_targets[MAX_NUM_TARGETS]; /* do_zeroflush: Use only last zero-separated part of input. * All previous parts are discarded */ static Bool do_zeroflush = False; /* do_follow: Follow mode for output */ static Bool do_follow = False; /* nodaemon: Disable daemon mode if True. */ static Bool no_daemon = False; /* logfile: name of file to log error messages to when detached */ static char logfile[MAXFNAME]; /* fstat() on stdin and stdout */ static struct stat in_statbuf, out_statbuf; static int total_input = 0; static int current_alloc = 0; static long timeout = 0; static struct itimerval timer; static struct itimerval zerot; #define USEC_PER_SEC 1000000 static int saved_argc; static char ** saved_argv; /* * usage () * * print usage information. */ static void usage (void) { printf ("Usage: xsel [options]\n"); printf ("Manipulate the X selection.\n\n"); printf ("By default the current selection is output and not modified if both\n"); printf ("standard input and standard output are terminals (ttys). Otherwise,\n"); printf ("the current selection is output if standard output is not a terminal\n"); printf ("(tty), and the selection is set from standard input if standard input\n"); printf ("is not a terminal (tty). If any input or output options are given then\n"); printf ("the program behaves only in the requested mode.\n\n"); printf ("If both input and output is required then the previous selection is\n"); printf ("output before being replaced by the contents of standard input.\n\n"); printf ("Input options\n"); printf (" -a, --append Append standard input to the selection\n"); printf (" -f, --follow Append to selection as standard input grows\n"); printf (" -z, --zeroflush Overwrites selection when zero ('\\0') is received\n"); printf (" -i, --input Read standard input into the selection\n\n"); printf ("Output options\n"); printf (" -o, --output Write the selection to standard output\n\n"); printf ("Action options\n"); printf (" -c, --clear Clear the selection\n"); printf (" -d, --delete Request that the selection be cleared and that\n"); printf (" the application owning it delete its contents\n\n"); printf ("Selection options\n"); printf (" -p, --primary Operate on the PRIMARY selection (default)\n"); printf (" -s, --secondary Operate on the SECONDARY selection\n"); printf (" -b, --clipboard Operate on the CLIPBOARD selection\n\n"); printf (" -k, --keep Do not modify the selections, but make the PRIMARY\n"); printf (" and SECONDARY selections persist even after the\n"); printf (" programs they were selected in exit.\n"); printf (" -x, --exchange Exchange the PRIMARY and SECONDARY selections\n\n"); printf ("X options\n"); printf (" --display displayname\n"); printf (" Specify the connection to the X server\n"); printf (" -m wm, --name wm Name with the process will be identified\n"); printf (" -t ms, --selectionTimeout ms\n"); printf (" Specify the timeout in milliseconds within which the\n"); printf (" selection must be retrieved. A value of 0 (zero)\n"); printf (" specifies no timeout (default)\n\n"); printf ("Miscellaneous options\n"); printf (" --trim Remove newline ('\\n') char from end of input / output\n"); printf (" -l, --logfile Specify file to log errors to when detached.\n"); printf (" -n, --nodetach Do not detach from the controlling terminal. Without\n"); printf (" this option, xsel will fork to become a background\n"); printf (" process in input, exchange and keep modes.\n\n"); printf (" -h, --help Display this help and exit\n"); printf (" -v, --verbose Print informative messages\n"); printf (" --version Output version information and exit\n\n"); printf ("Please report bugs to .\n"); } /* * exit_err (fmt) * * Print a formatted error message and errno information to stderr, * then exit with return code 1. */ static void exit_err (const char * fmt, ...) { va_list ap; int errno_save; char buf[MAXLINE]; int n; errno_save = errno; va_start (ap, fmt); snprintf (buf, MAXLINE, "%s: ", progname); n = strlen (buf); vsnprintf (buf+n, MAXLINE-n, fmt, ap); n = strlen (buf); snprintf (buf+n, MAXLINE-n, ": %s\n", strerror (errno_save)); fflush (stdout); /* in case stdout and stderr are the same */ fputs (buf, stderr); fflush (NULL); va_end (ap); exit (1); } /* * print_err (fmt) * * Print a formatted error message to stderr. */ static void print_err (const char * fmt, ...) { va_list ap; int errno_save; char buf[MAXLINE]; int n; errno_save = errno; va_start (ap, fmt); snprintf (buf, MAXLINE, "%s: ", progname); n = strlen (buf); vsnprintf (buf+n, MAXLINE-n, fmt, ap); n = strlen (buf); fflush (stdout); /* in case stdout and stderr are the same */ fputs (buf, stderr); fputc ('\n', stderr); fflush (NULL); va_end (ap); } /* * print_debug (level, fmt) * * Print a formatted debugging message of level 'level' to stderr */ #define print_debug(x,y...) {if (x <= debug_level) print_err (y);} /* * get_atom_name (atom) * * Returns a string with a printable name for the Atom 'atom'. */ static char * get_atom_name (Atom atom) { char * ret; static char atom_name[MAXLINE+2]; /* unused extra char to avoid string-op-truncation warning */ if (atom == None) return "None"; if (atom == XA_STRING) return "STRING"; if (atom == XA_PRIMARY) return "PRIMARY"; if (atom == XA_SECONDARY) return "SECONDARY"; if (atom == timestamp_atom) return "TIMESTAMP"; if (atom == multiple_atom) return "MULTIPLE"; if (atom == targets_atom) return "TARGETS"; if (atom == delete_atom) return "DELETE"; if (atom == incr_atom) return "INCR"; if (atom == null_atom) return "NULL"; if (atom == text_atom) return "TEXT"; if (atom == utf8_atom) return "UTF8_STRING"; ret = XGetAtomName (display, atom); strncpy (atom_name, ret, MAXLINE+1); if (atom_name[MAXLINE] != '\0') { atom_name[MAXLINE-3] = '.'; atom_name[MAXLINE-2] = '.'; atom_name[MAXLINE-1] = '.'; atom_name[MAXLINE] = '\0'; } XFree (ret); return atom_name; } /* * debug_property (level, requestor, property, target, length) * * Print debugging information (at level 'level') about a property received. */ static void debug_property (int level, Window requestor, Atom property, Atom target, unsigned long length) { print_debug (level, "Got window property: requestor 0x%x, property 0x%x, target 0x%x %s, length %ld bytes", requestor, property, target, get_atom_name (target), length); } /* * xs_malloc (size) * * Malloc wrapper. Always returns a successful allocation. Exits if the * allocation didn't succeed. */ static void * xs_malloc (size_t size) { void * ret; if (size == 0) size = 1; if ((ret = malloc (size)) == NULL) { exit_err ("malloc error"); } return ret; } /* * xs_strdup (s) * * strdup wrapper for unsigned char * */ #define xs_strdup(s) ((unsigned char *) _xs_strdup ((const char *)s)) static char * _xs_strdup (const char * s) { char * ret; if (s == NULL) return NULL; if ((ret = strdup(s)) == NULL) { exit_err ("strdup error"); } return ret; } /* * xs_strlen (s) * * strlen wrapper for unsigned char * */ #define xs_strlen(s) (strlen ((const char *) s)) /* * xs_strncpy (s) * * strncpy wrapper for unsigned char * */ #define xs_strncpy(dest,s,n) (_xs_strncpy ((char *)dest, (const char *)s, n)) static char * _xs_strncpy (char * dest, const char * src, size_t n) { if (n > 0) { strncpy (dest, src, n-1); dest[n-1] = '\0'; } return dest; } /* * get_xdg_cache_home () * * Get the user's cache directory */ static char * get_xdg_cache_home (void) { char * cachedir; char * homedir; static const char * slashbasename = "/.cache"; if ((cachedir = getenv ("XDG_CACHE_HOME")) == NULL) { if ((homedir = getenv ("HOME")) == NULL) { exit_err ("no HOME directory"); } cachedir = xs_malloc (strlen (homedir) + strlen (slashbasename) + 1); strcpy (cachedir, homedir); strcat (cachedir, slashbasename); } else { cachedir = _xs_strdup (cachedir); } mkdir (cachedir, S_IRWXU|S_IRGRP|S_IXGRP); return cachedir; } /* * The set of terminal signals we block while handling SelectionRequests. * * If we exit in the middle of handling a SelectionRequest, we might leave the * requesting client hanging, so we try to be nice and finish handling * requests before terminating. Hence we block SIG{ALRM,INT,TERM} while * handling requests and unblock them only while waiting in XNextEvent(). */ static sigset_t exit_sigs; static void block_exit_sigs(void) { sigprocmask (SIG_BLOCK, &exit_sigs, NULL); } static void unblock_exit_sigs(void) { sigprocmask (SIG_UNBLOCK, &exit_sigs, NULL); } /* The jmp_buf to longjmp out of the signal handler */ static sigjmp_buf env_alrm; /* * alarm_handler (sig) * * Signal handler for catching SIGALRM. */ static void alarm_handler (int sig) { siglongjmp (env_alrm, 1); } /* * set_timer_timeout () * * Set timer parameters according to specified timeout. */ static void set_timer_timeout (void) { timer.it_interval.tv_sec = timeout / USEC_PER_SEC; timer.it_interval.tv_usec = timeout % USEC_PER_SEC; timer.it_value.tv_sec = timeout / USEC_PER_SEC; timer.it_value.tv_usec = timeout % USEC_PER_SEC; } /* * set_daemon_timeout () * * Set up a timer to cause the daemon to exit after the desired * amount of time. */ static void set_daemon_timeout (void) { if (signal (SIGALRM, alarm_handler) == SIG_ERR) { exit_err ("error setting timeout handler"); } set_timer_timeout (); if (sigsetjmp (env_alrm, 0) == 0) { setitimer (ITIMER_REAL, &timer, (struct itimerval *)0); } else { print_debug (D_INFO, "daemon exiting after %d ms", timeout / 1000); exit (0); } } /* * become_daemon () * * Perform the required procedure to become a daemon process, as * outlined in the Unix programming FAQ: * http://www.steve.org.uk/Reference/Unix/faq_2.html#SEC16 * and open a logfile. */ static void become_daemon (void) { pid_t pid; int null_r_fd, null_w_fd, log_fd; char * cachedir; if (no_daemon) { /* If the user has specified a timeout, enforce it even if we don't * actually daemonize */ set_daemon_timeout (); return; } cachedir = get_xdg_cache_home(); /* Check that we can open a logfile before continuing */ /* If the user has specified a --logfile, use that ... */ if (logfile[0] == '\0') { /* ... otherwise use the default logfile */ snprintf (logfile, MAXFNAME, "%s/xsel.log", cachedir); } /* Make sure to create the logfile with sane permissions */ log_fd = open (logfile, O_WRONLY|O_APPEND|O_CREAT, 0600); if (log_fd == -1) { exit_err ("error opening logfile %s for writing", logfile); } print_debug (D_INFO, "opened logfile %s", logfile); if ((pid = fork()) == -1) { exit_err ("error forking"); } else if (pid > 0) { _exit (0); } if (setsid () == -1) { exit_err ("setsid error"); } if ((pid = fork()) == -1) { exit_err ("error forking"); } else if (pid > 0) { _exit (0); } umask (0); if (chdir (cachedir) == -1) { print_debug (D_WARN, "Could not chdir to %s\n", cachedir); if (chdir ("/") == -1) { exit_err ("Error chdir to /"); } } /* dup2 /dev/null on stdin unless following input */ if (!do_follow) { null_r_fd = open ("/dev/null", O_RDONLY); if (null_r_fd == -1) { exit_err ("error opening /dev/null for reading"); } if (dup2 (null_r_fd, 0) == -1) { exit_err ("error duplicating /dev/null on stdin"); } } /* dup2 /dev/null on stdout */ null_w_fd = open ("/dev/null", O_WRONLY|O_APPEND); if (null_w_fd == -1) { exit_err ("error opening /dev/null for writing"); } if (dup2 (null_w_fd, 1) == -1) { exit_err ("error duplicating /dev/null on stdout"); } /* dup2 logfile on stderr */ if (dup2 (log_fd, 2) == -1) { exit_err ("error duplicating logfile %s on stderr", logfile); } set_daemon_timeout (); free (cachedir); } /* * get_timestamp () * * Get the current X server time. * * This is done by doing a zero-length append to a random property of the * window, and checking the time on the subsequent PropertyNotify event. * * PRECONDITION: the window must have PropertyChangeMask set. */ static Time get_timestamp (void) { XEvent event; XChangeProperty (display, window, XA_WM_NAME, XA_STRING, 8, PropModeAppend, NULL, 0); while (1) { XNextEvent (display, &event); if (event.type == PropertyNotify) return event.xproperty.time; } } /* * SELECTION RETRIEVAL * =================== * * The following functions implement retrieval of an X selection, * optionally within a user-specified timeout. * * * Selection timeout handling. * --------------------------- * * The selection retrieval can time out if no response is received within * a user-specified time limit. In order to ensure we time the entire * selection retrieval, we use an interval timer and catch SIGALRM. * [Calling select() on the XConnectionNumber would only provide a timeout * to the first XEvent.] */ /* * get_append_property () * * Get a window property and append its data to a buffer at a given offset * pointed to by *offset. 'offset' is modified by this routine to point to * the end of the data. * * Returns True if more data is available for receipt. * * If an error is encountered, the buffer is free'd. */ static Bool get_append_property (XSelectionEvent * xsl, unsigned char ** buffer, unsigned long * offset, unsigned long * alloc) { unsigned char * ptr; Atom target; int format; unsigned long bytesafter, length; unsigned char * value; XGetWindowProperty (xsl->display, xsl->requestor, xsl->property, 0L, 1000000, True, (Atom)AnyPropertyType, &target, &format, &length, &bytesafter, &value); debug_property (D_TRACE, xsl->requestor, xsl->property, target, length); if (target != XA_STRING && target != utf8_atom && target != compound_text_atom) { print_debug (D_OBSC, "target %s not XA_STRING nor UTF8_STRING in get_append_property()", get_atom_name (target)); free (*buffer); *buffer = NULL; return False; } else if (length == 0) { /* A length of 0 indicates the end of the transfer */ print_debug (D_TRACE, "Got zero length property; end of INCR transfer"); return False; } else if (format == 8) { if (*offset + length + 1 > *alloc) { *alloc = *offset + length + 1; if ((*buffer = realloc (*buffer, *alloc)) == NULL) { exit_err ("realloc error"); } } ptr = *buffer + *offset; memcpy (ptr, value, length); ptr[length] = '\0'; *offset += length; print_debug (D_TRACE, "Appended %d bytes to buffer\n", length); } else { print_debug (D_WARN, "Retrieved non-8-bit data\n"); } return True; } /* * wait_incr_selection (selection) * * Retrieve a property of target type INCR. Perform incremental retrieval * and return the resulting data. */ static unsigned char * wait_incr_selection (Atom selection, XSelectionEvent * xsl, int init_alloc) { XEvent event; unsigned char * incr_base = NULL, * incr_ptr = NULL; unsigned long incr_alloc = 0, incr_xfer = 0; Bool wait_prop = True; print_debug (D_TRACE, "Initialising incremental retrieval of at least %d bytes\n", init_alloc); /* Take an interest in the requestor */ XSelectInput (xsl->display, xsl->requestor, PropertyChangeMask); incr_alloc = init_alloc; incr_base = xs_malloc (incr_alloc); incr_ptr = incr_base; print_debug (D_TRACE, "Deleting property that informed of INCR transfer"); XDeleteProperty (xsl->display, xsl->requestor, xsl->property); print_debug (D_TRACE, "Waiting on PropertyNotify events"); while (wait_prop) { XNextEvent (xsl->display, &event); switch (event.type) { case PropertyNotify: if (event.xproperty.state != PropertyNewValue) break; wait_prop = get_append_property (xsl, &incr_base, &incr_xfer, &incr_alloc); break; default: break; } } /* when zero length found, finish up & delete last */ XDeleteProperty (xsl->display, xsl->requestor, xsl->property); print_debug (D_TRACE, "Finished INCR retrieval"); return incr_base; } /* * wait_selection (selection, request_target) * * Block until we receive a SelectionNotify event, and return its * contents; or NULL in the case of a deletion or error. This assumes we * have already called XConvertSelection, requesting a string (explicitly * XA_STRING) or deletion (delete_atom). */ static unsigned char * wait_selection (Atom selection, Atom request_target) { XEvent event; Atom target; int format; unsigned long bytesafter, length; unsigned char * value, * retval = NULL; Bool keep_waiting = True; while (keep_waiting) { XNextEvent (display, &event); switch (event.type) { case SelectionNotify: if (event.xselection.selection != selection) break; if (event.xselection.property == None) { print_debug (D_WARN, "Conversion refused"); value = NULL; keep_waiting = False; } else if (event.xselection.property == null_atom && request_target == delete_atom) { } else { XGetWindowProperty (event.xselection.display, event.xselection.requestor, event.xselection.property, 0L, 1000000, False, (Atom)AnyPropertyType, &target, &format, &length, &bytesafter, &value); debug_property (D_TRACE, event.xselection.requestor, event.xselection.property, target, length); if (request_target == delete_atom && value == NULL) { keep_waiting = False; } else if (target == incr_atom) { /* Handle INCR transfers */ retval = wait_incr_selection (selection, &event.xselection, *(long *)value); keep_waiting = False; } else if (target != utf8_atom && target != XA_STRING && target != compound_text_atom && request_target != delete_atom) { /* Report non-TEXT atoms */ print_debug (D_WARN, "Selection (type %s) is not a string.", get_atom_name (target)); free (retval); retval = NULL; keep_waiting = False; } else { retval = xs_strdup (value); XFree (value); keep_waiting = False; } XDeleteProperty (event.xselection.display, event.xselection.requestor, event.xselection.property); } break; default: break; } } /* Now that we've received the SelectionNotify event, clear any * remaining timeout. */ if (timeout > 0) { // setitimer (ITIMER_REAL, (struct itimerval *)0, (struct itimerval *)0); setitimer (ITIMER_REAL, &zerot, (struct itimerval *)0); } return retval; } /* * get_selection (selection, request_target) * * Retrieves the specified selection and returns its value. * * If a non-zero timeout is specified then set a virtual interval * timer. Return NULL and print an error message if the timeout * expires before the selection has been retrieved. */ static unsigned char * get_selection (Atom selection, Atom request_target) { Atom prop; unsigned char * retval; prop = XInternAtom (display, "XSEL_DATA", False); XConvertSelection (display, selection, request_target, prop, window, timestamp); XSync (display, False); if (timeout > 0) { if (signal (SIGALRM, alarm_handler) == SIG_ERR) { exit_err ("error setting timeout handler"); } set_timer_timeout (); if (sigsetjmp (env_alrm, 0) == 0) { setitimer (ITIMER_REAL, &timer, (struct itimerval *)0); retval = wait_selection (selection, request_target); } else { print_debug (D_WARN, "selection timed out"); retval = NULL; } } else { retval = wait_selection (selection, request_target); } return retval; } /* * get_selection_text (Atom selection) * * Retrieve a text selection. First attempt to retrieve it as UTF_STRING, * and if that fails attempt to retrieve it as a plain XA_STRING. * * NB. Before implementing this, an attempt was made to query TARGETS and * request UTF8_STRING only if listed there, as described in: * http://www.pps.jussieu.fr/~jch/software/UTF8_STRING/UTF8_STRING.text * However, that did not seem to work reliably when tested against various * applications (eg. Mozilla Firefox). This method is of course more * reliable. */ static unsigned char * get_selection_text (Atom selection) { unsigned char * retval; if ((retval = get_selection (selection, utf8_atom)) == NULL) retval = get_selection (selection, XA_STRING); return retval; } /* * SELECTION SETTING * ================= * * The following functions allow a given selection to be set, appended to * or cleared, or to exchange the primary and secondary selections. */ /* * copy_sel (s) * * Copy a string into a new selection buffer, and intitialise * current_alloc and total_input to exactly its length. */ static unsigned char * copy_sel (unsigned char * s) { if (s) { current_alloc = total_input = xs_strlen (s); return xs_strdup (s); } current_alloc = total_input = 0; return NULL; } /* * read_input (read_buffer, do_select) * * Read input from stdin into the specified read_buffer. * * read_buffer must have been dynamically allocated before calling this * function, or be NULL. Input is read until end-of-file is reached, and * read_buffer will be reallocated to accomodate the entire contents of * the input. read_buffer, which may have been reallocated, is returned * upon completion. * * If 'do_select' is True, this function will first check if any data * is available for reading, and return immediately if not. */ static unsigned char * read_input (unsigned char * read_buffer, Bool do_select) { int insize = in_statbuf.st_blksize; unsigned char * new_buffer = NULL; int d, fatal = 0, nfd; ssize_t n; fd_set fds; struct timeval select_timeout; do { if (do_select) { try_read: /* Check if data is available for reading -- if not, return immediately */ FD_ZERO (&fds); FD_SET (0, &fds); select_timeout.tv_sec = (time_t)0; select_timeout.tv_usec = (time_t)0; nfd = select (1, &fds, NULL, NULL, &select_timeout); if (nfd == -1) { if (errno == EINTR) goto try_read; else exit_err ("select error"); } else if (nfd == 0) { print_debug (D_TRACE, "No data available for reading"); break; } } /* check if buffer is full */ if (current_alloc == total_input) { if ((d = (current_alloc % insize)) != 0) current_alloc += (insize-d); current_alloc *= 2; new_buffer = realloc (read_buffer, current_alloc); if (new_buffer == NULL) { exit_err ("realloc error"); } read_buffer = new_buffer; } /* read the remaining data, up to the optimal block length */ n = read (0, &read_buffer[total_input], MIN(current_alloc - total_input, insize)); if (n == -1) { switch (errno) { case EAGAIN: case EINTR: break; default: perror ("read error"); fatal = 1; break; } } total_input += n; } while (n != 0 && !fatal); read_buffer[total_input] = '\0'; if(do_zeroflush && total_input > 0) { int i; for(i=total_input-1; i>=0; i--) { if(read_buffer[i] == '\0') { print_debug (D_TRACE, "Flushing input at %d", i); memmove(&read_buffer[0], &read_buffer[i+1], total_input - i); total_input = total_input - i - 1; read_buffer[total_input] = '\0'; break; } } } print_debug (D_TRACE, "Accumulated %d bytes input", total_input); return read_buffer; } /* * initialise_read (read_buffer) * * Initialises the read_buffer and the state variable current_alloc. * read_buffer is reallocated to accomodate either the entire input * if stdin is a regular file, or at least one block of input otherwise. * If the supplied read_buffer is NULL, a new buffer will be allocated. */ static unsigned char * initialise_read (unsigned char * read_buffer) { int insize = in_statbuf.st_blksize; unsigned char * new_buffer = NULL; if (S_ISREG (in_statbuf.st_mode) && in_statbuf.st_size > 0) { current_alloc += in_statbuf.st_size; } else { current_alloc += insize; } if ((new_buffer = realloc (read_buffer, current_alloc)) == NULL) { exit_err ("realloc error"); } read_buffer = new_buffer; return read_buffer; } /* Forward declaration of refuse_all_incr () */ static void refuse_all_incr (void); /* * handle_x_errors () * * XError handler. */ static int handle_x_errors (Display * display, XErrorEvent * eev) { char err_buf[MAXLINE]; /* Make sure to send a refusal to all waiting INCR requests * and delete the corresponding properties. */ if (eev->error_code == BadAlloc) refuse_all_incr (); XGetErrorText (display, eev->error_code, err_buf, MAXLINE); exit_err (err_buf); return 0; } /* * clear_selection (selection) * * Clears the specified X selection 'selection'. This requests that no * process should own 'selection'; thus the X server will respond to * SelectionRequests with an empty property and we don't need to leave * a daemon hanging around to service this selection. */ static void clear_selection (Atom selection) { XSetSelectionOwner (display, selection, None, timestamp); /* Call XSync to ensure this operation completes before program * termination, especially if this is all we are doing. */ XSync (display, False); } /* * own_selection (selection) * * Requests ownership of the X selection. Returns True if ownership was * granted, and False otherwise. */ static Bool own_selection (Atom selection) { Window owner; XSetSelectionOwner (display, selection, window, timestamp); /* XGetSelectionOwner does a round trip to the X server, so there is * no need to call XSync here. */ owner = XGetSelectionOwner (display, selection); if (owner != window) { return False; } else { XSetErrorHandler (handle_x_errors); return True; } } static IncrTrack * incrtrack_list = NULL; /* * add_incrtrack (it) * * Add 'it' to the head of incrtrack_list. */ static void add_incrtrack (IncrTrack * it) { if (incrtrack_list) { incrtrack_list->prev = it; } it->prev = NULL; it->next = incrtrack_list; incrtrack_list = it; } /* * remove_incrtrack (it) * * Remove 'it' from incrtrack_list. */ static void remove_incrtrack (IncrTrack * it) { if (it->prev) { it->prev->next = it->next; } if (it->next) { it->next->prev = it->prev; } if (incrtrack_list == it) { incrtrack_list = it->next; } } /* * fresh_incrtrack () * * Create a new incrtrack, and add it to incrtrack_list. */ static IncrTrack * fresh_incrtrack (void) { IncrTrack * it; it = xs_malloc (sizeof (IncrTrack)); add_incrtrack (it); return it; } /* * trash_incrtrack (it) * * Remove 'it' from incrtrack_list, and free it. */ static void trash_incrtrack (IncrTrack * it) { remove_incrtrack (it); free (it); } /* * find_incrtrack (atom) * * Find the IncrTrack structure within incrtrack_list pertaining to 'atom', * if it exists. */ static IncrTrack * find_incrtrack (Atom atom) { IncrTrack * iti; for (iti = incrtrack_list; iti; iti = iti->next) { if (atom == iti->property) return iti; } return NULL; } /* Forward declaration of handle_multiple() */ static HandleResult handle_multiple (Display * display, Window requestor, Atom property, unsigned char * sel, Atom selection, Time time, MultTrack * mparent); /* Forward declaration of process_multiple() */ static HandleResult process_multiple (MultTrack * mt, Bool do_parent); /* * confirm_incr (it) * * Confirm the selection request of ITER tracked by 'it'. */ static void notify_incr (IncrTrack * it, HandleResult hr) { XSelectionEvent ev; /* Call XSync here to make sure any BadAlloc errors are caught before * confirming the conversion. */ XSync (it->display, False); print_debug (D_TRACE, "Confirming conversion"); /* Prepare a SelectionNotify event to send, placing the selection in the * requested property. */ ev.type = SelectionNotify; ev.display = it->display; ev.requestor = it->requestor; ev.selection = it->selection; ev.time = it->time; ev.target = it->target; if (hr & HANDLE_ERR) ev.property = None; else ev.property = it->property; XSendEvent (display, ev.requestor, False, (unsigned long)NULL, (XEvent *)&ev); } /* * refuse_all_incr () * * Refuse all INCR transfers in progress. ASSUMES that this is called in * response to an error, and that the program is about to bail out; * ie. incr_track is not cleaned out. */ static void refuse_all_incr (void) { IncrTrack * it; for (it = incrtrack_list; it; it = it->next) { XDeleteProperty (it->display, it->requestor, it->property); notify_incr (it, HANDLE_ERR); /* Don't bother trashing and list-removing these; we are about to * bail out anyway. */ } } /* * complete_incr (it) * * Finish off an INCR retrieval. If it was part of a multiple, continue * that; otherwise, send confirmation that this completed. */ static void complete_incr (IncrTrack * it, HandleResult hr) { MultTrack * mparent = it->mparent; if (mparent) { trash_incrtrack (it); process_multiple (mparent, True); } else { notify_incr (it, hr); trash_incrtrack (it); } } /* * notify_multiple (mt, hr) * * Confirm the selection request initiated with MULTIPLE tracked by 'mt'. */ static void notify_multiple (MultTrack * mt, HandleResult hr) { XSelectionEvent ev; /* Call XSync here to make sure any BadAlloc errors are caught before * confirming the conversion. */ XSync (mt->display, False); /* Prepare a SelectionNotify event to send, placing the selection in the * requested property. */ ev.type = SelectionNotify; ev.display = mt->display; ev.requestor = mt->requestor; ev.selection = mt->selection; ev.time = mt->time; ev.target = multiple_atom; if (hr & HANDLE_ERR) ev.property = None; else ev.property = mt->property; XSendEvent (display, ev.requestor, False, (unsigned long)NULL, (XEvent *)&ev); } /* * complete_multiple (mt, do_parent, hr) * * Complete a MULTIPLE transfer. Iterate to its parent MULTIPLE if * 'do_parent' is true. If there is not parent MULTIPLE, send notification * of its completion with status 'hr'. */ static void complete_multiple (MultTrack * mt, Bool do_parent, HandleResult hr) { MultTrack * mparent = mt->mparent; if (mparent) { free (mt); if (do_parent) process_multiple (mparent, True); } else { notify_multiple (mt, hr); free (mt); } } /* * change_property (display, requestor, property, target, format, mode, * data, nelements) * * Wrapper to XChangeProperty that performs INCR transfer if required and * returns status of entire transfer. */ static HandleResult change_property (Display * display, Window requestor, Atom property, Atom target, int format, int mode, unsigned char * data, int nelements, Atom selection, Time time, MultTrack * mparent) { XSelectionEvent ev; long nr_bytes; IncrTrack * it; print_debug (D_TRACE, "change_property ()"); nr_bytes = nelements * format / 8; if (nr_bytes <= max_req) { print_debug (D_TRACE, "data within maximum request size"); XChangeProperty (display, requestor, property, target, format, mode, data, nelements); return HANDLE_OK; } /* else */ print_debug (D_TRACE, "large data transfer"); /* Send a SelectionNotify event */ ev.type = SelectionNotify; ev.display = display; ev.requestor = requestor; ev.selection = selection; ev.time = time; ev.target = target; ev.property = property; XSelectInput (ev.display, ev.requestor, PropertyChangeMask); XChangeProperty (ev.display, ev.requestor, ev.property, incr_atom, 32, PropModeReplace, (unsigned char *)&nr_bytes, 1); XSendEvent (display, requestor, False, (unsigned long)NULL, (XEvent *)&ev); /* Set up the IncrTrack to track this */ it = fresh_incrtrack (); it->mparent = mparent; it->state = S_INCR_1; it->display = display; it->requestor = requestor; it->property = property; it->selection = selection; it->time = time; it->target = target; it->format = format; it->data = data; it->nelements = nelements; it->offset = 0; /* Maximum nr. of elements that can be transferred in one go */ it->max_elements = max_req * 8 / format; /* Nr. of elements to transfer in this instance */ it->chunk = MIN (it->max_elements, it->nelements - it->offset); /* Wait for that property to get deleted */ print_debug (D_TRACE, "Waiting on initial property deletion (%s)", get_atom_name (it->property)); return HANDLE_INCOMPLETE; } static HandleResult incr_stage_1 (IncrTrack * it) { /* First pass: PropModeReplace, from data, size chunk */ print_debug (D_TRACE, "Writing first chunk (%d bytes) (target 0x%x %s) to property 0x%x of requestor 0x%x", it->chunk, it->target, get_atom_name(it->target), it->property, it->requestor); XChangeProperty (it->display, it->requestor, it->property, it->target, it->format, PropModeReplace, it->data, it->chunk); it->offset += it->chunk; /* wait for PropertyNotify events */ print_debug (D_TRACE, "Waiting on subsequent deletions ..."); it->state = S_INCR_2; return HANDLE_INCOMPLETE; } static HandleResult incr_stage_2 (IncrTrack * it) { it->chunk = MIN (it->max_elements, it->nelements - it->offset); if (it->chunk <= 0) { /* Now write zero-length data to the property */ XChangeProperty (it->display, it->requestor, it->property, it->target, it->format, PropModeAppend, NULL, 0); it->state = S_NULL; print_debug (D_TRACE, "Set si to state S_NULL"); return HANDLE_OK; } else { print_debug (D_TRACE, "Writing chunk (%d bytes) to property", it->chunk); XChangeProperty (it->display, it->requestor, it->property, it->target, it->format, PropModeAppend, it->data+it->offset, it->chunk); it->offset += it->chunk; print_debug (D_TRACE, "%d bytes remaining", it->nelements - it->offset); return HANDLE_INCOMPLETE; } } /* * handle_timestamp (display, requestor, property) * * Handle a TIMESTAMP request. */ static HandleResult handle_timestamp (Display * display, Window requestor, Atom property, Atom selection, Time time, MultTrack * mparent) { return change_property (display, requestor, property, XA_INTEGER, 32, PropModeReplace, (unsigned char *)×tamp, 1, selection, time, mparent); } /* * handle_targets (display, requestor, property) * * Handle a TARGETS request. */ static HandleResult handle_targets (Display * display, Window requestor, Atom property, Atom selection, Time time, MultTrack * mparent) { Atom * targets_cpy; HandleResult r; targets_cpy = malloc (sizeof (supported_targets)); memcpy (targets_cpy, supported_targets, sizeof (supported_targets)); r = change_property (display, requestor, property, XA_ATOM, 32, PropModeReplace, (unsigned char *)targets_cpy, NUM_TARGETS, selection, time, mparent); free(targets_cpy); return r; } /* * handle_string (display, requestor, property, sel) * * Handle a STRING request; setting 'sel' as the data */ static HandleResult handle_string (Display * display, Window requestor, Atom property, unsigned char * sel, Atom selection, Time time, MultTrack * mparent) { return change_property (display, requestor, property, XA_STRING, 8, PropModeReplace, sel, xs_strlen(sel), selection, time, mparent); } /* * handle_utf8_string (display, requestor, property, sel) * * Handle a UTF8_STRING request; setting 'sel' as the data */ static HandleResult handle_utf8_string (Display * display, Window requestor, Atom property, unsigned char * sel, Atom selection, Time time, MultTrack * mparent) { return change_property (display, requestor, property, utf8_atom, 8, PropModeReplace, sel, xs_strlen(sel), selection, time, mparent); } /* * handle_delete (display, requestor, property) * * Handle a DELETE request. */ static HandleResult handle_delete (Display * display, Window requestor, Atom property) { XChangeProperty (display, requestor, property, null_atom, 0, PropModeReplace, NULL, 0); return DID_DELETE; } /* * process_multiple (mt, do_parent) * * Iterate through a MultTrack until it completes, or until one of its * entries initiates an interated selection. * * If 'do_parent' is true, and the actions proscribed in 'mt' are * completed during the course of this call, then process_multiple * is iteratively called on mt->mparent. */ static HandleResult process_multiple (MultTrack * mt, Bool do_parent) { HandleResult retval = HANDLE_OK; unsigned long i; if (!mt) return retval; for (; mt->index < mt->length; mt->index += 2) { i = mt->index; if (mt->atoms[i] == timestamp_atom) { retval |= handle_timestamp (mt->display, mt->requestor, mt->atoms[i+1], mt->selection, mt->time, mt); } else if (mt->atoms[i] == targets_atom) { retval |= handle_targets (mt->display, mt->requestor, mt->atoms[i+1], mt->selection, mt->time, mt); } else if (mt->atoms[i] == multiple_atom) { retval |= handle_multiple (mt->display, mt->requestor, mt->atoms[i+1], mt->sel, mt->selection, mt->time, mt); } else if (mt->atoms[i] == XA_STRING || mt->atoms[i] == text_atom) { retval |= handle_string (mt->display, mt->requestor, mt->atoms[i+1], mt->sel, mt->selection, mt->time, mt); } else if (mt->atoms[i] == utf8_atom) { retval |= handle_utf8_string (mt->display, mt->requestor, mt->atoms[i+1], mt->sel, mt->selection, mt->time, mt); } else if (mt->atoms[i] == delete_atom) { retval |= handle_delete (mt->display, mt->requestor, mt->atoms[i+1]); } else if (mt->atoms[i] == None) { /* the only other thing we know to handle is None, for which we * do nothing. This block is, like, __so__ redundant. Welcome to * Over-engineering 101 :) This comment is just here to keep the * logic documented and separate from the 'else' block. */ } else { /* for anything we don't know how to handle, we fail the conversion * by setting this: */ mt->atoms[i] = None; } /* If any of the conversions failed, signify this by setting that * atom to None ...*/ if (retval & HANDLE_ERR) { mt->atoms[i] = None; } /* ... but don't propogate HANDLE_ERR */ retval &= (~HANDLE_ERR); if (retval & HANDLE_INCOMPLETE) break; } if ((retval & HANDLE_INCOMPLETE) == 0) { complete_multiple (mt, do_parent, retval); } return retval; } /* * continue_incr (it) * * Continue an incremental transfer of IncrTrack * it. * * NB. If the incremental transfer was part of a multiple request, this * function calls process_multiple with do_parent=True because it is * assumed we are continuing an interrupted ITER, thus we must continue * the multiple as its original handler did not complete. */ static HandleResult continue_incr (IncrTrack * it) { HandleResult retval = HANDLE_OK; if (it->state == S_INCR_1) { retval = incr_stage_1 (it); } else if (it->state == S_INCR_2) { retval = incr_stage_2 (it); } /* If that completed the INCR, deal with completion */ if ((retval & HANDLE_INCOMPLETE) == 0) { complete_incr (it, retval); } return retval; } /* * handle_multiple (display, requestor, property, sel, selection, time) * * Handle a MULTIPLE request; possibly setting 'sel' if any STRING * requests are processed within it. Return value has DID_DELETE bit set * if any delete requests are processed. * * NB. This calls process_multiple with do_parent=False because it is * assumed we are "handling" the multiple request on behalf of a * multiple already in progress, or (more likely) directly off a * SelectionRequest event. */ static HandleResult handle_multiple (Display * display, Window requestor, Atom property, unsigned char * sel, Atom selection, Time time, MultTrack * mparent) { MultTrack * mt; int format; Atom type; unsigned long bytesafter; HandleResult retval = HANDLE_OK; mt = xs_malloc (sizeof (MultTrack)); XGetWindowProperty (display, requestor, property, 0L, 1000000, False, (Atom)AnyPropertyType, &type, &format, &mt->length, &bytesafter, (unsigned char **)&mt->atoms); /* Make sure we got the Atom list we want */ if (format != 32) return HANDLE_OK; mt->mparent = mparent; mt->display = display; mt->requestor = requestor; mt->sel = sel; mt->property = property; mt->selection = selection; mt->time = time; mt->index = 0; retval = process_multiple (mt, False); return retval; } /* * handle_selection_request (event, sel) * * Processes a SelectionRequest event 'event' and replies to its * sender appropriately, eg. with the contents of the string 'sel'. * Returns False if a DELETE request is processed, indicating to * the calling function to delete the corresponding selection. * Returns True otherwise. */ static Bool handle_selection_request (XEvent event, unsigned char * sel) { XSelectionRequestEvent * xsr = &event.xselectionrequest; XSelectionEvent ev; HandleResult hr = HANDLE_OK; Bool retval = True; print_debug (D_TRACE, "handle_selection_request, property=0x%x (%s), target=0x%x (%s)", xsr->property, get_atom_name (xsr->property), xsr->target, get_atom_name (xsr->target)); /* Prepare a SelectionNotify event to send, either as confirmation of * placing the selection in the requested property, or as notification * that this could not be performed. */ ev.type = SelectionNotify; ev.display = xsr->display; ev.requestor = xsr->requestor; ev.selection = xsr->selection; ev.time = xsr->time; ev.target = xsr->target; if (xsr->property == None && ev.target != multiple_atom) { /* Obsolete requestor */ xsr->property = xsr->target; } if (ev.time != CurrentTime && ev.time < timestamp) { /* If the time is outside the period we have owned the selection, * which is any time later than timestamp, or if the requested target * is not a string, then refuse the SelectionRequest. NB. Some broken * clients don't set a valid timestamp, so we have to check against * CurrentTime here. */ ev.property = None; } else if (ev.target == timestamp_atom) { /* Return timestamp used to acquire ownership if target is TIMESTAMP */ ev.property = xsr->property; hr = handle_timestamp (ev.display, ev.requestor, ev.property, ev.selection, ev.time, NULL); } else if (ev.target == targets_atom) { /* Return a list of supported targets (TARGETS)*/ ev.property = xsr->property; hr = handle_targets (ev.display, ev.requestor, ev.property, ev.selection, ev.time, NULL); } else if (ev.target == multiple_atom) { if (xsr->property == None) { /* Invalid MULTIPLE request */ ev.property = None; } else { /* Handle MULTIPLE request */ ev.property = xsr->property; hr = handle_multiple (ev.display, ev.requestor, ev.property, sel, ev.selection, ev.time, NULL); } } else if (ev.target == XA_STRING || ev.target == text_atom) { /* Received STRING or TEXT request */ ev.property = xsr->property; hr = handle_string (ev.display, ev.requestor, ev.property, sel, ev.selection, ev.time, NULL); } else if (ev.target == utf8_atom) { /* Received UTF8_STRING request */ ev.property = xsr->property; hr = handle_utf8_string (ev.display, ev.requestor, ev.property, sel, ev.selection, ev.time, NULL); } else if (ev.target == delete_atom) { /* Received DELETE request */ ev.property = xsr->property; hr = handle_delete (ev.display, ev.requestor, ev.property); retval = False; } else { /* Cannot convert to requested target. This includes most non-string * datatypes, and INSERT_SELECTION, INSERT_PROPERTY */ ev.property = None; } /* Return False if a DELETE was processed */ retval = (hr & DID_DELETE) ? False : True; /* If there was an error in the transfer, it should be refused */ if (hr & HANDLE_ERR) { print_debug (D_TRACE, "Error in transfer"); ev.property = None; } if ((hr & HANDLE_INCOMPLETE) == 0) { if (ev.property == None) {print_debug (D_TRACE, "Refusing conversion");} else { print_debug (D_TRACE, "Confirming conversion");} XSendEvent (display, ev.requestor, False, (unsigned long)NULL, (XEvent *)&ev); /* If we return False here, we may quit immediately, so sync out the * X queue. */ if (!retval) XSync (display, False); } return retval; } /* * set_selection (selection, sel) * * Takes ownership of the selection 'selection', then loops waiting for * its SelectionClear or SelectionRequest events. * * Handles SelectionRequest events, first checking for additional * input if the user has specified 'follow' mode. Returns when a * SelectionClear event is received for the specified selection. */ static void set_selection (Atom selection, unsigned char * sel) { XEvent event; IncrTrack * it; if (own_selection (selection) == False) return; for (;;) { /* Flush before unblocking signals so we send replies before exiting */ XFlush (display); unblock_exit_sigs (); XNextEvent (display, &event); block_exit_sigs (); switch (event.type) { case SelectionClear: if (event.xselectionclear.selection == selection) return; break; case SelectionRequest: if (event.xselectionrequest.selection != selection) break; if (do_follow) sel = read_input (sel, True); if (!handle_selection_request (event, sel)) return; break; case PropertyNotify: if (event.xproperty.state != PropertyDelete) break; it = find_incrtrack (event.xproperty.atom); if (it != NULL) { continue_incr (it); } break; default: break; } } } /* * set_selection__daemon (selection, sel) * * Creates a daemon process to handle selection requests for the * specified selection 'selection', to respond with selection text 'sel'. * If 'sel' is an empty string (NULL or "") then no daemon process is * created and the specified selection is cleared instead. */ static void set_selection__daemon (Atom selection, unsigned char * sel) { if (empty_string (sel) && !do_follow) { clear_selection (selection); return; } become_daemon (); set_selection (selection, sel); } /* * set_selection_pair (sel_p, sel_s) * * Handles SelectionClear and SelectionRequest events for both the * primary and secondary selections. Returns once SelectionClear events * have been received for both selections. Responds to SelectionRequest * events for the primary selection with text 'sel_p' and for the * secondary selection with text 'sel_s'. */ static void set_selection_pair (unsigned char * sel_p, unsigned char * sel_s) { XEvent event; IncrTrack * it; if (sel_p) { if (own_selection (XA_PRIMARY) == False) free_string (sel_p); } else { clear_selection (XA_PRIMARY); } if (sel_s) { if (own_selection (XA_SECONDARY) == False) free_string (sel_s); } else { clear_selection (XA_SECONDARY); } for (;;) { /* Flush before unblocking signals so we send replies before exiting */ XFlush (display); unblock_exit_sigs (); XNextEvent (display, &event); block_exit_sigs (); switch (event.type) { case SelectionClear: if (event.xselectionclear.selection == XA_PRIMARY) { free_string (sel_p); if (sel_s == NULL) return; } else if (event.xselectionclear.selection == XA_SECONDARY) { free_string (sel_s); if (sel_p == NULL) return; } break; case SelectionRequest: if (event.xselectionrequest.selection == XA_PRIMARY) { if (!handle_selection_request (event, sel_p)) { free_string (sel_p); if (sel_s == NULL) return; } } else if (event.xselectionrequest.selection == XA_SECONDARY) { if (!handle_selection_request (event, sel_s)) { free_string (sel_s); if (sel_p == NULL) return; } } break; case PropertyNotify: if (event.xproperty.state != PropertyDelete) break; it = find_incrtrack (event.xproperty.atom); if (it != NULL) { continue_incr (it); } break; default: break; } } } /* * set_selection_pair__daemon (sel_p, sel_s) * * Creates a daemon process to handle selection requests for both the * primary and secondary selections with texts 'sel_p' and 'sel_s' * respectively. * * If both 'sel_p' and 'sel_s' are empty strings (NULL or "") then no * daemon process is created, and both selections are cleared instead. */ static void set_selection_pair__daemon (unsigned char * sel_p, unsigned char * sel_s) { if (empty_string (sel_p) && empty_string (sel_s)) { clear_selection (XA_PRIMARY); clear_selection (XA_SECONDARY); return; } become_daemon (); set_selection_pair (sel_p, sel_s); } /* * keep_selections () * * Takes ownership of both the primary and secondary selections. The current * selection texts are retrieved and a new daemon process is created to * handle both selections unmodified. */ static void keep_selections (void) { unsigned char * text1, * text2; text1 = get_selection_text (XA_PRIMARY); text2 = get_selection_text (XA_SECONDARY); set_selection_pair__daemon (text1, text2); } /* * exchange_selections () * * Exchanges the primary and secondary selections. The current selection * texts are retrieved and a new daemon process is created to handle both * selections with their texts exchanged. */ static void exchange_selections (void) { unsigned char * text1, * text2; text1 = get_selection_text (XA_PRIMARY); text2 = get_selection_text (XA_SECONDARY); set_selection_pair__daemon (text2, text1); } /* * free_saved_argv () * * atexit function for freeing argv, after it has been relocated to the * heap. */ static void free_saved_argv (void) { int i; for (i=0; i < saved_argc; i++) { free (saved_argv[i]); } free (saved_argv); } /* * expand_argv (&argc, &argv) * * Explodes single letter options so that the argument parser can see * all of them. Relocates argv and all arguments to the heap. */ static void expand_argv(int * argc, char **argv[]) { int i, new_i, arglen, new_argc = *argc; char ** new_argv; char * arg; /* Calculate new argc */ for (i = 0; i < *argc; i++) { arglen = strlen((*argv)[i]); /* An option we need to expand? */ if ((arglen > 2) && (*argv)[i][0] == '-' && (*argv)[i][1] != '-') new_argc += arglen-2; } /* Allocate new_argv */ new_argv = xs_malloc (new_argc * sizeof(char *)); /* Copy args into new argv */ for (i = 0, new_i = 0; i < *argc; i++) { arglen = strlen((*argv)[i]); /* An option we need to expand? */ if ((arglen > 2) && (*argv)[i][0] == '-' && (*argv)[i][1] != '-') { /* Make each letter a new argument. */ char * c = ((*argv)[i] + 1); while (*c != '\0') { arg = xs_malloc(sizeof(char) * 3); arg[0] = '-'; arg[1] = *c; arg[2] = '\0'; new_argv[new_i++] = arg; c++; } } else { /* Simply copy the argument pointer to new_argv */ new_argv[new_i++] = _xs_strdup ((*argv)[i]); } } /* Set the expected return values */ *argc = new_argc; *argv = new_argv; /* Save the new argc, argv values and free them on exit */ saved_argc = new_argc; saved_argv = new_argv; atexit (free_saved_argv); } /* * main (argc, argv) * ================= * * Parse user options and set behaviour. * * By default the current selection is output and not modified if both * standard input and standard output are terminals (ttys). Otherwise, * the current selection is output if standard output is not a terminal * (tty), and the selection is set from standard input if standard input * is not a terminal (tty). If any input or output options are given then * the program behaves only in the requested mode. * * If both input and output is required then the previous selection is * output before being replaced by the contents of standard input. */ int main(int argc, char *argv[]) { Bool show_version = False; Bool show_help = False; Bool do_append = False, do_clear = False; Bool do_keep = False, do_exchange = False; Bool do_input = False, do_output = False; Bool force_input = False, force_output = False; Bool want_clipboard = False, do_delete = False; Bool trim_trailing_newline = False; Window root; Atom selection = XA_PRIMARY, test_atom; XClassHint * class_hints; int black; int i, s=0; unsigned char * old_sel = NULL, * new_sel = NULL; char * display_name = NULL; char * window_name = "xsel"; long timeout_ms = 0L; zerot.it_value.tv_sec = 0; zerot.it_value.tv_usec = 0; zerot.it_interval.tv_sec = 0; zerot.it_interval.tv_usec = 0; progname = argv[0]; /* Specify default behaviour based on input and output file types */ if (isatty(0) && isatty(1)) { /* Solo invocation; display the selection and exit */ do_input = False; do_output = True; } else { /* Use only what is not attached to the tty */ /* Gives expected behaviour with *basic* usage of "xsel < foo", "xsel > foo", etc. */ do_input = !isatty(0); do_output = !isatty(1); } /* NOTE: * Checking stdin/stdout for being a tty is NOT reliable to tell what the user wants. * This is because child processes inherit the file descriptors of their parents; * an xsel called in a script that is e.g. daemonized (not attached to a tty), or called * with a redirection or in a pipeline will have non-tty file descriptors on default. * The redirection/piping issue also applies to "grouped" or "compound" commands * in the shell (functions, subshells, curly-brace blocks, conditionals, loops, etc.). * In all these cases, the user *must* set the mode of operation explicitly. */ #define OPT(s) (strcmp (argv[i], (s)) == 0) /* Expand argv array before parsing to uncombine arguments. */ expand_argv(&argc, &argv); /* Parse options; modify behaviour according to user-specified options */ for (i=1; i < argc; i++) { if (OPT("--help") || OPT("-h")) { show_help = True; } else if (OPT("--version")) { show_version = True; } else if (OPT("--verbose") || OPT("-v")) { debug_level++; } else if (OPT("--append") || OPT("-a")) { force_input = True; do_output = False; do_append = True; } else if (OPT("--input") || OPT("-i")) { force_input = True; do_output = False; } else if (OPT("--clear") || OPT("-c")) { do_output = False; do_clear = True; } else if (OPT("--output") || OPT("-o")) { do_input = False; force_output = True; } else if (OPT("--follow") || OPT("-f")) { force_input = True; do_output = False; do_follow = True; trim_trailing_newline = False; } else if (OPT("--zeroflush") || OPT("-z")) { force_input = True; do_output = False; do_follow = True; do_zeroflush = True; } else if (OPT("--primary") || OPT("-p")) { selection = XA_PRIMARY; } else if (OPT("--secondary") || OPT("-s")) { selection = XA_SECONDARY; } else if (OPT("--clipboard") || OPT("-b")) { want_clipboard = True; } else if (OPT("--trim")) { trim_trailing_newline = True; } else if (OPT("--keep") || OPT("-k")) { do_keep = True; } else if (OPT("--exchange") || OPT("-x")) { do_exchange = True; } else if (OPT("--display")) { i++; if (i >= argc) goto usage_err; display_name = argv[i]; } else if (OPT("--windowName")) { i++; if (i >= argc) goto usage_err; window_name = argv[i]; } else if (OPT("--selectionTimeout") || OPT("-t")) { i++; if (i >= argc) goto usage_err; timeout_ms = strtol(argv[i], (char **)NULL, 10); if (timeout_ms < 0) timeout_ms = 0; } else if (OPT("--name") || OPT("-m")) { i++; if (i >= argc) goto usage_err; window_name = argv[i]; } else if (OPT("--nodetach") || OPT("-n")) { no_daemon = True; } else if (OPT("--delete") || OPT("-d")) { do_output = False; do_delete = True; } else if (OPT("--logfile") || OPT("-l")) { i++; if (i >= argc) goto usage_err; _xs_strncpy (logfile, argv[i], MAXFNAME); } else { goto usage_err; } } if (show_version) { printf ("xsel version " VERSION " by " AUTHOR "\n"); } if (show_help) { usage (); } if (show_version || show_help) { exit (0); } if (do_input || force_input) { if (fstat (0, &in_statbuf) == -1) { exit_err ("fstat error on stdin"); } if (S_ISDIR(in_statbuf.st_mode)) { exit_err ("-: Is a directory\n"); } } if (do_output || force_output) { if (fstat (1, &out_statbuf) == -1) { exit_err ("fstat error on stdout"); } if (S_ISDIR(out_statbuf.st_mode)) { exit_err ("stdout: Is a directory\n"); } } timeout = timeout_ms * 1000; display = XOpenDisplay (display_name); if (display==NULL) { exit_err ("Can't open display: %s\n", display_name ? display_name : "(null)"); } root = XDefaultRootWindow (display); /* Create an unmapped window for receiving events */ black = BlackPixel (display, DefaultScreen (display)); window = XCreateSimpleWindow (display, root, 0, 0, 1, 1, 0, black, black); print_debug (D_INFO, "Window id: 0x%x (unmapped)", window); if (window_name != NULL) { XStoreName (display, window, window_name); print_debug (D_INFO, "The name %s is assigned to the window", window_name); } /* Set window name and class */ XStoreName(display, window, window_name); class_hints = XAllocClassHint(); if (class_hints==NULL) { exit_err ("Can't allocate class hints memory\n"); } class_hints->res_name = "xsel"; class_hints->res_class = "XSel"; XSetClassHint(display, window, class_hints); XFree(class_hints); /* Get a timestamp */ XSelectInput (display, window, PropertyChangeMask); timestamp = get_timestamp (); print_debug (D_OBSC, "Timestamp: %lu", timestamp); /* Get the maximum incremental selection size in bytes */ /*max_req = MAX_SELECTION_INCR (display);*/ max_req = 4000; print_debug (D_OBSC, "Maximum request size: %ld bytes", max_req); /* Consistency check */ test_atom = XInternAtom (display, "PRIMARY", False); if (test_atom != XA_PRIMARY) print_debug (D_WARN, "XA_PRIMARY not named \"PRIMARY\"\n"); test_atom = XInternAtom (display, "SECONDARY", False); if (test_atom != XA_SECONDARY) print_debug (D_WARN, "XA_SECONDARY not named \"SECONDARY\"\n"); NUM_TARGETS=0; /* Get the TIMESTAMP atom */ timestamp_atom = XInternAtom (display, "TIMESTAMP", False); supported_targets[s++] = timestamp_atom; NUM_TARGETS++; /* Get the MULTIPLE atom */ multiple_atom = XInternAtom (display, "MULTIPLE", False); supported_targets[s++] = multiple_atom; NUM_TARGETS++; /* Get the TARGETS atom */ targets_atom = XInternAtom (display, "TARGETS", False); supported_targets[s++] = targets_atom; NUM_TARGETS++; /* Get the DELETE atom */ delete_atom = XInternAtom (display, "DELETE", False); supported_targets[s++] = delete_atom; NUM_TARGETS++; /* Get the INCR atom */ incr_atom = XInternAtom (display, "INCR", False); supported_targets[s++] = incr_atom; NUM_TARGETS++; /* Get the TEXT atom */ text_atom = XInternAtom (display, "TEXT", False); supported_targets[s++] = text_atom; NUM_TARGETS++; /* Get the UTF8_STRING atom */ utf8_atom = XInternAtom (display, "UTF8_STRING", True); if(utf8_atom != None) { supported_targets[s++] = utf8_atom; NUM_TARGETS++; } else { utf8_atom = XA_STRING; } supported_targets[s++] = XA_STRING; NUM_TARGETS++; if (NUM_TARGETS > MAX_NUM_TARGETS) { exit_err ("internal error num-targets (%d) > max-num-targets (%d)\n", NUM_TARGETS, MAX_NUM_TARGETS); } /* Get the NULL atom */ null_atom = XInternAtom (display, "NULL", False); /* Get the COMPOUND_TEXT atom. * NB. We do not currently serve COMPOUND_TEXT; we can retrieve it but * do not perform charset conversion. */ compound_text_atom = XInternAtom (display, "COMPOUND_TEXT", False); sigemptyset (&exit_sigs); sigaddset (&exit_sigs, SIGALRM); sigaddset (&exit_sigs, SIGINT); sigaddset (&exit_sigs, SIGTERM); /* handle selection keeping and exit if so */ if (do_keep) { keep_selections (); _exit (0); } /* handle selection exchange and exit if so */ if (do_exchange) { exchange_selections (); _exit (0); } /* Find the "CLIPBOARD" selection if required */ if (want_clipboard) { selection = XInternAtom (display, "CLIPBOARD", False); } /* handle output modes */ if (do_output || force_output) { /* Get the current selection */ old_sel = get_selection_text (selection); if (old_sel) { if (trim_trailing_newline) { unsigned int old_sel_len = xs_strlen(old_sel); if (old_sel[old_sel_len - 1 ] == '\n') { old_sel[old_sel_len - 1] = '\0'; } } printf ("%s", old_sel); if (!do_append && *old_sel != '\0' && isatty(1) && old_sel[xs_strlen (old_sel) - 1] != '\n') { fflush (stdout); } } } /* handle input and clear modes */ if (do_delete) { get_selection (selection, delete_atom); } else if (do_clear) { clear_selection (selection); } else if (do_input || force_input) { if (do_output || force_output) fflush (stdout); if (do_append) { if (!old_sel) old_sel = get_selection_text (selection); new_sel = copy_sel (old_sel); } new_sel = initialise_read (new_sel); if(!do_follow) new_sel = read_input (new_sel, False); if(trim_trailing_newline) { unsigned int sel_len = xs_strlen(new_sel); if (new_sel[sel_len - 1 ] == '\n') { new_sel[sel_len - 1] = '\0'; } } set_selection__daemon (selection, new_sel); } exit (0); usage_err: usage (); exit (0); } xsel-1.2.1/xsel.h000066400000000000000000000050121441746606700136270ustar00rootroot00000000000000/* * xsel -- manipulate the X selection * Copyright (C) 2001 Conrad Parker * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. No representations are made about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. */ #define AUTHOR "Conrad Parker " /* Default debug level (ship at 0) */ #define DEBUG_LEVEL 0 #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) #define empty_string(s) (s==NULL||s[0]=='\0') #define free_string(s) { free(s); s=NULL; } /* Maximum line length for error messages */ #define MAXLINE 4096 /* Maximum filename length */ #define MAXFNAME 1024 /* Maximum incremental selection size. (Ripped from Xt) */ #define MAX_SELECTION_INCR(dpy) (((65536 < XMaxRequestSize(dpy)) ? \ (65536 << 2) : (XMaxRequestSize(dpy) << 2))-100) /* * Debug levels (for print_debug()): * * 0 - Fatal errors (default/unmaskable) * 1 - Non-fatal warning (essential debugging info) * 2 - Informative (generally useful debugging info) * 3 - Obscure (more detailed debugging info) * 4 - Trace (sequential trace of progress) */ #define D_FATAL 0 #define D_WARN 1 #define D_INFO 2 #define D_OBSC 3 #define D_TRACE 4 /* An instance of a MULTIPLE SelectionRequest being served */ typedef struct _MultTrack MultTrack; struct _MultTrack { MultTrack * mparent; Display * display; Window requestor; Atom property; Atom selection; Time time; Atom * atoms; unsigned long length; unsigned long index; unsigned char * sel; }; /* Selection serving states */ typedef enum { S_NULL=0, S_INCR_1, S_INCR_2 } IncrState; /* An instance of a selection being served */ typedef struct _IncrTrack IncrTrack; struct _IncrTrack { MultTrack * mparent; IncrTrack * prev, * next; IncrState state; Display * display; Window requestor; Atom property; Atom selection; Time time; Atom target; int format; unsigned char * data; int nelements; /* total */ int offset, chunk, max_elements; /* all in terms of nelements */ }; /* Status of request handling */ typedef int HandleResult; #define HANDLE_OK 0 #define HANDLE_ERR (1<<0) #define HANDLE_INCOMPLETE (1<<1) #define DID_DELETE (1<<2)