996
int get_process_name(pid_t pid, char **name) {
1004
int get_process_comm(pid_t pid, char **name) {
1003
if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
1006
r = read_one_line_file(p, name);
1010
r = read_one_line_file("/proc/self/comm", name);
1013
if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
1016
r = read_one_line_file(p, name);
1015
int get_process_cmdline(pid_t pid, size_t max_length, char **line) {
1023
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
1018
1026
bool space = false;
1023
1030
assert(max_length > 0);
1026
if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
1034
f = fopen("/proc/self/cmdline", "re");
1037
if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
1035
if (!(r = new(char, max_length))) {
1047
r = new(char, max_length);
1037
1050
return -ENOMEM;
1110
int is_kernel_thread(pid_t pid) {
1120
if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
1129
count = fread(&c, 1, 1, f);
1133
/* Kernel threads have an empty cmdline */
1136
return eof ? 1 : -errno;
1141
int get_process_exe(pid_t pid, char **name) {
1147
r = readlink_malloc("/proc/self/exe", name);
1150
if (asprintf(&p, "/proc/%lu/exe", (unsigned long) pid) < 0)
1153
r = readlink_malloc(p, name);
1160
int get_process_uid(pid_t pid, uid_t *uid) {
1170
if (asprintf(&p, "/proc/%lu/status", (unsigned long) pid) < 0)
1180
char line[LINE_MAX], *l;
1182
if (!fgets(line, sizeof(line), f)) {
1192
if (startswith(l, "Uid:")) {
1194
l += strspn(l, WHITESPACE);
1196
l[strcspn(l, WHITESPACE)] = 0;
1198
r = parse_uid(l, uid);
1093
1211
char *strnappend(const char *s, const char *suffix, size_t b) {
2210
static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
2213
assert(n_fdset == 0 || fdset);
2215
for (i = 0; i < n_fdset; i++)
2087
2222
int close_all_fds(const int except[], unsigned n_except) {
2089
2224
struct dirent *de;
2092
if (!(d = opendir("/proc/self/fd")))
2227
assert(n_except == 0 || except);
2229
d = opendir("/proc/self/fd");
2234
/* When /proc isn't available (for example in chroots)
2235
* the fallback is brute forcing through the fd
2238
assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
2239
for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
2241
if (fd_in_set(fd, except, n_except))
2244
if (close_nointr(fd) < 0)
2245
if (errno != EBADF && r == 0)
2095
2252
while ((de = readdir(d))) {
2387
2543
bool need_nl = true;
2390
fputs("\x1B[1m", stdout);
2546
fputs(ANSI_HIGHLIGHT_ON, stdout);
2392
2548
va_start(ap, text);
2393
2549
vprintf(text, ap);
2397
fputs("\x1B[0m", stdout);
2553
fputs(ANSI_HIGHLIGHT_OFF, stdout);
2399
2555
fflush(stdout);
2401
if ((r = read_one_char(stdin, &c, &need_nl)) < 0) {
2557
r = read_one_char(stdin, &c, (usec_t) -1, &need_nl);
2403
2560
if (r == -EBADMSG) {
2404
2561
puts("Bad input, please try again.");
2437
2593
/* Disable exclusive mode, just in case */
2438
2594
ioctl(fd, TIOCNXCL);
2596
/* Switch to text mode */
2598
ioctl(fd, KDSETMODE, KD_TEXT);
2440
2600
/* Enable console unicode mode */
2442
ioctl(fd, KDSKBMODE, &arg);
2601
ioctl(fd, KDSKBMODE, K_UNICODE);
2444
2603
if (tcgetattr(fd, &termios) < 0) {
3134
3297
void rename_process(const char name[8]) {
3300
/* This is a like a poor man's setproctitle(). It changes the
3301
* comm field, argv[0], and also the glibc's internally used
3302
* name of the process. For the first one a limit of 16 chars
3303
* applies, to the second one usually one of 10 (i.e. length
3304
* of "/sbin/init"), to the third one one of 7 (i.e. length of
3305
* "systemd"). If you pass a longer string it will be
3137
3308
prctl(PR_SET_NAME, name);
3139
/* This is a like a poor man's setproctitle(). The string
3140
* passed should fit in 7 chars (i.e. the length of
3143
3310
if (program_invocation_name)
3144
3311
strncpy(program_invocation_name, name, strlen(program_invocation_name));
3494
3666
* first change the access mode and only then hand out
3495
3667
* ownership to avoid a window where access is too open. */
3497
if (chmod(path, mode) < 0)
3669
if (mode != (mode_t) -1)
3670
if (chmod(path, mode) < 0)
3673
if (uid != (uid_t) -1 || gid != (gid_t) -1)
3674
if (chown(path, uid, gid) < 0)
3680
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
3683
/* Under the assumption that we are running privileged we
3684
* first change the access mode and only then hand out
3685
* ownership to avoid a window where access is too open. */
3687
if (fchmod(fd, mode) < 0)
3500
if (chown(path, uid, gid) < 0)
3690
if (fchown(fd, uid, gid) < 0)
3543
3736
if (vasprintf(&s, format, ap) < 0)
3546
if ((fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0)
3739
fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
3549
write(fd, s, strlen(s));
3749
sl = 2 + 6 + 1; /* " [" status "]" */
3750
emax = (size_t) c > sl ? c - sl - 1 : 0;
3754
e = ellipsize(s, emax, 75);
3762
IOVEC_SET_STRING(iovec[n++], s);
3766
left = emax > sl ? emax - sl : 0;
3768
spaces = malloc(left);
3770
memset(spaces, ' ', left);
3771
iovec[n].iov_base = spaces;
3772
iovec[n].iov_len = left;
3779
IOVEC_SET_STRING(iovec[n++], " [");
3780
IOVEC_SET_STRING(iovec[n++], status);
3781
IOVEC_SET_STRING(iovec[n++], "]\n");
3783
IOVEC_SET_STRING(iovec[n++], "\n");
3785
writev(fd, iovec, n);
3555
3792
close_nointr_nofail(fd);
3558
void status_printf(const char *format, ...) {
3795
void status_printf(const char *status, bool ellipse, const char *format, ...) {
3561
3798
assert(format);
3563
3800
va_start(ap, format);
3564
status_vprintf(format, ap);
3801
status_vprintf(status, ellipse, format, ap);
3579
3816
log_warning("Failed to read /etc/os-release: %s", strerror(-r));
3582
#if defined(TARGET_FEDORA)
3584
if ((r = read_one_line_file("/etc/system-release", &pretty_name)) < 0) {
3587
log_warning("Failed to read /etc/system-release: %s", strerror(-r));
3591
if (!ansi_color && pretty_name) {
3593
/* This tries to mimic the color magic the old Red Hat sysinit
3596
if (startswith(pretty_name, "Red Hat"))
3597
const_color = "0;31"; /* Red for RHEL */
3598
else if (startswith(pretty_name, "Fedora"))
3599
const_color = "0;34"; /* Blue for Fedora */
3602
#elif defined(TARGET_SUSE)
3605
if ((r = read_one_line_file("/etc/SuSE-release", &pretty_name)) < 0) {
3608
log_warning("Failed to read /etc/SuSE-release: %s", strerror(-r));
3613
const_color = "0;32"; /* Green for openSUSE */
3615
#elif defined(TARGET_GENTOO)
3618
if ((r = read_one_line_file("/etc/gentoo-release", &pretty_name)) < 0) {
3621
log_warning("Failed to read /etc/gentoo-release: %s", strerror(-r));
3626
const_color = "1;34"; /* Light Blue for Gentoo */
3628
#elif defined(TARGET_ALTLINUX)
3631
if ((r = read_one_line_file("/etc/altlinux-release", &pretty_name)) < 0) {
3634
log_warning("Failed to read /etc/altlinux-release: %s", strerror(-r));
3639
const_color = "0;36"; /* Cyan for ALTLinux */
3642
#elif defined(TARGET_DEBIAN)
3647
if ((r = read_one_line_file("/etc/debian_version", &version)) < 0) {
3650
log_warning("Failed to read /etc/debian_version: %s", strerror(-r));
3652
pretty_name = strappend("Debian ", version);
3656
log_warning("Failed to allocate Debian version string.");
3661
const_color = "1;31"; /* Light Red for Debian */
3663
#elif defined(TARGET_UBUNTU)
3665
if ((r = parse_env_file("/etc/lsb-release", NEWLINE,
3666
"DISTRIB_DESCRIPTION", &pretty_name,
3670
log_warning("Failed to read /etc/lsb-release: %s", strerror(-r));
3674
const_color = "0;33"; /* Orange/Brown for Ubuntu */
3676
#elif defined(TARGET_MANDRIVA)
3681
if ((r = read_one_line_file("/etc/mandriva-release", &s) < 0)) {
3683
log_warning("Failed to read /etc/mandriva-release: %s", strerror(-r));
3685
p = strstr(s, " release ");
3689
p[strcspn(p, " ")] = '\0';
3691
/* This corresponds to standard rc.sysinit */
3692
if (asprintf(&pretty_name, "%s\x1B[0;39m %s", s, p) > 0)
3693
const_color = "1;36";
3695
log_warning("Failed to allocate Mandriva version string.");
3697
log_warning("Failed to parse /etc/mandriva-release");
3701
#elif defined(TARGET_MEEGO)
3704
if ((r = read_one_line_file("/etc/meego-release", &pretty_name)) < 0) {
3707
log_warning("Failed to read /etc/meego-release: %s", strerror(-r));
3712
const_color = "1;35"; /* Bright Magenta for MeeGo */
3715
3819
if (!pretty_name && !const_pretty)
3716
3820
const_pretty = "Linux";
3718
3822
if (!ansi_color && !const_color)
3719
3823
const_color = "1";
3721
status_printf("\nWelcome to \x1B[%sm%s\x1B[0m!\n\n",
3827
"\nWelcome to \x1B[%sm%s\x1B[0m!\n",
3722
3828
const_color ? const_color : ansi_color,
3723
3829
const_pretty ? const_pretty : pretty_name);
3969
int fd_columns(int fd) {
3973
if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
3982
unsigned columns(void) {
3864
3983
static __thread int parsed_columns = 0;
3867
3986
if (_likely_(parsed_columns > 0))
3868
3987
return parsed_columns;
3870
if ((e = getenv("COLUMNS")))
3989
e = getenv("COLUMNS");
3871
3991
parsed_columns = atoi(e);
3873
if (parsed_columns <= 0) {
3877
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0)
3878
parsed_columns = ws.ws_col;
3993
if (parsed_columns <= 0)
3994
parsed_columns = fd_columns(STDOUT_FILENO);
3881
3996
if (parsed_columns <= 0)
3882
3997
parsed_columns = 80;
3903
4051
a.st_ino != b.st_ino;
3906
char *ellipsize(const char *s, unsigned length, unsigned percent) {
4054
char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
3911
4059
assert(percent <= 100);
3912
assert(length >= 3);
3916
if (l <= 3 || l <= length)
3919
if (!(r = new0(char, length+1)))
4060
assert(new_length >= 3);
4062
if (old_length <= 3 || old_length <= new_length)
4063
return strndup(s, old_length);
4065
r = new0(char, new_length+1);
3922
x = (length * percent) / 100;
4069
x = (new_length * percent) / 100;
4071
if (x > new_length - 3)
3927
4074
memcpy(r, s, x);
3931
4078
memcpy(r + x + 3,
3932
s + l - (length - x - 3),
4079
s + old_length - (new_length - x - 3),
4080
new_length - x - 3);
4085
char *ellipsize(const char *s, size_t length, unsigned percent) {
4086
return ellipsize_mem(s, strlen(s), length, percent);
3938
4089
int touch(const char *path) {
4246
const char *default_term_for_tty(const char *tty) {
4398
bool tty_is_vc_resolve(const char *tty) {
4247
4399
char *active = NULL;
4252
4404
if (startswith(tty, "/dev/"))
4255
/* Resolve where /dev/console is pointing when determining
4407
/* Resolve where /dev/console is pointing to */
4257
4408
if (streq(tty, "console"))
4258
4409
if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
4259
4410
/* If multiple log outputs are configured the
4260
4411
* last one is what /dev/console points to */
4261
if ((tty = strrchr(active, ' ')))
4412
tty = strrchr(active, ' ');
4267
term = tty_is_vc(tty) ? "TERM=linux" : "TERM=vt100";
4273
bool dirent_is_file(struct dirent *de) {
4425
const char *default_term_for_tty(const char *tty) {
4428
return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt100";
4431
bool dirent_is_file(const struct dirent *de) {
4276
4434
if (ignore_file(de->d_name))
5143
int rtc_open(int flags) {
5147
/* First, we try to make use of the /dev/rtc symlink. If that
5148
* doesn't exist, we open the first RTC which has hctosys=1
5149
* set. If we don't find any we just take the first RTC that
5152
fd = open("/dev/rtc", flags);
5156
d = opendir("/sys/class/rtc");
5162
struct dirent buf, *de;
5165
r = readdir_r(d, &buf, &de);
5172
if (ignore_file(de->d_name))
5175
p = join("/sys/class/rtc/", de->d_name, "/hctosys", NULL);
5181
r = read_one_line_file(p, &v);
5187
r = parse_boolean(v);
5193
p = strappend("/dev/", de->d_name);
5194
fd = open(p, flags);
5207
fd = open("/dev/rtc0", flags);
4880
5214
int hwclock_get_time(struct tm *tm) {
4886
fd = open("/dev/rtc0", O_RDONLY|O_CLOEXEC);
5220
fd = rtc_open(O_RDONLY|O_CLOEXEC);
5068
5402
int audit_session_from_pid(pid_t pid, uint32_t *id) {
5076
5409
if (have_effective_cap(CAP_AUDIT_CONTROL) <= 0)
5077
5410
return -ENOENT;
5079
if (asprintf(&p, "/proc/%lu/sessionid", (unsigned long) pid) < 0)
5082
r = read_one_line_file(p, &s);
5413
r = read_one_line_file("/proc/self/sessionid", &s);
5417
if (asprintf(&p, "/proc/%lu/sessionid", (unsigned long) pid) < 0)
5420
r = read_one_line_file(p, &s);
5440
int audit_loginuid_from_pid(pid_t pid, uid_t *uid) {
5447
/* Only use audit login uid if we are executed with sufficient
5448
* capabilities so that pam_loginuid could do its job. If we
5449
* are lacking the CAP_AUDIT_CONTROL capabality we most likely
5450
* are being run in a container and /proc/self/loginuid is
5451
* useless since it probably contains a uid of the host
5454
if (have_effective_cap(CAP_AUDIT_CONTROL) <= 0)
5458
r = read_one_line_file("/proc/self/loginuid", &s);
5462
if (asprintf(&p, "/proc/%lu/loginuid", (unsigned long) pid) < 0)
5465
r = read_one_line_file(p, &s);
5472
r = parse_uid(s, &u);
5478
if (u == (uid_t) -1)
5100
5485
bool display_is_local(const char *display) {
5101
5486
assert(display);
6122
int prot_from_flags(int flags) {
6124
switch (flags & O_ACCMODE) {
6133
return PROT_READ|PROT_WRITE;
6140
unsigned long cap_last_cap(void) {
6141
static __thread unsigned long saved;
6142
static __thread bool valid = false;
6148
p = (unsigned long) CAP_LAST_CAP;
6150
if (prctl(PR_CAPBSET_READ, p) < 0) {
6152
/* Hmm, look downwards, until we find one that
6154
for (p--; p > 0; p --)
6155
if (prctl(PR_CAPBSET_READ, p) >= 0)
6160
/* Hmm, look upwards, until we find one that doesn't
6163
if (prctl(PR_CAPBSET_READ, p+1) < 0)
6173
char *format_bytes(char *buf, size_t l, off_t t) {
6176
static const struct {
6180
{ "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
6181
{ "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
6182
{ "T", 1024ULL*1024ULL*1024ULL*1024ULL },
6183
{ "G", 1024ULL*1024ULL*1024ULL },
6184
{ "M", 1024ULL*1024ULL },
6188
for (i = 0; i < ELEMENTSOF(table); i++) {
6190
if (t >= table[i].factor) {
6193
(unsigned long long) (t / table[i].factor),
6194
(unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
6201
snprintf(buf, l, "%lluB", (unsigned long long) t);
6209
void* memdup(const void *p, size_t l) {
6222
int fd_inc_sndbuf(int fd, size_t n) {
6224
socklen_t l = sizeof(value);
6226
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
6228
l == sizeof(value) &&
6229
(size_t) value >= n*2)
6233
r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
6240
int fd_inc_rcvbuf(int fd, size_t n) {
6242
socklen_t l = sizeof(value);
6244
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
6246
l == sizeof(value) &&
6247
(size_t) value >= n*2)
6251
r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));