summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile10
-rw-r--r--dwmtimestatus.c133
3 files changed, 144 insertions, 0 deletions
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 <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*)&current_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*)&current_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*)&current_status, 0, sizeof(struct status) );
+ memset( (void*)&status_props, 0, sizeof(XTextProperty) );
+ status_props.value = (unsigned char*)&current_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( &current_status, &status_props );
+ exit( EXIT_SUCCESS );
+}