xlsatoms.c revision f5effb2e
1/* 2 * 3Copyright 1989, 1998 The Open Group 4Copyright 2009 Open Text Corporation 5 6Permission to use, copy, modify, distribute, and sell this software and its 7documentation for any purpose is hereby granted without fee, provided that 8the above copyright notice appear in all copies and that both that 9copyright notice and this permission notice appear in supporting 10documentation. 11 12The above copyright notice and this permission notice shall be included in 13all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall not be 23used in advertising or otherwise to promote the sale, use or other dealings 24in this Software without prior written authorization from The Open Group. 25 * 26 * Author: Jim Fulton, MIT X Consortium 27 * Author: Peter Harris, Open Text Corporation 28 */ 29 30#include <stdio.h> 31#include <stdlib.h> 32#include <string.h> 33#include <xcb/xcb.h> 34#include <xcb/xproto.h> 35 36#define ATOMS_PER_BATCH 100 /* This number can be tuned 37 higher for fewer round-trips 38 lower for less bandwidth wasted */ 39 40static char *ProgramName; 41static char *DisplayString; 42 43static void do_name ( xcb_connection_t *c, char *format, char *name ); 44static int parse_range ( char *range, long *lowp, long *highp ); 45static void do_range ( xcb_connection_t *c, char *format, char *range ); 46static void list_atoms ( xcb_connection_t *c, char *format, int mask, 47 long low, long high ); 48 49static void 50usage(void) 51{ 52 fprintf (stderr, "usage: %s [-options...]\n\n", ProgramName); 53 fprintf (stderr, "where options include:\n"); 54 fprintf (stderr, 55 " -display dpy X server to which to connect\n"); 56 fprintf (stderr, 57 " -format string printf-style format to use\n"); 58 fprintf (stderr, 59 " -range [num]-[num] atom values to list\n"); 60 fprintf (stderr, 61 " -name string name of single atom to print\n"); 62 putc ('\n', stderr); 63 exit (1); 64} 65 66int 67main(int argc, char *argv[]) 68{ 69 char *displayname = NULL; 70 char *format = "%lu\t%s"; 71 int i, doit; 72 int didit = 0; 73 xcb_connection_t *c = NULL; 74 75 ProgramName = argv[0]; 76 77 for (doit = 0; doit < 2; doit++) { /* pre-parse to get display */ 78 for (i = 1; i < argc; i++) { 79 char *arg = argv[i]; 80 81 if (arg[0] == '-') { 82 switch (arg[1]) { 83 case 'd': /* -display dpy */ 84 if (++i >= argc) usage (); 85 if (!doit) displayname = argv[i]; 86 continue; 87 case 'f': /* -format string */ 88 if (++i >= argc) usage (); 89 if (doit) format = argv[i]; 90 continue; 91 case 'r': /* -range num-[num] */ 92 if (++i >= argc) usage (); 93 if (doit) { 94 do_range (c, format, argv[i]); 95 didit = 1; 96 } 97 continue; 98 case 'n': /* -name string */ 99 if (++i >= argc) usage (); 100 if (doit) { 101 do_name (c, format, argv[i]); 102 didit = 1; 103 } 104 continue; 105 } 106 } 107 usage (); 108 } 109 if (!doit) { 110 DisplayString = displayname; 111 if (!DisplayString) 112 DisplayString = getenv("DISPLAY"); 113 if (!DisplayString) 114 DisplayString = ""; 115 c = xcb_connect(displayname, NULL); 116 if (!c || xcb_connection_has_error(c)) { 117 fprintf (stderr, "%s: unable to open display \"%s\"\n", 118 ProgramName, DisplayString); 119 exit (1); 120 } 121 } else 122 if (!didit) /* no options, default is list all */ 123 list_atoms(c, format, 0, 0, 0); 124 } 125 126 xcb_disconnect(c); 127 exit (0); 128} 129 130static void 131do_name(xcb_connection_t *c, char *format, char *name) 132{ 133 xcb_intern_atom_reply_t *a = xcb_intern_atom_reply(c, 134 xcb_intern_atom_unchecked(c, 1, strlen(name), name), NULL); 135 136 if (a && a->atom != XCB_NONE) { 137 printf (format, (unsigned long) a->atom, name); 138 putchar ('\n'); 139 } else { 140 fprintf (stderr, "%s: no atom named \"%s\" on server \"%s\"\n", 141 ProgramName, name, DisplayString); 142 } 143 144 if (a) 145 free(a); 146} 147 148 149#define RangeLow (1 << 0) 150#define RangeHigh (1 << 1) 151 152static int 153parse_range(char *range, long *lowp, long *highp) 154{ 155 char *dash; 156 int mask = 0; 157 158 if (!range) { /* NULL means default */ 159 *lowp = 1; 160 return RangeLow; 161 } 162 163 dash = strchr(range, '-'); 164 if (!dash) dash = strchr(range, ':'); 165 if (dash) { 166 if (dash == range) { /* -high */ 167 *lowp = 1; 168 } else { /* low-[high] */ 169 *dash = '\0'; 170 *lowp = atoi (range); 171 *dash = '-'; 172 } 173 mask |= RangeLow; 174 dash++; 175 if (*dash) { /* [low]-high */ 176 *highp = atoi (dash); 177 mask |= RangeHigh; 178 } 179 } else { /* number (low == high) */ 180 *lowp = *highp = atoi (range); 181 mask |= (RangeLow | RangeHigh); 182 } 183 184 return mask; 185} 186 187static void 188do_range(xcb_connection_t *c, char *format, char *range) 189{ 190 int mask; 191 long low, high; 192 193 mask = parse_range (range, &low, &high); 194 list_atoms (c, format, mask, low, high); 195} 196 197static int 198say_batch(xcb_connection_t *c, char *format, xcb_get_atom_name_cookie_t *cookie, long low, long count) 199{ 200 xcb_generic_error_t *e; 201 char atom_name[1024]; 202 long i; 203 int done = 0; 204 205 for (i = 0; i < count; i++) 206 cookie[i] = xcb_get_atom_name(c, i + low); 207 208 for (i = 0; i < count; i++) { 209 xcb_get_atom_name_reply_t *r; 210 r = xcb_get_atom_name_reply(c, cookie[i], &e); 211 if (r) { 212 /* We could just use %.*s in 'format', but we want to be compatible 213 with legacy command line usage */ 214 snprintf(atom_name, sizeof(atom_name), "%.*s", 215 r->name_len, xcb_get_atom_name_name(r)); 216 217 printf (format, i + low, atom_name); 218 putchar ('\n'); 219 free(r); 220 } 221 if (e) { 222 done = 1; 223 free(e); 224 } 225 } 226 227 return done; 228} 229 230static void 231list_atoms(xcb_connection_t *c, char *format, int mask, long low, long high) 232{ 233 xcb_get_atom_name_cookie_t *cookie_jar; 234 int done = 0; 235 236 switch (mask) { 237 case RangeHigh: 238 low = 1; 239 /* fall through */ 240 case (RangeLow | RangeHigh): 241 cookie_jar = malloc((high - low + 1) * sizeof(xcb_get_atom_name_cookie_t)); 242 if (!cookie_jar) { 243 fprintf(stderr, "Out of memory allocating space for %ld atom requests\n", high - low); 244 return; 245 } 246 247 say_batch(c, format, cookie_jar, low, high - low + 1); 248 free(cookie_jar); 249 break; 250 251 default: 252 low = 1; 253 /* fall through */ 254 case RangeLow: 255 cookie_jar = malloc(ATOMS_PER_BATCH * sizeof(xcb_get_atom_name_cookie_t)); 256 if (!cookie_jar) { 257 fprintf(stderr, "Out of memory allocating space for %ld atom requests\n", (long) ATOMS_PER_BATCH); 258 return; 259 } 260 while (!done) { 261 done = say_batch(c, format, cookie_jar, low, ATOMS_PER_BATCH); 262 low += ATOMS_PER_BATCH; 263 } 264 free(cookie_jar); 265 break; 266 } 267 268 return; 269} 270