chiark / gitweb /
journalctl: reset cached column count on SIGWINCH
[elogind.git] / src / shared / util.c
index 6a40cf1d805d0d991a2b2dc6df244f76fa4f1a90..e0156868ade4e4259af439ab3fa5b9c77236cfa6 100644 (file)
@@ -70,6 +70,7 @@
 
 int saved_argc = 0;
 char **saved_argv = NULL;
+int parsed_columns = 0;
 
 size_t page_size(void) {
         static __thread size_t pgsz = 0;
@@ -1108,7 +1109,7 @@ int get_process_exe(pid_t pid, char **name) {
         return r;
 }
 
-int get_process_uid(pid_t pid, uid_t *uid) {
+static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
         char *p;
         FILE *f;
         int r;
@@ -1140,8 +1141,8 @@ int get_process_uid(pid_t pid, uid_t *uid) {
 
                 l = strstrip(line);
 
-                if (startswith(l, "Uid:")) {
-                        l += 4;
+                if (startswith(l, field)) {
+                        l += strlen(field);
                         l += strspn(l, WHITESPACE);
 
                         l[strcspn(l, WHITESPACE)] = 0;
@@ -1159,6 +1160,14 @@ finish:
         return r;
 }
 
+int get_process_uid(pid_t pid, uid_t *uid) {
+        return get_process_id(pid, "Uid:", uid);
+}
+
+int get_process_gid(pid_t pid, gid_t *gid) {
+        return get_process_id(pid, "Gid:", gid);
+}
+
 char *strnappend(const char *s, const char *suffix, size_t b) {
         size_t a;
         char *r;
@@ -1176,8 +1185,11 @@ char *strnappend(const char *s, const char *suffix, size_t b) {
         assert(suffix);
 
         a = strlen(s);
+        if (b > ((size_t) -1) - a)
+                return NULL;
 
-        if (!(r = new(char, a+b+1)))
+        r = new(char, a+b+1);
+        if (!r)
                 return NULL;
 
         memcpy(r, s, a);
@@ -2948,9 +2960,10 @@ int dir_is_empty(const char *path) {
                 return -errno;
 
         for (;;) {
-                struct dirent buf, *de;
+                struct dirent *de;
+                union dirent_storage buf;
 
-                r = readdir_r(d, &buf, &de);
+                r = readdir_r(d, &buf.de, &de);
                 if (r > 0)
                         return -r;
 
@@ -3252,12 +3265,13 @@ int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct
         }
 
         for (;;) {
-                struct dirent buf, *de;
+                struct dirent *de;
+                union dirent_storage buf;
                 bool is_dir, keep_around;
                 struct stat st;
                 int r;
 
-                r = readdir_r(d, &buf, &de);
+                r = readdir_r(d, &buf.de, &de);
                 if (r != 0 && ret == 0) {
                         ret = -r;
                         break;
@@ -3488,10 +3502,10 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
         }
 }
 
-void status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
-        char *s = NULL;
+int status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
         static const char status_indent[] = "         "; /* "[" STATUS "] " */
-        int fd = -1;
+        _cleanup_free_ char *s = NULL;
+        _cleanup_close_ int fd = -1;
         struct iovec iovec[5];
         int n = 0;
 
@@ -3501,11 +3515,11 @@ void status_vprintf(const char *status, bool ellipse, const char *format, va_lis
          * optional and go exclusively to the console. */
 
         if (vasprintf(&s, format, ap) < 0)
-                goto finish;
+                return log_oom();
 
         fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
         if (fd < 0)
-                goto finish;
+                return fd;
 
         if (ellipse) {
                 char *e;
@@ -3516,7 +3530,7 @@ void status_vprintf(const char *status, bool ellipse, const char *format, va_lis
                 if (c <= 0)
                         c = 80;
 
-                sl = status ? strlen(status_indent) : 0;
+                sl = status ? sizeof(status_indent)-1 : 0;
 
                 emax = c - sl - 1;
                 if (emax < 3)
@@ -3543,53 +3557,40 @@ void status_vprintf(const char *status, bool ellipse, const char *format, va_lis
         IOVEC_SET_STRING(iovec[n++], s);
         IOVEC_SET_STRING(iovec[n++], "\n");
 
-        writev(fd, iovec, n);
-
-finish:
-        free(s);
+        if (writev(fd, iovec, n) < 0)
+                return -errno;
 
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        return 0;
 }
 
-void status_printf(const char *status, bool ellipse, const char *format, ...) {
+int status_printf(const char *status, bool ellipse, const char *format, ...) {
         va_list ap;
+        int r;
 
         assert(format);
 
         va_start(ap, format);
-        status_vprintf(status, ellipse, format, ap);
+        r = status_vprintf(status, ellipse, format, ap);
         va_end(ap);
+
+        return r;
 }
 
-void status_welcome(void) {
-        char *pretty_name = NULL, *ansi_color = NULL;
-        const char *const_pretty = NULL, *const_color = NULL;
+int status_welcome(void) {
         int r;
+        _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
 
-        if ((r = parse_env_file("/etc/os-release", NEWLINE,
-                                "PRETTY_NAME", &pretty_name,
-                                "ANSI_COLOR", &ansi_color,
-                                NULL)) < 0) {
+        r = parse_env_file("/etc/os-release", NEWLINE,
+                           "PRETTY_NAME", &pretty_name,
+                           "ANSI_COLOR", &ansi_color,
+                           NULL);
+        if (r < 0 && r != -ENOENT)
+                log_warning("Failed to read /etc/os-release: %s", strerror(-r));
 
-                if (r != -ENOENT)
-                        log_warning("Failed to read /etc/os-release: %s", strerror(-r));
-        }
-
-        if (!pretty_name && !const_pretty)
-                const_pretty = "Linux";
-
-        if (!ansi_color && !const_color)
-                const_color = "1";
-
-        status_printf(NULL,
-                      false,
-                      "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
-                      const_color ? const_color : ansi_color,
-                      const_pretty ? const_pretty : pretty_name);
-
-        free(ansi_color);
-        free(pretty_name);
+        return status_printf(NULL, false,
+                             "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
+                             isempty(ansi_color) ? "1" : ansi_color,
+                             isempty(pretty_name) ? "Linux" : pretty_name);
 }
 
 char *replace_env(const char *format, char **env) {
@@ -3740,7 +3741,7 @@ int fd_columns(int fd) {
 }
 
 static unsigned columns_cached(bool cached) {
-        static __thread int parsed_columns = 0, env_columns = -1;
+        static __thread int env_columns = -1;
         const char *e;
 
         if (_likely_(parsed_columns > 0 && cached))
@@ -3776,6 +3777,11 @@ unsigned columns_uncached(void) {
         return columns_cached(false);
 }
 
+/* intended to be used as a SIGWINCH sighandler */
+void columns_cache_reset(int signum) {
+        parsed_columns = 0;
+}
+
 int fd_lines(int fd) {
         struct winsize ws;
         zero(ws);
@@ -3886,7 +3892,8 @@ char *unquote(const char *s, const char* quotes) {
 
         /* This is rather stupid, simply removes the heading and
          * trailing quotes if there is one. Doesn't care about
-         * escaping or anything. */
+         * escaping or anything. We should make this smarter one
+         * day...*/
 
         l = strlen(s);
         if (l < 2)
@@ -3899,39 +3906,40 @@ char *unquote(const char *s, const char* quotes) {
 }
 
 char *normalize_env_assignment(const char *s) {
-        char *name, *value, *p, *r;
+        _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
+        char *eq, *r;
 
-        p = strchr(s, '=');
+        eq = strchr(s, '=');
+        if (!eq) {
+                char *t;
 
-        if (!p) {
-                if (!(r = strdup(s)))
+                r = strdup(s);
+                if (!r)
                         return NULL;
 
-                return strstrip(r);
+                t = strstrip(r);
+                if (t == r)
+                        return r;
+
+                memmove(r, t, strlen(t) + 1);
+                return r;
         }
 
-        if (!(name = strndup(s, p - s)))
+        name = strndup(s, eq - s);
+        if (!name)
                 return NULL;
 
-        if (!(p = strdup(p+1))) {
-                free(name);
+        p = strdup(eq + 1);
+        if (!p)
                 return NULL;
-        }
 
         value = unquote(strstrip(p), QUOTES);
-        free(p);
-
-        if (!value) {
-                free(name);
+        if (!value)
                 return NULL;
-        }
 
-        if (asprintf(&r, "%s=%s", name, value) < 0)
+        if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
                 r = NULL;
 
-        free(value);
-        free(name);
-
         return r;
 }
 
@@ -4110,6 +4118,8 @@ static char *tag_to_udev_node(const char *tagvalue, const char *by) {
 }
 
 char *fstab_node_to_udev_node(const char *p) {
+        assert(p);
+
         if (startswith(p, "LABEL="))
                 return tag_to_udev_node(p+6, "label");
 
@@ -4644,49 +4654,9 @@ int copy_file(const char *from, const char *to) {
         return 0;
 }
 
-int symlink_or_copy(const char *from, const char *to) {
-        char *pf = NULL, *pt = NULL;
-        struct stat a, b;
-        int r;
-
-        assert(from);
-        assert(to);
-
-        if (path_get_parent(from, &pf) < 0 ||
-            path_get_parent(to, &pt) < 0) {
-                r = -ENOMEM;
-                goto finish;
-        }
-
-        if (stat(pf, &a) < 0 ||
-            stat(pt, &b) < 0) {
-                r = -errno;
-                goto finish;
-        }
-
-        if (a.st_dev != b.st_dev) {
-                free(pf);
-                free(pt);
-
-                return copy_file(from, to);
-        }
-
-        if (symlink(from, to) < 0) {
-                r = -errno;
-                goto finish;
-        }
-
-        r = 0;
-
-finish:
-        free(pf);
-        free(pt);
-
-        return r;
-}
-
-int symlink_or_copy_atomic(const char *from, const char *to) {
-        char *t, *x;
+int symlink_atomic(const char *from, const char *to) {
+        char *x;
+        _cleanup_free_ char *t;
         const char *fn;
         size_t k;
         unsigned long long ull;
@@ -4714,22 +4684,16 @@ int symlink_or_copy_atomic(const char *from, const char *to) {
 
         *x = 0;
 
-        r = symlink_or_copy(from, t);
-        if (r < 0) {
-                unlink(t);
-                free(t);
-                return r;
-        }
+        if (symlink(from, t) < 0)
+                return -errno;
 
         if (rename(t, to) < 0) {
                 r = -errno;
                 unlink(t);
-                free(t);
                 return r;
         }
 
-        free(t);
-        return r;
+        return 0;
 }
 
 bool display_is_local(const char *display) {
@@ -4989,10 +4953,11 @@ int get_files_in_directory(const char *path, char ***list) {
                 return -errno;
 
         for (;;) {
-                struct dirent buffer, *de;
+                struct dirent *de;
+                union dirent_storage buf;
                 int k;
 
-                k = readdir_r(d, &buffer, &de);
+                k = readdir_r(d, &buf.de, &de);
                 if (k != 0) {
                         r = -k;
                         goto finish;
@@ -5058,12 +5023,19 @@ char *strjoin(const char *x, ...) {
 
                 for (;;) {
                         const char *t;
+                        size_t n;
 
                         t = va_arg(ap, const char *);
                         if (!t)
                                 break;
 
-                        l += strlen(t);
+                        n = strlen(t);
+                        if (n > ((size_t) -1) - l) {
+                                va_end(ap);
+                                return NULL;
+                        }
+
+                        l += n;
                 }
         } else
                 l = 0;
@@ -5335,7 +5307,7 @@ int signal_from_string(const char *s) {
         int offset = 0;
         unsigned u;
 
-        signo =__signal_from_string(s);
+        signo = __signal_from_string(s);
         if (signo > 0)
                 return signo;
 
@@ -5727,7 +5699,7 @@ void warn_melody(void) {
         if (fd < 0)
                 return;
 
-        /* Yeah, this is synchronous. Kinda sucks. Bute well... */
+        /* Yeah, this is synchronous. Kinda sucks. But well... */
 
         ioctl(fd, KIOCSOUND, (int)(1193180/440));
         usleep(125*USEC_PER_MSEC);
@@ -5873,3 +5845,7 @@ void closedirp(DIR **d) {
         if (*d)
                 closedir(*d);
 }
+
+void umaskp(mode_t *u) {
+        umask(*u);
+}