We remove the hack with the sleep and global "delay"-variable and use a
monotonic clock to derive the desired monotonic properties of the tool.
Inside each function that demands a personal delay we can then just do a
nanosleep() and be done with it.
It's a shame that timespec is so ugly to work with, but there's really
no way to make it more beautiful. However, at this cost though we
finally can set the interval times in milliseconds and not only just
seconds.
We remove setlocale(), because nothing good ever came out of this
function.
Besides that we have some more code refactoring, especially in the
argument loop which saves us a bit of complexity.
/* See LICENSE file for copyright and license details. */
/* See LICENSE file for copyright and license details. */
-/* how often to update the statusbar (min value == 1) */
-static const int update_interval = 1;
+/* interval between updates (in ms) */
+static const int interval = 1000;
/* text to show if no value can be retrieved */
static const char unknown_str[] = "n/a";
/* text to show if no value can be retrieved */
static const char unknown_str[] = "n/a";
#include <ifaddrs.h>
#include <limits.h>
#include <linux/wireless.h>
#include <ifaddrs.h>
#include <limits.h>
#include <linux/wireless.h>
#include <netdb.h>
#include <pwd.h>
#include <signal.h>
#include <netdb.h>
#include <pwd.h>
#include <signal.h>
static const char *wifi_essid(const char *iface);
char *argv0;
static const char *wifi_essid(const char *iface);
char *argv0;
-static unsigned short int delay = 0;
static unsigned short int done;
static Display *dpy;
static unsigned short int done;
static Display *dpy;
static const char *
cpu_perc(void)
{
static const char *
cpu_perc(void)
{
int n, perc;
long double a[4], b[4];
FILE *fp;
int n, perc;
long double a[4], b[4];
FILE *fp;
if (n != 4)
return unknown_str;
if (n != 4)
return unknown_str;
- delay++;
- sleep(delay);
+ delay.tv_sec = (interval / 2) / 1000;
+ delay.tv_nsec = ((interval / 2) % 1000) * 1000000;
+ nanosleep(&delay, NULL);
fp = fopen("/proc/stat", "r");
if (fp == NULL) {
fp = fopen("/proc/stat", "r");
if (fp == NULL) {
+static void
+difftimespec(struct timespec *res, struct timespec *a, struct timespec *b)
+{
+ res->tv_sec = a->tv_sec - b->tv_sec - (a->tv_nsec < b->tv_nsec);
+ res->tv_nsec = a->tv_nsec - b->tv_nsec +
+ (a->tv_nsec < b->tv_nsec) * 1000000000;
+}
+
static void
usage(void)
{
static void
usage(void)
{
int
main(int argc, char *argv[])
{
int
main(int argc, char *argv[])
{
+ struct timespec start, current, diff, intspec, wait;
size_t i, len;
int sflag = 0;
size_t i, len;
int sflag = 0;
- char status_string[MAXLEN];
- char *element;
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);
- if (!sflag) {
- dpy = XOpenDisplay(NULL);
- if (!dpy) {
- fprintf(stderr, "slstatus: cannot open display");
- exit(1);
- }
+ if (!sflag && !(dpy = XOpenDisplay(NULL))) {
+ fprintf(stderr, "slstatus: cannot open display");
+ return 1;
- setlocale(LC_ALL, "");
-
- status_string[0] = '\0';
-
- for (element = status_string, i = len = 0; i < LEN(args);
- ++i, element += len) {
- argument = args[i];
- len = snprintf(element, sizeof(status_string)-1 - len,
- argument.fmt,
- argument.func(argument.args));
- if (len >= sizeof(status_string)) {
- status_string[sizeof(status_string)-1] = '\0';
- break;
+ clock_gettime(CLOCK_MONOTONIC, &start);
+
+ status[0] = '\0';
+ for (i = len = 0; i < LEN(args); i++) {
+ len += snprintf(status + len, sizeof(status) - len,
+ args[i].fmt, args[i].func(args[i].args));
+
+ if (len >= sizeof(status)) {
+ status[sizeof(status) - 1] = '\0';
- printf("%s\n", status_string);
+ printf("%s\n", status);
- XStoreName(dpy, DefaultRootWindow(dpy), status_string);
+ XStoreName(dpy, DefaultRootWindow(dpy), status);
- if ((update_interval - delay) <= 0) {
- delay = 0;
- continue;
- } else {
- sleep(update_interval - delay);
- delay = 0;
+ if (!done) {
+ clock_gettime(CLOCK_MONOTONIC, ¤t);
+ difftimespec(&diff, ¤t, &start);
+
+ intspec.tv_sec = interval / 1000;
+ intspec.tv_nsec = (interval % 1000) * 1000000;
+ difftimespec(&wait, &intspec, &diff);
+
+ if (wait.tv_sec >= 0) {
+ nanosleep(&wait, NULL);
+ }