about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Config/defs.mk.in2
-rw-r--r--Doc/Makefile.in3
-rw-r--r--Doc/Zsh/mod_newuser.yo37
-rw-r--r--Src/Modules/newuser.c99
-rw-r--r--Src/Modules/newuser.mdd12
-rw-r--r--Src/init.c12
-rw-r--r--Src/module.c107
-rw-r--r--Src/zsh.mdd6
-rw-r--r--configure.ac24
10 files changed, 266 insertions, 43 deletions
diff --git a/ChangeLog b/ChangeLog
index 022f174ab..e176008d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2005-07-20  Peter Stephenson  <pws@csr.com>
+
+	* 21498: configure.ac, Configs/defs.mk.in, Doc/Makefile.in,
+	Doc/Zsh/mod_newuser.yo, Src/init.c, Src/module.c, Src/zsh.mdd,
+	Src/Modules/newuser.c, Src/Modules/newuser.mdd: Add zsh/newuser
+	module, currently with no associated shell code.
+
 2005-07-20  Doug Kearns  <djkea2@gus.gscit.monash.edu.au>
 
 	* unposted: Completion/Unix/Command/_rake: add -s option to _arguments
diff --git a/Config/defs.mk.in b/Config/defs.mk.in
index fc59d68d2..52061a45e 100644
--- a/Config/defs.mk.in
+++ b/Config/defs.mk.in
@@ -43,6 +43,8 @@ mandir          = @mandir@
 datadir         = @datadir@
 fndir           = @fndir@
 sitefndir       = @sitefndir@
+scriptdir       = @scriptdir@
+sitescriptdir   = @sitescriptdir@
 htmldir         = $(datadir)/$(tzsh)/htmldoc
 
 # compilation
diff --git a/Doc/Makefile.in b/Doc/Makefile.in
index 72cf0f5f5..f1cbb3d8b 100644
--- a/Doc/Makefile.in
+++ b/Doc/Makefile.in
@@ -59,7 +59,8 @@ Zsh/mod_compctl.yo Zsh/mod_complete.yo Zsh/mod_complist.yo \
 Zsh/mod_computil.yo \
 Zsh/mod_datetime.yo Zsh/mod_deltochar.yo \
 Zsh/mod_example.yo Zsh/mod_files.yo \
-Zsh/mod_mapfile.yo Zsh/mod_mathfunc.yo Zsh/mod_parameter.yo Zsh/mod_pcre.yo \
+Zsh/mod_mapfile.yo Zsh/mod_mathfunc.yo Zsh/mod_newuser.yo \
+Zsh/mod_parameter.yo Zsh/mod_pcre.yo \
 Zsh/mod_sched.yo Zsh/mod_socket.yo \
 Zsh/mod_stat.yo  Zsh/mod_system.yo Zsh/mod_tcp.yo \
 Zsh/mod_termcap.yo Zsh/mod_terminfo.yo \
diff --git a/Doc/Zsh/mod_newuser.yo b/Doc/Zsh/mod_newuser.yo
new file mode 100644
index 000000000..202fb90e8
--- /dev/null
+++ b/Doc/Zsh/mod_newuser.yo
@@ -0,0 +1,37 @@
+COMMENT(!MOD!zsh/newuser
+Arrange for files for new users to be installed.
+!MOD!)
+The tt(zsh/newuser) module is loaded at boot if it is
+available, the tt(RCS) option is set, and the tt(PRIVILEGED) option is not
+set (all three are true by default).  This takes
+place immediately after commands in the global tt(zshenv) file (typically
+tt(/etc/zshenv)), if any, have been executed.  If the module is not
+available it is silently ignored by the shell; the module may safely be
+removed from tt($MODULE_PATH) by the administrator if it is not required.
+
+On loading, the module tests if any of the start-up files tt(.zshenv),
+tt(.zprofile), tt(.zshrc) or tt(.zlogin) exist in the directory given by
+the environment variable tt(ZDOTDIR), or the user's home directory if that
+is not set.
+
+If none of the start-up files were found, the module then looks for the
+file tt(newuser) first in a sitewide directory, usually the parent
+directory of the tt(site-functions) directory, and if that is not found the
+module searches in a version-specific directory, usually the parent of the
+tt(functions) directory containing version-specific functions.  (These
+directories can be configured when zsh is built using the
+tt(--enable-site-scriptdir=)var(dir) and tt(--enable-scriptdir=)var(dir)
+flags to tt(configure), respectively; the defaults are
+var(prefix)tt(/share/zsh) and var(prefix)tt(/share/zsh/$ZSH_VERSION) where
+the default var(prefix) is tt(/usr/local).)
+
+If the file tt(newuser) is found, it is then sourced in the same manner as
+a start-up file.  The file is expected to contain code to install start-up
+files for the user, however any valid shell code will be executed.
+
+The tt(zsh/newuser) module is then unconditionally unloaded.
+
+Note that it is possible to achieve exactly the same effect as the
+tt(zsh/newuser) module by adding code to tt(/etc/zshenv).  The module
+exists simply to allow the shell to make arrangements for new users without
+the need for invervention by package maintainers and system administrators.
diff --git a/Src/Modules/newuser.c b/Src/Modules/newuser.c
new file mode 100644
index 000000000..cbe09312f
--- /dev/null
+++ b/Src/Modules/newuser.c
@@ -0,0 +1,99 @@
+/*
+ * newuser.c - handler for easy setup for new zsh users
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 2005 Peter Stephenson
+ * 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 Peter Stephenson 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 Peter Stephenson and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Peter Stephenson 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 Peter Stephenson and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+
+#include "newuser.mdh"
+#include "newuser.pro"
+
+#include "../zshpaths.h"
+
+/**/
+int
+setup_(UNUSED(Module m))
+{
+    return 0;
+}
+
+/**/
+static int
+check_dotfile(const char *dotdir, const char *fname)
+{
+    VARARR(char, buf, strlen(dotdir) + strlen(fname) + 2);
+    sprintf(buf, "%s/%s", dotdir, fname);
+
+    return access(buf, F_OK);
+}
+
+/**/
+int
+boot_(UNUSED(Module m))
+{
+    const char *dotdir = getsparam("ZDOTDIR");
+    const char *spaths[] = {
+#ifdef SITESCRIPT_DIR
+	SITESCRIPT_DIR,
+#endif
+#ifdef SCRIPT_DIR
+	SCRIPT_DIR,
+#endif
+	0 };
+    const char **sp;
+
+    if (!dotdir)
+	dotdir = home;
+
+    if (check_dotfile(dotdir, ".zshenv") == 0 ||
+	check_dotfile(dotdir, ".zprofile") == 0 ||
+	check_dotfile(dotdir, ".zshrc") == 0 ||
+	check_dotfile(dotdir, ".zlogin") == 0)
+	return 0;
+
+    for (sp = spaths; *sp; sp++) {
+	VARARR(char, buf, strlen(*sp) + 9);
+	sprintf(buf, "%s/newuser", *sp);
+
+	if (!source(buf))
+	    break;
+    }
+
+    return 0;
+}
+
+/**/
+int
+cleanup_(UNUSED(Module m))
+{
+    return 0;
+}
+
+/**/
+int
+finish_(UNUSED(Module m))
+{
+    return 0;
+}
diff --git a/Src/Modules/newuser.mdd b/Src/Modules/newuser.mdd
new file mode 100644
index 000000000..419511dc3
--- /dev/null
+++ b/Src/Modules/newuser.mdd
@@ -0,0 +1,12 @@
+name=zsh/newuser
+link=dynamic
+# We will always try to load newuser, but there is
+# no error if it fails.
+load=no
+
+objects="newuser.o"
+
+:<<\Make
+newuser.o:  ../zshpaths.h
+
+Make
diff --git a/Src/init.c b/Src/init.c
index 6ec0370a3..c6fd0e4d9 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -948,8 +948,20 @@ run_init_scripts(void)
 #ifdef GLOBAL_ZSHENV
 	source(GLOBAL_ZSHENV);
 #endif
+
 	if (isset(RCS) && unset(PRIVILEGED))
+	{
+	    /*
+	     * Always attempt to load the newuser module to perform
+	     * checks for new zsh users.  Don't care if we can't load it.
+	     */
+	    if (load_module_silence("zsh/newuser", 1)) {
+		/* Unload it immediately. */
+		unload_named_module("zsh/newuser", "zsh", 1);
+	    }
+
 	    sourcehome(".zshenv");
+	}
 	if (islogin) {
 #ifdef GLOBAL_ZPROFILE
 	    if (isset(RCS) && isset(GLOBALRCS))
diff --git a/Src/module.c b/Src/module.c
index c50e032b6..7a0fcf811 100644
--- a/Src/module.c
+++ b/Src/module.c
@@ -434,12 +434,12 @@ try_load_module(char const *name)
 
 /**/
 static void *
-do_load_module(char const *name)
+do_load_module(char const *name, int silent)
 {
     void *ret;
 
     ret = try_load_module(name);
-    if (!ret) {
+    if (!ret && !silent) {
 	int waserr = errflag;
 	zerr("failed to load module: %s", name, 0);
 	errflag = waserr;
@@ -452,11 +452,12 @@ do_load_module(char const *name)
 
 /**/
 static void *
-do_load_module(char const *name)
+do_load_module(char const *name, int silent)
 {
     int waserr = errflag;
 
-    zerr("failed to load module: %s", name, 0);
+    if (!silent)
+	zerr("failed to load module: %s", name, 0);
     errflag = waserr;
 
     return NULL;
@@ -748,6 +749,13 @@ modname_ok(char const *p)
 mod_export int
 load_module(char const *name)
 {
+    return load_module_silence(name, 0);
+}
+
+/**/
+mod_export int
+load_module_silence(char const *name, int silent)
+{
     Module m;
     void *handle = NULL;
     Linkedmod linked;
@@ -755,7 +763,8 @@ load_module(char const *name)
     int set;
 
     if (!modname_ok(name)) {
-	zerr("invalid module name `%s'", name, 0);
+	if (!silent)
+	    zerr("invalid module name `%s'", name, 0);
 	return 0;
     }
     /*
@@ -766,7 +775,7 @@ load_module(char const *name)
     queue_signals();
     if (!(node = find_module(name, 1, &name))) {
 	if (!(linked = module_linked(name)) &&
-	    !(handle = do_load_module(name))) {
+	    !(handle = do_load_module(name, silent))) {
 	    unqueue_signals();
 	    return 0;
 	}
@@ -811,7 +820,7 @@ load_module(char const *name)
     m->flags |= MOD_BUSY;
     if (m->deps)
 	for (n = firstnode(m->deps); n; incnode(n))
-	    if (!load_module((char *) getdata(n))) {
+	    if (!load_module_silence((char *) getdata(n), silent)) {
 		m->flags &= ~MOD_BUSY;
 		unqueue_signals();
 		return 0;
@@ -820,7 +829,7 @@ load_module(char const *name)
     if (!m->u.handle) {
 	handle = NULL;
 	if (!(linked = module_linked(name)) &&
-	    !(handle = do_load_module(name))) {
+	    !(handle = do_load_module(name, silent))) {
 	    unqueue_signals();
 	    return 0;
 	}
@@ -886,7 +895,7 @@ require_module(char *nam, const char *module, UNUSED(int res), int test)
 	    return 0;
 	}
     } else
-	ret = load_module(module);
+	ret = load_module_silence(module, 0);
     unqueue_signals();
 
     return ret;
@@ -1549,6 +1558,50 @@ unload_module(Module m, LinkNode node)
     return 0;
 }
 
+
+/**/
+int
+unload_named_module(char *modname, char *nam, int silent)
+{
+    const char *mname;
+    LinkNode node;
+    Module m;
+    int ret = 0;
+
+    node = find_module(modname, 1, &mname);
+    if (node) {
+	LinkNode mn, dn;
+	int del = 0;
+
+	for (mn = firstnode(modules); mn; incnode(mn)) {
+	    m = (Module) getdata(mn);
+	    if (m->deps && m->u.handle)
+		for (dn = firstnode(m->deps); dn; incnode(dn))
+		    if (!strcmp((char *) getdata(dn), mname)) {
+			if (m->flags & MOD_UNLOAD)
+			    del = 1;
+			else {
+			    zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", mname, 0);
+			    return 1;
+			}
+		    }
+	}
+	m = (Module) getdata(node);
+	if (del)
+	    m->wrapper++;
+	if (unload_module(m, node))
+	    ret = 1;
+	if (del)
+	    m->wrapper--;
+    } else if (!silent) {
+	zwarnnam(nam, "no such module %s", modname, 0);
+	ret = 1;
+    }
+
+    return ret;
+}
+
+
 /**/
 static int
 bin_zmodload_load(char *nam, char **args, Options ops)
@@ -1558,39 +1611,9 @@ bin_zmodload_load(char *nam, char **args, Options ops)
     int ret = 0;
     if(OPT_ISSET(ops,'u')) {
 	/* unload modules */
-	const char *mname = *args;
 	for(; *args; args++) {
-	    node = find_module(*args, 1, &mname);
-	    if (node) {
-		LinkNode mn, dn;
-		int del = 0;
-
-		for (mn = firstnode(modules); mn; incnode(mn)) {
-		    m = (Module) getdata(mn);
-		    if (m->deps && m->u.handle)
-			for (dn = firstnode(m->deps); dn; incnode(dn))
-			    if (!strcmp((char *) getdata(dn), mname)) {
-				if (m->flags & MOD_UNLOAD)
-				    del = 1;
-				else {
-				    zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", mname, 0);
-				    ret = 1;
-				    goto cont;
-				}
-			    }
-		}
-		m = (Module) getdata(node);
-		if (del)
-		    m->wrapper++;
-		if (unload_module(m, node))
-		    ret = 1;
-		if (del)
-		    m->wrapper--;
-	    } else if (!OPT_ISSET(ops,'i')) {
-		zwarnnam(nam, "no such module %s", *args, 0);
+	    if (unload_named_module(*args, nam, OPT_ISSET(ops,'i')))
 		ret = 1;
-	    }
-	    cont: ;
 	}
 	return ret;
     } else if(!*args) {
@@ -1645,7 +1668,7 @@ getconddef(int inf, char *name, int autol)
 	    /* This is a definition for an autoloaded condition, load the *
 	     * module if we haven't tried that already. */
 	    if (f) {
-		load_module(p->module);
+		load_module_silence(p->module, 0);
 		f = 0;
 		p = NULL;
 	    } else {
@@ -2086,7 +2109,7 @@ getmathfunc(char *name, int autol)
 
 		removemathfunc(q, p);
 
-		load_module(n);
+		load_module_silence(n, 0);
 
 		return getmathfunc(name, 0);
 	    }
diff --git a/Src/zsh.mdd b/Src/zsh.mdd
index e4dae2a2d..3109e6b38 100644
--- a/Src/zsh.mdd
+++ b/Src/zsh.mdd
@@ -38,6 +38,12 @@ version.h: $(sdir_top)/Config/version.mk
 
 zshpaths.h: Makemod $(CONFIG_INCS)
 	@echo '#define MODULE_DIR "'$(MODDIR)'"' > zshpaths.h.tmp
+	@if test x$(sitescriptdir) != xno; then \
+	  echo '#define SITESCRIPT_DIR "'$(sitescriptdir)'"' >> zshpaths.h.tmp; \
+	fi
+	@if test x$(scriptdir) != xno; then \
+	  echo '#define SCRIPT_DIR "'$(scriptdir)'"' >> zshpaths.h.tmp; \
+	fi
 	@if test x$(sitefndir) != xno; then \
 	  echo '#define SITEFPATH_DIR "'$(sitefndir)'"' >> zshpaths.h.tmp; \
 	fi
diff --git a/configure.ac b/configure.ac
index e79f4062a..6399f53c5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -286,6 +286,30 @@ AC_SUBST(fndir)dnl
 AC_SUBST(sitefndir)dnl
 AC_SUBST(FUNCTIONS_SUBDIRS)dnl
 
+dnl Directories for scripts such as newuser.
+
+ifdef([scriptdir],[undefine([scriptdir])])dnl
+AC_ARG_ENABLE(scriptdir,
+[  --enable-scriptdir=DIR     the directory in which to install scripts],
+dnl ${VERSION} to be determined at compile time.
+[if test $enableval = yes; then
+  scriptdir=${datadir}/${tzsh_name}/'${VERSION}'
+else
+  scriptdir="$enableval"
+fi], [scriptdir=${datadir}/${tzsh_name}/'${VERSION}'])
+
+ifdef([sitescriptdir],[undefine([sitescriptdir])])dnl
+AC_ARG_ENABLE(site-scriptdir,
+[  --enable-site-scriptdir=DIR  same for site scripts (not version specific)],
+[if test $enableval = yes; then
+  sitescriptdir=${datadir}/${tzsh_name}
+else
+  sitescriptdir="$enableval"
+fi], [sitescriptdir=${datadir}/${tzsh_name}])
+
+AC_SUBST(scriptdir)dnl
+AC_SUBST(sitescriptdir)dnl
+
 dnl Do you want maildir support?
 ifdef([maildir_support],[undefine([maildir_support])])dnl
 AH_TEMPLATE([MAILDIR_SUPPORT],