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
135
136
137
|
#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_ptr = NULL;
XTextProperty *status_props_ptr = NULL;
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_ptr->dpy != NULL ){
if ( XCloseDisplay(current_status_ptr->dpy) == BadGC )
fputs( "XCloseDisplay returned BadGC error\n", stderr );
current_status_ptr->dpy = NULL;
}
memset( (void*)status_props_ptr, 0, sizeof(*status_props_ptr) );
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 );
struct status current_status = {0};
memset( (void*)¤t_status, 0, sizeof(struct status) );
XTextProperty status_props = {
.value = (unsigned char*)¤t_status.status,
.encoding = XA_STRING,
.format = 8,
.nitems = 0
};
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 );
current_status_ptr = ¤t_status;
status_props_ptr = &status_props;
status_update_loop( ¤t_status, &status_props );
exit( EXIT_SUCCESS );
}
|