chiark / gitweb /
cryptsetup: minimal cryptsetup unit generator
[elogind.git] / src / util.c
index 58f67b0d15b86b860ca2bb9bbe08ac8d40541b53..6f9399b41808720cd5202fea8ff4a74fd96833f0 100644 (file)
@@ -2605,6 +2605,15 @@ int make_stdio(int fd) {
         return 0;
 }
 
+int make_null_stdio(void) {
+        int null_fd;
+
+        if ((null_fd = open("/dev/null", O_RDWR|O_NOCTTY)) < 0)
+                return -errno;
+
+        return make_stdio(null_fd);
+}
+
 bool is_clean_exit(int code, int status) {
 
         if (code == CLD_EXITED)
@@ -3025,6 +3034,20 @@ void status_welcome(void) {
         status_printf("Welcome to Debian \x1B[1;31m%s\x1B[0m!\n", r); /* Light Red for Debian */
 
         free(r);
+#elif defined(TARGET_UBUNTU)
+        char *desc = NULL;
+        char *codename = NULL;
+
+        if (parse_env_file("/etc/lsb-release", NEWLINE,
+                "DISTRIB_DESCRIPTION", &desc,
+                "DISTRIB_CODENAME", &codename, NULL) < 0)
+                return;
+        if (desc && codename)
+                /* Light Red for Ubuntu */
+                status_printf("Welcome to \x1B[1;31m%s\x1B[0m (%s)\n",
+                        desc, codename);
+        free(desc);
+        free(codename);
 #elif defined(TARGET_ARCH)
         status_printf("Welcome to \x1B[1;36mArch Linux\x1B[0m!\n"); /* Cyan for Arch */
 #else
@@ -3339,6 +3362,261 @@ DIR *xopendirat(int fd, const char *name) {
         return fdopendir(openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC));
 }
 
+int signal_from_string_try_harder(const char *s) {
+        int signo;
+        assert(s);
+
+        if ((signo = signal_from_string(s)) <= 0)
+                if (startswith(s, "SIG"))
+                        return signal_from_string(s+3);
+
+        return signo;
+}
+
+int ask_password_tty(const char *message, usec_t until, const char *flag_file, char **_passphrase) {
+        struct termios old_termios, new_termios;
+        char passphrase[LINE_MAX];
+        size_t p = 0;
+        int r, ttyfd = -1, notify = -1;
+        struct pollfd pollfd[2];
+        bool reset_tty = false;
+        enum {
+                POLL_TTY,
+                POLL_INOTIFY
+        };
+
+        assert(message);
+        assert(_passphrase);
+
+        if (flag_file) {
+                if ((notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK)) < 0) {
+                        r = -errno;
+                        goto finish;
+                }
+
+                if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0) {
+                        r = -errno;
+                        goto finish;
+                }
+        }
+
+        if ((ttyfd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC)) >= 0) {
+
+                if (tcgetattr(ttyfd, &old_termios) < 0) {
+                        r = -errno;
+                        goto finish;
+                }
+
+                loop_write(ttyfd, "\x1B[1m", 4, false);
+                loop_write(ttyfd, message, strlen(message), false);
+                loop_write(ttyfd, ": ", 2, false);
+                loop_write(ttyfd, "\x1B[0m", 4, false);
+
+                new_termios = old_termios;
+                new_termios.c_lflag &= ~(ICANON|ECHO);
+                new_termios.c_cc[VMIN] = 1;
+                new_termios.c_cc[VTIME] = 0;
+
+                if (tcsetattr(ttyfd, TCSADRAIN, &new_termios) < 0) {
+                        r = -errno;
+                        goto finish;
+                }
+
+                reset_tty = true;
+        }
+
+        zero(pollfd);
+
+        pollfd[POLL_TTY].fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO;
+        pollfd[POLL_TTY].events = POLLIN;
+        pollfd[POLL_INOTIFY].fd = notify;
+        pollfd[POLL_INOTIFY].events = POLLIN;
+
+        for (;;) {
+                char c;
+                int sleep_for = -1, k;
+                ssize_t n;
+
+                if (until > 0) {
+                        usec_t y;
+
+                        y = now(CLOCK_MONOTONIC);
+
+                        if (y > until) {
+                                r = -ETIMEDOUT;
+                                goto finish;
+                        }
+
+                        sleep_for = (int) ((until - y) / USEC_PER_MSEC);
+                }
+
+                if (flag_file)
+                        if (access(flag_file, F_OK) < 0) {
+                                r = -errno;
+                                goto finish;
+                        }
+
+                if ((k = poll(pollfd, notify > 0 ? 2 : 1, sleep_for)) < 0) {
+
+                        if (errno == EINTR)
+                                continue;
+
+                        r = -errno;
+                        goto finish;
+                } else if (k == 0) {
+                        r = -ETIMEDOUT;
+                        goto finish;
+                }
+
+                if (notify > 0 && pollfd[POLL_INOTIFY].revents != 0)
+                        flush_fd(notify);
+
+                if (pollfd[POLL_TTY].revents == 0)
+                        continue;
+
+                if ((n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO, &c, 1)) < 0) {
+
+                        if (errno == EINTR || errno == EAGAIN)
+                                continue;
+
+                        r = -errno;
+                        goto finish;
+
+                } else if (n == 0)
+                        break;
+
+                if (c == '\n')
+                        break;
+                else if (c == 21) {
+
+                        while (p > 0) {
+                                p--;
+
+                                if (ttyfd >= 0)
+                                        loop_write(ttyfd, "\b \b", 3, false);
+                        }
+
+                } else if (c == '\b' || c == 127) {
+                        if (p > 0) {
+                                p--;
+
+                                if (ttyfd >= 0)
+                                        loop_write(ttyfd, "\b \b", 3, false);
+                        }
+                } else {
+                        passphrase[p++] = c;
+
+                        if (ttyfd >= 0)
+                                loop_write(ttyfd, "*", 1, false);
+                }
+        }
+
+        if (ttyfd >= 0)
+                loop_write(ttyfd, "\n", 1, false);
+
+        passphrase[p] = 0;
+
+        if (!(*_passphrase = strdup(passphrase))) {
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        r = 0;
+
+finish:
+        if (notify >= 0)
+                close_nointr_nofail(notify);
+
+        if (ttyfd >= 0) {
+                if (reset_tty)
+                        tcsetattr(ttyfd, TCSADRAIN, &old_termios);
+
+                close_nointr_nofail(ttyfd);
+        }
+
+        return r;
+}
+
+void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
+
+        assert(f);
+        assert(name);
+        assert(t);
+
+        if (!dual_timestamp_is_set(t))
+                return;
+
+        fprintf(f, "%s=%llu %llu\n",
+                name,
+                (unsigned long long) t->realtime,
+                (unsigned long long) t->monotonic);
+}
+
+void dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
+        unsigned long long a, b;
+
+        assert(value);
+        assert(t);
+
+        if (sscanf(value, "%lli %llu", &a, &b) != 2)
+                log_debug("Failed to parse finish timestamp value %s", value);
+        else {
+                t->realtime = a;
+                t->monotonic = b;
+        }
+}
+
+
+char *fstab_node_to_udev_node(const char *p) {
+        char *dn, *t, *u;
+        int r;
+
+        /* FIXME: to follow udev's logic 100% we need to leave valid
+         * UTF8 chars unescaped */
+
+        if (startswith(p, "LABEL=")) {
+
+                if (!(u = unquote(p+6, "\"\'")))
+                        return NULL;
+
+                t = xescape(u, "/ ");
+                free(u);
+
+                if (!t)
+                        return NULL;
+
+                r = asprintf(&dn, "/dev/disk/by-label/%s", t);
+                free(t);
+
+                if (r < 0)
+                        return NULL;
+
+                return dn;
+        }
+
+        if (startswith(p, "UUID=")) {
+
+                if (!(u = unquote(p+5, "\"\'")))
+                        return NULL;
+
+                t = xescape(u, "/ ");
+                free(u);
+
+                if (!t)
+                        return NULL;
+
+                r = asprintf(&dn, "/dev/disk/by-uuid/%s", ascii_strlower(t));
+                free(t);
+
+                if (r < 0)
+                        return NULL;
+
+                return dn;
+        }
+
+        return strdup(p);
+}
+
 static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_NONE] = "none",
         [IOPRIO_CLASS_RT] = "realtime",