#!/bin/bash

# Run all the different permutations of all the tests and other things
# This helps ensure that nothing gets broken.

_tests() {
    local vet="" # TODO: make it off
    local gover=$( ${gocmd} version | cut -f 3 -d ' ' )
    [[ $( ${gocmd} version ) == *"gccgo"* ]] && zcover=0
    [[ $( ${gocmd} version ) == *"gollvm"* ]] && zcover=0
    case $gover in
        go1.[7-9]*|go1.1[0-9]*|go2.*|devel*) true ;;
        *) return 1
    esac
    # note that codecgen requires fastpath, so you cannot do "codecgen codec.notfastpath"
    # we test the following permutations wnich all execute different code paths as below.
    echo "TestCodecSuite: (fastpath/unsafe), (!fastpath/unsafe), (fastpath/!unsafe), (!fastpath/!unsafe), (codecgen/unsafe)"
    local echo=1
    local nc=2 # count
    local cpus="1,$(nproc)"
    # if using the race detector, then set nc to
    if [[ " ${zargs[@]} " =~ "-race" ]]; then
        cpus="$(nproc)"
    fi
    local a=( "" "codec.notfastpath" "codec.safe" "codec.notfastpath codec.safe"  "codecgen" )
    local b=()
    local c=()
    for i in "${a[@]}"
    do
        local i2=${i:-default}
        [[ "$zwait" == "1" ]] && echo ">>>> TAGS: 'alltests $i'; RUN: 'TestCodecSuite'"
        [[ "$zcover" == "1" ]] && c=( -coverprofile "${i2// /-}.cov.out" )
        true &&
            ${gocmd} vet -printfuncs "errorf" "$@" &&
            if [[ "$echo" == 1 ]]; then set -o xtrace; fi &&
            ${gocmd} test ${zargs[*]} ${ztestargs[*]} -vet "$vet" -tags "alltests $i" -count $nc -cpu $cpus -run "TestCodecSuite" "${c[@]}" "$@" &
        if [[ "$echo" == 1 ]]; then set +o xtrace; fi
        b+=("${i2// /-}.cov.out")
        [[ "$zwait" == "1" ]] && wait

        # if [[ "$?" != 0 ]]; then return 1; fi
    done
    if [[ "$zextra" == "1" ]]; then
        [[ "$zwait" == "1" ]] && echo ">>>> TAGS: 'codec.notfastpath x'; RUN: 'Test.*X$'"
        [[ "$zcover" == "1" ]] && c=( -coverprofile "x.cov.out" )
        ${gocmd} test ${zargs[*]} ${ztestargs[*]} -vet "$vet" -tags "codec.notfastpath x" -count $nc -run 'Test.*X$' "${c[@]}" &
        b+=("x.cov.out")
        [[ "$zwait" == "1" ]] && wait
    fi
    wait
    # go tool cover is not supported for gccgo, gollvm, other non-standard go compilers
    [[ "$zcover" == "1" ]] &&
        command -v gocovmerge &&
        gocovmerge "${b[@]}" > __merge.cov.out &&
        ${gocmd} tool cover -html=__merge.cov.out
}

# is a generation needed?
_ng() {
    local a="$1"
    if [[ ! -e "$a" ]]; then echo 1; return; fi
    for i in `ls -1 *.go.tmpl gen.go values_test.go`
    do
        if [[ "$a" -ot "$i" ]]; then echo 1; return; fi
    done
}

_prependbt() {
    cat > ${2} <<EOF
// +build generated

EOF
    cat ${1} >> ${2}
    rm -f ${1}
}

# _build generates fast-path.go and gen-helper.go.
_build() {
    if ! [[ "${zforce}" || $(_ng "fast-path.generated.go") || $(_ng "gen-helper.generated.go") || $(_ng "gen.generated.go") ]]; then return 0; fi

    if [ "${zbak}" ]; then
        _zts=`date '+%m%d%Y_%H%M%S'`
        _gg=".generated.go"
        [ -e "gen-helper${_gg}" ] && mv gen-helper${_gg} gen-helper${_gg}__${_zts}.bak
        [ -e "fast-path${_gg}" ] && mv fast-path${_gg} fast-path${_gg}__${_zts}.bak
        [ -e "gen${_gg}" ] && mv gen${_gg} gen${_gg}__${_zts}.bak
    fi
    rm -f gen-helper.generated.go fast-path.generated.go gen.generated.go \
       *safe.generated.go *_generated_test.go *.generated_ffjson_expose.go

    cat > gen.generated.go <<EOF
// +build codecgen.exec

// Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a MIT license found in the LICENSE file.

package codec

// DO NOT EDIT. THIS FILE IS AUTO-GENERATED FROM gen-dec-(map|array).go.tmpl

const genDecMapTmpl = \`
EOF
    cat >> gen.generated.go < gen-dec-map.go.tmpl
    cat >> gen.generated.go <<EOF
\`

const genDecListTmpl = \`
EOF
    cat >> gen.generated.go < gen-dec-array.go.tmpl
    cat >> gen.generated.go <<EOF
\`

const genEncChanTmpl = \`
EOF
    cat >> gen.generated.go < gen-enc-chan.go.tmpl
    cat >> gen.generated.go <<EOF
\`
EOF
    cat > gen-from-tmpl.codec.generated.go <<EOF
package codec
func GenRunTmpl2Go(in, out string) { genRunTmpl2Go(in, out) }
func GenRunSortTmpl2Go(in, out string) { genRunSortTmpl2Go(in, out) }
EOF

    # stub xxxRv and xxxRvSlice creation, before you create it
    cat > gen-from-tmpl.sort-slice-stubs.generated.go <<EOF
// +build codecgen.sort_slice

package codec

import "reflect"
import "time"

EOF

    for i in string bool uint64 int64 float64 bytes time; do
        local i2=$i
        case $i in
            'time' ) i2="time.Time";;
            'bytes' ) i2="[]byte";;
        esac

        cat >> gen-from-tmpl.sort-slice-stubs.generated.go <<EOF
type ${i}Rv struct { v ${i2}; r reflect.Value }

type ${i}RvSlice []${i}Rv

func (${i}RvSlice) Len() int { return 0 }
func (${i}RvSlice) Less(i, j int) bool { return false }
func (${i}RvSlice) Swap(i, j int) {}

type ${i}Intf struct { v ${i2}; i interface{} }

type ${i}IntfSlice []${i}Intf

func (${i}IntfSlice) Len() int { return 0 }
func (${i}IntfSlice) Less(i, j int) bool { return false }
func (${i}IntfSlice) Swap(i, j int) {}

EOF
    done

    sed -e 's+// __DO_NOT_REMOVE__NEEDED_FOR_REPLACING__IMPORT_PATH__FOR_CODEC_BENCH__+import . "github.com/ugorji/go/codec"+' \
        shared_test.go > bench/shared_test.go

    # explicitly return 0 if this passes, else return 1
    local btags="codec.notfastpath codec.safe codecgen.exec"
    rm -f sort-slice.generated.go fast-path.generated.go gen-helper.generated.go mammoth_generated_test.go mammoth2_generated_test.go

    cat > gen-from-tmpl.sort-slice.generated.go <<EOF
// +build ignore

package main

import "${zpkg}"

func main() {
codec.GenRunSortTmpl2Go("sort-slice.go.tmpl", "sort-slice.generated.go")
}
EOF

    ${gocmd} run -tags "$btags codecgen.sort_slice" gen-from-tmpl.sort-slice.generated.go || return 1
    rm -f gen-from-tmpl.sort-slice.generated.go

    cat > gen-from-tmpl.generated.go <<EOF
// +build ignore

package main

import "${zpkg}"

func main() {
codec.GenRunTmpl2Go("fast-path.go.tmpl", "fast-path.generated.go")
codec.GenRunTmpl2Go("gen-helper.go.tmpl", "gen-helper.generated.go")
codec.GenRunTmpl2Go("mammoth-test.go.tmpl", "mammoth_generated_test.go")
codec.GenRunTmpl2Go("mammoth2-test.go.tmpl", "mammoth2_generated_test.go")
}
EOF

    ${gocmd} run -tags "$btags" gen-from-tmpl.generated.go || return 1
    rm -f gen-from-tmpl.generated.go

    rm -f gen-from-tmpl.*generated.go
    return 0
}

_codegenerators() {
    local c5="_generated_test.go"
    local c7="$PWD/codecgen"
    local c8="$c7/__codecgen"
    local c9="codecgen-scratch.go"

    if ! [[ $zforce || $(_ng "values_codecgen${c5}") ]]; then return 0; fi

    # Note: ensure you run the codecgen for this codebase/directory i.e. ./codecgen/codecgen
    true &&
        echo "codecgen ... " &&
        if [[ $zforce || ! -f "$c8" || "$c7/gen.go" -nt "$c8" ]]; then
            echo "rebuilding codecgen ... " && ( cd codecgen && ${gocmd} build -o $c8 ${zargs[*]} . )
        fi &&
        $c8 -rt 'codecgen' -t 'codecgen generated' -o "values_codecgen${c5}" -d 19780 "$zfin" "$zfin2" &&
        cp mammoth2_generated_test.go $c9 &&
        $c8 -t 'codecgen,!codec.notfastpath,!codec.notmammoth generated,!codec.notfastpath,!codec.notmammoth' -o "mammoth2_codecgen${c5}" -d 19781 "mammoth2_generated_test.go" &&
        rm -f $c9 &&
        echo "generators done!"
}

_prebuild() {
    echo "prebuild: zforce: $zforce"
    local d="$PWD"
    local zfin="test_values.generated.go"
    local zfin2="test_values_flex.generated.go"
    local zpkg="github.com/ugorji/go/codec"
    local returncode=1

    # zpkg=${d##*/src/}
    # zgobase=${d%%/src/*}
    # rm -f *_generated_test.go
    rm -f codecgen-*.go &&
        _build &&
        cp $d/values_test.go $d/$zfin &&
        cp $d/values_flex_test.go $d/$zfin2 &&
        _codegenerators &&
        if [[ "$(type -t _codegenerators_external )" = "function" ]]; then _codegenerators_external ; fi &&
        if [[ $zforce ]]; then ${gocmd} install ${zargs[*]} .; fi &&
        returncode=0 &&
        echo "prebuild done successfully"
    rm -f $d/$zfin $d/$zfin2
    return $returncode
    # unset zfin zfin2 zpkg
}

_make() {
    local makeforce=${zforce}
    zforce=1
    (cd codecgen && ${gocmd} install ${zargs[*]} .) && _prebuild && ${gocmd} install ${zargs[*]} .
    zforce=${makeforce}
}

_clean() {
    rm -f \
       gen-from-tmpl.*generated.go \
       codecgen-*.go \
       test_values.generated.go test_values_flex.generated.go
}

_release() {
    local reply
    read -p "Pre-release validation takes a few minutes and MUST be run from within GOPATH/src. Confirm y/n? " -n 1 -r reply
    echo
    if [[ ! $reply =~ ^[Yy]$ ]]; then return 1; fi

    # expects GOROOT, GOROOT_BOOTSTRAP to have been set.
    if [[ -z "${GOROOT// }" || -z "${GOROOT_BOOTSTRAP// }" ]]; then return 1; fi
    # (cd $GOROOT && git checkout -f master && git pull && git reset --hard)
    (cd $GOROOT && git pull)
    local f=`pwd`/make.release.out
    cat > $f <<EOF
========== `date` ===========
EOF
    # # go 1.6 and below kept giving memory errors on Mac OS X during SDK build or go run execution,
    # # that is fine, as we only explicitly test the last 3 releases and tip (2 years).
    local makeforce=${zforce}
    zforce=1
    for i in 1.10 1.11 1.12 master
    do
        echo "*********** $i ***********" >>$f
        if [[ "$i" != "master" ]]; then i="release-branch.go$i"; fi
        (false ||
             (echo "===== BUILDING GO SDK for branch: $i ... =====" &&
                  cd $GOROOT &&
                  git checkout -f $i && git reset --hard && git clean -f . &&
                  cd src && ./make.bash >>$f 2>&1 && sleep 1 ) ) &&
            echo "===== GO SDK BUILD DONE =====" &&
            _prebuild &&
            echo "===== PREBUILD DONE with exit: $? =====" &&
            _tests "$@"
        if [[ "$?" != 0 ]]; then return 1; fi
    done
    zforce=${makeforce}
    echo "++++++++ RELEASE TEST SUITES ALL PASSED ++++++++"
}

_usage() {
    # hidden args:
    # -pf [p=prebuild (f=force)]

    cat <<EOF
primary usage: $0
    -[tesow m n l d]   -> [t=tests (e=extra, s=short, o=cover, w=wait), m=make, n=inlining diagnostics, l=mid-stack inlining, d=race detector]
    -v                   -> v=verbose
EOF
    if [[ "$(type -t _usage_run)" = "function" ]]; then _usage_run ; fi
}

_main() {
    if [[ -z "$1" ]]; then _usage; return 1; fi
    local x # determines the main action to run in this build
    local zforce # force
    local zcover # generate cover profile and show in browser when done
    local zwait # run tests in sequence, not parallel ie wait for one to finish before starting another
    local zextra # means run extra (python based tests, etc) during testing

    local ztestargs=()
    local zargs=()
    local zverbose=()
    local zbenchflags=""

    local gocmd=${MYGOCMD:-go}

    OPTIND=1
    while getopts ":cetmnrgpfvldsowkxyzb:" flag
    do
        case "x$flag" in
            'xo') zcover=1 ;;
            'xe') zextra=1 ;;
            'xw') zwait=1 ;;
            'xf') zforce=1 ;;
            'xs') ztestargs+=("-short") ;;
            'xv') zverbose+=(1) ;;
            'xl') zargs+=("-gcflags"); zargs+=("-l=4") ;;
            'xn') zargs+=("-gcflags"); zargs+=("-m=2") ;;
            'xd') zargs+=("-race") ;;
            'xb') x='b'; zbenchflags=${OPTARG} ;;
            x\?) _usage; return 1 ;;
            *) x=$flag ;;
        esac
    done
    shift $((OPTIND-1))
    # echo ">>>> _main: extra args: $@"
    case "x$x" in
        'xt') _tests "$@" ;;
        'xm') _make "$@" ;;
        'xr') _release "$@" ;;
        'xg') _go ;;
        'xp') _prebuild "$@" ;;
        'xc') _clean "$@" ;;
        'xx') _analyze_checks "$@" ;;
        'xy') _analyze_debug_types "$@" ;;
        'xz') _analyze_do_inlining_and_more "$@" ;;
        'xk') _go_compiler_validation_suite ;;
        'xb') _bench "$@" ;;
    esac
    # unset zforce zargs zbenchflags
}

[ "." = `dirname $0` ] && _main "$@"


#!/usr/bin/env bash

# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -euo pipefail

top_dir='.'
if [[ $# -gt 0 ]]; then
    top_dir="${1}"
fi

p=$(pwd)
mod_dirs=()

# Note `mapfile` does not exist in older bash versions:
# https://stackoverflow.com/questions/41475261/need-alternative-to-readarray-mapfile-for-script-on-older-version-of-bash

while IFS= read -r line; do
    mod_dirs+=("$line")
done < <(find "${top_dir}" -type f -name 'go.mod' -exec dirname {} \; | sort)

for mod_dir in "${mod_dirs[@]}"; do
    cd "${mod_dir}"

    while IFS= read -r line; do
        echo ".${line#${p}}"
    done < <(go list --find -f '{{.Name}}|{{.Dir}}' ./... | grep '^main|' | cut -f 2- -d '|')
    cd "${p}"
done


#!/bin/bash

# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -euo pipefail

cd $(dirname $0)
TOOLS_DIR=$(pwd)/.tools

if [ -z "${GOPATH}" ] ; then
	printf "GOPATH is not defined.\n"
	exit -1
fi

if [ ! -d "${GOPATH}" ] ; then
	printf "GOPATH ${GOPATH} is invalid \n"
	exit -1
fi

# Pre-requisites
if ! git diff --quiet; then \
	git status
	printf "\n\nError: working tree is not clean\n"
	exit -1
fi

if [ "$(git tag --contains $(git log -1 --pretty=format:"%H"))" = "" ] ; then
	printf "$(git log -1)"
	printf "\n\nError: HEAD is not pointing to a tagged version"
fi

make ${TOOLS_DIR}/gojq

DIR_TMP="${GOPATH}/src/oteltmp/"
rm -rf $DIR_TMP
mkdir -p $DIR_TMP

printf "Copy examples to ${DIR_TMP}\n"
cp -a ./example ${DIR_TMP}

# Update go.mod files
printf "Update go.mod: rename module and remove replace\n"

PACKAGE_DIRS=$(find . -mindepth 2 -type f -name 'go.mod' -exec dirname {} \; | egrep 'example' | sed 's/^\.\///' | sort)

for dir in $PACKAGE_DIRS; do
	printf "  Update go.mod for $dir\n"
	(cd "${DIR_TMP}/${dir}" && \
	 # replaces is ("mod1" "mod2" â€¦)
	 replaces=($(go mod edit -json | ${TOOLS_DIR}/gojq '.Replace[].Old.Path')) && \
	 # strip double quotes
	 replaces=("${replaces[@]%\"}") && \
	 replaces=("${replaces[@]#\"}") && \
	 # make an array (-dropreplace=mod1 -dropreplace=mod2 â€¦)
	 dropreplaces=("${replaces[@]/#/-dropreplace=}") && \
	 go mod edit -module "oteltmp/${dir}" "${dropreplaces[@]}" && \
	 go mod tidy)
done
printf "Update done:\n\n"

# Build directories that contain main package. These directories are different than
# directories that contain go.mod files.
printf "Build examples:\n"
EXAMPLES=$(./get_main_pkgs.sh ./example)
for ex in $EXAMPLES; do
	printf "  Build $ex in ${DIR_TMP}/${ex}\n"
	(cd "${DIR_TMP}/${ex}" && \
	 go build .)
done

# Cleanup
printf "Remove copied files.\n"
rm -rf $DIR_TMP


#! /bin/bash
set -euo pipefail

cd "$(git rev-parse --show-toplevel)"

STD_PATH=src/crypto/ed25519/internal/edwards25519/field
LOCAL_PATH=curve25519/internal/field
LAST_SYNC_REF=$(cat $LOCAL_PATH/sync.checkpoint)

git fetch https://go.googlesource.com/go master

if git diff --quiet $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH; then
    echo "No changes."
else
    NEW_REF=$(git rev-parse FETCH_HEAD | tee $LOCAL_PATH/sync.checkpoint)
    echo "Applying changes from $LAST_SYNC_REF to $NEW_REF..."
    git diff $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH | \
        git apply -3 --directory=$LOCAL_PATH
fi


#!/usr/bin/env bash
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

# The plan9 package provides access to the raw system call
# interface of the underlying operating system.  Porting Go to
# a new architecture/operating system combination requires
# some manual effort, though there are tools that automate
# much of the process.  The auto-generated files have names
# beginning with z.
#
# This script runs or (given -n) prints suggested commands to generate z files
# for the current system.  Running those commands is not automatic.
# This script is documentation more than anything else.
#
# * asm_${GOOS}_${GOARCH}.s
#
# This hand-written assembly file implements system call dispatch.
# There are three entry points:
#
# 	func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
# 	func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
# 	func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
#
# The first and second are the standard ones; they differ only in
# how many arguments can be passed to the kernel.
# The third is for low-level use by the ForkExec wrapper;
# unlike the first two, it does not call into the scheduler to
# let it know that a system call is running.
#
# * syscall_${GOOS}.go
#
# This hand-written Go file implements system calls that need
# special handling and lists "//sys" comments giving prototypes
# for ones that can be auto-generated.  Mksyscall reads those
# comments to generate the stubs.
#
# * syscall_${GOOS}_${GOARCH}.go
#
# Same as syscall_${GOOS}.go except that it contains code specific
# to ${GOOS} on one particular architecture.
#
# * types_${GOOS}.c
#
# This hand-written C file includes standard C headers and then
# creates typedef or enum names beginning with a dollar sign
# (use of $ in variable names is a gcc extension).  The hardest
# part about preparing this file is figuring out which headers to
# include and which symbols need to be #defined to get the
# actual data structures that pass through to the kernel system calls.
# Some C libraries present alternate versions for binary compatibility
# and translate them on the way in and out of system calls, but
# there is almost always a #define that can get the real ones.
# See types_darwin.c and types_linux.c for examples.
#
# * zerror_${GOOS}_${GOARCH}.go
#
# This machine-generated file defines the system's error numbers,
# error strings, and signal numbers.  The generator is "mkerrors.sh".
# Usually no arguments are needed, but mkerrors.sh will pass its
# arguments on to godefs.
#
# * zsyscall_${GOOS}_${GOARCH}.go
#
# Generated by mksyscall.pl; see syscall_${GOOS}.go above.
#
# * zsysnum_${GOOS}_${GOARCH}.go
#
# Generated by mksysnum_${GOOS}.
#
# * ztypes_${GOOS}_${GOARCH}.go
#
# Generated by godefs; see types_${GOOS}.c above.

GOOSARCH="${GOOS}_${GOARCH}"

# defaults
mksyscall="go run mksyscall.go"
mkerrors="./mkerrors.sh"
zerrors="zerrors_$GOOSARCH.go"
mksysctl=""
zsysctl="zsysctl_$GOOSARCH.go"
mksysnum=
mktypes=
run="sh"

case "$1" in
-syscalls)
	for i in zsyscall*go
	do
		sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
		rm _$i
	done
	exit 0
	;;
-n)
	run="cat"
	shift
esac

case "$#" in
0)
	;;
*)
	echo 'usage: mkall.sh [-n]' 1>&2
	exit 2
esac

case "$GOOSARCH" in
_* | *_ | _)
	echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
	exit 1
	;;
plan9_386)
	mkerrors=
	mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,386"
	mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
	mktypes="XXX"
	;;
plan9_amd64)
	mkerrors=
	mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,amd64"
	mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
	mktypes="XXX"
	;;
plan9_arm)
	mkerrors=
	mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,arm"
	mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
	mktypes="XXX"
	;;
*)
	echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
	exit 1
	;;
esac

(
	if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
	case "$GOOS" in
	plan9)
		syscall_goos="syscall_$GOOS.go"
		if [ -n "$mksyscall" ]; then echo "$mksyscall $syscall_goos |gofmt >zsyscall_$GOOSARCH.go"; fi
		;;
	esac
	if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
	if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
	if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go |gofmt >ztypes_$GOOSARCH.go"; fi
) | $run


#!/usr/bin/env bash
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

# Generate Go code listing errors and other #defined constant
# values (ENAMETOOLONG etc.), by asking the preprocessor
# about the definitions.

unset LANG
export LC_ALL=C
export LC_CTYPE=C

CC=${CC:-gcc}

uname=$(uname)

includes='
#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <sys/signal.h>
#include <signal.h>
#include <sys/resource.h>
'

ccflags="$@"

# Write go tool cgo -godefs input.
(
	echo package plan9
	echo
	echo '/*'
	indirect="includes_$(uname)"
	echo "${!indirect} $includes"
	echo '*/'
	echo 'import "C"'
	echo
	echo 'const ('

	# The gcc command line prints all the #defines
	# it encounters while processing the input
	echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags |
	awk '
		$1 != "#define" || $2 ~ /\(/ || $3 == "" {next}

		$2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next}  # 386 registers
		$2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
		$2 ~ /^(SCM_SRCRT)$/ {next}
		$2 ~ /^(MAP_FAILED)$/ {next}

		$2 !~ /^ETH_/ &&
		$2 !~ /^EPROC_/ &&
		$2 !~ /^EQUIV_/ &&
		$2 !~ /^EXPR_/ &&
		$2 ~ /^E[A-Z0-9_]+$/ ||
		$2 ~ /^B[0-9_]+$/ ||
		$2 ~ /^V[A-Z0-9]+$/ ||
		$2 ~ /^CS[A-Z0-9]/ ||
		$2 ~ /^I(SIG|CANON|CRNL|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
		$2 ~ /^IGN/ ||
		$2 ~ /^IX(ON|ANY|OFF)$/ ||
		$2 ~ /^IN(LCR|PCK)$/ ||
		$2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
		$2 ~ /^C(LOCAL|READ)$/ ||
		$2 == "BRKINT" ||
		$2 == "HUPCL" ||
		$2 == "PENDIN" ||
		$2 == "TOSTOP" ||
		$2 ~ /^PAR/ ||
		$2 ~ /^SIG[^_]/ ||
		$2 ~ /^O[CNPFP][A-Z]+[^_][A-Z]+$/ ||
		$2 ~ /^IN_/ ||
		$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
		$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
		$2 == "ICMPV6_FILTER" ||
		$2 == "SOMAXCONN" ||
		$2 == "NAME_MAX" ||
		$2 == "IFNAMSIZ" ||
		$2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ ||
		$2 ~ /^SYSCTL_VERS/ ||
		$2 ~ /^(MS|MNT)_/ ||
		$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
		$2 ~ /^(O|F|FD|NAME|S|PTRACE|PT)_/ ||
		$2 ~ /^LINUX_REBOOT_CMD_/ ||
		$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
		$2 !~ "NLA_TYPE_MASK" &&
		$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
		$2 ~ /^SIOC/ ||
		$2 ~ /^TIOC/ ||
		$2 !~ "RTF_BITS" &&
		$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
		$2 ~ /^BIOC/ ||
		$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
		$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|NOFILE|STACK)|RLIM_INFINITY/ ||
		$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
		$2 ~ /^CLONE_[A-Z_]+/ ||
		$2 !~ /^(BPF_TIMEVAL)$/ &&
		$2 ~ /^(BPF|DLT)_/ ||
		$2 !~ "WMESGLEN" &&
		$2 ~ /^W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", $2, $2)}
		$2 ~ /^__WCOREFLAG$/ {next}
		$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}

		{next}
	' | sort

	echo ')'
) >_const.go

# Pull out the error names for later.
errors=$(
	echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
	awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' |
	sort
)

# Pull out the signal names for later.
signals=$(
	echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
	awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
	grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT' |
	sort
)

# Again, writing regexps to a file.
echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
	awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
	sort >_error.grep
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
	awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
	grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT' |
	sort >_signal.grep

echo '// mkerrors.sh' "$@"
echo '// Code generated by the command above; DO NOT EDIT.'
echo
go tool cgo -godefs -- "$@" _const.go >_error.out
cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
echo
echo '// Errors'
echo 'const ('
cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= Errno(\1)/'
echo ')'

echo
echo '// Signals'
echo 'const ('
cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= Signal(\1)/'
echo ')'

# Run C program to print error and syscall strings.
(
	echo -E "
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>

#define nelem(x) (sizeof(x)/sizeof((x)[0]))

enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below

int errors[] = {
"
	for i in $errors
	do
		echo -E '	'$i,
	done

	echo -E "
};

int signals[] = {
"
	for i in $signals
	do
		echo -E '	'$i,
	done

	# Use -E because on some systems bash builtin interprets \n itself.
	echo -E '
};

static int
intcmp(const void *a, const void *b)
{
	return *(int*)a - *(int*)b;
}

int
main(void)
{
	int i, j, e;
	char buf[1024], *p;

	printf("\n\n// Error table\n");
	printf("var errors = [...]string {\n");
	qsort(errors, nelem(errors), sizeof errors[0], intcmp);
	for(i=0; i<nelem(errors); i++) {
		e = errors[i];
		if(i > 0 && errors[i-1] == e)
			continue;
		strcpy(buf, strerror(e));
		// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
		if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
			buf[0] += a - A;
		printf("\t%d: \"%s\",\n", e, buf);
	}
	printf("}\n\n");

	printf("\n\n// Signal table\n");
	printf("var signals = [...]string {\n");
	qsort(signals, nelem(signals), sizeof signals[0], intcmp);
	for(i=0; i<nelem(signals); i++) {
		e = signals[i];
		if(i > 0 && signals[i-1] == e)
			continue;
		strcpy(buf, strsignal(e));
		// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
		if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
			buf[0] += a - A;
		// cut trailing : number.
		p = strrchr(buf, ":"[0]);
		if(p)
			*p = '\0';
		printf("\t%d: \"%s\",\n", e, buf);
	}
	printf("}\n\n");

	return 0;
}

'
) >_errors.c

$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out


#!/bin/sh
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

COMMAND="mksysnum_plan9.sh $@"

cat <<EOF
// $COMMAND
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT

package plan9

const(
EOF

SP='[ 	]' # space or tab
sed "s/^#define${SP}\\([A-Z0-9_][A-Z0-9_]*\\)${SP}${SP}*\\([0-9][0-9]*\\)/SYS_\\1=\\2/g" \
	< $1 | grep -v SYS__

cat <<EOF
)
EOF


#!/usr/bin/env bash
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

# This script runs or (given -n) prints suggested commands to generate files for
# the Architecture/OS specified by the GOARCH and GOOS environment variables.
# See README.md for more information about how the build system works.

GOOSARCH="${GOOS}_${GOARCH}"

# defaults
mksyscall="go run mksyscall.go"
mkerrors="./mkerrors.sh"
zerrors="zerrors_$GOOSARCH.go"
mksysctl=""
zsysctl="zsysctl_$GOOSARCH.go"
mksysnum=
mktypes=
mkasm=
run="sh"
cmd=""

case "$1" in
-syscalls)
	for i in zsyscall*go
	do
		# Run the command line that appears in the first line
		# of the generated file to regenerate it.
		sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
		rm _$i
	done
	exit 0
	;;
-n)
	run="cat"
	cmd="echo"
	shift
esac

case "$#" in
0)
	;;
*)
	echo 'usage: mkall.sh [-n]' 1>&2
	exit 2
esac

if [[ "$GOOS" = "linux" ]]; then
	# Use the Docker-based build system
	# Files generated through docker (use $cmd so you can Ctl-C the build or run)
	$cmd docker build --tag generate:$GOOS $GOOS
	$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && /bin/pwd):/build generate:$GOOS
	exit
fi

GOOSARCH_in=syscall_$GOOSARCH.go
case "$GOOSARCH" in
_* | *_ | _)
	echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
	exit 1
	;;
aix_ppc)
	mkerrors="$mkerrors -maix32"
	mksyscall="go run mksyscall_aix_ppc.go -aix"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	;;
aix_ppc64)
	mkerrors="$mkerrors -maix64"
	mksyscall="go run mksyscall_aix_ppc64.go -aix"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	;;
darwin_amd64)
	mkerrors="$mkerrors -m64"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	mkasm="go run mkasm.go"
	;;
darwin_arm64)
	mkerrors="$mkerrors -m64"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	mkasm="go run mkasm.go"
	;;
dragonfly_amd64)
	mkerrors="$mkerrors -m64"
	mksyscall="go run mksyscall.go -dragonfly"
	mksysnum="go run mksysnum.go 'https://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master'"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	;;
freebsd_386)
	mkerrors="$mkerrors -m32"
	mksyscall="go run mksyscall.go -l32"
	mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	;;
freebsd_amd64)
	mkerrors="$mkerrors -m64"
	mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	;;
freebsd_arm)
	mkerrors="$mkerrors"
	mksyscall="go run mksyscall.go -l32 -arm"
	mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
	# Let the type of C char be signed for making the bare syscall
	# API consistent across platforms.
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
	;;
freebsd_arm64)
	mkerrors="$mkerrors -m64"
	mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
	;;
freebsd_riscv64)
	mkerrors="$mkerrors -m64"
	mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
	;;
netbsd_386)
	mkerrors="$mkerrors -m32"
	mksyscall="go run mksyscall.go -l32 -netbsd"
	mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	;;
netbsd_amd64)
	mkerrors="$mkerrors -m64"
	mksyscall="go run mksyscall.go -netbsd"
	mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	;;
netbsd_arm)
	mkerrors="$mkerrors"
	mksyscall="go run mksyscall.go -l32 -netbsd -arm"
	mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
	# Let the type of C char be signed for making the bare syscall
	# API consistent across platforms.
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
	;;
netbsd_arm64)
	mkerrors="$mkerrors -m64"
	mksyscall="go run mksyscall.go -netbsd"
	mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	;;
openbsd_386)
	mkasm="go run mkasm.go"
	mkerrors="$mkerrors -m32"
	mksyscall="go run mksyscall.go -l32 -openbsd -libc"
	mksysctl="go run mksysctl_openbsd.go"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	;;
openbsd_amd64)
	mkasm="go run mkasm.go"
	mkerrors="$mkerrors -m64"
	mksyscall="go run mksyscall.go -openbsd -libc"
	mksysctl="go run mksysctl_openbsd.go"
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	;;
openbsd_arm)
	mkasm="go run mkasm.go"
	mkerrors="$mkerrors"
	mksyscall="go run mksyscall.go -l32 -openbsd -arm -libc"
	mksysctl="go run mksysctl_openbsd.go"
	# Let the type of C char be signed for making the bare syscall
	# API consistent across platforms.
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
	;;
openbsd_arm64)
	mkasm="go run mkasm.go"
	mkerrors="$mkerrors -m64"
	mksyscall="go run mksyscall.go -openbsd -libc"
	mksysctl="go run mksysctl_openbsd.go"
	# Let the type of C char be signed for making the bare syscall
	# API consistent across platforms.
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
	;;
openbsd_mips64)
	mkasm="go run mkasm.go"
	mkerrors="$mkerrors -m64"
	mksyscall="go run mksyscall.go -openbsd -libc"
	mksysctl="go run mksysctl_openbsd.go"
	# Let the type of C char be signed for making the bare syscall
	# API consistent across platforms.
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
	;;
openbsd_ppc64)
	mkasm="go run mkasm.go"
	mkerrors="$mkerrors -m64"
	mksyscall="go run mksyscall.go -openbsd -libc"
	mksysctl="go run mksysctl_openbsd.go"
	# Let the type of C char be signed for making the bare syscall
	# API consistent across platforms.
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
	;;
openbsd_riscv64)
	mkasm="go run mkasm.go"
	mkerrors="$mkerrors -m64"
	mksyscall="go run mksyscall.go -openbsd -libc"
	mksysctl="go run mksysctl_openbsd.go"
	# Let the type of C char be signed for making the bare syscall
	# API consistent across platforms.
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
	;;
solaris_amd64)
	mksyscall="go run mksyscall_solaris.go"
	mkerrors="$mkerrors -m64"
	mksysnum=
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	;;
illumos_amd64)
        mksyscall="go run mksyscall_solaris.go"
	mkerrors=
	mksysnum=
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
	;;
*)
	echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
	exit 1
	;;
esac

(
	if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
	case "$GOOS" in
	*)
		syscall_goos="syscall_$GOOS.go"
		case "$GOOS" in
		darwin | dragonfly | freebsd | netbsd | openbsd)
			syscall_goos="syscall_bsd.go $syscall_goos"
			;;
		esac
		if [ -n "$mksyscall" ]; then
			if [ "$GOOSARCH" == "aix_ppc64" ]; then
				# aix/ppc64 script generates files instead of writing to stdin.
				echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ;
			elif [ "$GOOS" == "illumos" ]; then
			        # illumos code generation requires a --illumos switch
			        echo "$mksyscall -illumos -tags illumos,$GOARCH syscall_illumos.go |gofmt > zsyscall_illumos_$GOARCH.go";
			        # illumos implies solaris, so solaris code generation is also required
				echo "$mksyscall -tags solaris,$GOARCH syscall_solaris.go syscall_solaris_$GOARCH.go |gofmt >zsyscall_solaris_$GOARCH.go";
			else
				echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
			fi
		fi
	esac
	if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
	if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
	if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go"; fi
	if [ -n "$mkasm" ]; then echo "$mkasm $GOOS $GOARCH"; fi
) | $run


#!/usr/bin/env bash
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

# Generate Go code listing errors and other #defined constant
# values (ENAMETOOLONG etc.), by asking the preprocessor
# about the definitions.

unset LANG
export LC_ALL=C
export LC_CTYPE=C

if test -z "$GOARCH" -o -z "$GOOS"; then
	echo 1>&2 "GOARCH or GOOS not defined in environment"
	exit 1
fi

# Check that we are using the new build system if we should
if [[ "$GOOS" = "linux" ]] && [[ "$GOLANG_SYS_BUILD" != "docker" ]]; then
	echo 1>&2 "In the Docker based build system, mkerrors should not be called directly."
	echo 1>&2 "See README.md"
	exit 1
fi

if [[ "$GOOS" = "aix" ]]; then
	CC=${CC:-gcc}
else
	CC=${CC:-cc}
fi

if [[ "$GOOS" = "solaris" ]]; then
	# Assumes GNU versions of utilities in PATH.
	export PATH=/usr/gnu/bin:$PATH
fi

uname=$(uname)

includes_AIX='
#include <net/if.h>
#include <net/netopt.h>
#include <netinet/ip_mroute.h>
#include <sys/protosw.h>
#include <sys/stropts.h>
#include <sys/mman.h>
#include <sys/poll.h>
#include <sys/select.h>
#include <sys/termio.h>
#include <termios.h>
#include <fcntl.h>

#define AF_LOCAL AF_UNIX
'

includes_Darwin='
#define _DARWIN_C_SOURCE
#define KERNEL 1
#define _DARWIN_USE_64_BIT_INODE
#define __APPLE_USE_RFC_3542
#include <stdint.h>
#include <sys/attr.h>
#include <sys/clonefile.h>
#include <sys/kern_control.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/ptrace.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <sys/sockio.h>
#include <sys/sys_domain.h>
#include <sys/sysctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <sys/xattr.h>
#include <sys/vsock.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <termios.h>

// for backwards compatibility because moved TIOCREMOTE to Kernel.framework after MacOSX12.0.sdk.
#define TIOCREMOTE 0x80047469
'

includes_DragonFly='
#include <sys/types.h>
#include <sys/event.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_clone.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <termios.h>
#include <netinet/ip.h>
#include <net/ip_mroute/ip_mroute.h>
'

includes_FreeBSD='
#include <sys/capsicum.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/disk.h>
#include <sys/event.h>
#include <sys/sched.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/sockio.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/ptrace.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <termios.h>
#include <netinet/ip.h>
#include <netinet/ip_mroute.h>
#include <sys/extattr.h>

#if __FreeBSD__ >= 10
#define IFT_CARP	0xf8	// IFT_CARP is deprecated in FreeBSD 10
#undef SIOCAIFADDR
#define SIOCAIFADDR	_IOW(105, 26, struct oifaliasreq)	// ifaliasreq contains if_data
#undef SIOCSIFPHYADDR
#define SIOCSIFPHYADDR	_IOW(105, 70, struct oifaliasreq)	// ifaliasreq contains if_data
#endif
'

includes_Linux='
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#ifndef __LP64__
#define _FILE_OFFSET_BITS 64
#endif
#define _GNU_SOURCE

// <sys/ioctl.h> is broken on powerpc64, as it fails to include definitions of
// these structures. We just include them copied from <bits/termios.h>.
#if defined(__powerpc__)
struct sgttyb {
        char    sg_ispeed;
        char    sg_ospeed;
        char    sg_erase;
        char    sg_kill;
        short   sg_flags;
};

struct tchars {
        char    t_intrc;
        char    t_quitc;
        char    t_startc;
        char    t_stopc;
        char    t_eofc;
        char    t_brkc;
};

struct ltchars {
        char    t_suspc;
        char    t_dsuspc;
        char    t_rprntc;
        char    t_flushc;
        char    t_werasc;
        char    t_lnextc;
};
#endif

#include <bits/sockaddr.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/signalfd.h>
#include <sys/socket.h>
#include <sys/timerfd.h>
#include <sys/uio.h>
#include <sys/xattr.h>
#include <netinet/udp.h>
#include <linux/audit.h>
#include <linux/bpf.h>
#include <linux/can.h>
#include <linux/can/error.h>
#include <linux/can/netlink.h>
#include <linux/can/raw.h>
#include <linux/capability.h>
#include <linux/cryptouser.h>
#include <linux/devlink.h>
#include <linux/dm-ioctl.h>
#include <linux/errqueue.h>
#include <linux/ethtool_netlink.h>
#include <linux/falloc.h>
#include <linux/fanotify.h>
#include <linux/fib_rules.h>
#include <linux/filter.h>
#include <linux/fs.h>
#include <linux/fscrypt.h>
#include <linux/fsverity.h>
#include <linux/genetlink.h>
#include <linux/hdreg.h>
#include <linux/hidraw.h>
#include <linux/if.h>
#include <linux/if_addr.h>
#include <linux/if_alg.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_ppp.h>
#include <linux/if_tun.h>
#include <linux/if_packet.h>
#include <linux/if_xdp.h>
#include <linux/input.h>
#include <linux/kcm.h>
#include <linux/kexec.h>
#include <linux/keyctl.h>
#include <linux/landlock.h>
#include <linux/loop.h>
#include <linux/lwtunnel.h>
#include <linux/magic.h>
#include <linux/memfd.h>
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netlink.h>
#include <linux/net_namespace.h>
#include <linux/nfc.h>
#include <linux/nsfs.h>
#include <linux/perf_event.h>
#include <linux/pps.h>
#include <linux/ptrace.h>
#include <linux/random.h>
#include <linux/reboot.h>
#include <linux/rtc.h>
#include <linux/rtnetlink.h>
#include <linux/sched.h>
#include <linux/seccomp.h>
#include <linux/serial.h>
#include <linux/sockios.h>
#include <linux/taskstats.h>
#include <linux/tipc.h>
#include <linux/vm_sockets.h>
#include <linux/wait.h>
#include <linux/watchdog.h>
#include <linux/wireguard.h>

#include <mtd/ubi-user.h>
#include <mtd/mtd-user.h>
#include <net/route.h>

#if defined(__sparc__)
// On sparc{,64}, the kernel defines struct termios2 itself which clashes with the
// definition in glibc. As only the error constants are needed here, include the
// generic termibits.h (which is included by termbits.h on sparc).
#include <asm-generic/termbits.h>
#else
#include <asm/termbits.h>
#endif

#ifndef MSG_FASTOPEN
#define MSG_FASTOPEN    0x20000000
#endif

#ifndef PTRACE_GETREGS
#define PTRACE_GETREGS	0xc
#endif

#ifndef PTRACE_SETREGS
#define PTRACE_SETREGS	0xd
#endif

#ifndef SOL_NETLINK
#define SOL_NETLINK	270
#endif

#ifndef SOL_SMC
#define SOL_SMC 286
#endif

#ifdef SOL_BLUETOOTH
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
// but it is already in bluetooth_linux.go
#undef SOL_BLUETOOTH
#endif

// Certain constants are missing from the fs/crypto UAPI
#define FS_KEY_DESC_PREFIX              "fscrypt:"
#define FS_KEY_DESC_PREFIX_SIZE         8
#define FS_MAX_KEY_SIZE                 64

// The code generator produces -0x1 for (~0), but an unsigned value is necessary
// for the tipc_subscr timeout __u32 field.
#undef TIPC_WAIT_FOREVER
#define TIPC_WAIT_FOREVER 0xffffffff

// Copied from linux/l2tp.h
// Including linux/l2tp.h here causes conflicts between linux/in.h
// and netinet/in.h included via net/route.h above.
#define IPPROTO_L2TP		115

// Copied from linux/hid.h.
// Keep in sync with the size of the referenced fields.
#define _HIDIOCGRAWNAME_LEN	128 // sizeof_field(struct hid_device, name)
#define _HIDIOCGRAWPHYS_LEN	64  // sizeof_field(struct hid_device, phys)
#define _HIDIOCGRAWUNIQ_LEN	64  // sizeof_field(struct hid_device, uniq)

#define _HIDIOCGRAWNAME		HIDIOCGRAWNAME(_HIDIOCGRAWNAME_LEN)
#define _HIDIOCGRAWPHYS		HIDIOCGRAWPHYS(_HIDIOCGRAWPHYS_LEN)
#define _HIDIOCGRAWUNIQ		HIDIOCGRAWUNIQ(_HIDIOCGRAWUNIQ_LEN)

'

includes_NetBSD='
#include <sys/types.h>
#include <sys/param.h>
#include <sys/event.h>
#include <sys/extattr.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/sched.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/termios.h>
#include <sys/ttycom.h>
#include <sys/wait.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_mroute.h>
#include <netinet/if_ether.h>

// Needed since <sys/param.h> refers to it...
#define schedppq 1
'

includes_OpenBSD='
#include <sys/types.h>
#include <sys/param.h>
#include <sys/event.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/select.h>
#include <sys/sched.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/termios.h>
#include <sys/ttycom.h>
#include <sys/unistd.h>
#include <sys/wait.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/if_var.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_mroute.h>
#include <netinet/if_ether.h>
#include <net/if_bridge.h>

// We keep some constants not supported in OpenBSD 5.5 and beyond for
// the promise of compatibility.
#define EMUL_ENABLED		0x1
#define EMUL_NATIVE		0x2
#define IPV6_FAITH		0x1d
#define IPV6_OPTIONS		0x1
#define IPV6_RTHDR_STRICT	0x1
#define IPV6_SOCKOPT_RESERVED1	0x3
#define SIOCGIFGENERIC		0xc020693a
#define SIOCSIFGENERIC		0x80206939
#define WALTSIG			0x4
'

includes_SunOS='
#include <limits.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/stat.h>
#include <sys/stream.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/mkdev.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/icmp6.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_mroute.h>
#include <termios.h>
'

includes='
#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <sys/signal.h>
#include <signal.h>
#include <sys/resource.h>
#include <time.h>
'
ccflags="$@"

# Write go tool cgo -godefs input.
(
	echo package unix
	echo
	echo '/*'
	indirect="includes_$(uname)"
	echo "${!indirect} $includes"
	echo '*/'
	echo 'import "C"'
	echo 'import "syscall"'
	echo
	echo 'const ('

	# The gcc command line prints all the #defines
	# it encounters while processing the input
	echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags |
	awk '
		$1 != "#define" || $2 ~ /\(/ || $3 == "" {next}

		$2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next}  # 386 registers
		$2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
		$2 ~ /^(SCM_SRCRT)$/ {next}
		$2 ~ /^(MAP_FAILED)$/ {next}
		$2 ~ /^ELF_.*$/ {next}# <asm/elf.h> contains ELF_ARCH, etc.

		$2 ~ /^EXTATTR_NAMESPACE_NAMES/ ||
		$2 ~ /^EXTATTR_NAMESPACE_[A-Z]+_STRING/ {next}

		$2 !~ /^ECCAPBITS/ &&
		$2 !~ /^ETH_/ &&
		$2 !~ /^EPROC_/ &&
		$2 !~ /^EQUIV_/ &&
		$2 !~ /^EXPR_/ &&
		$2 !~ /^EVIOC/ &&
		$2 ~ /^E[A-Z0-9_]+$/ ||
		$2 ~ /^B[0-9_]+$/ ||
		$2 ~ /^(OLD|NEW)DEV$/ ||
		$2 == "BOTHER" ||
		$2 ~ /^CI?BAUD(EX)?$/ ||
		$2 == "IBSHIFT" ||
		$2 ~ /^V[A-Z0-9]+$/ ||
		$2 ~ /^CS[A-Z0-9]/ ||
		$2 ~ /^I(SIG|CANON|CRNL|UCLC|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
		$2 ~ /^IGN/ ||
		$2 ~ /^IX(ON|ANY|OFF)$/ ||
		$2 ~ /^IN(LCR|PCK)$/ ||
		$2 !~ "X86_CR3_PCID_NOFLUSH" &&
		$2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
		$2 ~ /^C(LOCAL|READ|MSPAR|RTSCTS)$/ ||
		$2 == "BRKINT" ||
		$2 == "HUPCL" ||
		$2 == "PENDIN" ||
		$2 == "TOSTOP" ||
		$2 == "XCASE" ||
		$2 == "ALTWERASE" ||
		$2 == "NOKERNINFO" ||
		$2 == "NFDBITS" ||
		$2 ~ /^PAR/ ||
		$2 ~ /^SIG[^_]/ ||
		$2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ ||
		$2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ ||
		$2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ ||
		$2 ~ /^O?XTABS$/ ||
		$2 ~ /^TC[IO](ON|OFF)$/ ||
		$2 ~ /^IN_/ ||
		$2 ~ /^KCM/ ||
		$2 ~ /^LANDLOCK_/ ||
		$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
		$2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
		$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
		$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ ||
		$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
		$2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
		$2 ~ /^RAW_PAYLOAD_/ ||
		$2 ~ /^[US]F_/ ||
		$2 ~ /^TP_STATUS_/ ||
		$2 ~ /^FALLOC_/ ||
		$2 ~ /^ICMPV?6?_(FILTER|SEC)/ ||
		$2 == "SOMAXCONN" ||
		$2 == "NAME_MAX" ||
		$2 == "IFNAMSIZ" ||
		$2 ~ /^CTL_(HW|KERN|MAXNAME|NET|QUERY)$/ ||
		$2 ~ /^KERN_(HOSTNAME|OS(RELEASE|TYPE)|VERSION)$/ ||
		$2 ~ /^HW_MACHINE$/ ||
		$2 ~ /^SYSCTL_VERS/ ||
		$2 !~ "MNT_BITS" &&
		$2 ~ /^(MS|MNT|MOUNT|UMOUNT)_/ ||
		$2 ~ /^NS_GET_/ ||
		$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
		$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|PIOD|TFD)_/ ||
		$2 ~ /^KEXEC_/ ||
		$2 ~ /^LINUX_REBOOT_CMD_/ ||
		$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
		$2 ~ /^MODULE_INIT_/ ||
		$2 !~ "NLA_TYPE_MASK" &&
		$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
		$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
		$2 ~ /^FIORDCHK$/ ||
		$2 ~ /^SIOC/ ||
		$2 ~ /^TIOC/ ||
		$2 ~ /^TCGET/ ||
		$2 ~ /^TCSET/ ||
		$2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
		$2 !~ "RTF_BITS" &&
		$2 ~ /^(IFF|IFT|NET_RT|RTM(GRP)?|RTF|RTV|RTA|RTAX)_/ ||
		$2 ~ /^BIOC/ ||
		$2 ~ /^DIOC/ ||
		$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
		$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
		$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
		$2 ~ /^CLONE_[A-Z_]+/ ||
		$2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ &&
		$2 ~ /^(BPF|DLT)_/ ||
		$2 ~ /^AUDIT_/ ||
		$2 ~ /^(CLOCK|TIMER)_/ ||
		$2 ~ /^CAN_/ ||
		$2 ~ /^CAP_/ ||
		$2 ~ /^CP_/ ||
		$2 ~ /^CPUSTATES$/ ||
		$2 ~ /^CTLIOCGINFO$/ ||
		$2 ~ /^ALG_/ ||
		$2 ~ /^FI(CLONE|DEDUPERANGE)/ ||
		$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ ||
		$2 ~ /^FS_IOC_.*(ENCRYPTION|VERITY|[GS]ETFLAGS)/ ||
		$2 ~ /^FS_VERITY_/ ||
		$2 ~ /^FSCRYPT_/ ||
		$2 ~ /^DM_/ ||
		$2 ~ /^GRND_/ ||
		$2 ~ /^RND/ ||
		$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
		$2 ~ /^KEYCTL_/ ||
		$2 ~ /^PERF_/ ||
		$2 ~ /^SECCOMP_MODE_/ ||
		$2 ~ /^SEEK_/ ||
		$2 ~ /^SPLICE_/ ||
		$2 ~ /^SYNC_FILE_RANGE_/ ||
		$2 !~ /IOC_MAGIC/ &&
		$2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ ||
		$2 ~ /^(VM|VMADDR)_/ ||
		$2 ~ /^IOCTL_VM_SOCKETS_/ ||
		$2 ~ /^(TASKSTATS|TS)_/ ||
		$2 ~ /^CGROUPSTATS_/ ||
		$2 ~ /^GENL_/ ||
		$2 ~ /^STATX_/ ||
		$2 ~ /^RENAME/ ||
		$2 ~ /^UBI_IOC[A-Z]/ ||
		$2 ~ /^UTIME_/ ||
		$2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ ||
		$2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ ||
		$2 ~ /^FSOPT_/ ||
		$2 ~ /^WDIO[CFS]_/ ||
		$2 ~ /^NFN/ ||
		$2 ~ /^XDP_/ ||
		$2 ~ /^RWF_/ ||
		$2 ~ /^(HDIO|WIN|SMART)_/ ||
		$2 ~ /^CRYPTO_/ ||
		$2 ~ /^TIPC_/ ||
		$2 !~  "DEVLINK_RELOAD_LIMITS_VALID_MASK" &&
		$2 ~ /^DEVLINK_/ ||
		$2 ~ /^ETHTOOL_/ ||
		$2 ~ /^LWTUNNEL_IP/ ||
		$2 ~ /^ITIMER_/ ||
		$2 !~ "WMESGLEN" &&
		$2 ~ /^W[A-Z0-9]+$/ ||
		$2 ~ /^P_/ ||
		$2 ~/^PPPIOC/ ||
		$2 ~ /^FAN_|FANOTIFY_/ ||
		$2 == "HID_MAX_DESCRIPTOR_SIZE" ||
		$2 ~ /^_?HIDIOC/ ||
		$2 ~ /^BUS_(USB|HIL|BLUETOOTH|VIRTUAL)$/ ||
		$2 ~ /^MTD/ ||
		$2 ~ /^OTP/ ||
		$2 ~ /^MEM/ ||
		$2 ~ /^WG/ ||
		$2 ~ /^FIB_RULE_/ ||
		$2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)}
		$2 ~ /^__WCOREFLAG$/ {next}
		$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}

		{next}
	' | sort

	echo ')'
) >_const.go

# Pull out the error names for later.
errors=$(
	echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
	awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' |
	sort
)

# Pull out the signal names for later.
signals=$(
	echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
	awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
	grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' |
	sort
)

# Again, writing regexps to a file.
echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
	awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
	sort >_error.grep
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
	awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
	grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' |
	sort >_signal.grep

echo '// mkerrors.sh' "$@"
echo '// Code generated by the command above; see README.md. DO NOT EDIT.'
echo
echo "//go:build ${GOARCH} && ${GOOS}"
echo "// +build ${GOARCH},${GOOS}"
echo
go tool cgo -godefs -- "$@" _const.go >_error.out
cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
echo
echo '// Errors'
echo 'const ('
cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= syscall.Errno(\1)/'
echo ')'

echo
echo '// Signals'
echo 'const ('
cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= syscall.Signal(\1)/'
echo ')'

# Run C program to print error and syscall strings.
(
	echo -E "
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>

#define nelem(x) (sizeof(x)/sizeof((x)[0]))

enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below

struct tuple {
	int num;
	const char *name;
};

struct tuple errors[] = {
"
	for i in $errors
	do
		echo -E '	{'$i', "'$i'" },'
	done

	echo -E "
};

struct tuple signals[] = {
"
	for i in $signals
	do
		echo -E '	{'$i', "'$i'" },'
	done

	# Use -E because on some systems bash builtin interprets \n itself.
	echo -E '
};

static int
tuplecmp(const void *a, const void *b)
{
	return ((struct tuple *)a)->num - ((struct tuple *)b)->num;
}

int
main(void)
{
	int i, e;
	char buf[1024], *p;

	printf("\n\n// Error table\n");
	printf("var errorList = [...]struct {\n");
	printf("\tnum  syscall.Errno\n");
	printf("\tname string\n");
	printf("\tdesc string\n");
	printf("} {\n");
	qsort(errors, nelem(errors), sizeof errors[0], tuplecmp);
	for(i=0; i<nelem(errors); i++) {
		e = errors[i].num;
		if(i > 0 && errors[i-1].num == e)
			continue;
		strcpy(buf, strerror(e));
		// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
		if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
			buf[0] += a - A;
		printf("\t{ %d, \"%s\", \"%s\" },\n", e, errors[i].name, buf);
	}
	printf("}\n\n");

	printf("\n\n// Signal table\n");
	printf("var signalList = [...]struct {\n");
	printf("\tnum  syscall.Signal\n");
	printf("\tname string\n");
	printf("\tdesc string\n");
	printf("} {\n");
	qsort(signals, nelem(signals), sizeof signals[0], tuplecmp);
	for(i=0; i<nelem(signals); i++) {
		e = signals[i].num;
		if(i > 0 && signals[i-1].num == e)
			continue;
		strcpy(buf, strsignal(e));
		// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
		if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
			buf[0] += a - A;
		// cut trailing : number.
		p = strrchr(buf, ":"[0]);
		if(p)
			*p = '\0';
		printf("\t{ %d, \"%s\", \"%s\" },\n", e, signals[i].name, buf);
	}
	printf("}\n\n");

	return 0;
}

'
) >_errors.c

$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out


#!/bin/bash
set -e

if [[ $GO111MODULE == "on" ]]; then
  go get .
else
  go get -u -v $(go list -f '{{join .Imports "\n"}}{{"\n"}}{{join .TestImports "\n"}}' ./... | sort | uniq | grep -v appengine)
fi

if [[ $GOAPP == "true" ]]; then
  mkdir /tmp/sdk
  curl -o /tmp/sdk.zip "https://storage.googleapis.com/appengine-sdks/featured/go_appengine_sdk_linux_amd64-1.9.68.zip"
  unzip -q /tmp/sdk.zip -d /tmp/sdk
  # NOTE: Set the following env vars in the test script:
  # export PATH="$PATH:/tmp/sdk/go_appengine"
  # export APPENGINE_DEV_APPSERVER=/tmp/sdk/go_appengine/dev_appserver.py
fi


#!/bin/bash
set -e

go version
go test -v google.golang.org/appengine/...
go test -v -race google.golang.org/appengine/...
if [[ $GOAPP == "true" ]]; then
  export PATH="$PATH:/tmp/sdk/go_appengine"
  export APPENGINE_DEV_APPSERVER=/tmp/sdk/go_appengine/dev_appserver.py
  goapp version
  goapp test -v google.golang.org/appengine/...
fi


#!/bin/bash -e
#
# This script rebuilds the generated code for the protocol buffers.
# To run this you will need protoc and goprotobuf installed;
# see https://github.com/golang/protobuf for instructions.

PKG=google.golang.org/appengine

function die() {
	echo 1>&2 $*
	exit 1
}

# Sanity check that the right tools are accessible.
for tool in go protoc protoc-gen-go; do
	q=$(which $tool) || die "didn't find $tool"
	echo 1>&2 "$tool: $q"
done

echo -n 1>&2 "finding package dir... "
pkgdir=$(go list -f '{{.Dir}}' $PKG)
echo 1>&2 $pkgdir
base=$(echo $pkgdir | sed "s,/$PKG\$,,")
echo 1>&2 "base: $base"
cd $base

# Run protoc once per package.
for dir in $(find $PKG/internal -name '*.proto' | xargs dirname | sort | uniq); do
	echo 1>&2 "* $dir"
	protoc --go_out=. $dir/*.proto
done

for f in $(find $PKG/internal -name '*.pb.go'); do
  # Remove proto.RegisterEnum calls.
  # These cause duplicate registration panics when these packages
  # are used on classic App Engine. proto.RegisterEnum only affects
  # parsing the text format; we don't care about that.
  # https://code.google.com/p/googleappengine/issues/detail?id=11670#c17
  sed -i '/proto.RegisterEnum/d' $f
done


#!/usr/bin/env bash

# This script serves as an example to demonstrate how to generate the gRPC-Go
# interface and the related messages from .proto file.
#
# It assumes the installation of i) Google proto buffer compiler at
# https://github.com/google/protobuf (after v2.6.1) and ii) the Go codegen
# plugin at https://github.com/golang/protobuf (after 2015-02-20). If you have
# not, please install them first.
#
# We recommend running this script at $GOPATH/src.
#
# If this is not what you need, feel free to make your own scripts. Again, this
# script is for demonstration purpose.
#
proto=$1
protoc --go_out=plugins=grpc:. $proto


#!/bin/bash

TMP=$(mktemp -d /tmp/sdk.XXX) \
&& curl -o $TMP.zip "https://storage.googleapis.com/appengine-sdks/featured/go_appengine_sdk_linux_amd64-1.9.68.zip" \
&& unzip -q $TMP.zip -d $TMP \
&& export PATH="$PATH:$TMP/go_appengine"


#!/bin/bash
# Copyright 2020 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -eu -o pipefail

WORKDIR=$(mktemp -d)

function finish {
  rm -rf "$WORKDIR"
}
trap finish EXIT

export GOBIN=${WORKDIR}/bin
export PATH=${GOBIN}:${PATH}
mkdir -p ${GOBIN}

echo "remove existing generated files"
# grpc_testingv3/testv3.pb.go is not re-generated because it was
# intentionally generated by an older version of protoc-gen-go.
rm -f $(find . -name '*.pb.go' | grep -v 'grpc_testingv3/testv3.pb.go')

echo "go install google.golang.org/protobuf/cmd/protoc-gen-go"
(cd test/tools && go install google.golang.org/protobuf/cmd/protoc-gen-go)

echo "go install cmd/protoc-gen-go-grpc"
(cd cmd/protoc-gen-go-grpc && go install .)

echo "git clone https://github.com/grpc/grpc-proto"
git clone --quiet https://github.com/grpc/grpc-proto ${WORKDIR}/grpc-proto

echo "git clone https://github.com/protocolbuffers/protobuf"
git clone --quiet https://github.com/protocolbuffers/protobuf ${WORKDIR}/protobuf

# Pull in code.proto as a proto dependency
mkdir -p ${WORKDIR}/googleapis/google/rpc
echo "curl https://raw.githubusercontent.com/googleapis/googleapis/master/google/rpc/code.proto"
curl --silent https://raw.githubusercontent.com/googleapis/googleapis/master/google/rpc/code.proto > ${WORKDIR}/googleapis/google/rpc/code.proto

mkdir -p ${WORKDIR}/out

# Generates sources without the embed requirement
LEGACY_SOURCES=(
  ${WORKDIR}/grpc-proto/grpc/binlog/v1/binarylog.proto
  ${WORKDIR}/grpc-proto/grpc/channelz/v1/channelz.proto
  ${WORKDIR}/grpc-proto/grpc/health/v1/health.proto
  ${WORKDIR}/grpc-proto/grpc/lb/v1/load_balancer.proto
  profiling/proto/service.proto
  reflection/grpc_reflection_v1alpha/reflection.proto
)

# Generates only the new gRPC Service symbols
SOURCES=(
  $(git ls-files --exclude-standard --cached --others "*.proto" | grep -v '^\(profiling/proto/service.proto\|reflection/grpc_reflection_v1alpha/reflection.proto\)$')
  ${WORKDIR}/grpc-proto/grpc/gcp/altscontext.proto
  ${WORKDIR}/grpc-proto/grpc/gcp/handshaker.proto
  ${WORKDIR}/grpc-proto/grpc/gcp/transport_security_common.proto
  ${WORKDIR}/grpc-proto/grpc/lookup/v1/rls.proto
  ${WORKDIR}/grpc-proto/grpc/lookup/v1/rls_config.proto
  ${WORKDIR}/grpc-proto/grpc/service_config/service_config.proto
  ${WORKDIR}/grpc-proto/grpc/testing/*.proto
  ${WORKDIR}/grpc-proto/grpc/core/*.proto
)

# These options of the form 'Mfoo.proto=bar' instruct the codegen to use an
# import path of 'bar' in the generated code when 'foo.proto' is imported in
# one of the sources.
OPTS=Mgrpc/service_config/service_config.proto=/internal/proto/grpc_service_config,Mgrpc/core/stats.proto=google.golang.org/grpc/interop/grpc_testing/core

for src in ${SOURCES[@]}; do
  echo "protoc ${src}"
  protoc --go_out=${OPTS}:${WORKDIR}/out --go-grpc_out=${OPTS}:${WORKDIR}/out \
    -I"." \
    -I${WORKDIR}/grpc-proto \
    -I${WORKDIR}/googleapis \
    -I${WORKDIR}/protobuf/src \
    -I${WORKDIR}/istio \
    ${src}
done

for src in ${LEGACY_SOURCES[@]}; do
  echo "protoc ${src}"
  protoc --go_out=${OPTS}:${WORKDIR}/out --go-grpc_out=${OPTS},require_unimplemented_servers=false:${WORKDIR}/out \
    -I"." \
    -I${WORKDIR}/grpc-proto \
    -I${WORKDIR}/googleapis \
    -I${WORKDIR}/protobuf/src \
    -I${WORKDIR}/istio \
    ${src}
done

# The go_package option in grpc/lookup/v1/rls.proto doesn't match the
# current location. Move it into the right place.
mkdir -p ${WORKDIR}/out/google.golang.org/grpc/balancer/rls/internal/proto/grpc_lookup_v1
mv ${WORKDIR}/out/google.golang.org/grpc/lookup/grpc_lookup_v1/* ${WORKDIR}/out/google.golang.org/grpc/balancer/rls/internal/proto/grpc_lookup_v1

# grpc_testingv3/testv3.pb.go is not re-generated because it was
# intentionally generated by an older version of protoc-gen-go.
rm ${WORKDIR}/out/google.golang.org/grpc/reflection/grpc_testingv3/*.pb.go

# grpc/service_config/service_config.proto does not have a go_package option.
mv ${WORKDIR}/out/grpc/service_config/service_config.pb.go internal/proto/grpc_service_config

# grpc/testing does not have a go_package option.
mv ${WORKDIR}/out/grpc/testing/*.pb.go interop/grpc_testing/
mv ${WORKDIR}/out/grpc/core/*.pb.go interop/grpc_testing/core/

cp -R ${WORKDIR}/out/google.golang.org/grpc/* .


#!/bin/bash

set -ex  # Exit on error; debugging enabled.
set -o pipefail  # Fail a pipe if any sub-command fails.

# not makes sure the command passed to it does not exit with a return code of 0.
not() {
  # This is required instead of the earlier (! $COMMAND) because subshells and
  # pipefail don't work the same on Darwin as in Linux.
  ! "$@"
}

die() {
  echo "$@" >&2
  exit 1
}

fail_on_output() {
  tee /dev/stderr | not read
}

# Check to make sure it's safe to modify the user's git repo.
git status --porcelain | fail_on_output

# Undo any edits made by this script.
cleanup() {
  git reset --hard HEAD
}
trap cleanup EXIT

PATH="${HOME}/go/bin:${GOROOT}/bin:${PATH}"
go version

if [[ "$1" = "-install" ]]; then
  # Install the pinned versions as defined in module tools.
  pushd ./test/tools
  go install \
    golang.org/x/lint/golint \
    golang.org/x/tools/cmd/goimports \
    honnef.co/go/tools/cmd/staticcheck \
    github.com/client9/misspell/cmd/misspell
  popd
  if [[ -z "${VET_SKIP_PROTO}" ]]; then
    if [[ "${TRAVIS}" = "true" ]]; then
      PROTOBUF_VERSION=3.14.0
      PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
      pushd /home/travis
      wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME}
      unzip ${PROTOC_FILENAME}
      bin/protoc --version
      popd
    elif [[ "${GITHUB_ACTIONS}" = "true" ]]; then
      PROTOBUF_VERSION=3.14.0
      PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
      pushd /home/runner/go
      wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME}
      unzip ${PROTOC_FILENAME}
      bin/protoc --version
      popd
    elif not which protoc > /dev/null; then
      die "Please install protoc into your path"
    fi
  fi
  exit 0
elif [[ "$#" -ne 0 ]]; then
  die "Unknown argument(s): $*"
fi

# - Ensure all source files contain a copyright message.
not git grep -L "\(Copyright [0-9]\{4,\} gRPC authors\)\|DO NOT EDIT" -- '*.go'

# - Make sure all tests in grpc and grpc/test use leakcheck via Teardown.
not grep 'func Test[^(]' *_test.go
not grep 'func Test[^(]' test/*.go

# - Do not import x/net/context.
not git grep -l 'x/net/context' -- "*.go"

# - Do not import math/rand for real library code.  Use internal/grpcrand for
#   thread safety.
git grep -l '"math/rand"' -- "*.go" 2>&1 | not grep -v '^examples\|^stress\|grpcrand\|^benchmark\|wrr_test'

# - Do not call grpclog directly. Use grpclog.Component instead.
git grep -l 'grpclog.I\|grpclog.W\|grpclog.E\|grpclog.F\|grpclog.V' -- "*.go" | not grep -v '^grpclog/component.go\|^internal/grpctest/tlogger_test.go'

# - Ensure all ptypes proto packages are renamed when importing.
not git grep "\(import \|^\s*\)\"github.com/golang/protobuf/ptypes/" -- "*.go"

# - Ensure all xds proto imports are renamed to *pb or *grpc.
git grep '"github.com/envoyproxy/go-control-plane/envoy' -- '*.go' ':(exclude)*.pb.go' | not grep -v 'pb "\|grpc "'

# - Check imports that are illegal in appengine (until Go 1.11).
# TODO: Remove when we drop Go 1.10 support
go list -f {{.Dir}} ./... | xargs go run test/go_vet/vet.go

misspell -error .

# - Check that generated proto files are up to date.
if [[ -z "${VET_SKIP_PROTO}" ]]; then
  PATH="/home/travis/bin:${PATH}" make proto && \
    git status --porcelain 2>&1 | fail_on_output || \
    (git status; git --no-pager diff; exit 1)
fi

# - gofmt, goimports, golint (with exceptions for generated code), go vet,
# go mod tidy.
# Perform these checks on each module inside gRPC.
for MOD_FILE in $(find . -name 'go.mod'); do
  MOD_DIR=$(dirname ${MOD_FILE})
  pushd ${MOD_DIR}
  go vet -all ./... | fail_on_output
  gofmt -s -d -l . 2>&1 | fail_on_output
  goimports -l . 2>&1 | not grep -vE "\.pb\.go"
  golint ./... 2>&1 | not grep -vE "/testv3\.pb\.go:"

  go mod tidy
  git status --porcelain 2>&1 | fail_on_output || \
    (git status; git --no-pager diff; exit 1)
  popd
done

# - Collection of static analysis checks
#
# TODO(dfawley): don't use deprecated functions in examples or first-party
# plugins.
SC_OUT="$(mktemp)"
staticcheck -go 1.9 -checks 'inherit,-ST1015' ./... > "${SC_OUT}" || true
# Error if anything other than deprecation warnings are printed.
not grep -v "is deprecated:.*SA1019" "${SC_OUT}"
# Only ignore the following deprecated types/fields/functions.
not grep -Fv '.CredsBundle
.HeaderMap
.Metadata is deprecated: use Attributes
.NewAddress
.NewServiceConfig
.Type is deprecated: use Attributes
BuildVersion is deprecated
balancer.ErrTransientFailure
balancer.Picker
extDesc.Filename is deprecated
github.com/golang/protobuf/jsonpb is deprecated
grpc.CallCustomCodec
grpc.Code
grpc.Compressor
grpc.CustomCodec
grpc.Decompressor
grpc.MaxMsgSize
grpc.MethodConfig
grpc.NewGZIPCompressor
grpc.NewGZIPDecompressor
grpc.RPCCompressor
grpc.RPCDecompressor
grpc.ServiceConfig
grpc.WithBalancerName
grpc.WithCompressor
grpc.WithDecompressor
grpc.WithDialer
grpc.WithMaxMsgSize
grpc.WithServiceConfig
grpc.WithTimeout
http.CloseNotifier
info.SecurityVersion
proto is deprecated
proto.InternalMessageInfo is deprecated
proto.EnumName is deprecated
proto.ErrInternalBadWireType is deprecated
proto.FileDescriptor is deprecated
proto.Marshaler is deprecated
proto.MessageType is deprecated
proto.RegisterEnum is deprecated
proto.RegisterFile is deprecated
proto.RegisterType is deprecated
proto.RegisterExtension is deprecated
proto.RegisteredExtension is deprecated
proto.RegisteredExtensions is deprecated
proto.RegisterMapType is deprecated
proto.Unmarshaler is deprecated
resolver.Backend
resolver.GRPCLB
Target is deprecated: Use the Target field in the BuildOptions instead.
xxx_messageInfo_
' "${SC_OUT}"

# - special golint on package comments.
lint_package_comment_per_package() {
  # Number of files in this go package.
  fileCount=$(go list -f '{{len .GoFiles}}' $1)
  if [ ${fileCount} -eq 0 ]; then
    return 0
  fi
  # Number of package errors generated by golint.
  lintPackageCommentErrorsCount=$(golint --min_confidence 0 $1 | grep -c "should have a package comment")
  # golint complains about every file that's missing the package comment. If the
  # number of files for this package is greater than the number of errors, there's
  # at least one file with package comment, good. Otherwise, fail.
  if [ ${fileCount} -le ${lintPackageCommentErrorsCount} ]; then
    echo "Package $1 (with ${fileCount} files) is missing package comment"
    return 1
  fi
}
lint_package_comment() {
  set +ex

  count=0
  for i in $(go list ./...); do
    lint_package_comment_per_package "$i"
    ((count += $?))
  done

  set -ex
  return $count
}
lint_package_comment

echo SUCCESS


#!/bin/bash
if [ "$1" == "debug" ]; then
  echo "[INFO] Not generating ASA-x.x.x.jar as debug mode is enabled and user wants to troubleshoot the build process"
  exit 0
fi

echo "Cleaning existing build files..."
rm -rf cpp/build dotnet/bin dotnet/obj java/target || true
echo "Older build deleted"

echo "Downloading maven dependencies..."
cd java
mvn compile
cd ..

echo "Creating cpp build..."
mkdir -p cpp/build
cd cpp/build
cmake ..
cmake --build .
cd ../..
echo "cpp build created successfully"

echo """
====================================================================================================================================
Make sure azure credentials were provided successfully while building the docker image.
If not then stop this build.sh script and run
$ cd dotnet && dotnet restore --interactive
Open the URL on a browser and enter the code when prompted to authenticate

After the authentication, rerun the build.sh

For more information:
Azure Credential provider was installed while building the docker image to interactively acquire credentials for Azure Artifacts
https://github.com/microsoft/artifacts-credprovider
====================================================================================================================================
"""

echo "Creating dotnet build ..."
# This is where it hits case sensitive dir name errors. Wierd, but it works if triggerred second time
cd dotnet && (dotnet build || dotnet build) && cd ..

echo "Creating ASA-x.x.x.jar ..."
cd java
mvn package
# At this point jar should be created
ls -lh target/*.jar
echo "Jar created successfully"
cd ..

echo "Running sbt test..."
# Run test
cd scala && sbt test


#!/usr/bin/env bash
# DESCRIPTION: A simple shell script designed to fetch the latest version
# of the artifacts credential provider plugin for dotnet and
# install it into $HOME/.nuget/plugins.
# SEE: https://github.com/Microsoft/artifacts-credprovider/blob/master/README.md

REPO="Microsoft/artifacts-credprovider"
FILE="Microsoft.NuGet.CredentialProvider.tar.gz"
VERSION="latest"
# URL pattern documented at https://help.github.com/en/articles/linking-to-releases as of 2019-03-29
URI="https://github.com/$REPO/releases/$VERSION/download/$FILE"
NUGET_PLUGIN_DIR="$HOME/.nuget/plugins"

# Ensure plugin directory exists
if [ ! -d "${NUGET_PLUGIN_DIR}" ]; then
  echo "INFO: Creating the nuget plugin directory (i.e. ${NUGET_PLUGIN_DIR}). "
  if ! mkdir -p "${NUGET_PLUGIN_DIR}"; then
    echo "ERROR: Unable to create nuget plugins directory (i.e. ${NUGET_PLUGIN_DIR})."
    exit 1
  fi
fi

echo "Downloading from $URI"
# Extract netcore from the .tar.gz into the plugin directory

#Fetch the file
curl -H "Accept: application/octet-stream" \
     -s \
     -S \
     -L \
     "$URI" | tar xz -C "$HOME/.nuget/" "plugins/netcore"

echo "INFO: credential provider netcore plugin extracted to $HOME/.nuget/"


#!/usr/bin/env bash
set -euo pipefail
# This script creates / updates repos. The $_repos param should be *all* repos needed in the system, not just new ones needs.

# shellcheck source=src/runtime/bootstrap/lib/tools.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../../../runtime/bootstrap/lib/tools.sh"

_storage_account_name="$1"
_container_name="$2"
_container_rg="$3"
_subscription_id="$4"
_prefix="$5"
_applications="$6"

pushd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit 2

terraform_init "$_storage_account_name" "$_container_name" "$_container_rg"

terraform destroy \
    -auto-approve \
    -var "subscription_id=$_subscription_id" \
    -var "prefix=$_prefix" \
    -var "applications=$_applications"

rm -rf .terraform
popd || exit 2


#!/usr/bin/env bash
set -euo pipefail
# This script creates / updates repos. The $_repos param should be *all* repos needed in the system, not just new ones needs.

# shellcheck source=src/runtime/bootstrap/lib/tools.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../../../runtime/bootstrap/lib/tools.sh"

_storage_account_name="$1"
_container_name="$2"
_container_rg="$3"
_subscription_id="$4"
_prefix="$5"
_applications="$6"
_ini_file=${7:-}
_timestamp="$(date "+%Y:%m:%d-%H:%M")"

pushd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit 2

terraform_init "$_storage_account_name" "$_container_name" "$_container_rg"

terraform plan \
    -lock=true \
    -out "${_timestamp}.tfplan" \
    -var "subscription_id=$_subscription_id" \
    -var "prefix=$_prefix" \
    -var "applications=$_applications"

terraform apply "${_timestamp}.tfplan"

if [ -n "${_ini_file:-}" ];
then
    _break_glass="$(terraform output break_glass_id)"
    _read_only="$(terraform output read_only_id)"
    _sre="$(terraform output sre_id)"

    ini_val "$_ini_file" c12:generated.break-glass_group_id "$_break_glass"
    ini_val "$_ini_file" c12:generated.read-only_group_id "$_read_only"
    ini_val "$_ini_file" c12:generated.sre_group_id "$_sre"
fi

rm "${_timestamp}.tfplan"
popd || exit 2


#!/usr/bin/env bash
set -euxo pipefail

  function post_grant_request () {
    _resource_id=$(az ad sp show --id "$1" --query "objectId" -o json | jq "." -r)
    echo  "{\"principalId\": \"$3\", \"resourceId\": \"$_resource_id\", \"appRoleId\": \'$2\"}"
    az rest --method POST --uri https://graph.microsoft.com/beta/servicePrincipals/"$3"/appRoleAssignedTo \
            --header Content-Type=application/json \
            --body "{\"principalId\": \"$3\", \"resourceId\": \"$_resource_id\", \"appRoleId\": \"$2\"}"
  }

sleep 30
if [ -n "${GITHUB_ACTIONS+set}" ]; then
  # When on CI Pipeline Logged in Service Principal is currently unable to exec `az ad app permission admin-consent`
  # This calls the the Azure REST API and grants the listed Roles.
  echo "[INFO] sleep 30secs... "
  sleep 30
  _principal_id=${SP_ID}
  echo "[INFO] grant AAD roles"
  post_grant_request "00000002-0000-0000-c000-000000000000" "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175" "$_principal_id"
  post_grant_request "00000002-0000-0000-c000-000000000000" "1cda74f2-2616-4834-b122-5cb1b07f8a59" "$_principal_id"
  echo "[INFO] grant Microsoft Graph roles"
  post_grant_request "00000003-0000-0000-c000-000000000000" "06b708a9-e830-4db3-a914-8e69da51d44f" "$_principal_id"
  post_grant_request "00000003-0000-0000-c000-000000000000" "19dbc75e-c2e2-444c-a770-ec69d8559fc7" "$_principal_id"
else
  # When on Bootstrap (User account) use simpler Grant permission admin-consent
  az ad app permission admin-consent --id "${SP_APP_ID}"
fi


#!/usr/bin/env bash
set -euxo pipefail
# This script creates / updates repos. The $_repos param should be *all* repos needed in the system, not just new ones needs.

# shellcheck source=src/runtime/bootstrap/lib/tools.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../../../../runtime/bootstrap/lib/tools.sh"

_storage_account_name="$1"
_container_name="$2"
_container_rg="$3"
_access_token="$4"
_org="$5"
_prefix="$6"
_applications="$7"
_timestamp="$(date "+%Y:%m:%d-%H:%M")"

pushd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit 2

terraform_init "$_storage_account_name" "$_container_name" "$_container_rg"

terraform plan \
    -lock=true \
    -destroy \
    -out "${_timestamp}.tfplan" \
    -var "access_token=$_access_token" \
    -var "org=$_org" \
    -var "access_token=$_access_token" \
    -var "prefix=$_prefix" \
    -var "applications=$_applications"

terraform apply "${_timestamp}.tfplan"
rm "${_timestamp}.tfplan"
rm -rf .terraform
popd || exit 2


#!/usr/bin/env bash
set -euxo pipefail
# This script creates / updates repos. The $_repos param should be *all* repos needed in the system, not just new ones needs.

# shellcheck source=src/runtime/bootstrap/lib/tools.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../../../../runtime/bootstrap/lib/tools.sh"

_storage_account_name="$1"
_container_name="$2"
_container_rg="$3"
_access_token="$4"
_org="$5"
_prefix="$6"
_applications="$7"
_timestamp="$(date "+%Y:%m:%d-%H:%M")"

pushd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit 2

terraform_init "$_storage_account_name" "$_container_name" "$_container_rg"

terraform plan \
    -lock=true \
    -out "${_timestamp}.tfplan" \
    -var "access_token=$_access_token" \
    -var "org=$_org" \
    -var "access_token=$_access_token" \
    -var "prefix=$_prefix" \
    -var "applications=$_applications"

terraform apply "${_timestamp}.tfplan"
rm "${_timestamp}.tfplan"
popd || exit 2


#!/usr/bin/env bash
set -euxo pipefail
# This script creates / updates teams in github. The $_teams param should be *all* teams needed in the system, not just new ones needed.

# shellcheck source=src/runtime/bootstrap/lib/tools.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../../../../runtime/bootstrap/lib/tools.sh"

_storage_account_name="$1"
_container_name="$2"
_container_rg="$3"
_access_token="$4"
_subscription_id="$5"
_org="$6"
_prefix="$7"
_applications="$8"
_timestamp="$(date "+%Y:%m:%d-%H:%M")"

pushd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit 2

terraform_init "$_storage_account_name" "$_container_name" "$_container_rg"

terraform plan \
    -destroy \
    -out "${_timestamp}.tfplan" \
    -var "access_token=$_access_token" \
    -var "org=$_org" \
    -var "access_token=$_access_token" \
    -var "subscription_id=$_subscription_id" \
    -var "prefix=$_prefix" \
    -var "applications=$_applications"

terraform apply "${_timestamp}.tfplan"
rm "${_timestamp}.tfplan"
rm -rf .terraform
popd || exit 2


#!/usr/bin/env bash
set -euxo pipefail
# This script creates / updates teams in github. The $_teams param should be *all* teams needed in the system, not just new ones needed.

# shellcheck source=src/runtime/bootstrap/lib/tools.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../../../../runtime/bootstrap/lib/tools.sh"

_storage_account_name="$1"
_container_name="$2"
_container_rg="$3"
_access_token="$4"
_subscription_id="$5"
_org="$6"
_prefix="$7"
_applications="$8"
_timestamp="$(date "+%Y:%m:%d-%H:%M")"

pushd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit 2

terraform_init "$_storage_account_name" "$_container_name" "$_container_rg"

terraform plan \
    -lock=true \
    -out "${_timestamp}.tfplan" \
    -var "access_token=$_access_token" \
    -var "org=$_org" \
    -var "access_token=$_access_token" \
    -var "subscription_id=$_subscription_id" \
    -var "prefix=$_prefix" \
    -var "applications=$_applications"

terraform apply "${_timestamp}.tfplan"
rm "${_timestamp}.tfplan"
popd || exit 2


#!/usr/bin/env bash

# shellcheck disable=SC2034
read -r -d '' __usage <<-'EOF' || true # exits non-zero when EOF encountered
  -f --file [arg]  Config Filename to use. Default="./c12.ini"
  -v               Enable verbose mode, print script as it is executed
  -g --generate-config-example Generate a config file example
  -d --debug       Enables debug mode
  -h --help        This page
  -n --no-color    Disable color output
  -D --delete      Delete C12
EOF

# shellcheck disable=SC2034
read -r -d '' __helptext <<-'EOF' || true # exits non-zero when EOF encountered
 This script bootstraps a C12 environment for evaluation and testing.
 Examine the README.md file to see the resources it creates.

 To get started run './bootstrap --generate-config-example' and update the values
 in c12.ini
EOF
## Boilerplate files
# shellcheck source=src/runtime/bootstrap/lib/main.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/main.sh"
# shellcheck source=src/runtime/bootstrap/lib/ini_val.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/ini_val.sh"

## Component Files
# These contain the bash scripts to run the create / delete / update for each
# bootstrap step
# shellcheck source=src/runtime/bootstrap/steps/terraform_storage_account.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/steps/terraform_storage_account.sh"

# shellcheck source=src/runtime/bootstrap/steps/terraform_network.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/steps/terraform_network.sh"

# shellcheck source=src/runtime/bootstrap/steps/terraform_aks.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/steps/terraform_aks.sh"

# shellcheck source=src/runtime/bootstrap/steps/terraform_aad_credentials_pipeline.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/steps/terraform_aad_credentials_pipeline.sh"

# shellcheck source=src/runtime/bootstrap/steps/provision_ci_docker_images.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/steps/provision_ci_docker_images.sh"

# shellcheck source=src/runtime/bootstrap/steps/populate-repos.sh
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/steps/populate-repos.sh"

### Validation. Error out if the things required for your script are not present
##############################################################################

[[ "${arg_f:-}" ]]     || help      "Setting a filename with -f or --file is required"
[[ "${LOG_LEVEL:-}" ]] || emergency "Cannot continue without LOG_LEVEL. "

config_file="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$arg_f"
debug "expanding config file to $config_file"

# debug mode
if [[ "${arg_d:?}" = "1" ]]; then
  set -o xtrace
  PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
  LOG_LEVEL="7"
  # Enable error backtracing
  trap '__b3bp_err_report "${FUNCNAME:-.}" ${LINENO}' ERR
fi

# verbose mode
if [[ "${arg_v:?}" = "1" ]]; then
  set -o verbose
fi

# no color mode
if [[ "${arg_n:?}" = "1" ]]; then
  NO_COLOR="true"
fi

# help mode
if [[ "${arg_h:?}" = "1" ]]; then
  # Help exists with code 1
  help "Help using ${0}"
fi

### Runtime
##############################################################################

set -e

function destroy() {
    aad_credentials_for_pipelines_destroy
    destroy_aks
    destroy_network
    github_teams_delete
    aad_groups_delete
    github_repos_delete
    destroy_storage_account
    rm -rf ../cluster-on-boarding/terraform/.terraform
}

function generate_config() {
  # Azure info
  ini_val "$config_file" azure.subscription "<subscription id>" "ID of the subscription used for the C12 components"
  ini_val "$config_file" azure.location "<location id>" "ID of the location used for the C12 components"
  ini_val "$config_file" azure.arc-support "false" "[PREVIEW] See README for more info."
  # C12 info
  ini_val "$config_file" c12.prefix "<prefix>" "Prefix to use for names within the C12 deployments"
  ini_val "$config_file" c12:bootstrap.phase "bootstrap-config-generated" "Phase of C12 bootstrap - do not manually edit"

  # Github info
  ini_val "$config_file" github.org "<github org>" "GitHub org to use for C12 repos and co-ordination"
  ini_val "$config_file" github.access-token "<access token>" "GitHub Personal Access Token Used to manage the GitHub Organisation "
  ini_val "$config_file" github.access-token-username "<github username>" "GitHub username that was used to generate the access-token"
}

function aad_groups_create(){
    _storage_account_name=$(ini_val "$config_file" terraform:generated.storage-account-name)
    _container_name=$(ini_val "$config_file" terraform:generated.container-name)
    _container_rg=$(ini_val "$config_file" terraform:generated.container-rg)
    _access_token=$(ini_val "$config_file" github.access-token)
    _subscription_id=$(ini_val "$config_file" azure.subscription)
    _prefix=$(ini_val "$config_file" c12.prefix)
    # shellcheck disable=SC2154
    "$__dir"/../../components/identity-providers/aad/upsert-groups.sh \
        "$_storage_account_name" \
        "$_container_name" \
        "$_container_rg" \
        "$_subscription_id" \
        "$_prefix" \
        null \
        "$config_file"
}

function aad_groups_delete(){
    _storage_account_name=$(ini_val "$config_file" terraform:generated.storage-account-name)
    _container_name=$(ini_val "$config_file" terraform:generated.container-name)
    _container_rg=$(ini_val "$config_file" terraform:generated.container-rg)
    _access_token=$(ini_val "$config_file" github.access-token)
    _subscription_id=$(ini_val "$config_file" azure.subscription)
    _prefix=$(ini_val "$config_file" c12.prefix)
    "$__dir"/../../components/identity-providers/aad/delete-groups.sh \
        "$_storage_account_name" \
        "$_container_name" \
        "$_container_rg" \
        "$_subscription_id" \
        "$_prefix" \
        "[\"sample-app-nodejs\"]"
}

# shellcheck disable=SC2086
function github_repos_create() {
    _storage_account_name=$(ini_val "$config_file" terraform:generated.storage-account-name)
    _container_name=$(ini_val "$config_file" terraform:generated.container-name)
    _container_rg=$(ini_val "$config_file" terraform:generated.container-rg)
    _access_token=$(ini_val "$config_file" github.access-token)
    _org=$(ini_val "$config_file" github.org)
    _prefix=$(ini_val "$config_file" c12.prefix)
    "$__dir"/../../components/infrastructure/repos/github-enterprise-cloud/upsert-repos.sh \
        "$_storage_account_name" \
        "$_container_name" \
        "$_container_rg" \
        "$_access_token" \
        "$_org" \
        "$_prefix" \
        null
}

# shellcheck disable=SC2086
function github_repos_delete() {
    _storage_account_name=$(ini_val "$config_file" terraform:generated.storage-account-name)
    _container_name=$(ini_val "$config_file" terraform:generated.container-name)
    _container_rg=$(ini_val "$config_file" terraform:generated.container-rg)
    _access_token=$(ini_val "$config_file" github.access-token)
    _org=$(ini_val "$config_file" github.org)
    _prefix=$(ini_val "$config_file" c12.prefix)
    "$__dir"/../../components/infrastructure/repos/github-enterprise-cloud/delete-repos.sh \
        "$_storage_account_name" \
        "$_container_name" \
        "$_container_rg" \
        "$_access_token" \
        "$_org" \
        "$_prefix" \
        "[\"sample-app-nodejs\"]"
}
# shellcheck disable=SC2086
function github_teams_create() {
    _storage_account_name=$(ini_val "$config_file" terraform:generated.storage-account-name)
    _container_name=$(ini_val "$config_file" terraform:generated.container-name)
    _container_rg=$(ini_val "$config_file" terraform:generated.container-rg)
    _access_token=$(ini_val "$config_file" github.access-token)
    _subscription_id=$(ini_val "$config_file" azure.subscription)
    _org=$(ini_val "$config_file" github.org)
    _prefix=$(ini_val "$config_file" c12.prefix)
    "$__dir"/../../components/infrastructure/teams/github-enterprise-cloud/upsert-teams.sh \
        "$_storage_account_name" \
        "$_container_name" \
        "$_container_rg" \
        "$_access_token" \
        "$_subscription_id" \
        "$_org" \
        "$_prefix" \
        null
}

function github_teams_delete() {
    _storage_account_name=$(ini_val "$config_file" terraform:generated.storage-account-name)
    _container_name=$(ini_val "$config_file" terraform:generated.container-name)
    _container_rg=$(ini_val "$config_file" terraform:generated.container-rg)
    _access_token=$(ini_val "$config_file" github.access-token)
    _subscription_id=$(ini_val "$config_file" azure.subscription)
    _org=$(ini_val "$config_file" github.org)
    _prefix=$(ini_val "$config_file" c12.prefix)
    "$__dir"/../../components/infrastructure/teams/github-enterprise-cloud/delete-teams.sh \
        "$_storage_account_name" \
        "$_container_name" \
        "$_container_rg" \
        "$_access_token" \
        "$_subscription_id" \
        "$_org" \
        "$_prefix" \
        "[\"sample-app-nodejs\"]"
}

function hydrate_repos() {
     populate-repos "$config_file"
}

function adopt_cluster() {
    "$__dir"/../cluster-on-boarding/scripts/on_board_cluster.sh -f "$config_file"
}

function test_config() {
    warning "test_config not implemented yet. Only turning Github org string to lowercase if needed for now."
    info "./validate-config.sh"

    current_org=$(ini_val "$config_file" github.org)
    # shellcheck disable=SC2020
    lowercase_org="$(echo "$current_org" | tr '[:upper:]' '[:lower:]')"

    if [[ $current_org != "$lowercase_org" ]]; then
        # Turning Github org string to lowercase and writing it back to .ini file to avoid error creating repos
        ini_val "$config_file" github.org "$lowercase_org"
        warning "Github org value in .ini file was turned to lowercase (to create valid repo names)."

    fi
}

if [[ "${arg_g:?}" = "1" ]]; then
  # Help exists with code 1
  info "Generating sample config file in $config_file"
  generate_config
  exit 0
fi

if [[ "${arg_D:?}" = "1" ]]; then
  # Help exists with code 1
  warning "Destroying C12 infrastructure"
  destroy
  exit 0
fi

# shellcheck disable=SC2086
if [[ "$(ini_val $config_file azure.arc-support)" == "true" ]]; then
  # Check if location is support for Azure Arc
  _location=$(ini_val "$config_file" azure.location)
  _supported_locations="eastus westeurope"
  _supported="false"
  for supported in $_supported_locations
  do
    if [ "$_location" == "$supported" ]; then
      info "Azure location ${_location} is supported for Azure Arc"
      _supported="true"
      break   # break the for looop
    fi
  done
  if [ "$_supported" == "false" ]; then
    warning "Azure location ${_location} currently not supported for Azure Arc"
    exit 0
  fi
fi

# shellcheck disable=SC2086
while [ "$(ini_val $config_file c12:bootstrap.phase)" != "done" ]
do
    # shellcheck disable=SC2086
    case "$(ini_val $config_file c12:bootstrap.phase)" in
        "bootstrap-config-generated")
            test_config
            ini_val "$config_file" c12:bootstrap.phase "bootstrap-config-tested"
            ;;
        "bootstrap-config-tested")
            terraform_storage_account
            ini_val "$config_file" c12:bootstrap.phase "storage-account-created"
            ;;
        "storage-account-created")
            aad_groups_create
            ini_val "$config_file" c12:bootstrap.phase "aad-groups-created"
            ;;
        "aad-groups-created")
            terraform_network
            ini_val "$config_file" c12:bootstrap.phase "network-created"
            ;;
        "network-created")
            terraform_aks
            ini_val "$config_file" c12:bootstrap.phase "aks-created"
            ;;
        "aks-created")
            github_repos_create
            ini_val "$config_file" c12:bootstrap.phase "github-created"
            ;;
        "github-created")
            provision_ci_docker_image
            ini_val "$config_file" c12:bootstrap.phase "ci-images-provisioned"
            ;;
        "ci-images-provisioned")
            github_teams_create
            ini_val "$config_file" c12:bootstrap.phase "github-teams-created"
            ;;
        "github-teams-created")
            aad_credentials_for_pipelines_create
            ini_val "$config_file" c12:bootstrap.phase "aad-credentials-for-pipelines-created"
            ;;
        "aad-credentials-for-pipelines-created")
            adopt_cluster
            ini_val "$config_file" c12:bootstrap.phase "cluster-adopted"
            ;;
        "cluster-adopted")
            hydrate_repos
            ini_val "$config_file" c12:bootstrap.phase "github-repos-hydrated"
            ;;
        "github-repos-hydrated")
            ini_val "$config_file" c12:bootstrap.phase "done"
            ;;
        *)
            error "Unknown C12 state - exiting - have you ran './bootstrap.sh --generate-config-example'?"
            exit 3
    esac
done


#!/usr/bin/env bash
# BASH3 Boilerplate: ini_val
#
# This file:
#
#  - Can read and write .ini files using pure bash
#
# Limitations:
#
#  - All keys inside a section of the .ini file must be unique
#  - Optional comment parameter for the creation of new entries
#
# Usage as a function:
#
#  source ini_val.sh
#  ini_val data.ini connection.host 127.0.0.1 "Host name or IP address"
#
# Usage as a command:
#
#  ini_val.sh data.ini connection.host 127.0.0.1 "Host name or IP address"
#
# Based on a template by BASH3 Boilerplate v2.4.1
# http://bash3boilerplate.sh/#authors
#
# The MIT License (MIT)
# Copyright (c) 2013 Kevin van Zonneveld and contributors
# You are not obligated to bundle the LICENSE file with your b3bp projects as long
# as you leave these references intact in the header comments of your source files.

function ini_val() {
  local file="${1:-}"
  local sectionkey="${2:-}"
  local val="${3:-}"
  local comment="${4:-}"
  local delim="="
  local comment_delim=";"
  local section=""
  local key=""
  local current=""
  # add default section
  local section_default="default"

  if [[ ! -f "${file}" ]]; then
    # touch file if not exists
    touch "${file}"
  fi

  # Split on . for section. However, section is optional
  IFS='.' read -r section key <<< "${sectionkey}"
  if [[ ! "${key}" ]]; then
    key="${section}"
    # default section if not given
    section="${section_default}"
  fi

  current=$(sed -En "/^\[/{h;d;};G;s/^${key}([[:blank:]]*)${delim}(.*)\n\[${section}\]$/\2/p" "${file}"|awk '{$1=$1};1')

  if ! grep -q "\[${section}\]" "${file}"; then
    # create section if not exists (empty line to seperate new section)
    echo  >> "${file}"
    echo "[${section}]" >> "${file}"
  fi

  if [[ ! "${val}" ]]; then
    # get a value
    echo "${current}"
  else
    # set a value
    if [[ ! "${current}" ]]; then
      # doesn't exist yet, add
      if [[ ! "${section}" ]]; then
        # if no section is given, propagate the default section
        section=${section_default}
      fi
      # add to section
      if [[ ! "${comment}" ]]; then
        # add new key/value without comment
        RET="/\\[${section}\\]/a\\
${key}${delim}${val}"
      else
        # add new key/value with preceeding comment
        RET="/\\[${section}\\]/a\\
${comment_delim}[${key}] ${comment}\\
${key}${delim}${val}"
      fi
      sed -i.bak -e "${RET}" "${file}"
      # this .bak dance is done for BSD/GNU portability: http://stackoverflow.com/a/22084103/151666
      rm -f "${file}.bak"
    else
      # replace existing (modified to replace only keys in given section)
      sed -i.bak -e "/^\[${section}\]/,/^\[.*\]/ s|^\(${key}[ \t]*${delim}[ \t]*\).*$|\1${val}|" "${file}"
      # this .bak dance is done for BSD/GNU portability: http://stackoverflow.com/a/22084103/151666
      rm -f "${file}.bak"
    fi
  fi
}

if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
  export -f ini_val
else
  ini_val "${@}"
  exit ${?}
fi


#!/usr/bin/env bash

function __b3bp_log () {
  local log_level="${1}"
  shift

  # shellcheck disable=SC2034
  local color_debug="\\x1b[35m"
  # shellcheck disable=SC2034
  local color_info="\\x1b[32m"
  # shellcheck disable=SC2034
  local color_notice="\\x1b[34m"
  # shellcheck disable=SC2034
  local color_warning="\\x1b[33m"
  # shellcheck disable=SC2034
  local color_error="\\x1b[31m"
  # shellcheck disable=SC2034
  local color_critical="\\x1b[1;31m"
  # shellcheck disable=SC2034
  local color_alert="\\x1b[1;37;41m"
  # shellcheck disable=SC2034
  local color_emergency="\\x1b[1;4;5;37;41m"

  local colorvar="color_${log_level}"

  local color="${!colorvar:-${color_error}}"
  local color_reset="\\x1b[0m"

  if [[ "${NO_COLOR:-}" = "true" ]] || { [[ "${TERM:-}" != "xterm"* ]] && [[ "${TERM:-}" != "screen"* ]]; } || [[ ! -t 2 ]]; then
    if [[ "${NO_COLOR:-}" != "false" ]]; then
      # Don't use colors on pipes or non-recognized terminals
      color=""; color_reset=""
    fi
  fi

  # all remaining arguments are to be printed
  local log_line=""

  while IFS=$'\n' read -r log_line; do
    echo -e "$(date -u +"%Y-%m-%d %H:%M:%S UTC") ${color}$(printf "[%9s]" "${log_level}")${color_reset} ${log_line}" 1>&2
  done <<< "${@:-}"
}

function emergency () {                                __b3bp_log emergency "${@}"; exit 1; }
function alert ()     { [[ "${LOG_LEVEL:-0}" -ge 1 ]] && __b3bp_log alert "${@}"; true; }
function critical ()  { [[ "${LOG_LEVEL:-0}" -ge 2 ]] && __b3bp_log critical "${@}"; true; }
function error ()     { [[ "${LOG_LEVEL:-0}" -ge 3 ]] && __b3bp_log error "${@}"; true; }
function warning ()   { [[ "${LOG_LEVEL:-0}" -ge 4 ]] && __b3bp_log warning "${@}"; true; }
function notice ()    { [[ "${LOG_LEVEL:-0}" -ge 5 ]] && __b3bp_log notice "${@}"; true; }
function info ()      { [[ "${LOG_LEVEL:-0}" -ge 6 ]] && __b3bp_log info "${@}"; true; }
function debug ()     { [[ "${LOG_LEVEL:-0}" -ge 7 ]] && __b3bp_log debug "${@}"; true; }