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