diff options
| author | stderr64 <stderr64@null.net> | 2026-01-25 19:20:42 +0200 |
|---|---|---|
| committer | stderr64 <stderr64@null.net> | 2026-01-25 19:20:42 +0200 |
| commit | fc8ff5392be9b0da93aab7533cba0fbcd05dce76 (patch) | |
| tree | 18740143e1e01e03111dbb7d3d45809ade76ecbf /dwmtimestatus.c | |
| download | dwmtimestatus-fc8ff5392be9b0da93aab7533cba0fbcd05dce76.tar.gz dwmtimestatus-fc8ff5392be9b0da93aab7533cba0fbcd05dce76.tar.zst | |
First commit
Diffstat (limited to 'dwmtimestatus.c')
| -rw-r--r-- | dwmtimestatus.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/dwmtimestatus.c b/dwmtimestatus.c new file mode 100644 index 0000000..cd5c879 --- /dev/null +++ b/dwmtimestatus.c @@ -0,0 +1,133 @@ +#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 = {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) ); + memset( (void*)&status_props, 0, sizeof(XTextProperty) ); + status_props.value = (unsigned char*)¤t_status.status; + status_props.encoding = XA_STRING; + status_props.format = 8; + 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 ); +} |
