sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

slstatus-signals-1.0.patch (5036B)


      1 From 8eaf9e1d101d93c784b12902eb71d5b2985a6985 Mon Sep 17 00:00:00 2001
      2 From: sewn <sewn@disroot.org>
      3 Date: Sat, 12 Oct 2024 20:45:16 +0300
      4 Subject: [PATCH] implement signals & turns
      5 
      6 ---
      7  config.def.h |  11 ++++--
      8  slstatus.c   | 108 ++++++++++++++++++++++++++++++++-------------------
      9  2 files changed, 75 insertions(+), 44 deletions(-)
     10 
     11 diff --git a/config.def.h b/config.def.h
     12 index d805331..a89127b 100644
     13 --- a/config.def.h
     14 +++ b/config.def.h
     15 @@ -6,8 +6,8 @@ const unsigned int interval = 1000;
     16  /* text to show if no value can be retrieved */
     17  static const char unknown_str[] = "n/a";
     18  
     19 -/* maximum output string length */
     20 -#define MAXLEN 2048
     21 +/* maximum command output length */
     22 +#define CMDLEN 128
     23  
     24  /*
     25   * function            description                     argument (example)
     26 @@ -64,6 +64,9 @@ static const char unknown_str[] = "n/a";
     27   * wifi_perc           WiFi signal in percent          interface name (wlan0)
     28   */
     29  static const struct arg args[] = {
     30 -	/* function format          argument */
     31 -	{ datetime, "%s",           "%F %T" },
     32 +	/* function format          argument turn signal */
     33 +	{ datetime, "%s",           "%F %T", 1,   -1 },
     34  };
     35 +
     36 +/* maximum output string length */
     37 +#define MAXLEN CMDLEN * LEN(args)
     38 diff --git a/slstatus.c b/slstatus.c
     39 index fd31313..d5efd35 100644
     40 --- a/slstatus.c
     41 +++ b/slstatus.c
     42 @@ -15,20 +15,19 @@ struct arg {
     43  	const char *(*func)(const char *);
     44  	const char *fmt;
     45  	const char *args;
     46 +	unsigned int turn;
     47 +	int signal;
     48  };
     49  
     50  char buf[1024];
     51 -static volatile sig_atomic_t done;
     52 +static int sflag = 0;
     53 +static volatile sig_atomic_t done, upsigno;
     54  static Display *dpy;
     55  
     56  #include "config.h"
     57 +#define MAXLEN CMDLEN * LEN(args)
     58  
     59 -static void
     60 -terminate(const int signo)
     61 -{
     62 -	if (signo != SIGUSR1)
     63 -		done = 1;
     64 -}
     65 +static char statuses[LEN(args)][CMDLEN] = {0};
     66  
     67  static void
     68  difftimespec(struct timespec *res, struct timespec *a, struct timespec *b)
     69 @@ -44,17 +43,61 @@ usage(void)
     70  	die("usage: %s [-v] [-s] [-1]", argv0);
     71  }
     72  
     73 +static void
     74 +printstatus(unsigned int iter)
     75 +{
     76 +	size_t i;
     77 +	char status[MAXLEN];
     78 +	const char *res;
     79 +
     80 +	for (i = 0; i < LEN(args); i++) {
     81 +		if (!((!iter && !upsigno) || upsigno == SIGUSR1 ||
     82 +			(!upsigno && args[i].turn > 0 && !(iter % args[i].turn)) ||
     83 +			(args[i].signal >= 0 && upsigno - SIGRTMIN == args[i].signal)))
     84 +			continue;
     85 +
     86 +		if (!(res = args[i].func(args[i].args)))
     87 +			res = unknown_str;
     88 +
     89 +		if (esnprintf(statuses[i], sizeof(statuses[i]), args[i].fmt, res) < 0)
     90 +			break;
     91 +	}
     92 +
     93 +	status[0] = '\0';
     94 +	for (i = 0; i < LEN(args); i++)
     95 +		strcat(status, statuses[i]);
     96 +	status[strlen(status)] = '\0';
     97 +
     98 +	if (sflag) {
     99 +		puts(status);
    100 +		fflush(stdout);
    101 +		if (ferror(stdout))
    102 +			die("puts:");
    103 +	} else {
    104 +		if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0)
    105 +			die("XStoreName: Allocation failed");
    106 +		XFlush(dpy);
    107 +	}
    108 +}
    109 +
    110 +
    111 +static void
    112 +sighandler(const int signo)
    113 +{
    114 +	if ((signo <= SIGRTMAX && signo >= SIGRTMIN) || signo == SIGUSR1)
    115 +		upsigno = signo;
    116 +	else
    117 +		done = 1;
    118 +}
    119 +
    120  int
    121  main(int argc, char *argv[])
    122  {
    123  	struct sigaction act;
    124  	struct timespec start, current, diff, intspec, wait;
    125 -	size_t i, len;
    126 -	int sflag, ret;
    127 -	char status[MAXLEN];
    128 -	const char *res;
    129 +	unsigned int iter = 0;
    130 +	int i, ret;
    131  
    132 -	sflag = 0;
    133  	ARGBEGIN {
    134  	case 'v':
    135  		die("slstatus-"VERSION);
    136 @@ -72,11 +115,12 @@ main(int argc, char *argv[])
    137  		usage();
    138  
    139  	memset(&act, 0, sizeof(act));
    140 -	act.sa_handler = terminate;
    141 +	act.sa_handler = sighandler;
    142  	sigaction(SIGINT,  &act, NULL);
    143  	sigaction(SIGTERM, &act, NULL);
    144 -	act.sa_flags |= SA_RESTART;
    145  	sigaction(SIGUSR1, &act, NULL);
    146 +	for (i = SIGRTMIN; i <= SIGRTMAX; i++)
    147 +		sigaction(i, &act, NULL);
    148  
    149  	if (!sflag && !(dpy = XOpenDisplay(NULL)))
    150  		die("XOpenDisplay: Failed to open display");
    151 @@ -85,28 +129,7 @@ main(int argc, char *argv[])
    152  		if (clock_gettime(CLOCK_MONOTONIC, &start) < 0)
    153  			die("clock_gettime:");
    154  
    155 -		status[0] = '\0';
    156 -		for (i = len = 0; i < LEN(args); i++) {
    157 -			if (!(res = args[i].func(args[i].args)))
    158 -				res = unknown_str;
    159 -
    160 -			if ((ret = esnprintf(status + len, sizeof(status) - len,
    161 -			                     args[i].fmt, res)) < 0)
    162 -				break;
    163 -
    164 -			len += ret;
    165 -		}
    166 -
    167 -		if (sflag) {
    168 -			puts(status);
    169 -			fflush(stdout);
    170 -			if (ferror(stdout))
    171 -				die("puts:");
    172 -		} else {
    173 -			if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0)
    174 -				die("XStoreName: Allocation failed");
    175 -			XFlush(dpy);
    176 -		}
    177 +		printstatus(iter++);
    178  
    179  		if (!done) {
    180  			if (clock_gettime(CLOCK_MONOTONIC, &current) < 0)
    181 @@ -117,10 +140,15 @@ main(int argc, char *argv[])
    182  			intspec.tv_nsec = (interval % 1000) * 1E6;
    183  			difftimespec(&wait, &intspec, &diff);
    184  
    185 -			if (wait.tv_sec >= 0 &&
    186 -			    nanosleep(&wait, NULL) < 0 &&
    187 -			    errno != EINTR)
    188 -					die("nanosleep:");
    189 +			do {
    190 +					if (errno == EINTR) {
    191 +						printstatus(0);
    192 +						errno = upsigno = 0;
    193 +					}
    194 +					ret = nanosleep(&wait, &wait);
    195 +			} while (wait.tv_sec >= 0 && ret < 0 && !done);
    196 +			if (ret < 0 && errno != EINTR)
    197 +				die("nanosleep:");
    198  		}
    199  	} while (!done);
    200  
    201 -- 
    202 2.46.2
    203