xload.c revision 953c684b
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 /* reset gid first while still (maybe) root */ 182 if (setgid(getgid()) == -1) { 183 fprintf(stderr, gettext("%s: setgid failed: %s\n"), 184 ProgramName, strerror(errno)); 185 exit(1); 186 } 187 if (setuid(getuid()) == -1) { 188 fprintf(stderr, gettext("%s: setuid failed: %s\n"), 189 ProgramName, strerror(errno)); 190 exit(1); 191 } 192 193 XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL); 194 195 toplevel = XtAppInitialize(&app_con, "XLoad", options, XtNumber(options), 196 &argc, argv, NULL, NULL, (Cardinal) 0); 197 198#ifdef USE_GETTEXT 199 textdomain("xload"); 200 201 if ((domaindir = getenv ( "TEXTDOMAINDIR" )) == NULL) { 202 domaindir = LOCALEDIR; 203 } 204 bindtextdomain("xload", domaindir); 205#endif 206 207 if (argc != 1) usage(); 208 209 XtGetApplicationResources( toplevel, (XtPointer) &resources, 210 my_resources, XtNumber(my_resources), 211 NULL, (Cardinal) 0); 212 213 if (resources.use_lights) 214 { 215 char name[1024]; 216 XrmString type; 217 XrmValue db_value; 218 XrmValue int_value; 219 Bool found = False; 220 221 snprintf (name, sizeof(name), "%s.paned.load.update", XtName(toplevel)); 222 found = XrmGetResource (XtScreenDatabase(XtScreen(toplevel)), 223 name, "XLoad.Paned.StripChart.Interval", 224 &type, &db_value); 225 if (found) { 226 int_value.size = sizeof(int); 227 int_value.addr = (XPointer) &light_update; 228 found = XtConvertAndStore(toplevel, type, &db_value, XtRInt, 229 &int_value); 230 if (found) light_update *= 1000; 231 } 232 ClearLights (XtDisplay (toplevel)); 233 SetLights ((XtPointer) toplevel, (XtIntervalId *) 0); 234 } 235 else 236 { 237 /* 238 * This is a hack so that f.delete will do something useful in this 239 * single-window application. 240 */ 241 XtAppAddActions (app_con, xload_actions, XtNumber(xload_actions)); 242 XtOverrideTranslations(toplevel, 243 XtParseTranslationTable ("<Message>WM_PROTOCOLS: quit()")); 244 245 XtSetArg (args[0], XtNiconPixmap, &icon_pixmap); 246 XtGetValues(toplevel, args, ONE); 247 if (icon_pixmap == None) { 248 XtSetArg(args[0], XtNiconPixmap, 249 XCreateBitmapFromData(XtDisplay(toplevel), 250 XtScreen(toplevel)->root, 251 (char *)xload_bits, 252 xload_width, xload_height)); 253 XtSetValues (toplevel, args, ONE); 254 } 255 256 if (resources.show_label) { 257 pane = XtCreateManagedWidget ("paned", panedWidgetClass, 258 toplevel, NULL, ZERO); 259 260 label_wid = XtCreateManagedWidget ("label", labelWidgetClass, 261 pane, NULL, ZERO); 262 263 XtSetArg (args[0], XtNlabel, &label); 264 XtGetValues(label_wid, args, ONE); 265 266 if ( strcmp("label", label) == 0 ) { 267 (void) XmuGetHostname (host, 255); 268 XtSetArg (args[0], XtNlabel, host); 269 XtSetValues (label_wid, args, ONE); 270 } 271 272 load_parent = pane; 273 } 274 else 275 load_parent = toplevel; 276 277 load = XtCreateManagedWidget ("load", stripChartWidgetClass, 278 load_parent, NULL, ZERO); 279 280 if (resources.remote) 281 XtAddCallback(load, XtNgetValue, GetRLoadPoint, NULL); 282 else 283 XtAddCallback(load, XtNgetValue, GetLoadPoint, NULL); 284 285 XtRealizeWidget (toplevel); 286 wm_delete_window = XInternAtom (XtDisplay(toplevel), "WM_DELETE_WINDOW", 287 False); 288 (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel), 289 &wm_delete_window, 1); 290 } 291 XtAppMainLoop(app_con); 292 293 return 0; 294} 295 296static unsigned long current_leds; 297 298static void 299ClearLights (Display *dpy) 300{ 301 XKeyboardControl cntrl = { 302 .led_mode = LedModeOff 303 }; 304 XChangeKeyboardControl (dpy, KBLedMode, &cntrl); 305 current_leds = 0; 306} 307 308static void 309SetLights (XtPointer data, XtIntervalId *timer) 310{ 311 Widget toplevel; 312 Display *dpy; 313 double value; 314 unsigned long new_leds, change, bit; 315 int i; 316 317 toplevel = (Widget) data; 318 dpy = XtDisplay (toplevel); 319 if (resources.remote) 320 GetRLoadPoint (toplevel, (XtPointer) 0, (XtPointer) &value); 321 else 322 GetLoadPoint (toplevel, (XtPointer) 0, (XtPointer) &value); 323 new_leds = (1 << (int) (value + 0.1)) - 1; 324 change = new_leds ^ current_leds; 325 i = 1; 326 bit = 1; 327 while (current_leds != new_leds) 328 { 329 if (change & bit) 330 { 331 XKeyboardControl cntrl = { 332 .led = i, 333 .led_mode = new_leds & bit ? LedModeOn : LedModeOff 334 }; 335 XChangeKeyboardControl (dpy, KBLed|KBLedMode, &cntrl); 336 current_leds ^= bit; 337 } 338 i++; 339 bit <<= 1; 340 } 341 XtAppAddTimeOut(XtWidgetToApplicationContext(toplevel), light_update, 342 SetLights, data); 343} 344 345static void quit (Widget w, XEvent *event, String *params, Cardinal *num_params) 346{ 347 if (event->type == ClientMessage && 348 event->xclient.data.l[0] != wm_delete_window) { 349 XBell (XtDisplay(w), 0); 350 return; 351 } 352 if (resources.use_lights) 353 ClearLights (XtDisplay (w)); 354 XtDestroyApplicationContext(XtWidgetToApplicationContext(w)); 355 exit (0); 356} 357 358 359 360 361 362 363