#!/bin/sh set -u ME=$(basename $0) USAGE="Usage: ${ME} {options} Builds a license metadata specification and outputs it to stdout or {outfile}. The available options are: -k kind... license kinds -c condition... license conditions -p package... license package name -n notice... license notice file -d dependency... license metadata file dependency -t target... targets -m target:installed... map dependent targets to their installed names -is_container preserved dependent target name when given -o outfile output file " # Global flag variables license_kinds= license_conditions= license_package_name= license_notice= license_deps= targets= installmap= is_container=false ofile= # Global variables depfiles=" " effective_conditions= # Exits with a message. # # When the exit status is 2, assumes a usage error and outputs the usage message # to stderr before outputting the specific error message to stderr. # # Parameters: # Optional numeric exit status (defaults to 2, i.e. a usage error.) # Remaining args treated as an error message sent to stderr. die() { lstatus=2 case "${1:-}" in *[^0-9]*) ;; *) lstatus="$1"; shift ;; esac case "${lstatus}" in 2) echo "${USAGE}" >&2; echo >&2 ;; esac if [ -n "$*" ]; then echo -e "$*\n" >&2 fi exit $lstatus } # Sets the flag variables based on the command-line. # # invoke with: process_args "$@" process_args() { lcurr_flag= while [ "$#" -gt '0' ]; do case "${1}" in -h) echo "${USAGE}" exit 0 ;; -k) lcurr_flag=kind ;; -c) lcurr_flag=condition ;; -p) lcurr_flag=package ;; -n) lcurr_flag=notice ;; -d) lcurr_flag=dependency ;; -t) lcurr_flag=target ;; -m) lcurr_flag=installmap ;; -o) lcurr_flag=ofile ;; -is_container) lcurr_flag= is_container=true ;; -*) die "Unknown flag: \"${1}\"" ;; *) case "${lcurr_flag}" in kind) license_kinds="${license_kinds}${license_kinds:+ }${1}" ;; condition) license_conditions="${license_conditions}${license_conditions:+ }${1}" ;; package) license_package_name="${license_package_name}${license_package_name:+ }${1}" ;; notice) license_notice="${license_notice}${license_notice:+ }${1}" ;; dependency) license_deps="${license_deps}${license_deps:+ }${1}" ;; target) targets="${targets}${targets:+ }${1}" ;; installmap) installmap="${installmap}${installmap:+ }${1}" ;; ofile) if [ -n "${ofile}" ]; then die "Output file -o appears twice as \"${ofile}\" and \"${1}\"" fi ofile="${1}" ;; *) die "Must precede argument \"${1}\" with type flag." ;; esac ;; esac shift done } # Reads a license metadata file from stdin, and outputs the named dependencies. # # No parameters. extract_deps() { awk '$1 == "dep_name:" { sub(/^"/, "", $2); sub(/"$/, "", $2); print $2; }' } # Populates the depfiles variable identifying dependency files. # # Starting with the dependencies enumerated in license_deps, calculates the # transitive closure of all dependencies. # # Dependency names ending in .meta_module indirectly reference license # metadata with 1 license metadata filename per line. # # No parameters; no output. read_deps() { lnewdeps= for d in ${license_deps}; do case "${d}" in *.meta_module) lnewdeps="${lnewdeps}${lnewdeps:+ }"$(cat "${d}") ;; *) lnewdeps="${lnewdeps}${lnewdeps:+ }${d}" ;; esac done lnewdeps=$(echo "${lnewdeps}" | tr ' ' '\n' | sort -u) lalldeps= ldeps= lmod= ldep= while [ "${#lnewdeps}" -gt '0' ]; do ldeps="${lnewdeps}" lnewdeps= for ldep in ${ldeps}; do depfiles="${depfiles}${ldep} " lalldeps="${lalldeps}${lalldeps:+ }"$(cat "${ldep}" | extract_deps) done lalldeps=$(for d in ${lalldeps}; do echo "${d}"; done | sort -u) for d in ${lalldeps}; do ldeps="${d}" case "${d}" in *.meta_module) ldeps=$(cat "${d}") ;; esac for lmod in ${ldeps}; do if ! expr "${depfiles}" : ".* ${lmod} .*" >/dev/null 2>&1; then lnewdeps="${lnewdeps}${lnewdeps:+ }${lmod}" fi done done lalldeps= done } # Returns the effective license conditions for the current license metadata. # # If a module is restricted or links in a restricted module, the effective # license has a restricted condition. calculate_effective_conditions() { lconditions="${license_conditions}" case "${license_conditions}" in *restricted*) : do nothing ;; *) for d in ${depfiles}; do if cat "${d}" | egrep -q 'effective_condition\s*:.*restricted' ; then lconditions="${lconditions}${lconditions:+ }restricted" break fi done ;; esac echo "${lconditions}" } process_args "$@" if [ -n "${ofile}" ]; then # truncate the output file before appending results : >"${ofile}" else ofile=/dev/stdout fi # spit out the license metadata file content ( echo 'license_package_name: "'${license_package_name}'"' for kind in ${license_kinds}; do echo 'license_kind: "'${kind}'"' done for condition in ${license_conditions}; do echo 'license_condition: "'${condition}'"' done for f in ${license_notice}; do echo 'license_text: "'${f}'"' done echo "is_container: ${is_container}" for t in ${targets}; do echo 'target: "'${t}'"' done for m in ${installmap}; do echo 'install_map: "'${m}'"' done ) >>"${ofile}" read_deps effective_conditions=$(calculate_effective_conditions) for condition in ${effective_conditions}; do echo 'effective_condition: "'${condition}'"' done >>"${ofile}" for dep in ${depfiles}; do echo 'dep {' cat "${dep}" | \ awk -v name="${dep}" ' function strip_type() { $1 = "" sub(/^\s*/, "") } BEGIN { print " dep_name: " name } $1 == "license_package_name:" { strip_type() print " dep_package_name: "$0 } $1 == "dep_name:" { print " dep_sub_dep: "$2 } $1 == "license_kind:" { print " dep_license_kind: "$2 } $1 == "license_condition:" { print " dep_license_condition: "$2 } $1 == "is_container:" { print " dep_is_container: "$2 } $1 == "license_text:" { strip_type() print " dep_license_text: "$0 } $1 == "target:" { print " dep_target: "$2 } $1 == "install_map:" { print " dep_install_map: "$2 } ' # The restricted license kind is contagious to all linked dependencies. dep_conditions=$(echo $( cat "${dep}" | awk ' $1 == "effective_condition:" { $1 = "" sub(/^\s*/, "") gsub(/"/, "") print } ' )) for condition in ${dep_conditions}; do echo ' dep_effective_condition: "'${condition}'"' done if ! ${is_container}; then case "${dep_conditions}" in *restricted*) : already restricted -- nothing to inherit ;; *) case "${effective_conditions}" in *restricted*) # "contagious" restricted infects everything linked to restricted echo ' dep_effective_condition: "restricted"' ;; esac ;; esac fi echo '}' done >>"${ofile}"