projects/pwm

annotate pwm-clip.c @ 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
children
rev   line source
guido+pwm@26 1 /*
guido+pwm@26 2 * Copyright (C) 2017 Guido Berhoerster <guido+pwm@berhoerster.name>
guido+pwm@26 3 *
guido+pwm@26 4 * Permission is hereby granted, free of charge, to any person obtaining
guido+pwm@26 5 * a copy of this software and associated documentation files (the
guido+pwm@26 6 * "Software"), to deal in the Software without restriction, including
guido+pwm@26 7 * without limitation the rights to use, copy, modify, merge, publish,
guido+pwm@26 8 * distribute, sublicense, and/or sell copies of the Software, and to
guido+pwm@26 9 * permit persons to whom the Software is furnished to do so, subject to
guido+pwm@26 10 * the following conditions:
guido+pwm@26 11 *
guido+pwm@26 12 * The above copyright notice and this permission notice shall be included
guido+pwm@26 13 * in all copies or substantial portions of the Software.
guido+pwm@26 14 *
guido+pwm@26 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
guido+pwm@26 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
guido+pwm@26 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
guido+pwm@26 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
guido+pwm@26 19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
guido+pwm@26 20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
guido+pwm@26 21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
guido+pwm@26 22 */
guido+pwm@26 23
guido+pwm@26 24 #include "compat.h"
guido+pwm@26 25
guido+pwm@26 26 #ifdef HAVE_ERR_H
guido+pwm@26 27 #include <err.h>
guido+pwm@26 28 #endif /* HAVE_ERR_H */
guido+pwm@26 29 #include <errno.h>
guido+pwm@26 30 #include <nettle/base64.h>
guido+pwm@26 31 #include <string.h>
guido+pwm@26 32 #include <stdlib.h>
guido+pwm@26 33 #include <stdio.h>
guido+pwm@26 34 #include <unistd.h>
guido+pwm@26 35
guido+pwm@26 36 #include "util.h"
guido+pwm@26 37
guido+pwm@26 38 #define CHUNK_SIZE 128
guido+pwm@26 39
guido+pwm@26 40 static char *
guido+pwm@26 41 base64_encode(const unsigned char *src, size_t size)
guido+pwm@26 42 {
guido+pwm@26 43 char *dst = NULL;
guido+pwm@26 44 struct base64_encode_ctx b64_ctx;
guido+pwm@26 45 size_t len = 0;
guido+pwm@26 46
guido+pwm@26 47 dst = xmalloc(BASE64_ENCODE_LENGTH(size) +
guido+pwm@26 48 BASE64_ENCODE_FINAL_LENGTH);
guido+pwm@26 49
guido+pwm@26 50 base64_encode_init(&b64_ctx);
guido+pwm@26 51 len += base64_encode_update(&b64_ctx, (unsigned char *)dst, size, src);
guido+pwm@26 52 len += base64_encode_final(&b64_ctx, (unsigned char *)dst);
guido+pwm@26 53 dst[len] = '\0';
guido+pwm@26 54
guido+pwm@26 55 dst = xrealloc(dst, len + 1);
guido+pwm@26 56
guido+pwm@26 57 return (dst);
guido+pwm@26 58 }
guido+pwm@26 59
guido+pwm@26 60 static void
guido+pwm@26 61 set_clipboard(const char *s)
guido+pwm@26 62 {
guido+pwm@26 63 char *b64 = NULL;
guido+pwm@26 64
guido+pwm@26 65 b64 = base64_encode((const unsigned char *)s, strlen(s));
guido+pwm@26 66 printf("\033]52;c;%s\a\n", b64);
guido+pwm@26 67 free(b64);
guido+pwm@26 68 }
guido+pwm@26 69
guido+pwm@26 70 static void
guido+pwm@26 71 set_clipboard_dcs_tmux(const char *s)
guido+pwm@26 72 {
guido+pwm@26 73 char *b64 = NULL;
guido+pwm@26 74
guido+pwm@26 75 b64 = base64_encode((const unsigned char *)s, strlen(s));
guido+pwm@26 76 printf("\033Ptmux;\033\033]52;c;%s\a\033\\", b64);
guido+pwm@26 77 free(b64);
guido+pwm@26 78 }
guido+pwm@26 79
guido+pwm@26 80 static void
guido+pwm@26 81 set_clipboard_dcs_chunked(const char *s)
guido+pwm@26 82 {
guido+pwm@26 83 char *b64 = NULL;
guido+pwm@26 84 size_t i;
guido+pwm@26 85
guido+pwm@26 86 b64 = base64_encode((const unsigned char *)s, strlen(s));
guido+pwm@26 87
guido+pwm@26 88 printf("\033P\033]52;c;");
guido+pwm@26 89 for (i = 0; b64[i] != '\0'; i++) {
guido+pwm@26 90 if ((i > 0) && (i % CHUNK_SIZE == 0)) {
guido+pwm@26 91 printf("\033\\\033P");
guido+pwm@26 92 }
guido+pwm@26 93 putchar(b64[i]);
guido+pwm@26 94 }
guido+pwm@26 95 printf("\a\033\\");
guido+pwm@26 96
guido+pwm@26 97 free(b64);
guido+pwm@26 98 }
guido+pwm@26 99
guido+pwm@26 100 static void
guido+pwm@26 101 usage(void)
guido+pwm@26 102 {
guido+pwm@26 103 fprintf(stderr, "usage: %s\n", getprogname());
guido+pwm@26 104 }
guido+pwm@26 105
guido+pwm@26 106 int
guido+pwm@26 107 main(int argc, char *argv[])
guido+pwm@26 108 {
guido+pwm@26 109 int status = EXIT_FAILURE;
guido+pwm@26 110 char *term;
guido+pwm@26 111 void (*set_clipboard_func)(const char *);
guido+pwm@26 112 int errflag = 0;
guido+pwm@26 113 int c;
guido+pwm@26 114 ssize_t len;
guido+pwm@26 115 char *s = NULL;
guido+pwm@26 116 size_t size = 0;
guido+pwm@26 117
guido+pwm@26 118 setprogname(argv[0]);
guido+pwm@26 119
guido+pwm@26 120 term = getenv("TERM");
guido+pwm@26 121 if (term == NULL) {
guido+pwm@26 122 fprintf(stderr, "error: unknown terminal\n");
guido+pwm@26 123 goto out;
guido+pwm@26 124 } else if (strncmp(term, "xterm", strlen("xterm")) == 0) {
guido+pwm@26 125 set_clipboard_func = set_clipboard;
guido+pwm@26 126 } else if (strncmp(term, "tmux", strlen("tmux")) == 0) {
guido+pwm@26 127 set_clipboard_func = set_clipboard_dcs_tmux;
guido+pwm@26 128 } else if (strncmp(term, "screen", strlen("screen")) == 0) {
guido+pwm@26 129 if (getenv("TMUX") != NULL) {
guido+pwm@26 130 set_clipboard_func = set_clipboard_dcs_tmux;
guido+pwm@26 131 } else {
guido+pwm@26 132 set_clipboard_func = set_clipboard_dcs_chunked;
guido+pwm@26 133 }
guido+pwm@26 134 } else {
guido+pwm@26 135 fprintf(stderr, "terminal does not support setting "
guido+pwm@26 136 "X11 CLIPBOARD selection\n");
guido+pwm@26 137 goto out;
guido+pwm@26 138 }
guido+pwm@26 139
guido+pwm@26 140 while (!errflag && (c = getopt(argc, argv, "h")) != -1) {
guido+pwm@26 141 switch (c) {
guido+pwm@26 142 case 'h':
guido+pwm@26 143 usage();
guido+pwm@26 144 exit(EXIT_SUCCESS);
guido+pwm@26 145 default:
guido+pwm@26 146 errflag = 1;
guido+pwm@26 147 }
guido+pwm@26 148 }
guido+pwm@26 149 if (errflag || (optind + 1 < argc)) {
guido+pwm@26 150 usage();
guido+pwm@26 151 exit(EXIT_USAGE);
guido+pwm@26 152 }
guido+pwm@26 153
guido+pwm@26 154 errno = 0;
guido+pwm@26 155 len = getline(&s, &size, stdin);
guido+pwm@26 156 if (len < 0) {
guido+pwm@26 157 if (errno == 0) {
guido+pwm@26 158 fprintf(stderr, "failed to read line\n");
guido+pwm@26 159 goto out;
guido+pwm@26 160 } else {
guido+pwm@26 161 err(1, "getline");
guido+pwm@26 162 }
guido+pwm@26 163 }
guido+pwm@26 164 if ((len > 0) && (s[len - 1] == '\n')) {
guido+pwm@26 165 s[--len] = '\0';
guido+pwm@26 166 }
guido+pwm@26 167
guido+pwm@26 168 set_clipboard_func(s);
guido+pwm@26 169
guido+pwm@26 170 status = EXIT_SUCCESS;
guido+pwm@26 171
guido+pwm@26 172 out:
guido+pwm@26 173 free(s);
guido+pwm@26 174
guido+pwm@26 175 exit(status);
guido+pwm@26 176 }