xlsclients.c revision 70f7c90c
1/* 2 * $Xorg: xlsclients.c,v 1.4 2001/02/09 02:05:54 xorgcvs Exp $ 3 * 4 * 5Copyright 1989, 1998 The Open Group 6 7Permission to use, copy, modify, distribute, and sell this software and its 8documentation for any purpose is hereby granted without fee, provided that 9the above copyright notice appear in all copies and that both that 10copyright notice and this permission notice appear in supporting 11documentation. 12 13The above copyright notice and this permission notice shall be included in 14all copies or substantial portions of the Software. 15 16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 23Except as contained in this notice, the name of The Open Group shall not be 24used in advertising or otherwise to promote the sale, use or other dealings 25in this Software without prior written authorization from The Open Group. 26 * * 27 * Author: Jim Fulton, MIT X Consortium 28 */ 29/* $XFree86: xc/programs/xlsclients/xlsclients.c,v 1.5 2001/04/01 14:00:23 tsi Exp $ */ 30 31#include <stdio.h> 32#include <stdlib.h> 33#include <ctype.h> 34#include <X11/Xos.h> 35#include <X11/Xlib.h> 36#include <X11/Xatom.h> 37#include <X11/Xutil.h> 38#include <X11/Xmu/WinUtil.h> 39 40static char *ProgramName; 41 42static void lookat ( Display *dpy, Window root, Bool verbose, int maxcmdlen ); 43static void print_client_properties ( Display *dpy, Window w, 44 Bool verbose, int maxcmdlen ); 45static void print_text_field ( Display *dpy, char *s, XTextProperty *tp ); 46static int print_quoted_word ( char *s, int maxlen ); 47static void unknown ( Display *dpy, Atom actual_type, int actual_format ); 48 49static void 50usage(void) 51{ 52 fprintf (stderr, 53 "usage: %s [-display dpy] [-m len] [-[a][l]]\n", ProgramName); 54 exit (1); 55} 56 57int 58main(int argc, char *argv[]) 59{ 60 int i; 61 char *displayname = NULL; 62 Bool all_screens = False; 63 Bool verbose = False; 64 Display *dpy; 65 int maxcmdlen = 10000; 66 67 ProgramName = argv[0]; 68 69 for (i = 1; i < argc; i++) { 70 char *arg = argv[i]; 71 72 if (arg[0] == '-') { 73 char *cp; 74 75 switch (arg[1]) { 76 case 'd': /* -display dpyname */ 77 if (++i >= argc) usage (); 78 displayname = argv[i]; 79 continue; 80 case 'm': /* -max maxcmdlen */ 81 if (++i >= argc) usage (); 82 maxcmdlen = atoi (argv[i]); 83 continue; 84 } 85 86 for (cp = &arg[1]; *cp; cp++) { 87 switch (*cp) { 88 case 'a': /* -all */ 89 all_screens = True; 90 continue; 91 case 'l': /* -long */ 92 verbose = True; 93 continue; 94 default: 95 usage (); 96 } 97 } 98 } else { 99 usage (); 100 } 101 } 102 103 dpy = XOpenDisplay (displayname); 104 if (!dpy) { 105 fprintf (stderr, "%s: unable to open display \"%s\"\r\n", 106 ProgramName, XDisplayName (displayname)); 107 exit (1); 108 } 109 110 if (all_screens) { 111 for (i = 0; i < ScreenCount(dpy); i++) { 112 lookat (dpy, RootWindow(dpy,i), verbose, maxcmdlen); 113 } 114 } else { 115 lookat (dpy, DefaultRootWindow(dpy), verbose, maxcmdlen); 116 } 117 118 XCloseDisplay (dpy); 119 exit (0); 120} 121 122static void 123lookat(Display *dpy, Window root, Bool verbose, int maxcmdlen) 124{ 125 Window dummy, *children = NULL, client; 126 unsigned int i, nchildren = 0; 127 128 /* 129 * clients are not allowed to stomp on the root and ICCCM doesn't yet 130 * say anything about window managers putting stuff there; but, try 131 * anyway. 132 */ 133 print_client_properties (dpy, root, verbose, maxcmdlen); 134 135 /* 136 * then, get the list of windows 137 */ 138 if (!XQueryTree (dpy, root, &dummy, &dummy, &children, &nchildren)) { 139 return; 140 } 141 142 for (i = 0; i < nchildren; i++) { 143 client = XmuClientWindow (dpy, children[i]); 144 if (client != None) 145 print_client_properties (dpy, client, verbose, maxcmdlen); 146 } 147} 148 149static char *Nil = "(nil)"; 150 151static void 152print_client_properties(Display *dpy, Window w, Bool verbose, int maxcmdlen) 153{ 154 char **cliargv = NULL; 155 int i, cliargc; 156 XTextProperty nametp, machtp, tp; 157 int charsleft = maxcmdlen; 158 159 /* 160 * get the WM_MACHINE and WM_COMMAND list of strings 161 */ 162 if (!XGetWMClientMachine (dpy, w, &machtp)) { 163 machtp.value = NULL; 164 machtp.encoding = None; 165 } 166 167 if (!XGetCommand (dpy, w, &cliargv, &cliargc)) { 168 if (machtp.value) XFree ((char *) machtp.value); 169 return; 170 } 171 172 /* 173 * do header information 174 */ 175 if (verbose) { 176 printf ("Window 0x%lx:\n", w); 177 print_text_field (dpy, " Machine: ", &machtp); 178 if (XGetWMName (dpy, w, &nametp)) { 179 print_text_field (dpy, " Name: ", &nametp); 180 if (nametp.value) XFree ((char *) nametp.value); 181 } 182 } else { 183 print_text_field (dpy, NULL, &machtp); 184 putchar (' '); 185 putchar (' '); 186 } 187 if (machtp.value) XFree ((char *) machtp.value); 188 189 if (verbose) { 190 if (XGetWMIconName (dpy, w, &tp)) { 191 print_text_field (dpy, " Icon Name: ", &tp); 192 if (tp.value) XFree ((char *) tp.value); 193 } 194 } 195 196 197 /* 198 * do the command 199 */ 200 if (verbose) { 201 printf (" Command: "); 202 } 203 for (i = 0; i < cliargc && charsleft > 0; ) { 204 charsleft -= print_quoted_word (cliargv[i], charsleft); 205 i++; 206 if (i < cliargc && charsleft > 0) { 207 putchar (' '); charsleft--; 208 } 209 } 210 putchar ('\n'); 211 XFreeStringList (cliargv); 212 213 214 /* 215 * do trailer information 216 */ 217 if (verbose) { 218 XClassHint clh; 219 if (XGetClassHint (dpy, w, &clh)) { 220 printf (" Instance/Class: %s/%s", 221 clh.res_name ? clh.res_name : Nil, 222 clh.res_class ? clh.res_class : Nil); 223 if (clh.res_name) XFree (clh.res_name); 224 if (clh.res_class) XFree (clh.res_class); 225 putchar ('\n'); 226 } 227 } 228} 229 230static void 231print_text_field(Display *dpy, char *s, XTextProperty *tp) 232{ 233 if (tp->encoding == None || tp->format == 0) { 234 printf ("''"); 235 return; 236 } 237 238 if (s) printf ("%s", s); 239 if (tp->encoding == XA_STRING && tp->format == 8) { 240 printf ("%s", tp->value ? (char *) tp->value : Nil); 241 } else { 242 unknown (dpy, tp->encoding, tp->format); 243 } 244 if (s) putchar ('\n'); 245} 246 247/* returns the number of characters printed */ 248static int 249print_quoted_word(char *s, 250 int maxlen) /* max number of chars we can print */ 251{ 252 register char *cp; 253 Bool need_quote = False, in_quote = False; 254 char quote_char = '\'', other_quote = '"'; 255 int charsprinted = 0; 256 257 /* 258 * walk down seeing whether or not we need to quote 259 */ 260 for (cp = s; *cp; cp++) { 261 262 if (! ((isascii(*cp) && isalnum(*cp)) || 263 (*cp == '-' || *cp == '_' || *cp == '.' || *cp == '+' || 264 *cp == '/' || *cp == '=' || *cp == ':' || *cp == ','))) { 265 need_quote = True; 266 break; 267 } 268 } 269 270 /* 271 * write out the string: if we hit a quote, then close any previous quote, 272 * emit the other quote, swap quotes and continue on. 273 */ 274 in_quote = need_quote; 275 if (need_quote) { 276 putchar (quote_char); 277 charsprinted++; maxlen--; 278 } 279 for (cp = s; *cp && maxlen>0; cp++) { 280 if (*cp == quote_char) { 281 if (in_quote) { 282 putchar (quote_char); 283 charsprinted++; maxlen--; 284 } 285 putchar (other_quote); 286 charsprinted++; maxlen--; 287 { 288 char tmp = other_quote; 289 other_quote = quote_char; quote_char = tmp; 290 } 291 in_quote = True; 292 } 293 putchar (*cp); 294 charsprinted++; maxlen--; 295 } 296 /* close the quote if we opened one and if we printed the whole string */ 297 if (in_quote && maxlen>0) { 298 putchar (quote_char); 299 charsprinted++; maxlen--; 300 } 301 302 return charsprinted; 303} 304 305static void 306unknown(Display *dpy, Atom actual_type, int actual_format) 307{ 308 char *s; 309 310 printf ("<unknown type "); 311 if (actual_type == None) printf ("None"); 312 else if ((s = XGetAtomName (dpy, actual_type)) != NULL) { 313 fputs (s, stdout); 314 XFree (s); 315 } else { 316 fputs (Nil, stdout); 317 } 318 printf (" (%ld) or format %d>", actual_type, actual_format); 319} 320 321