Initial commit of ns-tools. - ns-tools - Namespace utilities to reuse Open Source packaging efforts.
       
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 84ab05a787db5488718d87a11897e5204e4a0416
 (HTM) Author: Christoph Lohmann <20h@r-36.net>
       Date:   Thu,  1 May 2014 18:13:49 +0200
       
       Initial commit of ns-tools.
       
       Diffstat:
         LICENSE                             |      21 +++++++++++++++++++++
         README.md                           |      81 ++++++++++++++++++++++++++++++
         bin/ns-boot                         |       8 ++++++++
         bin/ns-chroot                       |      48 +++++++++++++++++++++++++++++++
         bin/ns-copy-intel-ucode             |      22 ++++++++++++++++++++++
         bin/ns-gencapchrootallow            |      17 +++++++++++++++++
         bin/ns-init                         |       4 ++++
         bin/ns-kill                         |      16 ++++++++++++++++
         bin/ns-lsof                         |      14 ++++++++++++++
         bin/ns-path                         |      81 ++++++++++++++++++++++++++++++
         bin/ns-prepare                      |      84 +++++++++++++++++++++++++++++++
         bin/ns-root                         |      30 ++++++++++++++++++++++++++++++
         bin/ns-umount                       |      18 ++++++++++++++++++
         bin/ns-unprepare                    |      43 ++++++++++++++++++++++++++++++
         bin/ns-unprepare-all                |       7 +++++++
         bin/ns-update                       |      90 +++++++++++++++++++++++++++++++
         bin/ns-user                         |       8 ++++++++
         bin/ns-vzinit                       |      62 +++++++++++++++++++++++++++++++
         bin/ns-wrapper                      |      17 +++++++++++++++++
         bin/ns-wrapper-install              |      18 ++++++++++++++++++
       
       20 files changed, 689 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/LICENSE b/LICENSE
       @@ -0,0 +1,21 @@
       +MIT/X Consortium License
       +
       +© 2013-14 Christoph Lohmann <20h@r-36.net>
       +
       +Permission is hereby granted, free of charge, to any person obtaining a
       +copy of this software and associated documentation files (the "Software"),
       +tto deal in the Software without restriction, including without limitation
       +tthe rights to use, copy, modify, merge, publish, distribute, sublicense,
       +and/or sell copies of the Software, and to permit persons to whom the
       +Software is furnished to do so, subject to the following conditions:
       +
       +The above copyright notice and this permission notice shall be included in
       +all copies or substantial portions of the Software.
       +
       +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
       +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
       +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
       +DEALINGS IN THE SOFTWARE.
 (DIR) diff --git a/README.md b/README.md
       @@ -0,0 +1,81 @@
       +# Namespace tools
       +
       +## Namespaces
       +
       +Namespaces  are  basically  installations of whatever Linux distribution
       +you can find. Ns‐tools is using capchroot(1) to allow chroot  into  them
       +based on group and user authentication. Some wrapper utilities allow the
       +generation of wrapper scripts in /bin to run  utilities  in  the  names‐
       +paces.
       +
       +### Namespace configuration
       +
       +The  NSROOT  variable  is  not  yet implemented. For now /ns is the base
       +path. You can configure every  namespace  using  an  »rc.conf«  file  in
       +/ns/$namespace/.ns/.  There  the  variables  showin in ns‐prepare(1) are
       +shown.
       +
       +When  a  command is run, it is checked, whether a namespace is prepared.
       +The ONBOOT=1 variable defines, if the namespace should  be  prepared  on
       +boot.  The ns‐boot(1) script should be run in your init scripts, if this
       +is required.
       +
       +Alos look at the different variables to define which configuration files
       +should be copied over, linked or run over.
       +
       +## Installation (pre-alpha)
       +
       +        # Base installation
       +        mkdir /ns
       +        cp bin/* /bin
       +
       +        # Install capchroot as stated below.
       +
       +        # Install a Debian 7.0 image
       +        imageuri="$(ns-vzinit list | grep "debian-7.0-$(uname -m)")"
       +        ns-vzinit install "$imageuri" /ns/debian
       +
       +        ns-chroot debian
       +        debian shell> apt-get install nmap
       +        debian shell> exit
       +
       +        ns-wrapper-install debian nmap
       +        /bin/nmap -h
       +        ns-chroot debian man nmap
       +
       +### Capchroot
       +
       +Here are the links to install capchroot. For now this isn't automated.
       +
       +https://dev.archlinux.org/~thomas/capchroot/
       +http://bedrocklinux.org/1.0alpha1/install.html#DOWNLOAD%20Capchroot
       +
       +After you have a capchroot(1) binary, copy it to your PATH. Then create the
       +/etc/capchroot.allow file to define users which are allowed to run capchroot
       +and where. On my setup there is a »ns« group, which members are allowed to
       +chroot to the defined namespaces.
       +
       +        cat /etc/capchroot.allow
       +        /ns/debian @ns
       +        ...
       +
       +## Issues in the concept
       +* Unchroot is not yet implemented, so a complete linking in of X11 is not
       +  possible.
       +* Manpage paths are not global.
       +* Installation is weird.
       +* No Makefiles.
       +* Should be run on top of a static OS, but can be run everywhere, where chroot
       +  is allowed.
       +
       +## Links
       +
       +git://git.r-36.net/ns-tools
       +http://git.r-36.net/ns-tools
       +Bugs + Patches: 20h@r-36.net
       +
       +
       +Have fun!
       +
       +Christoph Lohmann <20h@r-36.net>
       +
 (DIR) diff --git a/bin/ns-boot b/bin/ns-boot
       @@ -0,0 +1,8 @@
       +#!/bin/sh
       +
       +for ns in $(ls -1 /ns);
       +do
       +        ns-prepare -b $(ns-root "$ns")
       +done
       +
       +
 (DIR) diff --git a/bin/ns-chroot b/bin/ns-chroot
       @@ -0,0 +1,48 @@
       +#!/bin/sh
       +
       +curdir="$(pwd)"
       +
       +dounprepare=0
       +t[ "$1" = "-u" ] && dounprepare=1 && shift 1
       +
       +if [ $# -lt 1 ];
       +tthen
       +        printf "usage: [-u] %s ns [cmd]\n" "$(basename $0)" >&2
       +        exit 1
       +fi
       +
       +nsroot="$(ns-root "$1")"
       +t[ $? -gt 0 ] && exit $?
       +
       +t[ -e "$nsroot/.ns/rc.conf" ] && . "$nsroot/.ns/rc.conf"
       +if [ -n "$SHBIN" ];
       +tthen
       +        cmd="$SHBIN"
       +else
       +        cmd="/bin/sh"
       +fi
       +t[ $# -gt 1 ] && cmd="$2" && shift 1
       +shift 1
       +
       +ns-prepare "$nsroot"
       +t[ $? -gt 0 ] && exit 1
       +
       +export PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
       +args="$@"
       +if [ ! -d "${nsroot}${curdir}" ];
       +tthen
       +        capchroot "$nsroot" $cmd -- "$@"
       +else
       +        capchroot -d "$curdir" "$nsroot" $cmd -- "$@"
       +fi
       +
       +if [ $dounprepare -eq 1 ];
       +tthen
       +        ns-unprepare "$nsroot"
       +else
       +        lsof "$nsroot" >/dev/null 2>&1
       +        [ $? -gt 0 ] && ns-unprepare "$nsroot"
       +fi
       +
       +exit 0
       +
 (DIR) diff --git a/bin/ns-copy-intel-ucode b/bin/ns-copy-intel-ucode
       @@ -0,0 +1,22 @@
       +#!/bin/sh
       +
       +if [ $# -lt 1 ];
       +tthen
       +        printf "usage: %s ns\n" "$(basename $0)" >&2
       +        exit 1
       +fi
       +
       +firmwarepath="/usr/lib/firmware/intel-ucode"
       +nsroot="$(ns-root "$1")"
       +
       +if [ ! -d "${nsroot}${firmwarepath}" ];
       +tthen
       +        printf "No '%s' in '%s' found.\n" \
       +                "${firmwarepath}" "${nsroot}" 2>&1
       +        exit 1
       +fi
       +
       +t[ ! -d "${firmwarepath}" ] && mkdir -p "${firmwarepath}"
       +
       +cp -rf ${nsroot}${firmwarepath}/* "${firmwarepath}"
       +
 (DIR) diff --git a/bin/ns-gencapchrootallow b/bin/ns-gencapchrootallow
       @@ -0,0 +1,17 @@
       +#!/bin/sh
       +
       +if [ $# -lt 1 ];
       +tthen
       +        printf "usage: %s root\n" "$(basename $0)" >&2
       +        exit 1
       +fi
       +
       +nsroot="$(ns-root "$1")"
       +t[ $? -gt 0 ] && exit $?
       +
       +cd "$nsroot"
       +for ns in $(ls -1d */);
       +do
       +        printf "%s/%s @ns\n" "$nsroot" "$(printf "%s\n" "$ns" | tr -d "/")"
       +done
       +        
 (DIR) diff --git a/bin/ns-init b/bin/ns-init
       @@ -0,0 +1,4 @@
       +#!/bin/sh
       +
       +mkdir -p /ns
       +
 (DIR) diff --git a/bin/ns-kill b/bin/ns-kill
       @@ -0,0 +1,16 @@
       +#!/bin/sh
       +
       +usage() {
       +        printf "usage: %s ns\n" "$(basename $1)" >&2
       +        exit 1
       +}
       +
       +t[ $# -lt 1 ] && usage $0
       +
       +nsroot="$(ns-root "$1")"
       +t[ $? -gt 0 ] && exit $?
       +
       +lsof -Fp "$nsroot" 2>/dev/null \
       +        | cut -b 2- \
       +        | xargs -n 1 kill -TERM
       +
 (DIR) diff --git a/bin/ns-lsof b/bin/ns-lsof
       @@ -0,0 +1,14 @@
       +#!/bin/sh
       +
       +usage() {
       +        printf "usage: %s ns\n" "$(basename $1)" >&2
       +        exit 1
       +}
       +
       +t[ $# -lt 1 ] && usage $0
       +
       +nsroot="$(ns-root "$1")"
       +t[ $? -gt 0 ] && exit $?
       +
       +lsof "$nsroot"
       +
 (DIR) diff --git a/bin/ns-path b/bin/ns-path
       @@ -0,0 +1,81 @@
       +#!/bin/sh
       +
       +usage() {
       +        printf "usage: %s [-rn] ns cmd\n" "$(basename $1)" >&2
       +        exit 1
       +}
       +
       +dorecursive=0
       +stripns=0
       +while getopts "rn" opt;
       +do
       +        case $opt in
       +        r)
       +                dorecursive=1
       +                ;;
       +        n)
       +                stripns=1
       +                ;;
       +        *)
       +                usage $0
       +                ;;
       +        esac
       +done
       +shift $(($OPTIND - 1))
       +
       +t[ $# -lt 2 ] && usage $0
       +
       +findpath() {
       +        errorn=1
       +        justone=0
       +        [ "$1" = "-1" ] && justone=1 && shift 1
       +        
       +        fnsroot="$1"
       +        fcmd="$2"
       +        NSPATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
       +        [ -e "$fnsroot/.ns/rc.conf" ] && . "$fnsroot/.ns/rc.conf"
       +
       +        for p in $(echo $NSPATH | tr ':' ' ');
       +        do
       +                if [ -x "$fnsroot${p}/$fcmd" -o -L "$fnsroot${p}/$fcmd" ];
       +                then
       +                        errorn=0
       +                        if [ $stripns -eq 1 ];
       +                        then
       +                                printf "%s/%s\n" "$p" "$fcmd"
       +                        else
       +                                printf "%s%s/%s\n" "$fnsroot" "$p" "$fcmd"
       +                        fi
       +                        [ $justone -eq 1 ] && return 0
       +                fi        
       +        done
       +        
       +        return $errorn
       +}        
       +
       +nsroot="$(ns-root "$1")"
       +t[ $? -gt 0 ] && exit $?
       +
       +cmd="$2"
       +rerrno=1
       +if [ $dorecursive -eq 1 ];
       +tthen
       +        cd "$nsroot";
       +        for ns in $(ls -1d */);
       +        do
       +                findpath "$nsroot/$(printf "%s\n" "$ns" | tr -d "/")" "$cmd"
       +                [ $? -eq 0 ] && rerrno=0
       +        done
       +else
       +        findpath -1 "$nsroot" "$cmd"
       +        rerrno=$?
       +fi
       +
       +if [ $rerrno -gt 0 ];
       +tthen
       +        printf "Could not find %s in namespace %s.\n" "$cmd" "$nsroot" >&2
       +        exit 1
       +else
       +        exit 0
       +fi
       +
 (DIR) diff --git a/bin/ns-prepare b/bin/ns-prepare
       @@ -0,0 +1,84 @@
       +#!/bin/sh
       +
       +doforce=0
       +doforceonboot=0
       +t[ "$1" = "-f" ] && doforce=1 && shift 1
       +t[ "$1" = "-b" ] && doforceonboot=1 && shift 1
       +
       +if [ $# -lt 1 ];
       +tthen
       +        printf "usage: %s [-f] ns\n" "$(basename $0)" >&2
       +        exit 1
       +fi
       +
       +nsroot="$(ns-root "$1")"
       +t[ $? -gt 0 ] && exit $?
       +
       +shift 1
       +
       +t[ -e "$nsroot/.ns/prepared" \
       +        -a $doforce -eq 0 \
       +        -a $doforceonboot -eq 0 ] && exit 0
       +
       +MOUNTFS=""
       +UMOUNTFS=""
       +TOUCHFILES=""
       +COPYFILES=""
       +LINKFILES=""
       +ONBOOT=0
       +
       +t[ -e "$nsroot/.ns/rc.conf" ] && . "$nsroot/.ns/rc.conf"
       +t[ $ONBOOT -eq 0 -a $doforceonboot -gt 0 ] && exit 0
       +
       +if [ ! -d "$nsroot" ];
       +tthen
       +        printf "$nsroot does not seem to be a valid directory.\n" >&2
       +        exit 1
       +fi
       +
       +if [ ! -d "$nsroot/.ns" ];
       +tthen
       +        mkdir -p "$nsroot/.ns"
       +        printf "MOUNTFS=\"\"\n" \
       +               "UMOUNTFS=\"\"\n" \
       +               "TOUCHFILES=\"\"\n" \
       +               "LINKFILES=\"\"\n" \ 
       +               "COPYFILES=\"\"\n" > "$nsroot/.ns/rc.conf"
       +fi
       +
       +filesystems="$MOUNTFS proc sys tmp dev dev/pts mnt home run devel nix usr/share/terminfo"
       +for m in $filesystems;
       +do
       +        mkdir -p "$nsroot/$m"
       +        mountpoint -q "$nsroot/$m" || mount -o rbind "/$m" "$nsroot/$m"
       +done
       +
       +#[ -d "$nsroot/mnt/root" ] || mkdir -p "$nsroot/mnt/root"
       +#mountpoint -q "$nsroot/mnt/root" || mount -o rbind / "$nsroot/mnt/root"
       +
       +ttfs="etc/mtab $TOUCHFILES";
       +for f in $tfs;
       +do
       +        touch "$nsroot/$f"
       +done
       +
       +cfs="bin/nssh bin/capchroot $COPYFILES"
       +for f in $cfs;
       +do
       +        [ -e "/$f" ] && cp -f "/$f" "$nsroot/$f"
       +done
       +
       +lnfs="etc/resolv.conf etc/hostname etc/localtime etc/capchroot.allow etc/hosts etc/locale.gen $LINKFILES"
       +for f in $lnfs;
       +do
       +        [ -e "/$f" ] && ln -f "/$f" "$nsroot/$f"
       +done
       +
       +t[ -x /bin/setcap ] && setcap cap_sys_chroot=ep "$nsroot/bin/capchroot"
       +
       +ttouch "$nsroot/.ns/prepared"
       +t[ $ONBOOT -gt 0 ] && touch "$nsroot/.ns/preparedonboot"
       +printf "$nsroot has been prepared.\n"
       +
       +exit 0
       +
 (DIR) diff --git a/bin/ns-root b/bin/ns-root
       @@ -0,0 +1,30 @@
       +#!/bin/sh
       +
       +if [ "$#" -lt 1 ];
       +tthen
       +        printf "usage: %s nsroot\n" "$(basename "$0")" >&2
       +        exit 1
       +fi
       +nsroot="$1"
       +
       +if [ -z "$(printf "%s\n" "$nsroot" | grep "/")" ];
       +tthen
       +        if [ -e "/ns/$nsroot" ];
       +        then
       +                printf "/ns/%s\n" "$nsroot"
       +                exit 0
       +        fi
       +        printf "Could not find nsroot '%s'.\n" "$nsroot" >&2
       +        exit 1
       +fi
       +
       +if [ ! -e "$nsroot" ];
       +tthen
       +        printf "Could not find nsroot '%s'.\n" "$nsroot" >&2
       +        exit 1
       +fi
       +
       +printf "%s\n" "$nsroot"
       +exit 0
       +
       +
 (DIR) diff --git a/bin/ns-umount b/bin/ns-umount
       @@ -0,0 +1,18 @@
       +#!/bin/sh
       +
       +if [ $# -lt 1 ];
       +tthen
       +        printf "usage: %s nsroot\n" "$(basename $0)" >&2
       +        exit 1
       +fi
       +
       +nsroot="$(ns-root "$1")"
       +t[ $? -gt 0 ] && exit $?
       +
       +mount | cut -d' ' -f 3 | grep "^${nsroot}" | sort -r \
       +        | while read -r m;
       +        do
       +                printf "Unmounting '%s'.\n" "$m"
       +                umount "$m";
       +        done
       +
 (DIR) diff --git a/bin/ns-unprepare b/bin/ns-unprepare
       @@ -0,0 +1,43 @@
       +#!/bin/sh
       +
       +doforce=0
       +t[ "$1" = "-f" ] && doforce=1 && shift 1
       +
       +if [ $# -lt 1 ];
       +tthen
       +        printf "usage: %s ns\n" "$(basename $0)" >&2
       +        exit 1
       +fi
       +
       +nsroot="$(ns-root "$1")"
       +t[ $? -gt 0 ] && exit $?
       +
       +t[ -e "$nsroot/.ns/preparedonboot" -a $doforce -eq 0 ] && exit 0
       +t[ ! -e "$nsroot/.ns/prepared" -a $doforce -eq 0 ] && exit 0
       +
       +MOUNTFS=""
       +UMOUNTFS=""
       +TOUCHFILES=""
       +COPYFILES=""
       +t[ -e "$nsroot/.ns/rc.conf" ] && . "$nsroot/.ns/rc.conf"
       +
       +if [ ! -d "$nsroot" ];
       +tthen
       +        printf "$nsroot does not seem to be a valid directory.\n" >&2
       +        exit 1
       +fi
       +
       +ns-umount "$nsroot" >/dev/null
       +
       +#ufilesystems="$UMOUNTFS proc sys tmp dev/pts mnt home run etc/conn etc/svc devel dev"
       +#for m in $ufilesystems;
       +#do
       +#        umount "$nsroot/$m"
       +#done
       +
       +rm -f "$nsroot/.ns/prepared"
       +rm -f "$nsroot/.ns/preparedonboot"
       +printf "$nsroot has been unprepared.\n"
       +
       +exit 0
       +
 (DIR) diff --git a/bin/ns-unprepare-all b/bin/ns-unprepare-all
       @@ -0,0 +1,7 @@
       +#!/bin/sh
       +
       +for ns in $(ls -1 /ns);
       +do
       +        ns-unprepare -f $(ns-root "$ns")
       +done
       +
 (DIR) diff --git a/bin/ns-update b/bin/ns-update
       @@ -0,0 +1,90 @@
       +#!/bin/sh
       +
       +usage() {
       +        printf "usage: %s [-r] ns\n" "$(basename $1)" >&2
       +        exit 1
       +}
       +
       +dorecursive=0
       +while getopts "r" opt;
       +do
       +        case $opt in
       +        r)
       +                dorecursive=1
       +                ;;
       +        *)
       +                usage $0
       +                ;;
       +        esac
       +done
       +shift $(($OPTIND - 1))
       +
       +t[ $# -lt 1 ] && usage $0
       +
       +nsroot="$(ns-root "$1")"
       +t[ $? -gt 0 ] && exit $?
       +
       +updatens() {
       +        fnsroot="$1"
       +
       +        # custom
       +        UPDATECMD=""        
       +        [ -e "$fnsroot/.ns/rc.conf" ] && . "$fnsroot/.ns/rc.conf"
       +        if [ -n "$UPDATECMD" ];
       +        then
       +                ns-chroot "$fnsroot" "$UPDATECMD"
       +                return $?
       +        fi 
       +        
       +        # pacman
       +        ppath="$(ns-path "$fnsroot" pacman 2>/dev/null)"
       +        if [ $? -eq 0 ];
       +        then
       +                ns-chroot "$fnsroot" pacman -Syu
       +                return $?
       +        fi
       +        
       +        # apt-get
       +        apath="$(ns-path "$fnsroot" apt-get 2>/dev/null)"
       +        if [ $? -eq 0 ];
       +        then
       +                ns-chroot "$fnsroot" apt-get update
       +                [ $? -gt 0 ] && return $?        
       +                ns-chroot "$fnsroot" apt-get upgrade
       +                return $?
       +        fi
       +        
       +        # yum
       +        ypath="$(ns-path "$fnsroot" yum 2>/dev/null)"
       +        if [ $? -eq 0 ];
       +        then
       +                ns-chroot "$fnsroot" yum update
       +                return $?
       +        fi
       +
       +        printf "Could not find update command for namespace %s.\n" "$fnsroot" >&2
       +        return 1        
       +}
       +
       +rerrno=0
       +if [ $dorecursive -eq 1 ];
       +tthen
       +        cd "$nsroot"
       +        for ns in $(ls -1d */);
       +        do
       +                updatens "$nsroot/$(printf "%s\n" "$ns" | tr -d "/")"
       +                [ $? -gt 0 ] && rerrno=1
       +        done
       +else
       +        updatens "$nsroot"
       +        rerrno=$?
       +fi
       +
       +if [ $rerrno -gt 0 ];
       +tthen
       +        printf "Could not update namespace %s.\n" "$nsroot" >&2
       +        exit 1
       +else
       +        exit 0
       +fi
       +
 (DIR) diff --git a/bin/ns-user b/bin/ns-user
       @@ -0,0 +1,8 @@
       +#!/bin/sh
       +
       +nsroot="$(ns-root "$1")"
       +t[ $? -gt 0 ] && exit $?
       +
       +user="$2"
       +
       +
 (DIR) diff --git a/bin/ns-vzinit b/bin/ns-vzinit
       @@ -0,0 +1,62 @@
       +#!/bin/sh
       +
       +getsortedhreflist() {
       +        wget -q -O - "$1" | sed 's/.*href="\([^"]*\)".*/\1/g' | grep ".tar...$" \
       +                | sort | while read -r href;
       +                do
       +                        printf "%s/%s\n" "$1" "$href"
       +                done
       +}
       +
       +#baseuri="http://download.proxmox.com/appliances"
       +#submodules="mail system www admin"
       +baseuri="http://download.openvz.org/template/precreated"
       +submodules="beta contrib unsupported"
       +
       +if [ $# -lt 1 ];
       +tthen
       +        printf "usage: %s cmd [opts]\n" "$(basename $0)" >&2
       +        exit 1
       +fi
       +
       +cmd="$1"
       +
       +case "$cmd" in
       +list)
       +        if [ $# -gt 1 ];
       +        then
       +                baseuri="$2"
       +                shift 2
       +                submodules="$*"
       +        fi
       +
       +        getsortedhreflist "$baseuri"        
       +        for m in $submodules;
       +        do
       +                getsortedhreflist "$baseuri/$m"
       +        done
       +        ;;
       +install)
       +        if [ $# -lt 3 ];
       +        then
       +                printf "usage: %s install uri nsroot\n" "$(basename $0)" >&2
       +                exit 1
       +        fi
       +
       +        nsroot="$3"
       +        [ ! -d "$nsroot" ] && mkdir -p "$nsroot"
       +        cd "$nsroot"
       +        [ $? -gt 0 ] && exit 1
       +
       +        filename="$(basename "$2")"        
       +        wget -O "$filename" "$2"
       +        tar -xf "$filename"
       +        rm -f "$filename"
       +        
       +        printf "$nsroot has been installed from $2.\n"
       +
       +        ;;
       +esac
       +
       +exit 0
       +
 (DIR) diff --git a/bin/ns-wrapper b/bin/ns-wrapper
       @@ -0,0 +1,17 @@
       +#!/bin/sh
       +
       +if [ $# -lt 2 ];
       +tthen
       +        printf "usage: %s ns cmd\n" "$(basename $0)" >&2
       +        exit 1
       +fi
       +
       +# nroot is checked by ns-path
       +nroot="$1"
       +cmd="$2"
       +
       +path="$(ns-path -n $nroot $cmd)"
       +t[ $? -gt 0 ] && exit 1
       +
       +printf "#!/bin/sh\nns-chroot \"%s\" %s \"\$@\"\n" "$nroot" "$path"
       +
 (DIR) diff --git a/bin/ns-wrapper-install b/bin/ns-wrapper-install
       @@ -0,0 +1,18 @@
       +#!/bin/sh
       +
       +if [ $# -lt 2 ];
       +tthen
       +        printf "usage: %s ns cmd\n" "$(basename $0)" >&2
       +        exit 1
       +fi
       +
       +# nsroot is checked by ns-wrapper
       +nroot="$1"
       +cmd="$2"
       +
       +cmdw="$(ns-wrapper $nroot $cmd)"
       +t[ $? -gt 0 ] && exit 1
       +
       +printf "%s\n" "$cmdw" > /bin/$cmd
       +chmod 755 /bin/$cmd
       +