#include #include extern const char *__progname; #include #include static const char *dispstr = 0; #define OM_UNSPEC 1 #define OM_SET 2 #define OM_QUERY 3 static int opmode = OM_UNSPEC; static int args_c; static char **args_v; static Display *disp; static void usage(void) { fprintf(stderr,"Usage: %s [options] [operation] [arguments]\n",__progname); fprintf(stderr,"options:\n"); fprintf(stderr," -display DISP set display to connect to\n"); fprintf(stderr,"operation and arguments:\n"); fprintf(stderr," -set WINDOWID PROPERTY-NAME TYPE SIZE [DATA...]\n"); fprintf(stderr," -query WINDOWID PROPERTY-NAME [FORMAT...]\n"); fprintf(stderr,"WINDOWID is a window ID number, or the word `root'\n"); fprintf(stderr,"PROPERTY-NAME is a string naming the property\n"); fprintf(stderr,"TYPE is a string naming the property's type\n"); fprintf(stderr,"SIZE is 8, 16, or 32\n"); fprintf(stderr,"DATA is zero or more numbers, or if SIZE is `string', a string\n"); fprintf(stderr,"FORMAT is zero or more format specifiers:\n"); fprintf(stderr," x print next element in hex\n"); exit(1); } static void handleargs(int ac, char **av) { int skip; int errs; skip = 0; errs = 0; if (0) { needarg:; fprintf(stderr,"%s: %s needs a following argument\n",__progname,*av); exit(1); } for (ac--,av++;;ac--,av++) { if (ac < 1) usage(); if (skip > 0) { skip --; continue; } #define WANTARG() do { if (++skip >= ac) goto needarg; } while (0) if (!strcmp(*av,"-display")) { WANTARG(); dispstr = av[skip]; continue; } if (!strcmp(*av,"-set")) { opmode = OM_SET; break; } if (!strcmp(*av,"-query")) { opmode = OM_QUERY; break; } fprintf(stderr,"%s: unrecognized operation `%s'\n",__progname,*av); errs ++; #undef WANTARG } ac --; av ++; if (errs) { usage(); exit(1); } switch (opmode) { case OM_UNSPEC: usage(); break; case OM_SET: if (ac < 4) usage(); args_c = ac; args_v = av; break; case OM_QUERY: if (ac < 2) usage(); args_c = ac; args_v = av; break; default: abort(); break; } } static void opendisp(void) { disp = XOpenDisplay(dispstr); if (! disp) { fprintf(stderr,"%s: can't open display",__progname); if (dispstr) fprintf(stderr," `%s'",dispstr); fprintf(stderr,"\n"); exit(1); } } static Window getwindowid(const char *s) { char *ep; unsigned long int v; if (!strcmp(s,"root")) return(XRootWindowOfScreen(XDefaultScreenOfDisplay(disp))); v = strtoul(s,&ep,0); if (*ep || (ep == s)) { fprintf(stderr,"%s: invalid window ID `%s'\n",__progname,s); exit(1); } return((Window)v); } static int get_size(const char *s) { long int v; char *ep; static void invalid(void) __attribute__((__noreturn__)); static void invalid(void) { fprintf(stderr,"%s: invalid size `%s'\n",__progname,s); usage(); exit(1); } v = strtol(s,&ep,0); if (*ep || (ep == s)) invalid(); switch (v) { case 8: case 16: case 32: return(v); break; } invalid(); } static void set_value(void *place, const char *valstr, int size) { unsigned long int v; char *ep; v = strtoul(valstr,&ep,0); if (*ep || (ep == valstr)) { fprintf(stderr,"%s: invalid value `%s'\n",__progname,valstr); usage(); } if ((v >> (size*4)) >> (size*4)) { fprintf(stderr,"%s: value `%s' out of range\n",__progname,valstr); usage(); } switch (size) { case 1: *(unsigned char *)place = v; break; case 2: *(unsigned short int *)place = v; break; case 4: *(unsigned int *)place = v; break; default: abort(); break; } } static void do_set(void) { Window win; const char *propname; const char *typename; int size; int n; int i; unsigned char *databuf; Atom pn; Atom tn; if (args_c < 4) abort(); opendisp(); win = getwindowid(args_v[0]); propname = args_v[1]; size = get_size(args_v[2]) >> 3; typename = args_v[3]; n = args_c - 4; databuf = malloc(n*size); for (i=0;i 0) && (ac > 0)) { v = (*fetch)(data); data += inc; if (!strcmp(*av,"x")) { printf("%#x\n",v); } else { fprintf(stderr,"%s: bad format spec `%s'\n",__progname,*av); exit(1); } samples --; ac --; av ++; } } static unsigned int fetch_8(const unsigned char *data) { return(*data); } static unsigned int fetch_16(const unsigned char *data) { return(*(const unsigned short int *)data); } static unsigned int fetch_32(const unsigned char *data) { return(*(const unsigned int *)data); } static void do_query(void) { Window win; const char *propname; Atom pn; Atom type; int format; unsigned long int returned; unsigned long int left; unsigned char *value; if (args_c < 2) abort(); opendisp(); win = getwindowid(args_v[0]); propname = args_v[1]; pn = XInternAtom(disp,propname,True); if (pn == None) { fprintf(stderr,"%s: no property `%s' found\n",__progname,propname); exit(1); } if (XGetWindowProperty(disp,win,pn,0,0,False,AnyPropertyType,&type,&format,&returned,&left,&value) != Success) { fprintf(stderr,"%s: XGetWindowProperty failed\n",__progname); exit(1); } XFree(value); if (type == None) { fprintf(stderr,"%s: no property `%s' found\n",__progname,propname); exit(1); } if (left > 65536) { fprintf(stderr,"%s: property `%s' too long\n",__progname,propname); exit(1); } if (XGetWindowProperty(disp,win,pn,0,(left+3)>>2,False,AnyPropertyType,&type,&format,&returned,&left,&value) != Success) { fprintf(stderr,"%s: XGetWindowProperty failed\n",__progname); exit(1); } if (left > 0) { fprintf(stderr,"%s: property `%s' grew\n",__progname,propname); exit(1); } switch (format) { case 8: print_data(value,returned,fetch_8,1,args_c-2,args_v+2); break; case 16: print_data(value,returned,fetch_16,2,args_c-2,args_v+2); break; case 32: print_data(value,returned,fetch_32,4,args_c-2,args_v+2); break; default: fprintf(stderr,"%s: property `%s' has impossible format %d\n",__progname,propname,format); break; } } int main(int, char **); int main(int ac, char **av) { handleargs(ac,av); switch (opmode) { case OM_SET: do_set(); break; case OM_QUERY: do_query(); break; default: abort(); break; } exit(0); }