From 15490398d7553605c422d8ab0e59e69e25111df4 Mon Sep 17 00:00:00 2001
From: Peter Stephenson
Date: Sat, 24 Oct 2015 20:48:47 +0100
Subject: 36944: extend fd management to zsocket
---
ChangeLog | 4 ++++
Doc/Zsh/mod_socket.yo | 5 +++++
Src/Modules/socket.c | 17 +++++++++++++++--
Src/Modules/tcp.c | 4 ++--
Src/utils.c | 25 +++++++++++++++----------
5 files changed, 41 insertions(+), 14 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 356e92319..71f15bb0d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2015-10-24 Peter Stephenson
+ * 36944: Src/utils.c, Src/Modules/tcp.c, Src/Modules/socket.c:
+ extend the previous to zsocket, although this needs to allow the
+ fd to be closed explicitly.
+
* 36941: Src/utils.c, Src/zsh.h, Src/Modules/tcp.c: ensure shell
knows about file descriptiors used by ztcp and allow such file
descriptors to be marked as internal if needed (not yet used).
diff --git a/Doc/Zsh/mod_socket.yo b/Doc/Zsh/mod_socket.yo
index 332c551fe..867f6081f 100644
--- a/Doc/Zsh/mod_socket.yo
+++ b/Doc/Zsh/mod_socket.yo
@@ -28,6 +28,11 @@ will be taken as the target file descriptor for the
connection.
In order to elicit more verbose output, use tt(-v).
+
+File descriptors can be closed with normal shell syntax when no longer
+needed, for example:
+
+example(exec {REPLY}>&-)
)
enditem()
diff --git a/Src/Modules/socket.c b/Src/Modules/socket.c
index 65b87d7dd..f683496df 100644
--- a/Src/Modules/socket.c
+++ b/Src/Modules/socket.c
@@ -115,6 +115,8 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
return 1;
}
+ addmodulefd(sfd, FDT_EXTERNAL);
+
if (targetfd) {
sfd = redup(sfd, targetfd);
}
@@ -127,6 +129,9 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
return 1;
}
+ /* allow to be closed explicitly */
+ fdtable[sfd] = FDT_EXTERNAL;
+
setiparam("REPLY", sfd);
if (verbose)
@@ -200,12 +205,16 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
return 1;
}
+ addmodulefd(rfd, FDT_EXTERNAL);
+
if (targetfd) {
sfd = redup(rfd, targetfd);
if (sfd < 0) {
zerrnam(nam, "could not duplicate socket fd to %d: %e", targetfd, errno);
+ zclose(rfd);
return 1;
}
+ fdtable[sfd] = FDT_EXTERNAL;
}
else {
sfd = rfd;
@@ -240,12 +249,16 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
}
else
{
+ addmodulefd(sfd, FDT_EXTERNAL);
+
if (targetfd) {
- sfd = redup(sfd, targetfd);
- if (sfd < 0) {
+ if (redup(sfd, targetfd) < 0) {
zerrnam(nam, "could not duplicate socket fd to %d: %e", targetfd, errno);
+ zclose(sfd);
return 1;
}
+ sfd = targetfd;
+ fdtable[sfd] = FDT_EXTERNAL;
}
setiparam("REPLY", sfd);
diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c
index 274f01ffc..7b0dcc74a 100644
--- a/Src/Modules/tcp.c
+++ b/Src/Modules/tcp.c
@@ -237,7 +237,7 @@ tcp_socket(int domain, int type, int protocol, int ztflags)
sess->fd = socket(domain, type, protocol);
/* We'll check failure and tidy up in caller */
- addmodulefd(sess->fd, FALSE);
+ addmodulefd(sess->fd, FDT_MODULE);
return sess;
}
@@ -549,7 +549,7 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
}
/* redup expects fd is already registered */
- addmodulefd(rfd, FALSE);
+ addmodulefd(rfd, FDT_MODULE);
if (targetfd) {
sess->fd = redup(rfd, targetfd);
diff --git a/Src/utils.c b/Src/utils.c
index 4c69d75a1..37a02c593 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1894,24 +1894,29 @@ redup(int x, int y)
/*
* Add an fd opened ithin a module.
*
- * If is_internal is FALSE, the fd can be used within the shell for
- * normal I/O but it will not be closed automatically or by normal shell
- * syntax; it can only be closed by the module (which should included
- * zclose() as part of the sequence).
+ * fdt is the type of the fd; see the FDT_ definitions in zsh.h.
+ * The most likely falures are:
+ *
+ * FDT_EXTERNAL: the fd can be used within the shell for normal I/O but
+ * it will not be closed automatically or by normal shell syntax.
+ *
+ * FDT_MODULE: as FDT_EXTERNAL, but it can only be closed by the module
+ * (which should included zclose() as part of the sequence, not by
+ * the standard shell syntax for closing file descriptors.
+ *
+ * FDT_INTERNAL: fd is treated like others created by the shell for
+ * internall use; it can be closed and will be closed by the shell if it
+ * exec's or performs an exec with a fork optimised out.
*
- * If is_internal is TRUE the fd is treated like others created by the
- * shell for internall use; it can be closed and will be closed by the
- * shell if it exec's or performs an exec with a fork optimised out.
- *.
* Safe if fd is -1 to indicate failure.
*/
/**/
mod_export void
-addmodulefd(int fd, bool is_internal)
+addmodulefd(int fd, int fdt)
{
if (fd >= 0) {
check_fd_table(fd);
- fdtable[fd] = is_internal ? FDT_INTERNAL : FDT_MODULE;
+ fdtable[fd] = fdt;
}
}
--
cgit 1.4.1