From fc8ff5392be9b0da93aab7533cba0fbcd05dce76 Mon Sep 17 00:00:00 2001 From: stderr64 Date: Sun, 25 Jan 2026 19:20:42 +0200 Subject: First commit --- .gitignore | 1 + Makefile | 10 +++++ dwmtimestatus.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 dwmtimestatus.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6ba65df --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +CC=gcc + +rel: + $(CC) -O2 -mavx2 -Werror -Wall -pedantic ./dwmtimestatus.c -o ./dwmtimestatus -lX11 + +debug: + $(CC) -O2 -mavx2 -ggdb -Werror -Wall -pedantic ./dwmtimestatus.c -o ./dwmtimestatus -lX11 + +clean: + rm ./dwmtimestatus 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 ); +} -- cgit v1.2.3-95-g76ab