X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Futil.c;h=58b96aec68f88fd8f09e9364a1f088cc8b153c8e;hp=41d8e7f999eeaffaf695d06bcbeea22e34ca9531;hb=0bab36f250cc79776954fd6066c1e2a33f64c016;hpb=6398320759ce4ed84922bb28f715d3c6c66166c4 diff --git a/src/util.c b/src/util.c index 41d8e7f99..58b96aec6 100644 --- a/src/util.c +++ b/src/util.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "macro.h" #include "util.h" @@ -306,40 +307,6 @@ int safe_atoi(const char *s, int *ret_i) { return 0; } -int safe_atolu(const char *s, long unsigned *ret_lu) { - char *x = NULL; - unsigned long l; - - assert(s); - assert(ret_lu); - - errno = 0; - l = strtoul(s, &x, 0); - - if (!x || *x || errno) - return errno ? -errno : -EINVAL; - - *ret_lu = l; - return 0; -} - -int safe_atoli(const char *s, long int *ret_li) { - char *x = NULL; - long l; - - assert(s); - assert(ret_li); - - errno = 0; - l = strtol(s, &x, 0); - - if (!x || *x || errno) - return errno ? -errno : -EINVAL; - - *ret_li = l; - return 0; -} - int safe_atollu(const char *s, long long unsigned *ret_llu) { char *x = NULL; unsigned long long l; @@ -393,7 +360,8 @@ char *split(const char *c, size_t *l, const char *separator, char **state) { /* Split a string into words, but consider strings enclosed in '' and * "" as words even if they include spaces. */ char *split_quoted(const char *c, size_t *l, char **state) { - char *current; + char *current, *e; + bool escaped = false; current = *state ? *state : (char*) c; @@ -404,26 +372,45 @@ char *split_quoted(const char *c, size_t *l, char **state) { if (*current == '\'') { current ++; - *l = strcspn(current, "'"); - *state = current+*l; - if (**state == '\'') - (*state)++; + for (e = current; *e; e++) { + if (escaped) + escaped = false; + else if (*e == '\\') + escaped = true; + else if (*e == '\'') + break; + } + + *l = e-current; + *state = *e == 0 ? e : e+1; } else if (*current == '\"') { current ++; - *l = strcspn(current, "\""); - *state = current+*l; - if (**state == '\"') - (*state)++; + for (e = current; *e; e++) { + if (escaped) + escaped = false; + else if (*e == '\\') + escaped = true; + else if (*e == '\"') + break; + } + + *l = e-current; + *state = *e == 0 ? e : e+1; } else { - *l = strcspn(current, WHITESPACE); - *state = current+*l; + for (e = current; *e; e++) { + if (escaped) + escaped = false; + else if (*e == '\\') + escaped = true; + else if (strchr(WHITESPACE, *e)) + break; + } + *l = e-current; + *state = e; } - /* FIXME: Cannot deal with strings that have spaces AND ticks - * in them */ - return (char*) current; } @@ -565,6 +552,67 @@ int get_process_name(pid_t pid, char **name) { return 0; } +int get_process_cmdline(pid_t pid, size_t max_length, char **line) { + char *p, *r, *k; + int c; + bool space = false; + size_t left; + FILE *f; + + assert(pid >= 1); + assert(max_length > 0); + assert(line); + + if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0) + return -ENOMEM; + + f = fopen(p, "r"); + free(p); + + if (!f) + return -errno; + + if (!(r = new(char, max_length))) { + fclose(f); + return -ENOMEM; + } + + k = r; + left = max_length; + while ((c = getc(f)) != EOF) { + + if (isprint(c)) { + if (space) { + if (left <= 4) + break; + + *(k++) = ' '; + left--; + space = false; + } + + if (left <= 4) + break; + + *(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; + + fclose(f); + + *line = r; + return 0; +} + char *strappend(const char *s, const char *suffix) { size_t a, b; char *r; @@ -1184,7 +1232,7 @@ char *cunescape(const char *s) { default: /* Invalid escape code, let's take it literal then */ *(t++) = '\\'; - *(t++) = 'f'; + *(t++) = *f; break; } } @@ -2537,6 +2585,105 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { return 0; } +cpu_set_t* cpu_set_malloc(unsigned *ncpus) { + cpu_set_t *r; + unsigned n = 1024; + + /* Allocates the cpuset in the right size */ + + for (;;) { + if (!(r = CPU_ALLOC(n))) + return NULL; + + if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) { + CPU_ZERO_S(CPU_ALLOC_SIZE(n), r); + + if (ncpus) + *ncpus = n; + + return r; + } + + CPU_FREE(r); + + if (errno != EINVAL) + return NULL; + + n *= 2; + } +} + +void status_vprintf(const char *format, va_list ap) { + char *s = NULL; + int fd = -1; + + assert(format); + + /* This independent of logging, as status messages are + * optional and go exclusively to the console. */ + + if (vasprintf(&s, format, ap) < 0) + goto finish; + + if ((fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0) + goto finish; + + write(fd, s, strlen(s)); + +finish: + free(s); + + if (fd >= 0) + close_nointr_nofail(fd); +} + +void status_printf(const char *format, ...) { + va_list ap; + + assert(format); + + va_start(ap, format); + status_vprintf(format, ap); + va_end(ap); +} + +void status_welcome(void) { + +#if defined(TARGET_FEDORA) + char *r; + + if (read_one_line_file("/etc/system-release", &r) < 0) + return; + + truncate_nl(r); + + /* This tries to mimic the color magic the old Red Hat sysinit + * script did. */ + + if (startswith(r, "Red Hat")) + status_printf("Welcome to \x1B[0;31m%s\x1B[0m!\n", r); /* Red for RHEL */ + else if (startswith(r, "Fedora")) + status_printf("Welcome to \x1B[0;34m%s\x1B[0m!\n", r); /* Blue for Fedora */ + else + status_printf("Welcome to %s!\n", r); + + free(r); + +#elif defined(TARGET_SUSE) + char *r; + + if (read_one_line_file("/etc/SuSE-release", &r) < 0) + return; + + truncate_nl(r); + + status_printf("Welcome to \x1B[0;32m%s\x1B[0m!\n", r); /* Green for SUSE */ + free(r); +#else +#warning "You probably should add a welcome text logic here." +#endif +} + static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime", @@ -2625,3 +2772,12 @@ static const char* const rlimit_table[] = { }; DEFINE_STRING_TABLE_LOOKUP(rlimit, int); + +static const char* const ip_tos_table[] = { + [IPTOS_LOWDELAY] = "low-delay", + [IPTOS_THROUGHPUT] = "throughput", + [IPTOS_RELIABILITY] = "reliability", + [IPTOS_LOWCOST] = "low-cost", +}; + +DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);