#! /bin/sh # Apart from these three lines, it is actually a -*- tcl -*- script \ exec expect "$0" -- "$@" # This file is part of rex # Copyright (C) 2012-2016 Sergey Poznyakoff # # Rex is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3, or (at your option) # any later version. # # Rex is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Rex. If not, see . package require Tcl 8.5 package require Expect 5.44.1.15 # #################################################### set distfiles { rex { dst {$bindir} mode 0755 sed {x { global option return [regsub {^(set sysconfdir[[:space:]]+).*} $x "\\1\"$option(sysconfdir)\""] }} } rex.man8 { dst {$mandir/man8} newname rex.8 mode 0644 sed {x { global option return [regsub {^(\.ds ET[[:space:]]+).*} $x "\\1$option(sysconfdir)"] }} } lib/entrustcard { install { $optmodules } files { entrustcard.tcl pkgIndex.tcl } dst {$tclpackagedir/entrustcard1.0} } lib/vpnc { install { $optmodules } files { vpnc.tcl pkgIndex.tcl } dst {$tclpackagedir/vpnc1.0} } COPYING { install 0 } README { install 0 } NEWS { install 0 } install { install 0 } } # #################################################### set verbose 0 set dry_run 0 set keep_going 0 set optmodules 0 proc nextarg retvar { upvar $retvar ret global argc global argv if {$argc == 0} { return 0 } set ret [lindex $argv 0] set argv [lreplace $argv 0 0] incr argc -1 return 1 } proc mkdir_p dir { set parent [file dirname $dir] if {![string equal $parent "/"] && ![string equal $parent "."]} { mkdir_p $parent } if {[file exists $dir]} { if {![file isdirectory $dir]} { return -code error "component $dir exists, but is not a directory" } } else { file mkdir $dir } } proc filelist {dir retvar} { upvar $retvar l foreach name [glob -nocomplain -directory $dir -types {f d} *] { if [file isdirectory $name] { readdir $name l } else { lappend l $name } } } # install [-sed PROC] [-mode MODE] [-newname NAME] FILE ... DIR proc install args { global argv0 global keep_going global failures while {[llength $args] > 0} { switch -- [lindex $args 0] { -sed { set sedproc [lindex $args 1] set args [lreplace $args 0 1] } -mode { set mode [lindex $args 1] set args [lreplace $args 0 1] } -newname { set newname [lindex $args 1] set args [lreplace $args 0 1] } default { break } } } switch -- [llength $args] { 0 - 1 { return -code error "bad # args" } 2 { } default { if [info exist newname] { return -code error "-newname is meaningless with multiple files" } } } set destdir [lindex $args end] mkdir_p $destdir foreach src [lreplace $args end end] { if [info exist newname] { set dst [file join $destdir $newname] } else { set dst [file join $destdir [file tail $src]] } if [info exists sedproc] { set ichan [open $src "r"] set ochan [open $dst "w" 0700] while {[gets $ichan line] >= 0} { puts $ochan [apply $sedproc $line] } close $ichan close $ochan } else { file copy -force -- $src $dst } if [info exists mode] { file attributes $dst -permissions $mode } else { file attributes $dst -permissions \ [file attributes $src -permissions] } } } proc rexversion {} { set chan [open rex r] while {[gets $chan line] >= 0} { if {[regexp {^set version[[:space:]]+"([0-9\.]+)"} $line x ver]} { break } } close $chan return $ver } proc register_file {fname retvar} { global argv0 upvar $retvar filelist if {[file exists $fname]} { lappend filelist $fname } else { puts "$argv0: required file $fname does not exist" exit 1 } } proc distrib {} { global argv0 global distfiles global verbose if {![file exists .git]} { puts "install --dist must be run from the toplevel rex source directory" exit 1 } for {set i 0} {$i < [llength $distfiles]} {incr i 2} { set fname [lindex $distfiles $i] unset -nocomplain directives array set directives [lindex $distfiles [expr $i + 1]] if [info exist directives(files)] { foreach f $directives(files) { register_file [file join $fname $f] filelist } } else { register_file $fname filelist } } set tarname "rex-[rexversion]" set archive "$tarname.tar.gz" set command {tar -chozf} lappend command $archive "--transform=s|^|$tarname/|" {*}$filelist if {$verbose} { puts "running $command" } if [catch { exec {*}$command } results options] { puts stderr $results puts stderr "$argv0: tar exited with code [lindex [dict get $options -errorcode] 2]" catch {file delete $archive} exit 1 } puts "Archive $archive ready for distribution" } array set option { prefix /usr bindir {$prefix/bin} mandir {$prefix/share/man} sysconfdir /etc/rex } set options [join [concat [array names option] tclpackagedir] {|}] proc expandvar {input} { global option global options global argv0 set rx "\\\$($options)" eval "set input [regsub -all $rx $input {$option(\1)}]" return $input } proc printhelp {} { puts {usage: install [OPTION] [ENVAR=VALUE...] installs rex OPTIONS are: -n, --dry-run do nothing, print what would have been done -k, --keep-going continue working after encountering an error -v, --verbose verbosely pring what is being done --dist create distribution tarball and terminate --prefix=DIR set installation prefix (default /usr) --sysconfdir=DIR set configuration directory (/etc/rex) --bindir=DIR set directory for user executables ($prefix/bin) --mandir=DIR set man documentation root directory ($prefix/share/man) --tclpackagedir=DIR directory for installing TCL packages --extras install extra packages ENVAR=VALUE assigns VALUE to the environment variable ENVAR for install and all its subprocesses. The DESTDIR environment variable changes root installation directory. } } while {[nextarg arg]} { switch -regexp -matchvar opt -- $arg \ "^--($options)(?:(=)(.+))?$" { set optname [lindex $opt 1] if [string eq [lindex $opt 2] "="] { set optval [lindex $opt 3] } elseif {![nextarg optval]} { puts stderr "$argv0: missing argument for --$optname" exit 1 } set option($optname) $optval } \ {([[:alpha:]_][[:alnum:]_]+)=(.*)} { set env([lindex $opt 1]) [lindex $opt 2] } \ {^--extras$} { set optmodules 1 } \ {^-h$} - \ {^--help$} { printhelp exit 0 } \ {^-n$} - \ {^--dry-run$} { set verbose 1 set dry_run 1 } \ {^-v$} - \ {^--verbose$} { set verbose 1 } \ {^-k$} - \ {^--keep-going$} { set keep_going 1 } \ {^--dist$} { set dist 1 } \ default { puts stderr "$argv0: invalid option $arg" exit } } if {[info exists dist]} { distrib exit 0 } if {![info exist tclpackagedir]} { set prefixlen [string length $option(prefix)] foreach dir [lreverse $auto_path] { if {[string equal -length $prefixlen $dir $option(prefix)]} { set option(tclpackagedir) $dir break } } if {![info exist tclpackagedir]} { set option(tclpackagedir) {$prefix/lib/rex} } } if {[info exists env(DESTDIR)]} { regsub -- {/$} $env(DESTDIR) "" } else { set env(DESTDIR) "" } foreach name [array names option] { set option($name) [expandvar $option($name)] } while {[llength $distfiles] > 0} { incr numinst set src [lindex $distfiles 0] unset -nocomplain directives array set directives [lindex $distfiles 1] set distfiles [lreplace $distfiles 0 1] if {[info exists directives(install)]} { if {![expr $directives(install)]} { continue } unset directives(install) } set destdir "$env(DESTDIR)[expandvar $directives(dst)]" unset directives(dst) if {[info exist directives(files)]} { # set infiles [lmap fname $directives(files) {[file join $src $fname]}] set infiles {} foreach fname $directives(files) { lappend infiles [file join $src $fname] } unset directives(files) } elseif [file isdirectory $src] { # filelist $src infiles error "source directory is disallowed: $src" } else { set infiles [list $src] } set install_args {} foreach opt [array names directives] { lappend install_args "-$opt" $directives($opt) } if {$verbose} { puts "install $install_args {*}$infiles $destdir" } if {!$dry_run} { if {[catch {install {*}$install_args {*}$infiles $destdir} res]} { puts stderr "$argv0: $res" if {$keep_going} { lappend failures $res } else { exit 1 } } } } if {[info exists failures]} { exit 1 } exit 0