diff options
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/architecture.h | 16 | ||||
-rw-r--r-- | src/shared/ask-password-api.c | 364 | ||||
-rw-r--r-- | src/shared/ask-password-api.h | 25 | ||||
-rw-r--r-- | src/shared/base-filesystem.c | 12 | ||||
-rw-r--r-- | src/shared/bus-util.c | 20 | ||||
-rw-r--r-- | src/shared/bus-util.h | 8 | ||||
-rw-r--r-- | src/shared/conf-parser.c | 117 | ||||
-rw-r--r-- | src/shared/conf-parser.h | 7 | ||||
-rw-r--r-- | src/shared/dns-domain.c | 11 | ||||
-rw-r--r-- | src/shared/dns-domain.h | 2 | ||||
-rw-r--r-- | src/shared/dropin.c | 5 | ||||
-rw-r--r-- | src/shared/fstab-util.c | 17 | ||||
-rw-r--r-- | src/shared/fstab-util.h | 1 | ||||
-rw-r--r-- | src/shared/install.c | 3 | ||||
-rw-r--r-- | src/shared/pager.c | 27 | ||||
-rw-r--r-- | src/shared/path-lookup.c | 6 | ||||
-rw-r--r-- | src/shared/ptyfwd.c | 49 | ||||
-rw-r--r-- | src/shared/ptyfwd.h | 12 | ||||
-rw-r--r-- | src/shared/sleep-config.c | 2 | ||||
-rw-r--r-- | src/shared/spawn-ask-password-agent.c | 12 | ||||
-rw-r--r-- | src/shared/sysctl-util.c | 13 |
21 files changed, 451 insertions, 278 deletions
diff --git a/src/shared/architecture.h b/src/shared/architecture.h index f5bbf65a90..61d067cad7 100644 --- a/src/shared/architecture.h +++ b/src/shared/architecture.h @@ -78,9 +78,11 @@ int uname_architecture(void); #if defined(__x86_64__) # define native_architecture() ARCHITECTURE_X86_64 # define LIB_ARCH_TUPLE "x86_64-linux-gnu" +# define PROC_CPUINFO_MODEL "model name" #elif defined(__i386__) # define native_architecture() ARCHITECTURE_X86 # define LIB_ARCH_TUPLE "i386-linux-gnu" +# define PROC_CPUINFO_MODEL "model name" #elif defined(__powerpc64__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_PPC64 @@ -89,6 +91,7 @@ int uname_architecture(void); # define native_architecture() ARCHITECTURE_PPC64_LE # define LIB_ARCH_TUPLE "powerpc64le-linux-gnu" # endif +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__powerpc__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_PPC @@ -97,15 +100,18 @@ int uname_architecture(void); # define native_architecture() ARCHITECTURE_PPC_LE # error "Missing LIB_ARCH_TUPLE for PPCLE" # endif +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__ia64__) # define native_architecture() ARCHITECTURE_IA64 # define LIB_ARCH_TUPLE "ia64-linux-gnu" #elif defined(__hppa64__) # define native_architecture() ARCHITECTURE_PARISC64 # error "Missing LIB_ARCH_TUPLE for HPPA64" +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__hppa__) # define native_architecture() ARCHITECTURE_PARISC # define LIB_ARCH_TUPLE "hppa‑linux‑gnu" +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__s390x__) # define native_architecture() ARCHITECTURE_S390X # define LIB_ARCH_TUPLE "s390x-linux-gnu" @@ -115,9 +121,11 @@ int uname_architecture(void); #elif defined(__sparc64__) # define native_architecture() ARCHITECTURE_SPARC64 # define LIB_ARCH_TUPLE "sparc64-linux-gnu" +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__sparc__) # define native_architecture() ARCHITECTURE_SPARC # define LIB_ARCH_TUPLE "sparc-linux-gnu" +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__mips64__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_MIPS64 @@ -126,6 +134,7 @@ int uname_architecture(void); # define native_architecture() ARCHITECTURE_MIPS64_LE # error "Missing LIB_ARCH_TUPLE for MIPS64_LE" # endif +# define PROC_CPUINFO_MODEL "cpu model" #elif defined(__mips__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_MIPS @@ -134,6 +143,7 @@ int uname_architecture(void); # define native_architecture() ARCHITECTURE_MIPS_LE # define LIB_ARCH_TUPLE "mipsel-linux-gnu" # endif +# define PROC_CPUINFO_MODEL "cpu model" #elif defined(__alpha__) # define native_architecture() ARCHITECTURE_ALPHA # define LIB_ARCH_TUPLE "alpha-linux-gnu" @@ -169,6 +179,7 @@ int uname_architecture(void); # define LIB_ARCH_TUPLE "arm-linux-gnu" # endif # endif +# define PROC_CPUINFO_MODEL "model name" #elif defined(__sh64__) # define native_architecture() ARCHITECTURE_SH64 # error "Missing LIB_ARCH_TUPLE for SH64" @@ -188,5 +199,10 @@ int uname_architecture(void); # error "Please register your architecture here!" #endif +#ifndef PROC_CPUINFO_MODEL +#warning "PROC_CPUINFO_MODEL not defined for your architecture" +#define PROC_CPUINFO_MODEL "model name" +#endif + const char *architecture_to_string(int a) _const_; int architecture_from_string(const char *s) _pure_; diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index b02cdf9a17..f8cf11b297 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -18,28 +18,158 @@ You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdbool.h> -#include <termios.h> -#include <unistd.h> -#include <poll.h> -#include <sys/inotify.h> + #include <errno.h> #include <fcntl.h> -#include <sys/socket.h> -#include <string.h> -#include <sys/un.h> +#include <poll.h> +#include <stdbool.h> #include <stddef.h> +#include <string.h> +#include <sys/inotify.h> #include <sys/signalfd.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <termios.h> +#include <unistd.h> -#include "util.h" #include "formats-util.h" +#include "missing.h" #include "mkdir.h" -#include "strv.h" #include "random-util.h" -#include "terminal-util.h" #include "signal-util.h" +#include "socket-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "util.h" #include "ask-password-api.h" +#define KEYRING_TIMEOUT_USEC ((5 * USEC_PER_MINUTE) / 2) + +static int lookup_key(const char *keyname, key_serial_t *ret) { + key_serial_t serial; + + assert(keyname); + assert(ret); + + serial = request_key("user", keyname, NULL, 0); + if (serial == -1) + return -errno; + + *ret = serial; + return 0; +} + +static int retrieve_key(key_serial_t serial, char ***ret) { + _cleanup_free_ char *p = NULL; + long m = 100, n; + char **l; + + assert(ret); + + for (;;) { + p = new(char, m); + if (!p) + return -ENOMEM; + + n = keyctl(KEYCTL_READ, (unsigned long) serial, (unsigned long) p, (unsigned long) m, 0); + if (n < 0) + return -errno; + + if (n < m) + break; + + free(p); + m *= 2; + } + + l = strv_parse_nulstr(p, n); + if (!l) + return -ENOMEM; + + *ret = l; + return 0; +} + +static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **passwords) { + _cleanup_strv_free_ char **l = NULL; + _cleanup_free_ char *p = NULL; + key_serial_t serial; + size_t n; + int r; + + assert(keyname); + assert(passwords); + + if (!(flags & ASK_PASSWORD_PUSH_CACHE)) + return 0; + + r = lookup_key(keyname, &serial); + if (r >= 0) { + r = retrieve_key(serial, &l); + if (r < 0) + return r; + } else if (r != -ENOKEY) + return r; + + r = strv_extend_strv(&l, passwords, true); + if (r <= 0) + return r; + + r = strv_make_nulstr(l, &p, &n); + if (r < 0) + return r; + + /* Truncate trailing NUL */ + assert(n > 0); + assert(p[n-1] == 0); + + serial = add_key("user", keyname, p, n-1, KEY_SPEC_USER_KEYRING); + if (serial == -1) + return -errno; + + if (keyctl(KEYCTL_SET_TIMEOUT, + (unsigned long) serial, + (unsigned long) DIV_ROUND_UP(KEYRING_TIMEOUT_USEC, USEC_PER_SEC), 0, 0) < 0) + log_debug_errno(errno, "Failed to adjust timeout: %m"); + + log_debug("Added key to keyring as %" PRIi32 ".", serial); + + return 1; +} + +static int add_to_keyring_and_log(const char *keyname, AskPasswordFlags flags, char **passwords) { + int r; + + assert(keyname); + assert(passwords); + + r = add_to_keyring(keyname, flags, passwords); + if (r < 0) + return log_debug_errno(r, "Failed to add password to keyring: %m"); + + return 0; +} + +int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret) { + + key_serial_t serial; + int r; + + assert(keyname); + assert(ret); + + if (!(flags & ASK_PASSWORD_ACCEPT_CACHED)) + return -EUNATCH; + + r = lookup_key(keyname, &serial); + if (r == -ENOSYS) /* when retrieving the distinction doesn't matter */ + return -ENOKEY; + if (r < 0) + return r; + + return retrieve_key(serial, ret); +} + static void backspace_chars(int ttyfd, size_t p) { if (ttyfd < 0) @@ -54,10 +184,11 @@ static void backspace_chars(int ttyfd, size_t p) { int ask_password_tty( const char *message, + const char *keyname, usec_t until, - bool echo, + AskPasswordFlags flags, const char *flag_file, - char **_passphrase) { + char **ret) { struct termios old_termios, new_termios; char passphrase[LINE_MAX], *x; @@ -66,15 +197,19 @@ int ask_password_tty( _cleanup_close_ int ttyfd = -1, notify = -1; struct pollfd pollfd[2]; bool reset_tty = false; - bool silent_mode = false; bool dirty = false; enum { POLL_TTY, POLL_INOTIFY }; - assert(message); - assert(_passphrase); + assert(ret); + + if (flags & ASK_PASSWORD_NO_TTY) + return -EUNATCH; + + if (!message) + message = "Password:"; if (flag_file) { notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); @@ -97,10 +232,10 @@ int ask_password_tty( goto finish; } - loop_write(ttyfd, ANSI_HIGHLIGHT, sizeof(ANSI_HIGHLIGHT)-1, false); + loop_write(ttyfd, ANSI_HIGHLIGHT, strlen(ANSI_HIGHLIGHT), false); loop_write(ttyfd, message, strlen(message), false); loop_write(ttyfd, " ", 1, false); - loop_write(ttyfd, ANSI_NORMAL, sizeof(ANSI_NORMAL)-1, false); + loop_write(ttyfd, ANSI_NORMAL, strlen(ANSI_NORMAL), false); new_termios = old_termios; new_termios.c_lflag &= ~(ICANON|ECHO); @@ -145,7 +280,7 @@ int ask_password_tty( goto finish; } - k = poll(pollfd, notify > 0 ? 2 : 1, sleep_for); + k = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for); if (k < 0) { if (errno == EINTR) continue; @@ -157,7 +292,7 @@ int ask_password_tty( goto finish; } - if (notify > 0 && pollfd[POLL_INOTIFY].revents != 0) + if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0) flush_fd(notify); if (pollfd[POLL_TTY].revents == 0) @@ -178,7 +313,7 @@ int ask_password_tty( break; else if (c == 21) { /* C-u */ - if (!silent_mode) + if (!(flags & ASK_PASSWORD_SILENT)) backspace_chars(ttyfd, p); p = 0; @@ -186,28 +321,28 @@ int ask_password_tty( if (p > 0) { - if (!silent_mode) + if (!(flags & ASK_PASSWORD_SILENT)) backspace_chars(ttyfd, 1); p--; - } else if (!dirty && !silent_mode) { + } else if (!dirty && !(flags & ASK_PASSWORD_SILENT)) { - silent_mode = true; + flags |= ASK_PASSWORD_SILENT; /* There are two ways to enter silent * mode. Either by pressing backspace - * as first key (and only as first key), - * or ... */ + * as first key (and only as first + * key), or ... */ if (ttyfd >= 0) loop_write(ttyfd, "(no echo) ", 10, false); } else if (ttyfd >= 0) loop_write(ttyfd, "\a", 1, false); - } else if (c == '\t' && !silent_mode) { + } else if (c == '\t' && !(flags & ASK_PASSWORD_SILENT)) { backspace_chars(ttyfd, p); - silent_mode = true; + flags |= ASK_PASSWORD_SILENT; /* ... or by pressing TAB at any time. */ @@ -221,8 +356,8 @@ int ask_password_tty( passphrase[p++] = c; - if (!silent_mode && ttyfd >= 0) - loop_write(ttyfd, echo ? &c : "*", 1, false); + if (!(flags & ASK_PASSWORD_SILENT) && ttyfd >= 0) + loop_write(ttyfd, (flags & ASK_PASSWORD_ECHO) ? &c : "*", 1, false); dirty = true; } @@ -234,7 +369,10 @@ int ask_password_tty( goto finish; } - *_passphrase = x; + if (keyname) + (void) add_to_keyring_and_log(keyname, flags, STRV_MAKE(x)); + + *ret = x; r = 0; finish: @@ -247,52 +385,38 @@ finish: } static int create_socket(char **name) { - int fd; - union { - struct sockaddr sa; - struct sockaddr_un un; - } sa = { + union sockaddr_union sa = { .un.sun_family = AF_UNIX, }; - int one = 1; - int r = 0; + _cleanup_close_ int fd = -1; + static const int one = 1; char *c; + int r; assert(name); fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (fd < 0) - return log_error_errno(errno, "socket() failed: %m"); + return -errno; snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/run/systemd/ask-password/sck.%" PRIx64, random_u64()); RUN_WITH_UMASK(0177) { - r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)); - } - - if (r < 0) { - r = -errno; - log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); - goto fail; + if (bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) + return -errno; } - if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) { - r = -errno; - log_error_errno(errno, "SO_PASSCRED failed: %m"); - goto fail; - } + if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) + return -errno; c = strdup(sa.un.sun_path); - if (!c) { - r = log_oom(); - goto fail; - } + if (!c) + return -ENOMEM; *name = c; - return fd; -fail: - safe_close(fd); + r = fd; + fd = -1; return r; } @@ -301,10 +425,10 @@ int ask_password_agent( const char *message, const char *icon, const char *id, + const char *keyname, usec_t until, - bool echo, - bool accept_cached, - char ***_passphrases) { + AskPasswordFlags flags, + char ***ret) { enum { FD_SOCKET, @@ -312,35 +436,38 @@ int ask_password_agent( _FD_MAX }; + _cleanup_close_ int socket_fd = -1, signal_fd = -1, fd = -1; char temp[] = "/run/systemd/ask-password/tmp.XXXXXX"; char final[sizeof(temp)] = ""; - _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *socket_name = NULL; - _cleanup_close_ int socket_fd = -1, signal_fd = -1, fd = -1; - sigset_t mask, oldmask; + _cleanup_strv_free_ char **l = NULL; + _cleanup_fclose_ FILE *f = NULL; struct pollfd pollfd[_FD_MAX]; + sigset_t mask, oldmask; int r; - assert(_passphrases); + assert(ret); + + if (flags & ASK_PASSWORD_NO_AGENT) + return -EUNATCH; assert_se(sigemptyset(&mask) >= 0); assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0); assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0); - mkdir_p_label("/run/systemd/ask-password", 0755); + (void) mkdir_p_label("/run/systemd/ask-password", 0755); fd = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC); if (fd < 0) { - r = log_error_errno(errno, - "Failed to create password file: %m"); + r = -errno; goto finish; } - fchmod(fd, 0644); + (void) fchmod(fd, 0644); f = fdopen(fd, "w"); if (!f) { - r = log_error_errno(errno, "Failed to allocate FILE: %m"); + r = -errno; goto finish; } @@ -348,7 +475,7 @@ int ask_password_agent( signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); if (signal_fd < 0) { - r = log_error_errno(errno, "signalfd(): %m"); + r = -errno; goto finish; } @@ -367,8 +494,8 @@ int ask_password_agent( "NotAfter="USEC_FMT"\n", getpid(), socket_name, - accept_cached ? 1 : 0, - echo ? 1 : 0, + (flags & ASK_PASSWORD_ACCEPT_CACHED) ? 1 : 0, + (flags & ASK_PASSWORD_ECHO) ? 1 : 0, until); if (message) @@ -381,10 +508,8 @@ int ask_password_agent( fprintf(f, "Id=%s\n", id); r = fflush_and_check(f); - if (r < 0) { - log_error_errno(r, "Failed to write query file: %m"); + if (r < 0) goto finish; - } memcpy(final, temp, sizeof(temp)); @@ -393,7 +518,7 @@ int ask_password_agent( final[sizeof(final)-9] = 'k'; if (rename(temp, final) < 0) { - r = log_error_errno(errno, "Failed to rename query file: %m"); + r = -errno; goto finish; } @@ -419,7 +544,6 @@ int ask_password_agent( t = now(CLOCK_MONOTONIC); if (until > 0 && until <= t) { - log_notice("Timed out"); r = -ETIME; goto finish; } @@ -429,12 +553,11 @@ int ask_password_agent( if (errno == EINTR) continue; - r = log_error_errno(errno, "poll() failed: %m"); + r = -errno; goto finish; } if (k <= 0) { - log_notice("Timed out"); r = -ETIME; goto finish; } @@ -445,7 +568,6 @@ int ask_password_agent( } if (pollfd[FD_SOCKET].revents != POLLIN) { - log_error("Unexpected poll() event."); r = -EIO; goto finish; } @@ -467,14 +589,14 @@ int ask_password_agent( errno == EINTR) continue; - r = log_error_errno(errno, "recvmsg() failed: %m"); + r = -errno; goto finish; } cmsg_close_all(&msghdr); if (n <= 0) { - log_error("Message too short"); + log_debug("Message too short"); continue; } @@ -482,84 +604,100 @@ int ask_password_agent( control.cmsghdr.cmsg_level != SOL_SOCKET || control.cmsghdr.cmsg_type != SCM_CREDENTIALS || control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) { - log_warning("Received message without credentials. Ignoring."); + log_debug("Received message without credentials. Ignoring."); continue; } ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr); if (ucred->uid != 0) { - log_warning("Got request from unprivileged user. Ignoring."); + log_debug("Got request from unprivileged user. Ignoring."); continue; } if (passphrase[0] == '+') { - char **l; - + /* An empty message refers to the empty password */ if (n == 1) l = strv_new("", NULL); else l = strv_parse_nulstr(passphrase+1, n-1); - /* An empty message refers to the empty password */ - if (!l) { r = -ENOMEM; goto finish; } if (strv_length(l) <= 0) { - strv_free(l); - log_error("Invalid packet"); + l = strv_free(l); + log_debug("Invalid packet"); continue; } - *_passphrases = l; + break; + } - } else if (passphrase[0] == '-') { + if (passphrase[0] == '-') { r = -ECANCELED; goto finish; - } else { - log_error("Invalid packet"); - continue; } - break; + log_debug("Invalid packet"); } + if (keyname) + (void) add_to_keyring_and_log(keyname, flags, l); + + *ret = l; + l = NULL; r = 0; finish: if (socket_name) - unlink(socket_name); + (void) unlink(socket_name); - unlink(temp); + (void) unlink(temp); if (final[0]) - unlink(final); + (void) unlink(final); assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0); - return r; } -int ask_password_auto(const char *message, const char *icon, const char *id, - usec_t until, bool accept_cached, char ***_passphrases) { - assert(message); - assert(_passphrases); +int ask_password_auto( + const char *message, + const char *icon, + const char *id, + const char *keyname, + usec_t until, + AskPasswordFlags flags, + char ***ret) { - if (isatty(STDIN_FILENO)) { - int r; + int r; + + assert(ret); + + if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) { + r = ask_password_keyring(keyname, flags, ret); + if (r != -ENOKEY) + return r; + } + + if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO)) { char *s = NULL, **l = NULL; - r = ask_password_tty(message, until, false, NULL, &s); + r = ask_password_tty(message, keyname, until, flags, NULL, &s); if (r < 0) return r; r = strv_consume(&l, s); if (r < 0) - return r; + return -ENOMEM; - *_passphrases = l; - return r; - } else - return ask_password_agent(message, icon, id, until, false, accept_cached, _passphrases); + *ret = l; + return 0; + } + + if (!(flags & ASK_PASSWORD_NO_AGENT)) + return ask_password_agent(message, icon, id, keyname, until, flags, ret); + + return -EUNATCH; } diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h index 0954e072be..913cad9f8a 100644 --- a/src/shared/ask-password-api.h +++ b/src/shared/ask-password-api.h @@ -21,11 +21,20 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ - -int ask_password_tty(const char *message, usec_t until, bool echo, const char *flag_file, char **_passphrase); - -int ask_password_agent(const char *message, const char *icon, const char *id, - usec_t until, bool echo, bool accept_cached, char ***_passphrases); - -int ask_password_auto(const char *message, const char *icon, const char *id, - usec_t until, bool accept_cached, char ***_passphrases); +#include <stdbool.h> + +#include "time-util.h" + +typedef enum AskPasswordFlags { + ASK_PASSWORD_ACCEPT_CACHED = 1, + ASK_PASSWORD_PUSH_CACHE = 2, + ASK_PASSWORD_ECHO = 4, /* show the password literally while reading, instead of "*" */ + ASK_PASSWORD_SILENT = 8, /* do no show any password at all while reading */ + ASK_PASSWORD_NO_TTY = 16, + ASK_PASSWORD_NO_AGENT = 32, +} AskPasswordFlags; + +int ask_password_tty(const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char **ret); +int ask_password_agent(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret); +int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret); +int ask_password_auto(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret); diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c index ab6fc171b0..48492ed13d 100644 --- a/src/shared/base-filesystem.c +++ b/src/shared/base-filesystem.c @@ -34,12 +34,13 @@ typedef struct BaseFilesystem { mode_t mode; const char *target; const char *exists; + bool ignore_failure; } BaseFilesystem; static const BaseFilesystem table[] = { { "bin", 0, "usr/bin\0", NULL }, { "lib", 0, "usr/lib\0", NULL }, - { "root", 0755, NULL, NULL }, + { "root", 0755, NULL, NULL, true }, { "sbin", 0, "usr/sbin\0", NULL }, { "usr", 0755, NULL, NULL }, { "var", 0755, NULL, NULL }, @@ -104,8 +105,13 @@ int base_filesystem_create(const char *root, uid_t uid, gid_t gid) { RUN_WITH_UMASK(0000) r = mkdirat(fd, table[i].dir, table[i].mode); - if (r < 0 && errno != EEXIST) - return log_error_errno(errno, "Failed to create directory at %s/%s: %m", root, table[i].dir); + if (r < 0 && errno != EEXIST) { + log_full_errno(table[i].ignore_failure ? LOG_DEBUG : LOG_ERR, errno, + "Failed to create directory at %s/%s: %m", root, table[i].dir); + + if (!table[i].ignore_failure) + return -errno; + } if (uid != UID_INVALID || gid != UID_INVALID) { if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0) diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 16b17c2c82..10df3fc3d6 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -574,14 +574,14 @@ int bus_check_peercred(sd_bus *c) { return 1; } -int bus_open_system_systemd(sd_bus **_bus) { +int bus_connect_system_systemd(sd_bus **_bus) { _cleanup_bus_unref_ sd_bus *bus = NULL; int r; assert(_bus); if (geteuid() != 0) - return sd_bus_open_system(_bus); + return sd_bus_default_system(_bus); /* If we are root and kdbus is not available, then let's talk * directly to the system instance, instead of going via the @@ -616,7 +616,7 @@ int bus_open_system_systemd(sd_bus **_bus) { r = sd_bus_start(bus); if (r < 0) - return sd_bus_open_system(_bus); + return sd_bus_default_system(_bus); r = bus_check_peercred(bus); if (r < 0) @@ -628,7 +628,7 @@ int bus_open_system_systemd(sd_bus **_bus) { return 0; } -int bus_open_user_systemd(sd_bus **_bus) { +int bus_connect_user_systemd(sd_bus **_bus) { _cleanup_bus_unref_ sd_bus *bus = NULL; _cleanup_free_ char *ee = NULL; const char *e; @@ -658,7 +658,7 @@ int bus_open_user_systemd(sd_bus **_bus) { e = secure_getenv("XDG_RUNTIME_DIR"); if (!e) - return sd_bus_open_user(_bus); + return sd_bus_default_user(_bus); ee = bus_address_escape(e); if (!ee) @@ -674,7 +674,7 @@ int bus_open_user_systemd(sd_bus **_bus) { r = sd_bus_start(bus); if (r < 0) - return sd_bus_open_user(_bus); + return sd_bus_default_user(_bus); r = bus_check_peercred(bus); if (r < 0) @@ -1209,7 +1209,7 @@ int bus_map_all_properties( return bus_message_map_all_properties(m, map, userdata); } -int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) { +int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) { int r; assert(transport >= 0); @@ -1244,7 +1244,7 @@ int bus_open_transport(BusTransport transport, const char *host, bool user, sd_b return r; } -int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) { +int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) { int r; assert(transport >= 0); @@ -1258,9 +1258,9 @@ int bus_open_transport_systemd(BusTransport transport, const char *host, bool us case BUS_TRANSPORT_LOCAL: if (user) - r = bus_open_user_systemd(bus); + r = bus_connect_user_systemd(bus); else - r = bus_open_system_systemd(bus); + r = bus_connect_system_systemd(bus); break; diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index d2b2d701ce..f03f951dc7 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -65,11 +65,11 @@ int bus_test_polkit(sd_bus_message *call, int capability, const char *action, co int bus_verify_polkit_async(sd_bus_message *call, int capability, const char *action, const char **details, bool interactive, uid_t good_user, Hashmap **registry, sd_bus_error *error); void bus_verify_polkit_async_registry_free(Hashmap *registry); -int bus_open_system_systemd(sd_bus **_bus); -int bus_open_user_systemd(sd_bus **_bus); +int bus_connect_system_systemd(sd_bus **_bus); +int bus_connect_user_systemd(sd_bus **_bus); -int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus); -int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus); +int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus); +int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus); int bus_print_property(const char *name, sd_bus_message *property, bool all); int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all); diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 946eac6823..c282fb1231 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -147,8 +147,7 @@ static int next_assignment(const char *unit, /* Warn about unknown non-extension fields. */ if (!relaxed && !startswith(lvalue, "X-")) - log_syntax(unit, LOG_WARNING, filename, line, EINVAL, - "Unknown lvalue '%s' in section '%s'", lvalue, section); + log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown lvalue '%s' in section '%s'", lvalue, section); return 0; } @@ -196,8 +195,7 @@ static int parse_line(const char* unit, * Support for them should be eventually removed. */ if (!allow_include) { - log_syntax(unit, LOG_ERR, filename, line, EBADMSG, - ".include not allowed here. Ignoring."); + log_syntax(unit, LOG_ERR, filename, line, 0, ".include not allowed here. Ignoring."); return 0; } @@ -216,8 +214,7 @@ static int parse_line(const char* unit, assert(k > 0); if (l[k-1] != ']') { - log_syntax(unit, LOG_ERR, filename, line, EBADMSG, - "Invalid section header '%s'", l); + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid section header '%s'", l); return -EBADMSG; } @@ -228,8 +225,7 @@ static int parse_line(const char* unit, if (sections && !nulstr_contains(sections, n)) { if (!relaxed && !startswith(n, "X-")) - log_syntax(unit, LOG_WARNING, filename, line, EINVAL, - "Unknown section '%s'. Ignoring.", n); + log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown section '%s'. Ignoring.", n); free(n); *section = mfree(*section); @@ -248,16 +244,15 @@ static int parse_line(const char* unit, if (sections && !*section) { if (!relaxed && !*section_ignored) - log_syntax(unit, LOG_WARNING, filename, line, EINVAL, - "Assignment outside of section. Ignoring."); + log_syntax(unit, LOG_WARNING, filename, line, 0, "Assignment outside of section. Ignoring."); return 0; } e = strchr(l, '='); if (!e) { - log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Missing '='."); - return -EBADMSG; + log_syntax(unit, LOG_WARNING, filename, line, 0, "Missing '='."); + return -EINVAL; } *e = 0; @@ -420,16 +415,17 @@ int config_parse_many(const char *conf_file, } #define DEFINE_PARSER(type, vartype, conv_func) \ - int config_parse_##type(const char *unit, \ - const char *filename, \ - unsigned line, \ - const char *section, \ - unsigned section_line, \ - const char *lvalue, \ - int ltype, \ - const char *rvalue, \ - void *data, \ - void *userdata) { \ + int config_parse_##type( \ + const char *unit, \ + const char *filename, \ + unsigned line, \ + const char *section, \ + unsigned section_line, \ + const char *lvalue, \ + int ltype, \ + const char *rvalue, \ + void *data, \ + void *userdata) { \ \ vartype *i = data; \ int r; \ @@ -441,21 +437,23 @@ int config_parse_many(const char *conf_file, \ r = conv_func(rvalue, i); \ if (r < 0) \ - log_syntax(unit, LOG_ERR, filename, line, -r, \ + log_syntax(unit, LOG_ERR, filename, line, r, \ "Failed to parse %s value, ignoring: %s", \ #type, rvalue); \ \ return 0; \ - } - -DEFINE_PARSER(int, int, safe_atoi) -DEFINE_PARSER(long, long, safe_atoli) -DEFINE_PARSER(uint32, uint32_t, safe_atou32) -DEFINE_PARSER(uint64, uint64_t, safe_atou64) -DEFINE_PARSER(unsigned, unsigned, safe_atou) -DEFINE_PARSER(double, double, safe_atod) -DEFINE_PARSER(nsec, nsec_t, parse_nsec) -DEFINE_PARSER(sec, usec_t, parse_sec) + } \ + struct __useless_struct_to_allow_trailing_semicolon__ + +DEFINE_PARSER(int, int, safe_atoi); +DEFINE_PARSER(long, long, safe_atoli); +DEFINE_PARSER(uint32, uint32_t, safe_atou32); +DEFINE_PARSER(uint64, uint64_t, safe_atou64); +DEFINE_PARSER(unsigned, unsigned, safe_atou); +DEFINE_PARSER(double, double, safe_atod); +DEFINE_PARSER(nsec, nsec_t, parse_nsec); +DEFINE_PARSER(sec, usec_t, parse_sec); +DEFINE_PARSER(mode, mode_t, parse_mode); int config_parse_iec_size(const char* unit, const char *filename, @@ -479,7 +477,7 @@ int config_parse_iec_size(const char* unit, r = parse_size(rvalue, 1024, &v); if (r < 0 || (uint64_t) (size_t) v != v) { - log_syntax(unit, LOG_ERR, filename, line, r < 0 ? r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue); return 0; } @@ -509,7 +507,7 @@ int config_parse_si_size(const char* unit, r = parse_size(rvalue, 1000, &v); if (r < 0 || (uint64_t) (size_t) v != v) { - log_syntax(unit, LOG_ERR, filename, line, r < 0 ? r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue); return 0; } @@ -564,8 +562,7 @@ int config_parse_bool(const char* unit, k = parse_boolean(rvalue); if (k < 0) { - log_syntax(unit, LOG_ERR, filename, line, -k, - "Failed to parse boolean value, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue); return 0; } @@ -626,7 +623,7 @@ int config_parse_string( assert(data); if (!utf8_is_valid(rvalue)) { - log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue); + log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); return 0; } @@ -664,12 +661,12 @@ int config_parse_path( assert(data); if (!utf8_is_valid(rvalue)) { - log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue); + log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); return 0; } if (!path_is_absolute(rvalue)) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Not an absolute path, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", rvalue); return 0; } @@ -730,7 +727,7 @@ int config_parse_strv(const char *unit, return log_oom(); if (!utf8_is_valid(n)) { - log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue); + log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); free(n); continue; } @@ -740,35 +737,7 @@ int config_parse_strv(const char *unit, return log_oom(); } if (!isempty(state)) - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Trailing garbage, ignoring."); - - return 0; -} - -int config_parse_mode( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - mode_t *m = data; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - if (parse_mode(rvalue, m) < 0) { - log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse mode value, ignoring: %s", rvalue); - return 0; - } + log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); return 0; } @@ -795,7 +764,7 @@ int config_parse_log_facility( x = log_facility_unshifted_from_string(rvalue); if (x < 0) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse log facility, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log facility, ignoring: %s", rvalue); return 0; } @@ -826,7 +795,7 @@ int config_parse_log_level( x = log_level_from_string(rvalue); if (x < 0) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse log level, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log level, ignoring: %s", rvalue); return 0; } @@ -855,7 +824,7 @@ int config_parse_signal( r = signal_from_string_try_harder(rvalue); if (r <= 0) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse signal name, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse signal name, ignoring: %s", rvalue); return 0; } @@ -884,7 +853,7 @@ int config_parse_personality( p = personality_from_string(rvalue); if (p == PERSONALITY_INVALID) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse personality, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse personality, ignoring: %s", rvalue); return 0; } diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index 4efed138c9..fb0234baae 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -123,13 +123,6 @@ int config_parse_log_level(const char *unit, const char *filename, unsigned line int config_parse_signal(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_personality(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); -#define log_invalid_utf8(unit, level, config_file, config_line, error, rvalue) \ - do { \ - _cleanup_free_ char *_p = utf8_escape_invalid(rvalue); \ - log_syntax(unit, level, config_file, config_line, error, \ - "String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \ - } while(false) - #define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \ int function(const char *unit, \ const char *filename, \ diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c index 6dc04d51e4..5680f01bd9 100644 --- a/src/shared/dns-domain.c +++ b/src/shared/dns-domain.c @@ -379,9 +379,8 @@ int dns_name_concat(const char *a, const char *b, char **_ret) { return 0; } -unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]) { +void dns_name_hash_func(const void *s, struct siphash *state) { const char *p = s; - unsigned long ul = hash_key[0]; int r; assert(p); @@ -400,13 +399,17 @@ unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_ if (k > 0) r = k; + if (r == 0) + break; + label[r] = 0; ascii_strlower(label); - ul = ul * hash_key[1] + ul + string_hash_func(label, hash_key); + string_hash_func(label, state); } - return ul; + /* enforce that all names are terminated by the empty label */ + string_hash_func("", state); } int dns_name_compare_func(const void *a, const void *b) { diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h index 8e73d9c20f..1f0d242c18 100644 --- a/src/shared/dns-domain.h +++ b/src/shared/dns-domain.h @@ -54,7 +54,7 @@ static inline int dns_name_is_valid(const char *s) { return 1; } -unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]); +void dns_name_hash_func(const void *s, struct siphash *state); int dns_name_compare_func(const void *a, const void *b); extern const struct hash_ops dns_name_hash_ops; diff --git a/src/shared/dropin.c b/src/shared/dropin.c index 963d05d32e..1845068adb 100644 --- a/src/shared/dropin.c +++ b/src/shared/dropin.c @@ -78,7 +78,7 @@ int write_drop_in(const char *dir, const char *unit, unsigned level, if (r < 0) return r; - mkdir_p(p, 0755); + (void) mkdir_p(p, 0755); return write_string_file_atomic_label(q, data); } @@ -132,8 +132,7 @@ static int iterate_dir( if (errno == ENOENT) return 0; - log_error_errno(errno, "Failed to open directory %s: %m", path); - return -errno; + return log_error_errno(errno, "Failed to open directory %s: %m", path); } for (;;) { diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c index e231a0ff80..db2146f8c1 100644 --- a/src/shared/fstab-util.c +++ b/src/shared/fstab-util.c @@ -20,9 +20,26 @@ ***/ #include "fstab-util.h" +#include "path-util.h" #include "strv.h" #include "util.h" +bool fstab_is_mount_point(const char *mount) { + _cleanup_free_ char *device = NULL; + _cleanup_endmntent_ FILE *f = NULL; + struct mntent *m; + + f = setmntent("/etc/fstab", "r"); + if (!f) + return false; + + while ((m = getmntent(f))) + if (path_equal(m->mnt_dir, mount)) + return true; + + return false; +} + int fstab_filter_options(const char *opts, const char *names, const char **namefound, char **value, char **filtered) { const char *name, *n = NULL, *x; diff --git a/src/shared/fstab-util.h b/src/shared/fstab-util.h index 387c562a96..872b2363cd 100644 --- a/src/shared/fstab-util.h +++ b/src/shared/fstab-util.h @@ -25,6 +25,7 @@ #include <stddef.h> #include "macro.h" +bool fstab_is_mount_point(const char *mount); int fstab_filter_options(const char *opts, const char *names, const char **namefound, char **value, char **filtered); diff --git a/src/shared/install.c b/src/shared/install.c index 3d2b5ae77f..238433c808 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -949,8 +949,7 @@ static int config_parse_also( return r; } if (!isempty(state)) - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Trailing garbage, ignoring."); + log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); return 0; } diff --git a/src/shared/pager.c b/src/shared/pager.c index 41da820938..d8f0fb404d 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -48,24 +48,27 @@ noreturn static void pager_fallback(void) { } int pager_open(bool jump_to_end) { - int fd[2]; + _cleanup_close_pair_ int fd[2] = { -1, -1 }; const char *pager; pid_t parent_pid; - int r; if (pager_pid > 0) return 1; - if ((pager = getenv("SYSTEMD_PAGER")) || (pager = getenv("PAGER"))) - if (!*pager || streq(pager, "cat")) - return 0; - if (!on_tty()) return 0; + pager = getenv("SYSTEMD_PAGER"); + if (!pager) + pager = getenv("PAGER"); + + /* If the pager is explicitly turned off, honour it */ + if (pager && (pager[0] == 0 || streq(pager, "cat"))) + return 0; + /* Determine and cache number of columns before we spawn the * pager so that we get the value from the actual tty */ - columns(); + (void) columns(); if (pipe(fd) < 0) return log_error_errno(errno, "Failed to create pager pipe: %m"); @@ -73,11 +76,8 @@ int pager_open(bool jump_to_end) { parent_pid = getpid(); pager_pid = fork(); - if (pager_pid < 0) { - r = log_error_errno(errno, "Failed to fork pager: %m"); - safe_close_pair(fd); - return r; - } + if (pager_pid < 0) + return log_error_errno(errno, "Failed to fork pager: %m"); /* In the child start the pager */ if (pager_pid == 0) { @@ -86,7 +86,7 @@ int pager_open(bool jump_to_end) { (void) reset_all_signal_handlers(); (void) reset_signal_mask(); - dup2(fd[0], STDIN_FILENO); + (void) dup2(fd[0], STDIN_FILENO); safe_close_pair(fd); /* Initialize a good set of less options */ @@ -141,7 +141,6 @@ int pager_open(bool jump_to_end) { if (dup2(fd[1], STDERR_FILENO) < 0) return log_error_errno(errno, "Failed to duplicate pager pipe: %m"); - safe_close_pair(fd); return 1; } diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index d803bbe07e..34eec959ef 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -181,7 +181,7 @@ static char** user_dirs( if (strv_extend_strv_concat(&res, config_dirs, "/systemd/user") < 0) return NULL; - if (strv_extend_strv(&res, (char**) config_unit_paths) < 0) + if (strv_extend_strv(&res, (char**) config_unit_paths, false) < 0) return NULL; if (runtime_dir) @@ -203,7 +203,7 @@ static char** user_dirs( if (strv_extend_strv_concat(&res, data_dirs, "/systemd/user") < 0) return NULL; - if (strv_extend_strv(&res, (char**) data_unit_paths) < 0) + if (strv_extend_strv(&res, (char**) data_unit_paths, false) < 0) return NULL; if (generator_late) @@ -318,7 +318,7 @@ int lookup_paths_init( if (!unit_path) return -ENOMEM; - r = strv_extend_strv(&p->unit_path, unit_path); + r = strv_extend_strv(&p->unit_path, unit_path, false); if (r < 0) return r; } diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 789f217efc..7749f20540 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -32,6 +32,8 @@ struct PTYForward { int master; + PTYForwardFlags flags; + sd_event_source *stdin_event_source; sd_event_source *stdout_event_source; sd_event_source *master_event_source; @@ -41,8 +43,6 @@ struct PTYForward { struct termios saved_stdin_attr; struct termios saved_stdout_attr; - bool read_only:1; - bool saved_stdin:1; bool saved_stdout:1; @@ -54,8 +54,7 @@ struct PTYForward { bool master_writable:1; bool master_hangup:1; - /* Continue reading after hangup? */ - bool ignore_vhangup:1; + bool read_from_master:1; bool last_char_set:1; char last_char; @@ -100,6 +99,18 @@ static bool look_for_escape(PTYForward *f, const char *buffer, size_t n) { return false; } +static bool ignore_vhangup(PTYForward *f) { + assert(f); + + if (f->flags & PTY_FORWARD_IGNORE_VHANGUP) + return true; + + if ((f->flags & PTY_FORWARD_IGNORE_INITIAL_VHANGUP) && !f->read_from_master) + return true; + + return false; +} + static int shovel(PTYForward *f) { ssize_t k; @@ -179,7 +190,7 @@ static int shovel(PTYForward *f) { * EAGAIN here and try again, unless * ignore_vhangup is off. */ - if (errno == EAGAIN || (errno == EIO && f->ignore_vhangup)) + if (errno == EAGAIN || (errno == EIO && ignore_vhangup(f))) f->master_readable = false; else if (errno == EPIPE || errno == ECONNRESET || errno == EIO) { f->master_readable = f->master_writable = false; @@ -190,8 +201,10 @@ static int shovel(PTYForward *f) { log_error_errno(errno, "read(): %m"); return sd_event_exit(f->event, EXIT_FAILURE); } - } else + } else { + f->read_from_master = true; f->out_buffer_full += (size_t) k; + } } if (f->stdout_writable && f->out_buffer_full > 0) { @@ -302,8 +315,7 @@ static int on_sigwinch_event(sd_event_source *e, const struct signalfd_siginfo * int pty_forward_new( sd_event *event, int master, - bool ignore_vhangup, - bool read_only, + PTYForwardFlags flags, PTYForward **ret) { _cleanup_(pty_forward_freep) PTYForward *f = NULL; @@ -314,8 +326,7 @@ int pty_forward_new( if (!f) return -ENOMEM; - f->read_only = read_only; - f->ignore_vhangup = ignore_vhangup; + f->flags = flags; if (event) f->event = sd_event_ref(event); @@ -325,7 +336,7 @@ int pty_forward_new( return r; } - if (!read_only) { + if (!(flags & PTY_FORWARD_READ_ONLY)) { r = fd_nonblock(STDIN_FILENO, true); if (r < 0) return r; @@ -344,7 +355,7 @@ int pty_forward_new( if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0) (void) ioctl(master, TIOCSWINSZ, &ws); - if (!read_only) { + if (!(flags & PTY_FORWARD_READ_ONLY)) { if (tcgetattr(STDIN_FILENO, &f->saved_stdin_attr) >= 0) { struct termios raw_stdin_attr; @@ -429,16 +440,20 @@ int pty_forward_get_last_char(PTYForward *f, char *ch) { return 0; } -int pty_forward_set_ignore_vhangup(PTYForward *f, bool ignore_vhangup) { +int pty_forward_set_ignore_vhangup(PTYForward *f, bool b) { int r; assert(f); - if (f->ignore_vhangup == ignore_vhangup) + if (!!(f->flags & PTY_FORWARD_IGNORE_VHANGUP) == b) return 0; - f->ignore_vhangup = ignore_vhangup; - if (!f->ignore_vhangup) { + if (b) + f->flags |= PTY_FORWARD_IGNORE_VHANGUP; + else + f->flags &= ~PTY_FORWARD_IGNORE_VHANGUP; + + if (!ignore_vhangup(f)) { /* We shall now react to vhangup()s? Let's check * immediately if we might be in one */ @@ -455,5 +470,5 @@ int pty_forward_set_ignore_vhangup(PTYForward *f, bool ignore_vhangup) { int pty_forward_get_ignore_vhangup(PTYForward *f) { assert(f); - return f->ignore_vhangup; + return !!(f->flags & PTY_FORWARD_IGNORE_VHANGUP); } diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h index 6f84e4036a..9b3214221b 100644 --- a/src/shared/ptyfwd.h +++ b/src/shared/ptyfwd.h @@ -27,7 +27,17 @@ typedef struct PTYForward PTYForward; -int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, bool read_only, PTYForward **f); +typedef enum PTYForwardFlags { + PTY_FORWARD_READ_ONLY = 1, + + /* Continue reading after hangup? */ + PTY_FORWARD_IGNORE_VHANGUP = 2, + + /* Continue reading after hangup but only if we never read anything else? */ + PTY_FORWARD_IGNORE_INITIAL_VHANGUP = 4, +} PTYForwardFlags; + +int pty_forward_new(sd_event *event, int master, PTYForwardFlags flags, PTYForward **f); PTYForward *pty_forward_free(PTYForward *f); int pty_forward_get_last_char(PTYForward *f, char *ch); diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index 1064fd5cbd..3dedbd1f62 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -226,7 +226,7 @@ static bool enough_memory_for_hibernation(void) { if (r < 0) return false; - r = get_status_field("/proc/meminfo", "\nActive(anon):", &active); + r = get_proc_field("/proc/meminfo", "Active(anon)", WHITESPACE, &active); if (r < 0) { log_error_errno(r, "Failed to retrieve Active(anon) from /proc/meminfo: %m"); return false; diff --git a/src/shared/spawn-ask-password-agent.c b/src/shared/spawn-ask-password-agent.c index 70466d17e5..29db855c67 100644 --- a/src/shared/spawn-ask-password-agent.c +++ b/src/shared/spawn-ask-password-agent.c @@ -19,13 +19,13 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <signal.h> #include <stdlib.h> #include <unistd.h> -#include <signal.h> #include "log.h" -#include "util.h" #include "process-util.h" +#include "util.h" #include "spawn-ask-password-agent.h" static pid_t agent_pid = 0; @@ -46,9 +46,9 @@ int ask_password_agent_open(void) { SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, "--watch", NULL); if (r < 0) - log_error_errno(r, "Failed to fork TTY ask password agent: %m"); + return log_error_errno(r, "Failed to fork TTY ask password agent: %m"); - return r; + return 1; } void ask_password_agent_close(void) { @@ -57,8 +57,8 @@ void ask_password_agent_close(void) { return; /* Inform agent that we are done */ - kill(agent_pid, SIGTERM); - kill(agent_pid, SIGCONT); + (void) kill(agent_pid, SIGTERM); + (void) kill(agent_pid, SIGCONT); (void) wait_for_terminate(agent_pid, NULL); agent_pid = 0; } diff --git a/src/shared/sysctl-util.c b/src/shared/sysctl-util.c index 1de0b94fd5..b2cab948ef 100644 --- a/src/shared/sysctl-util.c +++ b/src/shared/sysctl-util.c @@ -19,18 +19,17 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdlib.h> -#include <stdbool.h> #include <errno.h> -#include <string.h> -#include <stdio.h> -#include <limits.h> #include <getopt.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "fileio.h" #include "log.h" #include "util.h" -#include "fileio.h" -#include "build.h" #include "sysctl-util.h" char *sysctl_normalize(char *s) { |