X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Futil.c;h=c2173c7222f192ae6ce5b373b3f7809cfc54539b;hb=7640a5de1b3ffe6547200ad204d14e4f067caf4f;hp=39c9db72fcc93271fb33efd7412e4548ce423318;hpb=8480e784f176a4911e22497e01bfbdf084342520;p=elogind.git diff --git a/src/util.c b/src/util.c index 39c9db72f..c2173c722 100644 --- a/src/util.c +++ b/src/util.c @@ -496,6 +496,64 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) { return 0; } +int get_starttime_of_pid(pid_t pid, unsigned long long *st) { + int r; + FILE *f; + char fn[PATH_MAX], line[LINE_MAX], *p; + + assert(pid > 0); + assert(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"))) + return -errno; + + if (!(fgets(line, sizeof(line), f))) { + r = -errno; + fclose(f); + return r; + } + + fclose(f); + + /* Let's skip the pid and comm fields. The latter is enclosed + * in () but does not escape any () in its value, so let's + * skip over it manually */ + + if (!(p = strrchr(line, ')'))) + return -EIO; + + p++; + + if (sscanf(p, " " + "%*c " /* state */ + "%*d " /* ppid */ + "%*d " /* pgrp */ + "%*d " /* session */ + "%*d " /* tty_nr */ + "%*d " /* tpgid */ + "%*u " /* flags */ + "%*u " /* minflt */ + "%*u " /* cminflt */ + "%*u " /* majflt */ + "%*u " /* cmajflt */ + "%*u " /* utime */ + "%*u " /* stime */ + "%*d " /* cutime */ + "%*d " /* cstime */ + "%*d " /* priority */ + "%*d " /* nice */ + "%*d " /* num_threads */ + "%*d " /* itrealvalue */ + "%llu " /* starttime */, + st) != 1) + return -EIO; + + return 0; +} + int write_one_line_file(const char *fn, const char *line) { FILE *f; int r; @@ -550,6 +608,8 @@ int read_one_line_file(const char *fn, char **line) { goto finish; } + truncate_nl(c); + *line = c; r = 0; @@ -774,6 +834,29 @@ finish: return r; } +int write_env_file(const char *fname, char **l) { + + char **i; + FILE *f; + int r; + + f = fopen(fname, "we"); + if (!f) + return -errno; + + STRV_FOREACH(i, l) { + fputs(*i, f); + fputc('\n', f); + } + + fflush(f); + + r = ferror(f) ? -errno : 0; + fclose(f); + + return r; +} + char *truncate_nl(char *s) { assert(s); @@ -797,7 +880,6 @@ int get_process_name(pid_t pid, char **name) { if (r < 0) return r; - truncate_nl(*name); return 0; } @@ -3199,8 +3281,7 @@ void status_welcome(void) { if (r != -ENOENT) log_warning("Failed to read /etc/system-release: %s", strerror(-r)); - } else - truncate_nl(pretty_name); + } } if (!ansi_color && pretty_name) { @@ -3221,8 +3302,7 @@ void status_welcome(void) { if (r != -ENOENT) log_warning("Failed to read /etc/SuSE-release: %s", strerror(-r)); - } else - truncate_nl(pretty_name); + } } if (!ansi_color) @@ -3235,8 +3315,7 @@ void status_welcome(void) { if (r != -ENOENT) log_warning("Failed to read /etc/gentoo-release: %s", strerror(-r)); - } else - truncate_nl(pretty_name); + } } if (!ansi_color) @@ -3249,8 +3328,7 @@ void status_welcome(void) { if (r != -ENOENT) log_warning("Failed to read /etc/altlinux-release: %s", strerror(-r)); - } else - truncate_nl(pretty_name); + } } if (!ansi_color) @@ -3267,7 +3345,6 @@ void status_welcome(void) { if (r != -ENOENT) log_warning("Failed to read /etc/debian_version: %s", strerror(-r)); } else { - truncate_nl(version); pretty_name = strappend("Debian ", version); free(version); @@ -3826,8 +3903,6 @@ const char *default_term_for_tty(const char *tty) { * TERM */ if (streq(tty, "console")) if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) { - truncate_nl(active); - /* If multiple log outputs are configured the * last one is what /dev/console points to */ if ((tty = strrchr(active, ' '))) @@ -4254,6 +4329,59 @@ int have_effective_cap(int value) { return r; } +char* strshorten(char *s, size_t l) { + assert(s); + + if (l < strlen(s)) + s[l] = 0; + + return s; +} + +static bool hostname_valid_char(char c) { + return + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c == '-' || + c == '_' || + c == '.'; +} + +bool hostname_is_valid(const char *s) { + const char *p; + + if (isempty(s)) + return false; + + for (p = s; *p; p++) + if (!hostname_valid_char(*p)) + return false; + + if (p-s > HOST_NAME_MAX) + return false; + + return true; +} + +char* hostname_cleanup(char *s) { + char *p, *d; + + for (p = s, d = s; *p; p++) + if ((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9') || + *p == '-' || + *p == '_' || + *p == '.') + *(d++) = *p; + + *d = 0; + + strshorten(s, HOST_NAME_MAX); + return s; +} + static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime",