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 200112L
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
) {
148 if (system( Execute
) == -1)
149 fprintf(stderr
, "system(%s) returned an error",
155 printf("asload : fork() failed (%s), command not executed",
160 /* parent process simply waits for the child and continues */
161 if ( waitpid(pid
, 0, 0) == -1 ) {
162 printf("asload : waitpid() for child failed (%s)",
168 * child process drops the privileges
169 * executes the command and dies
171 if ( setuid(ruid
) ) {
172 printf("asload : setuid failed (%s), command not executed",
176 if (system( Execute
) == -1)
177 fprintf(stderr
, "system(%s) returned an error", Execute
);
180 int main(int argc
,char *argv
[])
183 unsigned int borderwidth
;
184 char *display_name
= NULL
;
185 char *wname
= "wmload";
190 XClassHint classHint
;
192 Atom _XA_WM_DELETE_WINDOW
= None
;
194 mywmhints
.initial_state
= NormalState
;
196 /* Parse command line options */
199 for(i
=1;i
<argc
;i
++) {
205 if(++i
>=argc
) usage();
206 sscanf(argv
[i
], "%d", &updatespeed
);
209 if(++i
>=argc
) usage();
210 strcpy(&Execute
[0], argv
[i
]);
211 strcat(&Execute
[0], " &");
217 if(++i
>=argc
) usage();
221 mywmhints
.initial_state
= IconicState
;
224 mywmhints
.initial_state
= WithdrawnState
;
227 if(++i
>=argc
) usage();
231 fprintf(stdout
, "\nwmload version: %i.%i.%i\n", major_VER
, minor_VER
, patch_VER
);
232 if(argc
== 2) exit(0);
240 fprintf(stderr
, "\nInvalid argument: %s\n", arg
);
245 /* Open the display */
246 if (!(dpy
= XOpenDisplay(display_name
)))
248 fprintf(stderr
,"wmload: can't open display %s\n",
249 XDisplayName(display_name
));
253 screen
= DefaultScreen(dpy
);
254 Root
= RootWindow(dpy
, screen
);
255 d_depth
= DefaultDepth(dpy
, screen
);
256 x_fd
= XConnectionNumber(dpy
);
257 _XA_WM_DELETE_WINDOW
= XInternAtom (dpy
, "WM_DELETE_WINDOW", False
);
259 /* Convert XPM Data to XImage */
262 /* Create a window to hold the banner */
263 mysizehints
.flags
= USSize
|USPosition
;
267 back_pix
= GetColor("white");
268 fore_pix
= GetColor("black");
270 XWMGeometry(dpy
, screen
, Geometry
, NULL
, (borderwidth
=1), &mysizehints
,
271 &mysizehints
.x
,&mysizehints
.y
,&mysizehints
.width
,&mysizehints
.height
, &i
);
273 mysizehints
.width
= wmload
.attributes
.width
;
274 mysizehints
.height
= wmload
.attributes
.height
;
276 win
= XCreateSimpleWindow(dpy
,Root
,mysizehints
.x
,mysizehints
.y
,
277 mysizehints
.width
,mysizehints
.height
,
278 borderwidth
,fore_pix
,back_pix
);
279 iconwin
= XCreateSimpleWindow(dpy
,win
,mysizehints
.x
,mysizehints
.y
,
280 mysizehints
.width
,mysizehints
.height
,
281 borderwidth
,fore_pix
,back_pix
);
284 XSetWMNormalHints(dpy
, win
, &mysizehints
);
285 classHint
.res_name
= "wmload";
286 classHint
.res_class
= "WMLoad";
287 XSetClassHint(dpy
, win
, &classHint
);
289 XSelectInput(dpy
,win
,MW_EVENTS
);
290 XSelectInput(dpy
,iconwin
,MW_EVENTS
);
291 XSetCommand(dpy
,win
,argv
,argc
);
293 if (XStringListToTextProperty(&wname
, 1, &name
) ==0) {
294 fprintf(stderr
, "wmload: can't allocate window name\n");
297 XSetWMName(dpy
, win
, &name
);
299 /* Create a GC for drawing */
300 gcm
= GCForeground
|GCBackground
|GCGraphicsExposures
;
301 gcv
.foreground
= fore_pix
;
302 gcv
.background
= back_pix
;
303 gcv
.graphics_exposures
= FALSE
;
304 NormalGC
= XCreateGC(dpy
, Root
, gcm
, &gcv
);
306 if (ONLYSHAPE
) { /* try to make shaped window here */
307 pixmask
= XCreateBitmapFromData(dpy
, win
, (char *)mask2_bits
, mask2_width
,
309 XShapeCombineMask(dpy
, win
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
310 XShapeCombineMask(dpy
, iconwin
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
313 mywmhints
.icon_window
= iconwin
;
314 mywmhints
.icon_x
= mysizehints
.x
;
315 mywmhints
.icon_y
= mysizehints
.y
;
316 mywmhints
.window_group
= win
;
317 mywmhints
.flags
= StateHint
| IconWindowHint
| IconPositionHint
319 XSetWMHints(dpy
, win
, &mywmhints
);
320 XSetWMProtocols (dpy
, win
, &_XA_WM_DELETE_WINDOW
, 1);
325 RedrawWindow(&visible
);
328 if (actualtime
!= time(0))
330 actualtime
= time(0);
332 if(actualtime
% updatespeed
== 0)
335 RedrawWindow(&visible
);
339 while (XPending(dpy
))
341 XNextEvent(dpy
,&Event
);
345 if(Event
.xexpose
.count
== 0 )
346 RedrawWindow(&visible
);
352 if ((Event
.xclient
.format
!= 32) ||
353 ((Atom
)Event
.xclient
.data
.l
[0] != _XA_WM_DELETE_WINDOW
))
356 XFreeGC(dpy
, NormalGC
);
357 XDestroyWindow(dpy
, iconwin
);
358 XDestroyWindow(dpy
, win
);
368 poll((struct poll
*) 0, (size_t) 0, 50);
374 ts
.tv_nsec
= 50000000L; /* 5/100 sec */
375 nanosleep(&ts
, NULL
);
382 /*****************************************************************************/
383 void nocolor(char *a
, char *b
)
385 fprintf(stderr
,"wmload: can't %s %s\n", a
,b
);
388 /*****************************************************************************/
389 /* convert the XPMIcons to XImage */
392 static char **alt_xpm
;
394 XWindowAttributes attributes
;
396 char tempc1
[12],tempc2
[12],tempc3
[12];
397 float colr
,colg
,colb
;
399 alt_xpm
=ONLYSHAPE
? mask_xpm
: back_xpm
;
401 /* for the colormap */
402 XGetWindowAttributes(dpy
,Root
,&attributes
);
404 /* get user-defined color or validate the default */
405 if (!XParseColor (dpy
, attributes
.colormap
, LedColor
, &col
))
407 nocolor("parse",LedColor
);
411 /* scale down the Xcolor values */
412 colr
= col
.red
/ 257;
413 colg
= col
.green
/ 257;
414 colb
= col
.blue
/ 257;
415 /* the brightest color */
416 sprintf(tempc1
, "S c #%.2x%.2x%.2x", (int)colr
, (int)colg
, (int)colb
);
417 back_xpm
[47] = tempc1
;
419 /* make medium color */
420 colr
= (colr
/100) *89;
421 colg
= (colg
/100) *89;
422 colb
= (colb
/100) *89;
423 sprintf(tempc2
, "R c #%.2x%.2x%.2x", (int)colr
, (int)colg
, (int)colb
);
424 back_xpm
[46] = tempc2
;
426 /* make darkest color */
427 colr
= (colr
/100) *89;
428 colg
= (colg
/100) *89;
429 colb
= (colb
/100) *89;
430 sprintf(tempc3
, "Q c #%.2x%.2x%.2x", (int)colr
, (int)colg
, (int)colb
);
431 back_xpm
[45] = tempc3
;
434 wmload
.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
435 ret
= XpmCreatePixmapFromData(dpy
, Root
, alt_xpm
, &wmload
.pixmap
,
436 &wmload
.mask
, &wmload
.attributes
);
437 if(ret
!= XpmSuccess
)
438 {fprintf(stderr
, "%s\n", ERR_colorcells
);exit(1);}
440 visible
.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
441 ret
= XpmCreatePixmapFromData(dpy
, Root
, back_xpm
, &visible
.pixmap
,
442 &visible
.mask
, &visible
.attributes
);
443 if(ret
!= XpmSuccess
)
444 {fprintf(stderr
, "%s\n", ERR_colorcells
);exit(1);}
448 /*****************************************************************************/
449 /* Removes expose events for a specific window from the queue */
450 int flush_expose (Window w
)
455 while (XCheckTypedWindowEvent (dpy
, w
, Expose
, &dummy
))i
++;
459 /*****************************************************************************/
460 /* Draws the icon window */
461 void RedrawWindow( XpmIcon
*v
)
463 flush_expose (iconwin
);
464 XCopyArea(dpy
,v
->pixmap
,iconwin
,NormalGC
,
465 0,0,v
->attributes
.width
, v
->attributes
.height
,0,0);
467 XCopyArea(dpy
,v
->pixmap
,win
,NormalGC
,
468 0,0,v
->attributes
.width
, v
->attributes
.height
,0,0);
472 /*****************************************************************************/
473 Pixel
GetColor(char *name
)
476 XWindowAttributes attributes
;
478 XGetWindowAttributes(dpy
,Root
,&attributes
);
480 if (!XParseColor (dpy
, attributes
.colormap
, name
, &color
))
482 nocolor("parse",name
);
484 else if(!XAllocColor (dpy
, attributes
.colormap
, &color
))
486 nocolor("alloc",name
);
491 /*****************************************************************************/
494 /* Save the 4 base colors in wmload */
495 XCopyArea(dpy
, visible
.pixmap
, wmload
.pixmap
, NormalGC
,
496 6,6,3,52, Shape(6), Shape(6));
498 /* Copy the base panel to visible */
499 XCopyArea(dpy
, wmload
.pixmap
, visible
.pixmap
, NormalGC
,
500 0,0,mysizehints
.width
, mysizehints
.height
, 0 ,0);
502 /* Remove the 4 base colors from visible */
503 XCopyArea(dpy
, visible
.pixmap
, visible
.pixmap
, NormalGC
,
504 Shape(9),Shape(6),3,52, Shape(6), Shape(6));
508 skip_token(const char *p
)
510 while (isspace(*p
)) p
++;
511 while (*p
&& !isspace(*p
)) p
++;
515 void GetLoad(int Maximum
, int *usr
, int *nice
, int *sys
, int *free
)
517 char buffer
[100];/*[4096+1];*/
522 fd
= open("/proc/stat", O_RDONLY
);
523 len
= read(fd
, buffer
, sizeof(buffer
)-1);
527 p
= skip_token(buffer
); /* "cpu" */
529 cp_time
[0] = strtoul(p
, &p
, 0); /* user */
530 cp_time
[1] = strtoul(p
, &p
, 0); /* nice */
531 cp_time
[2] = strtoul(p
, &p
, 0); /* system */
532 cp_time
[3] = strtoul(p
, &p
, 0); /* idle */
534 if( (*usr
= cp_time
[0] - last
[0]) < 0 ) *usr
= 0 ;
535 if( (*nice
= cp_time
[1] - last
[1]) < 0 ) *nice
= 0 ;
536 if( (*sys
= cp_time
[2] - last
[2]) < 0 ) *sys
= 0 ;
537 if( (*free
= cp_time
[3] - last
[3]) < 0 ) *free
= 0 ;
539 total
= *usr
+ *nice
+ *sys
+ *free
;
541 last
[0] = cp_time
[0];
542 last
[1] = cp_time
[1];
543 last
[2] = cp_time
[2];
544 last
[3] = cp_time
[3];
546 *usr
= rint(Maximum
* (float)(*usr
) /total
);
547 *nice
=rint(Maximum
* (float)(*nice
) /total
);
548 *sys
= rint(Maximum
* (float)(*sys
) /total
);
549 *free
= rint(Maximum
* (float)(*free
) /total
);
554 int UserTime
, NiceTime
, SystemTime
, FreeTime
, act
, constrain
;
555 GetLoad( 52, &UserTime
, &NiceTime
, &SystemTime
, &FreeTime
);
557 constrain
= (UserTime
+ NiceTime
+ SystemTime
+ FreeTime
);
560 if(FreeTime
> 0) FreeTime
--;
561 else if(SystemTime
> 0) SystemTime
--;
562 else if(NiceTime
> 0) NiceTime
--;
563 else if(UserTime
> 0) UserTime
--;
565 else if(constrain
== 51) FreeTime
++;
568 XCopyArea(dpy
, visible
.pixmap
, visible
.pixmap
, NormalGC
,
569 Shape(7), Shape(6), 51, 52, Shape(6), Shape(6));
575 XCopyArea(dpy
, wmload
.pixmap
, visible
.pixmap
, NormalGC
,
576 Shape(6), Shape(6), 1, UserTime
, Shape(57), Shape(act
));
579 act
= act
- NiceTime
;
581 XCopyArea(dpy
, wmload
.pixmap
, visible
.pixmap
, NormalGC
,
582 Shape(7), Shape(6), 1, NiceTime
, Shape(57), Shape(act
));
585 act
= act
- SystemTime
;
587 XCopyArea(dpy
, wmload
.pixmap
, visible
.pixmap
, NormalGC
,
588 Shape(8), Shape(6), 1, SystemTime
, Shape(57), Shape(act
));
592 XCopyArea(dpy
, wmload
.pixmap
, visible
.pixmap
, NormalGC
,
593 Shape(9), Shape(6), 1, FreeTime
, Shape(57), Shape(6));