projects/pwm

changeset 26:5bdea77d0c1d

Add pwm-clip utility for setting the X11 CLIPBOARD selection
author Guido Berhoerster <guido+pwm@berhoerster.name>
date Thu Sep 21 09:45:59 2017 +0200 (2017-09-21)
parents 616385fa1fd9
children 722a45b4028b
files Makefile compat.h compat/getline.c compat/getline.h pwm-clip.1.xml pwm-clip.c pwm.1.xml
line diff
     1.1 --- a/Makefile	Wed Sep 20 23:57:51 2017 +0200
     1.2 +++ b/Makefile	Thu Sep 21 09:45:59 2017 +0200
     1.3 @@ -83,6 +83,7 @@
     1.4    HAVE_ASPRINTF ?=	1
     1.5    HAVE_CLOSEFROM ?=	0
     1.6    HAVE_ERR_H ?=		1
     1.7 +  HAVE_GETLINE ?=	0
     1.8    HAVE_GETRANDOM ?=	0
     1.9    HAVE_SYS_QUEUE_H ?=	0
    1.10    HAVE_SETPROGNAME ?=	0
    1.11 @@ -92,6 +93,7 @@
    1.12    HAVE_ASPRINTF ?=	1
    1.13    HAVE_CLOSEFROM ?=	1
    1.14    HAVE_ERR_H ?=		1
    1.15 +  HAVE_GETLINE ?=	1
    1.16    HAVE_GETRANDOM ?=	0
    1.17    HAVE_SYS_QUEUE_H ?=	1
    1.18    HAVE_SETPROGNAME ?=	1
    1.19 @@ -101,6 +103,7 @@
    1.20    HAVE_ASPRINTF ?=	1
    1.21    HAVE_CLOSEFROM ?=	1
    1.22    HAVE_ERR_H ?=		1
    1.23 +  HAVE_GETLINE ?=	1
    1.24    HAVE_GETRANDOM ?=	0
    1.25    HAVE_SYS_QUEUE_H ?=	1
    1.26    HAVE_SYS_TREE_H ?=	1
    1.27 @@ -110,6 +113,7 @@
    1.28    HAVE_ASPRINTF ?=	1
    1.29    HAVE_CLOSEFROM ?=	1
    1.30    HAVE_ERR_H ?=		1
    1.31 +  HAVE_GETLINE ?=	1
    1.32    HAVE_GETRANDOM ?=	0
    1.33    HAVE_SYS_QUEUE_H ?=	1
    1.34    HAVE_SYS_TREE_H ?=	1
    1.35 @@ -119,11 +123,13 @@
    1.36      HAVE_ARC4RANDOM ?=	0
    1.37      HAVE_ASPRINTF ?=	0
    1.38      HAVE_ERR_H ?=	0
    1.39 +    HAVE_GETLINE ?=	0
    1.40      HAVE_GETRANDOM ?=	0
    1.41    else
    1.42      HAVE_ARC4RANDOM ?=	1
    1.43      HAVE_ASPRINTF ?=	1
    1.44      HAVE_ERR_H ?=	1
    1.45 +    HAVE_GETLINE ?=	1
    1.46      HAVE_GETRANDOM ?=	1
    1.47    endif
    1.48    HAVE_CLOSEFROM ?=	1
    1.49 @@ -135,6 +141,7 @@
    1.50    HAVE_ASPRINTF ?=	0
    1.51    HAVE_CLOSEFROM ?=	0
    1.52    HAVE_ERR_H ?=		0
    1.53 +  HAVE_GETLINE ?=	0
    1.54    HAVE_GETRANDOM ?=	0
    1.55    HAVE_SYS_QUEUE_H ?=	0
    1.56    HAVE_SETPROGNAME ?=	0
    1.57 @@ -149,6 +156,10 @@
    1.58  LIBPWM_LIB =		libpwm.a
    1.59  LIBPWM_LIB_MEMBERS =	$(LIBPWM_OBJS:%.o=$(LIBPWM_LIB)(%.o))
    1.60  
    1.61 +PWM_CLIP_OBJS =		pwm-clip.o
    1.62 +PWM_CLIP_BIN =		pwm-clip
    1.63 +PWM_CLIP_MAN1 =		pwm-clip.1
    1.64 +
    1.65  PWM_OBJS =		cmd.o \
    1.66  			io.o \
    1.67  			pager.o \
    1.68 @@ -158,20 +169,23 @@
    1.69  			pwm.o \
    1.70  			tok.o
    1.71  PWM_BIN =		$(PACKAGE)
    1.72 +PWM_MAN1 =		pwm.1
    1.73  
    1.74 -OBJS = $(LIBCOMPAT_OBJS) $(LIBPWM_OBJS) $(PWM_OBJS)
    1.75 +OBJS = $(LIBCOMPAT_OBJS) $(LIBPWM_OBJS) $(PWM_CLIP_OBJS) $(PWM_OBJS)
    1.76  
    1.77 -MANPAGES = pwm.1
    1.78 +MANPAGES = $(PWM_MAN1) $(PWM_CLIP_MAN1)
    1.79  
    1.80  .DEFAULT_TARGET = all
    1.81  
    1.82  .PHONY: all clean clobber dist install
    1.83  
    1.84 -all: $(PWM_BIN) $(MANPAGES)
    1.85 +all: $(PWM_BIN) $(PWM_CLIP_BIN) $(MANPAGES)
    1.86  
    1.87  $(PWM_BIN): XCPPFLAGS += -DPACKAGE=\"$(PACKAGE)\" \
    1.88  			-DVERSION=\"$(VERSION)\"
    1.89  $(PWM_BIN): LDLIBS =	-ltecla -lcurses -lpws -lnettle
    1.90 +$(PWM_CLIP_BIN): XCPPFLAGS += -Icompat/include
    1.91 +$(PWM_CLIP_BIN): LDLIBS = -lnettle
    1.92  ifeq ($(HAVE_ASPRINTF),1)
    1.93    XCPPFLAGS +=		-DHAVE_ASPRINTF
    1.94  else
    1.95 @@ -196,6 +210,11 @@
    1.96  else
    1.97    LIBCOMPAT_OBJS +=	compat/err.o
    1.98  endif
    1.99 +ifeq ($(HAVE_GETLINE),1)
   1.100 +  XCPPFLAGS +=		-DHAVE_GETLINE
   1.101 +else
   1.102 +  LIBCOMPAT_OBJS +=	compat/getline.o
   1.103 +endif
   1.104  ifeq ($(HAVE_SETPROGNAME),1)
   1.105    XCPPFLAGS +=		-DHAVE_SETPROGNAME
   1.106  else
   1.107 @@ -223,10 +242,15 @@
   1.108  
   1.109  $(LIBPWM_LIB): $(LIBPWM_LIB_MEMBERS)
   1.110  
   1.111 +$(PWM_CLIP_BIN): $(PWM_CLIP_OBJS) $(LIBPWM_LIB) $(LIBCOMPAT_LIB)
   1.112 +	$(LINK.o) $^ $(LDLIBS) -o $@
   1.113 +
   1.114 +$(eval $(call generate-manpage-rule,$(PWM_CLIP_MAN1)))
   1.115 +
   1.116  $(PWM_BIN): $(PWM_OBJS) $(LIBPWM_LIB) $(LIBCOMPAT_LIB)
   1.117  	$(LINK.o) $^ $(LDLIBS) -o $@
   1.118  
   1.119 -$(eval $(call generate-manpage-rule,$(MANPAGES)))
   1.120 +$(eval $(call generate-manpage-rule,$(PWM_MAN1)))
   1.121  
   1.122  %.o: %.c
   1.123  	$(MAKEDEPEND.c) $< | $(SED) -f deps.sed >$*.d
   1.124 @@ -238,6 +262,7 @@
   1.125  
   1.126  install: all
   1.127  	$(INSTALL.exec) $(PWM_BIN) "$(DESTDIR)$(bindir)/$(PWM_BIN)"
   1.128 +	$(INSTALL.exec) $(PWM_CLIP_BIN) "$(DESTDIR)$(bindir)/$(PWM_CLIP_BIN)"
   1.129  	for manpage in $(MANPAGES); do \
   1.130  	    if [ -L $${manpage} ]; then \
   1.131  	        $(INSTALL.link) $${manpage} \
   1.132 @@ -249,7 +274,8 @@
   1.133  	done
   1.134  
   1.135  clean:
   1.136 -	rm -f $(LIBCOMPAT_LIB) $(LIBPWM_LIB) $(PWM_BIN) $(OBJS) $(MANPAGES)
   1.137 +	rm -f $(LIBCOMPAT_LIB) $(LIBPWM_LIB) $(PWM_CLIP_BIN) $(PWM_BIN) \
   1.138 +	    $(OBJS) $(MANPAGES)
   1.139  
   1.140  clobber: clean
   1.141  	rm -f $(patsubst %.o,%.d,$(OBJS))
     2.1 --- a/compat.h	Wed Sep 20 23:57:51 2017 +0200
     2.2 +++ b/compat.h	Thu Sep 21 09:45:59 2017 +0200
     2.3 @@ -39,6 +39,10 @@
     2.4  #include "compat/err.h"
     2.5  #endif /* !HAVE_ERR_H */
     2.6  
     2.7 +#ifndef	HAVE_GETLINE
     2.8 +#include "compat/getline.h"
     2.9 +#endif /* !HAVE_GETLINE */
    2.10 +
    2.11  #ifndef	HAVE_GETENTROPY
    2.12  #include "compat/getentropy.h"
    2.13  #endif /* !HAVE_GETENTROPY */
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/compat/getline.c	Thu Sep 21 09:45:59 2017 +0200
     3.3 @@ -0,0 +1,93 @@
     3.4 +/*
     3.5 + * Copyright (C) 2016 Guido Berhoerster <guido+pwm@berhoerster.name>
     3.6 + *
     3.7 + * Permission is hereby granted, free of charge, to any person obtaining
     3.8 + * a copy of this software and associated documentation files (the
     3.9 + * "Software"), to deal in the Software without restriction, including
    3.10 + * without limitation the rights to use, copy, modify, merge, publish,
    3.11 + * distribute, sublicense, and/or sell copies of the Software, and to
    3.12 + * permit persons to whom the Software is furnished to do so, subject to
    3.13 + * the following conditions:
    3.14 + *
    3.15 + * The above copyright notice and this permission notice shall be included
    3.16 + * in all copies or substantial portions of the Software.
    3.17 + *
    3.18 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    3.19 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    3.20 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    3.21 + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    3.22 + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    3.23 + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    3.24 + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    3.25 + */
    3.26 +
    3.27 +#include <stdio.h>
    3.28 +#include <stdlib.h>
    3.29 +#include <limits.h>
    3.30 +#include <sys/types.h>
    3.31 +#include <errno.h>
    3.32 +
    3.33 +#include "getline.h"
    3.34 +
    3.35 +#define	MIN(x, y)	(((x) < (y)) ? (x) : (y))
    3.36 +
    3.37 +ssize_t
    3.38 +getdelim(char **linep, size_t *sizep, int delim, FILE *fp)
    3.39 +{
    3.40 +	ssize_t	len;
    3.41 +	char	*line = *linep;
    3.42 +	size_t	size = *sizep;
    3.43 +	size_t	pos = 0;
    3.44 +	char	*line_new;
    3.45 +	int	c;
    3.46 +
    3.47 +	if (*linep == NULL) {
    3.48 +		size = 0;
    3.49 +	}
    3.50 +
    3.51 +	flockfile(fp);
    3.52 +
    3.53 +	for (;;) {
    3.54 +		if (size - pos < 2) {
    3.55 +			size = MIN((size_t)SSIZE_MAX + 1,
    3.56 +			    (size < BUFSIZ) ? BUFSIZ : size * 1.5);
    3.57 +			if (size - pos < 2) {
    3.58 +				len = -1;
    3.59 +				errno = EOVERFLOW;
    3.60 +				break;
    3.61 +			}
    3.62 +			line_new = realloc(line, size);
    3.63 +			if (line_new == NULL) {
    3.64 +				len = -1;
    3.65 +				break;
    3.66 +			}
    3.67 +			*linep = line = line_new;
    3.68 +			*sizep = size;
    3.69 +		}
    3.70 +		c = fgetc(fp);
    3.71 +		if (c == EOF) {
    3.72 +			len = -1;
    3.73 +			break;
    3.74 +		}
    3.75 +		line[pos] = c;
    3.76 +		pos++;
    3.77 +		len = pos;
    3.78 +		if (c == delim) {
    3.79 +			break;
    3.80 +		}
    3.81 +	}
    3.82 +
    3.83 +	if (*linep != NULL) {
    3.84 +		(*linep)[pos] = '\0';
    3.85 +	}
    3.86 +
    3.87 +	funlockfile(fp);
    3.88 +
    3.89 +	return (len);
    3.90 +}
    3.91 +
    3.92 +ssize_t
    3.93 +getline(char **linep, size_t *sizep, FILE *fp)
    3.94 +{
    3.95 +	return (getdelim(linep, sizep, '\n', fp));
    3.96 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/compat/getline.h	Thu Sep 21 09:45:59 2017 +0200
     4.3 @@ -0,0 +1,33 @@
     4.4 +/*
     4.5 + * Copyright (C) 2016 Guido Berhoerster <guido+pwm@berhoerster.name>
     4.6 + *
     4.7 + * Permission is hereby granted, free of charge, to any person obtaining
     4.8 + * a copy of this software and associated documentation files (the
     4.9 + * "Software"), to deal in the Software without restriction, including
    4.10 + * without limitation the rights to use, copy, modify, merge, publish,
    4.11 + * distribute, sublicense, and/or sell copies of the Software, and to
    4.12 + * permit persons to whom the Software is furnished to do so, subject to
    4.13 + * the following conditions:
    4.14 + *
    4.15 + * The above copyright notice and this permission notice shall be included
    4.16 + * in all copies or substantial portions of the Software.
    4.17 + *
    4.18 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    4.19 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    4.20 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    4.21 + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    4.22 + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    4.23 + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    4.24 + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    4.25 + */
    4.26 +
    4.27 +#ifndef	GETLINE_H
    4.28 +#define	GETLINE_H
    4.29 +
    4.30 +#include <sys/types.h>
    4.31 +#include <stdio.h>
    4.32 +
    4.33 +ssize_t	getline(char **, size_t *, FILE *);
    4.34 +ssize_t getdelim(char **, size_t *, int, FILE *);
    4.35 +
    4.36 +#endif /* !GETLINE_H */
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/pwm-clip.1.xml	Thu Sep 21 09:45:59 2017 +0200
     5.3 @@ -0,0 +1,120 @@
     5.4 +<?xml version="1.0"?>
     5.5 +<!--
     5.6 +
     5.7 +Copyright (C) 2017 Guido Berhoerster <guido+pwm@berhoerster.name>
     5.8 +
     5.9 +Permission is hereby granted, free of charge, to any person obtaining
    5.10 +a copy of this software and associated documentation files (the
    5.11 +"Software"), to deal in the Software without restriction, including
    5.12 +without limitation the rights to use, copy, modify, merge, publish,
    5.13 +distribute, sublicense, and/or sell copies of the Software, and to
    5.14 +permit persons to whom the Software is furnished to do so, subject to
    5.15 +the following conditions:
    5.16 +
    5.17 +The above copyright notice and this permission notice shall be included
    5.18 +in all copies or substantial portions of the Software.
    5.19 +
    5.20 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    5.21 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    5.22 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    5.23 +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    5.24 +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    5.25 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    5.26 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    5.27 +
    5.28 +-->
    5.29 +<refentry xmlns="http://docbook.org/ns/docbook" xml:lang="en">
    5.30 +  <info>
    5.31 +    <author>
    5.32 +      <personname>
    5.33 +        <firstname>Guido</firstname>
    5.34 +        <surname>Berhoerster</surname>
    5.35 +      </personname>
    5.36 +      <email>guido+pwm@berhoerster.name</email>
    5.37 +      <personblurb/>
    5.38 +    </author>
    5.39 +    <date>21 September, 2017</date>
    5.40 +  </info>
    5.41 +  <refmeta>
    5.42 +    <refentrytitle>pwm-clip</refentrytitle>
    5.43 +    <manvolnum>1</manvolnum>
    5.44 +    <refmiscinfo class="source"/>
    5.45 +    <refmiscinfo class="version"/>
    5.46 +    <refmiscinfo class="manual">User Commands</refmiscinfo>
    5.47 +  </refmeta>
    5.48 +  <refnamediv>
    5.49 +    <refname>pwm-clip</refname>
    5.50 +    <refpurpose>set the system clipboard</refpurpose>
    5.51 +  </refnamediv>
    5.52 +  <refsynopsisdiv>
    5.53 +    <cmdsynopsis>
    5.54 +      <command>pwm-clip</command>
    5.55 +    </cmdsynopsis>
    5.56 +  </refsynopsisdiv>
    5.57 +  <refsect1>
    5.58 +    <title>Description</title>
    5.59 +    <para>The <command>pwm-clip</command> utility reads from the standard input
    5.60 +    stream until it encounters a newline character or the stream is at
    5.61 +    end-of-file, then removes any newline character at the end and places the
    5.62 +    data in the system clipboard. On X11 systems it sets the CLIPBOARD
    5.63 +    selection.</para>
    5.64 +    <para>The following terminals are currently supported:
    5.65 +    <simplelist type="horiz" columns="3">
    5.66 +      <member>xterm</member>
    5.67 +      <member>tmux</member>
    5.68 +      <member>screen</member>
    5.69 +    </simplelist>
    5.70 +    </para>
    5.71 +    <para>If <command>pwm-clip</command> is invoked in an unsupported terminal
    5.72 +    it will print an error message and exit.</para>
    5.73 +  </refsect1>
    5.74 +  <refsect1>
    5.75 +    <title>Environment Variables</title>
    5.76 +    <variablelist>
    5.77 +      <varlistentry>
    5.78 +        <term>
    5.79 +          <literal>TERM</literal>
    5.80 +        </term>
    5.81 +        <listitem>
    5.82 +          <para>The name of the terminal used by <command>pwm-clip</command> to
    5.83 +          determine whether setting the system clipboard is supported</para>
    5.84 +        </listitem>
    5.85 +      </varlistentry>
    5.86 +    </variablelist>
    5.87 +  </refsect1>
    5.88 +  <refsect1>
    5.89 +    <title>Exit Status</title>
    5.90 +    <para>The following exit values are returned:</para>
    5.91 +    <variablelist>
    5.92 +      <varlistentry>
    5.93 +        <term>0</term>
    5.94 +        <listitem>
    5.95 +          <para>Command successfully executed.</para>
    5.96 +        </listitem>
    5.97 +      </varlistentry>
    5.98 +      <varlistentry>
    5.99 +        <term>1</term>
   5.100 +        <listitem>
   5.101 +          <para>An unspecified error has occured.</para>
   5.102 +        </listitem>
   5.103 +      </varlistentry>
   5.104 +      <varlistentry>
   5.105 +        <term>2</term>
   5.106 +        <listitem>
   5.107 +          <para>Invalid command line options were specified.</para>
   5.108 +        </listitem>
   5.109 +      </varlistentry>
   5.110 +    </variablelist>
   5.111 +  </refsect1>
   5.112 +  <refsect1>
   5.113 +    <title>See Also</title>
   5.114 +    <para><citerefentry><refentrytitle>pwm</refentrytitle>
   5.115 +      <manvolnum>1</manvolnum></citerefentry>,
   5.116 +      <citerefentry><refentrytitle>xterm</refentrytitle>
   5.117 +      <manvolnum>1</manvolnum></citerefentry>,
   5.118 +      <citerefentry><refentrytitle>tmux</refentrytitle>
   5.119 +      <manvolnum>1</manvolnum></citerefentry>,
   5.120 +      <citerefentry><refentrytitle>screen</refentrytitle>
   5.121 +      <manvolnum>1</manvolnum></citerefentry></para>
   5.122 +  </refsect1>
   5.123 +</refentry>
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/pwm-clip.c	Thu Sep 21 09:45:59 2017 +0200
     6.3 @@ -0,0 +1,176 @@
     6.4 +/*
     6.5 + * Copyright (C) 2017 Guido Berhoerster <guido+pwm@berhoerster.name>
     6.6 + *
     6.7 + * Permission is hereby granted, free of charge, to any person obtaining
     6.8 + * a copy of this software and associated documentation files (the
     6.9 + * "Software"), to deal in the Software without restriction, including
    6.10 + * without limitation the rights to use, copy, modify, merge, publish,
    6.11 + * distribute, sublicense, and/or sell copies of the Software, and to
    6.12 + * permit persons to whom the Software is furnished to do so, subject to
    6.13 + * the following conditions:
    6.14 + *
    6.15 + * The above copyright notice and this permission notice shall be included
    6.16 + * in all copies or substantial portions of the Software.
    6.17 + *
    6.18 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    6.19 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    6.20 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    6.21 + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    6.22 + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    6.23 + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    6.24 + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    6.25 + */
    6.26 +
    6.27 +#include "compat.h"
    6.28 +
    6.29 +#ifdef	HAVE_ERR_H
    6.30 +#include <err.h>
    6.31 +#endif /* HAVE_ERR_H */
    6.32 +#include <errno.h>
    6.33 +#include <nettle/base64.h>
    6.34 +#include <string.h>
    6.35 +#include <stdlib.h>
    6.36 +#include <stdio.h>
    6.37 +#include <unistd.h>
    6.38 +
    6.39 +#include "util.h"
    6.40 +
    6.41 +#define	CHUNK_SIZE	128
    6.42 +
    6.43 +static char *
    6.44 +base64_encode(const unsigned char *src, size_t size)
    6.45 +{
    6.46 +	char		*dst = NULL;
    6.47 +	struct base64_encode_ctx b64_ctx;
    6.48 +	size_t		len = 0;
    6.49 +
    6.50 +	dst = xmalloc(BASE64_ENCODE_LENGTH(size) +
    6.51 +	    BASE64_ENCODE_FINAL_LENGTH);
    6.52 +
    6.53 +	base64_encode_init(&b64_ctx);
    6.54 +	len += base64_encode_update(&b64_ctx, (unsigned char *)dst, size, src);
    6.55 +	len += base64_encode_final(&b64_ctx, (unsigned char *)dst);
    6.56 +	dst[len] = '\0';
    6.57 +
    6.58 +	dst = xrealloc(dst, len + 1);
    6.59 +
    6.60 +	return (dst);
    6.61 +}
    6.62 +
    6.63 +static void
    6.64 +set_clipboard(const char *s)
    6.65 +{
    6.66 +	char	*b64 = NULL;
    6.67 +
    6.68 +	b64 = base64_encode((const unsigned char *)s, strlen(s));
    6.69 +	printf("\033]52;c;%s\a\n", b64);
    6.70 +	free(b64);
    6.71 +}
    6.72 +
    6.73 +static void
    6.74 +set_clipboard_dcs_tmux(const char *s)
    6.75 +{
    6.76 +	char	*b64 = NULL;
    6.77 +
    6.78 +	b64 = base64_encode((const unsigned char *)s, strlen(s));
    6.79 +	printf("\033Ptmux;\033\033]52;c;%s\a\033\\", b64);
    6.80 +	free(b64);
    6.81 +}
    6.82 +
    6.83 +static void
    6.84 +set_clipboard_dcs_chunked(const char *s)
    6.85 +{
    6.86 +	char	*b64 = NULL;
    6.87 +	size_t	i;
    6.88 +
    6.89 +	b64 = base64_encode((const unsigned char *)s, strlen(s));
    6.90 +
    6.91 +	printf("\033P\033]52;c;");
    6.92 +	for (i = 0; b64[i] != '\0'; i++) {
    6.93 +		if ((i > 0) && (i % CHUNK_SIZE == 0)) {
    6.94 +			printf("\033\\\033P");
    6.95 +		}
    6.96 +		putchar(b64[i]);
    6.97 +	}
    6.98 +	printf("\a\033\\");
    6.99 +
   6.100 +	free(b64);
   6.101 +}
   6.102 +
   6.103 +static void
   6.104 +usage(void)
   6.105 +{
   6.106 +	fprintf(stderr, "usage: %s\n", getprogname());
   6.107 +}
   6.108 +
   6.109 +int
   6.110 +main(int argc, char *argv[])
   6.111 +{
   6.112 +	int		status = EXIT_FAILURE;
   6.113 +	char		*term;
   6.114 +	void (*set_clipboard_func)(const char *);
   6.115 +	int		errflag = 0;
   6.116 +	int		c;
   6.117 +	ssize_t		len;
   6.118 +	char		*s = NULL;
   6.119 +	size_t		size = 0;
   6.120 +
   6.121 +	setprogname(argv[0]);
   6.122 +
   6.123 +	term = getenv("TERM");
   6.124 +	if (term == NULL) {
   6.125 +		fprintf(stderr, "error: unknown terminal\n");
   6.126 +		goto out;
   6.127 +	} else if (strncmp(term, "xterm", strlen("xterm")) == 0) {
   6.128 +		set_clipboard_func = set_clipboard;
   6.129 +	} else if (strncmp(term, "tmux", strlen("tmux")) == 0) {
   6.130 +		set_clipboard_func = set_clipboard_dcs_tmux;
   6.131 +	} else if (strncmp(term, "screen", strlen("screen")) == 0) {
   6.132 +		if (getenv("TMUX") != NULL) {
   6.133 +			set_clipboard_func = set_clipboard_dcs_tmux;
   6.134 +		} else {
   6.135 +			set_clipboard_func = set_clipboard_dcs_chunked;
   6.136 +		}
   6.137 +	} else {
   6.138 +		fprintf(stderr, "terminal does not support setting "
   6.139 +		    "X11 CLIPBOARD selection\n");
   6.140 +		goto out;
   6.141 +	}
   6.142 +
   6.143 +	while (!errflag && (c = getopt(argc, argv, "h")) != -1) {
   6.144 +		switch (c) {
   6.145 +		case 'h':
   6.146 +			usage();
   6.147 +			exit(EXIT_SUCCESS);
   6.148 +		default:
   6.149 +			errflag = 1;
   6.150 +		}
   6.151 +	}
   6.152 +	if (errflag || (optind + 1 < argc)) {
   6.153 +		usage();
   6.154 +		exit(EXIT_USAGE);
   6.155 +	}
   6.156 +
   6.157 +	errno = 0;
   6.158 +	len = getline(&s, &size, stdin);
   6.159 +	if (len < 0) {
   6.160 +		if (errno == 0) {
   6.161 +			fprintf(stderr, "failed to read line\n");
   6.162 +			goto out;
   6.163 +		} else {
   6.164 +			err(1, "getline");
   6.165 +		}
   6.166 +	}
   6.167 +	if ((len > 0) && (s[len - 1] == '\n')) {
   6.168 +		s[--len] = '\0';
   6.169 +	}
   6.170 +
   6.171 +	set_clipboard_func(s);
   6.172 +
   6.173 +	status = EXIT_SUCCESS;
   6.174 +
   6.175 +out:
   6.176 +	free(s);
   6.177 +
   6.178 +	exit(status);
   6.179 +}
     7.1 --- a/pwm.1.xml	Wed Sep 20 23:57:51 2017 +0200
     7.2 +++ b/pwm.1.xml	Thu Sep 21 09:45:59 2017 +0200
     7.3 @@ -74,8 +74,10 @@
     7.4      <command>pwm</command> provides commands to create, modify, delete, and
     7.5      display password database entries which may be organized in groups.  The
     7.6      contents of a field of a given entry can also be piped to an external
     7.7 -    command, e.g. in order to copy the content of the username or password
     7.8 -    field of an entry to the clipboard.</para>
     7.9 +    command such as the <citerefentry><refentrytitle>pwm-clip</refentrytitle>
    7.10 +    <manvolnum>1</manvolnum></citerefentry> utility in order to copy the
    7.11 +    content of the username or password field of an entry to the
    7.12 +    clipboard.</para>
    7.13      <para>If specified, <command>pwm</command> will open or create
    7.14      <replaceable>database_file</replaceable> instead of the user's default
    7.15      database.</para>
    7.16 @@ -672,7 +674,9 @@
    7.17    </refsect1>
    7.18    <refsect1>
    7.19      <title>See Also</title>
    7.20 -    <para><citerefentry><refentrytitle>pwsafe</refentrytitle>
    7.21 +    <para><citerefentry><refentrytitle>pwm-clip</refentrytitle>
    7.22 +      <manvolnum>1</manvolnum></citerefentry>,
    7.23 +      <citerefentry><refentrytitle>pwsafe</refentrytitle>
    7.24        <manvolnum>1</manvolnum></citerefentry>,
    7.25        <citerefentry><refentrytitle>sh</refentrytitle>
    7.26        <manvolnum>1</manvolnum></citerefentry>,