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