X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=d5de59fce90955530cf0f2c121f46a41ca7caa41;hp=9ec6e2fe2f5e2ad54bb373eb12da157806f7bab8;hb=55c0b89c575fcb2c075286d444ed4fb1cf8c8563;hpb=e8bc0ea2b100158bf35c635039226235aa879068 diff --git a/src/shared/util.c b/src/shared/util.c index 9ec6e2fe2..d5de59fce 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -439,7 +439,6 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) { if (!fgets(line, sizeof(line), f)) { r = feof(f) ? -EIO : -errno; - fclose(f); return r; } @@ -905,13 +904,10 @@ int get_process_comm(pid_t pid, char **name) { } int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) { - char *r, *k; + char *r = NULL, *k; int c; - bool space = false; - size_t left; FILE *f; - assert(max_length > 0); assert(line); if (pid == 0) @@ -927,47 +923,64 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * if (!f) return -errno; + if (max_length == 0) { + size_t len = 1; + while ((c = getc(f)) != EOF) { + k = realloc(r, len+1); + if (k == NULL) { + free(r); + fclose(f); + return -ENOMEM; + } + r = k; + r[len-1] = isprint(c) ? c : ' '; + r[len] = 0; + len++; + } + } else { + bool space = false; + size_t left; + r = new(char, max_length); + if (!r) { + fclose(f); + return -ENOMEM; + } - r = new(char, max_length); - if (!r) { - fclose(f); - return -ENOMEM; - } + k = r; + left = max_length; + while ((c = getc(f)) != EOF) { + + if (isprint(c)) { + if (space) { + if (left <= 4) + break; - k = r; - left = max_length; - while ((c = getc(f)) != EOF) { + *(k++) = ' '; + left--; + space = false; + } - if (isprint(c)) { - if (space) { if (left <= 4) break; - *(k++) = ' '; + *(k++) = (char) c; left--; - space = false; - } - - if (left <= 4) - break; + } else + space = true; + } - *(k++) = (char) c; - left--; - } else - space = true; + if (left <= 4) { + size_t n = MIN(left-1, 3U); + memcpy(k, "...", n); + k[n] = 0; + } else + *k = 0; } - if (left <= 4) { - size_t n = MIN(left-1, 3U); - memcpy(k, "...", n); - k[n] = 0; - } else - *k = 0; - fclose(f); /* Kernel threads have no argv[] */ - if (r[0] == 0) { + if (r == NULL || r[0] == 0) { char *t; int h; @@ -2851,6 +2864,9 @@ int get_ctty_devnr(pid_t pid, dev_t *d) { &ttynr) != 1) return -EIO; + if (major(ttynr) == 0 && minor(ttynr) == 0) + return -ENOENT; + *d = (dev_t) ttynr; return 0; } @@ -2869,7 +2885,8 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) { snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr)); char_array_0(fn); - if ((k = readlink_malloc(fn, &s)) < 0) { + k = readlink_malloc(fn, &s); + if (k < 0) { if (k != -ENOENT) return k; @@ -2890,7 +2907,8 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) { * symlink in /dev/char. Let's return something * vaguely useful. */ - if (!(b = strdup(fn + 5))) + b = strdup(fn + 5); + if (!b) return -ENOMEM; *r = b; @@ -4439,6 +4457,23 @@ int get_user_creds( return 0; } +char* uid_to_name(uid_t uid) { + struct passwd *p; + char *r; + + if (uid == 0) + return strdup("root"); + + p = getpwuid(uid); + if (p) + return strdup(p->pw_name); + + if (asprintf(&r, "%lu", (unsigned long) uid) < 0) + return NULL; + + return r; +} + int get_group_creds(const char **groupname, gid_t *gid) { struct group *g; gid_t id; @@ -5277,9 +5312,13 @@ int can_sleep(const char *type) { assert(type); + /* If /sys is read-only we cannot sleep */ + if (access("/sys/power/state", W_OK) < 0) + return false; + r = read_one_line_file("/sys/power/state", &p); if (r < 0) - return r == -ENOENT ? 0 : r; + return false; k = strlen(type); FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) @@ -5297,9 +5336,14 @@ int can_sleep_disk(const char *type) { assert(type); + /* If /sys is read-only we cannot sleep */ + if (access("/sys/power/state", W_OK) < 0 || + access("/sys/power/disk", W_OK) < 0) + return false; + r = read_one_line_file("/sys/power/disk", &p); if (r < 0) - return r == -ENOENT ? 0 : r; + return false; k = strlen(type); FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) { @@ -5604,12 +5648,14 @@ const char *draw_special_char(DrawSpecialChar ch) { [DRAW_TREE_VERT] = "\342\224\202 ", /* │ */ [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */ [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */ + [DRAW_TREE_SPACE] = " ", /* */ [DRAW_TRIANGULAR_BULLET] = "\342\200\243 ", /* ‣ */ }, /* ASCII fallback */ { [DRAW_TREE_VERT] = "| ", [DRAW_TREE_BRANCH] = "|-", [DRAW_TREE_RIGHT] = "`-", + [DRAW_TREE_SPACE] = " ", [DRAW_TRIANGULAR_BULLET] = "> ", } }; @@ -5668,7 +5714,7 @@ oom: } char *strip_tab_ansi(char **ibuf, size_t *_isz) { - const char *i, *begin; + const char *i, *begin = NULL; enum { STATE_OTHER, STATE_ESCAPE, @@ -5749,3 +5795,81 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) { return obuf; } + +int on_ac_power(void) { + bool found_offline = false, found_online = false; + _cleanup_closedir_ DIR *d = NULL; + + d = opendir("/sys/class/power_supply"); + if (!d) + return -errno; + + 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; + int k; + + k = readdir_r(d, &buf.de, &de); + if (k != 0) + return -k; + + if (!de) + break; + + if (ignore_file(de->d_name)) + continue; + + device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (device < 0) { + if (errno == ENOENT || errno == ENOTDIR) + continue; + + return -errno; + } + + fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { + if (errno == ENOENT) + continue; + + return -errno; + } + + n = read(fd, contents, sizeof(contents)); + if (n < 0) + return -errno; + + if (n != 6 || memcmp(contents, "Mains\n", 6)) + continue; + + close_nointr_nofail(fd); + fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { + if (errno == ENOENT) + continue; + + return -errno; + } + + n = read(fd, contents, sizeof(contents)); + if (n < 0) + return -errno; + + if (n != 2 || contents[1] != '\n') + return -EIO; + + if (contents[0] == '1') { + found_online = true; + break; + } else if (contents[0] == '0') + found_offline = true; + else + return -EIO; + } + + return found_online || !found_offline; +}