xload.c revision 48e69166
1/* $XConsortium: xload.c,v 1.37 94/04/17 20:43:44 converse Exp $ */
2/* $XFree86: xc/programs/xload/xload.c,v 1.6tsi Exp $ */
3/*
4
5Copyright (c) 1989  X Consortium
6
7Permission is hereby granted, free of charge, to any person obtaining
8a copy of this software and associated documentation files (the
9"Software"), to deal in the Software without restriction, including
10without limitation the rights to use, copy, modify, merge, publish,
11distribute, sublicense, and/or sell copies of the Software, and to
12permit persons to whom the Software is furnished to do so, subject to
13the following conditions:
14
15The above copyright notice and this permission notice shall be included
16in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
22OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24OTHER DEALINGS IN THE SOFTWARE.
25
26Except as contained in this notice, the name of the X Consortium shall
27not be used in advertising or otherwise to promote the sale, use or
28other dealings in this Software without prior written authorization
29from the X Consortium.
30
31*/
32/*
33 * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
34 *
35 * Permission is hereby granted, free of charge, to any person obtaining a
36 * copy of this software and associated documentation files (the "Software"),
37 * to deal in the Software without restriction, including without limitation
38 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
39 * and/or sell copies of the Software, and to permit persons to whom the
40 * Software is furnished to do so, subject to the following conditions:
41 *
42 * The above copyright notice and this permission notice (including the next
43 * paragraph) shall be included in all copies or substantial portions of the
44 * Software.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
49 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
50 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
51 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
52 * DEALINGS IN THE SOFTWARE.
53 */
54
55
56/*
57 * xload - display system load average in a window
58 */
59
60#ifdef HAVE_CONFIG_H
61# include "config.h"
62#endif
63
64#include <errno.h>
65#include <stdio.h>
66#include <stdlib.h>
67#include <unistd.h>
68#include <X11/Intrinsic.h>
69#include <X11/Xatom.h>
70#include <X11/StringDefs.h>
71#include <X11/Shell.h>
72
73#include <X11/Xaw/Cardinals.h>
74#include <X11/Xaw/Label.h>
75#include <X11/Xaw/Paned.h>
76#include <X11/Xaw/StripChart.h>
77#include <X11/Xmu/SysUtil.h>
78#include "xload.h"
79
80#ifdef USE_GETTEXT
81# include <X11/Xlocale.h>
82# include <libintl.h>
83#else
84# define gettext(a) (a)
85#endif
86
87#include "xload.bit"
88
89static char *ProgramName;
90
91static void quit(Widget w, XEvent *event, String *params, Cardinal *num_params);
92static void ClearLights(Display *dpy);
93static void SetLights(XtPointer data, XtIntervalId *timer);
94
95
96/*
97 * Command line options table.  Only resources are entered here...there is a
98 * pass over the remaining options after XtParseCommand is let loose.
99 */
100
101static XrmOptionDescRec options[] = {
102 {"-scale",		"*load.minScale",	XrmoptionSepArg,	NULL},
103 {"-update",		"*load.update",		XrmoptionSepArg,	NULL},
104 {"-hl",		"*load.highlight",	XrmoptionSepArg,	NULL},
105 {"-highlight",		"*load.highlight",	XrmoptionSepArg,	NULL},
106 {"-label",		"*label.label",		XrmoptionSepArg,	NULL},
107 {"-nolabel",		"*showLabel",	        XrmoptionNoArg,       "False"},
108 {"-lights",		"*useLights",		XrmoptionNoArg,	      "True"},
109 {"-jumpscroll",	"*load.jumpScroll",	XrmoptionSepArg,	NULL},
110 {"-remote",            "*remote",              XrmoptionSepArg,        NULL},
111};
112
113/*
114 * The structure containing the resource information for the
115 * Xload application resources.
116 */
117
118#define Offset(field) (XtOffsetOf(XLoadResources, field))
119
120static XtResource my_resources[] = {
121  {"showLabel", XtCBoolean, XtRBoolean, sizeof(Boolean),
122     Offset(show_label), XtRImmediate, (XtPointer) TRUE},
123  {"useLights", XtCBoolean, XtRBoolean, sizeof(Boolean),
124    Offset(use_lights), XtRImmediate, (XtPointer) FALSE},
125  {"remote", XtCString, XtRString, sizeof(XtRString),
126    Offset(remote), XtRImmediate, (XtPointer) FALSE},
127
128};
129
130#undef Offset
131
132XLoadResources resources;
133
134static XtActionsRec xload_actions[] = {
135    { "quit",	quit },
136};
137static Atom wm_delete_window;
138static int light_update = 10 * 1000;
139
140/*
141 * Exit with message describing command line format.
142 */
143
144static void usage(void)
145{
146    fprintf (stderr, gettext("usage:  %s [-options ...]\n\n"), ProgramName);
147    fprintf (stderr, gettext("where options include:\n"));
148    fprintf (stderr, "    -display %s",
149             gettext("display        X server on which to display\n"));
150    fprintf (stderr, "    -geometry %s",
151             gettext("geometry      size and location of window\n"));
152    fprintf (stderr, "    -fn %s",
153             gettext("font                font to use in label\n"));
154    fprintf (stderr, "    -scale %s",
155             gettext("number           minimum number of scale lines\n"));
156    fprintf (stderr, "    -update %s",
157             gettext("seconds         interval between updates\n"));
158    fprintf (stderr, "    -label %s",
159             gettext("string           annotation text\n"));
160    fprintf (stderr, "    -bg %s",
161             gettext("color               background color\n"));
162    fprintf (stderr, "    -fg %s",
163             gettext("color               graph color\n"));
164    fprintf (stderr, "    -hl %s",
165             gettext("color               scale and text color\n"));
166    fprintf (stderr, "    -nolabel                %s",
167             gettext("removes the label from above the chart.\n"));
168    fprintf (stderr, "    -jumpscroll %s",
169             gettext("value       number of pixels to scroll on overflow\n"));
170    fprintf (stderr, "    -lights                 %s",
171             gettext("use keyboard leds to display current load\n"));
172    fprintf (stderr, "\n");
173    exit(1);
174}
175
176int
177main(int argc, char **argv)
178{
179    XtAppContext app_con;
180    Widget toplevel, load, pane, label_wid, load_parent;
181    Arg args[1];
182    Pixmap icon_pixmap = None;
183    char *label, host[256];
184    char *domaindir;
185
186    XtSetLanguageProc ( NULL, NULL, NULL );
187
188    ProgramName = argv[0];
189
190    /* For security reasons, we reset our uid/gid after doing the necessary
191       system initialization and before calling any X routines. */
192    InitLoadPoint();
193    /* reset gid first while still (maybe) root */
194    if (setgid(getgid()) == -1) {
195	    fprintf(stderr, gettext("%s: setgid failed: %s\n"),
196		ProgramName, strerror(errno));
197	    exit(1);
198    }
199    if (setuid(getuid()) == -1) {
200	    fprintf(stderr, gettext("%s: setuid failed: %s\n"),
201		ProgramName, strerror(errno));
202	    exit(1);
203    }
204
205    XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL);
206
207    toplevel = XtAppInitialize(&app_con, "XLoad", options, XtNumber(options),
208			       &argc, argv, NULL, NULL, (Cardinal) 0);
209
210#ifdef USE_GETTEXT
211    textdomain("xload");
212
213    if ((domaindir = getenv ( "TEXTDOMAINDIR" )) == NULL) {
214	domaindir = LOCALEDIR;
215    }
216    bindtextdomain("xload", domaindir);
217#endif
218
219    if (argc != 1) usage();
220
221    XtGetApplicationResources( toplevel, (XtPointer) &resources,
222			      my_resources, XtNumber(my_resources),
223			      NULL, (Cardinal) 0);
224
225    if (resources.use_lights)
226    {
227	char	    name[1024];
228	XrmString   type;
229	XrmValue    db_value;
230	XrmValue    int_value;
231	Bool	    found = False;
232
233	(void) sprintf (name, "%s.paned.load.update", XtName(toplevel));
234	found = XrmGetResource (XtScreenDatabase(XtScreen(toplevel)),
235				name, "XLoad.Paned.StripChart.Interval",
236				&type, &db_value);
237	if (found) {
238	    int_value.size = sizeof(int);
239	    int_value.addr = (XPointer) &light_update;
240	    found = XtConvertAndStore(toplevel, type, &db_value, XtRInt,
241				      &int_value);
242	    if (found) light_update *= 1000;
243	}
244	ClearLights (XtDisplay (toplevel));
245	SetLights ((XtPointer) toplevel, (XtIntervalId *) 0);
246    }
247    else
248    {
249    	/*
250     	 * This is a hack so that f.delete will do something useful in this
251     	 * single-window application.
252     	 */
253    	XtAppAddActions (app_con, xload_actions, XtNumber(xload_actions));
254    	XtOverrideTranslations(toplevel,
255		    	XtParseTranslationTable ("<Message>WM_PROTOCOLS: quit()"));
256
257    	XtSetArg (args[0], XtNiconPixmap, &icon_pixmap);
258    	XtGetValues(toplevel, args, ONE);
259    	if (icon_pixmap == None) {
260	    XtSetArg(args[0], XtNiconPixmap,
261		     XCreateBitmapFromData(XtDisplay(toplevel),
262				       	   XtScreen(toplevel)->root,
263				       	   (char *)xload_bits,
264				       	   xload_width, xload_height));
265	    XtSetValues (toplevel, args, ONE);
266    	}
267
268    	if (resources.show_label) {
269      	  pane = XtCreateManagedWidget ("paned", panedWidgetClass,
270				    	toplevel, NULL, ZERO);
271
272      	  label_wid = XtCreateManagedWidget ("label", labelWidgetClass,
273					     pane, NULL, ZERO);
274
275      	  XtSetArg (args[0], XtNlabel, &label);
276      	  XtGetValues(label_wid, args, ONE);
277
278      	  if ( strcmp("label", label) == 0 ) {
279	    (void) XmuGetHostname (host, 255);
280	    XtSetArg (args[0], XtNlabel, host);
281	    XtSetValues (label_wid, args, ONE);
282      	  }
283
284      	  load_parent = pane;
285    	}
286    	else
287      	  load_parent = toplevel;
288
289    	load = XtCreateManagedWidget ("load", stripChartWidgetClass,
290				      load_parent, NULL, ZERO);
291
292    	if (resources.remote)
293	  XtAddCallback(load, XtNgetValue, GetRLoadPoint, NULL);
294	else
295	  XtAddCallback(load, XtNgetValue, GetLoadPoint, NULL);
296
297    	XtRealizeWidget (toplevel);
298    	wm_delete_window = XInternAtom (XtDisplay(toplevel), "WM_DELETE_WINDOW",
299				    	False);
300    	(void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel),
301			    	&wm_delete_window, 1);
302    }
303    XtAppMainLoop(app_con);
304
305    return 0;
306}
307
308static unsigned long	current_leds;
309
310static void
311ClearLights (Display *dpy)
312{
313    XKeyboardControl	cntrl;
314
315    cntrl.led_mode = LedModeOff;
316    XChangeKeyboardControl (dpy, KBLedMode, &cntrl);
317    current_leds = 0;
318}
319
320static void
321SetLights (XtPointer data, XtIntervalId *timer)
322{
323    Widget		toplevel;
324    Display		*dpy;
325    double		value;
326    unsigned long	new_leds, change, bit;
327    int			i;
328    XKeyboardControl	cntrl;
329
330    toplevel = (Widget) data;
331    dpy = XtDisplay (toplevel);
332    if (resources.remote)
333      GetRLoadPoint (toplevel, (XtPointer) 0, (XtPointer) &value);
334    else
335      GetLoadPoint (toplevel, (XtPointer) 0, (XtPointer) &value);
336    new_leds = (1 << (int) (value + 0.1)) - 1;
337    change = new_leds ^ current_leds;
338    i = 1;
339    bit = 1;
340    while (current_leds != new_leds)
341    {
342	if (change & bit)
343	{
344	    cntrl.led = i;
345	    cntrl.led_mode = new_leds & bit ? LedModeOn : LedModeOff;
346	    XChangeKeyboardControl (dpy, KBLed|KBLedMode, &cntrl);
347	    current_leds ^= bit;
348	}
349	i++;
350	bit <<= 1;
351    }
352    XtAppAddTimeOut(XtWidgetToApplicationContext(toplevel), light_update,
353		    SetLights, data);
354}
355
356static void quit (Widget w, XEvent *event, String *params, Cardinal *num_params)
357{
358    if (event->type == ClientMessage &&
359        event->xclient.data.l[0] != wm_delete_window) {
360        XBell (XtDisplay(w), 0);
361        return;
362    }
363    if (resources.use_lights)
364	ClearLights (XtDisplay (w));
365    XtDestroyApplicationContext(XtWidgetToApplicationContext(w));
366    exit (0);
367}
368
369
370
371
372
373
374