chiark / gitweb /
shared: add PTY helper
[elogind.git] / src / shared / pty.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 /*
23  * PTY
24  * A PTY object represents a single PTY connection between a master and a
25  * child. The child process is fork()ed so the caller controls what program
26  * will be run.
27  *
28  * Programs like /bin/login tend to perform a vhangup() on their TTY
29  * before running the login procedure. This also causes the pty master
30  * to get a EPOLLHUP event as long as no client has the TTY opened.
31  * This means, we cannot use the TTY connection as reliable way to track
32  * the client. Instead, we _must_ rely on the PID of the client to track
33  * them.
34  * However, this has the side effect that if the client forks and the
35  * parent exits, we loose them and restart the client. But this seems to
36  * be the expected behavior so we implement it here.
37  *
38  * Unfortunately, epoll always polls for EPOLLHUP so as long as the
39  * vhangup() is ongoing, we will _always_ get EPOLLHUP and cannot sleep.
40  * This gets worse if the client closes the TTY but doesn't exit.
41  * Therefore, the fd must be edge-triggered in the epoll-set so we
42  * only get the events once they change.
43  */
44
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <limits.h>
48 #include <pty.h>
49 #include <signal.h>
50 #include <stdbool.h>
51 #include <stdint.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <sys/epoll.h>
56 #include <sys/eventfd.h>
57 #include <sys/ioctl.h>
58 #include <sys/types.h>
59 #include <sys/uio.h>
60 #include <sys/wait.h>
61 #include <termios.h>
62 #include <unistd.h>
63
64 #include "barrier.h"
65 #include "macro.h"
66 #include "pty.h"
67 #include "ring.h"
68 #include "util.h"
69
70 #define PTY_BUFSIZE 16384
71
72 enum {
73         PTY_ROLE_UNKNOWN,
74         PTY_ROLE_PARENT,
75         PTY_ROLE_CHILD,
76 };
77
78 struct Pty {
79         unsigned long ref;
80         Barrier barrier;
81         int fd;
82         pid_t child;
83         sd_event_source *fd_source;
84         sd_event_source *child_source;
85
86         char in_buf[PTY_BUFSIZE];
87         Ring out_buf;
88
89         pty_event_t event_fn;
90         void *event_fn_userdata;
91
92         bool needs_requeue : 1;
93         unsigned int role : 2;
94 };
95
96 int pty_new(Pty **out) {
97         _pty_unref_ Pty *pty = NULL;
98         int r;
99
100         assert_return(out, -EINVAL);
101
102         pty = new0(Pty, 1);
103         if (!pty)
104                 return -ENOMEM;
105
106         pty->ref = 1;
107         pty->fd = -1;
108
109         pty->fd = posix_openpt(O_RDWR | O_NOCTTY | O_CLOEXEC | O_NONBLOCK);
110         if (pty->fd < 0)
111                 return -errno;
112
113         /*
114          * The slave-node is initialized to uid/gid of the caller of
115          * posix_openpt(). Only if devpts is mounted with fixed uid/gid this is
116          * skipped. In that case, grantpt() can overwrite these, but then you
117          * have to be root to use chown() (or a pt_chown helper has to be
118          * present). In those cases grantpt() really does something,
119          * otherwise it's a no-op. We call grantpt() here to try supporting
120          * those cases, even though no-one uses that, I guess. If you need other
121          * access-rights, set them yourself after this call returns (no, this is
122          * not racy, it looks racy, but races regarding your own UID are never
123          * important as an attacker could ptrace you; and the slave-pty is also
124          * still locked).
125          */
126         r = grantpt(pty->fd);
127         if (r < 0)
128                 return -errno;
129
130         r = barrier_init(&pty->barrier);
131         if (r < 0)
132                 return r;
133
134         *out = pty;
135         pty = NULL;
136         return 0;
137 }
138
139 Pty *pty_ref(Pty *pty) {
140         if (!pty || pty->ref < 1)
141                 return NULL;
142
143         ++pty->ref;
144         return pty;
145 }
146
147 Pty *pty_unref(Pty *pty) {
148         if (!pty || pty->ref < 1 || --pty->ref > 0)
149                 return NULL;
150
151         pty_close(pty);
152         pty->child_source = sd_event_source_unref(pty->child_source);
153         barrier_destroy(&pty->barrier);
154         ring_clear(&pty->out_buf);
155         free(pty);
156
157         return NULL;
158 }
159
160 Barrier *pty_get_barrier(Pty *pty) {
161         assert(pty);
162         return &pty->barrier;
163 }
164
165 bool pty_is_unknown(Pty *pty) {
166         return pty && pty->role == PTY_ROLE_UNKNOWN;
167 }
168
169 bool pty_is_parent(Pty *pty) {
170         return pty && pty->role == PTY_ROLE_PARENT;
171 }
172
173 bool pty_is_child(Pty *pty) {
174         return pty && pty->role == PTY_ROLE_CHILD;
175 }
176
177 bool pty_has_child(Pty *pty) {
178         return pty_is_parent(pty) && pty->child > 0;
179 }
180
181 pid_t pty_get_child(Pty *pty) {
182         return pty_has_child(pty) ? pty->child : -ECHILD;
183 }
184
185 bool pty_is_open(Pty *pty) {
186         return pty && pty->fd >= 0;
187 }
188
189 int pty_get_fd(Pty *pty) {
190         assert_return(pty, -EINVAL);
191
192         return pty_is_open(pty) ? pty->fd : -EPIPE;
193 }
194
195 int pty_make_child(Pty *pty) {
196         char slave_name[1024];
197         int r, fd;
198
199         assert_return(pty, -EINVAL);
200         assert_return(pty_is_unknown(pty), -EALREADY);
201
202         r = ptsname_r(pty->fd, slave_name, sizeof(slave_name));
203         if (r < 0)
204                 return -errno;
205
206         fd = open(slave_name, O_RDWR | O_CLOEXEC | O_NOCTTY);
207         if (fd < 0)
208                 return -errno;
209
210         safe_close(pty->fd);
211         pty->fd = fd;
212         pty->child = getpid();
213         pty->role = PTY_ROLE_CHILD;
214         barrier_set_role(&pty->barrier, BARRIER_CHILD);
215
216         return 0;
217 }
218
219 int pty_make_parent(Pty *pty, pid_t child) {
220         assert_return(pty, -EINVAL);
221         assert_return(pty_is_unknown(pty), -EALREADY);
222
223         pty->child = child;
224         pty->role = PTY_ROLE_PARENT;
225
226         return 0;
227 }
228
229 int pty_unlock(Pty *pty) {
230         assert_return(pty, -EINVAL);
231         assert_return(pty_is_unknown(pty) || pty_is_parent(pty), -EINVAL);
232         assert_return(pty_is_open(pty), -ENODEV);
233
234         return unlockpt(pty->fd) < 0 ? -errno : 0;
235 }
236
237 int pty_setup_child(Pty *pty) {
238         struct termios attr;
239         pid_t pid;
240         int r;
241
242         assert_return(pty, -EINVAL);
243         assert_return(pty_is_child(pty), -EINVAL);
244         assert_return(pty_is_open(pty), -EALREADY);
245
246         r = sigprocmask_many(SIG_SETMASK, -1);
247         if (r < 0)
248                 return r;
249
250         r = reset_all_signal_handlers();
251         if (r < 0)
252                 return r;
253
254         pid = setsid();
255         if (pid < 0 && errno != EPERM)
256                 return -errno;
257
258         r = ioctl(pty->fd, TIOCSCTTY, 0);
259         if (r < 0)
260                 return -errno;
261
262         r = tcgetattr(pty->fd, &attr);
263         if (r < 0)
264                 return -errno;
265
266         /* erase character should be normal backspace, PLEASEEE! */
267         attr.c_cc[VERASE] = 010;
268         /* always set UTF8 flag */
269         attr.c_iflag |= IUTF8;
270
271         r = tcsetattr(pty->fd, TCSANOW, &attr);
272         if (r < 0)
273                 return -errno;
274
275         if (dup2(pty->fd, STDIN_FILENO) != STDIN_FILENO ||
276             dup2(pty->fd, STDOUT_FILENO) != STDOUT_FILENO ||
277             dup2(pty->fd, STDERR_FILENO) != STDERR_FILENO)
278                 return -errno;
279
280         /* only close FD if it's not a std-fd */
281         pty->fd = (pty->fd > 2) ? safe_close(pty->fd) : -1;
282
283         return 0;
284 }
285
286 void pty_close(Pty *pty) {
287         if (!pty_is_open(pty))
288                 return;
289
290         pty->fd_source = sd_event_source_unref(pty->fd_source);
291         pty->fd = safe_close(pty->fd);
292 }
293
294 /*
295  * Drain input-queue and dispatch data via the event-handler. Returns <0 on
296  * error, 0 if queue is empty and 1 if we couldn't empty the input queue fast
297  * enough and there's still data left.
298  */
299 static int pty_dispatch_read(Pty *pty) {
300         unsigned int i;
301         ssize_t len;
302         int r;
303
304         /*
305          * We're edge-triggered, means we need to read the whole queue. This,
306          * however, might cause us to stall if the writer is faster than we
307          * are. Therefore, we read twice and if the second read still returned
308          * data, we reschedule.
309          */
310
311         for (i = 0; i < 2; ++i) {
312                 len = read(pty->fd, pty->in_buf, sizeof(pty->in_buf) - 1);
313                 if (len < 0) {
314                         if (errno == EINTR)
315                                 continue;
316
317                         return (errno == EAGAIN) ? 0 : -errno;
318                 } else if (len == 0) {
319                         continue;
320                 }
321
322                 /* set terminating zero for debugging safety */
323                 pty->in_buf[len] = 0;
324                 r = pty->event_fn(pty, pty->event_fn_userdata, PTY_DATA, pty->in_buf, len);
325                 if (r < 0)
326                         return r;
327         }
328
329         /* still data left, make sure we're queued again */
330         pty->needs_requeue = true;
331
332         return 1;
333 }
334
335 /*
336  * Drain output-queue by writing data to the pty. Returns <0 on error, 0 if the
337  * output queue is empty now and 1 if we couldn't empty the output queue fast
338  * enough and there's still data left.
339  */
340 static int pty_dispatch_write(Pty *pty) {
341         struct iovec vec[2];
342         unsigned int i;
343         ssize_t len;
344         size_t num;
345
346         /*
347          * Same as pty_dispatch_read(), we're edge-triggered so we need to call
348          * write() until either all data is written or it returns EAGAIN. We
349          * call it twice and if it still writes successfully, we reschedule.
350          */
351
352         for (i = 0; i < 2; ++i) {
353                 num = ring_peek(&pty->out_buf, vec);
354                 if (num < 1)
355                         return 0;
356
357                 len = writev(pty->fd, vec, (int)num);
358                 if (len < 0) {
359                         if (errno == EINTR)
360                                 continue;
361
362                         return (errno == EAGAIN) ? 1 : -errno;
363                 } else if (len == 0) {
364                         continue;
365                 }
366
367                 ring_pull(&pty->out_buf, (size_t)len);
368         }
369
370         /* still data left, make sure we're queued again */
371         if (ring_get_size(&pty->out_buf) > 0) {
372                 pty->needs_requeue = true;
373                 return 1;
374         }
375
376         return 0;
377 }
378
379 static int pty_fd_fn(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
380         Pty *pty = userdata;
381         int r_hup = 0, r_write = 0, r_read = 0, r;
382
383         /*
384          * Whenever we encounter I/O errors, we have to make sure to drain the
385          * input queue first, before we handle any HUP. A child might send us
386          * a message and immediately close the queue. We must not handle the
387          * HUP first or we loose data.
388          * Therefore, if we read a message successfully, we always return
389          * success and wait for the next event-loop iteration. Furthermore,
390          * whenever there is a write-error, we must try reading from the input
391          * queue even if EPOLLIN is not set. The input might have arrived in
392          * between epoll_wait() and write(). Therefore, write-errors are only
393          * ever handled if the input-queue is empty. In all other cases they
394          * are ignored until either reading fails or the input queue is empty.
395          */
396
397         if (revents & (EPOLLHUP | EPOLLERR))
398                 r_hup = -EPIPE;
399
400         if (revents & EPOLLOUT)
401                 r_write = pty_dispatch_write(pty);
402
403         /* Awesome! Kernel signals HUP without IN but queues are not empty.. */
404         if ((revents & EPOLLIN) || r_hup < 0 || r_write < 0) {
405                 r_read = pty_dispatch_read(pty);
406                 if (r_read > 0)
407                         return 0; /* still data left to fetch next round */
408         }
409
410         if (r_hup < 0 || r_write < 0 || r_read < 0) {
411                 /* PTY closed and input-queue drained */
412                 pty_close(pty);
413                 r = pty->event_fn(pty, pty->event_fn_userdata, PTY_HUP, NULL, 0);
414                 if (r < 0)
415                         return r;
416         }
417
418         return 0;
419 }
420
421 static int pty_fd_prepare_fn(sd_event_source *source, void *userdata) {
422         Pty *pty = userdata;
423         int r;
424
425         if (pty->needs_requeue) {
426                 /*
427                  * We're edge-triggered. In case we couldn't handle all events
428                  * or in case new write-data is queued, we set needs_requeue.
429                  * Before going asleep, we set the io-events *again*. sd-event
430                  * notices that we're edge-triggered and forwards the call to
431                  * the kernel even if the events didn't change. The kernel will
432                  * check the events and re-queue us on the ready queue in case
433                  * an event is pending.
434                  */
435                 r = sd_event_source_set_io_events(source, EPOLLHUP | EPOLLERR | EPOLLIN | EPOLLOUT | EPOLLET);
436                 if (r >= 0)
437                         pty->needs_requeue = false;
438         }
439
440         return 0;
441 }
442
443 static int pty_child_fn(sd_event_source *source, const siginfo_t *si, void *userdata) {
444         Pty *pty = userdata;
445         int r;
446
447         pty->child = 0;
448
449         r = pty->event_fn(pty, pty->event_fn_userdata, PTY_CHILD, si, sizeof(*si));
450         if (r < 0)
451                 return r;
452
453         return 0;
454 }
455
456 int pty_attach_event(Pty *pty, sd_event *event, pty_event_t event_fn, void *event_fn_userdata) {
457         int r;
458
459         assert_return(pty, -EINVAL);
460         assert_return(event, -EINVAL);
461         assert_return(event_fn, -EINVAL);
462         assert_return(pty_is_parent(pty), -EINVAL);
463
464         pty_detach_event(pty);
465
466         if (pty_is_open(pty)) {
467                 r = sd_event_add_io(event,
468                                     &pty->fd_source,
469                                     pty->fd,
470                                     EPOLLHUP | EPOLLERR | EPOLLIN | EPOLLOUT | EPOLLET,
471                                     pty_fd_fn,
472                                     pty);
473                 if (r < 0)
474                         goto error;
475
476                 r = sd_event_source_set_prepare(pty->fd_source, pty_fd_prepare_fn);
477                 if (r < 0)
478                         goto error;
479         }
480
481         if (pty_has_child(pty)) {
482                 r = sd_event_add_child(event,
483                                        &pty->child_source,
484                                        pty->child,
485                                        WEXITED,
486                                        pty_child_fn,
487                                        pty);
488                 if (r < 0)
489                         goto error;
490         }
491
492         pty->event_fn = event_fn;
493         pty->event_fn_userdata = event_fn_userdata;
494
495         return 0;
496
497 error:
498         pty_detach_event(pty);
499         return r;
500 }
501
502 void pty_detach_event(Pty *pty) {
503         if (!pty)
504                 return;
505
506         pty->child_source = sd_event_source_unref(pty->child_source);
507         pty->fd_source = sd_event_source_unref(pty->fd_source);
508         pty->event_fn = NULL;
509         pty->event_fn_userdata = NULL;
510 }
511
512 int pty_write(Pty *pty, const void *buf, size_t size) {
513         bool was_empty;
514         int r;
515
516         assert_return(pty, -EINVAL);
517         assert_return(pty_is_open(pty), -ENODEV);
518         assert_return(pty_is_parent(pty), -ENODEV);
519
520         if (size < 1)
521                 return 0;
522
523         /*
524          * Push @buf[0..@size] into the output ring-buffer. In case the
525          * ring-buffer wasn't empty beforehand, we're already waiting for
526          * EPOLLOUT and we're done. If it was empty, we have to re-queue the
527          * FD for EPOLLOUT as we're edge-triggered and wouldn't get any new
528          * EPOLLOUT event.
529          */
530
531         was_empty = ring_get_size(&pty->out_buf) < 1;
532
533         r = ring_push(&pty->out_buf, buf, size);
534         if (r < 0)
535                 return r;
536
537         if (was_empty)
538                 pty->needs_requeue = true;
539
540         return 0;
541 }
542
543 int pty_signal(Pty *pty, int sig) {
544         assert_return(pty, -EINVAL);
545         assert_return(pty_is_open(pty), -ENODEV);
546         assert_return(pty_is_parent(pty), -ENODEV);
547
548         return ioctl(pty->fd, TIOCSIG, sig) < 0 ? -errno : 0;
549 }
550
551 int pty_resize(Pty *pty, unsigned short term_width, unsigned short term_height) {
552         struct winsize ws;
553
554         assert_return(pty, -EINVAL);
555         assert_return(pty_is_open(pty), -ENODEV);
556         assert_return(pty_is_parent(pty), -ENODEV);
557
558         zero(ws);
559         ws.ws_col = term_width;
560         ws.ws_row = term_height;
561
562         /*
563          * This will send SIGWINCH to the pty slave foreground process group.
564          * We will also get one, but we don't need it.
565          */
566         return ioctl(pty->fd, TIOCSWINSZ, &ws) < 0 ? -errno : 0;
567 }
568
569 pid_t pty_fork(Pty **out, sd_event *event, pty_event_t event_fn, void *event_fn_userdata, unsigned short initial_term_width, unsigned short initial_term_height) {
570         _pty_unref_ Pty *pty = NULL;
571         int r;
572         pid_t pid;
573
574         assert_return(out, -EINVAL);
575         assert_return((event && event_fn) || (!event && !event_fn), -EINVAL);
576
577         r = pty_new(&pty);
578         if (r < 0)
579                 return r;
580
581         r = pty_unlock(pty);
582         if (r < 0)
583                 return r;
584
585         pid = fork();
586         if (pid < 0)
587                 return -errno;
588
589         if (pid == 0) {
590                 /* child */
591
592                 r = pty_make_child(pty);
593                 if (r < 0)
594                         _exit(-r);
595
596                 r = pty_setup_child(pty);
597                 if (r < 0)
598                         _exit(-r);
599
600                 /* sync with parent */
601                 if (!barrier_place_and_sync(&pty->barrier))
602                         _exit(1);
603
604                 /* fallthrough and return the child's PTY object */
605         } else {
606                 /* parent */
607
608                 r = pty_make_parent(pty, pid);
609                 if (r < 0)
610                         goto parent_error;
611
612                 r = pty_resize(pty, initial_term_width, initial_term_height);
613                 if (r < 0)
614                         goto parent_error;
615
616                 if (event) {
617                         r = pty_attach_event(pty, event, event_fn, event_fn_userdata);
618                         if (r < 0)
619                                 goto parent_error;
620                 }
621
622                 /* sync with child */
623                 if (!barrier_place_and_sync(&pty->barrier)) {
624                         r = -ECHILD;
625                         goto parent_error;
626                 }
627
628                 /* fallthrough and return the parent's PTY object */
629         }
630
631         *out = pty;
632         pty = NULL;
633         return pid;
634
635 parent_error:
636         barrier_abort(&pty->barrier);
637         waitpid(pty->child, NULL, 0);
638         pty->child = 0;
639         return r;
640 }