From dde4451b8524b444a809c048e730fae486830c4b Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Mon, 1 Aug 2022 18:52:41 +0200 Subject: [PATCH] src/cmd/INIT/package.sh: add install subcommand This now allows easy installation via: bin/package install DESTINATION_DIRECTORY [ COMMAND ... ] Commands are installed in bin and share/man subdirectories. If no command is specified, ksh and shcomp are assumed. --- README.md | 18 +++++---- bin/package | 81 +++++++++++++++++++++++++++++++++++++---- src/cmd/INIT/package.sh | 81 +++++++++++++++++++++++++++++++++++++---- src/cmd/ksh93/README | 19 ++++++---- 4 files changed, 171 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 03413f246..c1cc0caf2 100644 --- a/README.md +++ b/README.md @@ -80,13 +80,17 @@ bin/shtests --man ### Install -Automated installation is not supported yet. -To install manually: -```sh -cp arch/$(bin/package host type)/bin/ksh /usr/local/bin/ -cp src/cmd/ksh93/sh.1 /usr/local/share/man/man1/ksh.1 -``` -(adapting the destination directories as required). +Usage: `bin/package install` *destination_directory* [ *command* ... ] + +Any command from the `arch` directory can be installed. If no *command* is +specified, `ksh` and `shcomp` are assumed. + +The *destination_directory* is created if it does not exist. Commands are +installed in its `bin` subdirectory and each command's manual page, if +available, is installed in `share/man`. + +Destination directories with whitespace or shell pattern characters in their +pathnames are not yet supported. ## What is ksh93? diff --git a/bin/package b/bin/package index 7d3b3713a..f8a3ef532 100755 --- a/bin/package +++ b/bin/package @@ -106,7 +106,7 @@ command=${0##*/} case $(getopts '[-][123:xyz]' opt --xyz 2>/dev/null; echo 0$opt) in 0123) USAGE=$' [-? -@(#)$Id: '$command$' (ksh 93u+m) 2022-07-25 $ +@(#)$Id: '$command$' (ksh 93u+m) 2022-08-01 $ ] [-author?Glenn Fowler ] [-author?Contributors to https://github.com/ksh93/ksh] @@ -193,7 +193,17 @@ case $(getopts '[-][123:xyz]' opt --xyz 2>/dev/null; echo 0$opt) in release incompatibilities has for the most part been futile.] } - [+install\b To be reimplemented.] + [+install\b [ \adest_dir\a ]] [ \acommand\a ... ]]?Install commands + from the \b$INSTALLROOT\b tree + into appropriate subdirectories of \adest_dir\a. + If \adest_dir\a does not exist, + then it and any necessary subdirectories are created. + \adest_dir\a can be a directory like \a/usr/local\a + to install the \acommand\as directly, + or a temporary directory like \a/tmp/pkgtree/usr\a + to prepare for packaging with operating system-specific tools. + If no \acommand\a is specified, + then \aksh\a and \ashcomp\a are assumed.] [+make\b [ \apackage\a ]] [ \aoption\a ... ]] [ \atarget\a ... ]]?Build and install. The default \atarget\a is \binstall\b, which makes and installs \apackage\a. If the standard output is a terminal @@ -454,7 +464,14 @@ DESCRIPTION similar, predictable style. OS point release information is avoided as much as possible, but vendor resistance to release incompatibilities has for the most part been futile. - install To be reimplemented. + install [ dest_dir ] [ command ... ] + Install commands from the $INSTALLROOT tree into appropriate + subdirectories of dest_dir. If dest_dir does not exist, then it and + any necessary subdirectories are created. dest_dir can be a directory + like /usr/local to install the commands directly, or a temporary + directory like /tmp/pkgtree/usr to prepare for packaging with + operating system-specific tools. If no command is specified, then ksh + and shcomp are assumed. make [ package ] [ option ... ] [ target ... ] Build and install. The default target is install, which makes and installs package. If the standard output is a terminal then the @@ -535,7 +552,7 @@ SEE ALSO mamake(1), pax(1), pkgadd(1), pkgmk(1), rpm(1), sh(1), tar(1), optget(3) IMPLEMENTATION - version package (ksh 93u+m) 2022-02-24 + version package (ksh 93u+m) 2022-08-01 author Glenn Fowler author Contributors to https://github.com/ksh93/ksh copyright (c) 1994-2012 AT&T Intellectual Property @@ -1705,6 +1722,14 @@ err_out() exit 1 } +trace() +( + PS4="${action}: executing: " + exec 2>&1 # trace to standard output + set -o xtrace + "$@" +) + # cc checks # # CC: compiler base name name @@ -2634,6 +2659,48 @@ make_recurse() # dir done } +do_install() # dir [ command ... ] +{ + cd "$INSTALLROOT" + printf 'install: installing from %s\n' "$PWD" + set -o errexit + dd=$1 + shift + case $dd in + '' | [^/]*) + err_out "ERROR: destination directory '$dd' must begin with a /" ;; + esac + # commands to install by default + test "$#" -eq 0 && set -- ksh shcomp # pty suid_exec + for f + do test -f "bin/$f" || err_out "Not found: $f" "Build first? Run $0 make" + done + # set install directories + bindir=$dd/bin + mandir=$dd/share/man + man1dir=$mandir/man1 + # and off we go + trace mkdir -p "$bindir" "$man1dir" + for f + do # install executable + trace cp "bin/$f" "$bindir/" + # install manual + case $f in + ksh) trace cp "$PACKAGEROOT/src/cmd/ksh93/sh.1" "$man1dir/ksh.1" + ;; + *) # AT&T --man, etc. is a glorified error message: writes to stderr and exits with status 2 :-/ + manfile=$man1dir/${f##*/}.1 + bin/ksh -c '"$@" 2>&1; exit 0' _ "bin/$f" --nroff >$manfile + # ...so we cannot check for success; instead, check the result. + if grep -q '^.TH .* 1' "$manfile" + then printf "install: wrote '%s --nroff' output into %s\n" "bin/$f" "$manfile" + else rm "$manfile" + fi + ;; + esac + done +} + # check for native ASCII 0:yes 1:no __isascii__= @@ -2704,9 +2771,9 @@ export) case $INSTALLROOT in ;; install)cd $PACKAGEROOT - echo "A proper installation command is coming back soon, sorry." >&2 - echo "Meanwhile, copy ksh and shcomp from: $INSTALLROOT/arch/$HOSTTYPE/bin" >&2 - exit 1 + # TODO: breaks on directories with spaces or glob characters; make arguments handling robust + test -n "$args" || err_out "Usage: $0 install ROOTDIR [ COMMANDNAME ... ]" + capture do_install $args ;; make|view) diff --git a/src/cmd/INIT/package.sh b/src/cmd/INIT/package.sh index 7d3b3713a..f8a3ef532 100644 --- a/src/cmd/INIT/package.sh +++ b/src/cmd/INIT/package.sh @@ -106,7 +106,7 @@ command=${0##*/} case $(getopts '[-][123:xyz]' opt --xyz 2>/dev/null; echo 0$opt) in 0123) USAGE=$' [-? -@(#)$Id: '$command$' (ksh 93u+m) 2022-07-25 $ +@(#)$Id: '$command$' (ksh 93u+m) 2022-08-01 $ ] [-author?Glenn Fowler ] [-author?Contributors to https://github.com/ksh93/ksh] @@ -193,7 +193,17 @@ case $(getopts '[-][123:xyz]' opt --xyz 2>/dev/null; echo 0$opt) in release incompatibilities has for the most part been futile.] } - [+install\b To be reimplemented.] + [+install\b [ \adest_dir\a ]] [ \acommand\a ... ]]?Install commands + from the \b$INSTALLROOT\b tree + into appropriate subdirectories of \adest_dir\a. + If \adest_dir\a does not exist, + then it and any necessary subdirectories are created. + \adest_dir\a can be a directory like \a/usr/local\a + to install the \acommand\as directly, + or a temporary directory like \a/tmp/pkgtree/usr\a + to prepare for packaging with operating system-specific tools. + If no \acommand\a is specified, + then \aksh\a and \ashcomp\a are assumed.] [+make\b [ \apackage\a ]] [ \aoption\a ... ]] [ \atarget\a ... ]]?Build and install. The default \atarget\a is \binstall\b, which makes and installs \apackage\a. If the standard output is a terminal @@ -454,7 +464,14 @@ DESCRIPTION similar, predictable style. OS point release information is avoided as much as possible, but vendor resistance to release incompatibilities has for the most part been futile. - install To be reimplemented. + install [ dest_dir ] [ command ... ] + Install commands from the $INSTALLROOT tree into appropriate + subdirectories of dest_dir. If dest_dir does not exist, then it and + any necessary subdirectories are created. dest_dir can be a directory + like /usr/local to install the commands directly, or a temporary + directory like /tmp/pkgtree/usr to prepare for packaging with + operating system-specific tools. If no command is specified, then ksh + and shcomp are assumed. make [ package ] [ option ... ] [ target ... ] Build and install. The default target is install, which makes and installs package. If the standard output is a terminal then the @@ -535,7 +552,7 @@ SEE ALSO mamake(1), pax(1), pkgadd(1), pkgmk(1), rpm(1), sh(1), tar(1), optget(3) IMPLEMENTATION - version package (ksh 93u+m) 2022-02-24 + version package (ksh 93u+m) 2022-08-01 author Glenn Fowler author Contributors to https://github.com/ksh93/ksh copyright (c) 1994-2012 AT&T Intellectual Property @@ -1705,6 +1722,14 @@ err_out() exit 1 } +trace() +( + PS4="${action}: executing: " + exec 2>&1 # trace to standard output + set -o xtrace + "$@" +) + # cc checks # # CC: compiler base name name @@ -2634,6 +2659,48 @@ make_recurse() # dir done } +do_install() # dir [ command ... ] +{ + cd "$INSTALLROOT" + printf 'install: installing from %s\n' "$PWD" + set -o errexit + dd=$1 + shift + case $dd in + '' | [^/]*) + err_out "ERROR: destination directory '$dd' must begin with a /" ;; + esac + # commands to install by default + test "$#" -eq 0 && set -- ksh shcomp # pty suid_exec + for f + do test -f "bin/$f" || err_out "Not found: $f" "Build first? Run $0 make" + done + # set install directories + bindir=$dd/bin + mandir=$dd/share/man + man1dir=$mandir/man1 + # and off we go + trace mkdir -p "$bindir" "$man1dir" + for f + do # install executable + trace cp "bin/$f" "$bindir/" + # install manual + case $f in + ksh) trace cp "$PACKAGEROOT/src/cmd/ksh93/sh.1" "$man1dir/ksh.1" + ;; + *) # AT&T --man, etc. is a glorified error message: writes to stderr and exits with status 2 :-/ + manfile=$man1dir/${f##*/}.1 + bin/ksh -c '"$@" 2>&1; exit 0' _ "bin/$f" --nroff >$manfile + # ...so we cannot check for success; instead, check the result. + if grep -q '^.TH .* 1' "$manfile" + then printf "install: wrote '%s --nroff' output into %s\n" "bin/$f" "$manfile" + else rm "$manfile" + fi + ;; + esac + done +} + # check for native ASCII 0:yes 1:no __isascii__= @@ -2704,9 +2771,9 @@ export) case $INSTALLROOT in ;; install)cd $PACKAGEROOT - echo "A proper installation command is coming back soon, sorry." >&2 - echo "Meanwhile, copy ksh and shcomp from: $INSTALLROOT/arch/$HOSTTYPE/bin" >&2 - exit 1 + # TODO: breaks on directories with spaces or glob characters; make arguments handling robust + test -n "$args" || err_out "Usage: $0 install ROOTDIR [ COMMANDNAME ... ]" + capture do_install $args ;; make|view) diff --git a/src/cmd/ksh93/README b/src/cmd/ksh93/README index 39dfdee6d..0abd35bc3 100644 --- a/src/cmd/ksh93/README +++ b/src/cmd/ksh93/README @@ -198,6 +198,18 @@ character locales and really want to save some memory and CPU cycles, add '-DAST_NOMULTIBYTE' to CCFLAGS to compile out all multibyte character handling in ksh and supporting libraries. Not recommended for most users. +To install, use: bin/package install DESTINATION_DIRECTORY [ COMMAND ... ] + +Any command from the arch directory can be installed. If no COMMAND is +specified, ksh and shcomp are assumed. + +The DESTINATION_DIRECTORY is created if it does not exist. Commands are +installed in its bin subdirectory and each command's manual page, if +available, is installed in share/man. + +Destination directories with whitespace or shell pattern characters in their +pathnames are not yet supported. + For more information, run: bin/package help @@ -205,13 +217,6 @@ For more information, run: Many other commands in this repo self-document via the --help, --man and --html options; those that do have no separate manual page. -Automated installation is not supported yet. To install manually: - - cp arch/$(bin/package host type)/bin/ksh /usr/local/bin/ - cp src/cmd/ksh93/sh.1 /usr/local/share/man/man1/ksh.1 - -(adapting the destination directories as required). - The build should also generate shcomp, a program that will precompile a script. ksh93 is able to recognize files in this format and process them as scripts. You can use shcomp to send out scripts when you