From 18130bed7fa032513261d426b8c3915cf11e20c1 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Thu, 17 Sep 2015 21:44:14 -0700 Subject: 36552 plus test: fix Nularg string in quotestring(QT_DOLLARS) --- Src/utils.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Src/utils.c') diff --git a/Src/utils.c b/Src/utils.c index ca68eae32..d5fd88c00 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -5384,6 +5384,12 @@ quotestring(const char *s, char **e, int instring) "BUG: bad quote type in quotestring"); u = s; if (instring == QT_DOLLARS) { + /* + * The only way to get Nularg here is when + * it is placeholding for the empty string? + */ + if (inull(*u)) + *u++; /* * As we test for printability here we need to be able * to look for multibyte characters. -- cgit v1.2.3 From 07796811b03f58f2f143cd2860c67c9896c71acb Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 19 Sep 2015 09:34:05 -0700 Subject: cf. 36554: remove unnecessary pointer dereference --- Src/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Src/utils.c') diff --git a/Src/utils.c b/Src/utils.c index d5fd88c00..1de3d9578 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -5389,7 +5389,7 @@ quotestring(const char *s, char **e, int instring) * it is placeholding for the empty string? */ if (inull(*u)) - *u++; + u++; /* * As we test for printability here we need to be able * to look for multibyte characters. -- cgit v1.2.3 From 4375d7b905dca266c3a14bf603a908eb7c3dfbf2 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 19 Sep 2015 23:03:39 -0700 Subject: 36562: sanitize $PWD on import, per POSIX --- ChangeLog | 4 ++++ Src/utils.c | 20 +++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'Src/utils.c') diff --git a/ChangeLog b/ChangeLog index bb03894a0..6d99ccd81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-09-19 Barton E. Schaefer + + * 36562: Src/utils.c: sanitize $PWD on import, per POSIX + 2015-09-19 Peter Stephenson * 36559: Src/pattern.c: test earlier for overflow in pattern diff --git a/Src/utils.c b/Src/utils.c index 1de3d9578..ab3b0c274 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -692,9 +692,23 @@ ispwd(char *s) { struct stat sbuf, tbuf; - if (stat(unmeta(s), &sbuf) == 0 && stat(".", &tbuf) == 0) - if (sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino) - return 1; + /* POSIX: environment PWD must be absolute */ + if (*s != '/') + return 0; + + if (stat((s = unmeta(s)), &sbuf) == 0 && stat(".", &tbuf) == 0) + if (sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino) { + /* POSIX: No element of $PWD may be "." or ".." */ + while (*s) { + if (s[0] == '.' && + (!s[1] || s[1] == '/' || + (s[1] == '.' && (!s[2] || s[2] == '/')))) + break; + while (*s++ != '/' && *s) + continue; + } + return !*s; + } return 0; } -- cgit v1.2.3 From 3f9606333578384221948e285ed896738071b253 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 4 Oct 2015 14:01:08 -0700 Subject: 36773: limit CORRECT / CORRECT_ALL to directory names in cases where it is obvious that a directory is expected --- ChangeLog | 5 +++++ Src/utils.c | 49 ++++++++++++++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 19 deletions(-) (limited to 'Src/utils.c') diff --git a/ChangeLog b/ChangeLog index aa2253522..e1f58c9ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-04 Barton E. Schaefer + + * 36773: Src/utils.c: limit CORRECT / CORRECT_ALL to directory + names in cases where it is obvious that a directory is expected + 2015-10-03 Barton E. Schaefer * unposted (cf. 36696): Test/C03traps.ztst: test case for 36766 diff --git a/Src/utils.c b/Src/utils.c index ab3b0c274..61cbe84aa 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -2812,7 +2812,7 @@ spckword(char **s, int hist, int cmd, int ask) * as used in spscan(), so that an autocd is chosen * * only when it is better than anything so far, and * * so we prefer directories earlier in the cdpath. */ - if ((thisdist = mindist(*pp, *s, bestcd)) < d) { + if ((thisdist = mindist(*pp, *s, bestcd, 1)) < d) { best = dupstring(bestcd); d = thisdist; } @@ -4057,7 +4057,8 @@ spname(char *oldname) thresh = 3; else if (thresh > 100) thresh = 100; - if ((thisdist = mindist(newname, spnameguess, spnamebest)) >= thresh) { + thisdist = mindist(newname, spnameguess, spnamebest, *old == '/'); + if (thisdist >= thresh) { /* The next test is always true, except for the first path * * component. We could initialize bestdist to some large * * constant instead, and then compare to that constant here, * @@ -4082,42 +4083,52 @@ spname(char *oldname) /**/ static int -mindist(char *dir, char *mindistguess, char *mindistbest) +mindist(char *dir, char *mindistguess, char *mindistbest, int wantdir) { int mindistd, nd; DIR *dd; char *fn; char *buf; + struct stat st; + size_t dirlen; if (dir[0] == '\0') dir = "."; mindistd = 100; - buf = zalloc(strlen(dir) + strlen(mindistguess) + 2); + if (!(buf = zalloc((dirlen = strlen(dir)) + strlen(mindistguess) + 2))) + return 0; sprintf(buf, "%s/%s", dir, mindistguess); - if (access(unmeta(buf), F_OK) == 0) { + if (stat(unmeta(buf), &st) == 0 && (!wantdir || S_ISDIR(st.st_mode))) { strcpy(mindistbest, mindistguess); free(buf); return 0; } - free(buf); - if (!(dd = opendir(unmeta(dir)))) - return mindistd; - while ((fn = zreaddir(dd, 0))) { - if (spnamepat && pattry(spnamepat, fn)) - continue; - nd = spdist(fn, mindistguess, - (int)strlen(mindistguess) / 4 + 1); - if (nd <= mindistd) { - strcpy(mindistbest, fn); - mindistd = nd; - if (mindistd == 0) - break; + if ((dd = opendir(unmeta(dir)))) { + while ((fn = zreaddir(dd, 0))) { + if (spnamepat && pattry(spnamepat, fn)) + continue; + nd = spdist(fn, mindistguess, + (int)strlen(mindistguess) / 4 + 1); + if (nd <= mindistd) { + if (wantdir) { + if (!(buf = zrealloc(buf, dirlen + strlen(fn) + 2))) + continue; + sprintf(buf, "%s/%s", dir, fn); + if (stat(unmeta(buf), &st) != 0 || !S_ISDIR(st.st_mode)) + continue; + } + strcpy(mindistbest, fn); + mindistd = nd; + if (mindistd == 0) + break; + } } + closedir(dd); } - closedir(dd); + free(buf); return mindistd; } -- cgit v1.2.3 From 1f6dcf9bcdade41886e36826196e79502a9afa26 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 24 Oct 2015 20:24:35 +0100 Subject: 36941: Mark file descripors in ztcp as used. Allow such file descriptors to be either internal and closed on exec or external and so managed explicitly by module. --- ChangeLog | 6 ++++++ Src/Modules/tcp.c | 7 ++++++- Src/utils.c | 26 ++++++++++++++++++++++++++ Src/zsh.h | 15 +++++++++++---- 4 files changed, 49 insertions(+), 5 deletions(-) (limited to 'Src/utils.c') diff --git a/ChangeLog b/ChangeLog index 84f1b9856..356e92319 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-10-24 Peter Stephenson + + * 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). + 2015-10-22 Daniel Shahaf * unposted: Doc/Zsh/contrib.yo: vcs_info docs: Typo fix. diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c index bc1765da1..274f01ffc 100644 --- a/Src/Modules/tcp.c +++ b/Src/Modules/tcp.c @@ -236,6 +236,8 @@ tcp_socket(int domain, int type, int protocol, int ztflags) if (!sess) return NULL; sess->fd = socket(domain, type, protocol); + /* We'll check failure and tidy up in caller */ + addmodulefd(sess->fd, FALSE); return sess; } @@ -298,7 +300,7 @@ tcp_close(Tcp_session sess) { if (sess->fd != -1) { - err = close(sess->fd); + err = zclose(sess->fd); if (err) zwarn("connection close failed: %e", errno); } @@ -546,6 +548,9 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) return 1; } + /* redup expects fd is already registered */ + addmodulefd(rfd, FALSE); + if (targetfd) { sess->fd = redup(rfd, targetfd); if (sess->fd < 0) { diff --git a/Src/utils.c b/Src/utils.c index 61cbe84aa..4c69d75a1 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1891,6 +1891,32 @@ redup(int x, int y) return ret; } +/* + * 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). + * + * 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) +{ + if (fd >= 0) { + check_fd_table(fd); + fdtable[fd] = is_internal ? FDT_INTERNAL : FDT_MODULE; + } +} + +/**/ + /* * Indicate that an fd has a file lock; if cloexec is 1 it will be closed * on exec. diff --git a/Src/zsh.h b/Src/zsh.h index 15fa5e417..f819249c3 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -405,26 +405,33 @@ enum { * the {varid}> file syntax. */ #define FDT_EXTERNAL 2 +/* + * Entry visible to other processes but controlled by a module. + * The difference from FDT_EXTERNAL is that closing this using + * standard fd syntax will fail as there is some tidying up that + * needs to be done by the module's own mechanism. + */ +#define FDT_MODULE 3 /* * Entry used by output from the XTRACE option. */ -#define FDT_XTRACE 3 +#define FDT_XTRACE 4 /* * Entry used for file locking. */ -#define FDT_FLOCK 4 +#define FDT_FLOCK 5 /* * As above, but the fd is not marked for closing on exec, * so the shell can still exec the last process. */ -#define FDT_FLOCK_EXEC 5 +#define FDT_FLOCK_EXEC 6 #ifdef PATH_DEV_FD /* * Entry used by a process substition. * This marker is not tested internally as we associated the file * descriptor with a job for closing. */ -#define FDT_PROC_SUBST 6 +#define FDT_PROC_SUBST 7 #endif /* Flags for input stack */ -- cgit v1.2.3 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(-) (limited to 'Src/utils.c') 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 v1.2.3 From c8c42d6ed55c23f83a4a94eaae7e42a70c5d55c7 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 24 Oct 2015 20:59:48 +0100 Subject: unposted: small typo --- ChangeLog | 2 ++ Src/utils.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'Src/utils.c') diff --git a/ChangeLog b/ChangeLog index 71f15bb0d..ef5cbe1f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-10-24 Peter Stephenson + * unposted: Src/utils.c: small typo. + * 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. diff --git a/Src/utils.c b/Src/utils.c index 37a02c593..b72addaff 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1905,7 +1905,7 @@ redup(int x, int y) * 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 + * internal 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. -- cgit v1.2.3 From 272119b774a5227e8778e5f86b4a519db89ab0fa Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 24 Oct 2015 21:00:30 +0100 Subject: unposted: small typo again --- Src/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Src/utils.c') diff --git a/Src/utils.c b/Src/utils.c index b72addaff..0afa8c908 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1901,7 +1901,7 @@ redup(int x, int y) * 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 + * (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 -- cgit v1.2.3