From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20219 invoked from network); 20 Jul 2005 14:02:07 -0000 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 20 Jul 2005 14:02:07 -0000 Received: (qmail 18250 invoked from network); 20 Jul 2005 14:02:01 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 20 Jul 2005 14:02:01 -0000 Received: (qmail 26680 invoked by alias); 20 Jul 2005 14:01:58 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 21498 Received: (qmail 26671 invoked from network); 20 Jul 2005 14:01:57 -0000 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by sunsite.dk with SMTP; 20 Jul 2005 14:01:57 -0000 Received: (qmail 17952 invoked from network); 20 Jul 2005 14:01:57 -0000 Received: from mailhost1.csr.com (HELO MAILSWEEPER01.csr.com) (81.105.217.43) by a.mx.sunsite.dk with SMTP; 20 Jul 2005 14:01:49 -0000 Received: from exchange03.csr.com (unverified [10.100.137.60]) by MAILSWEEPER01.csr.com (Content Technologies SMTPRS 4.3.12) with ESMTP id for ; Wed, 20 Jul 2005 14:59:45 +0100 Received: from news01.csr.com ([10.103.143.38]) by exchange03.csr.com with Microsoft SMTPSVC(5.0.2195.6713); Wed, 20 Jul 2005 15:03:50 +0100 Received: from news01.csr.com (localhost.localdomain [127.0.0.1]) by news01.csr.com (8.13.1/8.12.11) with ESMTP id j6KE1lrR004736 for ; Wed, 20 Jul 2005 15:01:47 +0100 Received: from csr.com (pws@localhost) by news01.csr.com (8.13.1/8.13.1/Submit) with ESMTP id j6KE1k5i004733 for ; Wed, 20 Jul 2005 15:01:47 +0100 Message-Id: <200507201401.j6KE1k5i004733@news01.csr.com> X-Authentication-Warning: news01.csr.com: pws owned process doing -bs To: zsh-workers@sunsite.dk Subject: PATCH: Re: Implementation of simple newuser module (how to start?) In-reply-to: References: Date: Wed, 20 Jul 2005 15:01:46 +0100 From: Peter Stephenson X-OriginalArrivalTime: 20 Jul 2005 14:03:50.0300 (UTC) FILETIME=[DAC32DC0:01C58D33] X-Spam-Checker-Version: SpamAssassin 3.0.4 (2005-06-05) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=0.4 required=5.0 tests=AWL,BAYES_50,NO_OBLIGATION autolearn=no version=3.0.4 Here is an initial attempt at the zsh/newuser module. Note the logic: the module is loaded and immediately unloaded just before .zshenv would be run, and under exactly the same conditions (so /etc/zshenv has just been executed if it exists). This seems to me to be about the best choice. It does mean that the module will be run if the shell is non-interactive; it is up to the newuser script or whatever it calls to handle this. (This might be made clearer in the manual entry, or alternatively the module could only be run for an interactive shell.) I haven't provided any newuser file yet. Arrangements will have to be made to instal that: not entirely sure where from, since it's not a function, possibly Etc which at least has a Makefile. However, this should be good enough to play around with your own ideas. (When I've worked out how to install it, I may provide an initial newuser file which simply creates .zshrc with a comment.) Please suggest improvements to the manual entry if I've made it too tortuous. Index: configure.ac =================================================================== RCS file: /cvsroot/zsh/zsh/configure.ac,v retrieving revision 1.34 diff -u -r1.34 configure.ac --- configure.ac 31 May 2005 07:44:11 -0000 1.34 +++ configure.ac 20 Jul 2005 13:59:34 -0000 @@ -286,6 +286,30 @@ 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], Index: Config/defs.mk.in =================================================================== RCS file: /cvsroot/zsh/zsh/Config/defs.mk.in,v retrieving revision 1.9 diff -u -r1.9 defs.mk.in --- Config/defs.mk.in 4 Feb 2005 16:59:40 -0000 1.9 +++ Config/defs.mk.in 20 Jul 2005 13:59:35 -0000 @@ -43,6 +43,8 @@ datadir = @datadir@ fndir = @fndir@ sitefndir = @sitefndir@ +scriptdir = @scriptdir@ +sitescriptdir = @sitescriptdir@ htmldir = $(datadir)/$(tzsh)/htmldoc # compilation Index: Doc/Makefile.in =================================================================== RCS file: /cvsroot/zsh/zsh/Doc/Makefile.in,v retrieving revision 1.24 diff -u -r1.24 Makefile.in --- Doc/Makefile.in 6 May 2005 15:53:02 -0000 1.24 +++ Doc/Makefile.in 20 Jul 2005 13:59:35 -0000 @@ -59,7 +59,8 @@ 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 \ Index: Doc/Zsh/mod_newuser.yo =================================================================== RCS file: Doc/Zsh/mod_newuser.yo diff -N Doc/Zsh/mod_newuser.yo --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Doc/Zsh/mod_newuser.yo 20 Jul 2005 13:59:36 -0000 @@ -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. Index: Src/init.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/init.c,v retrieving revision 1.54 diff -u -r1.54 init.c --- Src/init.c 15 Jul 2005 17:41:53 -0000 1.54 +++ Src/init.c 20 Jul 2005 13:59:36 -0000 @@ -948,8 +948,20 @@ #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)) Index: Src/module.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/module.c,v retrieving revision 1.17 diff -u -r1.17 module.c --- Src/module.c 12 Jan 2005 12:19:06 -0000 1.17 +++ Src/module.c 20 Jul 2005 13:59:36 -0000 @@ -434,12 +434,12 @@ /**/ 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 @@ /**/ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ return 0; } } else - ret = load_module(module); + ret = load_module_silence(module, 0); unqueue_signals(); return ret; @@ -1549,6 +1558,50 @@ 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 @@ 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 @@ /* 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 @@ removemathfunc(q, p); - load_module(n); + load_module_silence(n, 0); return getmathfunc(name, 0); } Index: Src/zsh.mdd =================================================================== RCS file: /cvsroot/zsh/zsh/Src/zsh.mdd,v retrieving revision 1.12 diff -u -r1.12 zsh.mdd --- Src/zsh.mdd 15 Feb 2005 18:32:39 -0000 1.12 +++ Src/zsh.mdd 20 Jul 2005 13:59:36 -0000 @@ -38,6 +38,12 @@ 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 Index: Src/Modules/newuser.c =================================================================== RCS file: Src/Modules/newuser.c diff -N Src/Modules/newuser.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Src/Modules/newuser.c 20 Jul 2005 13:59:36 -0000 @@ -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; +} Index: Src/Modules/newuser.mdd =================================================================== RCS file: Src/Modules/newuser.mdd diff -N Src/Modules/newuser.mdd --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Src/Modules/newuser.mdd 20 Jul 2005 13:59:36 -0000 @@ -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 -- Peter Stephenson Software Engineer CSR PLC, Churchill House, Cambridge Business Park, Cowley Road Cambridge, CB4 0WZ, UK Tel: +44 (0)1223 692070 ********************************************************************** This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the system manager. **********************************************************************