summaryrefslogtreecommitdiff
path: root/Src/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Modules')
-rw-r--r--Src/Modules/curses.c2
-rw-r--r--Src/Modules/datetime.c15
-rw-r--r--Src/Modules/files.c2
-rw-r--r--Src/Modules/newuser.c2
-rw-r--r--Src/Modules/regex.c38
-rw-r--r--Src/Modules/socket.c9
-rw-r--r--Src/Modules/stat.c7
-rw-r--r--Src/Modules/system.c183
-rw-r--r--Src/Modules/system.mdd2
-rw-r--r--Src/Modules/tcp.c9
-rw-r--r--Src/Modules/zftp.c8
-rw-r--r--Src/Modules/zpty.c2
12 files changed, 248 insertions, 31 deletions
diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c
index 41ad2c6e4..62dbd55ea 100644
--- a/Src/Modules/curses.c
+++ b/Src/Modules/curses.c
@@ -765,7 +765,7 @@ zccmd_string(const char *nam, char **args)
w = (ZCWin)getdata(node);
#ifdef HAVE_WADDWSTR
- mb_metacharinit();
+ mb_charinit();
wptr = wstr = zhalloc((strlen(str)+1) * sizeof(wchar_t));
while (*str && (clen = mb_metacharlenconv(str, &wc))) {
diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c
index 63a04dc89..86c61cf1c 100644
--- a/Src/Modules/datetime.c
+++ b/Src/Modules/datetime.c
@@ -53,10 +53,12 @@ reverse_strftime(char *nam, char **argv, char *scalar, int quiet)
* to use the current timezone. This is probably the best guess;
* it's the one that will cause dates and times output by strftime
* without the -r option and without an explicit timezone to be
- * converted back correctly.
+ * converted back correctly. Additionally, tm_mday is set to 1
+ * as that and not 0 corresponds to the first of the month.
*/
(void)memset(&tm, 0, sizeof(tm));
tm.tm_isdst = -1;
+ tm.tm_mday = 1;
endp = strptime(argv[1], argv[0], &tm);
if (!endp) {
@@ -96,7 +98,7 @@ reverse_strftime(char *nam, char **argv, char *scalar, int quiet)
static int
output_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
{
- int bufsize, x;
+ int bufsize, x, len;
char *endptr = NULL, *scalar = NULL, *buffer;
time_t secs;
struct tm *t;
@@ -129,16 +131,19 @@ output_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
bufsize = strlen(argv[0]) * 8;
buffer = zalloc(bufsize);
+ len = 0;
for (x=0; x < 4; x++) {
- if (ztrftime(buffer, bufsize, argv[0], t, 0L) >= 0)
+ if ((len = ztrftime(buffer, bufsize, argv[0], t, 0L)) >= 0)
break;
buffer = zrealloc(buffer, bufsize *= 2);
}
+ DPUTS(len < 0, "bad output from ztrftime");
if (scalar) {
- setsparam(scalar, metafy(buffer, -1, META_DUP));
+ setsparam(scalar, metafy(buffer, len, META_DUP));
} else {
- printf("%s\n", buffer);
+ fwrite(buffer, 1, len, stdout);
+ putchar('\n');
}
zfree(buffer, bufsize);
diff --git a/Src/Modules/files.c b/Src/Modules/files.c
index f86b9c1e9..dbcff6307 100644
--- a/Src/Modules/files.c
+++ b/Src/Modules/files.c
@@ -131,7 +131,7 @@ domkdir(char *nam, char *path, mode_t mode, int p)
return 0;
}
oumask = umask(0);
- err = mkdir(path, mode) ? errno : 0;
+ err = mkdir(rpath, mode) ? errno : 0;
umask(oumask);
if(!err)
return 0;
diff --git a/Src/Modules/newuser.c b/Src/Modules/newuser.c
index 71902da7d..efdb2abba 100644
--- a/Src/Modules/newuser.c
+++ b/Src/Modules/newuser.c
@@ -67,7 +67,7 @@ check_dotfile(const char *dotdir, const char *fname)
int
boot_(UNUSED(Module m))
{
- const char *dotdir = getsparam("ZDOTDIR");
+ const char *dotdir = getsparam_u("ZDOTDIR");
const char *spaths[] = {
#ifdef SITESCRIPT_DIR
SITESCRIPT_DIR,
diff --git a/Src/Modules/regex.c b/Src/Modules/regex.c
index ce57de986..16cc77f30 100644
--- a/Src/Modules/regex.c
+++ b/Src/Modules/regex.c
@@ -115,6 +115,7 @@ zcond_regex_match(char **a, int id)
} else {
zlong offs;
char *ptr;
+ int clen, leftlen;
m = matches;
s = metafy(lhstr + m->rm_so, m->rm_eo - m->rm_so, META_DUP);
@@ -123,19 +124,25 @@ zcond_regex_match(char **a, int id)
* Count the characters before the match.
*/
ptr = lhstr;
+ leftlen = m->rm_so;
offs = 0;
- MB_METACHARINIT();
- while (ptr < lhstr + m->rm_so) {
+ MB_CHARINIT();
+ while (leftlen) {
offs++;
- ptr += MB_METACHARLEN(ptr);
+ clen = MB_CHARLEN(ptr, leftlen);
+ ptr += clen;
+ leftlen -= clen;
}
setiparam("MBEGIN", offs + !isset(KSHARRAYS));
/*
* Add on the characters in the match.
*/
- while (ptr < lhstr + m->rm_eo) {
+ leftlen = m->rm_eo - m->rm_so;
+ while (leftlen) {
offs++;
- ptr += MB_METACHARLEN(ptr);
+ clen = MB_CHARLEN(ptr, leftlen);
+ ptr += clen;
+ leftlen -= clen;
}
setiparam("MEND", offs + !isset(KSHARRAYS) - 1);
if (nelem) {
@@ -148,20 +155,31 @@ zcond_regex_match(char **a, int id)
++n, ++m, ++bptr, ++eptr)
{
char buf[DIGBUFSIZE];
+ if (m->rm_so < 0 || m->rm_eo < 0) {
+ *bptr = ztrdup("-1");
+ *eptr = ztrdup("-1");
+ continue;
+ }
ptr = lhstr;
+ leftlen = m->rm_so;
offs = 0;
/* Find the start offset */
- MB_METACHARINIT();
- while (ptr < lhstr + m->rm_so) {
+ MB_CHARINIT();
+ while (leftlen) {
offs++;
- ptr += MB_METACHARLEN(ptr);
+ clen = MB_CHARLEN(ptr, leftlen);
+ ptr += clen;
+ leftlen -= clen;
}
convbase(buf, offs + !isset(KSHARRAYS), 10);
*bptr = ztrdup(buf);
/* Continue to the end offset */
- while (ptr < lhstr + m->rm_eo) {
+ leftlen = m->rm_eo - m->rm_so;
+ while (leftlen ) {
offs++;
- ptr += MB_METACHARLEN(ptr);
+ clen = MB_CHARLEN(ptr, leftlen);
+ ptr += clen;
+ leftlen -= clen;
}
convbase(buf, offs + !isset(KSHARRAYS) - 1, 10);
*eptr = ztrdup(buf);
diff --git a/Src/Modules/socket.c b/Src/Modules/socket.c
index 6c70d3166..65b87d7dd 100644
--- a/Src/Modules/socket.c
+++ b/Src/Modules/socket.c
@@ -175,7 +175,7 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
tv.tv_sec = 0;
tv.tv_usec = 0;
- if ((ret = select(lfd+1, &rfds, NULL, NULL, &tv))) return 1;
+ if ((ret = select(lfd+1, &rfds, NULL, NULL, &tv)) == 0) return 1;
else if (ret == -1)
{
zwarnnam(nam, "select error: %e", errno);
@@ -191,8 +191,11 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
}
len = sizeof(soun);
- if ((rfd = accept(lfd, (struct sockaddr *)&soun, &len)) == -1)
- {
+ do {
+ rfd = accept(lfd, (struct sockaddr *)&soun, &len);
+ } while (rfd < 0 && errno == EINTR && !errflag);
+
+ if (rfd == -1) {
zwarnnam(nam, "could not accept connection: %e", errno);
return 1;
}
diff --git a/Src/Modules/stat.c b/Src/Modules/stat.c
index 6fc53894c..396177149 100644
--- a/Src/Modules/stat.c
+++ b/Src/Modules/stat.c
@@ -197,8 +197,11 @@ stattimeprint(time_t tim, char *outbuf, int flags)
}
if (flags & STF_STRING) {
char *oend = outbuf + strlen(outbuf);
- ztrftime(oend, 40, timefmt, (flags & STF_GMT) ? gmtime(&tim) :
- localtime(&tim), 0L);
+ /* Where the heck does "40" come from? */
+ int len = ztrftime(oend, 40, timefmt, (flags & STF_GMT) ? gmtime(&tim) :
+ localtime(&tim), 0L);
+ if (len > 0)
+ metafy(oend, len, META_NOALLOC);
if (flags & STF_RAW)
strcat(oend, ")");
}
diff --git a/Src/Modules/system.c b/Src/Modules/system.c
index f6a21d160..1ab1fb17e 100644
--- a/Src/Modules/system.c
+++ b/Src/Modules/system.c
@@ -279,6 +279,182 @@ bin_syswrite(char *nam, char **args, Options ops, UNUSED(int func))
}
+static struct { char *name; int oflag; } openopts[] = {
+#ifdef O_CLOEXEC
+ { "cloexec", O_CLOEXEC },
+#else
+# ifdef FD_CLOEXEC
+ { "cloexec", 0 }, /* this needs to be first in the table */
+# endif
+#endif
+#ifdef O_NOFOLLOW
+ { "nofollow", O_NOFOLLOW },
+#endif
+#ifdef O_SYNC
+ { "sync", O_SYNC },
+#endif
+#ifdef O_NOATIME
+ { "noatime", O_NOATIME },
+#endif
+ { "excl", O_EXCL | O_CREAT },
+ { "creat", O_CREAT },
+ { "create", O_CREAT },
+ { "truncate", O_TRUNC },
+ { "trunc", O_TRUNC }
+};
+
+/**/
+static int
+bin_sysopen(char *nam, char **args, Options ops, UNUSED(int func))
+{
+ int read = OPT_ISSET(ops, 'r');
+ int write = OPT_ISSET(ops, 'w');
+ int append = OPT_ISSET(ops, 'a') ? O_APPEND : 0;
+ int flags = O_NOCTTY | append | ((append || write) ?
+ (read ? O_RDWR : O_WRONLY) : O_RDONLY);
+ char *opt, *ptr, *nextopt, *fdvar;
+ int o, fd, explicit = -1;
+ mode_t perms = 0666;
+#if defined(FD_CLOEXEC) && !defined(O_CLOEXEC)
+ int fdflags;
+#endif
+
+ if (!OPT_ISSET(ops, 'u')) {
+ zwarnnam(nam, "file descriptor not specified");
+ return 1;
+ }
+
+ /* file descriptor, either 0-9 or a variable name */
+ fdvar = OPT_ARG(ops, 'u');
+ if (idigit(*fdvar) && !fdvar[1]) {
+ explicit = atoi(fdvar);
+ } else if (!isident(fdvar)) {
+ zwarnnam(nam, "not an identifier: %s", fdvar);
+ return 1;
+ }
+
+ /* open options */
+ if (OPT_ISSET(ops, 'o')) {
+ opt = OPT_ARG(ops, 'o');
+ while (opt) {
+ if (!strncasecmp(opt, "O_", 2)) /* ignore initial O_ */
+ opt += 2;
+ if ((nextopt = strchr(opt, ',')))
+ *nextopt++ = '\0';
+ for (o = sizeof(openopts)/sizeof(*openopts) - 1; o >= 0 &&
+ strcasecmp(openopts[o].name, opt); o--) {}
+ if (o < 0) {
+ zwarnnam(nam, "unsupported option: %s\n", opt);
+ return 1;
+ }
+#if defined(FD_CLOEXEC) && !defined(O_CLOEXEC)
+ if (!openopts[o].oflag)
+ fdflags = FD_CLOEXEC;
+#endif
+ flags |= openopts[o].oflag;
+ opt = nextopt;
+ }
+ }
+
+ /* -m: permissions or mode for created files */
+ if (OPT_ISSET(ops, 'm')) {
+ ptr = opt = OPT_ARG(ops, 'm');
+ while (*ptr >= '0' && *ptr <= '7') ptr++;
+ if (*ptr || ptr - opt < 3) {
+ zwarnnam(nam, "invalid mode %s", opt);
+ return 1;
+ }
+ perms = zstrtol(opt, 0, 8); /* octal number */
+ }
+
+ if (flags & O_CREAT)
+ fd = open(*args, flags, perms);
+ else
+ fd = open(*args, flags);
+
+ if (fd == -1) {
+ zwarnnam(nam, "can't open file %s: %e", *args, errno);
+ return 1;
+ }
+ fd = (explicit > -1) ? redup(fd, explicit) : movefd(fd);
+ if (fd == -1) {
+ zwarnnam(nam, "can't open file %s", *args);
+ return 1;
+ }
+
+#if defined(FD_CLOEXEC) && !defined(O_CLOEXEC)
+ if (fdflags)
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+ if (explicit == -1) {
+ fdtable[fd] = FDT_EXTERNAL;
+ setiparam(fdvar, fd);
+ /* if setting the variable failed, close fd to avoid leak */
+ if (errflag)
+ zclose(fd);
+ }
+
+ return 0;
+}
+
+
+/*
+ * Return values of bin_sysseek:
+ * 0 Success
+ * 1 Error in parameters to command
+ * 2 Error on seek, ERRNO set by system
+ */
+
+/**/
+static int
+bin_sysseek(char *nam, char **args, Options ops, UNUSED(int func))
+{
+ int w = SEEK_SET, fd = 0;
+ char *whence;
+ off_t pos;
+
+ /* -u: file descriptor if not stdin */
+ if (OPT_ISSET(ops, 'u')) {
+ fd = getposint(OPT_ARG(ops, 'u'), nam);
+ if (fd < 0)
+ return 1;
+ }
+
+ /* -w: whence - starting point of seek */
+ if (OPT_ISSET(ops, 'w')) {
+ whence = OPT_ARG(ops, 'w');
+ if (!(strcasecmp(whence, "current") && strcmp(whence, "1")))
+ w = SEEK_CUR;
+ else if (!(strcasecmp(whence, "end") && strcmp(whence, "2")))
+ w = SEEK_END;
+ else if (strcasecmp(whence, "start") && strcmp(whence, "0")) {
+ zwarnnam(nam, "unknown argument to -w: %s", whence);
+ return 1;
+ }
+ }
+
+ pos = (off_t)mathevali(*args);
+ return (lseek(fd, pos, w) == -1) ? 2 : 0;
+}
+
+/**/
+static mnumber
+math_systell(UNUSED(char *name), int argc, mnumber *argv, UNUSED(int id))
+{
+ int fd = (argv->type == MN_INTEGER) ? argv->u.l : (int)argv->u.d;
+ mnumber ret;
+ ret.type = MN_INTEGER;
+ ret.u.l = 0;
+
+ if (fd < 0) {
+ zerr("file descriptor out of range");
+ return ret;
+ }
+ ret.u.l = lseek(fd, 0, SEEK_CUR);
+ return ret;
+}
+
+
/*
* Return values of bin_syserror:
* 0 Successfully processed error
@@ -542,6 +718,8 @@ static struct builtin bintab[] = {
BUILTIN("syserror", 0, bin_syserror, 0, 1, 0, "e:p:", NULL),
BUILTIN("sysread", 0, bin_sysread, 0, 1, 0, "c:i:o:s:t:", NULL),
BUILTIN("syswrite", 0, bin_syswrite, 1, 1, 0, "c:o:", NULL),
+ BUILTIN("sysopen", 0, bin_sysopen, 1, 1, 0, "rwau:o:m:", NULL),
+ BUILTIN("sysseek", 0, bin_sysseek, 1, 1, 0, "u:w:", NULL),
BUILTIN("zsystem", 0, bin_zsystem, 1, -1, 0, NULL, NULL)
};
@@ -611,6 +789,9 @@ scanpmsysparams(UNUSED(HashTable ht), ScanFunc func, int flags)
func(&spm.node, flags);
}
+static struct mathfunc mftab[] = {
+ NUMMATHFUNC("systell", math_systell, 1, 1, 0)
+};
static struct paramdef partab[] = {
SPECIALPMDEF("errnos", PM_ARRAY|PM_READONLY,
@@ -622,7 +803,7 @@ static struct paramdef partab[] = {
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
- NULL, 0,
+ mftab, sizeof(mftab)/sizeof(*mftab),
partab, sizeof(partab)/sizeof(*partab),
0
};
diff --git a/Src/Modules/system.mdd b/Src/Modules/system.mdd
index 46f02d166..eed0c1b9d 100644
--- a/Src/Modules/system.mdd
+++ b/Src/Modules/system.mdd
@@ -2,7 +2,7 @@ name=zsh/system
link=dynamic
load=no
-autofeatures="b:sysread b:syswrite b:syserror p:errnos"
+autofeatures="b:sysread b:syswrite b:sysopen b:sysseek b:syserror p:errnos f:systell"
objects="system.o errnames.o"
diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c
index 0d9522047..bc1765da1 100644
--- a/Src/Modules/tcp.c
+++ b/Src/Modules/tcp.c
@@ -519,7 +519,7 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
tv.tv_sec = 0;
tv.tv_usec = 0;
- if ((ret = select(lfd+1, &rfds, NULL, NULL, &tv))) return 1;
+ if ((ret = select(lfd+1, &rfds, NULL, NULL, &tv)) == 0) return 1;
else if (ret == -1)
{
zwarnnam(nam, "select error: %e", errno);
@@ -536,8 +536,11 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
sess = zts_alloc(ZTCP_INBOUND);
len = sizeof(sess->peer.in);
- if ((rfd = accept(lfd, (struct sockaddr *)&sess->peer.in, &len)) == -1)
- {
+ do {
+ rfd = accept(lfd, (struct sockaddr *)&sess->peer.in, &len);
+ } while (rfd < 0 && errno == EINTR && !errflag);
+
+ if (rfd == -1) {
zwarnnam(nam, "could not accept connection: %e", errno);
tcp_close(sess);
return 1;
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index 09d4bd703..bd51512f9 100644
--- a/Src/Modules/zftp.c
+++ b/Src/Modules/zftp.c
@@ -731,7 +731,7 @@ zfgetmsg(void)
stopit = (*ptr++ != '-');
queue_signals();
- if (!(verbose = getsparam("ZFTP_VERBOSE")))
+ if (!(verbose = getsparam_u("ZFTP_VERBOSE")))
verbose = "";
if (strchr(verbose, lastcodestr[0])) {
/* print the whole thing verbatim */
@@ -1785,7 +1785,7 @@ zftp_open(char *name, char **args, int flags)
char *hname;
alarm(0);
queue_signals();
- if ((hname = getsparam("ZFTP_HOST")) && *hname)
+ if ((hname = getsparam_u("ZFTP_HOST")) && *hname)
zwarnnam(name, "timeout connecting to %s", hname);
else
zwarnnam(name, "timeout on host name lookup");
@@ -3077,7 +3077,7 @@ bin_zftp(char *name, char **args, UNUSED(Options ops), UNUSED(int func))
}
queue_signals();
- if ((prefs = getsparam("ZFTP_PREFS"))) {
+ if ((prefs = getsparam_u("ZFTP_PREFS"))) {
zfprefs = 0;
for (ptr = prefs; *ptr; ptr++) {
switch (toupper(STOUC(*ptr))) {
@@ -3149,9 +3149,11 @@ zftp_cleanup(void)
zfclose(zfsess != cursess);
}
zsfree(lastmsg);
+ lastmsg = NULL;
zfunsetparam("ZFTP_SESSION");
freelinklist(zfsessions, (FreeFunc) freesession);
zfree(zfstatusp, sizeof(int)*zfsesscnt);
+ zfstatusp = NULL;
}
static int
diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c
index 7b6130c6f..12e42b5bd 100644
--- a/Src/Modules/zpty.c
+++ b/Src/Modules/zpty.c
@@ -463,6 +463,8 @@ newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
#endif
errno == EINTR));
+ setiparam("REPLY", master);
+
return 0;
}