summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md9
-rw-r--r--configure.ac1
-rw-r--r--man/i3status.man83
-rw-r--r--src/print_cpu_temperature.c21
-rw-r--r--src/print_cpu_usage.c11
-rw-r--r--src/print_ddate.c190
-rw-r--r--src/print_disk_info.c74
-rw-r--r--src/print_eth_info.c37
-rw-r--r--src/print_volume.c26
-rw-r--r--testcases/020-percentliteral-cpu_temperature/expected_output.txt1
-rw-r--r--testcases/020-percentliteral-cpu_temperature/i3status.conf10
-rw-r--r--testcases/020-percentliteral-cpu_temperature/temp1_input1
-rw-r--r--testcases/020-percentliteral-ddate/expected_output.txt1
-rw-r--r--testcases/020-percentliteral-ddate/i3status.conf9
14 files changed, 219 insertions, 255 deletions
diff --git a/README.md b/README.md
index d818ee6..2d398c8 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# i3status
+# i3status
## Description
@@ -16,19 +16,20 @@ i3status has the following dependencies:
* libyajl-dev
* libasound2-dev
* libnl-genl-3-dev
+ * autoconf (compile-time only dependency)
* asciidoc (only for the documentation)
* libpulse-dev (for getting the current volume using PulseAudio)
On debian-based systems, the following line will install all requirements:
```bash
-apt-get install libconfuse-dev libyajl-dev libasound2-dev libiw-dev asciidoc libpulse-dev libnl-genl-3-dev
+apt-get install autoconf libconfuse-dev libyajl-dev libasound2-dev libiw-dev asciidoc libpulse-dev libnl-genl-3-dev
```
## Upstream
i3status is developed at https://github.com/i3/i3status
-## Compilation
+## Compilation
Prefer installing i3status via your Linux distribution’s package manager.
@@ -38,7 +39,7 @@ If you absolutely have to build from source, use:
autoreconf -fi
mkdir build
cd build
- ../configure
+ ../configure --disable-sanitizers
make -j8
sudo make install
```
diff --git a/configure.ac b/configure.ac
index c6750e3..11caa33 100644
--- a/configure.ac
+++ b/configure.ac
@@ -101,7 +101,6 @@ case $host_os in
;;
netbsd*)
AC_SEARCH_LIBS([prop_string_create], [prop])
- AC_SEARCH_LIBS([_oss_ioctl], [ossaudio])
;;
esac
diff --git a/man/i3status.man b/man/i3status.man
index c2849c3..9699529 100644
--- a/man/i3status.man
+++ b/man/i3status.man
@@ -182,10 +182,10 @@ none::
Does not use any color codes. Separates values by the pipe symbol by default.
This should be used with i3bar and can be used for custom scripts.
-It's also possible to use the color_good, color_degraded, color_bad directives
-to define specific colors per module. If one of these directives is defined
-in a module section its value will override the value defined in the general
-section just for this module.
+It's also possible to use the +color_good+, +color_degraded+, +color_bad+
+directives to define specific colors per module. If one of these directives is
+defined in a module section its value will override the value defined in the
+general section just for this module.
If you don't fancy the vertical separators between modules i3status/i3bar
uses by default, you can employ the +separator+ directive to configure how
@@ -235,8 +235,8 @@ best available public IPv6 address on your computer).
Gets used, free, available and total amount of bytes on the given mounted filesystem.
-These values can also be expressed in percentages with the percentage_used,
-percentage_free, percentage_avail and percentage_used_of_avail formats.
+These values can also be expressed in percentages with the +percentage_used+,
++percentage_free+, +percentage_avail+ and +percentage_used_of_avail+ formats.
Byte sizes are presented in a human readable format using a set of prefixes
whose type can be specified via the "prefix_type" option. Three sets of
@@ -250,16 +250,16 @@ SI prefixes (k, M, G, T) represent multiples of powers of 1000.
custom::
The custom prefixes (K, M, G, T) represent multiples of powers of 1024.
-It is possible to define a low_threshold that causes the disk text to be
-displayed using color_bad. The low_threshold type can be of threshold_type
+It is possible to define a +low_threshold+ that causes the disk text to be
+displayed using +color_bad+. The +low_threshold+ type can be of +threshold_type+
"bytes_free", "bytes_avail", "percentage_free", or "percentage_avail", where
the former two can be prepended by a generic prefix (k, m, g, t) having
-prefix_type. So, if you configure low_threshold to 2, threshold_type to
+prefix_type. So, if you configure +low_threshold+ to 2, +threshold_type+ to
"gbytes_avail", and prefix_type to "binary", and the remaining available disk
-space is below 2 GiB, it will be colored bad. If not specified, threshold_type
-is assumed to be "percentage_avail" and low_threshold to be set to 0, which
+space is below 2 GiB, it will be colored bad. If not specified, +threshold_type+
+is assumed to be "percentage_avail" and +low_threshold+ to be set to 0, which
implies no coloring at all. You can customize the output format when below
-low_threshold with format_below_threshold.
++low_threshold+ with +format_below_threshold.+
You can define a different format with the option "format_not_mounted"
which is used if the path does not exist or is not a mount point. Defaults to "".
@@ -283,7 +283,7 @@ which is used if the path does not exist or is not a mount point. Defaults to ""
Expands the given path to a pidfile and checks if the process ID found inside
is valid (that is, if the process is running). You can use this to check if
a specific application, such as a VPN client or your DHCP client is running.
-There also is an option "format_down". You can hide the output with
+There also is an option +format_down+. You can hide the output with
+format_down=""+.
*Example order*: +run_watch DHCP+
@@ -294,7 +294,7 @@ There also is an option "format_down". You can hide the output with
Checks if the given path exists in the filesystem. You can use this to check if
something is active, like for example a VPN tunnel managed by NetworkManager.
-There also is an option "format_down". You can hide the output with
+There also is an option +format_down+. You can hide the output with
+format_down=""+.
*Example order*: +path_exists VPN+
@@ -358,14 +358,15 @@ If you want the battery percentage to be shown in another format, use
+format_percentage = "%.00f%s"+
If your battery is represented in a non-standard path in /sys, be sure to
-modify the "path" property accordingly, i.e. pointing to the uevent file on
+modify the +path+ property accordingly, i.e. pointing to the uevent file on
your system. The first occurrence of %d gets replaced with the battery number,
but you can just hard-code a path as well.
It is possible to define a low_threshold that causes the battery text to be
-colored red. The low_threshold type can be of threshold_type "time" or
-"percentage". So, if you configure low_threshold to 10 and threshold_type to
-"time", and your battery lasts another 9 minutes, it will be colored red.
+colored +color_bad+. The +low_threshold+ type can be of +threshold_type+ "time"
+or "percentage". So, if you configure +low_threshold+ to 10 and +threshold_type+
+to "time", and your battery lasts another 9 minutes, it will be colored
++color_bad+.
To show an aggregate of all batteries in the system, use "all" as the number. In
this case (for Linux), the /sys path must contain the "%d" sequence. Otherwise,
@@ -407,10 +408,10 @@ FULL) is used.
=== CPU-Temperature
Gets the temperature of the given thermal zone. It is possible to
-define a max_threshold that will color the temperature red in case the
+define a +max_threshold+ that will color the temperature red in case the
specified thermal zone is getting too hot. Defaults to 75 degrees C. The
-output format when above max_threshold can be customized with
-format_above_threshold.
+output format when above +max_threshold+ can be customized with
++format_above_threshold+.
*Example order*: +cpu_temperature 0+
@@ -427,17 +428,17 @@ format_above_threshold.
Gets the percentual CPU usage from +/proc/stat+ (Linux) or +sysctl(3)+
(FreeBSD/OpenBSD).
-It is possible to define a max_threshold that will color the load
-value red in case the CPU average over the last interval is getting
+It is possible to define a +max_threshold+ that will color the load
+value with +color_bad+ in case the CPU average over the last interval is getting
higher than the configured threshold. Defaults to 95. The output
-format when above max_threshold can be customized with
-format_above_threshold.
+format when above +max_threshold+ can be customized with
++format_above_threshold+.
-It is possible to define a degraded_threshold that will color the load
-value yellow in case the CPU average over the last interval is getting
-higher than the configured threshold. Defaults to 90. The output format
+It is possible to define a +degraded_threshold+ that will color the load
+value with +color_degraded+ in case the CPU average over the last interval is
+getting higher than the configured threshold. Defaults to 90. The output format
when above degraded threshold can be customized with
-format_above_degraded_threshold.
++format_above_degraded_threshold+.
For displaying the Nth CPU usage, you can use the %cpu<N> format string,
starting from %cpu0. This feature is currently not supported in FreeBSD.
@@ -464,11 +465,11 @@ available. These will print human readable values. It's also possible to prefix
the placeholders with +percentage_+ to get a value in percent.
It's possible to define a +threshold_degraded+ and a +threshold_critical+ to
-color the status bar output in yellow or red, if the available memory falls
-below the given threshold. Possible values of the threshold can be any integer,
-suffixed with an iec symbol (+T+, +G+, +M+, +K+). Alternatively, the integer
-can be suffixed by a percent sign, which then rets evaluated relatively to
-total memory.
+color the status bar output in +color_degraded+ or +color_bad+, if the available
+memory falls below the given threshold. Possible values of the threshold can be
+any integer, suffixed with an iec symbol (+T+, +G+, +M+, +K+). Alternatively,
+the integer can be suffixed by a percent sign, which then rets evaluated
+relatively to total memory.
If the +format_degraded+ parameter is given and either the critical or the
degraded threshold applies, +format_degraded+ will get used as format string.
@@ -510,10 +511,10 @@ methods to distinguish the actually used memory.
Gets the system load (number of processes waiting for CPU time in the last
1, 5 and 15 minutes). It is possible to define a max_threshold that will
-color the load value red in case the load average of the last minute is
+color the load value +color_bad+ in case the load average of the last minute is
getting higher than the configured threshold. Defaults to 5. The output
-format when above max_threshold can be customized with
-format_above_threshold.
+format when above +max_threshold+ can be customized with
++format_above_threshold+.
*Example order*: +load+
@@ -645,9 +646,9 @@ volume master {
Outputs the contents of the specified file. You can use this to check contents
of files on your system, for example /proc/uptime. By default the function only
reads the first 254 characters of the file, if you want to override this set
-the Max_characters option. It will never read beyond the first 4095 characters.
-If the file is not found "no file" will be printed, if the file can't be read
-"error read" will be printed.
+the +Max_characters+ option. It will never read beyond the first 4095
+characters. If the file is not found "no file" will be printed, if the file
+can't be read "error read" will be printed.
*Example order*: read_file UPTIME
@@ -682,7 +683,7 @@ separator::
A boolean value which specifies whether a separator line should be drawn
after this block. The default is true, meaning the separator line will be
drawn. Note that if you disable the separator line, there will still be a
- gap after the block, unless you also use separator_block_width.
+ gap after the block, unless you also use +separator_block_width+.
separator_block_width::
The amount of pixels to leave blank after the block. In the middle of this
gap, a separator symbol will be drawn unless separator is disabled. This is
diff --git a/src/print_cpu_temperature.c b/src/print_cpu_temperature.c
index 01744a1..f94d1a7 100644
--- a/src/print_cpu_temperature.c
+++ b/src/print_cpu_temperature.c
@@ -10,6 +10,8 @@
#include "i3status.h"
+#define STRING_SIZE 20
+
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <err.h>
#include <sys/types.h>
@@ -213,7 +215,6 @@ void print_cpu_temperature_info(yajl_gen json_gen, char *buffer, int zone, const
char *outwalk = buffer;
#ifdef THERMAL_ZONE
const char *selected_format = format;
- const char *walk;
bool colorful_output = false;
char *thermal_zone;
temperature_t temperature;
@@ -248,18 +249,13 @@ void print_cpu_temperature_info(yajl_gen json_gen, char *buffer, int zone, const
selected_format = format_above_threshold;
}
- for (walk = selected_format; *walk != '\0'; walk++) {
- if (*walk != '%') {
- *(outwalk++) = *walk;
-
- } else if (BEGINS_WITH(walk + 1, "degrees")) {
- outwalk += sprintf(outwalk, "%s", temperature.formatted_value);
- walk += strlen("degrees");
+ char string_degrees[STRING_SIZE];
+ snprintf(string_degrees, STRING_SIZE, "%s", temperature.formatted_value);
+ placeholder_t placeholders[] = {
+ {.name = "%degrees", .value = string_degrees}};
- } else {
- *(outwalk++) = '%';
- }
- }
+ const size_t num = sizeof(placeholders) / sizeof(placeholder_t);
+ buffer = format_placeholders(selected_format, &placeholders[0], num);
if (colorful_output) {
END_COLOR;
@@ -269,6 +265,7 @@ void print_cpu_temperature_info(yajl_gen json_gen, char *buffer, int zone, const
free(thermal_zone);
OUTPUT_FULL_TEXT(buffer);
+ free(buffer);
return;
error:
free(thermal_zone);
diff --git a/src/print_cpu_usage.c b/src/print_cpu_usage.c
index 979e082..abf3481 100644
--- a/src/print_cpu_usage.c
+++ b/src/print_cpu_usage.c
@@ -183,7 +183,8 @@ void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format, const
#if defined(__linux__)
else if (BEGINS_WITH(walk + 1, "cpu")) {
int number = -1;
- sscanf(walk + 1, "cpu%d", &number);
+ int length = strlen("cpu");
+ sscanf(walk + 1, "cpu%d%n", &number, &length);
if (number == -1) {
fprintf(stderr, "i3status: provided CPU number cannot be parsed\n");
} else if (number >= cpu_count) {
@@ -194,13 +195,7 @@ void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format, const
int cpu_diff_usage = (cpu_diff_total ? (1000 * (cpu_diff_total - cpu_diff_idle) / cpu_diff_total + 5) / 10 : 0);
outwalk += sprintf(outwalk, "%02d%s", cpu_diff_usage, pct_mark);
}
- int padding = 1;
- int step = 10;
- while (step <= number) {
- step *= 10;
- padding++;
- }
- walk += strlen("cpu") + padding;
+ walk += length;
}
#endif
else {
diff --git a/src/print_ddate.c b/src/print_ddate.c
index 93e652d..1a5258c 100644
--- a/src/print_ddate.c
+++ b/src/print_ddate.c
@@ -9,6 +9,8 @@
#include "i3status.h"
+#define STRING_SIZE 20
+
/* define fixed output-Strings */
char *season_long[5] = {
"Chaos",
@@ -59,116 +61,6 @@ struct disc_time {
int st_tibs_day;
};
-/* Print the date *dt in format *format */
-static int format_output(char *outwalk, char *format, struct disc_time *dt) {
- char *orig_outwalk = outwalk;
- char *i;
- char *tibs_end = 0;
-
- for (i = format; *i != '\0'; i++) {
- if (*i != '%') {
- *(outwalk++) = *i;
- continue;
- }
- switch (*(i + 1)) {
- /* Weekday in long and abbreviation */
- case 'A':
- outwalk += sprintf(outwalk, "%s", day_long[dt->week_day]);
- break;
- case 'a':
- outwalk += sprintf(outwalk, "%s", day_short[dt->week_day]);
- break;
- /* Season in long and abbreviation */
- case 'B':
- outwalk += sprintf(outwalk, "%s", season_long[dt->season]);
- break;
- case 'b':
- outwalk += sprintf(outwalk, "%s", season_short[dt->season]);
- break;
- /* Day of the season (ordinal and cardinal) */
- case 'd':
- outwalk += sprintf(outwalk, "%d", dt->season_day + 1);
- break;
- case 'e':
- outwalk += sprintf(outwalk, "%d", dt->season_day + 1);
- if (dt->season_day > 9 && dt->season_day < 13) {
- outwalk += sprintf(outwalk, "th");
- break;
- }
-
- switch (dt->season_day % 10) {
- case 0:
- outwalk += sprintf(outwalk, "st");
- break;
- case 1:
- outwalk += sprintf(outwalk, "nd");
- break;
- case 2:
- outwalk += sprintf(outwalk, "rd");
- break;
- default:
- outwalk += sprintf(outwalk, "th");
- break;
- }
- break;
- /* YOLD */
- case 'Y':
- outwalk += sprintf(outwalk, "%d", dt->year);
- break;
- /* Holidays */
- case 'H':
- if (dt->season_day == 4) {
- outwalk += sprintf(outwalk, "%s", holidays[dt->season]);
- }
- if (dt->season_day == 49) {
- outwalk += sprintf(outwalk, "%s", holidays[dt->season + 5]);
- }
- break;
- /* Stop parsing the format string, except on Holidays */
- case 'N':
- if (dt->season_day != 4 && dt->season_day != 49) {
- return (outwalk - orig_outwalk);
- }
- break;
- /* Newline- and Tabbing-characters */
- case 'n':
- outwalk += sprintf(outwalk, "\n");
- break;
- case 't':
- outwalk += sprintf(outwalk, "\t");
- break;
- /* The St. Tib's Day replacement */
- case '{':
- tibs_end = strstr(i, "%}");
- if (tibs_end == NULL) {
- i++;
- break;
- }
- if (dt->st_tibs_day) {
- /* We outpt "St. Tib's Day... */
- outwalk += sprintf(outwalk, "St. Tib's Day");
- } else {
- /* ...or parse the substring between %{ and %} ... */
- *tibs_end = '\0';
- outwalk += format_output(outwalk, i + 2, dt);
- *tibs_end = '%';
- }
- /* ...and continue with the rest */
- i = tibs_end;
- break;
- case '}':
- i++;
- break;
- default:
- /* No escape-sequence, so we just skip */
- outwalk += sprintf(outwalk, "%%%c", *(i + 1));
- break;
- }
- i++;
- }
- return (outwalk - orig_outwalk);
-}
-
/* Get the current date and convert it to discordian */
struct disc_time *get_ddate(struct tm *current_tm) {
static struct disc_time dt;
@@ -202,17 +94,83 @@ struct disc_time *get_ddate(struct tm *current_tm) {
void print_ddate(yajl_gen json_gen, char *buffer, const char *format, time_t t) {
char *outwalk = buffer;
- static char *form = NULL;
struct tm current_tm;
struct disc_time *dt;
set_timezone(NULL); /* Use local time. */
localtime_r(&t, &current_tm);
if ((dt = get_ddate(&current_tm)) == NULL)
return;
- if (form == NULL)
- if ((form = malloc(strlen(format) + 1)) == NULL)
- return;
- strcpy(form, format);
- outwalk += format_output(outwalk, form, dt);
+
+ char string_A[STRING_SIZE];
+ char string_a[STRING_SIZE];
+ char string_B[STRING_SIZE];
+ char string_b[STRING_SIZE];
+ char string_d[STRING_SIZE];
+ char string_e[STRING_SIZE];
+ char string_Y[STRING_SIZE];
+ char string_H[STRING_SIZE];
+ char string_N[STRING_SIZE];
+ /* Newline- and Tabbing-characters */
+ char string_n[2] = "\n";
+ char string_t[2] = "\t";
+ char string_tibs_day[14] = "St. Tib's Day";
+
+ /* Weekday in long and abbreviation */
+ snprintf(string_A, STRING_SIZE, "%s", day_long[dt->week_day]);
+ snprintf(string_a, STRING_SIZE, "%s", day_short[dt->week_day]);
+ /* Season in long and abbreviation */
+ snprintf(string_B, STRING_SIZE, "%s", season_long[dt->season]);
+ snprintf(string_b, STRING_SIZE, "%s", season_short[dt->season]);
+ /* Day of the season (ordinal and cardinal) */
+ snprintf(string_d, STRING_SIZE, "%d", dt->season_day + 1);
+ snprintf(string_e, STRING_SIZE, "%d", dt->season_day + 1);
+ if (dt->season_day > 9 && dt->season_day < 13) {
+ strcat(string_e, "th");
+ }
+ switch (dt->season_day % 10) {
+ case 0:
+ strcat(string_e, "st");
+ break;
+ case 1:
+ strcat(string_e, "nd");
+ break;
+ case 2:
+ strcat(string_e, "rd");
+ break;
+ default:
+ strcat(string_e, "th");
+ break;
+ }
+ /* YOLD */
+ snprintf(string_Y, STRING_SIZE, "%d", dt->year);
+ /* Holidays */
+ if (dt->season_day == 4) {
+ snprintf(string_H, STRING_SIZE, "%s", holidays[dt->season]);
+ }
+ if (dt->season_day == 49) {
+ snprintf(string_H, STRING_SIZE, "%s", holidays[dt->season + 5]);
+ }
+ /* Stop parsing the format string, except on Holidays */
+ if (dt->season_day != 4 && dt->season_day != 49) {
+ snprintf(string_N, STRING_SIZE, "%s", "\0");
+ }
+
+ placeholder_t placeholders[] = {
+ {.name = "%A", .value = string_A},
+ {.name = "%a", .value = string_a},
+ {.name = "%B", .value = string_B},
+ {.name = "%b", .value = string_b},
+ {.name = "%d", .value = string_d},
+ {.name = "%e", .value = string_e},
+ {.name = "%Y", .value = string_Y},
+ {.name = "%H", .value = string_H},
+ {.name = "%N", .value = string_N},
+ {.name = "%n", .value = string_n},
+ {.name = "%t", .value = string_t},
+ {.name = "%{", .value = string_tibs_day},
+ {.name = "%}", .value = ""}};
+
+ const size_t num = sizeof(placeholders) / sizeof(placeholder_t);
+ buffer = format_placeholders(format, &placeholders[0], num);
OUTPUT_FULL_TEXT(buffer);
}
diff --git a/src/print_disk_info.c b/src/print_disk_info.c
index 5f12e93..5f510a0 100644
--- a/src/print_disk_info.c
+++ b/src/print_disk_info.c
@@ -20,6 +20,8 @@
#include "i3status.h"
+#define STRING_SIZE 20
+
#define BINARY_BASE UINT64_C(1024)
#define DECIMAL_BASE UINT64_C(1000)
@@ -113,7 +115,6 @@ static bool below_threshold(struct statvfs buf, const char *prefix_type, const c
*/
void print_disk_info(yajl_gen json_gen, char *buffer, const char *path, const char *format, const char *format_below_threshold, const char *format_not_mounted, const char *prefix_type, const char *threshold_type, const double low_threshold) {
const char *selected_format = format;
- const char *walk;
char *outwalk = buffer;
bool colorful_output = false;
bool mounted = false;
@@ -177,50 +178,41 @@ void print_disk_info(yajl_gen json_gen, char *buffer, const char *path, const ch
selected_format = format_below_threshold;
}
- for (walk = selected_format; *walk != '\0'; walk++) {
- if (*walk != '%') {
- *(outwalk++) = *walk;
-
- } else if (BEGINS_WITH(walk + 1, "free")) {
- outwalk += print_bytes_human(outwalk, (uint64_t)buf.f_bsize * (uint64_t)buf.f_bfree, prefix_type);
- walk += strlen("free");
-
- } else if (BEGINS_WITH(walk + 1, "used")) {
- outwalk += print_bytes_human(outwalk, (uint64_t)buf.f_bsize * ((uint64_t)buf.f_blocks - (uint64_t)buf.f_bfree), prefix_type);
- walk += strlen("used");
-
- } else if (BEGINS_WITH(walk + 1, "total")) {
- outwalk += print_bytes_human(outwalk, (uint64_t)buf.f_bsize * (uint64_t)buf.f_blocks, prefix_type);
- walk += strlen("total");
-
- } else if (BEGINS_WITH(walk + 1, "avail")) {
- outwalk += print_bytes_human(outwalk, (uint64_t)buf.f_bsize * (uint64_t)buf.f_bavail, prefix_type);
- walk += strlen("avail");
-
- } else if (BEGINS_WITH(walk + 1, "percentage_free")) {
- outwalk += sprintf(outwalk, "%.01f%s", 100.0 * (double)buf.f_bfree / (double)buf.f_blocks, pct_mark);
- walk += strlen("percentage_free");
-
- } else if (BEGINS_WITH(walk + 1, "percentage_used_of_avail")) {
- outwalk += sprintf(outwalk, "%.01f%s", 100.0 * (double)(buf.f_blocks - buf.f_bavail) / (double)buf.f_blocks, pct_mark);
- walk += strlen("percentage_used_of_avail");
-
- } else if (BEGINS_WITH(walk + 1, "percentage_used")) {
- outwalk += sprintf(outwalk, "%.01f%s", 100.0 * (double)(buf.f_blocks - buf.f_bfree) / (double)buf.f_blocks, pct_mark);
- walk += strlen("percentage_used");
-
- } else if (BEGINS_WITH(walk + 1, "percentage_avail")) {
- outwalk += sprintf(outwalk, "%.01f%s", 100.0 * (double)buf.f_bavail / (double)buf.f_blocks, pct_mark);
- walk += strlen("percentage_avail");
-
- } else {
- *(outwalk++) = '%';
- }
- }
+ char string_free[STRING_SIZE];
+ char string_used[STRING_SIZE];
+ char string_total[STRING_SIZE];
+ char string_avail[STRING_SIZE];
+ char string_percentage_free[STRING_SIZE];
+ char string_percentage_used_of_avail[STRING_SIZE];
+ char string_percentage_used[STRING_SIZE];
+ char string_percentage_avail[STRING_SIZE];
+
+ print_bytes_human(string_free, (uint64_t)buf.f_bsize * (uint64_t)buf.f_bfree, prefix_type);
+ print_bytes_human(string_used, (uint64_t)buf.f_bsize * ((uint64_t)buf.f_blocks - (uint64_t)buf.f_bfree), prefix_type);
+ print_bytes_human(string_total, (uint64_t)buf.f_bsize * (uint64_t)buf.f_blocks, prefix_type);
+ print_bytes_human(string_avail, (uint64_t)buf.f_bsize * (uint64_t)buf.f_bavail, prefix_type);
+ snprintf(string_percentage_free, STRING_SIZE, "%.01f%s", 100.0 * (double)buf.f_bfree / (double)buf.f_blocks, pct_mark);
+ snprintf(string_percentage_used_of_avail, STRING_SIZE, "%.01f%s", 100.0 * (double)(buf.f_blocks - buf.f_bavail) / (double)buf.f_blocks, pct_mark);
+ snprintf(string_percentage_used, STRING_SIZE, "%.01f%s", 100.0 * (double)(buf.f_blocks - buf.f_bfree) / (double)buf.f_blocks, pct_mark);
+ snprintf(string_percentage_avail, STRING_SIZE, "%.01f%s", 100.0 * (double)buf.f_bavail / (double)buf.f_blocks, pct_mark);
+
+ placeholder_t placeholders[] = {
+ {.name = "%free", .value = string_free},
+ {.name = "%used", .value = string_used},
+ {.name = "%total", .value = string_total},
+ {.name = "%avail", .value = string_avail},
+ {.name = "%percentage_free", .value = string_percentage_free},
+ {.name = "%percentage_used_of_avail", .value = string_percentage_used_of_avail},
+ {.name = "%percentage_used", .value = string_percentage_used},
+ {.name = "%percentage_avail", .value = string_percentage_avail}};
+
+ const size_t num = sizeof(placeholders) / sizeof(placeholder_t);
+ buffer = format_placeholders(selected_format, &placeholders[0], num);
if (colorful_output)
END_COLOR;
*outwalk = '\0';
OUTPUT_FULL_TEXT(buffer);
+ free(buffer);
}
diff --git a/src/print_eth_info.c b/src/print_eth_info.c
index 81e74a7..c0d6649 100644
--- a/src/print_eth_info.c
+++ b/src/print_eth_info.c
@@ -15,6 +15,8 @@
#include "i3status.h"
+#define STRING_SIZE 20
+
#if defined(__linux__)
#include <linux/ethtool.h>
#include <linux/sockios.h>
@@ -137,8 +139,8 @@ static int print_eth_speed(char *outwalk, const char *interface) {
void print_eth_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down) {
const char *format = format_down; // default format
- const char *walk;
char *outwalk = buffer;
+ size_t num = 0;
INSTANCE(interface);
@@ -177,29 +179,24 @@ void print_eth_info(yajl_gen json_gen, char *buffer, const char *interface, cons
START_COLOR("color_good");
}
-out:
- for (walk = format; *walk != '\0'; walk++) {
- if (*walk != '%') {
- *(outwalk++) = *walk;
-
- } else if (BEGINS_WITH(walk + 1, "ip")) {
- outwalk += sprintf(outwalk, "%s", ip_address);
- walk += strlen("ip");
-
- } else if (BEGINS_WITH(walk + 1, "speed")) {
- outwalk += print_eth_speed(outwalk, interface);
- walk += strlen("speed");
+ char string_ip[STRING_SIZE];
+ char string_speed[STRING_SIZE];
+ char string_interface[STRING_SIZE];
+ snprintf(string_ip, STRING_SIZE, "%s", ip_address);
+ print_eth_speed(string_speed, interface);
+ snprintf(string_interface, STRING_SIZE, "%s", interface);
+ placeholder_t placeholders[] = {
+ {.name = "%ip", .value = string_ip},
+ {.name = "%speed", .value = string_speed},
+ {.name = "%interface", .value = string_interface}};
+ num = sizeof(placeholders) / sizeof(placeholder_t);
- } else if (BEGINS_WITH(walk + 1, "interface")) {
- outwalk += sprintf(outwalk, "%s", interface);
- walk += strlen("interface");
+out:
+ buffer = format_placeholders(format, &placeholders[0], num);
- } else {
- *(outwalk++) = '%';
- }
- }
END_COLOR;
free(ipv4_address);
free(ipv6_address);
OUTPUT_FULL_TEXT(buffer);
+ free(buffer);
}
diff --git a/src/print_volume.c b/src/print_volume.c
index 575024a..89955a8 100644
--- a/src/print_volume.c
+++ b/src/print_volume.c
@@ -15,13 +15,13 @@
#include <math.h>
#endif
-#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
+#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <fcntl.h>
#include <unistd.h>
#include <sys/soundcard.h>
#endif
-#if defined(__OpenBSD__)
+#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <fcntl.h>
#include <unistd.h>
#include <sys/audioio.h>
@@ -261,7 +261,7 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *
mixerpath = defaultmixer;
if ((mixfd = open(mixerpath, O_RDWR)) < 0) {
-#if defined(__OpenBSD__)
+#if defined(__NetBSD__) || defined(__OpenBSD__)
warn("audioio: Cannot open mixer");
#else
warn("OSS: Cannot open mixer");
@@ -272,7 +272,7 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *
if (mixer_idx > 0)
free(mixerpath);
-#if defined(__OpenBSD__)
+#if defined(__NetBSD__) || defined(__OpenBSD__)
int oclass_idx = -1, master_idx = -1, master_mute_idx = -1;
int master_next = AUDIO_MIXER_LAST;
mixer_devinfo_t devinfo, devinfo2;
@@ -327,15 +327,17 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *
vol = (int)vinfo.un.value.level[AUDIO_MIXER_LEVEL_MONO];
}
- vinfo.dev = master_mute_idx;
- vinfo.type = AUDIO_MIXER_ENUM;
- if (ioctl(mixfd, AUDIO_MIXER_READ, &vinfo) == -1)
- goto out;
+ if (master_mute_idx != -1) {
+ vinfo.dev = master_mute_idx;
+ vinfo.type = AUDIO_MIXER_ENUM;
+ if (ioctl(mixfd, AUDIO_MIXER_READ, &vinfo) == -1)
+ goto out;
- if (master_mute_idx != -1 && vinfo.un.ord) {
- START_COLOR("color_degraded");
- fmt = fmt_muted;
- pbval = 0;
+ if (vinfo.un.ord) {
+ START_COLOR("color_degraded");
+ fmt = fmt_muted;
+ pbval = 0;
+ }
}
#else
diff --git a/testcases/020-percentliteral-cpu_temperature/expected_output.txt b/testcases/020-percentliteral-cpu_temperature/expected_output.txt
new file mode 100644
index 0000000..a0c0525
--- /dev/null
+++ b/testcases/020-percentliteral-cpu_temperature/expected_output.txt
@@ -0,0 +1 @@
+I can %haz literal% % ?
diff --git a/testcases/020-percentliteral-cpu_temperature/i3status.conf b/testcases/020-percentliteral-cpu_temperature/i3status.conf
new file mode 100644
index 0000000..b1c4008
--- /dev/null
+++ b/testcases/020-percentliteral-cpu_temperature/i3status.conf
@@ -0,0 +1,10 @@
+general {
+ output_format = "none"
+}
+
+order += "cpu_temperature 0"
+
+cpu_temperature 0 {
+ format = "I can %haz literal% % ?"
+ path = "testcases/020-percentliteral-cpu_temperature/temp1_input"
+} \ No newline at end of file
diff --git a/testcases/020-percentliteral-cpu_temperature/temp1_input b/testcases/020-percentliteral-cpu_temperature/temp1_input
new file mode 100644
index 0000000..a90c8f8
--- /dev/null
+++ b/testcases/020-percentliteral-cpu_temperature/temp1_input
@@ -0,0 +1 @@
+37000 \ No newline at end of file
diff --git a/testcases/020-percentliteral-ddate/expected_output.txt b/testcases/020-percentliteral-ddate/expected_output.txt
new file mode 100644
index 0000000..a0c0525
--- /dev/null
+++ b/testcases/020-percentliteral-ddate/expected_output.txt
@@ -0,0 +1 @@
+I can %haz literal% % ?
diff --git a/testcases/020-percentliteral-ddate/i3status.conf b/testcases/020-percentliteral-ddate/i3status.conf
new file mode 100644
index 0000000..0e0f9c3
--- /dev/null
+++ b/testcases/020-percentliteral-ddate/i3status.conf
@@ -0,0 +1,9 @@
+general {
+ output_format = "none"
+}
+
+order += "ddate"
+
+ddate {
+ format = "I can %haz literal% % ?"
+}