1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <assert.h>
#include <string.h>
#include <time.h>
#include <getopt.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xproto.h>
#include <X11/Xutil.h>
struct status{
Display *dpy;
Window root;
char status[256];
const char *time_format;
unsigned int status_update_interval;
};
struct sigaction *s_act = NULL;
struct status current_status = {0};
XTextProperty status_props = {
.value = (unsigned char*)¤t_status.status,
.encoding = XA_STRING,
.format = 8,
.nitems = 0
};
void sighandler( int si_code, siginfo_t *si_info, void *si_adr ){
int exit_status = EXIT_SUCCESS;
if ( si_code == SIGSEGV ){
fprintf( stderr, "error: SIGSEGV received: %s\n", strerror(errno) );
exit_status = EXIT_FAILURE;
}
else
{
fprintf( stdout, "Received signal %i, exiting\n", si_code );
}
if ( current_status.dpy != NULL ){
if ( XCloseDisplay(current_status.dpy) == BadGC )
fputs( "XCloseDisplay returned BadGC error\n", stderr );
current_status.dpy = NULL;
}
memset( (void*)¤t_status, 0, sizeof(struct status) );
memset( (void*)&status_props, 0, sizeof(XTextProperty) );
free( s_act );
s_act = NULL;
exit( exit_status );
}
void update_status( struct status *status_info, XTextProperty *xprops ){
if ( status_info == NULL || xprops == NULL )
return;
XSetTextProperty( status_info->dpy, status_info->root, xprops, XA_WM_NAME );
XSync( status_info->dpy, 0 );
return;
}
void status_update_loop( struct status *cstatus, XTextProperty *status_properties ){
if ( cstatus == NULL || status_properties == NULL ){
fputs( "error: status struct pointer is NULL\n", stderr );
return;
}
time_t current_time = 0;
struct tm *time_info = NULL;
while ( 1 ){
memset( (void*)&cstatus->status, 0, sizeof(cstatus->status) * sizeof(char) );
current_time = time( NULL );
time_info = localtime( (const time_t*)¤t_time );
if ( (status_properties->nitems = (long unsigned int)strftime((char*)&cstatus->status, (sizeof(cstatus->status) * sizeof(char)) - 1, cstatus->time_format, time_info)) <= 0 ){
sleep( cstatus->status_update_interval );
continue;
}
update_status( cstatus, status_properties );
sleep( cstatus->status_update_interval );
}
return;
}
int main( int argc, char **args ){
if ( argc < 5 ){
fprintf( stdout, "Usage: %s -i [update interval in seconds] -d [display] -f [time format]\n", args[0] );
exit( EXIT_SUCCESS );
}
s_act = (struct sigaction*)calloc( 1, sizeof(struct sigaction) );
if ( s_act == NULL ){
perror( "sigaction struct allocation failed" );
exit( EXIT_FAILURE );
}
if ( sigemptyset(&s_act->sa_mask) == -1 ){
perror( "failed to create empty sigset" );
free( s_act );
exit( EXIT_FAILURE );
}
s_act->sa_flags = SA_SIGINFO;
s_act->sa_sigaction = &sighandler;
if ( sigaction(SIGABRT, (const struct sigaction*)s_act, NULL) == -1 ){
perror( "failed to set SIGABRT handler" );
free( s_act );
exit( EXIT_FAILURE );
}
assert( sigaction(SIGSEGV, (const struct sigaction*)s_act, NULL) != -1 );
assert( sigaction(SIGINT, (const struct sigaction*)s_act, NULL) != -1 );
assert( sigaction(SIGTERM, (const struct sigaction*)s_act, NULL) != -1 );
assert( sigaction(SIGPIPE, (const struct sigaction*)s_act, NULL) != -1 );
memset( (void*)¤t_status, 0, sizeof(struct status) );
const char *optstring = "i:d:f:";
int opt_char = 0;
while ( (opt_char = getopt(argc, args, optstring)) != -1 ){
switch (opt_char){
case 'i':
current_status.status_update_interval = (unsigned int)strtoull( optarg, NULL, 10 );
assert( errno == 0 );
break;
case 'd':
current_status.dpy = XOpenDisplay( (_Xconst char*)optarg );
assert( current_status.dpy != NULL );
break;
case 'f':
current_status.time_format = (const char*)optarg;
assert( current_status.time_format != NULL && strlen(current_status.time_format) > 0 );
break;
default:
break;
}
}
current_status.root = DefaultRootWindow( current_status.dpy );
status_update_loop( ¤t_status, &status_props );
exit( EXIT_SUCCESS );
}
|