X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=872f6f737192c827212f45a1aed2fa3c1c12b167;hp=152724949d3c14d1823cc488f63bf0daa8096932;hb=4750fade135aed733aa7a5fda7c670e6b4391538;hpb=a5c32cff1f56afe6f0c6c70d91a88a7a8238b2d7 diff --git a/src/shared/util.c b/src/shared/util.c index 152724949..872f6f737 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -353,6 +353,23 @@ int safe_atolli(const char *s, long long int *ret_lli) { return 0; } +int safe_atod(const char *s, double *ret_d) { + char *x = NULL; + double d; + + assert(s); + assert(ret_d); + + errno = 0; + d = strtod(s, &x); + + if (!x || x == s || *x || errno) + return errno ? -errno : -EINVAL; + + *ret_d = (double) d; + return 0; +} + /* Split a string into words. */ char *split(const char *c, size_t *l, const char *separator, char **state) { char *current; @@ -1012,7 +1029,6 @@ int rmdir_parents(const char *path, const char *stop) { return 0; } - char hexchar(int x) { static const char table[16] = "0123456789abcdef"; @@ -1033,6 +1049,23 @@ int unhexchar(char c) { return -1; } +char *hexmem(const void *p, size_t l) { + char *r, *z; + const uint8_t *x; + + z = r = malloc(l * 2 + 1); + if (!r) + return NULL; + + for (x = p; x < (const uint8_t*) p + l; x++) { + *(z++) = hexchar(*x >> 4); + *(z++) = hexchar(*x & 15); + } + + *z = 0; + return r; +} + char octchar(int x) { return '0' + (x & 7); } @@ -1308,16 +1341,24 @@ char *bus_path_escape(const char *s) { assert(s); /* Escapes all chars that D-Bus' object path cannot deal - * with. Can be reverse with bus_path_unescape() */ + * with. Can be reverse with bus_path_unescape(). We special + * case the empty string. */ - if (!(r = new(char, strlen(s)*3+1))) + if (*s == 0) + return strdup("_"); + + r = new(char, strlen(s)*3 + 1); + if (!r) return NULL; for (f = s, t = r; *f; f++) { + /* Escape everything that is not a-zA-Z0-9. We also + * escape 0-9 if it's the first character */ + if (!(*f >= 'A' && *f <= 'Z') && !(*f >= 'a' && *f <= 'z') && - !(*f >= '0' && *f <= '9')) { + !(f > s && *f >= '0' && *f <= '9')) { *(t++) = '_'; *(t++) = hexchar(*f >> 4); *(t++) = hexchar(*f); @@ -1335,7 +1376,12 @@ char *bus_path_unescape(const char *f) { assert(f); - if (!(r = strdup(f))) + /* Special case for the empty string */ + if (streq(f, "_")) + return strdup(""); + + r = new(char, strlen(f) + 1); + if (!r) return NULL; for (t = r; *f; f++) { @@ -2842,12 +2888,13 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus) { } } -int status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) { +int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) { static const char status_indent[] = " "; /* "[" STATUS "] " */ _cleanup_free_ char *s = NULL; _cleanup_close_ int fd = -1; - struct iovec iovec[5]; + struct iovec iovec[6]; int n = 0; + static bool prev_ephemeral; assert(format); @@ -2885,6 +2932,10 @@ int status_vprintf(const char *status, bool ellipse, const char *format, va_list zero(iovec); + if (prev_ephemeral) + IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE); + prev_ephemeral = ephemeral; + if (status) { if (!isempty(status)) { IOVEC_SET_STRING(iovec[n++], "["); @@ -2895,7 +2946,8 @@ int status_vprintf(const char *status, bool ellipse, const char *format, va_list } IOVEC_SET_STRING(iovec[n++], s); - IOVEC_SET_STRING(iovec[n++], "\n"); + if (!ephemeral) + IOVEC_SET_STRING(iovec[n++], "\n"); if (writev(fd, iovec, n) < 0) return -errno; @@ -2903,14 +2955,14 @@ int status_vprintf(const char *status, bool ellipse, const char *format, va_list return 0; } -int status_printf(const char *status, bool ellipse, const char *format, ...) { +int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) { va_list ap; int r; assert(format); va_start(ap, format); - r = status_vprintf(status, ellipse, format, ap); + r = status_vprintf(status, ellipse, ephemeral, format, ap); va_end(ap); return r; @@ -2927,7 +2979,7 @@ int status_welcome(void) { if (r < 0 && r != -ENOENT) log_warning("Failed to read /etc/os-release: %s", strerror(-r)); - return status_printf(NULL, false, + return status_printf(NULL, false, false, "\nWelcome to \x1B[%sm%s\x1B[0m!\n", isempty(ansi_color) ? "1" : ansi_color, isempty(pretty_name) ? "Linux" : pretty_name); @@ -3486,6 +3538,29 @@ int vtnr_from_tty(const char *tty) { return i; } +char *resolve_dev_console(char **active) { + char *tty; + + /* Resolve where /dev/console is pointing to, if /sys is actually ours + * (i.e. not read-only-mounted which is a sign for container setups) */ + + if (path_is_read_only_fs("/sys") > 0) + return NULL; + + if (read_one_line_file("/sys/class/tty/console/active", active) < 0) + return NULL; + + /* If multiple log outputs are configured the last one is what + * /dev/console points to */ + tty = strrchr(*active, ' '); + if (tty) + tty++; + else + tty = *active; + + return tty; +} + bool tty_is_vc_resolve(const char *tty) { char *active = NULL; bool b; @@ -3495,19 +3570,11 @@ bool tty_is_vc_resolve(const char *tty) { if (startswith(tty, "/dev/")) tty += 5; - /* Resolve where /dev/console is pointing to, if /sys is - * actually ours (i.e. not read-only-mounted which is a sign - * for container setups) */ - if (streq(tty, "console") && path_is_read_only_fs("/sys") <= 0) - if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) { - /* If multiple log outputs are configured the - * last one is what /dev/console points to */ - tty = strrchr(active, ' '); - if (tty) - tty++; - else - tty = active; - } + if (streq(tty, "console")) { + tty = resolve_dev_console(&active); + if (!tty) + return false; + } b = tty_is_vc(tty); free(active); @@ -3556,8 +3623,8 @@ void execute_directory(const char *directory, DIR *d, char *argv[]) { assert(directory); - /* Executes all binaries in a directory in parallel and waits - * until all they all finished. */ + /* Executes all binaries in a directory in parallel and + * waits for them to finish. */ if (!d) { if (!(_d = opendir(directory))) { @@ -5186,10 +5253,6 @@ int get_shell(char **_sh) { return 0; } -void freep(void *p) { - free(*(void**) p); -} - void fclosep(FILE **f) { if (*f) fclose(*f); @@ -5210,10 +5273,6 @@ void closedirp(DIR **d) { closedir(*d); } -void umaskp(mode_t *u) { - umask(*u); -} - bool filename_is_safe(const char *p) { if (isempty(p)) @@ -5494,7 +5553,6 @@ int on_ac_power(void) { for (;;) { struct dirent *de; union dirent_storage buf; - _cleanup_free_ char *p = NULL; _cleanup_close_ int fd = -1, device = -1; char contents[6]; ssize_t n; @@ -5639,3 +5697,121 @@ int search_and_fopen_nulstr(const char *path, const char *mode, const char *sear return search_and_fopen_internal(path, mode, s, _f); } + +int create_tmp_dir(char template[], char** dir_name) { + int r = 0; + char *d, *dt; + mode_t _cleanup_umask_ u; + + assert(dir_name); + + u = umask(0077); + d = mkdtemp(template); + if (!d) { + log_error("Can't create directory %s: %m", template); + return -errno; + } + + dt = strjoin(d, "/tmp", NULL); + if (!dt) { + r = log_oom(); + goto fail2; + } + + umask(0000); + r = mkdir(dt, 0777); + if (r) { + log_error("Can't create directory %s: %m", dt); + r = -errno; + goto fail1; + } + log_debug("Created temporary directory %s", dt); + + r = chmod(dt, 0777 | S_ISVTX); + if (r < 0) { + log_error("Failed to chmod %s: %m", dt); + r = -errno; + goto fail1; + } + log_debug("Set sticky bit on %s", dt); + + *dir_name = dt; + + return 0; +fail1: + rmdir(dt); +fail2: + rmdir(template); + return r; +} + +char *strextend(char **x, ...) { + va_list ap; + size_t f, l; + char *r, *p; + + assert(x); + + l = f = *x ? strlen(*x) : 0; + + va_start(ap, x); + for (;;) { + const char *t; + size_t n; + + t = va_arg(ap, const char *); + if (!t) + break; + + n = strlen(t); + if (n > ((size_t) -1) - l) { + va_end(ap); + return NULL; + } + + l += n; + } + va_end(ap); + + r = realloc(*x, l+1); + if (!r) + return NULL; + + p = r + f; + + va_start(ap, x); + for (;;) { + const char *t; + + t = va_arg(ap, const char *); + if (!t) + break; + + p = stpcpy(p, t); + } + va_end(ap); + + *p = 0; + *x = r; + + return r + l; +} + +char *strrep(const char *s, unsigned n) { + size_t l; + char *r, *p; + unsigned i; + + assert(s); + + l = strlen(s); + p = r = malloc(l * n + 1); + if (!r) + return NULL; + + for (i = 0; i < n; i++) + p = stpcpy(p, s); + + *p = 0; + return r; +}