chiark / gitweb /
shared: introduce cmsg_close_all() call
[elogind.git] / src / shared / util.c
index 3aa952fd77adcf4ed706ceafa6607ebcdef00321..dc6528013bb0a7fded44e17a9e84e3eb5473b9f8 100644 (file)
@@ -25,6 +25,8 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <libintl.h>
+#include <locale.h>
 #include <stdio.h>
 #include <syslog.h>
 #include <sched.h>
@@ -39,7 +41,7 @@
 #include <linux/tiocl.h>
 #include <termios.h>
 #include <stdarg.h>
-#include <sys/poll.h>
+#include <poll.h>
 #include <ctype.h>
 #include <sys/prctl.h>
 #include <sys/utsname.h>
 #include <locale.h>
 #include <sys/personality.h>
 #include <sys/xattr.h>
-#include <libgen.h>
 #include <sys/statvfs.h>
 #include <sys/file.h>
 #include <linux/fs.h>
+
+/* When we include libgen.h because we need dirname() we immediately
+ * undefine basename() since libgen.h defines it as a macro to the XDG
+ * version which is really broken. */
+#include <libgen.h>
 #undef basename
 
 #ifdef HAVE_SYS_AUXV_H
 #include <sys/auxv.h>
 #endif
 
+#include "config.h"
 #include "macro.h"
 #include "util.h"
 #include "ioprio.h"
@@ -4248,6 +4255,11 @@ bool hostname_is_valid(const char *s) {
         if (isempty(s))
                 return false;
 
+        /* Doesn't accept empty hostnames, hostnames with trailing or
+         * leading dots, and hostnames with multiple dots in a
+         * sequence. Also ensures that the length stays below
+         * HOST_NAME_MAX. */
+
         for (p = s, dot = true; *p; p++) {
                 if (*p == '.') {
                         if (dot)
@@ -5462,6 +5474,19 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) {
         return r;
 }
 
+bool http_etag_is_valid(const char *etag) {
+        if (isempty(etag))
+                return false;
+
+        if (!endswith(etag, "\""))
+                return false;
+
+        if (!startswith(etag, "\"") && !startswith(etag, "W/\""))
+                return false;
+
+        return true;
+}
+
 bool http_url_is_valid(const char *url) {
         const char *p;
 
@@ -5760,6 +5785,11 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
         return NULL;
 }
 
+void init_gettext(void) {
+        setlocale(LC_ALL, "");
+        textdomain(GETTEXT_PACKAGE);
+}
+
 bool is_locale_utf8(void) {
         const char *set;
         static int cached_answer = -1;
@@ -6434,7 +6464,7 @@ int container_get_leader(const char *machine, pid_t *pid) {
         assert(machine);
         assert(pid);
 
-        p = strappenda("/run/systemd/machines/", machine);
+        p = strjoina("/run/systemd/machines/", machine);
         r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
         if (r == -ENOENT)
                 return -EHOSTDOWN;
@@ -6673,7 +6703,7 @@ int open_tmpfile(const char *path, int flags) {
 #endif
 
         /* Fall back to unguessable name + unlinking */
-        p = strappenda(path, "/systemd-tmp-XXXXXX");
+        p = strjoina(path, "/systemd-tmp-XXXXXX");
 
         fd = mkostemp_safe(p, flags);
         if (fd < 0)
@@ -7202,7 +7232,7 @@ int take_password_lock(const char *root) {
          * awfully racy, and thus we just won't do them. */
 
         if (root)
-                path = strappenda(root, "/etc/.pwd.lock");
+                path = strjoina(root, "/etc/.pwd.lock");
         else
                 path = "/etc/.pwd.lock";
 
@@ -8025,3 +8055,68 @@ void sigkill_wait(pid_t *pid) {
         if (kill(*pid, SIGKILL) > 0)
                 (void) wait_for_terminate(*pid, NULL);
 }
+
+int syslog_parse_priority(const char **p, int *priority, bool with_facility) {
+        int a = 0, b = 0, c = 0;
+        int k;
+
+        assert(p);
+        assert(*p);
+        assert(priority);
+
+        if ((*p)[0] != '<')
+                return 0;
+
+        if (!strchr(*p, '>'))
+                return 0;
+
+        if ((*p)[2] == '>') {
+                c = undecchar((*p)[1]);
+                k = 3;
+        } else if ((*p)[3] == '>') {
+                b = undecchar((*p)[1]);
+                c = undecchar((*p)[2]);
+                k = 4;
+        } else if ((*p)[4] == '>') {
+                a = undecchar((*p)[1]);
+                b = undecchar((*p)[2]);
+                c = undecchar((*p)[3]);
+                k = 5;
+        } else
+                return 0;
+
+        if (a < 0 || b < 0 || c < 0 ||
+            (!with_facility && (a || b || c > 7)))
+                return 0;
+
+        if (with_facility)
+                *priority = a*100 + b*10 + c;
+        else
+                *priority = (*priority & LOG_FACMASK) | c;
+
+        *p += k;
+        return 1;
+}
+
+ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
+        size_t i;
+
+        if (!key)
+                return -1;
+
+        for (i = 0; i < len; ++i)
+                if (streq_ptr(table[i], key))
+                        return (ssize_t)i;
+
+        return -1;
+}
+
+void cmsg_close_all(struct msghdr *mh) {
+        struct cmsghdr *cmsg;
+
+        assert(mh);
+
+        for (cmsg = CMSG_FIRSTHDR(mh); cmsg; cmsg = CMSG_NXTHDR(mh, cmsg))
+                if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+                        close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
+}