commit 6ba5dbba0ae24afbb2f68251959abddba9647e24 from: Onana Onana Xavier Manuel date: Wed Aug 12 03:59:54 2026 UTC Implemented first level nesting with button 3 and exit kill/pkill -9. ria can also reclaim RIA_SOCK_PATH after kill -9. commit - ee1d108f5e904a480f409dc7720c9b46edb992f2 commit + 6ba5dbba0ae24afbb2f68251959abddba9647e24 blob - a8309bdc5f78d1162658f15c2d6cd903e4b40c3b blob + 1d79f2a4e0cb8b8b042f9b0322cfe6837078fdc6 --- ria/ria.c +++ ria/ria.c @@ -31,7 +31,6 @@ main() { struct stat pstat; struct event ev; - int ret; signal(SIGTERM, int_handler); signal(SIGINT, int_handler); @@ -59,10 +58,7 @@ main() fill(0xFF7F7F7F); draw_cursor(); - while (running) { - if ((ret = wsctl_run()) == -1) - break; - + while (wsctl_run() != -1 && running) { while (event_pop(&ev) != -1) { switch (ev.type) { case EVENT_TYPE_KEYBOARD: blob - 32eefef87d805428144c1408a4049ca5bad0cbad blob + 2e378abe7bf09690301f53a6e189f70c253d6495 --- ria/wsctl.c +++ ria/wsctl.c @@ -6,9 +6,13 @@ #include #include #include +#include +#include +#include #include #include +#include #include #include @@ -30,15 +34,19 @@ static int read_cmd(void); static int sock_init(void); static void sock_exit(void); static int add_fd(int, int); +static int remove_fd(int); enum fdtype { FD_MOUSE, FD_KEYBOARD, + FD_MASTER, + FD_SLAVE, FD_PROTOCOL, }; struct fdinfo { int fd; + pid_t pid; /* This is only useful for FD_SLAVE */ enum fdtype type; }; @@ -193,12 +201,20 @@ wsctl_exit() } } - free(wsctl.pfinfo); - free(wsctl.pfds); - close(wsctl.mouse.fd); + while (wsctl.pflen > 0) { + int type = wsctl.pfinfo[wsctl.pflen - 1].type; + int pid = wsctl.pfinfo[wsctl.pflen - 1].pid; + int fd = wsctl.pfinfo[wsctl.pflen - 1].fd; + int status; + + if (type == FD_SLAVE) { + kill(pid, SIGTERM); + if (waitpid(pid, &status, 0) == -1) + perror("waitpid"); + } + remove_fd(fd); + } free(fb->bdat); - close(wsctl.kbd.fd); - close(wsctl.fd); free(fb); sock_exit(); } @@ -236,8 +252,28 @@ wsctl_run() case FD_PROTOCOL: read_cmd(); break; + /* + * Information exchange between nested instance and + * their parents happen here. + */ + case FD_MASTER: + break; + case FD_SLAVE: + break; } } + + if (pfd->revents & POLLHUP) { + if (info->type == FD_SLAVE) { + int status; + + /* Making sure no zombie process stays */ + if (waitpid(info->pid, &status, WNOHANG) == info->pid) { + remove_fd(pfd->fd); + i--; + } + } + } } return 0; @@ -246,6 +282,70 @@ wsctl_run() int wsctl_fork() { + int sv[2]; + int pid; + + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, sv) == -1) + return -1; + + if ((pid = fork()) == -1) + return -1; + + if (pid == 0) { + pid_t shell; + int master; + int ret; + + remove_fd(wsctl.mouse.fd); + remove_fd(wsctl.kbd.fd); + remove_fd(wsctl.sock.fd); + remove_fd(wsctl.fd); + munmap(fb->dat, fb->bytes); + free(fb->bdat); + close(sv[0]); + + shell = forkpty(&master, NULL, NULL, NULL); + fprintf(stderr, "forkpty: master=%d, shell=%d\n", master, shell); + + if (shell == -1) { + perror("forkpty"); + close(sv[1]); + _exit(1); + } + + if (shell == 0) { + setpgid(0, 0); + execl("/bin/ksh", "ksh",(char *) NULL); + _exit(1); + } + + struct pollfd pfd = { + .fd = sv[1], + .events = POLLIN, + }; + + while (1) { + if ((ret = poll(&pfd, 1, -1)) == -1) + break; + + if (pfd.revents & (POLLHUP | POLLERR)) { + if (kill(-shell, SIGTERM) == -1) + perror("kill"); + if (waitpid(shell, NULL, 0) == -1) + perror("waitpid"); + break; + } + } + printf("Death\n"); + close(master); + close(sv[1]); + _exit(0); + } + + close(sv[1]); + int idx = add_fd(sv[0], FD_SLAVE); + wsctl.pfinfo[idx].pid = pid; + return 0; } @@ -269,6 +369,39 @@ add_fd(int fd, int type) wsctl.pfds = pfds; wsctl.pflen++; + return idx; +} + +static int +remove_fd(int fd) +{ + struct fdinfo *infos; + struct pollfd *pfds; + int idx = -1; + + for (int i = 0; i < wsctl.pflen; i++) { + if (wsctl.pfds[i].fd == fd) { + idx = i; + break; + } + } + + if (idx == -1) return 0; + + close(wsctl.pfds[idx].fd); + wsctl.pflen--; + + if (idx < wsctl.pflen) { + wsctl.pfinfo[idx] = wsctl.pfinfo[wsctl.pflen]; + wsctl.pfds[idx] = wsctl.pfds[wsctl.pflen]; + } + + infos = reallocarray(wsctl.pfinfo, sizeof(*wsctl.pfinfo), wsctl.pflen); + pfds = reallocarray(wsctl.pfds, sizeof(*wsctl.pfds), wsctl.pflen); + + wsctl.pfinfo = infos; + wsctl.pfds = pfds; + return 0; } @@ -462,8 +595,31 @@ sock_init() wsctl.sock.len = sizeof(wsctl.sock.addr); if (bind(wsctl.sock.fd, (struct sockaddr *)&wsctl.sock.addr, wsctl.sock.len) == -1) { - close(wsctl.sock.fd); - return -1; + /* socket exists and might be in use */ + if (errno != EADDRINUSE) { + close(wsctl.sock.fd); + return -1; + } + + int check = socket(AF_UNIX, SOCK_STREAM, 0); + if (check == -1) { + close(wsctl.sock.fd); + return -1; + } + + if (connect(check, (struct sockaddr *)&wsctl.sock.addr, wsctl.sock.len) == 0) { + errno = EADDRINUSE; + close(wsctl.sock.fd); + close(check); + return -1; + } + + close(check); + unlink(RIA_SOCK_PATH); + + if (bind(wsctl.sock.fd, (struct sockaddr *)&wsctl.sock.addr, wsctl.sock.len)) { + return -1; + } } if (listen(wsctl.sock.fd, SOMAXCONN)) {