1 /*
2 * xcut.c Manipulate X cut buffers from command line.
3 *
4 * Copyright (C) Tim Potter, 1998-1999
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id: xcut.c,v 1.4 1999/09/21 05:55:33 tpot Exp $
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26
27 #include <X11/X.h>
28 #include <X11/Xlib.h>
29 #include <X11/Xatom.h>
30
31 #define BUFSIZE 65535 /* Buffer size for reading input */
32
33 /* Print program usage information */
34
usage(char * progname)35 void usage(char *progname)
36 {
37 fprintf(stderr, "usage: %s [options]\n", progname);
38 fprintf(stderr, "\t-display displayname\tserver to connect to\n");
39 fprintf(stderr, "\t-p\t\t\tpaste cut buffer to stdout\n");
40 exit(1);
41 }
42
43 /* Cut from stdin */
44
cut(char * progname,Display * display)45 void cut(char *progname, Display *display)
46 {
47 char *file_buffer, *cut_buffer;
48 int nread, cut_size;
49
50 file_buffer = malloc(BUFSIZE);
51 cut_buffer = NULL;
52
53 cut_size = 0;
54
55 /* Store all of standard input */
56
57 while((nread = read(STDIN_FILENO, file_buffer, BUFSIZE)) > 0) {
58
59 /* Add to cut buffer */
60
61 cut_size += nread;
62 cut_buffer = realloc(cut_buffer, cut_size);
63 memcpy(&cut_buffer[cut_size - nread], file_buffer, nread);
64 }
65
66 /* Error processing */
67
68 if (nread == -1) {
69 perror(progname);
70 exit(2);
71 }
72
73 /* Perform the cut. If we don't call XSetSelectionOwner() before
74 doing the cut, existing selections are not overridden. */
75
76 XSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
77 XStoreBytes(display, cut_buffer, cut_size);
78
79 /* Clean up */
80
81 free(cut_buffer);
82 free(file_buffer);
83 }
84
85 /* Paste to stdout */
86
paste(char * progname,Display * display)87 void paste(char *progname, Display *display)
88 {
89 char *buffer;
90 int nbytes, num_written = 0;
91
92 if ((buffer = XFetchBytes(display, &nbytes)) != NULL) {
93
94 /* Send data to stdout */
95
96 do {
97 num_written += write(STDOUT_FILENO, buffer + num_written, nbytes - num_written);
98 } while (num_written < nbytes);
99
100 /* Clean up */
101
102 XFree(buffer);
103 }
104 }
105
106 /*
107 * Main program
108 */
109
main(int argc,char * argv[])110 int main (int argc, char *argv[])
111 {
112 Display *display;
113 char *displayname = NULL, *progname;
114 int i, do_paste = 0;
115
116 /* Parse command line arguments */
117
118 progname = argv[0];
119
120 for (i = 1; i < argc; i++) {
121 char *arg = argv[i];
122
123 if (strcmp("-display", arg) == 0) {
124 if (++i >= argc) usage(progname);
125 displayname = argv[i];
126 continue;
127 } else if (strcmp("-p", arg) == 0) {
128 do_paste = 1;
129 continue;
130 }
131
132 fprintf(stderr, "unknown option '%s'\n", arg);
133 usage(progname);
134 }
135
136
137 /* Open display */
138
139 if ((display = XOpenDisplay(displayname)) == NULL) {
140 fprintf(stderr, "%s: unable to open display %s\n", progname,
141 displayname);
142 exit(2);
143 }
144
145 /* Perform operation */
146
147 if (do_paste) {
148 paste(progname, display);
149 } else {
150 cut(progname, display);
151 }
152
153 /* Clean up and exit */
154
155 XCloseDisplay(display);
156 exit(0);
157 }
158