1 /* wmload - system load monitor designed for Window Maker
2 * Copyright (C) 1996 Beat Christen <bchriste@iiic.ethz.ch>
3 * Copyright (C) 1997 Ryan Land <rland@bc1.com>
4 * Copyright (C) 2015 Window Maker Developers Team
5 * <wmaker-dev@lists.windowmaker.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
21 #define _POSIX_C_SOURCE 199309L
33 #include <X11/extensions/shape.h>
37 #include <X11/Xatom.h>
46 #define MW_EVENTS (ExposureMask | ButtonPressMask | StructureNotifyMask)
48 #define Shape(num) (ONLYSHAPE ? num-5 : num)
51 /* Global Data storage/structures ********************************************/
52 static long cp_time
[NCPUSTATES
];
53 static long last
[NCPUSTATES
];
54 int ONLYSHAPE
=0; /* default value is noshape */
56 static char *help_message
[] = {
57 "where options include:",
58 " -u <secs> updatespeed",
59 " -exe <program> program to start on click",
60 " -led <color> color of the led",
61 " -position [+|-]x[+|-]y position of wmload",
62 " -shape without groundplate",
63 " -iconic start up as icon",
64 " -withdrawn start up withdrawn",
65 " -ver output version",
69 /* X11 Variables *************************************************************/
70 Display
*dpy
; /* welches DISPLAY */
71 Window Root
; /* Hintergrund-Drawable */
75 XSizeHints mysizehints
;
77 Pixel back_pix
, fore_pix
;
79 Window iconwin
, win
; /* My home is my window */
82 char *LedColor
= "LightSeaGreen";
83 char Execute
[] = "echo no program has been specified";
84 char *ERR_colorcells
= "not enough free color cells\n";
87 /* XPM Structures & Variables ************************************************/
88 typedef struct _XpmIcon
{
91 XpmAttributes attributes
;
99 /* Function definitions ******************************************************/
101 Pixel
GetColor(char *name
);
102 void RedrawWindow( XpmIcon
*v
);
106 /*****************************************************************************/
107 /* Source Code <--> Function Implementations */
108 /*****************************************************************************/
113 fprintf(stderr
,"\nusage: %s [-options ...] \n", ProgName
);
114 for (cpp
= help_message
; *cpp
; cpp
++) {
115 fprintf(stderr
, "%s\n", *cpp
);
117 fprintf(stderr
,"\n");
122 * Copied from ascpu - albert@tigr.net - 09 Mar 2000
124 * This function executes an external command while
125 * checking whether we should drop the privileges.
127 * Since we might need privileges later we fork and
128 * then drop privileges in one of the instances which
129 * will then execute the command and die.
131 * This fixes the security hole for FreeBSD and AIX
132 * where this program needs privileges to access
133 * the system information.
135 void ExecuteExternal()
140 printf("asload: system(%s)\n",Execute
);
142 if( Execute
[0] == '\0' ) {
147 if ( ruid
== euid
) {
153 printf("asload : fork() failed (%s), command not executed",
158 /* parent process simply waits for the child and continues */
159 if ( waitpid(pid
, 0, 0) == -1 ) {
160 printf("asload : waitpid() for child failed (%s)",
166 * child process drops the privileges
167 * executes the command and dies
169 if ( setuid(ruid
) ) {
170 printf("asload : setuid failed (%s), command not executed",
177 int main(int argc
,char *argv
[])
180 unsigned int borderwidth
;
181 char *display_name
= NULL
;
182 char *wname
= "wmload";
187 XClassHint classHint
;
189 Atom _XA_WM_DELETE_WINDOW
= None
;
191 mywmhints
.initial_state
= NormalState
;
193 /* Parse command line options */
196 for(i
=1;i
<argc
;i
++) {
202 if(++i
>=argc
) usage();
203 sscanf(argv
[i
], "%d", &updatespeed
);
206 if(++i
>=argc
) usage();
207 strcpy(&Execute
[0], argv
[i
]);
208 strcat(&Execute
[0], " &");
214 if(++i
>=argc
) usage();
218 mywmhints
.initial_state
= IconicState
;
221 mywmhints
.initial_state
= WithdrawnState
;
224 if(++i
>=argc
) usage();
228 fprintf(stdout
, "\nwmload version: %i.%i.%i\n", major_VER
, minor_VER
, patch_VER
);
229 if(argc
== 2) exit(0);
237 fprintf(stderr
, "\nInvalid argument: %s\n", arg
);
242 /* Open the display */
243 if (!(dpy
= XOpenDisplay(display_name
)))
245 fprintf(stderr
,"wmload: can't open display %s\n",
246 XDisplayName(display_name
));
250 screen
= DefaultScreen(dpy
);
251 Root
= RootWindow(dpy
, screen
);
252 d_depth
= DefaultDepth(dpy
, screen
);
253 x_fd
= XConnectionNumber(dpy
);
254 _XA_WM_DELETE_WINDOW
= XInternAtom (dpy
, "WM_DELETE_WINDOW", False
);
256 /* Convert XPM Data to XImage */
259 /* Create a window to hold the banner */
260 mysizehints
.flags
= USSize
|USPosition
;
264 back_pix
= GetColor("white");
265 fore_pix
= GetColor("black");
267 XWMGeometry(dpy
, screen
, Geometry
, NULL
, (borderwidth
=1), &mysizehints
,
268 &mysizehints
.x
,&mysizehints
.y
,&mysizehints
.width
,&mysizehints
.height
, &i
);
270 mysizehints
.width
= wmload
.attributes
.width
;
271 mysizehints
.height
= wmload
.attributes
.height
;
273 win
= XCreateSimpleWindow(dpy
,Root
,mysizehints
.x
,mysizehints
.y
,
274 mysizehints
.width
,mysizehints
.height
,
275 borderwidth
,fore_pix
,back_pix
);
276 iconwin
= XCreateSimpleWindow(dpy
,win
,mysizehints
.x
,mysizehints
.y
,
277 mysizehints
.width
,mysizehints
.height
,
278 borderwidth
,fore_pix
,back_pix
);
281 XSetWMNormalHints(dpy
, win
, &mysizehints
);
282 classHint
.res_name
= "wmload";
283 classHint
.res_class
= "WMLoad";
284 XSetClassHint(dpy
, win
, &classHint
);
286 XSelectInput(dpy
,win
,MW_EVENTS
);
287 XSelectInput(dpy
,iconwin
,MW_EVENTS
);
288 XSetCommand(dpy
,win
,argv
,argc
);
290 if (XStringListToTextProperty(&wname
, 1, &name
) ==0) {
291 fprintf(stderr
, "wmload: can't allocate window name\n");
294 XSetWMName(dpy
, win
, &name
);
296 /* Create a GC for drawing */
297 gcm
= GCForeground
|GCBackground
|GCGraphicsExposures
;
298 gcv
.foreground
= fore_pix
;
299 gcv
.background
= back_pix
;
300 gcv
.graphics_exposures
= FALSE
;
301 NormalGC
= XCreateGC(dpy
, Root
, gcm
, &gcv
);
303 if (ONLYSHAPE
) { /* try to make shaped window here */
304 pixmask
= XCreateBitmapFromData(dpy
, win
, (char *)mask2_bits
, mask2_width
,
306 XShapeCombineMask(dpy
, win
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
307 XShapeCombineMask(dpy
, iconwin
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
310 mywmhints
.icon_window
= iconwin
;
311 mywmhints
.icon_x
= mysizehints
.x
;
312 mywmhints
.icon_y
= mysizehints
.y
;
313 mywmhints
.window_group
= win
;
314 mywmhints
.flags
= StateHint
| IconWindowHint
| IconPositionHint
316 XSetWMHints(dpy
, win
, &mywmhints
);
317 XSetWMProtocols (dpy
, win
, &_XA_WM_DELETE_WINDOW
, 1);
322 RedrawWindow(&visible
);
325 if (actualtime
!= time(0))
327 actualtime
= time(0);
329 if(actualtime
% updatespeed
== 0)
332 RedrawWindow(&visible
);
336 while (XPending(dpy
))
338 XNextEvent(dpy
,&Event
);
342 if(Event
.xexpose
.count
== 0 )
343 RedrawWindow(&visible
);
349 if ((Event
.xclient
.format
!= 32) ||
350 ((Atom
)Event
.xclient
.data
.l
[0] != _XA_WM_DELETE_WINDOW
))
353 XFreeGC(dpy
, NormalGC
);
354 XDestroyWindow(dpy
, iconwin
);
355 XDestroyWindow(dpy
, win
);
365 poll((struct poll
*) 0, (size_t) 0, 50);
371 ts
.tv_nsec
= 50000000L; /* 5/100 sec */
372 nanosleep(&ts
, NULL
);
379 /*****************************************************************************/
380 void nocolor(char *a
, char *b
)
382 fprintf(stderr
,"wmload: can't %s %s\n", a
,b
);
385 /*****************************************************************************/
386 /* convert the XPMIcons to XImage */
389 static char **alt_xpm
;
391 XWindowAttributes attributes
;
393 char tempc1
[12],tempc2
[12],tempc3
[12];
394 float colr
,colg
,colb
;
396 alt_xpm
=ONLYSHAPE
? mask_xpm
: back_xpm
;
398 /* for the colormap */
399 XGetWindowAttributes(dpy
,Root
,&attributes
);
401 /* get user-defined color or validate the default */
402 if (!XParseColor (dpy
, attributes
.colormap
, LedColor
, &col
))
404 nocolor("parse",LedColor
);
408 /* scale down the Xcolor values */
409 colr
= col
.red
/ 257;
410 colg
= col
.green
/ 257;
411 colb
= col
.blue
/ 257;
412 /* the brightest color */
413 sprintf(tempc1
, "S c #%.2x%.2x%.2x", (int)colr
, (int)colg
, (int)colb
);
414 back_xpm
[47] = tempc1
;
416 /* make medium color */
417 colr
= (colr
/100) *89;
418 colg
= (colg
/100) *89;
419 colb
= (colb
/100) *89;
420 sprintf(tempc2
, "R c #%.2x%.2x%.2x", (int)colr
, (int)colg
, (int)colb
);
421 back_xpm
[46] = tempc2
;
423 /* make darkest color */
424 colr
= (colr
/100) *89;
425 colg
= (colg
/100) *89;
426 colb
= (colb
/100) *89;
427 sprintf(tempc3
, "Q c #%.2x%.2x%.2x", (int)colr
, (int)colg
, (int)colb
);
428 back_xpm
[45] = tempc3
;
431 wmload
.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
432 ret
= XpmCreatePixmapFromData(dpy
, Root
, alt_xpm
, &wmload
.pixmap
,
433 &wmload
.mask
, &wmload
.attributes
);
434 if(ret
!= XpmSuccess
)
435 {fprintf(stderr
, "%s\n", ERR_colorcells
);exit(1);}
437 visible
.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
438 ret
= XpmCreatePixmapFromData(dpy
, Root
, back_xpm
, &visible
.pixmap
,
439 &visible
.mask
, &visible
.attributes
);
440 if(ret
!= XpmSuccess
)
441 {fprintf(stderr
, "%s\n", ERR_colorcells
);exit(1);}
445 /*****************************************************************************/
446 /* Removes expose events for a specific window from the queue */
447 int flush_expose (Window w
)
452 while (XCheckTypedWindowEvent (dpy
, w
, Expose
, &dummy
))i
++;
456 /*****************************************************************************/
457 /* Draws the icon window */
458 void RedrawWindow( XpmIcon
*v
)
460 flush_expose (iconwin
);
461 XCopyArea(dpy
,v
->pixmap
,iconwin
,NormalGC
,
462 0,0,v
->attributes
.width
, v
->attributes
.height
,0,0);
464 XCopyArea(dpy
,v
->pixmap
,win
,NormalGC
,
465 0,0,v
->attributes
.width
, v
->attributes
.height
,0,0);
469 /*****************************************************************************/
470 Pixel
GetColor(char *name
)
473 XWindowAttributes attributes
;
475 XGetWindowAttributes(dpy
,Root
,&attributes
);
477 if (!XParseColor (dpy
, attributes
.colormap
, name
, &color
))
479 nocolor("parse",name
);
481 else if(!XAllocColor (dpy
, attributes
.colormap
, &color
))
483 nocolor("alloc",name
);
488 /*****************************************************************************/
491 /* Save the 4 base colors in wmload */
492 XCopyArea(dpy
, visible
.pixmap
, wmload
.pixmap
, NormalGC
,
493 6,6,3,52, Shape(6), Shape(6));
495 /* Copy the base panel to visible */
496 XCopyArea(dpy
, wmload
.pixmap
, visible
.pixmap
, NormalGC
,
497 0,0,mysizehints
.width
, mysizehints
.height
, 0 ,0);
499 /* Remove the 4 base colors from visible */
500 XCopyArea(dpy
, visible
.pixmap
, visible
.pixmap
, NormalGC
,
501 Shape(9),Shape(6),3,52, Shape(6), Shape(6));
505 skip_token(const char *p
)
507 while (isspace(*p
)) p
++;
508 while (*p
&& !isspace(*p
)) p
++;
512 void GetLoad(int Maximum
, int *usr
, int *nice
, int *sys
, int *free
)
514 char buffer
[100];/*[4096+1];*/
519 fd
= open("/proc/stat", O_RDONLY
);
520 len
= read(fd
, buffer
, sizeof(buffer
)-1);
524 p
= skip_token(buffer
); /* "cpu" */
526 cp_time
[0] = strtoul(p
, &p
, 0); /* user */
527 cp_time
[1] = strtoul(p
, &p
, 0); /* nice */
528 cp_time
[2] = strtoul(p
, &p
, 0); /* system */
529 cp_time
[3] = strtoul(p
, &p
, 0); /* idle */
531 if( (*usr
= cp_time
[0] - last
[0]) < 0 ) *usr
= 0 ;
532 if( (*nice
= cp_time
[1] - last
[1]) < 0 ) *nice
= 0 ;
533 if( (*sys
= cp_time
[2] - last
[2]) < 0 ) *sys
= 0 ;
534 if( (*free
= cp_time
[3] - last
[3]) < 0 ) *free
= 0 ;
536 total
= *usr
+ *nice
+ *sys
+ *free
;
538 last
[0] = cp_time
[0];
539 last
[1] = cp_time
[1];
540 last
[2] = cp_time
[2];
541 last
[3] = cp_time
[3];
543 *usr
= rint(Maximum
* (float)(*usr
) /total
);
544 *nice
=rint(Maximum
* (float)(*nice
) /total
);
545 *sys
= rint(Maximum
* (float)(*sys
) /total
);
546 *free
= rint(Maximum
* (float)(*free
) /total
);
551 int UserTime
, NiceTime
, SystemTime
, FreeTime
, act
, constrain
;
552 GetLoad( 52, &UserTime
, &NiceTime
, &SystemTime
, &FreeTime
);
554 constrain
= (UserTime
+ NiceTime
+ SystemTime
+ FreeTime
);
557 if(FreeTime
> 0) FreeTime
--;
558 else if(SystemTime
> 0) SystemTime
--;
559 else if(NiceTime
> 0) NiceTime
--;
560 else if(UserTime
> 0) UserTime
--;
562 else if(constrain
== 51) FreeTime
++;
565 XCopyArea(dpy
, visible
.pixmap
, visible
.pixmap
, NormalGC
,
566 Shape(7), Shape(6), 51, 52, Shape(6), Shape(6));
572 XCopyArea(dpy
, wmload
.pixmap
, visible
.pixmap
, NormalGC
,
573 Shape(6), Shape(6), 1, UserTime
, Shape(57), Shape(act
));
576 act
= act
- NiceTime
;
578 XCopyArea(dpy
, wmload
.pixmap
, visible
.pixmap
, NormalGC
,
579 Shape(7), Shape(6), 1, NiceTime
, Shape(57), Shape(act
));
582 act
= act
- SystemTime
;
584 XCopyArea(dpy
, wmload
.pixmap
, visible
.pixmap
, NormalGC
,
585 Shape(8), Shape(6), 1, SystemTime
, Shape(57), Shape(act
));
589 XCopyArea(dpy
, wmload
.pixmap
, visible
.pixmap
, NormalGC
,
590 Shape(9), Shape(6), 1, FreeTime
, Shape(57), Shape(6));