Set up pseudo terminal and fork slave

This commit is contained in:
Daniel Eklöf 2019-06-13 15:19:10 +02:00
parent 4de6a8ad38
commit acda4d2d31
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
4 changed files with 127 additions and 7 deletions

62
main.c
View file

@ -2,7 +2,9 @@
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <poll.h>
@ -12,7 +14,9 @@
#define LOG_MODULE "main"
#define LOG_ENABLE_DBG 1
#include "log.h"
#include "shm.h"
#include "slave.h"
struct wayland {
struct wl_display *display;
@ -27,6 +31,7 @@ struct wayland {
struct context {
bool quit;
int ptmx;
struct wayland wl;
};
@ -71,7 +76,7 @@ static void
handle_global(void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version)
{
LOG_DBG("global: %s", interface);
//LOG_DBG("global: %s", interface);
struct context *c = data;
if (strcmp(interface, wl_compositor_interface.name) == 0) {
@ -144,7 +149,7 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
int32_t width, int32_t height, struct wl_array *states)
{
//struct context *c = data;
LOG_DBG("xdg-toplevel: configure: %dx%d", width, height);
//LOG_DBG("xdg-toplevel: configure: %dx%d", width, height);
if (width <= 0 || height <= 0)
return;
@ -169,7 +174,7 @@ static void
xdg_surface_configure(void *data, struct xdg_surface *xdg_surface,
uint32_t serial)
{
LOG_DBG("xdg-surface: configure");
//LOG_DBG("xdg-surface: configure");
xdg_surface_ack_configure(xdg_surface, serial);
}
@ -196,9 +201,15 @@ main(int argc, const char *const *argv)
struct context c = {
.quit = false,
.ptmx = posix_openpt(O_RDWR | O_NOCTTY),
.wl = {0},
};
if (c.ptmx == -1) {
LOG_ERRNO("failed to open pseudo terminal");
goto out;
}
c.wl.display = wl_display_connect(NULL);
if (c.wl.display == NULL) {
LOG_ERR("failed to connect to wayland; no compositor running?");
@ -252,23 +263,57 @@ main(int argc, const char *const *argv)
wl_display_dispatch_pending(c.wl.display);
pid_t pid = fork();
switch (pid) {
case -1:
LOG_ERRNO("failed to fork");
goto out;
case 0:
/* Child */
slave_spawn(c.ptmx);
assert(false);
break;
default:
LOG_DBG("slave has PID %d", pid);
break;
}
while (!c.quit) {
struct pollfd fds[] = {
{.fd = wl_display_get_fd(c.wl.display), .events = POLLIN},
{.fd = c.ptmx, .events = POLLIN},
};
wl_display_flush(c.wl.display);
poll(fds, 1, -1);
poll(fds, sizeof(fds) / sizeof(fds[0]), -1);
if (fds[0].revents & POLLIN) {
wl_display_dispatch(c.wl.display);
}
if (fds[0].revents & POLLHUP) {
LOG_WARN("disconnected from wayland");
break;
}
wl_display_dispatch(c.wl.display);
}
if (fds[1].revents & POLLIN) {
char data[1024];
ssize_t count = read(c.ptmx, data, sizeof(data));
if (count < 0) {
LOG_ERRNO("failed to read from pseudo terminal");
break;
}
ret = EXIT_SUCCESS;
LOG_DBG("%.*s", (int)count, data);
}
if (fds[1].revents & POLLHUP) {
ret = EXIT_SUCCESS;
break;
}
}
out:
shm_fini();
@ -289,6 +334,9 @@ out:
if (c.wl.display != NULL)
wl_display_disconnect(c.wl.display);
if (c.ptmx != -1)
close(c.ptmx);
cairo_debug_reset_static_data();
return ret;
}

View file

@ -56,6 +56,7 @@ executable(
'log.c', 'log.h',
'main.c',
'shm.c', 'shm.h',
'slave.c', 'slave.h',
'tllist.h',
wl_proto_src + wl_proto_headers,
dependencies: [cairo, cairo_ft, fontconfig, wayland_client, wayland_cursor, xkb],

67
slave.c Normal file
View file

@ -0,0 +1,67 @@
#define _XOPEN_SOURCE 500
#include "slave.h"
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#define LOG_MODULE "slave"
#define LOG_ENABLE_DBG 1
#include "log.h"
void
slave_spawn(int ptmx)
{
int pts = -1;
const char *pts_name = ptsname(ptmx);
if (grantpt(ptmx) == -1) {
LOG_ERRNO("failed to grantpt()");
goto err;
}
if (unlockpt(ptmx) == -1) {
LOG_ERRNO("failed to unlockpt()");
goto err;
}
close(ptmx);
ptmx = -1;
if (setsid() == -1) {
LOG_ERRNO("failed to setsid()");
goto err;
}
pts = open(pts_name, O_RDWR);
if (pts == -1) {
LOG_ERRNO("failed to open pseudo terminal slave device");
goto err;
}
if (dup2(pts, STDIN_FILENO) == -1 ||
dup2(pts, STDOUT_FILENO) == -1 ||
dup2(pts, STDERR_FILENO) == -1)
{
LOG_ERRNO("failed to dup stdin/stdout/stderr");
goto err;
}
close(pts);
pts = -1;
/* TODO: exec() */
const char *s = "hello world\n";
write(STDOUT_FILENO, s, strlen(s));
sleep(1000);
err:
if (pts != -1)
close(pts);
if (ptmx != -1)
close(ptmx);
_exit(errno);
}

4
slave.h Normal file
View file

@ -0,0 +1,4 @@
#pragma once
#include <stdbool.h>
void slave_spawn(int ptmx);