summaryrefslogtreecommitdiff
path: root/Src/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Modules')
-rw-r--r--Src/Modules/attr.c67
-rw-r--r--Src/Modules/datetime.c21
-rw-r--r--Src/Modules/db_gdbm.c184
-rw-r--r--Src/Modules/langinfo.c3
-rw-r--r--Src/Modules/tcp.c4
-rw-r--r--Src/Modules/zftp.c1
-rw-r--r--Src/Modules/zpty.c6
-rw-r--r--Src/Modules/zselect.c2
-rw-r--r--Src/Modules/zutil.c8
9 files changed, 222 insertions, 74 deletions
diff --git a/Src/Modules/attr.c b/Src/Modules/attr.c
index 6e08b10c5..78c1104a9 100644
--- a/Src/Modules/attr.c
+++ b/Src/Modules/attr.c
@@ -98,36 +98,33 @@ static int
bin_getattr(char *nam, char **argv, Options ops, UNUSED(int func))
{
int ret = 0;
- int list_len, val_len = 0, attr_len = 0, slen;
+ int val_len = 0, attr_len = 0, slen;
char *value, *file = argv[0], *attr = argv[1], *param = argv[2];
int symlink = OPT_ISSET(ops, 'h');
unmetafy(file, &slen);
unmetafy(attr, NULL);
- list_len = xlistxattr(file, NULL, 0, symlink);
- if (list_len > 0) {
- val_len = xgetxattr(file, attr, NULL, 0, symlink);
- if (val_len == 0) {
+ val_len = xgetxattr(file, attr, NULL, 0, symlink);
+ if (val_len == 0) {
+ if (param)
+ unsetparam(param);
+ return 0;
+ }
+ if (val_len > 0) {
+ value = (char *)zalloc(val_len+1);
+ attr_len = xgetxattr(file, attr, value, val_len, symlink);
+ if (attr_len > 0 && attr_len <= val_len) {
+ value[attr_len] = '\0';
if (param)
- unsetparam(param);
- return 0;
- }
- if (val_len > 0) {
- value = (char *)zalloc(val_len+1);
- attr_len = xgetxattr(file, attr, value, val_len, symlink);
- if (attr_len > 0 && attr_len <= val_len) {
- value[attr_len] = '\0';
- if (param)
- setsparam(param, metafy(value, attr_len, META_DUP));
- else
- printf("%s\n", value);
- }
- zfree(value, val_len+1);
+ setsparam(param, metafy(value, attr_len, META_DUP));
+ else
+ printf("%s\n", value);
}
+ zfree(value, val_len+1);
}
- if (list_len < 0 || val_len < 0 || attr_len < 0 || attr_len > val_len) {
+ if (val_len < 0 || attr_len < 0 || attr_len > val_len) {
zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno);
- ret = 1 + (attr_len > val_len || attr_len < 0);
+ ret = 1 + ((val_len > 0 && attr_len > val_len) || attr_len < 0);
}
return ret;
}
@@ -189,24 +186,20 @@ bin_listattr(char *nam, char **argv, Options ops, UNUSED(int func))
if (list_len > 0 && list_len <= val_len) {
char *p = value;
if (param) {
- if (strlen(value) + 1 == list_len)
- setsparam(param, metafy(value, list_len-1, META_DUP));
- else {
- int arrlen = 0;
- char **array = NULL, **arrptr = NULL;
+ int arrlen = 0;
+ char **array = NULL, **arrptr = NULL;
- while (p < &value[list_len]) {
- arrlen++;
- p += strlen(p) + 1;
- }
- arrptr = array = (char **)zshcalloc((arrlen+1) * sizeof(char *));
- p = value;
- while (p < &value[list_len]) {
- *arrptr++ = metafy(p, -1, META_DUP);
- p += strlen(p) + 1;
- }
- setaparam(param, array);
+ while (p < &value[list_len]) {
+ arrlen++;
+ p += strlen(p) + 1;
+ }
+ arrptr = array = (char **)zshcalloc((arrlen+1) * sizeof(char *));
+ p = value;
+ while (p < &value[list_len]) {
+ *arrptr++ = metafy(p, -1, META_DUP);
+ p += strlen(p) + 1;
}
+ setaparam(param, array);
} else while (p < &value[list_len]) {
printf("%s\n", p);
p += strlen(p) + 1;
diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c
index 00ebd2b49..63a04dc89 100644
--- a/Src/Modules/datetime.c
+++ b/Src/Modules/datetime.c
@@ -94,7 +94,7 @@ reverse_strftime(char *nam, char **argv, char *scalar, int quiet)
}
static int
-bin_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
+output_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
{
int bufsize, x;
char *endptr = NULL, *scalar = NULL, *buffer;
@@ -145,6 +145,25 @@ bin_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
return 0;
}
+static int
+bin_strftime(char *nam, char **argv, Options ops, int func)
+{
+ int result = 1;
+ char *tz = getsparam("TZ");
+
+ startparamscope();
+ if (tz && *tz) {
+ Param pm = createparam("TZ", PM_LOCAL|PM_SCALAR|PM_EXPORTED);
+ if (pm)
+ pm->level = locallevel; /* because createparam() doesn't */
+ setsparam("TZ", ztrdup(tz));
+ }
+ result = output_strftime(nam, argv, ops, func);
+ endparamscope();
+
+ return result;
+}
+
static zlong
getcurrentsecs(UNUSED(Param pm))
{
diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c
index 9a2a7a5b9..76d4751bf 100644
--- a/Src/Modules/db_gdbm.c
+++ b/Src/Modules/db_gdbm.c
@@ -39,16 +39,17 @@
#include <gdbm.h>
-#if 0 /* what is this for? */
static char *backtype = "db/gdbm";
-#endif
static const struct gsu_scalar gdbm_gsu =
{ gdbmgetfn, gdbmsetfn, gdbmunsetfn };
+/**/
+static const struct gsu_hash gdbm_hash_gsu =
+{ hashgetfn, gdbmhashsetfn, gdbmhashunsetfn };
static struct builtin bintab[] = {
- BUILTIN("ztie", 0, bin_ztie, 1, -1, 0, "d:f:", NULL),
- BUILTIN("zuntie", 0, bin_zuntie, 1, -1, 0, NULL, NULL),
+ BUILTIN("ztie", 0, bin_ztie, 1, -1, 0, "d:f:r", NULL),
+ BUILTIN("zuntie", 0, bin_zuntie, 1, -1, 0, "u", NULL),
};
/**/
@@ -57,36 +58,67 @@ bin_ztie(char *nam, char **args, Options ops, UNUSED(int func))
{
char *resource_name, *pmname;
GDBM_FILE dbf = NULL;
+ int read_write = GDBM_SYNC, pmflags = PM_REMOVABLE;
Param tied_param;
if(!OPT_ISSET(ops,'d')) {
- zwarnnam(nam, "you must pass `-d db/gdbm' to ztie", NULL);
+ zwarnnam(nam, "you must pass `-d %s'", backtype);
return 1;
}
if(!OPT_ISSET(ops,'f')) {
- zwarnnam(nam, "you must pass `-f' with a filename to ztie", NULL);
+ zwarnnam(nam, "you must pass `-f' with a filename", NULL);
return 1;
}
+ if (OPT_ISSET(ops,'r')) {
+ read_write |= GDBM_READER;
+ pmflags |= PM_READONLY;
+ } else {
+ read_write |= GDBM_WRCREAT;
+ }
/* Here should be a lookup of the backend type against
* a registry.
*/
-
- pmname = ztrdup(*args);
+ if (strcmp(OPT_ARG(ops, 'd'), backtype) != 0) {
+ zwarnnam(nam, "unsupported backend type `%s'", OPT_ARG(ops, 'd'));
+ return 1;
+ }
resource_name = OPT_ARG(ops, 'f');
+ pmname = *args;
+
+ if ((tied_param = (Param)paramtab->getnode(paramtab, pmname)) &&
+ !(tied_param->node.flags & PM_UNSET)) {
+ /*
+ * Unset any existing parameter. Note there's no implicit
+ * "local" here, but if the existing parameter is local
+ * that will be reflected in the new one.
+ *
+ * We need to do this before attempting to open the DB
+ * in case this variable is already tied to a DB.
+ *
+ * This can fail if the variable is readonly or restricted.
+ * We could call unsetparam() and check errflag instead
+ * of the return status.
+ */
+ if (unsetparam_pm(tied_param, 0, 1))
+ return 1;
+ }
- if (!(tied_param = createspecialhash(pmname, &getgdbmnode, &scangdbmkeys, 0))) {
- zwarnnam(nam, "cannot create the requested parameter name", NULL);
+ dbf = gdbm_open(resource_name, 0, read_write, 0666, 0);
+ if(!dbf) {
+ zwarnnam(nam, "error opening database file %s", resource_name);
return 1;
}
- dbf = gdbm_open(resource_name, 0, GDBM_WRCREAT | GDBM_SYNC, 0666, 0);
- if(!dbf) {
- zwarnnam(nam, "error opening database file %s", resource_name);
+ if (!(tied_param = createspecialhash(pmname, &getgdbmnode, &scangdbmkeys,
+ pmflags))) {
+ zwarnnam(nam, "cannot create the requested parameter %s", pmname);
+ gdbm_close(dbf);
return 1;
}
+ tied_param->gsu.h = &gdbm_hash_gsu;
tied_param->u.hash->tmpdata = (void *)dbf;
return 0;
@@ -97,20 +129,33 @@ static int
bin_zuntie(char *nam, char **args, Options ops, UNUSED(int func))
{
Param pm;
- GDBM_FILE dbf;
-
- pm = (Param) paramtab->getnode(paramtab, args[0]);
- if(!pm) {
- zwarnnam(nam, "cannot untie %s", args[0]);
- return 1;
+ char *pmname;
+ int ret = 0;
+
+ for (pmname = *args; *args++; pmname = *args) {
+ pm = (Param) paramtab->getnode(paramtab, pmname);
+ if(!pm) {
+ zwarnnam(nam, "cannot untie %s", pmname);
+ ret = 1;
+ continue;
+ }
+ if (pm->gsu.h != &gdbm_hash_gsu) {
+ zwarnnam(nam, "not a tied gdbm hash: %s", pmname);
+ ret = 1;
+ continue;
+ }
+
+ queue_signals();
+ if (OPT_ISSET(ops,'u'))
+ gdbmuntie(pm); /* clear read-only-ness */
+ if (unsetparam_pm(pm, 0, 1)) {
+ /* assume already reported */
+ ret = 1;
+ }
+ unqueue_signals();
}
- dbf = (GDBM_FILE)(pm->u.hash->tmpdata);
- gdbm_close(dbf);
-/* free(pm->u.hash->tmpdata); */
- paramtab->removenode(paramtab, pm->node.nam);
-
- return 0;
+ return ret;
}
/**/
@@ -153,7 +198,7 @@ gdbmsetfn(Param pm, char *val)
/**/
static void
-gdbmunsetfn(Param pm, int um)
+gdbmunsetfn(Param pm, UNUSED(int um))
{
datum key;
GDBM_FILE dbf;
@@ -191,9 +236,7 @@ scangdbmkeys(HashTable ht, ScanFunc func, int flags)
{
Param pm = NULL;
datum key, content;
- GDBM_FILE dbf;
-
- dbf = (GDBM_FILE)(ht->tmpdata);
+ GDBM_FILE dbf = (GDBM_FILE)(ht->tmpdata);
pm = (Param) hcalloc(sizeof(struct param));
@@ -216,6 +259,89 @@ scangdbmkeys(HashTable ht, ScanFunc func, int flags)
}
+/**/
+static void
+gdbmhashsetfn(Param pm, HashTable ht)
+{
+ int i;
+ HashNode hn;
+ GDBM_FILE dbf;
+ datum key, content;
+
+ if (!pm->u.hash || pm->u.hash == ht)
+ return;
+
+ if (!(dbf = (GDBM_FILE)(pm->u.hash->tmpdata)))
+ return;
+
+ key = gdbm_firstkey(dbf);
+ while (key.dptr) {
+ queue_signals();
+ (void)gdbm_delete(dbf, key);
+ free(key.dptr);
+ unqueue_signals();
+ key = gdbm_firstkey(dbf);
+ }
+
+ /* just deleted everything, clean up */
+ (void)gdbm_reorganize(dbf);
+
+ if (!ht)
+ return;
+
+ for (i = 0; i < ht->hsize; i++)
+ for (hn = ht->nodes[i]; hn; hn = hn->next) {
+ struct value v;
+
+ v.isarr = v.flags = v.start = 0;
+ v.end = -1;
+ v.arr = NULL;
+ v.pm = (Param) hn;
+
+ key.dptr = v.pm->node.nam;
+ key.dsize = strlen(key.dptr) + 1;
+
+ queue_signals();
+
+ content.dptr = getstrvalue(&v);
+ content.dsize = strlen(content.dptr) + 1;
+
+ (void)gdbm_store(dbf, key, content, GDBM_REPLACE);
+
+ unqueue_signals();
+ }
+}
+
+/**/
+static void
+gdbmuntie(Param pm)
+{
+ GDBM_FILE dbf = (GDBM_FILE)(pm->u.hash->tmpdata);
+ HashTable ht = pm->u.hash;
+
+ if (dbf) /* paranoia */
+ gdbm_close(dbf);
+
+ ht->tmpdata = NULL;
+
+ /* for completeness ... createspecialhash() should have an inverse */
+ ht->getnode = ht->getnode2 = gethashnode2;
+ ht->scantab = NULL;
+
+ pm->node.flags &= ~(PM_SPECIAL|PM_READONLY);
+ pm->gsu.h = &stdhash_gsu;
+}
+
+/**/
+static void
+gdbmhashunsetfn(Param pm, UNUSED(int exp))
+{
+ gdbmuntie(pm);
+ /* hash table is now normal, so proceed normally... */
+ pm->gsu.h->setfn(pm, NULL);
+ pm->node.flags |= PM_UNSET;
+}
+
#else
# error no gdbm
#endif /* have gdbm */
diff --git a/Src/Modules/langinfo.c b/Src/Modules/langinfo.c
index f10fdfef5..eb45d161b 100644
--- a/Src/Modules/langinfo.c
+++ b/Src/Modules/langinfo.c
@@ -395,7 +395,8 @@ liitem(const char *name)
static HashNode
getlanginfo(UNUSED(HashTable ht), const char *name)
{
- int len, *elem;
+ int len;
+ nl_item *elem;
char *listr, *nameu;
Param pm = NULL;
diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c
index 3f92050ae..0d9522047 100644
--- a/Src/Modules/tcp.c
+++ b/Src/Modules/tcp.c
@@ -623,6 +623,7 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
zthost = zsh_getipnodebyname(desthost, AF_INET, 0, &herrno);
if (!zthost || errflag) {
zwarnnam(nam, "host resolution failure: %s", desthost);
+ zsfree(desthost);
return 1;
}
@@ -630,6 +631,7 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
if (!sess) {
zwarnnam(nam, "unable to allocate a TCP session slot");
+ zsfree(desthost);
return 1;
}
@@ -665,6 +667,8 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
sess->fd = redup(sess->fd, targetfd);
if (sess->fd < 0) {
zerrnam(nam, "could not duplicate socket fd to %d: %e", targetfd, errno);
+ zsfree(desthost);
+ tcp_close(sess);
return 1;
}
}
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index d16e2f618..09d4bd703 100644
--- a/Src/Modules/zftp.c
+++ b/Src/Modules/zftp.c
@@ -50,7 +50,6 @@ struct zftp_session;
typedef struct zftp_session *Zftp_session;
#include "tcp.h"
-#include "tcp.mdh"
#include "zftp.mdh"
#include "zftp.pro"
diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c
index d119658c3..7b6130c6f 100644
--- a/Src/Modules/zpty.c
+++ b/Src/Modules/zpty.c
@@ -189,7 +189,11 @@ get_pty(int master, int *retfd)
#endif
if (master) {
+#ifdef HAVE_POSIX_OPENPT
+ if ((mfd = posix_openpt(O_RDWR|O_NOCTTY)) < 0)
+#else
if ((mfd = open("/dev/ptmx", O_RDWR|O_NOCTTY)) < 0)
+#endif
return 1;
if (grantpt(mfd) || unlockpt(mfd) || !(name = ptsname(mfd))) {
@@ -304,7 +308,7 @@ newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
prog = parse_string(zjoin(args, ' ', 1), 0);
if (!prog) {
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
scriptname = oscriptname;
ineval = oineval;
return 1;
diff --git a/Src/Modules/zselect.c b/Src/Modules/zselect.c
index c02074646..30a3f51a5 100644
--- a/Src/Modules/zselect.c
+++ b/Src/Modules/zselect.c
@@ -251,7 +251,7 @@ bin_zselect(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
outptr = outdata = (char **)zalloc((fdcount+1)*sizeof(char *));
while (nonempty(fdlist))
*outptr++ = getlinknode(fdlist);
- *outptr = '\0';
+ *outptr = NULL;
/* and store in array parameter */
if (outhash)
sethparam(outhash, outdata);
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index 1cca0c4b8..c89495070 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -301,7 +301,8 @@ setstypat(Style s, char *pat, Patprog prog, char **vals, int eval)
int ef = errflag;
eprog = parse_string(zjoin(vals, ' ', 1), 0);
- errflag = ef;
+ /* Keep any user interrupt error status */
+ errflag = ef | (errflag & ERRFLAG_INT);
if (!eprog)
{
@@ -394,10 +395,11 @@ evalstyle(Stypat p)
unsetparam("reply");
execode(p->eval, 1, 0, "style");
if (errflag) {
- errflag = ef;
+ /* Keep any user interrupt error status */
+ errflag = ef | (errflag & ERRFLAG_INT);
return NULL;
}
- errflag = ef;
+ errflag = ef | (errflag & ERRFLAG_INT);
queue_signals();
if ((ret = getaparam("reply")))