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