aboutsummaryrefslogtreecommitdiff
path: root/src/term.c
diff options
context:
space:
mode:
authorThijs Schreijer <thijs@thijsschreijer.nl>2025-04-09 13:15:38 +0200
committerThijs Schreijer <thijs@thijsschreijer.nl>2025-04-09 13:25:58 +0200
commit2dd41df8144efeda71739dc2c0d1e62e00a6225a (patch)
tree88b0e2119a2c4b67c126349214a53b3ef8782c2b /src/term.c
parent96fb7f1608e00d6f8ceb2a5d9a90483e92fe4e3a (diff)
downloadluasystem-detach.tar.gz
luasystem-detach.tar.bz2
luasystem-detach.zip
fix review commentsdetach
Diffstat (limited to '')
-rw-r--r--src/term.c69
1 files changed, 34 insertions, 35 deletions
diff --git a/src/term.c b/src/term.c
index caca4e1..792832d 100644
--- a/src/term.c
+++ b/src/term.c
@@ -652,41 +652,55 @@ static int lst_tcsetattr(lua_State *L)
652#ifndef _WIN32 652#ifndef _WIN32
653/* 653/*
654reopen FDs for independent file descriptions. 654reopen FDs for independent file descriptions.
655fd should be either 1 or 2 (stdout or stderr)
656*/ 655*/
657static int reopen_fd(lua_State *L, int fd, int flags) { 656static void reopen_fd(lua_State *L, int fd, int flags) {
658 char path[64]; 657 char path[64];
659 int newfd = -1; 658 int newfd = -1;
660 659
660 if (fd != STDOUT_FILENO && fd != STDERR_FILENO) {
661 luaL_error(L, "Invalid file descriptor: %d. Only stdout (1) and stderr (2) are supported.", fd);
662 }
663
664 const char *fallback_path = (fd == STDOUT_FILENO) ? "/dev/stdout" :
665 (fd == STDERR_FILENO) ? "/dev/stderr" : NULL;
666
661 // If fd is a terminal, reopen its actual device (e.g. /dev/ttys003) 667 // If fd is a terminal, reopen its actual device (e.g. /dev/ttys003)
662 // Works on all POSIX platforms that have terminals (macOS, Linux, BSD, etc.) 668 // Works on all POSIX platforms that have terminals (macOS, Linux, BSD, etc.)
663 if (isatty(fd)) { 669 if (isatty(fd)) {
664 const char *tty = ttyname(fd); 670 const char *tty = ttyname(fd);
665 if (tty) { 671 if (tty) {
666 newfd = open(tty, flags); 672 newfd = open(tty, flags);
667 if (newfd >= 0) return newfd;
668 } 673 }
669 } 674 }
670 675
671 // For non-tty: try /dev/fd/N — POSIX-compliant and standard on macOS, Linux, BSD. 676 if (newfd < 0) {
672 // This gives a new file description even if the target is a file or pipe. 677 // For non-tty: try /dev/fd/N — POSIX-compliant and standard on macOS, Linux, BSD.
673 snprintf(path, sizeof(path), "/dev/fd/%d", fd); 678 // This gives a new file description even if the target is a file or pipe.
674 newfd = open(path, flags); 679 snprintf(path, sizeof(path), "/dev/fd/%d", fd);
675 if (newfd >= 0) return newfd; 680 newfd = open(path, flags);
681 }
676 682
677 // Fallback: for platforms/environments where /dev/fd/N doesn't exist. 683 if (newfd < 0) {
678 // /dev/stdout and /dev/stderr are standard on Linux, but may not create new descriptions. 684 // Fallback: for platforms/environments where /dev/fd/N doesn't exist.
679 const char *fallback_path = (fd == 1) ? "/dev/stdout" : 685 // /dev/stdout and /dev/stderr are standard on Linux, but may not create new descriptions.
680 (fd == 2) ? "/dev/stderr" : NULL; 686 if (fallback_path) {
687 newfd = open(fallback_path, flags);
688 }
689 }
681 690
682 if (fallback_path) { 691 if (newfd < 0) {
683 newfd = open(fallback_path, flags); 692 // All attempts failed — raise error with detailed info (call will not return)
684 if (newfd >= 0) return newfd; 693 luaL_error(L, "Failed to reopen fd %d: tried ttyname(), /dev/fd/%d, and fallback %s: %s",
694 fd, fd, fallback_path ? fallback_path : "(none)", strerror(errno));
685 } 695 }
686 696
687 // All attempts failed — raise error with detailed info 697 // Replace the original fd with the new one
688 return luaL_error(L, "Failed to reopen fd %d: tried ttyname(), /dev/fd/%d, and fallback %s: %s", 698 if (dup2(newfd, fd) < 0) {
689 fd, fd, fallback_path ? fallback_path : "(none)", strerror(errno)); 699 close(newfd);
700 luaL_error(L, "dup2 failed for fd %d: %s", fd, strerror(errno));
701 }
702
703 close(newfd); // Close the new fd, as dup2 has replaced the original fd with it
690} 704}
691#endif 705#endif
692 706
@@ -720,23 +734,8 @@ static int lst_detachfds(lua_State *L) {
720 734
721#ifndef _WIN32 735#ifndef _WIN32
722 // Reopen stdout and stderr with new file descriptions 736 // Reopen stdout and stderr with new file descriptions
723 int fd_out = reopen_fd(L, 1, O_WRONLY); 737 reopen_fd(L, STDOUT_FILENO, O_WRONLY);
724 int fd_err = reopen_fd(L, 2, O_WRONLY); 738 reopen_fd(L, STDERR_FILENO, O_WRONLY);
725
726 // Replace fd 1 and 2 in-place using dup2
727 if (dup2(fd_out, 1) < 0) {
728 close(fd_out);
729 return luaL_error(L, "dup2 failed for stdout: %s", strerror(errno));
730 }
731 if (dup2(fd_err, 2) < 0) {
732 close(fd_err);
733 return luaL_error(L, "dup2 failed for stderr: %s", strerror(errno));
734 }
735
736 // Clean up temporary file descriptors — fd 1 and 2 now own them
737 close(fd_out);
738 close(fd_err);
739
740#endif 739#endif
741 740
742 lua_pushboolean(L, 1); 741 lua_pushboolean(L, 1);