mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
Set up pseudo terminal and fork slave
This commit is contained in:
parent
4de6a8ad38
commit
acda4d2d31
4 changed files with 127 additions and 7 deletions
62
main.c
62
main.c
|
|
@ -2,7 +2,9 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
|
|
@ -12,7 +14,9 @@
|
||||||
#define LOG_MODULE "main"
|
#define LOG_MODULE "main"
|
||||||
#define LOG_ENABLE_DBG 1
|
#define LOG_ENABLE_DBG 1
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#include "shm.h"
|
#include "shm.h"
|
||||||
|
#include "slave.h"
|
||||||
|
|
||||||
struct wayland {
|
struct wayland {
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
|
|
@ -27,6 +31,7 @@ struct wayland {
|
||||||
|
|
||||||
struct context {
|
struct context {
|
||||||
bool quit;
|
bool quit;
|
||||||
|
int ptmx;
|
||||||
struct wayland wl;
|
struct wayland wl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -71,7 +76,7 @@ static void
|
||||||
handle_global(void *data, struct wl_registry *registry,
|
handle_global(void *data, struct wl_registry *registry,
|
||||||
uint32_t name, const char *interface, uint32_t version)
|
uint32_t name, const char *interface, uint32_t version)
|
||||||
{
|
{
|
||||||
LOG_DBG("global: %s", interface);
|
//LOG_DBG("global: %s", interface);
|
||||||
struct context *c = data;
|
struct context *c = data;
|
||||||
|
|
||||||
if (strcmp(interface, wl_compositor_interface.name) == 0) {
|
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)
|
int32_t width, int32_t height, struct wl_array *states)
|
||||||
{
|
{
|
||||||
//struct context *c = data;
|
//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)
|
if (width <= 0 || height <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -169,7 +174,7 @@ static void
|
||||||
xdg_surface_configure(void *data, struct xdg_surface *xdg_surface,
|
xdg_surface_configure(void *data, struct xdg_surface *xdg_surface,
|
||||||
uint32_t serial)
|
uint32_t serial)
|
||||||
{
|
{
|
||||||
LOG_DBG("xdg-surface: configure");
|
//LOG_DBG("xdg-surface: configure");
|
||||||
xdg_surface_ack_configure(xdg_surface, serial);
|
xdg_surface_ack_configure(xdg_surface, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -196,9 +201,15 @@ main(int argc, const char *const *argv)
|
||||||
|
|
||||||
struct context c = {
|
struct context c = {
|
||||||
.quit = false,
|
.quit = false,
|
||||||
|
.ptmx = posix_openpt(O_RDWR | O_NOCTTY),
|
||||||
.wl = {0},
|
.wl = {0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (c.ptmx == -1) {
|
||||||
|
LOG_ERRNO("failed to open pseudo terminal");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
c.wl.display = wl_display_connect(NULL);
|
c.wl.display = wl_display_connect(NULL);
|
||||||
if (c.wl.display == NULL) {
|
if (c.wl.display == NULL) {
|
||||||
LOG_ERR("failed to connect to wayland; no compositor running?");
|
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);
|
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) {
|
while (!c.quit) {
|
||||||
struct pollfd fds[] = {
|
struct pollfd fds[] = {
|
||||||
{.fd = wl_display_get_fd(c.wl.display), .events = POLLIN},
|
{.fd = wl_display_get_fd(c.wl.display), .events = POLLIN},
|
||||||
|
{.fd = c.ptmx, .events = POLLIN},
|
||||||
};
|
};
|
||||||
|
|
||||||
wl_display_flush(c.wl.display);
|
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) {
|
if (fds[0].revents & POLLHUP) {
|
||||||
LOG_WARN("disconnected from wayland");
|
LOG_WARN("disconnected from wayland");
|
||||||
break;
|
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:
|
out:
|
||||||
shm_fini();
|
shm_fini();
|
||||||
|
|
@ -289,6 +334,9 @@ out:
|
||||||
if (c.wl.display != NULL)
|
if (c.wl.display != NULL)
|
||||||
wl_display_disconnect(c.wl.display);
|
wl_display_disconnect(c.wl.display);
|
||||||
|
|
||||||
|
if (c.ptmx != -1)
|
||||||
|
close(c.ptmx);
|
||||||
|
|
||||||
cairo_debug_reset_static_data();
|
cairo_debug_reset_static_data();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ executable(
|
||||||
'log.c', 'log.h',
|
'log.c', 'log.h',
|
||||||
'main.c',
|
'main.c',
|
||||||
'shm.c', 'shm.h',
|
'shm.c', 'shm.h',
|
||||||
|
'slave.c', 'slave.h',
|
||||||
'tllist.h',
|
'tllist.h',
|
||||||
wl_proto_src + wl_proto_headers,
|
wl_proto_src + wl_proto_headers,
|
||||||
dependencies: [cairo, cairo_ft, fontconfig, wayland_client, wayland_cursor, xkb],
|
dependencies: [cairo, cairo_ft, fontconfig, wayland_client, wayland_cursor, xkb],
|
||||||
|
|
|
||||||
67
slave.c
Normal file
67
slave.c
Normal 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
4
slave.h
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
void slave_spawn(int ptmx);
|
||||||
Loading…
Add table
Add a link
Reference in a new issue