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