X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=util.c;h=8556ea12cd153d6899f3b98a8cc803e80b61f401;hp=dd4dc097a95aaf2f129cec8076e5bdb14db8c3d7;hb=22be7e82e20a972b0e2338ee9af11a79033a8db4;hpb=8d567588cad053f79abe603ab113e1b85a92f1da diff --git a/util.c b/util.c index dd4dc097a..8556ea12c 100644 --- a/util.c +++ b/util.c @@ -114,6 +114,9 @@ bool endswith(const char *s, const char *postfix) { sl = strlen(s); pl = strlen(postfix); + if (pl == 0) + return true; + if (sl < pl) return false; @@ -129,6 +132,9 @@ bool startswith(const char *s, const char *prefix) { sl = strlen(s); pl = strlen(prefix); + if (pl == 0) + return true; + if (sl < pl) return false; @@ -147,11 +153,14 @@ bool first_word(const char *s, const char *word) { if (sl < wl) return false; + if (wl == 0) + return true; + if (memcmp(s, word, wl) != 0) return false; - return (s[wl] == 0 || - strchr(WHITESPACE, s[wl])); + return s[wl] == 0 || + strchr(WHITESPACE, s[wl]); } int close_nointr(int fd) { @@ -1140,6 +1149,39 @@ bool path_startswith(const char *path, const char *prefix) { } } +bool path_equal(const char *a, const char *b) { + assert(a); + assert(b); + + if ((a[0] == '/') != (b[0] == '/')) + return false; + + for (;;) { + size_t j, k; + + a += strspn(a, "/"); + b += strspn(b, "/"); + + if (*a == 0 && *b == 0) + return true; + + if (*a == 0 || *b == 0) + return false; + + j = strcspn(a, "/"); + k = strcspn(b, "/"); + + if (j != k) + return false; + + if (memcmp(a, b, j) != 0) + return false; + + a += j; + b += k; + } +} + char *ascii_strlower(char *t) { char *p; @@ -1215,7 +1257,7 @@ int close_all_fds(const int except[], unsigned n_except) { while ((de = readdir(d))) { int fd = -1; - if (de->d_name[0] == '.') + if (ignore_file(de->d_name)) continue; if ((r = safe_atoi(de->d_name, &fd)) < 0) @@ -1324,7 +1366,7 @@ int chvt(int vt) { if (ioctl(fd, VT_ACTIVATE, vt) < 0) r = -errno; - close_nointr(r); + close_nointr_nofail(r); return r; } @@ -1387,10 +1429,14 @@ int ask(char *ret, const char *replies, const char *text, ...) { int r; bool need_nl = true; + fputs("\x1B[1m", stdout); + va_start(ap, text); vprintf(text, ap); va_end(ap); + fputs("\x1B[0m", stdout); + fflush(stdout); if ((r = read_one_char(stdin, &c, &need_nl)) < 0) { @@ -1612,7 +1658,7 @@ int acquire_terminal(const char *name, bool fail, bool force) { } if (notify >= 0) - close_nointr(notify); + close_nointr_nofail(notify); if ((r = reset_terminal(fd)) < 0) log_warning("Failed to reset terminal: %s", strerror(-r)); @@ -1621,23 +1667,34 @@ int acquire_terminal(const char *name, bool fail, bool force) { fail: if (fd >= 0) - close_nointr(fd); + close_nointr_nofail(fd); if (notify >= 0) - close_nointr(notify); + close_nointr_nofail(notify); return r; } int release_terminal(void) { int r = 0, fd; + struct sigaction sa_old, sa_new; - if ((fd = open("/dev/tty", O_RDWR)) < 0) + if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY)) < 0) return -errno; + /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed + * by our own TIOCNOTTY */ + + zero(sa_new); + sa_new.sa_handler = SIG_IGN; + sa_new.sa_flags = SA_RESTART; + assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0); + if (ioctl(fd, TIOCNOTTY) < 0) r = -errno; + assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0); + close_nointr_nofail(fd); return r; } @@ -1743,6 +1800,69 @@ int path_is_mount_point(const char *t) { return a.st_dev != b.st_dev; } +int parse_usec(const char *t, usec_t *usec) { + static const struct { + const char *suffix; + usec_t usec; + } table[] = { + { "sec", USEC_PER_SEC }, + { "s", USEC_PER_SEC }, + { "min", USEC_PER_MINUTE }, + { "hr", USEC_PER_HOUR }, + { "h", USEC_PER_HOUR }, + { "d", USEC_PER_DAY }, + { "w", USEC_PER_WEEK }, + { "msec", USEC_PER_MSEC }, + { "ms", USEC_PER_MSEC }, + { "m", USEC_PER_MINUTE }, + { "usec", 1ULL }, + { "us", 1ULL }, + { "", USEC_PER_SEC }, + }; + + const char *p; + usec_t r = 0; + + assert(t); + assert(usec); + + p = t; + do { + long long l; + char *e; + unsigned i; + + errno = 0; + l = strtoll(p, &e, 10); + + if (errno != 0) + return -errno; + + if (l < 0) + return -ERANGE; + + if (e == p) + return -EINVAL; + + e += strspn(e, WHITESPACE); + + for (i = 0; i < ELEMENTSOF(table); i++) + if (startswith(e, table[i].suffix)) { + r += (usec_t) l * table[i].usec; + p = e + strlen(table[i].suffix); + break; + } + + if (i >= ELEMENTSOF(table)) + return -EINVAL; + + } while (*p != 0); + + *usec = r; + + return 0; +} + static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime",