return -errno;
if (!(fgets(line, sizeof(line), f))) {
- r = -errno;
+ r = feof(f) ? -EIO : -errno;
fclose(f);
return r;
}
return -errno;
if (!(fgets(line, sizeof(line), f))) {
- r = -errno;
+ r = feof(f) ? -EIO : -errno;
fclose(f);
return r;
}
return -errno;
if (!(fgets(t, sizeof(t), f))) {
- r = -errno;
+ r = feof(f) ? -EIO : -errno;
goto finish;
}
return r;
}
+int get_process_uid(pid_t pid, uid_t *uid) {
+ char *p;
+ FILE *f;
+ int r;
+
+ assert(uid);
+
+ if (pid == 0)
+ return getuid();
+
+ if (asprintf(&p, "/proc/%lu/status", (unsigned long) pid) < 0)
+ return -ENOMEM;
+
+ f = fopen(p, "re");
+ free(p);
+
+ if (!f)
+ return -errno;
+
+ while (!feof(f)) {
+ char line[LINE_MAX], *l;
+
+ if (!fgets(line, sizeof(line), f)) {
+ if (feof(f))
+ break;
+
+ r = -errno;
+ goto finish;
+ }
+
+ l = strstrip(line);
+
+ if (startswith(l, "Uid:")) {
+ l += 4;
+ l += strspn(l, WHITESPACE);
+
+ l[strcspn(l, WHITESPACE)] = 0;
+
+ r = parse_uid(l, uid);
+ goto finish;
+ }
+ }
+
+ r = -EIO;
+
+finish:
+ fclose(f);
+
+ return r;
+}
+
char *strnappend(const char *s, const char *suffix, size_t b) {
size_t a;
char *r;
bool need_nl = true;
if (on_tty)
- fputs("\x1B[1m", stdout);
+ fputs(ANSI_HIGHLIGHT_ON, stdout);
va_start(ap, text);
vprintf(text, ap);
va_end(ap);
if (on_tty)
- fputs("\x1B[0m", stdout);
+ fputs(ANSI_HIGHLIGHT_OFF, stdout);
fflush(stdout);
int reset_terminal_fd(int fd) {
struct termios termios;
int r = 0;
- long arg;
/* Set terminal to some sane defaults */
/* Disable exclusive mode, just in case */
ioctl(fd, TIOCNXCL);
+ /* Switch to text mode */
+ ioctl(fd, KDSETMODE, KD_TEXT);
+
/* Enable console unicode mode */
- arg = K_UNICODE;
- ioctl(fd, KDSKBMODE, &arg);
+ ioctl(fd, KDSKBMODE, K_UNICODE);
if (tcgetattr(fd, &termios) < 0) {
r = -errno;
ssize_t l;
struct inotify_event *e;
- if ((l = read(notify, &inotify_buffer, sizeof(inotify_buffer))) < 0) {
+ if ((l = read(notify, inotify_buffer, sizeof(inotify_buffer))) < 0) {
if (errno == EINTR)
continue;
while (nbytes > 0) {
ssize_t k;
- if ((k = write(fd, p, nbytes)) <= 0) {
+ k = write(fd, p, nbytes);
+ if (k <= 0) {
if (k < 0 && errno == EINTR)
continue;
{ "M", 1024ULL*1024ULL },
{ "G", 1024ULL*1024ULL*1024ULL },
{ "T", 1024ULL*1024ULL*1024ULL*1024ULL },
+ { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
+ { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
{ "", 1 },
};
return -errno;
if (!fgets(line, sizeof(line), f)) {
- k = -errno;
+ k = feof(f) ? -EIO : -errno;
fclose(f);
return k;
}
}
}
-void status_vprintf(const char *format, va_list ap) {
- char *s = NULL;
- int fd = -1;
+void status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
+ char *s = NULL, *spaces = NULL, *e;
+ int fd = -1, c;
+ size_t emax, sl, left;
+ struct iovec iovec[5];
+ int n = 0;
assert(format);
if (vasprintf(&s, format, ap) < 0)
goto finish;
- if ((fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0)
+ fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
+ if (fd < 0)
goto finish;
- write(fd, s, strlen(s));
+ if (ellipse) {
+ c = fd_columns(fd);
+ if (c <= 0)
+ c = 80;
+
+ if (status) {
+ sl = 2 + 6 + 1; /* " [" status "]" */
+ emax = (size_t) c > sl ? c - sl - 1 : 0;
+ } else
+ emax = c - 1;
+
+ e = ellipsize(s, emax, 75);
+ if (e) {
+ free(s);
+ s = e;
+ }
+ }
+
+ zero(iovec);
+ IOVEC_SET_STRING(iovec[n++], s);
+
+ if (ellipse) {
+ sl = strlen(s);
+ left = emax > sl ? emax - sl : 0;
+ if (left > 0) {
+ spaces = malloc(left);
+ if (spaces) {
+ memset(spaces, ' ', left);
+ iovec[n].iov_base = spaces;
+ iovec[n].iov_len = left;
+ n++;
+ }
+ }
+ }
+
+ if (status) {
+ IOVEC_SET_STRING(iovec[n++], " [");
+ IOVEC_SET_STRING(iovec[n++], status);
+ IOVEC_SET_STRING(iovec[n++], "]\n");
+ } else
+ IOVEC_SET_STRING(iovec[n++], "\n");
+
+ writev(fd, iovec, n);
finish:
free(s);
+ free(spaces);
if (fd >= 0)
close_nointr_nofail(fd);
}
-void status_printf(const char *format, ...) {
+void status_printf(const char *status, bool ellipse, const char *format, ...) {
va_list ap;
assert(format);
va_start(ap, format);
- status_vprintf(format, ap);
+ status_vprintf(status, ellipse, format, ap);
va_end(ap);
}
if (!ansi_color && !const_color)
const_color = "1";
- status_printf("\nWelcome to \x1B[%sm%s\x1B[0m!\n\n",
+ status_printf(NULL,
+ false,
+ "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
const_color ? const_color : ansi_color,
const_pretty ? const_pretty : pretty_name);
return r;
}
-int columns(void) {
+int fd_columns(int fd) {
+ struct winsize ws;
+ zero(ws);
+
+ if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
+ return -errno;
+
+ if (ws.ws_col <= 0)
+ return -EIO;
+
+ return ws.ws_col;
+}
+
+unsigned columns(void) {
static __thread int parsed_columns = 0;
const char *e;
if (_likely_(parsed_columns > 0))
return parsed_columns;
- if ((e = getenv("COLUMNS")))
+ e = getenv("COLUMNS");
+ if (e)
parsed_columns = atoi(e);
- if (parsed_columns <= 0) {
- struct winsize ws;
- zero(ws);
-
- if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0)
- parsed_columns = ws.ws_col;
- }
+ if (parsed_columns <= 0)
+ parsed_columns = fd_columns(STDOUT_FILENO);
if (parsed_columns <= 0)
parsed_columns = 80;
a.st_ino != b.st_ino;
}
-char *ellipsize(const char *s, unsigned length, unsigned percent) {
- size_t l, x;
+char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
+ size_t x;
char *r;
assert(s);
assert(percent <= 100);
- assert(length >= 3);
-
- l = strlen(s);
+ assert(new_length >= 3);
- if (l <= 3 || l <= length)
- return strdup(s);
+ if (old_length <= 3 || old_length <= new_length)
+ return strndup(s, old_length);
- if (!(r = new0(char, length+1)))
+ r = new0(char, new_length+1);
+ if (!r)
return r;
- x = (length * percent) / 100;
+ x = (new_length * percent) / 100;
- if (x > length - 3)
- x = length - 3;
+ if (x > new_length - 3)
+ x = new_length - 3;
memcpy(r, s, x);
r[x] = '.';
r[x+1] = '.';
r[x+2] = '.';
memcpy(r + x + 3,
- s + l - (length - x - 3),
- length - x - 3);
+ s + old_length - (new_length - x - 3),
+ new_length - x - 3);
return r;
}
+char *ellipsize(const char *s, size_t length, unsigned percent) {
+ return ellipsize_mem(s, strlen(s), length, percent);
+}
+
int touch(const char *path) {
int fd;
return i;
}
-const char *default_term_for_tty(const char *tty) {
+bool tty_is_vc_resolve(const char *tty) {
char *active = NULL;
- const char *term;
+ bool b;
assert(tty);
if (startswith(tty, "/dev/"))
tty += 5;
- /* Resolve where /dev/console is pointing when determining
- * TERM */
+ /* Resolve where /dev/console is pointing to */
if (streq(tty, "console"))
if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
/* If multiple log outputs are configured the
* last one is what /dev/console points to */
- if ((tty = strrchr(active, ' ')))
+ tty = strrchr(active, ' ');
+ if (tty)
tty++;
else
tty = active;
}
- term = tty_is_vc(tty) ? "TERM=linux" : "TERM=vt100";
+ b = tty_is_vc(tty);
free(active);
- return term;
+ return b;
+}
+
+const char *default_term_for_tty(const char *tty) {
+ assert(tty);
+
+ return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt100";
}
bool dirent_is_file(const struct dirent *de) {
return pollfd.revents & POLLHUP;
}
+int fd_wait_for_event(int fd, int event) {
+ struct pollfd pollfd;
+ int r;
+
+ zero(pollfd);
+ pollfd.fd = fd;
+ pollfd.events = event;
+
+ r = poll(&pollfd, 1, -1);
+ if (r < 0)
+ return -errno;
+
+ if (r == 0)
+ return 0;
+
+ return pollfd.revents;
+}
+
int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
FILE *f;
char *t;
default:
return -EINVAL;
}
+}
unsigned long cap_last_cap(void) {
static __thread unsigned long saved;
return p;
}
+
+char *format_bytes(char *buf, size_t l, off_t t) {
+ unsigned i;
+
+ static const struct {
+ const char *suffix;
+ off_t factor;
+ } table[] = {
+ { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
+ { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
+ { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
+ { "G", 1024ULL*1024ULL*1024ULL },
+ { "M", 1024ULL*1024ULL },
+ { "K", 1024ULL },
+ };
+
+ for (i = 0; i < ELEMENTSOF(table); i++) {
+
+ if (t >= table[i].factor) {
+ snprintf(buf, l,
+ "%llu.%llu%s",
+ (unsigned long long) (t / table[i].factor),
+ (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
+ table[i].suffix);
+
+ goto finish;
+ }
+ }
+
+ snprintf(buf, l, "%lluB", (unsigned long long) t);
+
+finish:
+ buf[l-1] = 0;
+ return buf;
+
+}
+
+void* memdup(const void *p, size_t l) {
+ void *r;
+
+ assert(p);
+
+ r = malloc(l);
+ if (!r)
+ return NULL;
+
+ memcpy(r, p, l);
+ return r;
+}