about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/socket.c17
-rw-r--r--Src/Modules/tcp.c4
-rw-r--r--Src/utils.c25
3 files changed, 32 insertions, 14 deletions
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;
     }
 }