chiark / gitweb /
Prep v228: Add remaining updates from upstream (2/3)
[elogind.git] / src / basic / terminal-util.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2010 Lennart Poettering
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <assert.h>
21 #include <fcntl.h>
22 #include <linux/kd.h>
23 #include <linux/tiocl.h>
24 #include <linux/vt.h>
25 #include <poll.h>
26 #include <signal.h>
27 #include <sys/ioctl.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <termios.h>
31 #include <time.h>
32 #include <unistd.h>
33
34 #include "alloc-util.h"
35 #include "fd-util.h"
36 #include "fileio.h"
37 #include "fs-util.h"
38 #include "io-util.h"
39 #include "parse-util.h"
40 #include "path-util.h"
41 #include "process-util.h"
42 #include "socket-util.h"
43 #include "stat-util.h"
44 #include "string-util.h"
45 #include "terminal-util.h"
46 #include "time-util.h"
47 #include "util.h"
48
49 static volatile unsigned cached_columns = 0;
50 static volatile unsigned cached_lines = 0;
51
52 int chvt(int vt) {
53         _cleanup_close_ int fd;
54
55         fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
56         if (fd < 0)
57                 return -errno;
58
59         if (vt <= 0) {
60                 int tiocl[2] = {
61                         TIOCL_GETKMSGREDIRECT,
62                         0
63                 };
64
65                 if (ioctl(fd, TIOCLINUX, tiocl) < 0)
66                         return -errno;
67
68                 vt = tiocl[0] <= 0 ? 1 : tiocl[0];
69         }
70
71         if (ioctl(fd, VT_ACTIVATE, vt) < 0)
72                 return -errno;
73
74         return 0;
75 }
76
77 int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
78         struct termios old_termios, new_termios;
79         char c, line[LINE_MAX];
80
81         assert(f);
82         assert(ret);
83
84         if (tcgetattr(fileno(f), &old_termios) >= 0) {
85                 new_termios = old_termios;
86
87                 new_termios.c_lflag &= ~ICANON;
88                 new_termios.c_cc[VMIN] = 1;
89                 new_termios.c_cc[VTIME] = 0;
90
91                 if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
92                         size_t k;
93
94                         if (t != USEC_INFINITY) {
95                                 if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
96                                         tcsetattr(fileno(f), TCSADRAIN, &old_termios);
97                                         return -ETIMEDOUT;
98                                 }
99                         }
100
101                         k = fread(&c, 1, 1, f);
102
103                         tcsetattr(fileno(f), TCSADRAIN, &old_termios);
104
105                         if (k <= 0)
106                                 return -EIO;
107
108                         if (need_nl)
109                                 *need_nl = c != '\n';
110
111                         *ret = c;
112                         return 0;
113                 }
114         }
115
116         if (t != USEC_INFINITY) {
117                 if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
118                         return -ETIMEDOUT;
119         }
120
121         errno = 0;
122         if (!fgets(line, sizeof(line), f))
123                 return errno ? -errno : -EIO;
124
125         truncate_nl(line);
126
127         if (strlen(line) != 1)
128                 return -EBADMSG;
129
130         if (need_nl)
131                 *need_nl = false;
132
133         *ret = line[0];
134         return 0;
135 }
136
137 /// UNNEEDED by elogind
138 #if 0
139 int ask_char(char *ret, const char *replies, const char *text, ...) {
140         int r;
141
142         assert(ret);
143         assert(replies);
144         assert(text);
145
146         for (;;) {
147                 va_list ap;
148                 char c;
149                 bool need_nl = true;
150
151                 if (on_tty())
152                         fputs(ANSI_HIGHLIGHT, stdout);
153
154                 va_start(ap, text);
155                 vprintf(text, ap);
156                 va_end(ap);
157
158                 if (on_tty())
159                         fputs(ANSI_NORMAL, stdout);
160
161                 fflush(stdout);
162
163                 r = read_one_char(stdin, &c, USEC_INFINITY, &need_nl);
164                 if (r < 0) {
165
166                         if (r == -EBADMSG) {
167                                 puts("Bad input, please try again.");
168                                 continue;
169                         }
170
171                         putchar('\n');
172                         return r;
173                 }
174
175                 if (need_nl)
176                         putchar('\n');
177
178                 if (strchr(replies, c)) {
179                         *ret = c;
180                         return 0;
181                 }
182
183                 puts("Read unexpected character, please try again.");
184         }
185 }
186
187 int ask_string(char **ret, const char *text, ...) {
188         assert(ret);
189         assert(text);
190
191         for (;;) {
192                 char line[LINE_MAX];
193                 va_list ap;
194
195                 if (on_tty())
196                         fputs(ANSI_HIGHLIGHT, stdout);
197
198                 va_start(ap, text);
199                 vprintf(text, ap);
200                 va_end(ap);
201
202                 if (on_tty())
203                         fputs(ANSI_NORMAL, stdout);
204
205                 fflush(stdout);
206
207                 errno = 0;
208                 if (!fgets(line, sizeof(line), stdin))
209                         return errno ? -errno : -EIO;
210
211                 if (!endswith(line, "\n"))
212                         putchar('\n');
213                 else {
214                         char *s;
215
216                         if (isempty(line))
217                                 continue;
218
219                         truncate_nl(line);
220                         s = strdup(line);
221                         if (!s)
222                                 return -ENOMEM;
223
224                         *ret = s;
225                         return 0;
226                 }
227         }
228 }
229 #endif // 0
230
231 int reset_terminal_fd(int fd, bool switch_to_text) {
232         struct termios termios;
233         int r = 0;
234
235         /* Set terminal to some sane defaults */
236
237         assert(fd >= 0);
238
239         /* We leave locked terminal attributes untouched, so that
240          * Plymouth may set whatever it wants to set, and we don't
241          * interfere with that. */
242
243         /* Disable exclusive mode, just in case */
244         (void) ioctl(fd, TIOCNXCL);
245
246         /* Switch to text mode */
247         if (switch_to_text)
248                 (void) ioctl(fd, KDSETMODE, KD_TEXT);
249
250         /* Enable console unicode mode */
251         (void) ioctl(fd, KDSKBMODE, K_UNICODE);
252
253         if (tcgetattr(fd, &termios) < 0) {
254                 r = -errno;
255                 goto finish;
256         }
257
258         /* We only reset the stuff that matters to the software. How
259          * hardware is set up we don't touch assuming that somebody
260          * else will do that for us */
261
262         termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
263         termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
264         termios.c_oflag |= ONLCR;
265         termios.c_cflag |= CREAD;
266         termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
267
268         termios.c_cc[VINTR]    =   03;  /* ^C */
269         termios.c_cc[VQUIT]    =  034;  /* ^\ */
270         termios.c_cc[VERASE]   = 0177;
271         termios.c_cc[VKILL]    =  025;  /* ^X */
272         termios.c_cc[VEOF]     =   04;  /* ^D */
273         termios.c_cc[VSTART]   =  021;  /* ^Q */
274         termios.c_cc[VSTOP]    =  023;  /* ^S */
275         termios.c_cc[VSUSP]    =  032;  /* ^Z */
276         termios.c_cc[VLNEXT]   =  026;  /* ^V */
277         termios.c_cc[VWERASE]  =  027;  /* ^W */
278         termios.c_cc[VREPRINT] =  022;  /* ^R */
279         termios.c_cc[VEOL]     =    0;
280         termios.c_cc[VEOL2]    =    0;
281
282         termios.c_cc[VTIME]  = 0;
283         termios.c_cc[VMIN]   = 1;
284
285         if (tcsetattr(fd, TCSANOW, &termios) < 0)
286                 r = -errno;
287
288 finish:
289         /* Just in case, flush all crap out */
290         (void) tcflush(fd, TCIOFLUSH);
291
292         return r;
293 }
294
295 int reset_terminal(const char *name) {
296         _cleanup_close_ int fd = -1;
297
298         /* We open the terminal with O_NONBLOCK here, to ensure we
299          * don't block on carrier if this is a terminal with carrier
300          * configured. */
301
302         fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
303         if (fd < 0)
304                 return fd;
305
306         return reset_terminal_fd(fd, true);
307 }
308
309 int open_terminal(const char *name, int mode) {
310         int fd, r;
311         unsigned c = 0;
312
313         /*
314          * If a TTY is in the process of being closed opening it might
315          * cause EIO. This is horribly awful, but unlikely to be
316          * changed in the kernel. Hence we work around this problem by
317          * retrying a couple of times.
318          *
319          * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
320          */
321
322         if (mode & O_CREAT)
323                 return -EINVAL;
324
325         for (;;) {
326                 fd = open(name, mode, 0);
327                 if (fd >= 0)
328                         break;
329
330                 if (errno != EIO)
331                         return -errno;
332
333                 /* Max 1s in total */
334                 if (c >= 20)
335                         return -errno;
336
337                 usleep(50 * USEC_PER_MSEC);
338                 c++;
339         }
340
341         r = isatty(fd);
342         if (r < 0) {
343                 safe_close(fd);
344                 return -errno;
345         }
346
347         if (!r) {
348                 safe_close(fd);
349                 return -ENOTTY;
350         }
351
352         return fd;
353 }
354
355 int acquire_terminal(
356                 const char *name,
357                 bool fail,
358                 bool force,
359                 bool ignore_tiocstty_eperm,
360                 usec_t timeout) {
361
362         int fd = -1, notify = -1, r = 0, wd = -1;
363         usec_t ts = 0;
364
365         assert(name);
366
367         /* We use inotify to be notified when the tty is closed. We
368          * create the watch before checking if we can actually acquire
369          * it, so that we don't lose any event.
370          *
371          * Note: strictly speaking this actually watches for the
372          * device being closed, it does *not* really watch whether a
373          * tty loses its controlling process. However, unless some
374          * rogue process uses TIOCNOTTY on /dev/tty *after* closing
375          * its tty otherwise this will not become a problem. As long
376          * as the administrator makes sure not configure any service
377          * on the same tty as an untrusted user this should not be a
378          * problem. (Which he probably should not do anyway.) */
379
380         if (timeout != USEC_INFINITY)
381                 ts = now(CLOCK_MONOTONIC);
382
383         if (!fail && !force) {
384                 notify = inotify_init1(IN_CLOEXEC | (timeout != USEC_INFINITY ? IN_NONBLOCK : 0));
385                 if (notify < 0) {
386                         r = -errno;
387                         goto fail;
388                 }
389
390                 wd = inotify_add_watch(notify, name, IN_CLOSE);
391                 if (wd < 0) {
392                         r = -errno;
393                         goto fail;
394                 }
395         }
396
397         for (;;) {
398                 struct sigaction sa_old, sa_new = {
399                         .sa_handler = SIG_IGN,
400                         .sa_flags = SA_RESTART,
401                 };
402
403                 if (notify >= 0) {
404                         r = flush_fd(notify);
405                         if (r < 0)
406                                 goto fail;
407                 }
408
409                 /* We pass here O_NOCTTY only so that we can check the return
410                  * value TIOCSCTTY and have a reliable way to figure out if we
411                  * successfully became the controlling process of the tty */
412                 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
413                 if (fd < 0)
414                         return fd;
415
416                 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
417                  * if we already own the tty. */
418                 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
419
420                 /* First, try to get the tty */
421                 if (ioctl(fd, TIOCSCTTY, force) < 0)
422                         r = -errno;
423
424                 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
425
426                 /* Sometimes, it makes sense to ignore TIOCSCTTY
427                  * returning EPERM, i.e. when very likely we already
428                  * are have this controlling terminal. */
429                 if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
430                         r = 0;
431
432                 if (r < 0 && (force || fail || r != -EPERM))
433                         goto fail;
434
435                 if (r >= 0)
436                         break;
437
438                 assert(!fail);
439                 assert(!force);
440                 assert(notify >= 0);
441
442                 for (;;) {
443                         union inotify_event_buffer buffer;
444                         struct inotify_event *e;
445                         ssize_t l;
446
447                         if (timeout != USEC_INFINITY) {
448                                 usec_t n;
449
450                                 n = now(CLOCK_MONOTONIC);
451                                 if (ts + timeout < n) {
452                                         r = -ETIMEDOUT;
453                                         goto fail;
454                                 }
455
456                                 r = fd_wait_for_event(fd, POLLIN, ts + timeout - n);
457                                 if (r < 0)
458                                         goto fail;
459
460                                 if (r == 0) {
461                                         r = -ETIMEDOUT;
462                                         goto fail;
463                                 }
464                         }
465
466                         l = read(notify, &buffer, sizeof(buffer));
467                         if (l < 0) {
468                                 if (errno == EINTR || errno == EAGAIN)
469                                         continue;
470
471                                 r = -errno;
472                                 goto fail;
473                         }
474
475                         FOREACH_INOTIFY_EVENT(e, buffer, l) {
476                                 if (e->wd != wd || !(e->mask & IN_CLOSE)) {
477                                         r = -EIO;
478                                         goto fail;
479                                 }
480                         }
481
482                         break;
483                 }
484
485                 /* We close the tty fd here since if the old session
486                  * ended our handle will be dead. It's important that
487                  * we do this after sleeping, so that we don't enter
488                  * an endless loop. */
489                 fd = safe_close(fd);
490         }
491
492         safe_close(notify);
493
494         return fd;
495
496 fail:
497         safe_close(fd);
498         safe_close(notify);
499
500         return r;
501 }
502
503 /// UNNEEDED by elogind
504 #if 0
505 int release_terminal(void) {
506         static const struct sigaction sa_new = {
507                 .sa_handler = SIG_IGN,
508                 .sa_flags = SA_RESTART,
509         };
510
511         _cleanup_close_ int fd = -1;
512         struct sigaction sa_old;
513         int r = 0;
514
515         fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
516         if (fd < 0)
517                 return -errno;
518
519         /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
520          * by our own TIOCNOTTY */
521         assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
522
523         if (ioctl(fd, TIOCNOTTY) < 0)
524                 r = -errno;
525
526         assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
527
528         return r;
529 }
530 #endif // 0
531
532 int terminal_vhangup_fd(int fd) {
533         assert(fd >= 0);
534
535         if (ioctl(fd, TIOCVHANGUP) < 0)
536                 return -errno;
537
538         return 0;
539 }
540
541 int terminal_vhangup(const char *name) {
542         _cleanup_close_ int fd;
543
544         fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
545         if (fd < 0)
546                 return fd;
547
548         return terminal_vhangup_fd(fd);
549 }
550
551 int vt_disallocate(const char *name) {
552         _cleanup_close_ int fd = -1;
553         unsigned u;
554         int r;
555
556         /* Deallocate the VT if possible. If not possible
557          * (i.e. because it is the active one), at least clear it
558          * entirely (including the scrollback buffer) */
559
560         if (!startswith(name, "/dev/"))
561                 return -EINVAL;
562
563         if (!tty_is_vc(name)) {
564                 /* So this is not a VT. I guess we cannot deallocate
565                  * it then. But let's at least clear the screen */
566
567                 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
568                 if (fd < 0)
569                         return fd;
570
571                 loop_write(fd,
572                            "\033[r"    /* clear scrolling region */
573                            "\033[H"    /* move home */
574                            "\033[2J",  /* clear screen */
575                            10, false);
576                 return 0;
577         }
578
579         if (!startswith(name, "/dev/tty"))
580                 return -EINVAL;
581
582         r = safe_atou(name+8, &u);
583         if (r < 0)
584                 return r;
585
586         if (u <= 0)
587                 return -EINVAL;
588
589         /* Try to deallocate */
590         fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
591         if (fd < 0)
592                 return fd;
593
594         r = ioctl(fd, VT_DISALLOCATE, u);
595         fd = safe_close(fd);
596
597         if (r >= 0)
598                 return 0;
599
600         if (errno != EBUSY)
601                 return -errno;
602
603         /* Couldn't deallocate, so let's clear it fully with
604          * scrollback */
605         fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
606         if (fd < 0)
607                 return fd;
608
609         loop_write(fd,
610                    "\033[r"   /* clear scrolling region */
611                    "\033[H"   /* move home */
612                    "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
613                    10, false);
614         return 0;
615 }
616
617 /// UNNEEDED by elogind
618 #if 0
619 int make_console_stdio(void) {
620         int fd, r;
621
622         /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
623
624         fd = acquire_terminal("/dev/console", false, true, true, USEC_INFINITY);
625         if (fd < 0)
626                 return log_error_errno(fd, "Failed to acquire terminal: %m");
627
628         r = reset_terminal_fd(fd, true);
629         if (r < 0)
630                 log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
631
632         r = make_stdio(fd);
633         if (r < 0)
634                 return log_error_errno(r, "Failed to duplicate terminal fd: %m");
635
636         return 0;
637 }
638 #endif // 0
639
640 bool tty_is_vc(const char *tty) {
641         assert(tty);
642
643         return vtnr_from_tty(tty) >= 0;
644 }
645
646 bool tty_is_console(const char *tty) {
647         assert(tty);
648
649         if (startswith(tty, "/dev/"))
650                 tty += 5;
651
652         return streq(tty, "console");
653 }
654
655 int vtnr_from_tty(const char *tty) {
656         int i, r;
657
658         assert(tty);
659
660         if (startswith(tty, "/dev/"))
661                 tty += 5;
662
663         if (!startswith(tty, "tty") )
664                 return -EINVAL;
665
666         if (tty[3] < '0' || tty[3] > '9')
667                 return -EINVAL;
668
669         r = safe_atoi(tty+3, &i);
670         if (r < 0)
671                 return r;
672
673         if (i < 0 || i > 63)
674                 return -EINVAL;
675
676         return i;
677 }
678
679 char *resolve_dev_console(char **active) {
680         char *tty;
681
682         /* Resolve where /dev/console is pointing to, if /sys is actually ours
683          * (i.e. not read-only-mounted which is a sign for container setups) */
684
685         if (path_is_read_only_fs("/sys") > 0)
686                 return NULL;
687
688         if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
689                 return NULL;
690
691         /* If multiple log outputs are configured the last one is what
692          * /dev/console points to */
693         tty = strrchr(*active, ' ');
694         if (tty)
695                 tty++;
696         else
697                 tty = *active;
698
699         if (streq(tty, "tty0")) {
700                 char *tmp;
701
702                 /* Get the active VC (e.g. tty1) */
703                 if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
704                         free(*active);
705                         tty = *active = tmp;
706                 }
707         }
708
709         return tty;
710 }
711
712 bool tty_is_vc_resolve(const char *tty) {
713         _cleanup_free_ char *active = NULL;
714
715         assert(tty);
716
717         if (startswith(tty, "/dev/"))
718                 tty += 5;
719
720         if (streq(tty, "console")) {
721                 tty = resolve_dev_console(&active);
722                 if (!tty)
723                         return false;
724         }
725
726         return tty_is_vc(tty);
727 }
728
729 /// UNNEEDED by elogind
730 #if 0
731 const char *default_term_for_tty(const char *tty) {
732         assert(tty);
733
734         return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt220";
735 }
736 #endif // 0
737
738 int fd_columns(int fd) {
739         struct winsize ws = {};
740
741         if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
742                 return -errno;
743
744         if (ws.ws_col <= 0)
745                 return -EIO;
746
747         return ws.ws_col;
748 }
749
750 unsigned columns(void) {
751         const char *e;
752         int c;
753
754         if (_likely_(cached_columns > 0))
755                 return cached_columns;
756
757         c = 0;
758         e = getenv("COLUMNS");
759         if (e)
760                 (void) safe_atoi(e, &c);
761
762         if (c <= 0)
763                 c = fd_columns(STDOUT_FILENO);
764
765         if (c <= 0)
766                 c = 80;
767
768         cached_columns = c;
769         return cached_columns;
770 }
771
772 int fd_lines(int fd) {
773         struct winsize ws = {};
774
775         if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
776                 return -errno;
777
778         if (ws.ws_row <= 0)
779                 return -EIO;
780
781         return ws.ws_row;
782 }
783
784 unsigned lines(void) {
785         const char *e;
786         int l;
787
788         if (_likely_(cached_lines > 0))
789                 return cached_lines;
790
791         l = 0;
792         e = getenv("LINES");
793         if (e)
794                 (void) safe_atoi(e, &l);
795
796         if (l <= 0)
797                 l = fd_lines(STDOUT_FILENO);
798
799         if (l <= 0)
800                 l = 24;
801
802         cached_lines = l;
803         return cached_lines;
804 }
805
806 /* intended to be used as a SIGWINCH sighandler */
807 /// UNNEEDED by elogind
808 #if 0
809 void columns_lines_cache_reset(int signum) {
810         cached_columns = 0;
811         cached_lines = 0;
812 }
813 #endif // 0
814
815 bool on_tty(void) {
816         static int cached_on_tty = -1;
817
818         if (_unlikely_(cached_on_tty < 0))
819                 cached_on_tty = isatty(STDOUT_FILENO) > 0;
820
821         return cached_on_tty;
822 }
823
824 int make_stdio(int fd) {
825         int r, s, t;
826
827         assert(fd >= 0);
828
829         r = dup2(fd, STDIN_FILENO);
830         s = dup2(fd, STDOUT_FILENO);
831         t = dup2(fd, STDERR_FILENO);
832
833         if (fd >= 3)
834                 safe_close(fd);
835
836         if (r < 0 || s < 0 || t < 0)
837                 return -errno;
838
839         /* Explicitly unset O_CLOEXEC, since if fd was < 3, then
840          * dup2() was a NOP and the bit hence possibly set. */
841         fd_cloexec(STDIN_FILENO, false);
842         fd_cloexec(STDOUT_FILENO, false);
843         fd_cloexec(STDERR_FILENO, false);
844
845         return 0;
846 }
847
848 int make_null_stdio(void) {
849         int null_fd;
850
851         null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
852         if (null_fd < 0)
853                 return -errno;
854
855         return make_stdio(null_fd);
856 }
857
858 /// UNNEEDED by elogind
859 #if 0
860 int getttyname_malloc(int fd, char **ret) {
861         size_t l = 100;
862         int r;
863
864         assert(fd >= 0);
865         assert(ret);
866
867         for (;;) {
868                 char path[l];
869
870                 r = ttyname_r(fd, path, sizeof(path));
871                 if (r == 0) {
872                         const char *p;
873                         char *c;
874
875                         p = startswith(path, "/dev/");
876                         c = strdup(p ?: path);
877                         if (!c)
878                                 return -ENOMEM;
879
880                         *ret = c;
881                         return 0;
882                 }
883
884                 if (r != ERANGE)
885                         return -r;
886
887                 l *= 2;
888         }
889
890         return 0;
891 }
892
893 int getttyname_harder(int fd, char **r) {
894         int k;
895         char *s = NULL;
896
897         k = getttyname_malloc(fd, &s);
898         if (k < 0)
899                 return k;
900
901         if (streq(s, "tty")) {
902                 free(s);
903                 return get_ctty(0, NULL, r);
904         }
905
906         *r = s;
907         return 0;
908 }
909 #endif // 0
910
911 int get_ctty_devnr(pid_t pid, dev_t *d) {
912         int r;
913         _cleanup_free_ char *line = NULL;
914         const char *p;
915         unsigned long ttynr;
916
917         assert(pid >= 0);
918
919         p = procfs_file_alloca(pid, "stat");
920         r = read_one_line_file(p, &line);
921         if (r < 0)
922                 return r;
923
924         p = strrchr(line, ')');
925         if (!p)
926                 return -EIO;
927
928         p++;
929
930         if (sscanf(p, " "
931                    "%*c "  /* state */
932                    "%*d "  /* ppid */
933                    "%*d "  /* pgrp */
934                    "%*d "  /* session */
935                    "%lu ", /* ttynr */
936                    &ttynr) != 1)
937                 return -EIO;
938
939         if (major(ttynr) == 0 && minor(ttynr) == 0)
940                 return -ENXIO;
941
942         if (d)
943                 *d = (dev_t) ttynr;
944
945         return 0;
946 }
947
948 int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
949         char fn[sizeof("/dev/char/")-1 + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL;
950         _cleanup_free_ char *s = NULL;
951         const char *p;
952         dev_t devnr;
953         int k;
954
955         assert(r);
956
957         k = get_ctty_devnr(pid, &devnr);
958         if (k < 0)
959                 return k;
960
961         sprintf(fn, "/dev/char/%u:%u", major(devnr), minor(devnr));
962
963         k = readlink_malloc(fn, &s);
964         if (k < 0) {
965
966                 if (k != -ENOENT)
967                         return k;
968
969                 /* This is an ugly hack */
970                 if (major(devnr) == 136) {
971                         if (asprintf(&b, "pts/%u", minor(devnr)) < 0)
972                                 return -ENOMEM;
973                 } else {
974                         /* Probably something like the ptys which have no
975                          * symlink in /dev/char. Let's return something
976                          * vaguely useful. */
977
978                         b = strdup(fn + 5);
979                         if (!b)
980                                 return -ENOMEM;
981                 }
982         } else {
983                 if (startswith(s, "/dev/"))
984                         p = s + 5;
985                 else if (startswith(s, "../"))
986                         p = s + 3;
987                 else
988                         p = s;
989
990                 b = strdup(p);
991                 if (!b)
992                         return -ENOMEM;
993         }
994
995         *r = b;
996         if (_devnr)
997                 *_devnr = devnr;
998
999         return 0;
1000 }
1001
1002 /// UNNEEDED by elogind
1003 #if 0
1004 int ptsname_malloc(int fd, char **ret) {
1005         size_t l = 100;
1006
1007         assert(fd >= 0);
1008         assert(ret);
1009
1010         for (;;) {
1011                 char *c;
1012
1013                 c = new(char, l);
1014                 if (!c)
1015                         return -ENOMEM;
1016
1017                 if (ptsname_r(fd, c, l) == 0) {
1018                         *ret = c;
1019                         return 0;
1020                 }
1021                 if (errno != ERANGE) {
1022                         free(c);
1023                         return -errno;
1024                 }
1025
1026                 free(c);
1027                 l *= 2;
1028         }
1029 }
1030
1031 int ptsname_namespace(int pty, char **ret) {
1032         int no = -1, r;
1033
1034         /* Like ptsname(), but doesn't assume that the path is
1035          * accessible in the local namespace. */
1036
1037         r = ioctl(pty, TIOCGPTN, &no);
1038         if (r < 0)
1039                 return -errno;
1040
1041         if (no < 0)
1042                 return -EIO;
1043
1044         if (asprintf(ret, "/dev/pts/%i", no) < 0)
1045                 return -ENOMEM;
1046
1047         return 0;
1048 }
1049
1050 int openpt_in_namespace(pid_t pid, int flags) {
1051         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
1052         _cleanup_close_pair_ int pair[2] = { -1, -1 };
1053         siginfo_t si;
1054         pid_t child;
1055         int r;
1056
1057         assert(pid > 0);
1058
1059         r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
1060         if (r < 0)
1061                 return r;
1062
1063         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1064                 return -errno;
1065
1066         child = fork();
1067         if (child < 0)
1068                 return -errno;
1069
1070         if (child == 0) {
1071                 int master;
1072
1073                 pair[0] = safe_close(pair[0]);
1074
1075                 r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
1076                 if (r < 0)
1077                         _exit(EXIT_FAILURE);
1078
1079                 master = posix_openpt(flags|O_NOCTTY|O_CLOEXEC);
1080                 if (master < 0)
1081                         _exit(EXIT_FAILURE);
1082
1083                 if (unlockpt(master) < 0)
1084                         _exit(EXIT_FAILURE);
1085
1086                 if (send_one_fd(pair[1], master, 0) < 0)
1087                         _exit(EXIT_FAILURE);
1088
1089                 _exit(EXIT_SUCCESS);
1090         }
1091
1092         pair[1] = safe_close(pair[1]);
1093
1094         r = wait_for_terminate(child, &si);
1095         if (r < 0)
1096                 return r;
1097         if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1098                 return -EIO;
1099
1100         return receive_one_fd(pair[0], 0);
1101 }
1102
1103 int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
1104         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
1105         _cleanup_close_pair_ int pair[2] = { -1, -1 };
1106         siginfo_t si;
1107         pid_t child;
1108         int r;
1109
1110         r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
1111         if (r < 0)
1112                 return r;
1113
1114         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1115                 return -errno;
1116
1117         child = fork();
1118         if (child < 0)
1119                 return -errno;
1120
1121         if (child == 0) {
1122                 int master;
1123
1124                 pair[0] = safe_close(pair[0]);
1125
1126                 r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
1127                 if (r < 0)
1128                         _exit(EXIT_FAILURE);
1129
1130                 master = open_terminal(name, mode|O_NOCTTY|O_CLOEXEC);
1131                 if (master < 0)
1132                         _exit(EXIT_FAILURE);
1133
1134                 if (send_one_fd(pair[1], master, 0) < 0)
1135                         _exit(EXIT_FAILURE);
1136
1137                 _exit(EXIT_SUCCESS);
1138         }
1139
1140         pair[1] = safe_close(pair[1]);
1141
1142         r = wait_for_terminate(child, &si);
1143         if (r < 0)
1144                 return r;
1145         if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1146                 return -EIO;
1147
1148         return receive_one_fd(pair[0], 0);
1149 }
1150 #endif // 0