about summary refs log tree commit diff
path: root/Src/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Modules')
-rw-r--r--Src/Modules/.distfiles1
-rw-r--r--Src/Modules/example.c8
-rw-r--r--Src/Modules/parameter.c662
-rw-r--r--Src/Modules/parameter.mdd3
-rw-r--r--Src/Modules/stat.c12
-rw-r--r--Src/Modules/zftp.c135
6 files changed, 759 insertions, 62 deletions
diff --git a/Src/Modules/.distfiles b/Src/Modules/.distfiles
index 23c7eae3f..dbc152fa8 100644
--- a/Src/Modules/.distfiles
+++ b/Src/Modules/.distfiles
@@ -4,6 +4,7 @@ DISTFILES_SRC='
     clone.mdd clone.c
     example.mdd example.c
     files.mdd files.c
+    parameter.mdd parameter.c
     stat.mdd stat.c
     zftp.mdd zftp.c
 '
diff --git a/Src/Modules/example.c b/Src/Modules/example.c
index 50b8c1626..1b24f336c 100644
--- a/Src/Modules/example.c
+++ b/Src/Modules/example.c
@@ -32,7 +32,7 @@
 
 /* parameters */
 
-static long intparam;
+static zlong intparam;
 static char *strparam;
 static char **arrparam;
 
@@ -55,7 +55,11 @@ bin_example(char *nam, char **args, char *ops, int func)
 	fputs(*args, stdout);
     }
     printf("\nName: %s\n", nam);
+#ifdef ZSH_64_BIT_TYPE
+    printf("\nInteger Parameter: %s\n", output64(intparam));
+#else
     printf("\nInteger Parameter: %ld\n", intparam);
+#endif
     printf("String Parameter: %s\n", strparam ? strparam : "");
     printf("Array Parameter:");
     if (p)
@@ -79,7 +83,7 @@ cond_p_len(char **a, int id)
     char *s1 = cond_str(a, 0);
 
     if (a[1]) {
-	long v = cond_val(a, 1);
+	zlong v = cond_val(a, 1);
 
 	return strlen(s1) == v;
     } else {
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
new file mode 100644
index 000000000..2257933f5
--- /dev/null
+++ b/Src/Modules/parameter.c
@@ -0,0 +1,662 @@
+/*
+ * parameter.c - parameter interface to zsh internals
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 1999 Sven Wischnowsky
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Sven Wischnowsky or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Sven Wischnowsky and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Sven Wischnowsky and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose.  The software
+ * provided hereunder is on an "as is" basis, and Sven Wischnowsky and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+
+#include "parameter.mdh"
+#include "parameter.pro"
+
+/* Empty dummy function for special hash parameters. */
+
+/**/
+static void
+shempty(void)
+{
+}
+
+/* Create a simple special hash parameter. */
+
+/**/
+static Param
+createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan)
+{
+    Param pm;
+    HashTable ht;
+
+    if (!(pm = createparam(name, PM_SPECIAL|PM_REMOVABLE|PM_HASHED)))
+	return NULL;
+
+    pm->level = pm->old ? locallevel : 0;
+    pm->gets.hfn = hashgetfn;
+    pm->sets.hfn = hashsetfn;
+    pm->unsetfn = stdunsetfn;
+    pm->u.hash = ht = newhashtable(7, name, NULL);
+
+    ht->hash        = hasher;
+    ht->emptytable  = (TableFunc) shempty;
+    ht->filltable   = NULL;
+    ht->addnode     = (AddNodeFunc) shempty;
+    ht->getnode     = ht->getnode2 = get;
+    ht->removenode  = (RemoveNodeFunc) shempty;
+    ht->disablenode = NULL;
+    ht->enablenode  = NULL;
+    ht->freenode    = (FreeNodeFunc) shempty;
+    ht->printnode   = printparamnode;
+    ht->scantab     = scan;
+
+    return pm;
+}
+
+/* Functions for the parameters special parameter. */
+
+/* Return a string describing the type of a parameter. */
+
+/**/
+static char *
+paramtypestr(Param pm)
+{
+    char *val = NULL;
+    int f = pm->flags;
+
+    if (!(f & PM_UNSET)) {
+	switch (PM_TYPE(f)) {
+	case PM_SCALAR:  val = "scalar"; break;
+	case PM_ARRAY:   val = "array"; break;
+	case PM_INTEGER: val = "integer"; break;
+	case PM_HASHED:  val = "association"; break;
+	}
+	DPUTS(!val, "BUG: type not handled in parameter");
+	val = dupstring(val);
+	if (f & PM_LEFT)
+	    val = dyncat(val, "-left");
+	if (f & PM_RIGHT_B)
+	    val = dyncat(val, "-right_blanks");
+	if (f & PM_RIGHT_Z)
+	    val = dyncat(val, "-right_zeros");
+	if (f & PM_LOWER)
+	    val = dyncat(val, "-lower");
+	if (f & PM_UPPER)
+	    val = dyncat(val, "-upper");
+	if (f & PM_READONLY)
+	    val = dyncat(val, "-readonly");
+	if (f & PM_TAGGED)
+	    val = dyncat(val, "-tag");
+	if (f & PM_EXPORTED)
+	    val = dyncat(val, "-export");
+	if (f & PM_UNIQUE)
+	    val = dyncat(val, "-unique");
+    } else
+	val = dupstring("");
+
+    return val;
+}
+
+/**/
+static HashNode
+getpmparameter(HashTable ht, char *name)
+{
+    Param rpm, pm = NULL;
+
+    HEAPALLOC {
+	pm = (Param) zhalloc(sizeof(struct param));
+	pm->nam = dupstring(name);
+	pm->flags = PM_SCALAR | PM_READONLY;
+	pm->sets.cfn = NULL;
+	pm->gets.cfn = strgetfn;
+	pm->unsetfn = NULL;
+	pm->ct = 0;
+	pm->env = NULL;
+	pm->ename = NULL;
+	pm->old = NULL;
+	pm->level = 0;
+	if ((rpm = (Param) realparamtab->getnode(realparamtab, name)) &&
+	    !(rpm->flags & PM_UNSET))
+	    pm->u.str = paramtypestr(rpm);
+	else {
+	    pm->u.str = "";
+	    pm->flags |= PM_UNSET;
+	}
+    } LASTALLOC;
+
+    return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmparameters(HashTable ht, ScanFunc func, int flags)
+{
+    struct param pm;
+    int i;
+    HashNode hn;
+
+    pm.flags = PM_SCALAR | PM_READONLY;
+    pm.sets.cfn = NULL;
+    pm.gets.cfn = strgetfn;
+    pm.unsetfn = NULL;
+    pm.ct = 0;
+    pm.env = NULL;
+    pm.ename = NULL;
+    pm.old = NULL;
+    pm.level = 0;
+
+    for (i = 0; i < realparamtab->hsize; i++)
+	for (hn = realparamtab->nodes[i]; hn; hn = hn->next) {
+	    pm.nam = hn->nam;
+	    if (func != scancountparams)
+		pm.u.str = paramtypestr((Param) hn);
+	    func((HashNode) &pm, flags);
+	}
+}
+
+/* Functions for the commands special parameter. */
+
+/**/
+static void
+setpmcommand(Param pm, char *value)
+{
+    if (isset(RESTRICTED))
+	zwarnnam(NULL, "restricted: %s", value, 0);
+    else {
+	Cmdnam cn = zcalloc(sizeof(*cn));
+
+	cn->flags = HASHED;
+	cn->u.cmd = ztrdup(value);
+
+	cmdnamtab->addnode(cmdnamtab, ztrdup(pm->nam), (HashNode) cn);
+    }
+}
+
+/**/
+static void
+unsetpmcommand(Param pm, int exp)
+{
+    HashNode hn = cmdnamtab->removenode(cmdnamtab, pm->nam);
+
+    if (hn)
+	cmdnamtab->freenode(hn);
+}
+
+/**/
+static void
+setpmcommands(Param pm, HashTable ht)
+{
+    int i;
+    HashNode hn;
+
+    for (i = 0; i < ht->hsize; i++)
+	for (hn = ht->nodes[i]; hn; hn = hn->next) {
+	    Cmdnam cn = zcalloc(sizeof(*cn));
+	    struct value v;
+
+	    v.isarr = v.inv = v.a = 0;
+	    v.b = -1;
+	    v.arr = NULL;
+	    v.pm = (Param) hn;
+
+	    cn->flags = HASHED;
+	    cn->u.cmd = ztrdup(getstrvalue(&v));
+
+	    cmdnamtab->addnode(cmdnamtab, ztrdup(hn->nam), (HashNode) cn);
+	}
+}
+
+/**/
+static HashNode
+getpmcommand(HashTable ht, char *name)
+{
+    Cmdnam cmd;
+    Param pm = NULL;
+
+    if (!(cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name)) &&
+	isset(HASHLISTALL)) {
+	cmdnamtab->filltable(cmdnamtab);
+	cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name);
+    }
+    HEAPALLOC {
+	pm = (Param) zhalloc(sizeof(struct param));
+	pm->nam = dupstring(name);
+	pm->flags = PM_SCALAR;
+	pm->sets.cfn = setpmcommand;
+	pm->gets.cfn = strgetfn;
+	pm->unsetfn = unsetpmcommand;
+	pm->ct = 0;
+	pm->env = NULL;
+	pm->ename = NULL;
+	pm->old = NULL;
+	pm->level = 0;
+	if (cmd) {
+	    if (cmd->flags & HASHED)
+		pm->u.str = cmd->u.cmd;
+	    else {
+		pm->u.str = zhalloc(strlen(*(cmd->u.name)) +
+				    strlen(name) + 2);
+		strcpy(pm->u.str, *(cmd->u.name));
+		strcat(pm->u.str, "/");
+		strcat(pm->u.str, name);
+	    }
+	} else {
+	    pm->u.str = "";
+	    pm->flags |= PM_UNSET;
+	}
+    } LASTALLOC;
+
+    return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmcommands(HashTable ht, ScanFunc func, int flags)
+{
+    struct param pm;
+    int i;
+    HashNode hn;
+    Cmdnam cmd;
+
+    if (isset(HASHLISTALL))
+	cmdnamtab->filltable(cmdnamtab);
+
+    pm.flags = PM_SCALAR;
+    pm.sets.cfn = setpmcommand;
+    pm.gets.cfn = strgetfn;
+    pm.unsetfn = unsetpmcommand;
+    pm.ct = 0;
+    pm.env = NULL;
+    pm.ename = NULL;
+    pm.old = NULL;
+    pm.level = 0;
+
+    for (i = 0; i < cmdnamtab->hsize; i++)
+	for (hn = cmdnamtab->nodes[i]; hn; hn = hn->next) {
+	    pm.nam = hn->nam;
+	    cmd = (Cmdnam) hn;
+	    if (func != scancountparams) {
+		if (cmd->flags & HASHED)
+		    pm.u.str = cmd->u.cmd;
+		else {
+		    pm.u.str = zhalloc(strlen(*(cmd->u.name)) +
+				       strlen(cmd->nam) + 2);
+		    strcpy(pm.u.str, *(cmd->u.name));
+		    strcat(pm.u.str, "/");
+		    strcat(pm.u.str, cmd->nam);
+		}
+	    }
+	    func((HashNode) &pm, flags);
+	}
+}
+
+/* Functions for the functions special parameter. */
+
+/**/
+static void
+setfunction(char *name, char *value)
+{
+    char *val;
+    Shfunc shf;
+    List list;
+    int sn;
+
+    val = ztrdup(value);
+    val = metafy(val, strlen(val), META_REALLOC);
+
+    HEAPALLOC {
+	list = parse_string(val);
+    } LASTALLOC;
+
+    if (!list || list == &dummy_list) {
+	zwarnnam(NULL, "invalid function definition", val, 0);
+	zsfree(val);
+	return;
+    }
+    PERMALLOC {
+	shf = (Shfunc) zalloc(sizeof(*shf));
+	shf->funcdef = (List) dupstruct(list);
+	shf->flags = 0;
+
+	if (!strncmp(name, "TRAP", 4) &&
+	    (sn = getsignum(name + 4)) != -1) {
+	    if (settrap(sn, shf->funcdef)) {
+		freestruct(shf->funcdef);
+		zfree(shf, sizeof(*shf));
+		zsfree(val);
+		LASTALLOC_RETURN;
+	    }
+	    sigtrapped[sn] |= ZSIG_FUNC;
+	}
+	shfunctab->addnode(shfunctab, ztrdup(name), shf);
+    } LASTALLOC;
+
+    zsfree(val);
+}
+
+/**/
+static void
+setpmfunction(Param pm, char *value)
+{
+    setfunction(pm->nam, value);
+}
+
+/**/
+static void
+unsetpmfunction(Param pm, int exp)
+{
+    HashNode hn = shfunctab->removenode(shfunctab, pm->nam);
+
+    if (hn)
+	shfunctab->freenode(hn);
+}
+
+/**/
+static void
+setpmfunctions(Param pm, HashTable ht)
+{
+    int i;
+    HashNode hn;
+
+    for (i = 0; i < ht->hsize; i++)
+	for (hn = ht->nodes[i]; hn; hn = hn->next) {
+	    struct value v;
+
+	    v.isarr = v.inv = v.a = 0;
+	    v.b = -1;
+	    v.arr = NULL;
+	    v.pm = (Param) hn;
+
+	    setfunction(hn->nam, getstrvalue(&v));
+	}
+}
+
+/**/
+static HashNode
+getpmfunction(HashTable ht, char *name)
+{
+    Shfunc shf;
+    Param pm = NULL;
+
+    HEAPALLOC {
+	pm = (Param) zhalloc(sizeof(struct param));
+	pm->nam = dupstring(name);
+	pm->flags = PM_SCALAR;
+	pm->sets.cfn = setpmfunction;
+	pm->gets.cfn = strgetfn;
+	pm->unsetfn = unsetpmfunction;
+	pm->ct = 0;
+	pm->env = NULL;
+	pm->ename = NULL;
+	pm->old = NULL;
+	pm->level = 0;
+
+	if ((shf = (Shfunc) shfunctab->getnode(shfunctab, name))) {
+	    if (shf->flags & PM_UNDEFINED)
+		pm->u.str = "undefined";
+	    else {
+		char *t = getpermtext((void *) dupstruct((void *)
+							 shf->funcdef)), *h;
+
+		h = dupstring(t);
+		zsfree(t);
+		unmetafy(h, NULL);
+
+		pm->u.str = h;
+	    }
+	} else {
+	    pm->u.str = "";
+	    pm->flags |= PM_UNSET;
+	}
+    } LASTALLOC;
+
+    return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmfunctions(HashTable ht, ScanFunc func, int flags)
+{
+    struct param pm;
+    int i;
+    HashNode hn;
+
+    pm.flags = PM_SCALAR;
+    pm.sets.cfn = setpmcommand;
+    pm.gets.cfn = strgetfn;
+    pm.unsetfn = unsetpmcommand;
+    pm.ct = 0;
+    pm.env = NULL;
+    pm.ename = NULL;
+    pm.old = NULL;
+    pm.level = 0;
+
+    for (i = 0; i < shfunctab->hsize; i++)
+	for (hn = shfunctab->nodes[i]; hn; hn = hn->next) {
+	    if (!(hn->flags & DISABLED)) {
+		pm.nam = hn->nam;
+		if (func != scancountparams) {
+		    if (((Shfunc) hn)->flags & PM_UNDEFINED)
+			pm.u.str = "undefined";
+		    else {
+			char *t = getpermtext((void *)
+					      dupstruct((void *) ((Shfunc) hn)->funcdef));
+
+			unmetafy((pm.u.str = dupstring(t)), NULL);
+			zsfree(t);
+		    }
+		}
+		func((HashNode) &pm, flags);
+	    }
+	}
+}
+
+/* Functions for the options special parameter. */
+
+/**/
+static void
+setpmoption(Param pm, char *value)
+{
+    int n;
+
+    if (!value || (strcmp(value, "on") && strcmp(value, "off")))
+	zwarnnam(NULL, "invalid value: %s", value, 0);
+    else if (!(n = optlookup(pm->nam)))
+	zwarnnam(NULL, "no such option: %s", pm->nam, 0);
+    else if (dosetopt(n, (value && strcmp(value, "off")), 0))
+	zwarnnam(NULL, "can't change option: %s", pm->nam, 0);
+}
+
+/**/
+static void
+unsetpmoption(Param pm, int exp)
+{
+    int n;
+
+    if (!(n = optlookup(pm->nam)))
+	zwarnnam(NULL, "no such option: %s", pm->nam, 0);
+    else if (dosetopt(n, 0, 0))
+	zwarnnam(NULL, "can't change option: %s", pm->nam, 0);
+}
+
+/**/
+static void
+setpmoptions(Param pm, HashTable ht)
+{
+    int i;
+    HashNode hn;
+
+    for (i = 0; i < ht->hsize; i++)
+	for (hn = ht->nodes[i]; hn; hn = hn->next) {
+	    struct value v;
+	    char *val;
+
+	    v.isarr = v.inv = v.a = 0;
+	    v.b = -1;
+	    v.arr = NULL;
+	    v.pm = (Param) hn;
+
+	    val = getstrvalue(&v);
+	    if (!val || (strcmp(val, "on") && strcmp(val, "off")))
+		zwarnnam(NULL, "invalid value: %s", val, 0);
+	    else if (dosetopt(optlookup(hn->nam),
+			      (val && strcmp(val, "off")), 0))
+		zwarnnam(NULL, "can't change option: %s", hn->nam, 0);
+	}
+}
+
+/**/
+static HashNode
+getpmoption(HashTable ht, char *name)
+{
+    Param pm = NULL;
+    int n;
+
+    HEAPALLOC {
+	pm = (Param) zhalloc(sizeof(struct param));
+	pm->nam = dupstring(name);
+	pm->flags = PM_SCALAR;
+	pm->sets.cfn = setpmoption;
+	pm->gets.cfn = strgetfn;
+	pm->unsetfn = unsetpmoption;
+	pm->ct = 0;
+	pm->env = NULL;
+	pm->ename = NULL;
+	pm->old = NULL;
+	pm->level = 0;
+
+	if ((n = optlookup(name)))
+	    pm->u.str = dupstring(opts[n] ? "on" : "off");
+	else {
+	    pm->u.str = "";
+	    pm->flags |= PM_UNSET;
+	}
+    } LASTALLOC;
+
+    return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmoptions(HashTable ht, ScanFunc func, int flags)
+{
+    struct param pm;
+    int i;
+    HashNode hn;
+
+    pm.flags = PM_SCALAR;
+    pm.sets.cfn = setpmoption;
+    pm.gets.cfn = strgetfn;
+    pm.unsetfn = unsetpmoption;
+    pm.ct = 0;
+    pm.env = NULL;
+    pm.ename = NULL;
+    pm.old = NULL;
+    pm.level = 0;
+
+    for (i = 0; i < optiontab->hsize; i++)
+	for (hn = optiontab->nodes[i]; hn; hn = hn->next) {
+	    pm.nam = hn->nam;
+	    pm.u.str = opts[((Optname) hn)->optno] ? "on" : "off";
+	    func((HashNode) &pm, flags);
+	}
+}
+
+/* Names and Params for the special parameters. */
+
+#define PAR_NAM "parameters"
+#define CMD_NAM "commands"
+#define FUN_NAM "functions"
+#define OPT_NAM "options"
+
+static Param parpm, cmdpm, funpm, optpm;
+
+/**/
+int
+setup_parameter(Module m)
+{
+    return 0;
+}
+
+/**/
+int
+boot_parameter(Module m)
+{
+    /* Create the special associative arrays.
+     * As an example for autoloaded parameters, this is probably a bad
+     * example, because we the zsh core doesn't support creation of
+     * special hashes, yet. */
+
+    unsetparam(PAR_NAM);
+    if (!(parpm = createspecialhash(PAR_NAM, getpmparameter,
+				    scanpmparameters)))
+	return 1;
+    parpm->flags |= PM_READONLY;
+    unsetparam(CMD_NAM);
+    if (!(cmdpm = createspecialhash(CMD_NAM, getpmcommand,
+				    scanpmcommands)))
+	return 1;
+    cmdpm->sets.hfn = setpmcommands;
+    unsetparam(FUN_NAM);
+    if (!(funpm = createspecialhash(FUN_NAM, getpmfunction,
+				    scanpmfunctions)))
+	return 1;
+    funpm->sets.hfn = setpmfunctions;
+    unsetparam(OPT_NAM);
+    if (!(optpm = createspecialhash(OPT_NAM, getpmoption,
+				    scanpmoptions)))
+	return 1;
+    optpm->sets.hfn = setpmoptions;
+
+    return 0;
+}
+
+#ifdef MODULE
+
+/**/
+int
+cleanup_parameter(Module m)
+{
+    Param pm;
+
+    /* Remove the special parameters if they are still the same. */
+
+    if ((pm = (Param) paramtab->getnode(paramtab, PAR_NAM)) && pm == parpm) {
+	pm->flags &= ~PM_READONLY;
+	unsetparam_pm(pm, 0, 1);
+    }
+    if ((pm = (Param) paramtab->getnode(paramtab, CMD_NAM)) && pm == cmdpm)
+	unsetparam_pm(pm, 0, 1);
+    if ((pm = (Param) paramtab->getnode(paramtab, FUN_NAM)) && pm == funpm)
+	unsetparam_pm(pm, 0, 1);
+    if ((pm = (Param) paramtab->getnode(paramtab, OPT_NAM)) && pm == optpm)
+	unsetparam_pm(pm, 0, 1);
+    return 0;
+}
+
+/**/
+int
+finish_parameter(Module m)
+{
+    return 0;
+}
+
+#endif
diff --git a/Src/Modules/parameter.mdd b/Src/Modules/parameter.mdd
new file mode 100644
index 000000000..e2820aa9c
--- /dev/null
+++ b/Src/Modules/parameter.mdd
@@ -0,0 +1,3 @@
+autoparams="parameters commands functions options"
+
+objects="parameter.o"
diff --git a/Src/Modules/stat.c b/Src/Modules/stat.c
index 6f80e2a96..d8179143e 100644
--- a/Src/Modules/stat.c
+++ b/Src/Modules/stat.c
@@ -213,7 +213,13 @@ statprint(struct stat *sbuf, char *outbuf, char *fname, int iwhich, int flags)
 	break;
 
     case ST_INO:
+#ifdef INO_T_IS_64_BIT
+	convbase(optr, sbuf->st_ino, 0);
+#else
+	DPUTS(sizeof(sbuf->st_ino) > 4,
+	      "Shell compiled with wrong ino_t size");
 	statulprint((unsigned long)sbuf->st_ino, optr);
+#endif
 	break;
 
     case ST_MODE:
@@ -237,7 +243,13 @@ statprint(struct stat *sbuf, char *outbuf, char *fname, int iwhich, int flags)
 	break;
 
     case ST_SIZE:
+#ifdef OFF_T_IS_64_BIT
+	convbase(optr, sbuf->st_size, 0);
+#else
+	DPUTS(sizeof(sbuf->st_size) > 4,
+	      "Shell compiled with wrong off_t size");
 	statulprint((unsigned long)sbuf->st_size, optr);
+#endif
 	break;
 
     case ST_ATIM:
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index 651a5c952..873617e95 100644
--- a/Src/Modules/zftp.c
+++ b/Src/Modules/zftp.c
@@ -117,7 +117,7 @@ enum {
     ZFHD_EORB = 128		/* block is end of file */
 };
 
-typedef int (*readwrite_t)(int, char *, size_t, int);
+typedef int (*readwrite_t)(int, char *, off_t, int);
 
 struct zftpcmd {
     const char *nam;
@@ -195,7 +195,7 @@ static char *zfparams[] = {
 enum {
     ZFPM_READONLY = 0x01,	/* make parameter readonly */
     ZFPM_IFUNSET  = 0x02,	/* only set if not already set */
-    ZFPM_INTEGER  = 0x04	/* passed pointer to long */
+    ZFPM_INTEGER  = 0x04	/* passed pointer to off_t */
 };
 
 /*
@@ -250,25 +250,26 @@ static int zfhas_size, zfhas_mdtm;
  * --- we don't try to track it because it's too complicated.
  */
 enum {
-    ZFST_ASCI = 0x00,		/* type for next transfer is ASCII */
-    ZFST_IMAG = 0x01,		/* type for next transfer is image */
+    ZFST_ASCI = 0x0000,		/* type for next transfer is ASCII */
+    ZFST_IMAG = 0x0001,		/* type for next transfer is image */
 
-    ZFST_TMSK = 0x01,		/* mask for type flags */
-    ZFST_TBIT = 0x01,		/* number of bits in type flags */
+    ZFST_TMSK = 0x0001,		/* mask for type flags */
+    ZFST_TBIT = 0x0001,		/* number of bits in type flags */
 
-    ZFST_CASC = 0x00,		/* current type is ASCII - default */
-    ZFST_CIMA = 0x02,		/* current type is image */
+    ZFST_CASC = 0x0000,		/* current type is ASCII - default */
+    ZFST_CIMA = 0x0002,		/* current type is image */
 
-    ZFST_STRE = 0x00,		/* stream mode - default */
-    ZFST_BLOC = 0x04,		/* block mode */
+    ZFST_STRE = 0x0000,		/* stream mode - default */
+    ZFST_BLOC = 0x0004,		/* block mode */
 
-    ZFST_MMSK = 0x04,		/* mask for mode flags */
+    ZFST_MMSK = 0x0004,		/* mask for mode flags */
 
-    ZFST_LOGI = 0x08,		/* user logged in */
-    ZFST_NOPS = 0x10,		/* server doesn't understand PASV */
-    ZFST_NOSZ = 0x20,		/* server doesn't send `(XXXX bytes)' reply */
-    ZFST_TRSZ = 0x40,		/* tried getting 'size' from reply */
-    ZFST_CLOS = 0x80		/* connection closed */
+    ZFST_LOGI = 0x0008,		/* user logged in */
+    ZFST_SYST = 0x0010,		/* done system type check */
+    ZFST_NOPS = 0x0020,		/* server doesn't understand PASV */
+    ZFST_NOSZ = 0x0040,		/* server doesn't send `(XXXX bytes)' reply */
+    ZFST_TRSZ = 0x0080,		/* tried getting 'size' from reply */
+    ZFST_CLOS = 0x0100		/* connection closed */
 };
 #define ZFST_TYPE(x) (x & ZFST_TMSK)
 /*
@@ -461,7 +462,7 @@ zfmovefd(int fd)
  * set a non-special parameter.
  * if ZFPM_IFUNSET, don't set if it already exists.
  * if ZFPM_READONLY, make it readonly, but only when creating it.
- * if ZFPM_INTEGER, val pointer is to long (NB not int), don't free.
+ * if ZFPM_INTEGER, val pointer is to off_t (NB not int), don't free.
  */
 /**/
 static void
@@ -488,7 +489,7 @@ zfsetparam(char *name, void *val, int flags)
 	return;
     }
     if (type == PM_INTEGER)
-	pm->sets.ifn(pm, *(long *)val);
+	pm->sets.ifn(pm, *(off_t *)val);
     else
 	pm->sets.cfn(pm, (char *)val);
 }
@@ -1009,7 +1010,7 @@ zfgetdata(char *name, char *rest, char *cmd, int getsize)
 	    if (isdigit(STOUC(*ptr))) {
 		zfstatus &= ~ZFST_NOSZ;
 		if (getsize) {
-		    long sz = zstrtol(ptr, NULL, 10);
+		    off_t sz = zstrtol(ptr, NULL, 10);
 		    zfsetparam("ZFTP_SIZE", &sz, ZFPM_READONLY|ZFPM_INTEGER);
 		}
 	    }
@@ -1090,9 +1091,9 @@ zfgetdata(char *name, char *rest, char *cmd, int getsize)
 
 /**/
 static int
-zfstats(char *fnam, int remote, long *retsize, char **retmdtm, int fd)
+zfstats(char *fnam, int remote, off_t *retsize, char **retmdtm, int fd)
 {
-    long sz = -1;
+    off_t sz = -1;
     char *mt = NULL;
     int ret;
 
@@ -1151,7 +1152,7 @@ zfstats(char *fnam, int remote, long *retsize, char **retmdtm, int fd)
 
 	if ((fd == -1 ? stat(fnam, &statbuf) : fstat(fd, &statbuf)) < 0)
 	    return 1;
-	/* make sure it's long, since this has to be a pointer */
+	/* make sure it's off_t, since this has to be a pointer */
 	sz = statbuf.st_size;
 
 	if (retmdtm) {
@@ -1179,9 +1180,9 @@ zfstats(char *fnam, int remote, long *retsize, char **retmdtm, int fd)
 
 /**/
 static void
-zfstarttrans(char *nam, int recv, long sz)
+zfstarttrans(char *nam, int recv, off_t sz)
 {
-    long cnt = 0;
+    off_t cnt = 0;
     /*
      * sz = -1 signifies error getting size.  don't set ZFTP_SIZE if sz is
      * zero, either: it probably came from an fstat() on a pipe, so it
@@ -1210,7 +1211,7 @@ zfendtrans()
 
 /**/
 static int
-zfread(int fd, char *bf, size_t sz, int tmout)
+zfread(int fd, char *bf, off_t sz, int tmout)
 {
     int ret;
 
@@ -1235,7 +1236,7 @@ zfread(int fd, char *bf, size_t sz, int tmout)
 
 /**/
 static int
-zfwrite(int fd, char *bf, size_t sz, int tmout)
+zfwrite(int fd, char *bf, off_t sz, int tmout)
 {
     int ret;
 
@@ -1262,11 +1263,11 @@ static int zfread_eof;
 
 /**/
 static int
-zfread_block(int fd, char *bf, size_t sz, int tmout)
+zfread_block(int fd, char *bf, off_t sz, int tmout)
 {
     int n;
     struct zfheader hdr;
-    size_t blksz, cnt;
+    off_t blksz, cnt;
     char *bfptr;
     do {
 	/* we need the header */
@@ -1314,11 +1315,11 @@ zfread_block(int fd, char *bf, size_t sz, int tmout)
 
 /**/
 static int
-zfwrite_block(int fd, char *bf, size_t sz, int tmout)
+zfwrite_block(int fd, char *bf, off_t sz, int tmout)
 {
     int n;
     struct zfheader hdr;
-    size_t cnt;
+    off_t cnt;
     char *bfptr;
     /* we need the header */
     do {
@@ -1359,7 +1360,7 @@ zfwrite_block(int fd, char *bf, size_t sz, int tmout)
 
 /**/
 static int
-zfsenddata(char *name, int recv, int progress, long startat)
+zfsenddata(char *name, int recv, int progress, off_t startat)
 {
 #define ZF_BUFSIZE 32768
 #define ZF_ASCSIZE (ZF_BUFSIZE/2)
@@ -1367,7 +1368,7 @@ zfsenddata(char *name, int recv, int progress, long startat)
     int n, ret = 0, gotack = 0, fdin, fdout, fromasc = 0, toasc = 0;
     int rtmout = 0, wtmout = 0;
     char lsbuf[ZF_BUFSIZE], *ascbuf = NULL, *optr;
-    long sofar = 0, last_sofar = 0;
+    off_t sofar = 0, last_sofar = 0;
     readwrite_t read_ptr = zfread, write_ptr = zfwrite;
     List l;
 
@@ -1598,7 +1599,7 @@ zftp_open(char *name, char **args, int flags)
     struct protoent *zprotop;
     struct servent *zservp;
     struct hostent *zhostp = NULL;
-    char **addrp, tbuf[2] = "X", *fname;
+    char **addrp, *fname;
     int err, len, tmout;
 
     if (!*args) {
@@ -1802,32 +1803,11 @@ zftp_open(char *name, char **args, int flags)
 #endif
     unlink(fname);
 
-    /* now find out what system we're connected to */
-    if (!(zfprefs & ZFPF_DUMB) && zfsendcmd("SYST\r\n") == 2) {
-	char *ptr = lastmsg, *eptr, *systype;
-	for (eptr = ptr; *eptr; eptr++)
-	    ;
-	systype = ztrduppfx(ptr, eptr-ptr);
-	if (!strncmp(systype, "UNIX Type: L8", 13)) {
-	    /*
-	     * Use binary for transfers.  This simple test saves much
-	     * hassle for all concerned, particularly me.
-	     */
-	    zfstatus |= ZFST_IMAG;
-	    zfis_unix = 1;
-	}
-	/*
-	 * we could set zfis_unix based just on the UNIX part,
-	 * but I don't really know the consequences of that.
-	 */
-	zfsetparam("ZFTP_SYSTEM", systype, ZFPM_READONLY);
-    } else if (zcfd == -1) {
+    if (zcfd == -1) {
 	/* final paranoid check */
 	return 1;
     }
 	
-    tbuf[0] = (ZFST_TYPE(zfstatus) == ZFST_ASCI) ? 'A' : 'I';
-    zfsetparam("ZFTP_TYPE", ztrdup(tbuf), ZFPM_READONLY);
     zfsetparam("ZFTP_MODE", ztrdup("S"), ZFPM_READONLY);
     /* if remaining arguments, use them to log in. */
     if (zcfd > -1 && *++args)
@@ -1964,7 +1944,7 @@ static int
 zftp_login(char *name, char **args, int flags)
 {
     char *ucmd, *passwd = NULL, *acct = NULL;
-    char *user;
+    char *user, tbuf[2] = "X";
     int stopit;
 
     if ((zfstatus & ZFST_LOGI) && zfsendcmd("REIN\r\n") >= 4)
@@ -2045,6 +2025,36 @@ zftp_login(char *name, char **args, int flags)
 	zfsetparam("ZFTP_ACCOUNT", ztrdup(acct), ZFPM_READONLY);
 
     /*
+     * Now find out what system we're connected to. Some systems
+     * won't let us do this until we're logged in; it's fairly safe
+     * to delay it here for all systems.
+     */
+    if (!(zfprefs & ZFPF_DUMB) && !(zfstatus & ZFST_SYST)) {
+	if (zfsendcmd("SYST\r\n") == 2) {
+	    char *ptr = lastmsg, *eptr, *systype;
+	    for (eptr = ptr; *eptr; eptr++)
+		;
+	    systype = ztrduppfx(ptr, eptr-ptr);
+	    if (!strncmp(systype, "UNIX Type: L8", 13)) {
+		/*
+		 * Use binary for transfers.  This simple test saves much
+		 * hassle for all concerned, particularly me.
+		 */
+		zfstatus |= ZFST_IMAG;
+		zfis_unix = 1;
+	    }
+	    /*
+	     * we could set zfis_unix based just on the UNIX part,
+	     * but I don't really know the consequences of that.
+	     */
+	    zfsetparam("ZFTP_SYSTEM", systype, ZFPM_READONLY);
+	}
+	zfstatus |= ZFST_SYST;
+    }
+    tbuf[0] = (ZFST_TYPE(zfstatus) == ZFST_ASCI) ? 'A' : 'I';
+    zfsetparam("ZFTP_TYPE", ztrdup(tbuf), ZFPM_READONLY);
+
+    /*
      * Get the directory.  This is possibly an unnecessary overhead, of
      * course, but when you're being driven by shell functions there's
      * just no way of telling.
@@ -2307,7 +2317,7 @@ zftp_local(char *name, char **args, int flags)
 {
     int more = !!args[1], ret = 0, dofd = !*args;
     while (*args || dofd) {
-	long sz;
+	off_t sz;
 	char *mt;
 	int newret = zfstats(*args, !(flags & ZFTP_HERE), &sz, &mt,
 			     dofd ? 0 : -1);
@@ -2324,7 +2334,12 @@ zftp_local(char *name, char **args, int flags)
 	    fputs(*args, stdout);
 	    fputc(' ', stdout);
 	}
+#ifdef OFF_T_IS_64_BIT
+	printf("%s %s\n", output64(sz), mt);
+#else
+	DPUTS(sizeof(sz) > 4, "Shell compiled with wrong off_t size");
 	printf("%ld %s\n", sz, mt);
+#endif
 	zsfree(mt);
 	if (dofd)
 	    break;
@@ -2371,9 +2386,9 @@ zftp_getput(char *name, char **args, int flags)
 	fflush(stdout);		/* since we may be using fd 1 */
     for (; *args; args++) {
 	char *ln, *rest = NULL;
-	long startat = 0;
+	off_t startat = 0;
 	if (progress && (l = getshfunc("zftp_progress")) != &dummy_list) {
-	    long sz;
+	    off_t sz;
 	    /*
 	     * This calls the SIZE command to get the size for remote
 	     * files.  Some servers send the size with the reply to
@@ -2701,7 +2716,7 @@ boot_zftp(Module m)
     if ((ret = addbuiltins(m->nam, bintab,
 			   sizeof(bintab)/sizeof(*bintab))) == 1) {
 	/* if successful, set some default parameters */
-	long tmout_def = 60;
+	off_t tmout_def = 60;
 	zfsetparam("ZFTP_VERBOSE", ztrdup("450"), ZFPM_IFUNSET);
 	zfsetparam("ZFTP_TMOUT", &tmout_def, ZFPM_IFUNSET|ZFPM_INTEGER);
 	zfsetparam("ZFTP_PREFS", ztrdup("PS"), ZFPM_IFUNSET);