xload.c revision 8846b520
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 _X_NORETURN 143usage(void) 144{ 145 fprintf (stderr, gettext("usage: %s [-options ...]\n\n%s\n"), 146 ProgramName, gettext( 147 "where options include:\n" 148 " -display <display> X server on which to display\n" 149 " -geometry <geometry> size and location of window\n" 150 " -fn <font> font to use in label\n" 151 " -scale <number> minimum number of scale lines\n" 152 " -update <seconds> interval between updates\n" 153 " -label <string> annotation text\n" 154 " -bg <color> background color\n" 155 " -fg <color> graph color\n" 156 " -hl <color> scale and text color\n" 157 " -nolabel removes the label from above the chart.\n" 158 " -jumpscroll <value> number of pixels to scroll on overflow\n" 159 " -lights use keyboard leds to display current load\n" 160 )); 161 exit(1); 162} 163 164int 165main(int argc, char **argv) 166{ 167 XtAppContext app_con; 168 Widget toplevel, load, pane, label_wid, load_parent; 169 Arg args[1]; 170 Pixmap icon_pixmap = None; 171 char *label, host[256]; 172 const char *domaindir; 173 174 XtSetLanguageProc ( NULL, NULL, NULL ); 175 176 ProgramName = argv[0]; 177 178 /* For security reasons, we reset our uid/gid after doing the necessary 179 system initialization and before calling any X routines. */ 180 InitLoadPoint(); 181 182#if !defined(_WIN32) || defined(__CYGWIN__) 183 /* reset gid first while still (maybe) root */ 184 if (setgid(getgid()) == -1) { 185 fprintf(stderr, gettext("%s: setgid failed: %s\n"), 186 ProgramName, strerror(errno)); 187 exit(1); 188 } 189 if (setuid(getuid()) == -1) { 190 fprintf(stderr, gettext("%s: setuid failed: %s\n"), 191 ProgramName, strerror(errno)); 192 exit(1); 193 } 194#endif 195 196 XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL); 197 198 toplevel = XtAppInitialize(&app_con, "XLoad", options, XtNumber(options), 199 &argc, argv, NULL, NULL, (Cardinal) 0); 200 201#ifdef USE_GETTEXT 202 textdomain("xload"); 203 204 if ((domaindir = getenv ( "TEXTDOMAINDIR" )) == NULL) { 205 domaindir = LOCALEDIR; 206 } 207 bindtextdomain("xload", domaindir); 208#endif 209 210 if (argc != 1) usage(); 211 212 XtGetApplicationResources( toplevel, (XtPointer) &resources, 213 my_resources, XtNumber(my_resources), 214 NULL, (Cardinal) 0); 215 216 if (resources.use_lights) 217 { 218 char name[1024]; 219 XrmString type; 220 XrmValue db_value; 221 XrmValue int_value; 222 Bool found = False; 223 224 snprintf (name, sizeof(name), "%s.paned.load.update", XtName(toplevel)); 225 found = XrmGetResource (XtScreenDatabase(XtScreen(toplevel)), 226 name, "XLoad.Paned.StripChart.Interval", 227 &type, &db_value); 228 if (found) { 229 int_value.size = sizeof(int); 230 int_value.addr = (XPointer) &light_update; 231 found = XtConvertAndStore(toplevel, type, &db_value, XtRInt, 232 &int_value); 233 if (found) light_update *= 1000; 234 } 235 ClearLights (XtDisplay (toplevel)); 236 SetLights ((XtPointer) toplevel, (XtIntervalId *) 0); 237 } 238 else 239 { 240 /* 241 * This is a hack so that f.delete will do something useful in this 242 * single-window application. 243 */ 244 XtAppAddActions (app_con, xload_actions, XtNumber(xload_actions)); 245 XtOverrideTranslations(toplevel, 246 XtParseTranslationTable ("<Message>WM_PROTOCOLS: quit()")); 247 248 XtSetArg (args[0], XtNiconPixmap, &icon_pixmap); 249 XtGetValues(toplevel, args, ONE); 250 if (icon_pixmap == None) { 251 XtSetArg(args[0], XtNiconPixmap, 252 XCreateBitmapFromData(XtDisplay(toplevel), 253 XtScreen(toplevel)->root, 254 (char *)xload_bits, 255 xload_width, xload_height)); 256 XtSetValues (toplevel, args, ONE); 257 } 258 259 if (resources.show_label) { 260 pane = XtCreateManagedWidget ("paned", panedWidgetClass, 261 toplevel, NULL, ZERO); 262 263 label_wid = XtCreateManagedWidget ("label", labelWidgetClass, 264 pane, NULL, ZERO); 265 266 XtSetArg (args[0], XtNlabel, &label); 267 XtGetValues(label_wid, args, ONE); 268 269 if ( strcmp("label", label) == 0 ) { 270 (void) XmuGetHostname (host, 255); 271 XtSetArg (args[0], XtNlabel, host); 272 XtSetValues (label_wid, args, ONE); 273 } 274 275 load_parent = pane; 276 } 277 else 278 load_parent = toplevel; 279 280 load = XtCreateManagedWidget ("load", stripChartWidgetClass, 281 load_parent, NULL, ZERO); 282 283 if (resources.remote) 284 XtAddCallback(load, XtNgetValue, GetRLoadPoint, NULL); 285 else 286 XtAddCallback(load, XtNgetValue, GetLoadPoint, NULL); 287 288 XtRealizeWidget (toplevel); 289 wm_delete_window = XInternAtom (XtDisplay(toplevel), "WM_DELETE_WINDOW", 290 False); 291 (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel), 292 &wm_delete_window, 1); 293 } 294 XtAppMainLoop(app_con); 295 296 return 0; 297} 298 299static unsigned long current_leds; 300 301static void 302ClearLights (Display *dpy) 303{ 304 XKeyboardControl cntrl = { 305 .led_mode = LedModeOff 306 }; 307 XChangeKeyboardControl (dpy, KBLedMode, &cntrl); 308 current_leds = 0; 309} 310 311static void 312SetLights (XtPointer data, XtIntervalId *timer) 313{ 314 Widget toplevel; 315 Display *dpy; 316 double value; 317 unsigned long new_leds, change, bit; 318 int i; 319 320 toplevel = (Widget) data; 321 dpy = XtDisplay (toplevel); 322 if (resources.remote) 323 GetRLoadPoint (toplevel, (XtPointer) 0, (XtPointer) &value); 324 else 325 GetLoadPoint (toplevel, (XtPointer) 0, (XtPointer) &value); 326 new_leds = (1 << (int) (value + 0.1)) - 1; 327 change = new_leds ^ current_leds; 328 i = 1; 329 bit = 1; 330 while (current_leds != new_leds) 331 { 332 if (change & bit) 333 { 334 XKeyboardControl cntrl = { 335 .led = i, 336 .led_mode = new_leds & bit ? LedModeOn : LedModeOff 337 }; 338 XChangeKeyboardControl (dpy, KBLed|KBLedMode, &cntrl); 339 current_leds ^= bit; 340 } 341 i++; 342 bit <<= 1; 343 } 344 XtAppAddTimeOut(XtWidgetToApplicationContext(toplevel), light_update, 345 SetLights, data); 346} 347 348static void quit (Widget w, XEvent *event, String *params, Cardinal *num_params) 349{ 350 if (event->type == ClientMessage && 351 event->xclient.data.l[0] != wm_delete_window) { 352 XBell (XtDisplay(w), 0); 353 return; 354 } 355 if (resources.use_lights) 356 ClearLights (XtDisplay (w)); 357 XtDestroyApplicationContext(XtWidgetToApplicationContext(w)); 358 exit (0); 359} 360 361 362 363 364 365 366