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