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