From 2659326de3bfef3f32c9618f082f22b22c42f9aa Mon Sep 17 00:00:00 2001 From: Kris <1611248+Rinzwind@users.noreply.github.com> Date: Sat, 10 Feb 2024 16:22:48 +0100 Subject: [PATCH 1/6] Added library with a function to spawn a process connected to a pseudo-terminal. --- CMakeLists.txt | 4 ++++ tty/tty.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 tty/tty.c diff --git a/CMakeLists.txt b/CMakeLists.txt index afafbcb421..43fd9d2c5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -571,6 +571,10 @@ add_subdirectory(ffiTestLibrary ${CMAKE_CURRENT_BINARY_DIR}/build/ffiTestLibrary # Handling Third party dependencies add_third_party_dependencies_per_platform() +if (UNIX) + addIndependentLibraryWithRPATH(tty ${CMAKE_CURRENT_SOURCE_DIR}/tty/tty.c) +endif() + # Packaging Setup include(cmake/packaging.cmake) diff --git a/tty/tty.c b/tty/tty.c new file mode 100644 index 0000000000..8032fddb56 --- /dev/null +++ b/tty/tty.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include +#include +#include + +#define CHECK_ERROR(exp) if ((exp) == -1) { printf("Error in %s at %s: %s\n", __func__, #exp, strerror(errno)); exit(1); } + +pid_t tty_spawn(int fdm, const char *path, char *const argv[], char *const envp[]) +{ + pid_t pid = fork(); + if (pid == 0) + { + int fds = open(ptsname(fdm), O_RDWR); + close(fdm); + close(0); + close(1); + close(2); + dup(fds); + dup(fds); + dup(fds); + close(fds); + CHECK_ERROR(setsid()); + CHECK_ERROR(ioctl(0, TIOCSCTTY, 0)); + CHECK_ERROR(execve(path, argv, envp)); + } + return pid; +} From 3a1bc2b3f20f991b4f23ad8c7a7ec74f26862eed Mon Sep 17 00:00:00 2001 From: Kris <1611248+Rinzwind@users.noreply.github.com> Date: Sun, 18 Feb 2024 01:10:58 +0100 Subject: [PATCH 2/6] =?UTF-8?q?Added=20comment=20to=20=E2=80=98tty=5Fspawn?= =?UTF-8?q?=E2=80=99=20describing=20its=20functionality=20and=20the=20moti?= =?UTF-8?q?vation=20for=20providing=20it=20through=20a=20library=20include?= =?UTF-8?q?d=20with=20the=20VM.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tty/tty.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tty/tty.c b/tty/tty.c index 8032fddb56..a6c0bf62a2 100644 --- a/tty/tty.c +++ b/tty/tty.c @@ -9,6 +9,25 @@ #define CHECK_ERROR(exp) if ((exp) == -1) { printf("Error in %s at %s: %s\n", __func__, #exp, strerror(errno)); exit(1); } pid_t tty_spawn(int fdm, const char *path, char *const argv[], char *const envp[]) + /* + Spawns a process as a session leader with a pseudo-terminal as + its controlling terminal, its standard file descriptors + referring to the terminal, and executing a file with the given + arguments and environment. The first argument is expected to + be a file descriptor referring to a master pseudo-terminal + device as returned by 'posix_openpt'. The next three arguments + should be given as expected by 'execve'. The process ID of the + new process is returned, or -1 if one could not be created. If + the process is created but fails to create the session, set + the controlling terminal or execute the file, it exits with + status 1 after printing an error message on the terminal that + indicates the call that failed. + + Provided through a library included with the VM to support + Pharo terminal emulators: it can only be partially replicated + through the FFI by using 'posix_spawn', as that seems to lack + a way to set the controlling terminal of the new process. + */ { pid_t pid = fork(); if (pid == 0) From ec4b863f808247100a7ed0c87693dfb3c847ad2b Mon Sep 17 00:00:00 2001 From: Kris <1611248+Rinzwind@users.noreply.github.com> Date: Sun, 18 Feb 2024 01:40:46 +0100 Subject: [PATCH 3/6] =?UTF-8?q?Added=20definition=20for=20=E2=80=98=5FXOPE?= =?UTF-8?q?N=5FSOURCE=E2=80=99=20to=20=E2=80=98tty.c=E2=80=99.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tty/tty.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tty/tty.c b/tty/tty.c index a6c0bf62a2..5eceb26077 100644 --- a/tty/tty.c +++ b/tty/tty.c @@ -1,3 +1,7 @@ +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 500 +#endif + #include #include #include From 10c9f57389a61effd718fceeceee34c26b09b3b4 Mon Sep 17 00:00:00 2001 From: Kris <1611248+Rinzwind@users.noreply.github.com> Date: Sun, 18 Feb 2024 10:12:25 +0100 Subject: [PATCH 4/6] =?UTF-8?q?Made=20=E2=80=98tty=5Fspawn=E2=80=99=20also?= =?UTF-8?q?=20check=20for=20errors=20when=20opening=20the=20slave=20pseudo?= =?UTF-8?q?-terminal=20device=20and=20setting=20up=20the=20standard=20file?= =?UTF-8?q?=20descriptors.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tty/tty.c | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/tty/tty.c b/tty/tty.c index 5eceb26077..933327e603 100644 --- a/tty/tty.c +++ b/tty/tty.c @@ -10,7 +10,19 @@ #include #include -#define CHECK_ERROR(exp) if ((exp) == -1) { printf("Error in %s at %s: %s\n", __func__, #exp, strerror(errno)); exit(1); } +#define CHECK_NULL(exp) \ + if ((exp) == NULL) { \ + exit(1); \ + } +#define CHECK_ERROR(exp) \ + if ((exp) == -1) { \ + exit(1); \ + } +#define CHECK_ERROR_PRINT(exp) \ + if ((exp) == -1) { \ + printf("Error in %s at %s: %s\n", __func__, #exp, strerror(errno)); \ + exit(1); \ + } pid_t tty_spawn(int fdm, const char *path, char *const argv[], char *const envp[]) /* @@ -22,10 +34,12 @@ pid_t tty_spawn(int fdm, const char *path, char *const argv[], char *const envp[ device as returned by 'posix_openpt'. The next three arguments should be given as expected by 'execve'. The process ID of the new process is returned, or -1 if one could not be created. If - the process is created but fails to create the session, set - the controlling terminal or execute the file, it exits with - status 1 after printing an error message on the terminal that - indicates the call that failed. + the process is created but fails to open the slave device, or + set up the standard file descriptors, it exits with status 1. + If it fails to create the session, set the controlling + terminal or execute the file, it exits with status 1 after + printing an error message on the terminal that indicates the + call that failed. Provided through a library included with the VM to support Pharo terminal emulators: it can only be partially replicated @@ -36,18 +50,21 @@ pid_t tty_spawn(int fdm, const char *path, char *const argv[], char *const envp[ pid_t pid = fork(); if (pid == 0) { - int fds = open(ptsname(fdm), O_RDWR); - close(fdm); - close(0); - close(1); - close(2); - dup(fds); - dup(fds); - dup(fds); - close(fds); - CHECK_ERROR(setsid()); - CHECK_ERROR(ioctl(0, TIOCSCTTY, 0)); - CHECK_ERROR(execve(path, argv, envp)); + char *sname; + CHECK_NULL(sname = ptsname(fdm)); + int fds; + CHECK_ERROR(fds = open(sname, O_RDWR)); + CHECK_ERROR(close(fdm)); + CHECK_ERROR(close(0)); + CHECK_ERROR(close(1)); + CHECK_ERROR(close(2)); + CHECK_ERROR(dup(fds)); + CHECK_ERROR(dup(fds)); + CHECK_ERROR(dup(fds)); + CHECK_ERROR(close(fds)); + CHECK_ERROR_PRINT(setsid()); + CHECK_ERROR_PRINT(ioctl(0, TIOCSCTTY, 0)); + CHECK_ERROR_PRINT(execve(path, argv, envp)); } return pid; } From b5e2dfece77fc712878f4de8ceb05a63d14e3395 Mon Sep 17 00:00:00 2001 From: Kris <1611248+Rinzwind@users.noreply.github.com> Date: Sun, 18 Feb 2024 10:23:16 +0100 Subject: [PATCH 5/6] =?UTF-8?q?Changed=20exit=20status=20for=20errors=20in?= =?UTF-8?q?=20the=20setup=20of=20the=20child=20process=20in=20=E2=80=98tty?= =?UTF-8?q?=5Fspawn=E2=80=99=20from=201=20to=20127=20(similar=20to=20?= =?UTF-8?q?=E2=80=98posix=5Fspawn=E2=80=99).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tty/tty.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tty/tty.c b/tty/tty.c index 933327e603..5d5d64bee3 100644 --- a/tty/tty.c +++ b/tty/tty.c @@ -10,18 +10,19 @@ #include #include +#define STATUS_ERROR 127 #define CHECK_NULL(exp) \ if ((exp) == NULL) { \ - exit(1); \ + exit(STATUS_ERROR); \ } #define CHECK_ERROR(exp) \ if ((exp) == -1) { \ - exit(1); \ + exit(STATUS_ERROR); \ } #define CHECK_ERROR_PRINT(exp) \ if ((exp) == -1) { \ printf("Error in %s at %s: %s\n", __func__, #exp, strerror(errno)); \ - exit(1); \ + exit(STATUS_ERROR); \ } pid_t tty_spawn(int fdm, const char *path, char *const argv[], char *const envp[]) @@ -35,9 +36,9 @@ pid_t tty_spawn(int fdm, const char *path, char *const argv[], char *const envp[ should be given as expected by 'execve'. The process ID of the new process is returned, or -1 if one could not be created. If the process is created but fails to open the slave device, or - set up the standard file descriptors, it exits with status 1. + set up the standard file descriptors, it exits with status 127. If it fails to create the session, set the controlling - terminal or execute the file, it exits with status 1 after + terminal or execute the file, it exits with status 127 after printing an error message on the terminal that indicates the call that failed. From 6fa0c9e28884ae9553051588bcefb07a74b51e6b Mon Sep 17 00:00:00 2001 From: Kris <1611248+Rinzwind@users.noreply.github.com> Date: Thu, 14 Mar 2024 22:22:04 +0100 Subject: [PATCH 6/6] =?UTF-8?q?Changed=20error=20checking=20macros=20used?= =?UTF-8?q?=20in=20the=20child=20process=20in=20=E2=80=98tty=5Fspawn?= =?UTF-8?q?=E2=80=99=20to=20use=20=E2=80=98=5Fexit=E2=80=99=20instead=20of?= =?UTF-8?q?=20=E2=80=98exit=E2=80=99,=20and=20=E2=80=98dprintf=E2=80=99=20?= =?UTF-8?q?instead=20of=20=E2=80=98printf=E2=80=99,=20to=20avoid=20flushin?= =?UTF-8?q?g=20the=20open=20streams=20copied,=20buffers=20included,=20from?= =?UTF-8?q?=20the=20parent=20process.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tty/tty.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tty/tty.c b/tty/tty.c index 5d5d64bee3..86b6ecced6 100644 --- a/tty/tty.c +++ b/tty/tty.c @@ -1,5 +1,5 @@ #ifndef _XOPEN_SOURCE -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #endif #include @@ -13,16 +13,16 @@ #define STATUS_ERROR 127 #define CHECK_NULL(exp) \ if ((exp) == NULL) { \ - exit(STATUS_ERROR); \ + _exit(STATUS_ERROR); \ } #define CHECK_ERROR(exp) \ if ((exp) == -1) { \ - exit(STATUS_ERROR); \ + _exit(STATUS_ERROR); \ } #define CHECK_ERROR_PRINT(exp) \ if ((exp) == -1) { \ - printf("Error in %s at %s: %s\n", __func__, #exp, strerror(errno)); \ - exit(STATUS_ERROR); \ + dprintf(2, "Error in %s at %s: %s\n", __func__, #exp, strerror(errno)); \ + _exit(STATUS_ERROR); \ } pid_t tty_spawn(int fdm, const char *path, char *const argv[], char *const envp[])