xload.c revision fd0c672f
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/* 34 * xload - display system load average in a window 35 */ 36 37#include <errno.h> 38#include <stdio.h> 39#include <stdlib.h> 40#include <unistd.h> 41#include <X11/Intrinsic.h> 42#include <X11/Xatom.h> 43#include <X11/StringDefs.h> 44#include <X11/Shell.h> 45 46#include <X11/Xaw/Cardinals.h> 47#include <X11/Xaw/Label.h> 48#include <X11/Xaw/Paned.h> 49#include <X11/Xaw/StripChart.h> 50#include <X11/Xmu/SysUtil.h> 51#include "xload.h" 52 53#include "xload.bit" 54 55char *ProgramName; 56 57static void quit(Widget w, XEvent *event, String *params, Cardinal *num_params); 58static void ClearLights(Display *dpy); 59static void SetLights(XtPointer data, XtIntervalId *timer); 60 61/* 62 * Definition of the Application resources structure. 63 */ 64 65typedef struct _XLoadResources { 66 Boolean show_label; 67 Boolean use_lights; 68 String remote; 69} XLoadResources; 70 71/* 72 * Command line options table. Only resources are entered here...there is a 73 * pass over the remaining options after XtParseCommand is let loose. 74 */ 75 76static XrmOptionDescRec options[] = { 77 {"-scale", "*load.minScale", XrmoptionSepArg, NULL}, 78 {"-update", "*load.update", XrmoptionSepArg, NULL}, 79 {"-hl", "*load.highlight", XrmoptionSepArg, NULL}, 80 {"-highlight", "*load.highlight", XrmoptionSepArg, NULL}, 81 {"-label", "*label.label", XrmoptionSepArg, NULL}, 82 {"-nolabel", "*showLabel", XrmoptionNoArg, "False"}, 83 {"-lights", "*useLights", XrmoptionNoArg, "True"}, 84 {"-jumpscroll", "*load.jumpScroll", XrmoptionSepArg, NULL}, 85 {"-remote", "*remote", XrmoptionSepArg, NULL}, 86}; 87 88/* 89 * The structure containing the resource information for the 90 * Xload application resources. 91 */ 92 93#define Offset(field) (XtOffsetOf(XLoadResources, field)) 94 95static XtResource my_resources[] = { 96 {"showLabel", XtCBoolean, XtRBoolean, sizeof(Boolean), 97 Offset(show_label), XtRImmediate, (XtPointer) TRUE}, 98 {"useLights", XtCBoolean, XtRBoolean, sizeof(Boolean), 99 Offset(use_lights), XtRImmediate, (XtPointer) FALSE}, 100 {"remote", XtCString, XtRString, sizeof(XtRString), 101 Offset(remote), XtRImmediate, (XtPointer) FALSE}, 102 103}; 104 105#undef Offset 106 107XLoadResources resources; 108 109static XtActionsRec xload_actions[] = { 110 { "quit", quit }, 111}; 112static Atom wm_delete_window; 113static int light_update = 10 * 1000; 114 115/* 116 * Exit with message describing command line format. 117 */ 118 119static void usage(void) 120{ 121 fprintf (stderr, "usage: %s [-options ...]\n\n", ProgramName); 122 fprintf (stderr, "where options include:\n"); 123 fprintf (stderr, 124 " -display dpy X server on which to display\n"); 125 fprintf (stderr, 126 " -geometry geom size and location of window\n"); 127 fprintf (stderr, 128 " -fn font font to use in label\n"); 129 fprintf (stderr, 130 " -scale number minimum number of scale lines\n"); 131 fprintf (stderr, 132 " -update seconds interval between updates\n"); 133 fprintf (stderr, 134 " -label string annotation text\n"); 135 fprintf (stderr, 136 " -bg color background color\n"); 137 fprintf (stderr, 138 " -fg color graph color\n"); 139 fprintf (stderr, 140 " -hl color scale and text color\n"); 141 fprintf (stderr, 142 " -nolabel removes the label from above the chart.\n"); 143 fprintf (stderr, 144 " -jumpscroll value number of pixels to scroll on overflow\n"); 145 fprintf (stderr, 146 " -remote host remote host to monitor\n"); 147 fprintf (stderr, "\n"); 148 exit(1); 149} 150 151int 152main(int argc, char **argv) 153{ 154 XtAppContext app_con; 155 Widget toplevel, load, pane, label_wid, load_parent; 156 Arg args[1]; 157 Pixmap icon_pixmap = None; 158 char *label, host[256]; 159 160 ProgramName = argv[0]; 161 162 /* For security reasons, we reset our uid/gid after doing the necessary 163 system initialization and before calling any X routines. */ 164 InitLoadPoint(); 165 /* reset gid first while still (maybe) root */ 166 if (setgid(getgid()) == -1) { 167 fprintf(stderr, "%s: setgid failed: %s\n", 168 ProgramName, strerror(errno)); 169 exit(1); 170 } 171 if (setuid(getuid()) == -1) { 172 fprintf(stderr, "%s: setuid failed: %s\n", 173 ProgramName, strerror(errno)); 174 exit(1); 175 } 176 177 XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL); 178 179 toplevel = XtAppInitialize(&app_con, "XLoad", options, XtNumber(options), 180 &argc, argv, NULL, NULL, (Cardinal) 0); 181 if (argc != 1) usage(); 182 183 XtGetApplicationResources( toplevel, (XtPointer) &resources, 184 my_resources, XtNumber(my_resources), 185 NULL, (Cardinal) 0); 186 187 if (resources.use_lights) 188 { 189 char name[1024]; 190 XrmString type; 191 XrmValue db_value; 192 XrmValue int_value; 193 Bool found = False; 194 195 (void) sprintf (name, "%s.paned.load.update", XtName(toplevel)); 196 found = XrmGetResource (XtScreenDatabase(XtScreen(toplevel)), 197 name, "XLoad.Paned.StripChart.Interval", 198 &type, &db_value); 199 if (found) { 200 int_value.size = sizeof(int); 201 int_value.addr = (XPointer) &light_update; 202 found = XtConvertAndStore(toplevel, type, &db_value, XtRInt, 203 &int_value); 204 if (found) light_update *= 1000; 205 } 206 ClearLights (XtDisplay (toplevel)); 207 SetLights ((XtPointer) toplevel, (XtIntervalId *) 0); 208 } 209 else 210 { 211 /* 212 * This is a hack so that f.delete will do something useful in this 213 * single-window application. 214 */ 215 XtAppAddActions (app_con, xload_actions, XtNumber(xload_actions)); 216 XtOverrideTranslations(toplevel, 217 XtParseTranslationTable ("<Message>WM_PROTOCOLS: quit()")); 218 219 XtSetArg (args[0], XtNiconPixmap, &icon_pixmap); 220 XtGetValues(toplevel, args, ONE); 221 if (icon_pixmap == None) { 222 XtSetArg(args[0], XtNiconPixmap, 223 XCreateBitmapFromData(XtDisplay(toplevel), 224 XtScreen(toplevel)->root, 225 (char *)xload_bits, 226 xload_width, xload_height)); 227 XtSetValues (toplevel, args, ONE); 228 } 229 230 if (resources.show_label) { 231 pane = XtCreateManagedWidget ("paned", panedWidgetClass, 232 toplevel, NULL, ZERO); 233 234 label_wid = XtCreateManagedWidget ("label", labelWidgetClass, 235 pane, NULL, ZERO); 236 237 XtSetArg (args[0], XtNlabel, &label); 238 XtGetValues(label_wid, args, ONE); 239 240 if ( strcmp("label", label) == 0 ) { 241 (void) XmuGetHostname (host, 255); 242 XtSetArg (args[0], XtNlabel, host); 243 XtSetValues (label_wid, args, ONE); 244 } 245 246 load_parent = pane; 247 } 248 else 249 load_parent = toplevel; 250 251 load = XtCreateManagedWidget ("load", stripChartWidgetClass, 252 load_parent, NULL, ZERO); 253 254 if (resources.remote) 255 XtAddCallback(load, XtNgetValue, GetRLoadPoint, NULL); 256 else 257 XtAddCallback(load, XtNgetValue, GetLoadPoint, NULL); 258 259 XtRealizeWidget (toplevel); 260 wm_delete_window = XInternAtom (XtDisplay(toplevel), "WM_DELETE_WINDOW", 261 False); 262 (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel), 263 &wm_delete_window, 1); 264 } 265 XtAppMainLoop(app_con); 266 267 return 0; 268} 269 270static unsigned long current_leds; 271 272static void 273ClearLights (dpy) 274 Display *dpy; 275{ 276 XKeyboardControl cntrl; 277 278 cntrl.led_mode = LedModeOff; 279 XChangeKeyboardControl (dpy, KBLedMode, &cntrl); 280 current_leds = 0; 281} 282 283static void 284SetLights (data, timer) 285 XtPointer data; 286 XtIntervalId *timer; 287{ 288 Widget toplevel; 289 Display *dpy; 290 double value; 291 unsigned long new_leds, change, bit; 292 int i; 293 XKeyboardControl cntrl; 294 295 toplevel = (Widget) data; 296 dpy = XtDisplay (toplevel); 297 if (resources.remote) 298 GetRLoadPoint (toplevel, (XtPointer) 0, (XtPointer) &value); 299 else 300 GetLoadPoint (toplevel, (XtPointer) 0, (XtPointer) &value); 301 new_leds = (1 << (int) (value + 0.1)) - 1; 302 change = new_leds ^ current_leds; 303 i = 1; 304 bit = 1; 305 while (current_leds != new_leds) 306 { 307 if (change & bit) 308 { 309 cntrl.led = i; 310 cntrl.led_mode = new_leds & bit ? LedModeOn : LedModeOff; 311 XChangeKeyboardControl (dpy, KBLed|KBLedMode, &cntrl); 312 current_leds ^= bit; 313 } 314 i++; 315 bit <<= 1; 316 } 317 XtAppAddTimeOut(XtWidgetToApplicationContext(toplevel), light_update, 318 SetLights, data); 319} 320 321static void quit (w, event, params, num_params) 322 Widget w; 323 XEvent *event; 324 String *params; 325 Cardinal *num_params; 326{ 327 if (event->type == ClientMessage && 328 event->xclient.data.l[0] != wm_delete_window) { 329 XBell (XtDisplay(w), 0); 330 return; 331 } 332 if (resources.use_lights) 333 ClearLights (XtDisplay (w)); 334 XtDestroyApplicationContext(XtWidgetToApplicationContext(w)); 335 exit (0); 336} 337 338 339 340 341 342 343