X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Futil.c;h=a0fbdc517e7167a7f85cfe4ecccdfb9afa22175f;hp=5d57d52dc8ba7763f5e9b52f699e8c839ad0eb60;hb=4d44e4f0b5d54327c112ad26a4b26397789d7192;hpb=98a28fef2618e54a644614c759f371f297381b70 diff --git a/src/util.c b/src/util.c index 5d57d52dc..a0fbdc517 100644 --- a/src/util.c +++ b/src/util.c @@ -53,6 +53,7 @@ #include #include #include +#include #include "macro.h" #include "util.h" @@ -64,6 +65,9 @@ #include "exit-status.h" #include "hashmap.h" +int saved_argc = 0; +char **saved_argv = NULL; + size_t page_size(void) { static __thread size_t pgsz = 0; long r; @@ -487,7 +491,7 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) { assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1)); char_array_0(fn); - if (!(f = fopen(fn, "r"))) + if (!(f = fopen(fn, "re"))) return -errno; if (!(fgets(line, sizeof(line), f))) { @@ -532,7 +536,7 @@ int get_starttime_of_pid(pid_t pid, unsigned long long *st) { assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1)); char_array_0(fn); - if (!(f = fopen(fn, "r"))) + if (!(f = fopen(fn, "re"))) return -errno; if (!(fgets(line, sizeof(line), f))) { @@ -1007,7 +1011,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, char **line) { if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0) return -ENOMEM; - f = fopen(p, "r"); + f = fopen(p, "re"); free(p); if (!f) @@ -2653,7 +2657,7 @@ int release_terminal(void) { int r = 0, fd; struct sigaction sa_old, sa_new; - if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY)) < 0) + if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC)) < 0) return -errno; /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed @@ -2944,6 +2948,10 @@ int make_stdio(int fd) { if (r < 0 || s < 0 || t < 0) return -errno; + fd_cloexec(STDIN_FILENO, false); + fd_cloexec(STDOUT_FILENO, false); + fd_cloexec(STDERR_FILENO, false); + return 0; } @@ -3026,6 +3034,20 @@ void rename_process(const char name[8]) { if (program_invocation_name) strncpy(program_invocation_name, name, strlen(program_invocation_name)); + + if (saved_argc > 0) { + int i; + + if (saved_argv[0]) + strncpy(saved_argv[0], name, strlen(saved_argv[0])); + + for (i = 1; i < saved_argc; i++) { + if (!saved_argv[i]) + break; + + memset(saved_argv[i], 0, strlen(saved_argv[i])); + } + } } void sigset_add_many(sigset_t *ss, ...) { @@ -3114,23 +3136,28 @@ int getttyname_harder(int fd, char **r) { if (streq(s, "tty")) { free(s); - return get_ctty(r, NULL); + return get_ctty(0, NULL, r); } *r = s; return 0; } -int get_ctty_devnr(dev_t *d) { +int get_ctty_devnr(pid_t pid, dev_t *d) { int k; - char line[LINE_MAX], *p; + char line[LINE_MAX], *p, *fn; unsigned long ttynr; FILE *f; - if (!(f = fopen("/proc/self/stat", "r"))) + if (asprintf(&fn, "/proc/%lu/stat", (unsigned long) (pid <= 0 ? getpid() : pid)) < 0) + return -ENOMEM; + + f = fopen(fn, "re"); + free(fn); + if (!f) return -errno; - if (!(fgets(line, sizeof(line), f))) { + if (!fgets(line, sizeof(line), f)) { k = -errno; fclose(f); return k; @@ -3138,7 +3165,8 @@ int get_ctty_devnr(dev_t *d) { fclose(f); - if (!(p = strrchr(line, ')'))) + p = strrchr(line, ')'); + if (!p) return -EIO; p++; @@ -3156,14 +3184,15 @@ int get_ctty_devnr(dev_t *d) { return 0; } -int get_ctty(char **r, dev_t *_devnr) { +int get_ctty(pid_t pid, dev_t *_devnr, char **r) { int k; char fn[PATH_MAX], *s, *b, *p; dev_t devnr; assert(r); - if ((k = get_ctty_devnr(&devnr)) < 0) + k = get_ctty_devnr(pid, &devnr); + if (k < 0) return k; snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr)); @@ -3837,8 +3866,12 @@ char *normalize_env_assignment(const char *s) { } int wait_for_terminate(pid_t pid, siginfo_t *status) { + siginfo_t dummy; + assert(pid >= 1); - assert(status); + + if (!status) + status = &dummy; for (;;) { zero(*status); @@ -4248,7 +4281,7 @@ int detect_container(const char **id) { return 1; } - if ((f = fopen("/proc/self/cgroup", "r"))) { + if ((f = fopen("/proc/self/cgroup", "re"))) { for (;;) { char line[LINE_MAX], *p; @@ -4667,7 +4700,11 @@ int vt_disallocate(const char *name) { if (fd < 0) return fd; - loop_write(fd, "\033[H\033[2J", 7, false); /* clear screen */ + loop_write(fd, + "\033[r" /* clear scrolling region */ + "\033[H" /* move home */ + "\033[2J", /* clear screen */ + 10, false); close_nointr_nofail(fd); return 0; @@ -4703,8 +4740,11 @@ int vt_disallocate(const char *name) { if (fd < 0) return fd; - /* Requires Linux 2.6.40 */ - loop_write(fd, "\033[H\033[3J", 7, false); /* clear screen including scrollback */ + loop_write(fd, + "\033[r" /* clear scrolling region */ + "\033[H" /* move home */ + "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */ + 10, false); close_nointr_nofail(fd); return 0; @@ -5123,6 +5163,110 @@ int audit_session_from_pid(pid_t pid, uint32_t *id) { return 0; } +bool display_is_local(const char *display) { + assert(display); + + return + display[0] == ':' && + display[1] >= '0' && + display[1] <= '9'; +} + +int socket_from_display(const char *display, char **path) { + size_t k; + char *f, *c; + + assert(display); + assert(path); + + if (!display_is_local(display)) + return -EINVAL; + + k = strspn(display+1, "0123456789"); + + f = new(char, sizeof("/tmp/.X11-unix/X") + k); + if (!f) + return -ENOMEM; + + c = stpcpy(f, "/tmp/.X11-unix/X"); + memcpy(c, display+1, k); + c[k] = 0; + + *path = f; + + return 0; +} + +int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home) { + struct passwd *p; + unsigned long lu; + + assert(username); + assert(*username); + assert(uid); + assert(gid); + assert(home); + + /* We enforce some special rules for uid=0: in order to avoid + * NSS lookups for root we hardcode its data. */ + + if (streq(*username, "root") || streq(*username, "0")) { + *username = "root"; + *uid = 0; + *gid = 0; + *home = "/root"; + return 0; + } + + if (safe_atolu(*username, &lu) >= 0) { + errno = 0; + p = getpwuid((uid_t) lu); + + /* If there are multiple users with the same id, make + * sure to leave $USER to the configured value instead + * of the first occurrence in the database. However if + * the uid was configured by a numeric uid, then let's + * pick the real username from /etc/passwd. */ + if (p) + *username = p->pw_name; + } else { + errno = 0; + p = getpwnam(*username); + } + + if (!p) + return errno != 0 ? -errno : -ESRCH; + + *uid = p->pw_uid; + *gid = p->pw_gid; + *home = p->pw_dir; + return 0; +} + +int glob_exists(const char *path) { + glob_t g; + int r, k; + + assert(path); + + zero(g); + errno = 0; + k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); + + if (k == GLOB_NOMATCH) + r = 0; + else if (k == GLOB_NOSPACE) + r = -ENOMEM; + else if (k == 0) + r = !strv_isempty(g.gl_pathv); + else + r = errno ? -errno : -EIO; + + globfree(&g); + + return r; +} + static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime",