123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- /*
- *
- Copyright 1989, 1998 The Open Group
- Copyright 2009 Open Text Corporation
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Except as contained in this notice, the name of The Open Group shall not be
- used in advertising or otherwise to promote the sale, use or other dealings
- in this Software without prior written authorization from The Open Group.
- *
- * Author: Jim Fulton, MIT X Consortium
- * Author: Peter Harris, Open Text Corporation
- */
- #ifdef HAVE_CONFIG_H
- # include "config.h"
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <xcb/xcb.h>
- #include <xcb/xproto.h>
- #define ATOMS_PER_BATCH 100 /* This number can be tuned
- higher for fewer round-trips
- lower for less bandwidth wasted */
- static const char *ProgramName;
- static const char *DisplayString;
- static void do_name ( xcb_connection_t *c, const char *format, char *name );
- static int parse_range ( char *range, long *lowp, long *highp );
- static void do_range ( xcb_connection_t *c, const char *format, char *range );
- static void list_atoms ( xcb_connection_t *c, const char *format, int mask,
- long low, long high );
- static void
- usage(const char *errmsg)
- {
- if (errmsg != NULL)
- fprintf (stderr, "%s: %s\n\n", ProgramName, errmsg);
- fprintf (stderr, "usage: %s [-options...]\n\n%s\n", ProgramName,
- "where options include:\n"
- " -display dpy X server to which to connect\n"
- " -format string printf-style format to use\n"
- " -range [num]-[num] atom values to list\n"
- " -name string name of single atom to print\n"
- " -version print program version\n"
- );
- exit (1);
- }
- int
- main(int argc, char *argv[])
- {
- char *displayname = NULL;
- const char *format = "%lu\t%s";
- int i, doit;
- int didit = 0;
- xcb_connection_t *c = NULL;
- ProgramName = argv[0];
- for (doit = 0; doit < 2; doit++) { /* pre-parse to get display */
- for (i = 1; i < argc; i++) {
- char *arg = argv[i];
- if (arg[0] == '-') {
- switch (arg[1]) {
- case 'd': /* -display dpy */
- if (++i >= argc) usage ("-display requires an argument");
- if (!doit) displayname = argv[i];
- continue;
- case 'f': /* -format string */
- if (++i >= argc) usage ("-format requires an argument");
- if (doit) format = argv[i];
- continue;
- case 'r': /* -range num-[num] */
- if (++i >= argc) usage ("-range requires an argument");
- if (doit) {
- do_range (c, format, argv[i]);
- didit = 1;
- }
- continue;
- case 'n': /* -name string */
- if (++i >= argc) usage ("-name requires an argument");
- if (doit) {
- do_name (c, format, argv[i]);
- didit = 1;
- }
- continue;
- case 'v':
- if (strcmp(arg, "-version") == 0) {
- puts(PACKAGE_STRING);
- exit(0);
- }
- /* else FALLTHROUGH to unrecognized arg case below */
- }
- }
- fprintf (stderr, "%s: unrecognized argument %s\n\n",
- ProgramName, arg);
- usage (NULL);
- }
- if (!doit) {
- DisplayString = displayname;
- if (!DisplayString)
- DisplayString = getenv("DISPLAY");
- if (!DisplayString)
- DisplayString = "";
- c = xcb_connect(displayname, NULL);
- if (!c || xcb_connection_has_error(c)) {
- fprintf (stderr, "%s: unable to open display \"%s\"\n",
- ProgramName, DisplayString);
- exit (1);
- }
- } else
- if (!didit) /* no options, default is list all */
- list_atoms(c, format, 0, 0, 0);
- }
- xcb_disconnect(c);
- exit (0);
- }
- static void
- do_name(xcb_connection_t *c, const char *format, char *name)
- {
- xcb_intern_atom_reply_t *a = xcb_intern_atom_reply(c,
- xcb_intern_atom_unchecked(c, 1, strlen(name), name), NULL);
- if (a && a->atom != XCB_NONE) {
- printf (format, (unsigned long) a->atom, name);
- putchar ('\n');
- } else {
- fprintf (stderr, "%s: no atom named \"%s\" on server \"%s\"\n",
- ProgramName, name, DisplayString);
- }
- if (a)
- free(a);
- }
- #define RangeLow (1 << 0)
- #define RangeHigh (1 << 1)
- static int
- parse_range(char *range, long *lowp, long *highp)
- {
- char *dash;
- int mask = 0;
- if (!range) { /* NULL means default */
- *lowp = 1;
- return RangeLow;
- }
- dash = strchr(range, '-');
- if (!dash) dash = strchr(range, ':');
- if (dash) {
- if (dash == range) { /* -high */
- *lowp = 1;
- } else { /* low-[high] */
- *dash = '\0';
- *lowp = atoi (range);
- *dash = '-';
- }
- mask |= RangeLow;
- dash++;
- if (*dash) { /* [low]-high */
- *highp = atoi (dash);
- mask |= RangeHigh;
- }
- } else { /* number (low == high) */
- *lowp = *highp = atoi (range);
- mask |= (RangeLow | RangeHigh);
- }
- return mask;
- }
- static void
- do_range(xcb_connection_t *c, const char *format, char *range)
- {
- int mask;
- long low, high;
- mask = parse_range (range, &low, &high);
- list_atoms (c, format, mask, low, high);
- }
- static int
- say_batch(xcb_connection_t *c, const char *format, xcb_get_atom_name_cookie_t *cookie, long low, long count)
- {
- xcb_generic_error_t *e;
- char atom_name[1024];
- long i;
- int done = 0;
- for (i = 0; i < count; i++)
- cookie[i] = xcb_get_atom_name(c, i + low);
- for (i = 0; i < count; i++) {
- xcb_get_atom_name_reply_t *r;
- r = xcb_get_atom_name_reply(c, cookie[i], &e);
- if (r) {
- /* We could just use %.*s in 'format', but we want to be compatible
- with legacy command line usage */
- snprintf(atom_name, sizeof(atom_name), "%.*s",
- r->name_len, xcb_get_atom_name_name(r));
- printf (format, i + low, atom_name);
- putchar ('\n');
- free(r);
- }
- if (e) {
- done = 1;
- free(e);
- }
- }
- return done;
- }
- static void
- list_atoms(xcb_connection_t *c, const char *format, int mask, long low, long high)
- {
- xcb_get_atom_name_cookie_t *cookie_jar;
- int done = 0;
- switch (mask) {
- case RangeHigh:
- low = 1;
- /* fall through */
- case (RangeLow | RangeHigh):
- cookie_jar = malloc((high - low + 1) * sizeof(xcb_get_atom_name_cookie_t));
- if (!cookie_jar) {
- fprintf(stderr, "Out of memory allocating space for %ld atom requests\n", high - low);
- return;
- }
- say_batch(c, format, cookie_jar, low, high - low + 1);
- free(cookie_jar);
- break;
- default:
- low = 1;
- /* fall through */
- case RangeLow:
- cookie_jar = malloc(ATOMS_PER_BATCH * sizeof(xcb_get_atom_name_cookie_t));
- if (!cookie_jar) {
- fprintf(stderr, "Out of memory allocating space for %ld atom requests\n", (long) ATOMS_PER_BATCH);
- return;
- }
- while (!done) {
- done = say_batch(c, format, cookie_jar, low, ATOMS_PER_BATCH);
- low += ATOMS_PER_BATCH;
- }
- free(cookie_jar);
- break;
- }
- return;
- }
|