d26629a83d770a76bc05bd598363177b85a895b2
[platform/upstream/kmscon.git] / src / kmscon_cdev.c
1 /*
2  * kmscon - Character-Device Session
3  *
4  * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files
8  * (the "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 /*
27  * Character-Device Session
28  */
29
30 #define FUSE_USE_VERSION 29
31
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <linux/kd.h>
35 #include <linux/major.h>
36 #include <linux/vt.h>
37 #include <pthread.h>
38 #include <signal.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/epoll.h>
42 #include <termio.h>
43 #include <termios.h>
44 #include <unistd.h>
45 #include "kmscon_cdev.h"
46 #include "kmscon_seat.h"
47 #include "shl_array.h"
48 #include "shl_dlist.h"
49 #include "shl_log.h"
50 #include "shl_ring.h"
51 #include "tsm_screen.h"
52 #include "tsm_vte.h"
53 #include "uterm_input.h"
54
55 #include <fuse/fuse.h>
56 #include <fuse/fuse_common.h>
57 #include <fuse/fuse_lowlevel.h>
58 #include <fuse/fuse_opt.h>
59 #include <fuse/cuse_lowlevel.h>
60
61 #define LOG_SUBSYSTEM "cdev"
62
63 struct kmscon_cdev {
64         struct kmscon_seat *seat;
65         struct ev_eloop *eloop;
66         struct uterm_input *input;
67         struct kmscon_session *s;
68         struct ev_fd *efd;
69         unsigned int minor;
70
71         struct fuse_session *session;
72         int fd;
73         struct fuse_chan *channel;
74
75         size_t bufsize;
76         char *buf;
77
78         struct shl_dlist clients;
79         int error;
80 };
81
82 struct cdev_client {
83         struct shl_dlist list;
84         struct kmscon_cdev *cdev;
85         bool dead;
86
87         struct tsm_screen *screen;
88         struct tsm_vte *vte;
89
90         bool active;
91         struct kmscon_session *s;
92
93         struct fuse_pollhandle *ph;
94         struct shl_ring *ring;
95         struct shl_dlist readers;
96
97         long kdmode;
98         long kbmode;
99
100         struct vt_mode vtmode;
101         struct fuse_ctx user;
102         bool pending_switch;
103
104         struct shl_dlist waiters;
105 };
106
107 struct cdev_reader {
108         struct shl_dlist list;
109         bool killed;
110         fuse_req_t req;
111         size_t len;
112 };
113
114 struct cdev_waiter {
115         struct shl_dlist list;
116         bool killed;
117         fuse_req_t req;
118 };
119
120 static pthread_mutex_t cdev_lock = PTHREAD_MUTEX_INITIALIZER;
121 static struct shl_array *cdev_ids = NULL;
122
123 static int cdev_allocate_id(void)
124 {
125         static const bool init = true;
126         int ret, len, i;
127
128         pthread_mutex_lock(&cdev_lock);
129
130         if (!cdev_ids) {
131                 ret = shl_array_new(&cdev_ids, sizeof(bool), 4);
132                 if (ret)
133                         goto err_unlock;
134         }
135
136         len = shl_array_get_length(cdev_ids);
137         for (i = 0; i < len; ++i)
138                 if (!*SHL_ARRAY_AT(cdev_ids, bool, i))
139                         break;
140
141         if (i >= len) {
142                 ret = shl_array_push(cdev_ids, &init);
143                 if (ret)
144                         goto err_unlock;
145                 ret = len;
146         } else {
147                 *SHL_ARRAY_AT(cdev_ids, bool, i) = true;
148                 ret = i;
149         }
150
151 err_unlock:
152         pthread_mutex_unlock(&cdev_lock);
153         return (ret < 0) ? ret : (ret + 16384);
154 }
155
156 /*
157  * Cdev Clients
158  * As opposed to kernel VTs, we only provide one single char-dev per seat and
159  * each client that opens it is managed separately. Hence, it is not possible to
160  * use such a VT shared by two clients except if you pass the FD between the
161  * clients. This has several advantages and avoids many bugs in the kernel VT
162  * implementation.
163  * For every user opening a /dev/ttyF<seat> device, a separate cdev_client is
164  * created. A cdev_client emulates a single kernel VT but is managed as a
165  * dedicated kmscon_session on its seat. We start a kmscon_terminal as backend
166  * so you actually can run "agetty" on this fake-VT. When set into graphical
167  * mode, the terminal is suspended and you can run an XServer on it. We emulate
168  * the VT-switching signal-API, too. We release all DRM devices if a fake-VT is
169  * active and reacquire them afterwards. This allows the clients to actually
170  * implement graphical terminals. However, if you fail to release the DRM
171  * devices, we actually try to kill the fake-VT so we can get access again.
172  */
173
174 static void reader_interrupt(fuse_req_t req, void *data)
175 {
176         struct cdev_reader *reader = data;
177
178         if (!reader)
179                 return;
180
181         reader->killed = true;
182 }
183
184 static int reader_new(struct cdev_reader **out, struct cdev_client *client,
185                       fuse_req_t req)
186 {
187         struct cdev_reader *reader;
188
189         if (fuse_req_interrupted(req))
190                 return -ENOENT;
191
192         reader = malloc(sizeof(*reader));
193         if (!reader)
194                 return -ENOMEM;
195         memset(reader, 0, sizeof(*reader));
196         reader->req = req;
197         fuse_req_interrupt_func(req, reader_interrupt, reader);
198         if (reader->killed) {
199                 fuse_req_interrupt_func(req, NULL, NULL);
200                 free(reader);
201                 return -ENOENT;
202         }
203
204         shl_dlist_link_tail(&client->readers, &reader->list);
205         *out = reader;
206         return 0;
207 }
208
209 static void reader_free(struct cdev_reader *reader, int error)
210 {
211         shl_dlist_unlink(&reader->list);
212         if (reader->req) {
213                 fuse_req_interrupt_func(reader->req, NULL, NULL);
214                 fuse_reply_err(reader->req, -error);
215         }
216         free(reader);
217 }
218
219 static int reader_release(struct cdev_reader *reader, const char *buf,
220                           size_t len)
221 {
222         int ret;
223
224         fuse_req_interrupt_func(reader->req, NULL, NULL);
225         ret = fuse_reply_buf(reader->req, buf, len);
226         reader->req = NULL;
227         reader_free(reader, 0);
228         return ret;
229 }
230
231 static void waiter_interrupt(fuse_req_t req, void *data)
232 {
233         struct cdev_waiter *waiter = data;
234
235         if (!waiter)
236                 return;
237
238         waiter->killed = true;
239 }
240
241 static int waiter_new(struct cdev_waiter **out, struct cdev_client *client,
242                       fuse_req_t req)
243 {
244         struct cdev_waiter *waiter;
245
246         if (fuse_req_interrupted(req))
247                 return -ENOENT;
248
249         waiter = malloc(sizeof(*waiter));
250         if (!waiter)
251                 return -ENOMEM;
252         memset(waiter, 0, sizeof(*waiter));
253         waiter->req = req;
254         fuse_req_interrupt_func(req, waiter_interrupt, waiter);
255         if (waiter->killed) {
256                 fuse_req_interrupt_func(req, NULL, NULL);
257                 free(waiter);
258                 return -ENOENT;
259         }
260
261         shl_dlist_link_tail(&client->waiters, &waiter->list);
262         *out = waiter;
263         return 0;
264 }
265
266 static void waiter_free(struct cdev_waiter *waiter, int error)
267 {
268         shl_dlist_unlink(&waiter->list);
269         if (waiter->req) {
270                 fuse_req_interrupt_func(waiter->req, NULL, NULL);
271                 fuse_reply_err(waiter->req, -error);
272         }
273         free(waiter);
274 }
275
276 static int waiter_release(struct cdev_waiter *waiter)
277 {
278         int ret;
279
280         fuse_req_interrupt_func(waiter->req, NULL, NULL);
281         ret = fuse_reply_ioctl(waiter->req, 0, NULL, 0);
282         waiter->req = NULL;
283         waiter_free(waiter, 0);
284         return ret;
285 }
286
287 static void client_vte_event(struct tsm_vte *vte, const char *u8, size_t len,
288                              void *data)
289 {
290         struct cdev_client *client = data;
291         struct cdev_reader *reader;
292         int ret;
293         bool was_empty;
294         const char *buf;
295         size_t size;
296
297         /* TODO: we should have a maximum buffer size here */
298         was_empty = shl_ring_is_empty(client->ring);
299         ret = shl_ring_write(client->ring, u8, len);
300         if (ret)
301                 log_warning("cannot resize buffer for cdev client: %d", ret);
302
303         if (shl_ring_is_empty(client->ring))
304                 return;
305
306         if (was_empty && client->ph) {
307                 fuse_notify_poll(client->ph);
308                 fuse_pollhandle_destroy(client->ph);
309                 client->ph = NULL;
310         }
311
312         while (!shl_dlist_empty(&client->readers)) {
313                 reader = shl_dlist_entry(client->readers.next,
314                                          struct cdev_reader, list);
315                 if (reader->killed)
316                         continue;
317
318                 /* TODO: fix filling the whole buffer instead of returning
319                  * partial buffers when the ring data is split */
320                 buf = shl_ring_peek(client->ring, &size, 0);
321                 if (!size)
322                         break;
323                 if (size > reader->len)
324                         size = reader->len;
325
326                 ret = reader_release(reader, buf, size);
327                 if (ret < 0)
328                         continue;
329                 shl_ring_drop(client->ring, size);
330         }
331 }
332
333 static void client_input_event(struct uterm_input *input,
334                                struct uterm_input_event *ev,
335                                void *data)
336 {
337         struct cdev_client *client = data;
338
339         if (!client->active || ev->handled)
340                 return;
341
342         /* we drop all input in K_OFF mode */
343         if (client->kbmode == K_OFF)
344                 return;
345
346         /* TODO: see kmscon_terminal on how this is special. We need to fix this
347          * when xkbcommon provides the first multi-sym events. */
348         if (ev->num_syms > 1)
349                 return;
350
351         if (tsm_vte_handle_keyboard(client->vte, ev->keysyms[0], ev->ascii,
352                                     ev->mods, ev->codepoints[0])) {
353                 tsm_screen_sb_reset(client->screen);
354                 ev->handled = true;
355         }
356 }
357
358 static int client_activate(struct cdev_client *client)
359 {
360         int ret;
361         struct cdev_waiter *waiter;
362
363         /* TODO: Check whether we have CAP_KILL capability during startup */
364         if (client->vtmode.mode == VT_PROCESS && client->vtmode.acqsig) {
365                 ret = kill(client->user.pid, client->vtmode.acqsig);
366                 if (ret)
367                         log_warning("cannot send activation signal to process %d of cdev client %p (%d): %m",
368                                     client->user.pid, client, errno);
369         }
370
371         while (!shl_dlist_empty(&client->waiters)) {
372                 waiter = shl_dlist_entry(client->waiters.next,
373                                          struct cdev_waiter, list);
374                 if (waiter->killed)
375                         waiter_free(waiter, 0);
376                 else
377                         waiter_release(waiter);
378         }
379
380         client->active = true;
381         return 0;
382 }
383
384 static int client_deactivate(struct cdev_client *client)
385 {
386         int ret;
387
388         if (client->vtmode.mode == VT_PROCESS && client->vtmode.relsig) {
389                 ret = kill(client->user.pid, client->vtmode.relsig);
390                 if (ret)
391                         log_warning("cannot send deactivation signal to process %d of cdev client %p (%d): %m",
392                                     client->user.pid, client, errno);
393                 client->pending_switch = true;
394                 return -EINPROGRESS;
395         }
396
397         client->active = false;
398         return 0;
399 }
400
401 static void client_kill(struct cdev_client *client)
402 {
403         struct cdev_reader *reader;
404         struct cdev_waiter *waiter;
405
406         if (client->dead) {
407                 log_error("killing already dead client");
408                 return;
409         }
410
411         log_debug("kill fake TTY client %p", client);
412
413         client->dead = true;
414
415         if (client->ph) {
416                 fuse_notify_poll(client->ph);
417                 fuse_pollhandle_destroy(client->ph);
418         }
419
420         while (!shl_dlist_empty(&client->readers)) {
421                 reader = shl_dlist_entry(client->readers.next,
422                                          struct cdev_reader, list);
423                 reader_free(reader, -EPIPE);
424         }
425
426         while (!shl_dlist_empty(&client->waiters)) {
427                 waiter = shl_dlist_entry(client->waiters.next,
428                                          struct cdev_waiter, list);
429                 waiter_free(waiter, -EPIPE);
430         }
431
432         uterm_input_unregister_cb(client->cdev->input, client_input_event,
433                                   client);
434         tsm_vte_unref(client->vte);
435         tsm_screen_unref(client->screen);
436         shl_ring_free(client->ring);
437 }
438
439 static int client_session_event(struct kmscon_session *s,
440                                 struct kmscon_session_event *ev,
441                                 void *data)
442 {
443         struct cdev_client *client = data;
444
445         switch (ev->type) {
446         case KMSCON_SESSION_ACTIVATE:
447                 return client_activate(client);
448         case KMSCON_SESSION_DEACTIVATE:
449                 return client_deactivate(client);
450         case KMSCON_SESSION_UNREGISTER:
451                 client_kill(client);
452                 break;
453         }
454
455         return 0;
456 }
457
458 static int client_new(struct cdev_client **out, struct kmscon_cdev *cdev)
459 {
460         struct cdev_client *client;
461         int ret;
462
463         client = malloc(sizeof(*client));
464         if (!client)
465                 return -ENOMEM;
466         memset(client, 0, sizeof(*client));
467         client->cdev = cdev;
468         client->kdmode = KD_TEXT;
469         client->kbmode = K_UNICODE;
470         client->vtmode.mode = VT_AUTO;
471         shl_dlist_init(&client->readers);
472         shl_dlist_init(&client->waiters);
473
474         log_debug("new fake TTY client %p", client);
475
476         ret = shl_ring_new(&client->ring);
477         if (ret) {
478                 log_error("cannot create ring buffer for new cdev client: %d",
479                           ret);
480                 goto err_free;
481         }
482
483         /* TODO: Share the terminal-handling with the terminal-session. We
484          * currently just create the screen/vte objects here to get meaningful
485          * parsers. However, we should also correctly handled the terminal as is
486          * and draw it to the screen if in text-mode.
487          * This is nearly identical to the terminal-session so we should share
488          * the implementation between both instead of doing everything ourself
489          * here. */
490
491         ret = tsm_screen_new(&client->screen, log_llog, NULL);
492         if (ret) {
493                 log_error("cannot create TSM screen for new cdev client: %d",
494                           ret);
495                 goto err_ring;
496         }
497
498         ret = tsm_vte_new(&client->vte, client->screen, client_vte_event,
499                           client, log_llog, NULL);
500         if (ret) {
501                 log_error("cannot create TSM VTE for new cdev client: %d",
502                           ret);
503                 goto err_screen;
504         }
505
506         ret = uterm_input_register_cb(cdev->input, client_input_event, client);
507         if (ret) {
508                 log_error("cannot register input callback for cdev client: %d",
509                           ret);
510                 goto err_vte;
511         }
512
513         ret = kmscon_seat_register_session(cdev->seat, &client->s,
514                                            client_session_event, client);
515         if (ret) {
516                 log_error("cannot register session for cdev client: %d", ret);
517                 goto err_input;
518         }
519
520         shl_dlist_link(&cdev->clients, &client->list);
521         *out = client;
522         return 0;
523
524 err_input:
525         uterm_input_unregister_cb(cdev->input, client_input_event, client);
526 err_vte:
527         tsm_vte_unref(client->vte);
528 err_screen:
529         tsm_screen_unref(client->screen);
530 err_ring:
531         shl_ring_free(client->ring);
532 err_free:
533         free(client);
534         return ret;
535 }
536
537 static void client_destroy(struct cdev_client *client)
538 {
539         log_debug("destroy client %p", client);
540
541         if (!client->dead)
542                 kmscon_session_unregister(client->s);
543         shl_dlist_unlink(&client->list);
544         free(client);
545 }
546
547 /* This must be called after each event dispatch round. It cleans up all
548  * interrupted/killed readers. The readers cannot be released right away due to
549  * heavy locking inside of FUSE. We have to delay these tasks and clean up after
550  * each dispatch round. */
551 static void client_cleanup(struct cdev_client *client)
552 {
553         struct shl_dlist *i, *tmp;
554         struct cdev_reader *reader;
555         struct cdev_waiter *waiter;
556
557         shl_dlist_for_each_safe(i, tmp, &client->readers) {
558                 reader = shl_dlist_entry(i, struct cdev_reader, list);
559                 if (reader->killed)
560                         reader_free(reader, -ENOENT);
561         }
562
563         shl_dlist_for_each_safe(i, tmp, &client->waiters) {
564                 waiter = shl_dlist_entry(i, struct cdev_waiter, list);
565                 if (waiter->killed)
566                         waiter_free(waiter, -ENOENT);
567         }
568 }
569
570 /*
571  * FUSE low-level ops
572  * This implements all the file-system operations on the character-device. It is
573  * important that we handle interrupts correctly (ENOENT) and never loose any
574  * data. This is all single threaded as it is not performance critical at all.
575  */
576
577 static void ll_open(fuse_req_t req, struct fuse_file_info *fi)
578 {
579         struct kmscon_cdev *cdev = fuse_req_userdata(req);
580         struct cdev_client *client;
581         int ret;
582
583         ret = client_new(&client, cdev);
584         if (ret)
585                 goto err_out;
586
587         fi->fh = (long)client;
588         fi->nonseekable = 1;
589         fi->direct_io = 1;
590         ret = fuse_reply_open(req, fi);
591         if (ret < 0)
592                 client_destroy(client);
593         else
594                 kmscon_session_enable(client->s);
595
596         return;
597
598 err_out:
599         fuse_reply_err(req, -ret);
600 }
601
602 static void ll_release(fuse_req_t req, struct fuse_file_info *fi)
603 {
604         struct cdev_client *client = (void*)fi->fh;
605
606         if (!client) {
607                 fuse_reply_err(req, EINVAL);
608                 return;
609         }
610
611         client_destroy(client);
612         fuse_reply_err(req, 0);
613 }
614
615 static void ll_read(fuse_req_t req, size_t size, off_t off,
616                     struct fuse_file_info *fi)
617 {
618         struct cdev_client *client = (void*)fi->fh;
619         struct cdev_reader *reader;
620         const char *buf;
621         size_t len;
622         int ret;
623
624         if (!client) {
625                 fuse_reply_err(req, EINVAL);
626                 return;
627         }
628
629         if (client->dead) {
630                 fuse_reply_err(req, EPIPE);
631                 return;
632         }
633
634         if (off != 0) {
635                 fuse_reply_err(req, EINVAL);
636                 return;
637         }
638
639         if (!size) {
640                 fuse_reply_buf(req, "", 0);
641                 return;
642         }
643
644         /* TODO: use a proper intermediate buffer as this might return only
645          * partial data */
646         buf = shl_ring_peek(client->ring, &len, 0);
647         if (!len) {
648                 if (fi->flags & O_NONBLOCK) {
649                         fuse_reply_err(req, EAGAIN);
650                         return;
651                 }
652
653                 ret = reader_new(&reader, client, req);
654                 if (ret) {
655                         fuse_reply_err(req, -ret);
656                         return;
657                 }
658
659                 reader->len = size;
660                 return;
661         }
662
663         if (len > size)
664                 len = size;
665         ret = fuse_reply_buf(req, buf, len);
666         if (ret < 0)
667                 return;
668         shl_ring_drop(client->ring, len);
669 }
670
671 static void ll_write(fuse_req_t req, const char *buf, size_t size, off_t off,
672                      struct fuse_file_info *fi)
673 {
674         struct cdev_client *client = (void*)fi->fh;
675         int ret;
676
677         if (!client) {
678                 fuse_reply_err(req, EINVAL);
679                 return;
680         }
681
682         if (client->dead) {
683                 fuse_reply_err(req, EPIPE);
684                 return;
685         }
686
687         ret = fuse_reply_write(req, size);
688         if (ret < 0)
689                 return;
690         tsm_vte_input(client->vte, buf, size);
691 }
692
693 static void ll_poll(fuse_req_t req, struct fuse_file_info *fi,
694                     struct fuse_pollhandle *ph)
695 {
696         struct cdev_client *client = (void*)fi->fh;
697         unsigned int flags;
698
699         if (!client) {
700                 fuse_reply_err(req, EINVAL);
701                 return;
702         }
703
704         if (client->dead) {
705                 if (ph)
706                         fuse_pollhandle_destroy(ph);
707                 fuse_reply_poll(req, EPOLLHUP | EPOLLIN | EPOLLOUT |
708                                      EPOLLWRNORM | EPOLLRDNORM);
709                 return;
710         }
711
712         if (client->ph)
713                 fuse_pollhandle_destroy(client->ph);
714         client->ph = ph;
715
716         flags = EPOLLOUT | EPOLLWRNORM;
717         if (!shl_ring_is_empty(client->ring))
718                 flags |= EPOLLIN | EPOLLRDNORM;
719
720         fuse_reply_poll(req, flags);
721 }
722
723 static void ioctl_TCFLSH(struct cdev_client *client, fuse_req_t req, int val)
724 {
725         switch (val) {
726         case TCIFLUSH:
727                 shl_ring_flush(client->ring);
728                 break;
729         case TCIOFLUSH:
730                 shl_ring_flush(client->ring);
731                 /* fallthrough */
732         case TCOFLUSH:
733                 /* nothing to do; we have no output queue */
734                 break;
735         default:
736                 fuse_reply_err(req, EINVAL);
737                 return;
738         }
739
740         fuse_reply_ioctl(req, 0, NULL, 0);
741 }
742
743 static void ioctl_VT_ACTIVATE(struct cdev_client *client, fuse_req_t req,
744                               int val)
745 {
746         unsigned short target, id;
747
748         id = client->cdev->minor;
749         target = val;
750
751         if (id == target) {
752                 kmscon_session_schedule(client->s);
753         } else {
754                 kmscon_seat_schedule(client->cdev->seat, target);
755         }
756
757         fuse_reply_ioctl(req, 0, NULL, 0);
758 }
759
760 static void ioctl_VT_WAITACTIVE(struct cdev_client *client, fuse_req_t req,
761                                 int val)
762 {
763         int ret;
764         struct cdev_waiter *waiter;
765
766         if (client->active) {
767                 fuse_reply_ioctl(req, 0, NULL, 0);
768                 return;
769         }
770
771         ret = waiter_new(&waiter, client, req);
772         if (ret) {
773                 fuse_reply_err(req, -ret);
774                 return;
775         }
776 }
777
778 static void ioctl_VT_GETSTATE(struct cdev_client *client, fuse_req_t req)
779 {
780         struct vt_stat buf;
781         unsigned short id;
782
783         id = client->cdev->minor;
784         if (id == 0 || id == 1)
785                 id = 2;
786
787         memset(&buf, 0, sizeof(buf));
788         buf.v_active = client->active ? id : 1;
789         buf.v_signal = 0;
790         buf.v_state = ~0;
791
792         fuse_reply_ioctl(req, 0, &buf, sizeof(buf));
793 }
794
795 static void ioctl_VT_GETMODE(struct cdev_client *client, fuse_req_t req)
796 {
797         fuse_reply_ioctl(req, 0, &client->vtmode, sizeof(client->vtmode));
798 }
799
800 static void ioctl_VT_SETMODE(struct cdev_client *client, fuse_req_t req,
801                              struct vt_mode *mode)
802 {
803         bool proc;
804
805         proc = mode->mode == VT_PROCESS;
806
807         /* TODO: implement "waitv" logic */
808         if (mode->waitv) {
809                 fuse_reply_err(req, EINVAL);
810                 return;
811         }
812
813         if (mode->frsig)
814                 log_debug("cdev client uses non-zero 'frsig' in VT_SETMODE: %d",
815                           mode->frsig);
816
817         if (mode->mode != VT_AUTO && mode->mode != VT_PROCESS) {
818                 fuse_reply_err(req, EINVAL);
819                 return;
820         }
821
822         if (proc && (mode->relsig > SIGRTMAX || mode->acqsig > SIGRTMAX ||
823                      mode->relsig < 0 || mode->acqsig < 0)) {
824                 fuse_reply_err(req, EINVAL);
825                 return;
826         }
827
828         memcpy(&client->vtmode, mode, sizeof(*mode));
829         memcpy(&client->user, fuse_req_ctx(req), sizeof(client->user));
830         fuse_reply_ioctl(req, 0, NULL, 0);
831 }
832
833 static void ioctl_VT_RELDISP(struct cdev_client *client, fuse_req_t req,
834                              int val)
835 {
836         if (client->pending_switch) {
837                 client->pending_switch = false;
838                 if (val > 0) {
839                         client->active = false;
840                         kmscon_session_notify_deactivated(client->s);
841                 }
842         }
843
844         fuse_reply_ioctl(req, 0, NULL, 0);
845 }
846
847 static void ioctl_KDGETMODE(struct cdev_client *client, fuse_req_t req)
848 {
849         fuse_reply_ioctl(req, 0, &client->kdmode, sizeof(long));
850 }
851
852 static void ioctl_KDSETMODE(struct cdev_client *client, fuse_req_t req,
853                             long val)
854 {
855         int ret;
856
857         switch (val) {
858         case KD_TEXT:
859                 ret = kmscon_session_set_foreground(client->s);
860                 if (ret) {
861                         fuse_reply_err(req, -ret);
862                         return;
863                 }
864                 client->kdmode = KD_TEXT;
865                 break;
866         case KD_GRAPHICS:
867                 ret = kmscon_session_set_background(client->s);
868                 if (ret) {
869                         fuse_reply_err(req, -ret);
870                         return;
871                 }
872                 client->kdmode = KD_GRAPHICS;
873                 break;
874         default:
875                 fuse_reply_err(req, EINVAL);
876                 return;
877         }
878
879         fuse_reply_ioctl(req, 0, NULL, 0);
880 }
881
882 static void ioctl_KDGKBMODE(struct cdev_client *client, fuse_req_t req)
883 {
884         fuse_reply_ioctl(req, 0, &client->kbmode, sizeof(long));
885 }
886
887 static void ioctl_KDSKBMODE(struct cdev_client *client, fuse_req_t req,
888                             long val)
889 {
890         switch (val) {
891         case K_RAW:
892         case K_UNICODE:
893         case K_OFF:
894                 /* TODO: we handle K_RAW/K_UNICODE the same way as it is unclear
895                  * what K_RAW should do? */
896                 client->kbmode = val;
897                 fuse_reply_ioctl(req, 0, NULL, 0);
898                 break;
899         case K_XLATE:
900         case K_MEDIUMRAW:
901                 /* TODO: what do these do? */
902                 fuse_reply_err(req, EOPNOTSUPP);
903                 break;
904         default:
905                 fuse_reply_err(req, EINVAL);
906                 break;
907         }
908 }
909
910 static bool ioctl_param(fuse_req_t req, void *arg, size_t in_want,
911                         size_t in_have, size_t out_want, size_t out_have)
912 {
913         bool retry;
914         struct iovec in, out;
915         size_t in_num, out_num;
916
917         retry = false;
918         memset(&in, 0, sizeof(in));
919         in_num = 0;
920         memset(&out, 0, sizeof(out));
921         out_num = 0;
922
923         if (in_want) {
924                 if (!in_have) {
925                         retry = true;
926                 } else if (in_have < in_want) {
927                         fuse_reply_err(req, EFAULT);
928                         return true;
929                 }
930
931                 in.iov_base = arg;
932                 in.iov_len = in_want;
933                 in_num = 1;
934         }
935         if (out_want) {
936                 if (!out_have) {
937                         retry = true;
938                 } else if (out_have < out_want) {
939                         fuse_reply_err(req, EFAULT);
940                         return true;
941                 }
942
943                 out.iov_base = arg;
944                 out.iov_len = out_want;
945                 out_num = 1;
946         }
947
948         if (retry)
949                 fuse_reply_ioctl_retry(req, in_num ? &in : NULL, in_num,
950                                        out_num ? &out : NULL, out_num);
951         return retry;
952 }
953
954 static void ll_ioctl(fuse_req_t req, int cmd, void *arg,
955                      struct fuse_file_info *fi, unsigned int flags,
956                      const void *in_buf, size_t in_bufsz, size_t out_bufsz)
957 {
958         struct cdev_client *client = (void*)fi->fh;
959         bool compat;
960
961         if (!client) {
962                 fuse_reply_err(req, EINVAL);
963                 return;
964         }
965
966         if (client->dead) {
967                 fuse_reply_err(req, EPIPE);
968                 return;
969         }
970
971         /* TODO: fix compat-ioctls */
972         compat = !!(flags & FUSE_IOCTL_COMPAT);
973         if (compat) {
974                 fuse_reply_err(req, EOPNOTSUPP);
975                 return;
976         }
977
978         switch (cmd) {
979         case TCFLSH:
980                 if (ioctl_param(req, arg, 0, in_bufsz, 0, out_bufsz))
981                         return;
982                 ioctl_TCFLSH(client, req, (long)arg);
983                 break;
984         case VT_ACTIVATE:
985                 if (ioctl_param(req, arg, 0, in_bufsz, 0, out_bufsz))
986                         return;
987                 ioctl_VT_ACTIVATE(client, req, (long)arg);
988                 break;
989         case VT_WAITACTIVE:
990                 if (ioctl_param(req, arg, 0, in_bufsz, 0, out_bufsz))
991                         return;
992                 ioctl_VT_WAITACTIVE(client, req, (long)arg);
993                 break;
994         case VT_GETSTATE:
995                 if (ioctl_param(req, arg, 0, in_bufsz,
996                                 sizeof(struct vt_stat), out_bufsz))
997                         return;
998                 ioctl_VT_GETSTATE(client, req);
999                 break;
1000         case VT_OPENQRY:
1001                 if (ioctl_param(req, arg, 0, in_bufsz,
1002                                 sizeof(int), out_bufsz))
1003                         return;
1004                 fuse_reply_err(req, EOPNOTSUPP);
1005                 break;
1006         case VT_GETMODE:
1007                 if (ioctl_param(req, arg, 0, in_bufsz,
1008                                 sizeof(struct vt_mode), out_bufsz))
1009                         return;
1010                 ioctl_VT_GETMODE(client, req);
1011                 break;
1012         case VT_SETMODE:
1013                 if (ioctl_param(req, arg, sizeof(struct vt_mode), in_bufsz,
1014                                 0, out_bufsz))
1015                         return;
1016                 ioctl_VT_SETMODE(client, req, (struct vt_mode*)in_buf);
1017                 break;
1018         case VT_RELDISP:
1019                 if (ioctl_param(req, arg, 0, in_bufsz, 0, out_bufsz))
1020                         return;
1021                 ioctl_VT_RELDISP(client, req, (long)arg);
1022                 break;
1023         case KDGETMODE:
1024                 if (ioctl_param(req, arg, 0, in_bufsz,
1025                                 sizeof(long), out_bufsz))
1026                         return;
1027                 ioctl_KDGETMODE(client, req);
1028                 break;
1029         case KDSETMODE:
1030                 if (ioctl_param(req, arg, 0, in_bufsz, 0, out_bufsz))
1031                         return;
1032                 ioctl_KDSETMODE(client, req, (long)arg);
1033                 break;
1034         case KDGKBMODE:
1035                 if (ioctl_param(req, arg, 0, in_bufsz,
1036                                 sizeof(long), out_bufsz))
1037                         return;
1038                 ioctl_KDGKBMODE(client, req);
1039                 break;
1040         case KDSKBMODE:
1041                 if (ioctl_param(req, arg, 0, in_bufsz, 0, out_bufsz))
1042                         return;
1043                 ioctl_KDSKBMODE(client, req, (long)arg);
1044                 break;
1045         case TCGETS:
1046                 if (ioctl_param(req, arg, 0, in_bufsz,
1047                                 sizeof(struct termios), out_bufsz))
1048                         return;
1049                 fuse_reply_err(req, EOPNOTSUPP);
1050                 break;
1051         case TCSETS:
1052                 if (ioctl_param(req, arg, sizeof(struct termios), in_bufsz,
1053                                 0, out_bufsz))
1054                         return;
1055                 fuse_reply_err(req, EOPNOTSUPP);
1056                 break;
1057         case TCSETSW:
1058                 if (ioctl_param(req, arg, sizeof(struct termios), in_bufsz,
1059                                 0, out_bufsz))
1060                         return;
1061                 fuse_reply_err(req, EOPNOTSUPP);
1062                 break;
1063         case TCSETSF:
1064                 if (ioctl_param(req, arg, sizeof(struct termios), in_bufsz,
1065                                 0, out_bufsz))
1066                         return;
1067                 fuse_reply_err(req, EOPNOTSUPP);
1068                 break;
1069         default:
1070                 fuse_reply_err(req, EINVAL);
1071                 break;
1072         }
1073 }
1074
1075 static void ll_destroy(void *data) {
1076         struct kmscon_cdev *cdev = data;
1077         struct cdev_client *client;
1078
1079         /* on unexpected shutdown this releases all currently open clients */
1080         while (!shl_dlist_empty(&cdev->clients)) {
1081                 client = shl_dlist_entry(cdev->clients.next,
1082                                          struct cdev_client, list);
1083                 client_destroy(client);
1084         }
1085 }
1086
1087 static const struct cuse_lowlevel_ops ll_ops = {
1088         .init = NULL,
1089         .destroy = ll_destroy,
1090         .open = ll_open,
1091         .release = ll_release,
1092         .read = ll_read,
1093         .write = ll_write,
1094         .poll = ll_poll,
1095         .ioctl = ll_ioctl,
1096         .flush = NULL,
1097         .fsync = NULL,
1098 };
1099
1100 /*
1101  * FUSE channel ops
1102  * The connection to the FUSE kernel module is done via a file-descriptor.
1103  * Writing to it is synchronous, so the commands that we write are _immediately_
1104  * executed and return the result to us. Furthermore, write() is always
1105  * non-blocking and always succeeds so no reason to watch for EAGAIN.
1106  * Reading from the FD, on the other hand, may block if there is no data
1107  * available. However, we only read if the FD was signaled readable so we can
1108  * use a blocking FD to avoid any side-effects. The kernel maintains an
1109  * event-queue that we read from. So there may be pending events that we haven't
1110  * read but which affect the calls that we write to the kernel. This is
1111  * important when handling interrupts.
1112  * chan_receive() and chan_send() handle I/O to the kernel module and are hooked
1113  * up into a fuse-channel.
1114  */
1115
1116 static int chan_receive(struct fuse_chan **chp, char *buf, size_t size)
1117 {
1118         struct fuse_chan *ch = *chp;
1119         struct kmscon_cdev *cdev = fuse_chan_data(ch);
1120         struct fuse_session *se = fuse_chan_session(ch);
1121         int fd = fuse_chan_fd(ch);
1122         ssize_t res;
1123
1124         if (!se || !cdev)
1125                 return -EINVAL;
1126
1127         if (!size)
1128                 return 0;
1129
1130 restart:
1131         if (fuse_session_exited(se))
1132                 return 0;
1133
1134         res = read(fd, buf, size);
1135         if (!res) {
1136                 /* EOF on cuse file */
1137                 log_error("fuse channel shut down");
1138                 fuse_session_exit(se);
1139                 return 0;
1140         } else if (res < 0) {
1141                 /* ENOENT is returned if the operation was interrupted, it's
1142                  * safe to restart */
1143                 if (errno == ENOENT)
1144                         goto restart;
1145
1146                 /* ENODEV is returned if the FS got unmounted. This shouldn't
1147                  * occur for CUSE devices. Anyway, exit if this happens. */
1148                 if (errno == ENODEV) {
1149                         fuse_session_exit(se);
1150                         return 0;
1151                 }
1152
1153                 /* EINTR and EAGAIN are simply forwarded to the caller. */
1154                 if (errno == EINTR || errno == EAGAIN)
1155                         return -errno;
1156
1157                 cdev->error = -errno;
1158                 log_error("fuse channel read error (%d): %m", errno);
1159                 fuse_session_exit(se);
1160                 return cdev->error;
1161         }
1162
1163         return res;
1164 }
1165
1166 static int chan_send(struct fuse_chan *ch, const struct iovec iov[],
1167                      size_t count)
1168 {
1169         struct kmscon_cdev *cdev = fuse_chan_data(ch);
1170         struct fuse_session *se = fuse_chan_session(ch);
1171         int fd = fuse_chan_fd(ch);
1172         int ret;
1173
1174         if (!cdev || !se)
1175                 return -EINVAL;
1176         if (!iov || !count)
1177                 return 0;
1178
1179         ret = writev(fd, iov, count);
1180         if (ret < 0) {
1181                 /* ENOENT is returned on interruptions */
1182                 if (!fuse_session_exited(se) && errno != ENOENT) {
1183                         cdev->error = -errno;
1184                         log_error("cannot write to fuse-channel (%d): %m",
1185                                   errno);
1186                         fuse_session_exit(se);
1187                 }
1188                 return cdev->error;
1189         }
1190
1191         return 0;
1192 }
1193
1194 static const struct fuse_chan_ops chan_ops = {
1195         .receive = chan_receive,
1196         .send = chan_send,
1197         .destroy = NULL,
1198 };
1199
1200 /*
1201  * Character Device
1202  * This creates the high-level character-device driver and registers a
1203  * fake-session that is used to control each fake-VT session.
1204  * channel_event() is a callback when I/O is possible on the FUSE FD and
1205  * performs all outstanding tasks.
1206  * On error, the fake-session is unregistered and deleted which also destroys
1207  * _all_ client fake-sessions.
1208  */
1209
1210 static void channel_event(struct ev_fd *fd, int mask, void *data)
1211 {
1212         struct kmscon_cdev *cdev = data;
1213         int ret;
1214         struct fuse_buf buf;
1215         struct fuse_chan *ch;
1216         struct shl_dlist *i;
1217         struct cdev_client *client;
1218
1219         if (mask & (EV_HUP | EV_ERR)) {
1220                 log_error("HUP/ERR on fuse channel");
1221                 cdev->error = -EPIPE;
1222                 kmscon_session_unregister(cdev->s);
1223                 return;
1224         }
1225
1226         if (!(mask & EV_READABLE))
1227                 return;
1228
1229         memset(&buf, 0, sizeof(buf));
1230         buf.mem = cdev->buf;
1231         buf.size = cdev->bufsize;
1232         ch = cdev->channel;
1233         ret = fuse_session_receive_buf(cdev->session, &buf, &ch);
1234         if (ret == -EINTR || ret == -EAGAIN) {
1235                 return;
1236         } else if (ret < 0) {
1237                 log_error("fuse channel read error: %d", ret);
1238                 cdev->error = ret;
1239                 kmscon_session_unregister(cdev->s);
1240                 return;
1241         }
1242
1243         fuse_session_process_buf(cdev->session, &buf, ch);
1244         if (fuse_session_exited(cdev->session)) {
1245                 log_error("fuse session exited");
1246                 if (!cdev->error)
1247                         cdev->error = -EFAULT;
1248                 kmscon_session_unregister(cdev->s);
1249                 return;
1250         }
1251
1252         /* Readers can get interrupted asynchronously. Due to heavy locking
1253          * inside of FUSE, we cannot release them right away. So cleanup all
1254          * killed readers after we processed all buffers. */
1255         shl_dlist_for_each(i, &cdev->clients) {
1256                 client = shl_dlist_entry(i, struct cdev_client, list);
1257                 client_cleanup(client);
1258         }
1259 }
1260
1261 static int kmscon_cdev_init(struct kmscon_cdev *cdev)
1262 {
1263         static const char prefix[] = "DEVNAME=";
1264         static const char fname[] = "/dev/cuse";
1265         int ret, id;
1266         size_t bufsize;
1267         struct cuse_info ci;
1268         const char *dev_info_argv[1];
1269         char *name;
1270
1271         /* TODO: libfuse makes sure that fd 0, 1 and 2 are available as standard
1272          * streams, otherwise they fail. This is awkward and we should check
1273          * whether this is really needed and _why_?
1274          * If it is needed, fix upstream to stop that crazy! */
1275
1276         shl_dlist_init(&cdev->clients);
1277
1278         ret = asprintf(&name, "%sttyF%s", prefix,
1279                        kmscon_seat_get_name(cdev->seat));
1280         if (ret <= 0) {
1281                 log_error("cannot allocate memory for fuse-devname");
1282                 return -ENOMEM;
1283         }
1284
1285         log_info("initializing fake VT TTY device /dev/%s",
1286                  &name[sizeof(prefix) - 1]);
1287
1288         id = cdev_allocate_id();
1289         if (id < 0) {
1290                 log_error("cannot allocate new cdev TTY id: %d", id);
1291                 free(name);
1292                 return id;
1293         }
1294         cdev->minor = id;
1295
1296         dev_info_argv[0] = name;
1297         memset(&ci, 0, sizeof(ci));
1298         ci.dev_major = TTY_MAJOR;
1299         ci.dev_minor = cdev->minor;
1300         ci.dev_info_argc = 1;
1301         ci.dev_info_argv = dev_info_argv;
1302         ci.flags = CUSE_UNRESTRICTED_IOCTL;
1303
1304         cdev->session = cuse_lowlevel_new(NULL, &ci, &ll_ops, cdev);
1305         free(name);
1306
1307         if (!cdev->session) {
1308                 log_error("cannot create fuse-ll session");
1309                 return -ENOMEM;
1310         }
1311
1312         cdev->fd = open(fname, O_RDWR | O_CLOEXEC);
1313         if (cdev->fd < 0) {
1314                 log_error("cannot open %s (%d): %m", fname, errno);
1315                 ret = -EFAULT;
1316                 goto err_session;
1317         }
1318
1319         bufsize = getpagesize() + 0x1000;
1320         if (bufsize < 0x21000)
1321                 bufsize = 0x21000;
1322
1323         cdev->bufsize = bufsize;
1324         cdev->buf = malloc(bufsize);
1325         if (!cdev->buf) {
1326                 log_error("cannot allocate memory for buffer of size %zu",
1327                           bufsize);
1328                 ret = -ENOMEM;
1329                 goto err_fd;
1330         }
1331
1332         /* Argh! libfuse does not use "const" for the "chan_ops" pointer so we
1333          * actually have to cast it. Their implementation does not write into it
1334          * so we can safely use a constant storage for it.
1335          * TODO: Fix libfuse upstream! */
1336         cdev->channel = fuse_chan_new((void*)&chan_ops, cdev->fd, bufsize,
1337                                       cdev);
1338         if (!cdev->channel) {
1339                 log_error("cannot allocate fuse-channel");
1340                 ret = -ENOMEM;
1341                 goto err_buf;
1342         }
1343
1344         ret = ev_eloop_new_fd(cdev->eloop, &cdev->efd, cdev->fd, EV_READABLE,
1345                               channel_event, cdev);
1346         if (ret) {
1347                 log_error("cannot create fd-object in eloop: %d", ret);
1348                 goto err_chan;
1349         }
1350
1351         fuse_session_add_chan(cdev->session, cdev->channel);
1352         return 0;
1353
1354 err_chan:
1355         fuse_chan_destroy(cdev->channel);
1356 err_buf:
1357         free(cdev->buf);
1358 err_fd:
1359         close(cdev->fd);
1360 err_session:
1361         fuse_session_destroy(cdev->session);
1362         return ret;
1363 }
1364
1365 void kmscon_cdev_destroy(struct kmscon_cdev *cdev)
1366 {
1367         if (!cdev)
1368                 return;
1369
1370         if (cdev->error)
1371                 log_warning("cdev module failed with error %d (maybe another kmscon process is already running?)",
1372                             cdev->error);
1373
1374         fuse_session_destroy(cdev->session);
1375         ev_eloop_rm_fd(cdev->efd);
1376         free(cdev->buf);
1377         close(cdev->fd);
1378 }
1379
1380 static int session_event(struct kmscon_session *session,
1381                          struct kmscon_session_event *ev, void *data)
1382 {
1383         struct kmscon_cdev *cdev = data;
1384
1385         switch (ev->type) {
1386         case KMSCON_SESSION_UNREGISTER:
1387                 log_debug("destroy cdev session");
1388                 kmscon_cdev_destroy(cdev);
1389                 free(cdev);
1390                 break;
1391         }
1392
1393         return 0;
1394 }
1395
1396 int kmscon_cdev_register(struct kmscon_session **out,
1397                          struct kmscon_seat *seat)
1398 {
1399         struct kmscon_cdev *cdev;
1400         int ret;
1401
1402         if (!out || !seat)
1403                 return -EINVAL;
1404
1405         cdev = malloc(sizeof(*cdev));
1406         if (!cdev)
1407                 return -ENOMEM;
1408         memset(cdev, 0, sizeof(*cdev));
1409         cdev->seat = seat;
1410         cdev->eloop = kmscon_seat_get_eloop(seat);
1411         cdev->input = kmscon_seat_get_input(seat);
1412
1413         ret = kmscon_cdev_init(cdev);
1414         if (ret)
1415                 goto err_free;
1416
1417         ret = kmscon_seat_register_session(seat, &cdev->s, session_event, cdev);
1418         if (ret) {
1419                 log_error("cannot register session for cdev: %d", ret);
1420                 goto err_cdev;
1421         }
1422
1423         *out = cdev->s;
1424         return 0;
1425
1426 err_cdev:
1427         kmscon_cdev_destroy(cdev);
1428 err_free:
1429         free(cdev);
1430         return ret;
1431 }