diff options
Diffstat (limited to 'Src/Modules')
-rw-r--r-- | Src/Modules/curses.c | 2 | ||||
-rw-r--r-- | Src/Modules/datetime.c | 15 | ||||
-rw-r--r-- | Src/Modules/files.c | 2 | ||||
-rw-r--r-- | Src/Modules/newuser.c | 2 | ||||
-rw-r--r-- | Src/Modules/regex.c | 38 | ||||
-rw-r--r-- | Src/Modules/socket.c | 9 | ||||
-rw-r--r-- | Src/Modules/stat.c | 7 | ||||
-rw-r--r-- | Src/Modules/system.c | 183 | ||||
-rw-r--r-- | Src/Modules/system.mdd | 2 | ||||
-rw-r--r-- | Src/Modules/tcp.c | 9 | ||||
-rw-r--r-- | Src/Modules/zftp.c | 8 | ||||
-rw-r--r-- | Src/Modules/zpty.c | 2 |
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; } |