chiark / gitweb /
systemd-analyze: use argparse instead of getopt
[elogind.git] / src / shared / util.c
index 2d4a4c1102bd2f082c247f2c38dc27e873321210..5a326ec43512f7cd85927daaa2f105f0e8da7b9a 100644 (file)
@@ -57,6 +57,8 @@
 #include <sys/vfs.h>
 #include <linux/magic.h>
 #include <limits.h>
+#include <langinfo.h>
+#include <locale.h>
 
 #include "macro.h"
 #include "util.h"
@@ -75,6 +77,10 @@ char **saved_argv = NULL;
 static volatile unsigned cached_columns = 0;
 static volatile unsigned cached_lines = 0;
 
+bool is_efiboot(void) {
+        return access("/sys/firmware/efi", F_OK) >= 0;
+}
+
 size_t page_size(void) {
         static __thread size_t pgsz = 0;
         long r;
@@ -148,6 +154,9 @@ usec_t timespec_load(const struct timespec *ts) {
             ts->tv_nsec == (long) -1)
                 return (usec_t) -1;
 
+        if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC)
+                return (usec_t) -1;
+
         return
                 (usec_t) ts->tv_sec * USEC_PER_SEC +
                 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
@@ -175,6 +184,9 @@ usec_t timeval_load(const struct timeval *tv) {
             tv->tv_usec == (suseconds_t) -1)
                 return (usec_t) -1;
 
+        if ((usec_t) tv->tv_sec > (UINT64_MAX - tv->tv_usec) / USEC_PER_SEC)
+                return (usec_t) -1;
+
         return
                 (usec_t) tv->tv_sec * USEC_PER_SEC +
                 (usec_t) tv->tv_usec;
@@ -371,7 +383,7 @@ int safe_atou(const char *s, unsigned *ret_u) {
         errno = 0;
         l = strtoul(s, &x, 0);
 
-        if (!x || *x || errno)
+        if (!x || x == s || *x || errno)
                 return errno ? -errno : -EINVAL;
 
         if ((unsigned long) (unsigned) l != l)
@@ -391,7 +403,7 @@ int safe_atoi(const char *s, int *ret_i) {
         errno = 0;
         l = strtol(s, &x, 0);
 
-        if (!x || *x || errno)
+        if (!x || x == s || *x || errno)
                 return errno ? -errno : -EINVAL;
 
         if ((long) (int) l != l)
@@ -411,7 +423,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
         errno = 0;
         l = strtoull(s, &x, 0);
 
-        if (!x || *x || errno)
+        if (!x || x == s || *x || errno)
                 return errno ? -errno : -EINVAL;
 
         *ret_llu = l;
@@ -428,7 +440,7 @@ int safe_atolli(const char *s, long long int *ret_lli) {
         errno = 0;
         l = strtoll(s, &x, 0);
 
-        if (!x || *x || errno)
+        if (!x || x == s || *x || errno)
                 return errno ? -errno : -EINVAL;
 
         *ret_lli = l;
@@ -5201,7 +5213,7 @@ static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_IDLE] = "idle"
 };
 
-DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
 
 static const char *const sigchld_code_table[] = {
         [CLD_EXITED] = "exited",
@@ -5237,7 +5249,7 @@ static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
         [LOG_FAC(LOG_LOCAL7)] = "local7"
 };
 
-DEFINE_STRING_TABLE_LOOKUP(log_facility_unshifted, int);
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
 
 static const char *const log_level_table[] = {
         [LOG_EMERG] = "emerg",
@@ -5250,7 +5262,7 @@ static const char *const log_level_table[] = {
         [LOG_DEBUG] = "debug"
 };
 
-DEFINE_STRING_TABLE_LOOKUP(log_level, int);
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
 
 static const char* const sched_policy_table[] = {
         [SCHED_OTHER] = "other",
@@ -5260,7 +5272,7 @@ static const char* const sched_policy_table[] = {
         [SCHED_RR] = "rr"
 };
 
-DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
 
 static const char* const rlimit_table[] = {
         [RLIMIT_CPU] = "LimitCPU",
@@ -5290,7 +5302,7 @@ static const char* const ip_tos_table[] = {
         [IPTOS_LOWCOST] = "low-cost",
 };
 
-DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
 
 static const char *const __signal_table[] = {
         [SIGHUP] = "HUP",
@@ -6109,3 +6121,45 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
         }
         return NULL;
 }
+
+bool is_locale_utf8(void) {
+        const char *set;
+        static int cached_answer = -1;
+
+        if (cached_answer >= 0)
+                goto out;
+
+        if (!setlocale(LC_ALL, "")) {
+                cached_answer = true;
+                goto out;
+        }
+
+        set = nl_langinfo(CODESET);
+        if (!set) {
+                cached_answer = true;
+                goto out;
+        }
+
+        cached_answer = streq(set, "UTF-8");
+out:
+        return (bool)cached_answer;
+}
+
+const char *draw_special_char(DrawSpecialChar ch) {
+        static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
+                /* UTF-8 */ {
+                        [DRAW_TREE_VERT]          = "\342\224\202 ",            /* │  */
+                        [DRAW_TREE_BRANCH]        = "\342\224\234\342\224\200", /* ├─ */
+                        [DRAW_TREE_RIGHT]         = "\342\224\224\342\224\200", /* └─ */
+                        [DRAW_TRIANGULAR_BULLET]  = "\342\200\243 ",            /* ‣  */
+                },
+                /* ASCII fallback */ {
+                        [DRAW_TREE_VERT]          = "| ",
+                        [DRAW_TREE_BRANCH]        = "|-",
+                        [DRAW_TREE_RIGHT]         = "`-",
+                        [DRAW_TRIANGULAR_BULLET]  = "> ",
+                }
+        };
+
+        return draw_table[!is_locale_utf8()][ch];
+}