blob: 5c26464136eab3f8d234415f9d5f4427ffaaee5f [file] [log] [blame]
Benjamin Franzkebfeda132012-01-30 14:04:04 +01001/*
2 * Copyright © 2012 Benjamin Franzke
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
Benjamin Franzkebfeda132012-01-30 14:04:04 +010023#include "config.h"
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <assert.h>
29#include <errno.h>
30
31#include <error.h>
32#include <getopt.h>
33
34#include <sys/types.h>
35#include <sys/ioctl.h>
36#include <sys/stat.h>
37#include <sys/wait.h>
38#include <sys/socket.h>
39#include <sys/epoll.h>
40#include <sys/signalfd.h>
41#include <signal.h>
42#include <unistd.h>
43#include <fcntl.h>
44
45#include <termios.h>
46#include <linux/vt.h>
47#include <linux/major.h>
48
49#include <pwd.h>
50#include <grp.h>
51#include <security/pam_appl.h>
52
53#include <xf86drm.h>
54
55#ifdef HAVE_SYSTEMD_LOGIN
56#include <systemd/sd-login.h>
57#endif
58
59#include "weston-launch.h"
60
Quentin Glidicff323092013-05-17 16:20:37 +020061#define MAX_ARGV_SIZE 256
62
Benjamin Franzkebfeda132012-01-30 14:04:04 +010063struct weston_launch {
64 struct pam_conv pc;
65 pam_handle_t *ph;
66 int tty;
67 int ttynr;
68 int sock[2];
69 struct passwd *pw;
70
71 int epollfd;
72 int signalfd;
73
74 pid_t child;
75 int verbose;
76};
77
Kristian Høgsberg9e140912012-04-10 01:26:18 -040078union cmsg_data { unsigned char b[4]; int fd; };
79
Benjamin Franzkebfeda132012-01-30 14:04:04 +010080static gid_t *
81read_groups(void)
82{
83 int n;
84 gid_t *groups;
85
86 n = getgroups(0, NULL);
Rob Bradford40be7b42012-12-05 18:47:11 +000087
88 if (n < 0) {
89 fprintf(stderr, "Unable to retrieve groups: %m\n");
90 return NULL;
91 }
92
Benjamin Franzkebfeda132012-01-30 14:04:04 +010093 groups = malloc(n * sizeof(gid_t));
94 if (!groups)
95 return NULL;
96
97 if (getgroups(n, groups) < 0) {
Rob Bradford40be7b42012-12-05 18:47:11 +000098 fprintf(stderr, "Unable to retrieve groups: %m\n");
Benjamin Franzkebfeda132012-01-30 14:04:04 +010099 free(groups);
100 return NULL;
101 }
102 return groups;
103}
104
105static int
106weston_launch_allowed(struct weston_launch *wl)
107{
108 struct group *gr;
109 gid_t *groups;
110 int i;
111#ifdef HAVE_SYSTEMD_LOGIN
112 char *session, *seat;
113 int err;
114#endif
115
116 if (getuid() == 0)
117 return 1;
118
119 gr = getgrnam("weston-launch");
120 if (gr) {
121 groups = read_groups();
122 if (groups) {
123 for (i = 0; groups[i]; ++i) {
124 if (groups[i] == gr->gr_gid) {
125 free(groups);
126 return 1;
127 }
128 }
129 free(groups);
130 }
131 }
132
133#ifdef HAVE_SYSTEMD_LOGIN
134 err = sd_pid_get_session(getpid(), &session);
135 if (err == 0 && session) {
136 if (sd_session_is_active(session) &&
137 sd_session_get_seat(session, &seat) == 0) {
138 free(seat);
139 free(session);
140 return 1;
141 }
142 free(session);
143 }
144#endif
145
146 return 0;
147}
148
149static int
150pam_conversation_fn(int msg_count,
151 const struct pam_message **messages,
152 struct pam_response **responses,
153 void *user_data)
154{
155 return PAM_SUCCESS;
156}
157
158static int
159setup_pam(struct weston_launch *wl)
160{
161 int err;
162
163 wl->pc.conv = pam_conversation_fn;
164 wl->pc.appdata_ptr = wl;
165
166 err = pam_start("login", wl->pw->pw_name, &wl->pc, &wl->ph);
John Kåre Alsaker5b90d8f2012-10-12 12:25:05 +0200167 if (err != PAM_SUCCESS) {
168 fprintf(stderr, "failed to start pam transaction: %d: %s\n",
169 err, pam_strerror(wl->ph, err));
170 return -1;
171 }
172
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100173 err = pam_set_item(wl->ph, PAM_TTY, ttyname(wl->tty));
174 if (err != PAM_SUCCESS) {
175 fprintf(stderr, "failed to set PAM_TTY item: %d: %s\n",
176 err, pam_strerror(wl->ph, err));
177 return -1;
178 }
179
180 err = pam_open_session(wl->ph, 0);
181 if (err != PAM_SUCCESS) {
182 fprintf(stderr, "failed to open pam session: %d: %s\n",
183 err, pam_strerror(wl->ph, err));
184 return -1;
185 }
186
187 return 0;
188}
189
190static int
191setup_launcher_socket(struct weston_launch *wl)
192{
193 struct epoll_event ev;
194
195 if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, wl->sock) < 0)
196 error(1, errno, "socketpair failed");
197
198 fcntl(wl->sock[0], F_SETFD, O_CLOEXEC);
199
200 memset(&ev, 0, sizeof ev);
201 ev.events = EPOLLIN;
202 ev.data.fd = wl->sock[0];
203 if (epoll_ctl(wl->epollfd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0)
204 return -errno;
205
206 return 0;
207}
208
209static int
210setup_signals(struct weston_launch *wl)
211{
Philipp Brüschweilerff253122013-03-09 19:38:56 +0100212 int ret;
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100213 sigset_t mask;
214 struct sigaction sa;
215 struct epoll_event ev;
216
217 memset(&sa, 0, sizeof sa);
218 sa.sa_handler = SIG_DFL;
219 sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
Philipp Brüschweilerff253122013-03-09 19:38:56 +0100220 ret = sigaction(SIGCHLD, &sa, NULL);
221 assert(ret == 0);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100222
Kristian Høgsberg18684d42013-07-22 11:59:18 -0700223 sa.sa_handler = SIG_IGN;
224 sa.sa_flags = 0;
225 sigaction(SIGHUP, &sa, NULL);
226
Philipp Brüschweilerff253122013-03-09 19:38:56 +0100227 ret = sigemptyset(&mask);
228 assert(ret == 0);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100229 sigaddset(&mask, SIGCHLD);
230 sigaddset(&mask, SIGINT);
231 sigaddset(&mask, SIGTERM);
Philipp Brüschweilerff253122013-03-09 19:38:56 +0100232 ret = sigprocmask(SIG_BLOCK, &mask, NULL);
233 assert(ret == 0);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100234
235 wl->signalfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
236 if (wl->signalfd < 0)
237 return -errno;
238
239 memset(&ev, 0, sizeof ev);
240 ev.events = EPOLLIN;
241 ev.data.fd = wl->signalfd;
242 if (epoll_ctl(wl->epollfd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0)
243 return -errno;
244
245 return 0;
246}
247
248static void
249setenv_fd(const char *env, int fd)
250{
251 char buf[32];
252
253 snprintf(buf, sizeof buf, "%d", fd);
254 setenv(env, buf, 1);
255}
256
257static int
258handle_setmaster(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
259{
Kristian Høgsberg9e140912012-04-10 01:26:18 -0400260 int ret = -1;
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100261 struct cmsghdr *cmsg;
262 struct weston_launcher_set_master *message;
Kristian Høgsberg9e140912012-04-10 01:26:18 -0400263 union cmsg_data *data;
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100264
265 if (len != sizeof(*message)) {
266 error(0, 0, "missing value in setmaster request");
267 goto out;
268 }
269
270 message = msg->msg_iov->iov_base;
271
272 cmsg = CMSG_FIRSTHDR(msg);
273 if (!cmsg ||
274 cmsg->cmsg_level != SOL_SOCKET ||
275 cmsg->cmsg_type != SCM_RIGHTS) {
276 error(0, 0, "invalid control message");
277 goto out;
278 }
279
Kristian Høgsberg9e140912012-04-10 01:26:18 -0400280 data = (union cmsg_data *) CMSG_DATA(cmsg);
281 if (data->fd == -1) {
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100282 error(0, 0, "missing drm fd in socket request");
283 goto out;
284 }
285
286 if (message->set_master)
Kristian Høgsberg9e140912012-04-10 01:26:18 -0400287 ret = drmSetMaster(data->fd);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100288 else
Kristian Høgsberg9e140912012-04-10 01:26:18 -0400289 ret = drmDropMaster(data->fd);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100290
Kristian Høgsberg9e140912012-04-10 01:26:18 -0400291 close(data->fd);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100292out:
293 do {
294 len = send(wl->sock[0], &ret, sizeof ret, 0);
295 } while (len < 0 && errno == EINTR);
296 if (len < 0)
297 return -1;
298
299 return 0;
300}
301
302static int
303handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
304{
305 int fd = -1, ret = -1;
306 char control[CMSG_SPACE(sizeof(fd))];
307 struct cmsghdr *cmsg;
308 struct stat s;
309 struct msghdr nmsg;
310 struct iovec iov;
311 struct weston_launcher_open *message;
Kristian Høgsberg9e140912012-04-10 01:26:18 -0400312 union cmsg_data *data;
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100313
314 message = msg->msg_iov->iov_base;
315 if ((size_t)len < sizeof(*message))
316 goto err0;
317
318 /* Ensure path is null-terminated */
319 ((char *) message)[len-1] = '\0';
320
321 if (stat(message->path, &s) < 0)
322 goto err0;
323
324 fd = open(message->path, message->flags);
Rob Bradfordd33f2b02013-05-20 16:55:10 +0100325 if (fd < 0) {
326 fprintf(stderr, "Error opening device %s: %m\n",
327 message->path);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100328 goto err0;
Rob Bradfordd33f2b02013-05-20 16:55:10 +0100329 }
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100330
331 if (major(s.st_rdev) != INPUT_MAJOR) {
332 close(fd);
333 fd = -1;
Rob Bradfordd33f2b02013-05-20 16:55:10 +0100334 fprintf(stderr, "Device %s is not an input device\n",
335 message->path);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100336 goto err0;
337 }
338
339err0:
340 memset(&nmsg, 0, sizeof nmsg);
341 nmsg.msg_iov = &iov;
342 nmsg.msg_iovlen = 1;
343 if (fd != -1) {
344 nmsg.msg_control = control;
345 nmsg.msg_controllen = sizeof control;
346 cmsg = CMSG_FIRSTHDR(&nmsg);
347 cmsg->cmsg_level = SOL_SOCKET;
348 cmsg->cmsg_type = SCM_RIGHTS;
349 cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
Kristian Høgsberg9e140912012-04-10 01:26:18 -0400350 data = (union cmsg_data *) CMSG_DATA(cmsg);
351 data->fd = fd;
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100352 nmsg.msg_controllen = cmsg->cmsg_len;
353 ret = 0;
354 }
355 iov.iov_base = &ret;
356 iov.iov_len = sizeof ret;
357
358 if (wl->verbose)
359 fprintf(stderr, "weston-launch: opened %s: ret: %d, fd: %d\n",
360 message->path, ret, fd);
361 do {
362 len = sendmsg(wl->sock[0], &nmsg, 0);
363 } while (len < 0 && errno == EINTR);
364
365 if (len < 0)
366 return -1;
367
368 return 0;
369}
370
371static int
372handle_socket_msg(struct weston_launch *wl)
373{
374 char control[CMSG_SPACE(sizeof(int))];
375 char buf[BUFSIZ];
376 struct msghdr msg;
377 struct iovec iov;
378 int ret = -1;
379 ssize_t len;
380 struct weston_launcher_message *message;
381
382 memset(&msg, 0, sizeof(msg));
383 iov.iov_base = buf;
384 iov.iov_len = sizeof buf;
385 msg.msg_iov = &iov;
386 msg.msg_iovlen = 1;
387 msg.msg_control = control;
388 msg.msg_controllen = sizeof control;
389
390 do {
391 len = recvmsg(wl->sock[0], &msg, 0);
392 } while (len < 0 && errno == EINTR);
393
394 if (len < 1)
395 return -1;
396
397 message = (void *) buf;
398 switch (message->opcode) {
399 case WESTON_LAUNCHER_OPEN:
400 ret = handle_open(wl, &msg, len);
401 break;
402 case WESTON_LAUNCHER_DRM_SET_MASTER:
403 ret = handle_setmaster(wl, &msg, len);
404 break;
405 }
406
407 return ret;
408}
409
410static void
411quit(struct weston_launch *wl, int status)
412{
413 int err;
414
415 close(wl->epollfd);
416 close(wl->signalfd);
417 close(wl->sock[0]);
418
419 err = pam_close_session(wl->ph, 0);
420 if (err)
421 fprintf(stderr, "pam_close_session failed: %d: %s\n",
422 err, pam_strerror(wl->ph, err));
423 pam_end(wl->ph, err);
424
425 exit(status);
426}
427
428static int
429handle_signal(struct weston_launch *wl)
430{
431 struct signalfd_siginfo sig;
Philipp Brüschweiler7a3ec742013-03-10 15:14:01 +0100432 int pid, status, ret;
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100433
434 if (read(wl->signalfd, &sig, sizeof sig) != sizeof sig) {
435 error(0, errno, "reading signalfd failed");
436 return -1;
437 }
438
439 switch (sig.ssi_signo) {
440 case SIGCHLD:
441 pid = waitpid(-1, &status, 0);
442 if (pid == wl->child) {
443 wl->child = 0;
Philipp Brüschweiler7a3ec742013-03-10 15:14:01 +0100444 if (WIFEXITED(status))
445 ret = WEXITSTATUS(status);
446 else if (WIFSIGNALED(status))
447 /*
448 * If weston dies because of signal N, we
449 * return 10+N. This is distinct from
450 * weston-launch dying because of a signal
451 * (128+N).
452 */
453 ret = 10 + WTERMSIG(status);
454 else
455 ret = 0;
456 quit(wl, ret);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100457 }
458 break;
459 case SIGTERM:
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100460 case SIGINT:
461 if (wl->child)
Kristian Høgsberg1a81abb2013-06-17 15:23:20 -0400462 kill(wl->child, sig.ssi_signo);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100463 break;
464 default:
465 return -1;
466 }
467
468 return 0;
469}
470
471static int
472setup_tty(struct weston_launch *wl, const char *tty)
473{
474 struct stat buf;
475 char *t;
476
477 if (tty) {
478 t = ttyname(STDIN_FILENO);
479 if (t && strcmp(t, tty) == 0)
480 wl->tty = STDIN_FILENO;
481 else
482 wl->tty = open(tty, O_RDWR | O_NOCTTY);
483 } else {
484 int tty0 = open("/dev/tty0", O_WRONLY | O_CLOEXEC);
485 char filename[16];
486
487 if (tty0 < 0)
Tiago Vignatti314db6e2012-04-17 20:10:11 +0300488 error(1, errno, "could not open tty0");
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100489
490 if (ioctl(tty0, VT_OPENQRY, &wl->ttynr) < 0 || wl->ttynr == -1)
491 error(1, errno, "failed to find non-opened console");
492
493 snprintf(filename, sizeof filename, "/dev/tty%d", wl->ttynr);
494 wl->tty = open(filename, O_RDWR | O_NOCTTY);
495 close(tty0);
496 }
497
498 if (wl->tty < 0)
499 error(1, errno, "failed to open tty");
500
501 if (tty) {
502 if (fstat(wl->tty, &buf) < 0)
503 error(1, errno, "stat %s failed", tty);
504
505 if (major(buf.st_rdev) != TTY_MAJOR)
506 error(1, 0, "invalid tty device: %s", tty);
507
508 wl->ttynr = minor(buf.st_rdev);
509 }
510
511 return 0;
512}
513
514static void
Kristian Høgsbergca70f2f2013-07-19 21:25:20 -0700515launch_compositor(struct weston_launch *wl, int argc, char *argv[])
516{
517 char *child_argv[MAX_ARGV_SIZE];
518 char **env;
519 int i;
520
521 if (wl->verbose)
522 printf("weston-launch: spawned weston with pid: %d\n", getpid());
523 if (wl->tty != STDIN_FILENO) {
524 if (setsid() < 0)
525 error(1, errno, "setsid failed");
526 if (ioctl(wl->tty, TIOCSCTTY, 0) < 0)
527 error(1, errno, "TIOCSCTTY failed - tty is in use");
528 }
529
530 if (setgid(wl->pw->pw_gid) < 0 ||
531#ifdef HAVE_INITGROUPS
532 initgroups(wl->pw->pw_name, wl->pw->pw_gid) < 0 ||
533#endif
534 setuid(wl->pw->pw_uid) < 0)
535 error(1, errno, "dropping privileges failed");
536
Kristian Høgsbergca70f2f2013-07-19 21:25:20 -0700537 env = pam_getenvlist(wl->ph);
538 if (env) {
539 for (i = 0; env[i]; ++i) {
540 if (putenv(env[i]) < 0)
541 error(0, 0, "putenv %s failed", env[i]);
542 }
543 free(env);
544 }
545
546 if (wl->tty != STDIN_FILENO)
547 setenv_fd("WESTON_TTY_FD", wl->tty);
548
549 setenv_fd("WESTON_LAUNCHER_SOCK", wl->sock[1]);
550
551 unsetenv("DISPLAY");
552
553 child_argv[0] = wl->pw->pw_shell;
554 child_argv[1] = "-l";
555 child_argv[2] = "-c";
556 child_argv[3] = BINDIR "/weston \"$@\"";
557 child_argv[4] = "weston";
558 for (i = 0; i < argc; ++i)
559 child_argv[5 + i] = argv[i];
560 child_argv[5 + i] = NULL;
561
562 execv(child_argv[0], child_argv);
563 error(1, errno, "exec failed");
564}
565
566static void
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100567help(const char *name)
568{
569 fprintf(stderr, "Usage: %s [args...] [-- [weston args..]]\n", name);
570 fprintf(stderr, " -u, --user Start session as specified username\n");
Tiago Vignatti314db6e2012-04-17 20:10:11 +0300571 fprintf(stderr, " -t, --tty Start session on alternative tty\n");
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100572 fprintf(stderr, " -v, --verbose Be verbose\n");
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100573 fprintf(stderr, " -h, --help Display this help message\n");
574}
575
576int
577main(int argc, char *argv[])
578{
579 struct weston_launch wl;
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100580 int i, c;
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100581 char *tty = NULL, *new_user = NULL;
Quentin Glidicff323092013-05-17 16:20:37 +0200582 char *term;
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100583 struct option opts[] = {
584 { "user", required_argument, NULL, 'u' },
585 { "tty", required_argument, NULL, 't' },
586 { "verbose", no_argument, NULL, 'v' },
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100587 { "help", no_argument, NULL, 'h' },
588 { 0, 0, NULL, 0 }
589 };
590
591 memset(&wl, 0, sizeof wl);
592
Kristian Høgsbergab499942013-07-19 21:26:24 -0700593 while ((c = getopt_long(argc, argv, "u:t::vh", opts, &i)) != -1) {
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100594 switch (c) {
595 case 'u':
596 new_user = optarg;
597 if (getuid() != 0)
598 error(1, 0, "Permission denied. -u allowed for root only");
599 break;
600 case 't':
601 tty = optarg;
602 break;
603 case 'v':
604 wl.verbose = 1;
605 break;
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100606 case 'h':
Scott Moreaucc9acfc2013-01-21 23:40:59 -0700607 help("weston-launch");
Siddharth Heroord6be88b2013-03-12 02:36:52 +0530608 exit(EXIT_FAILURE);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100609 }
610 }
611
Ander Conselvan de Oliveira9bdfc482013-05-22 22:55:33 +0300612 if ((argc - optind) > (MAX_ARGV_SIZE - 6))
Quentin Glidicff323092013-05-17 16:20:37 +0200613 error(1, E2BIG, "Too many arguments to pass to weston");
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100614
615 if (new_user)
616 wl.pw = getpwnam(new_user);
617 else
618 wl.pw = getpwuid(getuid());
619 if (wl.pw == NULL)
620 error(1, errno, "failed to get username");
621
Quentin Glidicff323092013-05-17 16:20:37 +0200622 term = getenv("TERM");
Kristian Høgsberg272d2432013-01-29 14:14:06 -0500623 clearenv();
Quentin Glidicff323092013-05-17 16:20:37 +0200624 setenv("TERM", term, 1);
Kristian Høgsberg272d2432013-01-29 14:14:06 -0500625 setenv("USER", wl.pw->pw_name, 1);
626 setenv("LOGNAME", wl.pw->pw_name, 1);
627 setenv("HOME", wl.pw->pw_dir, 1);
628 setenv("SHELL", wl.pw->pw_shell, 1);
629
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100630 if (!weston_launch_allowed(&wl))
Tiago Vignatti314db6e2012-04-17 20:10:11 +0300631 error(1, 0, "Permission denied. You should either:\n"
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100632#ifdef HAVE_SYSTEMD_LOGIN
633 " - run from an active and local (systemd) session.\n"
634#else
635 " - enable systemd session support for weston-launch.\n"
636#endif
Tiago Vignatti314db6e2012-04-17 20:10:11 +0300637 " - or add yourself to the 'weston-launch' group.");
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100638
639 if (setup_tty(&wl, tty) < 0)
Siddharth Heroord6be88b2013-03-12 02:36:52 +0530640 exit(EXIT_FAILURE);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100641
642 if (setup_pam(&wl) < 0)
Siddharth Heroord6be88b2013-03-12 02:36:52 +0530643 exit(EXIT_FAILURE);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100644
645 wl.epollfd = epoll_create1(EPOLL_CLOEXEC);
646 if (wl.epollfd < 0)
647 error(1, errno, "epoll create failed");
648
649 if (setup_launcher_socket(&wl) < 0)
Siddharth Heroord6be88b2013-03-12 02:36:52 +0530650 exit(EXIT_FAILURE);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100651
652 if (setup_signals(&wl) < 0)
Siddharth Heroord6be88b2013-03-12 02:36:52 +0530653 exit(EXIT_FAILURE);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100654
Kristian Høgsbergca70f2f2013-07-19 21:25:20 -0700655 wl.child = fork();
656 if (wl.child == -1) {
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100657 error(1, errno, "fork failed");
Kristian Høgsbergca70f2f2013-07-19 21:25:20 -0700658 exit(EXIT_FAILURE);
659 }
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100660
Kristian Høgsbergca70f2f2013-07-19 21:25:20 -0700661 if (wl.child == 0)
662 launch_compositor(&wl, argc - optind, argv + optind);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100663
Kristian Høgsbergca70f2f2013-07-19 21:25:20 -0700664 close(wl.sock[1]);
665 if (wl.tty != STDIN_FILENO)
666 close(wl.tty);
Quentin Glidic735302e2013-06-19 15:27:11 +0200667
Kristian Høgsbergca70f2f2013-07-19 21:25:20 -0700668 while (1) {
669 struct epoll_event ev;
670 int n;
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100671
Kristian Høgsbergca70f2f2013-07-19 21:25:20 -0700672 n = epoll_wait(wl.epollfd, &ev, 1, -1);
673 if (n < 0)
674 error(0, errno, "epoll_wait failed");
675 if (n != 1)
676 continue;
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100677
Kristian Høgsbergca70f2f2013-07-19 21:25:20 -0700678 if (ev.data.fd == wl.sock[0])
679 handle_socket_msg(&wl);
680 else if (ev.data.fd == wl.signalfd)
681 handle_signal(&wl);
Benjamin Franzkebfeda132012-01-30 14:04:04 +0100682 }
683
684 return 0;
685}