Fix #258 - Quoted variable with env utility was breaking start command

#!/bin/sh

set -e

# Set VERBOSE to enable verbose logging of the boot script
#VERBOSE=true
if [ ! -z "$DEBUG_BOOT" ]; then
    set -x
fi;

my_readlink_f() {
    TARGET_FILE="$1"
    cd "$(dirname "$TARGET_FILE")"
    TARGET_FILE=$(basename "$TARGET_FILE")

    # Iterate down a (possible) chain of symlinks
    while [ -L "$TARGET_FILE" ]
    do
        TARGET_FILE=$(readlink "$TARGET_FILE")
        cd "$(dirname "$TARGET_FILE")"
        TARGET_FILE=$(basename "$TARGET_FILE")
    done
    # Compute the canonicalized name by finding the physical path
    # for the directory we're in and appending the target file.
    PHYS_DIR=$(pwd -P)
    RESULT="$PHYS_DIR/$TARGET_FILE"
    echo "$RESULT"
}

# Path to this script
if uname | grep -q 'Darwin'; then
  # on OSX, best to install coreutils from homebrew or similar
  # to get greadlink
  if command -v greadlink >/dev/null 2>&1; then
    SCRIPT="${SCRIPT:-$(greadlink -f "$0")}"
  else
    SCRIPT="${SCRIPT:-$(my_readlink_f "$0")}"
  fi
else
  SCRIPT="${SCRIPT:-$(readlink -f "$0" )}"
fi

# Parent directory of this script
SCRIPT_DIR="${SCRIPT_DIR:-$(dirname "${SCRIPT}")}"
# Root directory of all releases
RELEASE_ROOT_DIR="${RELEASE_ROOT_DIR:-$(dirname "$(dirname "${SCRIPT_DIR}")")}"

# Disable flow control for run_erl
# Flow control can cause several problems. On Linux, if you
# accidentally hit Ctrl-S (instead of Ctrl-D to detach) and
# then some other key, the entire beam process will hang when
# attempting to write to stdout. On Solaris, the beam process
# will hang on writing if ScrollLock is on.
RUN_ERL_DISABLE_FLOWCNTRL="${RUN_ERL_DISABLE_FLOWCNTRL:-true}"
# Name of the release
REL_NAME="${REL_NAME:-<%= release_name %>}"
# Current version of the release
REL_VSN="${REL_VSN:-<%= release_version %>}"
# Current version of ERTS being used
# If this is not present/unset, it will be detected
<%= if ((is_binary(include_erts) or include_erts) and not is_nil(erts_vsn)) do %>ERTS_VSN="${ERTS_VSN:-<%= erts_vsn %>}"<% end %>
# VM code loading mode, embedded by default, can also be interactive
# See http://erlang.org/doc/man/code.html
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
# Path to start_erl.data
START_ERL_DATA="${START_ERL_DATA:-$RELEASE_ROOT_DIR/releases/start_erl.data}"
# Directory containing the current version of this release
REL_DIR="${REL_DIR:-$RELEASE_ROOT_DIR/releases/$REL_VSN}"
# The lib directory for this release
REL_LIB_DIR="${REL_LIB_DIR:-$RELEASE_ROOT_DIR/lib}"
# Options passed to erl
ERL_OPTS="${ERL_OPTS:-<%= release.profile.erl_opts %>}"
# Environment variables for run_erl
RUN_ERL_ENV="${RUN_ERL_ENV:-<%= release.profile.run_erl_env %>}"
# When stdout is piped to a file, this is the directory those files will
# be stored in. defaults to /log in the release root directory

# RELEASE_MUTABLE_DIR
RELEASE_MUTABLE_DIR="${RELEASE_MUTABLE_DIR:-$RELEASE_ROOT_DIR/var}"

RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-$RELEASE_MUTABLE_DIR/log}"
# A string of extra options to pass to erl, here for plugins
EXTRA_OPTS="${EXTRA_OPTS:-}"

# Pre-start/stop event hook paths
PRE_CONFIGURE_HOOKS="$REL_DIR/hooks/pre_configure.d"
PRE_START_HOOKS="$REL_DIR/hooks/pre_start.d"
POST_START_HOOKS="$REL_DIR/hooks/post_start.d"
PRE_STOP_HOOKS="$REL_DIR/hooks/pre_stop.d"
POST_STOP_HOOKS="$REL_DIR/hooks/post_stop.d"
PRE_UPGRADE_HOOKS="$REL_DIR/hooks/pre_upgrade.d"
POST_UPGRADE_HOOKS="$REL_DIR/hooks/post_upgrade.d"

# Get node pid
get_pid() {
    if output="$(nodetool rpcterms os getpid)"
    then
        echo "$output" | sed -e 's/"//g'
        return 0
    else
        echo "$output"
        return 1
    fi
}

# Generate a unique nodename
gen_nodename() {
    id="longname$(gen_id)-${NAME}"
    "$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell "${NAME_TYPE}" "$id"
}

# Generate a random id
gen_id() {
    od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
}

# Control a node
# Use like `nodetool "ping"`
nodetool() {
    command="$1"; shift
    name=${PEERNAME:-$NAME}
    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$name" \
                            -setcookie "$COOKIE" "$command" "$@"
}

# Run an escript in the node's environment
# Use like `escript "path/to/escript"`
escript() {
    shift; scriptpath="$1"; shift
    export RELEASE_ROOT_DIR

    "$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" "$@"
}

## Run hooks for one of the configured startup phases
run_hooks() {
  case $1 in
    pre_configure)
      _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
      ;;
    pre_start)
      _run_hooks_from_dir "$PRE_START_HOOKS"
      ;;
    pre_stop)
      _run_hooks_from_dir "$PRE_STOP_HOOKS"
      ;;
    post_start)
      _run_hooks_from_dir "$POST_START_HOOKS"
      ;;
    post_stop)
      _run_hooks_from_dir "$POST_STOP_HOOKS"
      ;;
    pre_upgrade)
      _run_hooks_from_dir "$PRE_UPGRADE_HOOKS"
      ;;
    post_upgrade)
      _run_hooks_from_dir "$POST_UPGRADE_HOOKS"
      ;;
  esac
}

# Private. Load target cookie, either from vm.args or $HOME/.cookie
_load_cookie() {
    COOKIE_ARG="$(grep '^-setcookie' "$VMARGS_PATH" || true)"
    DEFAULT_COOKIE_FILE="$HOME/.erlang.cookie"
    if [ -z "$COOKIE_ARG" ]; then
        if [ -f "$DEFAULT_COOKIE_FILE" ]; then
            COOKIE="$(cat "$DEFAULT_COOKIE_FILE")"
        fi
    else
        # Extract cookie name from COOKIE_ARG
        COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
    fi
}

# Private. Ensure that cookie is set.
_check_cookie() {
    # Attempt reloading cookie in case it has been set in a hook
    if [ -z "$COOKIE" ]; then
        _load_cookie
    fi
    # Die if cookie is still not set, as connecting via distribution will fail
    if [ -z "$COOKIE" ]; then
        printf "a secret cookie must be provided in one of the following ways:\n  - with vm.args using the -setcookie parameter,\n  or\n  by writing the cookie to '%s', with permissions set to 0400", "$DEFAULT_COOKIE_FILE"
        exit 1
    fi
}

# Private. For setting up the Erlang runtime to use
_init_erts_config() {
    if [ -z "$ERTS_VSN" ]; then
        set +e # temporarily disable so we can display a nice error message to the user
        __erl="$(which erl)"
        set -e
        if [ -z "${__erl}"  ]; then
            echo 'erlang runtime not found. If erlang is installed check your $PATH. aborting.'
            exit 1
        fi
        export ROOTDIR
        ROOTDIR="$("$__erl" -eval 'io:format("~s~n", [code:root_dir()]), halt().' -noshell)"
        export ERTS_VSN
        ERTS_VSN="$(_get_erts_vsn)"
        export ERTS_DIR="$ROOTDIR/erts-$ERTS_VSN"
        # Update start_erl.data
        echo "$ERTS_VSN $REL_VSN" > "$START_ERL_DATA"
    else
        __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
        if [ -d "$__erts_dir" ]; then
            export ROOTDIR="$RELEASE_ROOT_DIR"
            export ERTS_DIR="$__erts_dir"
        else
            unset ERTS_VSN
            _init_erts_config
        fi
    fi
}

# Private. For determining the version of ERTS available to the release
# This is only ever called if ERTS_VSN is not set
_get_erts_vsn() {
    if [ -z "$ERTS_VSN" ]; then
        "$ROOTDIR"/bin/erl \
            -eval 'Ver = erlang:system_info(version), io:format("~s~n", [Ver]), halt()' \
            -noshell
    else
        echo "$ERTS_VSN"
    fi
}

# Private. Gets a list of code paths for this release
_get_code_paths() {
    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/release_utils.escript" "get_code_paths" "$ROOTDIR" "$ERTS_DIR" "$REL_NAME" "$REL_VSN"
}

# Private. Open a shell on a remote node
_rem_sh() {
    # Generate a unique id used to allow multiple remsh to the same node
    # transparently
    id="remsh$(gen_id)-${NAME}"

    # Get the node's ticktime so that we use the same thing.
    TICKTIME="$(nodetool rpcterms net_kernel get_net_ticktime)"

    # Setup remote shell command to control node
    if [ ! -z "$USE_ERL_SHELL" ]; then
        exec "$BINDIR/erl" \
            -hidden \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime "$TICKTIME" \
            "$NAME_TYPE" "$id" -remsh "$NAME" -setcookie "$COOKIE"
    else
        __code_paths=$(_get_code_paths)
        exec "$BINDIR/erl" \
            -pa "$CONSOLIDATED_DIR" \
            ${__code_paths} \
            -hidden -noshell \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime "$TICKTIME" \
            -user Elixir.IEx.CLI "$NAME_TYPE" "$id" -setcookie "$COOKIE" \
            -extra --no-halt +iex -"$NAME_TYPE" "$id" --cookie "$COOKIE" --remsh "$NAME"
    fi
}

# Output a start command for the last argument of run_erl
_start_command() {
    printf "exec \"%s\" \"%s\" -- %s %s" "$RELEASE_ROOT_DIR/bin/$REL_NAME" \
           "$START_OPTION" "${ARGS}" "${EXTRA_OPTS}"
}

# Do a textual replacement of ${VAR} occurrences in $1 and pipe to $2
_replace_os_vars() {
    awk '
        function escape(s) {
            gsub(/'\&'/, "\\\\&", s);
            return s;
        }
        {
            while(match($0,"[$]{[^}]*}")) {
                var=substr($0,RSTART+2,RLENGTH-3);
                gsub("[$]{"var"}", escape(ENVIRON[var]))
            }
        }1' < "$1" > "$1.bak"
    mv -- "$1.bak" "$1"
}

# Private. Run hooks from directory.
_run_hooks_from_dir() {
   if [ -d "$1" ]; then
      for file in $1/[0-9a-zA-Z]*.sh; do
        [ -f "$file" ] || continue
        . "$file"
      done
   fi
}

# Private. Sets config paths for sys.config and vm.args,
# and ensures that env var replacements are performed
_init_configs() {
    # Set VMARGS_PATH, the path to the vm.args file to use
    # Use $RELEASE_CONFIG_DIR/vm.args if exists, otherwise releases/VSN/vm.args
    if [ -z "$VMARGS_PATH" ]; then
        if [ -f "$RELEASE_CONFIG_DIR/vm.args" ]; then
            export SRC_VMARGS_PATH="$RELEASE_CONFIG_DIR/vm.args"
        else
            export SRC_VMARGS_PATH="$REL_DIR/vm.args"
        fi
    else
        export SRC_VMARGS_PATH="$VMARGS_PATH"
    fi
    if [ "$SRC_VMARGS_PATH" != "$RELEASE_MUTABLE_DIR/vm.args" ]; then
        echo "#### Generated - edit/create $RELEASE_CONFIG_DIR/vm.args instead." \
            >  "$RELEASE_MUTABLE_DIR/vm.args"
        cat  "$SRC_VMARGS_PATH"                              \
            >> "$RELEASE_MUTABLE_DIR/vm.args"
        export DEST_VMARGS_PATH="$RELEASE_MUTABLE_DIR"/vm.args
    fi
    if [ ! -z "$REPLACE_OS_VARS" ]; then
        _replace_os_vars "$DEST_VMARGS_PATH"
    fi
    export VMARGS_PATH="${VMARGS_PATH:-$DEST_VMARGS_PATH}"

    # Set SYS_CONFIG_PATH, the path to the sys.config file to use
    # Use $RELEASE_CONFIG_DIR/sys.config if exists, otherwise releases/VSN/sys.config
    if [ -z "$SYS_CONFIG_PATH" ]; then
        if [ -f "$RELEASE_CONFIG_DIR/sys.config" ]; then
            export SRC_SYS_CONFIG_PATH="$RELEASE_CONFIG_DIR/sys.config"
        else
            export SRC_SYS_CONFIG_PATH="$REL_DIR/sys.config"
        fi
    else
        export SRC_SYS_CONFIG_PATH="$SYS_CONFIG_PATH"
    fi
    if [ "$SRC_SYS_CONFIG_PATH" != "$RELEASE_MUTABLE_DIR/sys.config" ]; then
        (echo "%% Generated - edit/create $RELEASE_CONFIG_DIR/sys.config instead."; \
        cat  "$SRC_SYS_CONFIG_PATH")                              \
            > "$RELEASE_MUTABLE_DIR/sys.config"
        export DEST_SYS_CONFIG_PATH="$RELEASE_MUTABLE_DIR"/sys.config
    fi
    if [ ! -z "$REPLACE_OS_VARS" ]; then
        _replace_os_vars "$DEST_SYS_CONFIG_PATH"
    fi
    export SYS_CONFIG_PATH="${SYS_CONFIG_PATH:-$DEST_SYS_CONFIG_PATH}"
}

# If TERM is not set, set it to xterm
if [ -z "$TERM" ]; then
    export TERM=xterm
fi

# Make sure ERTS configuration is set
_init_erts_config

# Allow override of where to read configuration from
# By default it's RELEASE_ROOT_DIR
if [ -z "$RELEASE_CONFIG_DIR" ]; then
    export RELEASE_CONFIG_DIR="$RELEASE_ROOT_DIR"
fi

# Make sure directories exist
mkdir -p "$RELEASE_MUTABLE_DIR"
echo "Files in this directory are regenerated frequently, edits will be lost" \
    > "$RELEASE_MUTABLE_DIR/WARNING_README"
mkdir -p "$RUNNER_LOG_DIR"

# Make sure config paths are setup
_init_configs

# Extract the target node name from node.args
# Should be `-sname somename` or `-name somename@somehost`
export NAME_ARG
NAME_ARG="$(grep -E '^-s?name' "$VMARGS_PATH" || true)"
if [ -z "$NAME_ARG" ]; then
    echo "vm.args needs to have either -name or -sname parameter."
    exit 1
fi

# Extract the name type and name from the NAME_ARG for REMSH
# NAME_TYPE should be -name or -sname
export NAME_TYPE
NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}' | tail -n 1)"
# NAME will be either `somename` or `somename@somehost`
export NAME
NAME="$(echo "$NAME_ARG" | awk '{print $2}' | tail -n 1)"

# Where the pipe will be stored when using `start`
# This is used so you can attach the running application to the current
# shell using `attach`
PIPE_DIR="${PIPE_DIR:-$RELEASE_MUTABLE_DIR/erl_pipes/$NAME/}"

# Extract the target cookie
_load_cookie

export ROOTDIR="$RELEASE_ROOT_DIR"
export BINDIR="$ERTS_DIR/bin"
export EMU="beam"
export PROGNAME="erl"
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
export ERTS_LIB_DIR="$ERTS_DIR/../lib"
CONSOLIDATED_DIR="$ROOTDIR/lib/${REL_NAME}-${REL_VSN}/consolidated"

cd "$ROOTDIR"

# User can specify an sname without @hostname
# This will fail when creating remote shell
# So here we check for @ and add @hostname if missing
case $NAME in
    *@*)
        # Nothing to do
        ;;
    *)
        NAME=$NAME@$(gen_nodename)
        ;;
esac

# For Elixir runtime
export DISTILLERY_TASK="$1"

# Check the first argument for instructions
case "$1" in
    start|start_boot)

        # Make sure there is not already a node running
        #RES=`$NODETOOL ping`
        #if [ "$RES" = "pong" ]; then
        #    echo "Node is already running!"
        #    exit 1
        #fi
        # Save this for later.
        CMD=$1
        case "$1" in
            start)
                shift
                START_OPTION="console"
                HEART_OPTION="start"
                ;;
            start_boot)
                shift
                START_OPTION="console_boot"
                HEART_OPTION="start_boot"
                ;;
        esac
        ARGS="$*"
        RUN_PARAM="$*"

        _check_cookie
        run_hooks pre_configure
        run_hooks pre_start

        # Set arguments for the heart command
        set -- "$SCRIPT_DIR/$REL_NAME" "$HEART_OPTION"
        [ "$RUN_PARAM" ] && set -- "$@" "$RUN_PARAM"

        # Export the HEART_COMMAND
        HEART_COMMAND="$RELEASE_ROOT_DIR/bin/$REL_NAME $CMD"
        export HEART_COMMAND

        mkdir -p "$PIPE_DIR"

        env $RUN_ERL_ENV "$BINDIR/run_erl" -daemon "$PIPE_DIR" "$RUNNER_LOG_DIR" \
                          "$(_start_command)"

        run_hooks post_start
        ;;

    stop)
        _check_cookie
        run_hooks pre_stop
        # Wait for the node to completely stop...
        PID="$(get_pid)"
        if ! nodetool "stop"; then
            exit 1
        fi
        while kill -s 0 "$PID" 2>/dev/null;
        do
            sleep 1
        done
        run_hooks post_stop
        ;;

    restart)
        _check_cookie
        run_hooks pre_configure
        run_hooks pre_start
        ## Restart the VM without exiting the process
        if ! nodetool "restart"; then
            exit 1
        fi
        ;;

    reboot)
        _check_cookie
        run_hooks pre_configure
        run_hooks pre_start
        ## Restart the VM completely (uses heart to restart it)
        if ! nodetool "reboot"; then
            exit 1
        fi
        ;;

    pid)
        ## Get the VM's pid
        _check_cookie
        if ! get_pid; then
            exit 1
        fi
        ;;

    ping)
        _check_cookie
        ## See if the VM is alive
        if ! nodetool "ping"; then
            exit 1
        fi
        ;;

    pingpeer)
        PEERNAME=$2 nodetool "ping"
        exit_status=$?
        if [ "$exit_status" -ne 0 ]; then
            exit $exit_status
        fi
        ;;

    escript)
        _check_cookie
        ## Run an escript under the node's environment
        if ! escript "$@"; then
            exit 1
        fi
        ;;

    attach)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        exec "$BINDIR/to_erl" "$PIPE_DIR"
        ;;

    remote_console)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        _rem_sh
        ;;

    upgrade|downgrade|install)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        SOURCE_VERSION="$REL_VSN"
        TARGET_VERSION="$2"

        "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "unpack_release" "$REL_NAME" "$NAME_TYPE"  "$NAME" "$COOKIE" "$TARGET_VERSION"

        # Update environment to reflect target version environment
        REL_VSN="$TARGET_VERSION"
        REL_DIR="$RELEASE_ROOT_DIR/releases/$TARGET_VERSION"

        # Prepare new configs
        if [ "$SRC_VMARGS_PATH" = "$RELEASE_MUTABLE_DIR/vm.args" ]; then
            unset VMARGS_PATH
        else
            if [ "$SRC_VMARGS_PATH" = "$RELEASE_ROOT_DIR/releases/$SOURCE_VERSION/vm.args" ]; then
                unset VMARGS_PATH
            else
                export VMARGS_PATH="$SRC_VMARGS_PATH"
            fi
        fi
        if [ "$SRC_SYS_CONFIG_PATH" = "$RELEASE_MUTABLE_DIR/sys.config" ]; then
            unset SYS_CONFIG_PATH
        else
            if [ "$SRC_SYS_CONFIG_PATH" = "$RELEASE_ROOT_DIR/releases/$SOURCE_VERSION/sys.config" ]; then
                unset SYS_CONFIG_PATH
            else
                export SYS_CONFIG_PATH="$SRC_SYS_CONFIG_PATH"
            fi
        fi
        _init_configs
        # We have to do some juggling to ensure the correct config is used by the upgrade handler
        # First, we detect if there was a failed upgrade, so we can start over
        if [ -f "$REL_DIR/sys.config.bak" ]; then
            mv "$REL_DIR/sys.config.bak" "$REL_DIR/sys.config"
        fi
        if [ -f "$REL_DIR/vm.args.bak" ]; then
            mv "$REL_DIR/vm.args.bak" "$REL_DIR/vm.args"
        fi
        # Then, backup the packaged configs
        cp "$REL_DIR/sys.config" "$REL_DIR/sys.config.bak"
        cp "$REL_DIR/vm.args" "$REL_DIR/vm.args.bak"
        # Then, substitute in the prepared configs
        cp "$SYS_CONFIG_PATH" "$REL_DIR/sys.config"
        cp "$VMARGS_PATH" "$REL_DIR/vm.args"
        # Make sure any pre-configuration hooks are run
        run_hooks pre_configure
        # Run any pre-upgrade tasks
        run_hooks pre_upgrade

        "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "install_release" "$REL_NAME" "$NAME_TYPE"  "$NAME" "$COOKIE" "$TARGET_VERSION"

        # We were successful, clean up the configs
        mv "$REL_DIR/sys.config.bak" "$REL_DIR/sys.config"
        mv "$REL_DIR/vm.args.bak" "$REL_DIR/vm.args"

        # Run any post-upgrade hooks
        run_hooks post_upgrade

        ;;
    unpack)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        exec "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "unpack_release" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
        ;;

    console|console_clean|console_boot)
        # .boot file typically just $REL_NAME (ie, the app name)
        # however, for debugging, sometimes start_clean.boot is useful.
        # For e.g. 'setup', one may even want to name another boot script.
        case "$1" in
            console)
                if [ -f "$REL_DIR/$REL_NAME.boot" ]; then
                  BOOTFILE="$REL_DIR/$REL_NAME"
                else
                  BOOTFILE="$REL_DIR/start"
                fi
                ;;
            console_clean)
                BOOTFILE="$ROOTDIR/bin/start_clean"
                __code_paths=$(_get_code_paths)
                EXTRA_CODE_PATHS=${__code_paths}
                ;;
            console_boot)
                shift
                BOOTFILE="$1"
                shift
                ;;
        esac
        # Setup beam-required vars
        EMU="beam"
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$*"

        _check_cookie

        # Start the VM, executing pre_start hook along
        # the way. We can't run the post_start hook because
        # the console will crash with no TTY attached
        run_hooks pre_configure
        run_hooks pre_start

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" \
            -boot "$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            ${EXTRA_CODE_PATHS} \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -user Elixir.IEx.CLI \
            -extra --no-halt +iex

        # Dump environment info for logging purposes
        if [ ! -z "$VERBOSE" ]; then
            echo "Exec: $*" -- "${1+$ARGS}" "${EXTRA_OPTS}"
            echo "Root: $ROOTDIR"

            # Log the startup
            echo "$RELEASE_ROOT_DIR"
        fi;

        logger -t "$REL_NAME[$$]" "Starting up"

        exec "$@" -- "${1+$ARGS}" "${EXTRA_OPTS}"
        ;;

    foreground)
        # start up the release in the foreground for use by runit
        # or other supervision services

        [ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start
        FOREGROUNDOPTIONS="-noshell -noinput +Bd"

        # Setup beam-required vars
        EMU=beam
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$*"

        _check_cookie

        # Start the VM, executing pre and post start hooks
        run_hooks pre_configure
        run_hooks pre_start

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
            -boot "$REL_DIR/$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -extra ${EXTRA_OPTS}

        # Dump environment info for logging purposes
        if [ ! -z "$VERBOSE" ]; then
            echo "Exec: $*" -- "${1+$ARGS}"
            echo "Root: $ROOTDIR"
        fi;

        "$@" -- "${1+$ARGS}" &
        __bg_pid=$!
        run_hooks post_start
        wait $__bg_pid
        __exit_code=$?
        run_hooks post_stop
        exit $__exit_code
        ;;
    rpc)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpc "$@"
        ;;
    rpcterms)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpcterms "$@"
        ;;
    eval)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        nodetool "eval" "$@"
        ;;
    command)
        # Execute as command-line utility
        #
        # Like the escript command, this does not start the OTP application.
        # If your command depends on a running OTP application,
        # use
        #
        #     {:ok, _} = Application.ensure_all_started(:your_app)

        _check_cookie

        run_hooks pre_configure

        shift
        MODULE="$1"; shift
        FUNCTION="$1"; shift

        # Save extra arguments
        ARGS=$*

        # Build arguments for erlexec
        __code_paths=$(_get_code_paths)
        set -- "$ERL_OPTS"
        [ "$SYS_CONFIG_PATH" ] && set -- "$@" -config "$SYS_CONFIG_PATH"
        set -- "$@" -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR"
        set -- "$@" -noshell
        set -- "$@" -boot start_clean
        set -- "$@" -pa "$CONSOLIDATED_DIR"
        set -- "$@" ${__code_paths}
        set -- "$@" -s "$MODULE" "$FUNCTION"

        "$BINDIR"/erlexec "$@" -extra "$ARGS"
        exit "$?"
        ;;
    reload_config)
        # Reload the running system's configuration
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        run_hooks pre_configure

        shift
        nodetool "reload_config" "$SYS_CONFIG_PATH"
        ;;
    describe)
        ## Print a summary of information about this release
        echo "$REL_NAME-$REL_VSN\n"
        echo "erts:        $ERTS_VSN"
        echo "path:        $REL_DIR"
        echo "sys.config:  $SYS_CONFIG_PATH"
        echo "vm.args:     $VMARGS_PATH"
        echo "name:        $NAME"
        echo "cookie:      $COOKIE"
        echo "erl_opts:    ${ERL_OPTS:-none provided}"
        echo "run_erl_env: ${RUN_ERL_ENV:-none provided}"
        echo ""
        echo "hooks:"
        __has_hooks=0
        for hook in "$REL_DIR"/hooks/*.d/[0-9a-zA-Z]*.sh; do
            [ -f "$hook" ] || continue
            __has_hooks=1
            echo "$hook"
        done
        if [ $__has_hooks -eq 0 ]; then
            echo "No custom hooks found."
        fi
        echo ""
        echo "commands:"
        __has_commands=0
        for command in "$REL_DIR"/commands/*.sh; do
            [ -f "$command" ] || continue
            __has_commands=1
            echo "$command"
        done
        if [ $__has_commands -eq 0 ]; then
            echo "No custom commands found."
        fi
        exit 0
        ;;
    *)
        __command_path="$REL_DIR/commands/$1.sh"
        if [ -f "$__command_path" ]; then
            _check_cookie
            . "$__command_path"
        else
            echo "Usage: $REL_NAME <task>"
            echo
            echo "Service Control"
            echo "======================="
            echo "start                          # start $REL_NAME as a daemon"
            echo "start_boot <file>              # start $REL_NAME as a daemon, but supply a custom .boot file"
            echo "foreground                     # start $REL_NAME in the foreground"
            echo "console                        # start $REL_NAME with a console attached"
            echo "console_clean                  # start a console with code paths set but no apps loaded/started"
            echo "console_boot <file>            # start $REL_NAME with a console attached, but supply a custom .boot file"
            echo "stop                           # stop the $REL_NAME daemon"
            echo "restart                        # restart the $REL_NAME daemon without shutting down the VM"
            echo "reboot                         # restart the $REL_NAME daemon"
            echo "reload_config                  # reload the current system's configuration from disk"
            echo
            echo "Upgrades"
            echo "======================="
            echo "upgrade <version>              # upgrade $REL_NAME to <version>"
            echo "downgrade <version>            # downgrade $REL_NAME to <version>"
            echo "install <version>              # install the $REL_NAME-<version> release, but do not upgrade to it"
            echo
            echo "Utilities"
            echo "======================="
            echo "attach                         # attach the current TTY to $REL_NAME's console"
            echo "remote_console                 # remote shell to $REL_NAME's console"
            echo "pid                            # get the pid of the running $REL_NAME instance"
            echo "ping                           # checks if $REL_NAME is running, pong is returned if successful"
            echo "pingpeer <peer>                # check if a peer node is running, pong is returned if successful"
            echo "escript <file>                 # execute an escript"
            echo "rpc <mod> <fun> [<args..>]     # execute an RPC call using the given MFA"
            echo "rpcterms <mod> <fun> [<expr>]  # execute an RPC call using the given Erlang expression for args"
            echo "eval <expr>                    # execute the given Erlang expression on the running node"
            echo "command <mod> <fun> [<args..>] # execute the given MFA"
            echo "describe                       # print useful information about the $REL_NAME release"
            echo
            echo "Custom Commands"
            echo "======================="
            __has_commands=0
            for command in "$REL_DIR"/commands/*.sh; do
                [ -f "$command" ] || continue
                __has_commands=1
                echo "$command"
            done
            if [ $__has_commands -eq 0 ]; then
                echo "No custom commands found."
            fi
            echo ""
            exit 1
        fi
        ;;
esac

exit 0

#!/bin/sh

set -e

# Set VERBOSE to enable verbose logging of the boot script
#VERBOSE=true
if [ ! -z "$DEBUG_BOOT" ]; then
    set -x
fi;

my_readlink_f() {
    TARGET_FILE="$1"
    cd "$(dirname "$TARGET_FILE")"
    TARGET_FILE=$(basename "$TARGET_FILE")

    # Iterate down a (possible) chain of symlinks
    while [ -L "$TARGET_FILE" ]
    do
        TARGET_FILE=$(readlink "$TARGET_FILE")
        cd "$(dirname "$TARGET_FILE")"
        TARGET_FILE=$(basename "$TARGET_FILE")
    done
    # Compute the canonicalized name by finding the physical path
    # for the directory we're in and appending the target file.
    PHYS_DIR=$(pwd -P)
    RESULT="$PHYS_DIR/$TARGET_FILE"
    echo "$RESULT"
}

# Path to this script
if uname | grep -q 'Darwin'; then
  # on OSX, best to install coreutils from homebrew or similar
  # to get greadlink
  if command -v greadlink >/dev/null 2>&1; then
    SCRIPT="${SCRIPT:-$(greadlink -f "$0")}"
  else
    SCRIPT="${SCRIPT:-$(my_readlink_f "$0")}"
  fi
else
  SCRIPT="${SCRIPT:-$(readlink -f "$0" )}"
fi

# Parent directory of this script
SCRIPT_DIR="${SCRIPT_DIR:-$(dirname "${SCRIPT}")}"
# Root directory of all releases
RELEASE_ROOT_DIR="${RELEASE_ROOT_DIR:-$(dirname "$(dirname "${SCRIPT_DIR}")")}"

# Disable flow control for run_erl
# Flow control can cause several problems. On Linux, if you
# accidentally hit Ctrl-S (instead of Ctrl-D to detach) and
# then some other key, the entire beam process will hang when
# attempting to write to stdout. On Solaris, the beam process
# will hang on writing if ScrollLock is on.
RUN_ERL_DISABLE_FLOWCNTRL="${RUN_ERL_DISABLE_FLOWCNTRL:-true}"
# Name of the release
REL_NAME="${REL_NAME:-<%= release_name %>}"
# Current version of the release
REL_VSN="${REL_VSN:-<%= release_version %>}"
# Current version of ERTS being used
# If this is not present/unset, it will be detected
<%= if ((is_binary(include_erts) or include_erts) and not is_nil(erts_vsn)) do %>ERTS_VSN="${ERTS_VSN:-<%= erts_vsn %>}"<% end %>
# VM code loading mode, embedded by default, can also be interactive
# See http://erlang.org/doc/man/code.html
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
# Path to start_erl.data
START_ERL_DATA="${START_ERL_DATA:-$RELEASE_ROOT_DIR/releases/start_erl.data}"
# Directory containing the current version of this release
REL_DIR="${REL_DIR:-$RELEASE_ROOT_DIR/releases/$REL_VSN}"
# The lib directory for this release
REL_LIB_DIR="${REL_LIB_DIR:-$RELEASE_ROOT_DIR/lib}"
# Options passed to erl
ERL_OPTS="${ERL_OPTS:-<%= release.profile.erl_opts %>}"
# Environment variables for run_erl
RUN_ERL_ENV="${RUN_ERL_ENV:-<%= release.profile.run_erl_env %>}"
# When stdout is piped to a file, this is the directory those files will
# be stored in. defaults to /log in the release root directory

# RELEASE_MUTABLE_DIR
RELEASE_MUTABLE_DIR="${RELEASE_MUTABLE_DIR:-$RELEASE_ROOT_DIR/var}"

RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-$RELEASE_MUTABLE_DIR/log}"
# A string of extra options to pass to erl, here for plugins
EXTRA_OPTS="${EXTRA_OPTS:-}"

# Pre-start/stop event hook paths
PRE_CONFIGURE_HOOKS="$REL_DIR/hooks/pre_configure.d"
PRE_START_HOOKS="$REL_DIR/hooks/pre_start.d"
POST_START_HOOKS="$REL_DIR/hooks/post_start.d"
PRE_STOP_HOOKS="$REL_DIR/hooks/pre_stop.d"
POST_STOP_HOOKS="$REL_DIR/hooks/post_stop.d"
PRE_UPGRADE_HOOKS="$REL_DIR/hooks/pre_upgrade.d"
POST_UPGRADE_HOOKS="$REL_DIR/hooks/post_upgrade.d"

# Get node pid
get_pid() {
    if output="$(nodetool rpcterms os getpid)"
    then
        echo "$output" | sed -e 's/"//g'
        return 0
    else
        echo "$output"
        return 1
    fi
}

# Generate a unique nodename
gen_nodename() {
    id="longname$(gen_id)-${NAME}"
    "$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell "${NAME_TYPE}" "$id"
}

# Generate a random id
gen_id() {
    od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
}

# Control a node
# Use like `nodetool "ping"`
nodetool() {
    command="$1"; shift
    name=${PEERNAME:-$NAME}
    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$name" \
                            -setcookie "$COOKIE" "$command" "$@"
}

# Run an escript in the node's environment
# Use like `escript "path/to/escript"`
escript() {
    shift; scriptpath="$1"; shift
    export RELEASE_ROOT_DIR

    "$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" "$@"
}

## Run hooks for one of the configured startup phases
run_hooks() {
  case $1 in
    pre_configure)
      _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
      ;;
    pre_start)
      _run_hooks_from_dir "$PRE_START_HOOKS"
      ;;
    pre_stop)
      _run_hooks_from_dir "$PRE_STOP_HOOKS"
      ;;
    post_start)
      _run_hooks_from_dir "$POST_START_HOOKS"
      ;;
    post_stop)
      _run_hooks_from_dir "$POST_STOP_HOOKS"
      ;;
    pre_upgrade)
      _run_hooks_from_dir "$PRE_UPGRADE_HOOKS"
      ;;
    post_upgrade)
      _run_hooks_from_dir "$POST_UPGRADE_HOOKS"
      ;;
  esac
}

# Private. Load target cookie, either from vm.args or $HOME/.cookie
_load_cookie() {
    COOKIE_ARG="$(grep '^-setcookie' "$VMARGS_PATH" || true)"
    DEFAULT_COOKIE_FILE="$HOME/.erlang.cookie"
    if [ -z "$COOKIE_ARG" ]; then
        if [ -f "$DEFAULT_COOKIE_FILE" ]; then
            COOKIE="$(cat "$DEFAULT_COOKIE_FILE")"
        fi
    else
        # Extract cookie name from COOKIE_ARG
        COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
    fi
}

# Private. Ensure that cookie is set.
_check_cookie() {
    # Attempt reloading cookie in case it has been set in a hook
    if [ -z "$COOKIE" ]; then
        _load_cookie
    fi
    # Die if cookie is still not set, as connecting via distribution will fail
    if [ -z "$COOKIE" ]; then
        printf "a secret cookie must be provided in one of the following ways:\n  - with vm.args using the -setcookie parameter,\n  or\n  by writing the cookie to '%s', with permissions set to 0400", "$DEFAULT_COOKIE_FILE"
        exit 1
    fi
}

# Private. For setting up the Erlang runtime to use
_init_erts_config() {
    if [ -z "$ERTS_VSN" ]; then
        set +e # temporarily disable so we can display a nice error message to the user
        __erl="$(which erl)"
        set -e
        if [ -z "${__erl}"  ]; then
            echo 'erlang runtime not found. If erlang is installed check your $PATH. aborting.'
            exit 1
        fi
        export ROOTDIR
        ROOTDIR="$("$__erl" -eval 'io:format("~s~n", [code:root_dir()]), halt().' -noshell)"
        export ERTS_VSN
        ERTS_VSN="$(_get_erts_vsn)"
        export ERTS_DIR="$ROOTDIR/erts-$ERTS_VSN"
        # Update start_erl.data
        echo "$ERTS_VSN $REL_VSN" > "$START_ERL_DATA"
    else
        __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
        if [ -d "$__erts_dir" ]; then
            export ROOTDIR="$RELEASE_ROOT_DIR"
            export ERTS_DIR="$__erts_dir"
        else
            unset ERTS_VSN
            _init_erts_config
        fi
    fi
}

# Private. For determining the version of ERTS available to the release
# This is only ever called if ERTS_VSN is not set
_get_erts_vsn() {
    if [ -z "$ERTS_VSN" ]; then
        "$ROOTDIR"/bin/erl \
            -eval 'Ver = erlang:system_info(version), io:format("~s~n", [Ver]), halt()' \
            -noshell
    else
        echo "$ERTS_VSN"
    fi
}

# Private. Gets a list of code paths for this release
_get_code_paths() {
    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/release_utils.escript" "get_code_paths" "$ROOTDIR" "$ERTS_DIR" "$REL_NAME" "$REL_VSN"
}

# Private. Open a shell on a remote node
_rem_sh() {
    # Generate a unique id used to allow multiple remsh to the same node
    # transparently
    id="remsh$(gen_id)-${NAME}"

    # Get the node's ticktime so that we use the same thing.
    TICKTIME="$(nodetool rpcterms net_kernel get_net_ticktime)"

    # Setup remote shell command to control node
    if [ ! -z "$USE_ERL_SHELL" ]; then
        exec "$BINDIR/erl" \
            -hidden \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime "$TICKTIME" \
            "$NAME_TYPE" "$id" -remsh "$NAME" -setcookie "$COOKIE"
    else
        __code_paths=$(_get_code_paths)
        exec "$BINDIR/erl" \
            -pa "$CONSOLIDATED_DIR" \
            ${__code_paths} \
            -hidden -noshell \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime "$TICKTIME" \
            -user Elixir.IEx.CLI "$NAME_TYPE" "$id" -setcookie "$COOKIE" \
            -extra --no-halt +iex -"$NAME_TYPE" "$id" --cookie "$COOKIE" --remsh "$NAME"
    fi
}

# Output a start command for the last argument of run_erl
_start_command() {
    printf "exec \"%s\" \"%s\" -- %s %s" "$RELEASE_ROOT_DIR/bin/$REL_NAME" \
           "$START_OPTION" "${ARGS}" "${EXTRA_OPTS}"
}

# Do a textual replacement of ${VAR} occurrences in $1 and pipe to $2
_replace_os_vars() {
    awk '
        function escape(s) {
            gsub(/'\&'/, "\\\\&", s);
            return s;
        }
        {
            while(match($0,"[$]{[^}]*}")) {
                var=substr($0,RSTART+2,RLENGTH-3);
                gsub("[$]{"var"}", escape(ENVIRON[var]))
            }
        }1' < "$1" > "$1.bak"
    mv -- "$1.bak" "$1"
}

# Private. Run hooks from directory.
_run_hooks_from_dir() {
   if [ -d "$1" ]; then
      for file in $1/[0-9a-zA-Z]*.sh; do
        [ -f "$file" ] || continue
        . "$file"
      done
   fi
}

# Private. Sets config paths for sys.config and vm.args,
# and ensures that env var replacements are performed
_init_configs() {
    # Set VMARGS_PATH, the path to the vm.args file to use
    # Use $RELEASE_CONFIG_DIR/vm.args if exists, otherwise releases/VSN/vm.args
    if [ -z "$VMARGS_PATH" ]; then
        if [ -f "$RELEASE_CONFIG_DIR/vm.args" ]; then
            export SRC_VMARGS_PATH="$RELEASE_CONFIG_DIR/vm.args"
        else
            export SRC_VMARGS_PATH="$REL_DIR/vm.args"
        fi
    else
        export SRC_VMARGS_PATH="$VMARGS_PATH"
    fi
    if [ "$SRC_VMARGS_PATH" != "$RELEASE_MUTABLE_DIR/vm.args" ]; then
        echo "#### Generated - edit/create $RELEASE_CONFIG_DIR/vm.args instead." \
            >  "$RELEASE_MUTABLE_DIR/vm.args"
        cat  "$SRC_VMARGS_PATH"                              \
            >> "$RELEASE_MUTABLE_DIR/vm.args"
        export DEST_VMARGS_PATH="$RELEASE_MUTABLE_DIR"/vm.args
    fi
    if [ ! -z "$REPLACE_OS_VARS" ]; then
        _replace_os_vars "$DEST_VMARGS_PATH"
    fi
    export VMARGS_PATH="${VMARGS_PATH:-$DEST_VMARGS_PATH}"

    # Set SYS_CONFIG_PATH, the path to the sys.config file to use
    # Use $RELEASE_CONFIG_DIR/sys.config if exists, otherwise releases/VSN/sys.config
    if [ -z "$SYS_CONFIG_PATH" ]; then
        if [ -f "$RELEASE_CONFIG_DIR/sys.config" ]; then
            export SRC_SYS_CONFIG_PATH="$RELEASE_CONFIG_DIR/sys.config"
        else
            export SRC_SYS_CONFIG_PATH="$REL_DIR/sys.config"
        fi
    else
        export SRC_SYS_CONFIG_PATH="$SYS_CONFIG_PATH"
    fi
    if [ "$SRC_SYS_CONFIG_PATH" != "$RELEASE_MUTABLE_DIR/sys.config" ]; then
        (echo "%% Generated - edit/create $RELEASE_CONFIG_DIR/sys.config instead."; \
        cat  "$SRC_SYS_CONFIG_PATH")                              \
            > "$RELEASE_MUTABLE_DIR/sys.config"
        export DEST_SYS_CONFIG_PATH="$RELEASE_MUTABLE_DIR"/sys.config
    fi
    if [ ! -z "$REPLACE_OS_VARS" ]; then
        _replace_os_vars "$DEST_SYS_CONFIG_PATH"
    fi
    export SYS_CONFIG_PATH="${SYS_CONFIG_PATH:-$DEST_SYS_CONFIG_PATH}"
}

# If TERM is not set, set it to xterm
if [ -z "$TERM" ]; then
    export TERM=xterm
fi

# Make sure ERTS configuration is set
_init_erts_config

# Allow override of where to read configuration from
# By default it's RELEASE_ROOT_DIR
if [ -z "$RELEASE_CONFIG_DIR" ]; then
    export RELEASE_CONFIG_DIR="$RELEASE_ROOT_DIR"
fi

# Make sure directories exist
mkdir -p "$RELEASE_MUTABLE_DIR"
echo "Files in this directory are regenerated frequently, edits will be lost" \
    > "$RELEASE_MUTABLE_DIR/WARNING_README"
mkdir -p "$RUNNER_LOG_DIR"

# Make sure config paths are setup
_init_configs

# Extract the target node name from node.args
# Should be `-sname somename` or `-name somename@somehost`
export NAME_ARG
NAME_ARG="$(grep -E '^-s?name' "$VMARGS_PATH" || true)"
if [ -z "$NAME_ARG" ]; then
    echo "vm.args needs to have either -name or -sname parameter."
    exit 1
fi

# Extract the name type and name from the NAME_ARG for REMSH
# NAME_TYPE should be -name or -sname
export NAME_TYPE
NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}' | tail -n 1)"
# NAME will be either `somename` or `somename@somehost`
export NAME
NAME="$(echo "$NAME_ARG" | awk '{print $2}' | tail -n 1)"

# Where the pipe will be stored when using `start`
# This is used so you can attach the running application to the current
# shell using `attach`
PIPE_DIR="${PIPE_DIR:-$RELEASE_MUTABLE_DIR/erl_pipes/$NAME/}"

# Extract the target cookie
_load_cookie

export ROOTDIR="$RELEASE_ROOT_DIR"
export BINDIR="$ERTS_DIR/bin"
export EMU="beam"
export PROGNAME="erl"
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
export ERTS_LIB_DIR="$ERTS_DIR/../lib"
CONSOLIDATED_DIR="$ROOTDIR/lib/${REL_NAME}-${REL_VSN}/consolidated"

cd "$ROOTDIR"

# User can specify an sname without @hostname
# This will fail when creating remote shell
# So here we check for @ and add @hostname if missing
case $NAME in
    *@*)
        # Nothing to do
        ;;
    *)
        NAME=$NAME@$(gen_nodename)
        ;;
esac

# For Elixir runtime
export DISTILLERY_TASK="$1"

# Check the first argument for instructions
case "$1" in
    start|start_boot)

        # Make sure there is not already a node running
        #RES=`$NODETOOL ping`
        #if [ "$RES" = "pong" ]; then
        #    echo "Node is already running!"
        #    exit 1
        #fi
        # Save this for later.
        CMD=$1
        case "$1" in
            start)
                shift
                START_OPTION="console"
                HEART_OPTION="start"
                ;;
            start_boot)
                shift
                START_OPTION="console_boot"
                HEART_OPTION="start_boot"
                ;;
        esac
        ARGS="$*"
        RUN_PARAM="$*"

        _check_cookie
        run_hooks pre_configure
        run_hooks pre_start

        # Set arguments for the heart command
        set -- "$SCRIPT_DIR/$REL_NAME" "$HEART_OPTION"
        [ "$RUN_PARAM" ] && set -- "$@" "$RUN_PARAM"

        # Export the HEART_COMMAND
        HEART_COMMAND="$RELEASE_ROOT_DIR/bin/$REL_NAME $CMD"
        export HEART_COMMAND

        mkdir -p "$PIPE_DIR"

        env "$RUN_ERL_ENV" "$BINDIR/run_erl" -daemon "$PIPE_DIR" "$RUNNER_LOG_DIR" \
                          "$(_start_command)"

        run_hooks post_start
        ;;

    stop)
        _check_cookie
        run_hooks pre_stop
        # Wait for the node to completely stop...
        PID="$(get_pid)"
        if ! nodetool "stop"; then
            exit 1
        fi
        while kill -s 0 "$PID" 2>/dev/null;
        do
            sleep 1
        done
        run_hooks post_stop
        ;;

    restart)
        _check_cookie
        run_hooks pre_configure
        run_hooks pre_start
        ## Restart the VM without exiting the process
        if ! nodetool "restart"; then
            exit 1
        fi
        ;;

    reboot)
        _check_cookie
        run_hooks pre_configure
        run_hooks pre_start
        ## Restart the VM completely (uses heart to restart it)
        if ! nodetool "reboot"; then
            exit 1
        fi
        ;;

    pid)
        ## Get the VM's pid
        _check_cookie
        if ! get_pid; then
            exit 1
        fi
        ;;

    ping)
        _check_cookie
        ## See if the VM is alive
        if ! nodetool "ping"; then
            exit 1
        fi
        ;;

    pingpeer)
        PEERNAME=$2 nodetool "ping"
        exit_status=$?
        if [ "$exit_status" -ne 0 ]; then
            exit $exit_status
        fi
        ;;

    escript)
        _check_cookie
        ## Run an escript under the node's environment
        if ! escript "$@"; then
            exit 1
        fi
        ;;

    attach)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        exec "$BINDIR/to_erl" "$PIPE_DIR"
        ;;

    remote_console)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        _rem_sh
        ;;

    upgrade|downgrade|install)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        SOURCE_VERSION="$REL_VSN"
        TARGET_VERSION="$2"

        "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "unpack_release" "$REL_NAME" "$NAME_TYPE"  "$NAME" "$COOKIE" "$TARGET_VERSION"

        # Update environment to reflect target version environment
        REL_VSN="$TARGET_VERSION"
        REL_DIR="$RELEASE_ROOT_DIR/releases/$TARGET_VERSION"

        # Prepare new configs
        if [ "$SRC_VMARGS_PATH" = "$RELEASE_MUTABLE_DIR/vm.args" ]; then
            unset VMARGS_PATH
        else
            if [ "$SRC_VMARGS_PATH" = "$RELEASE_ROOT_DIR/releases/$SOURCE_VERSION/vm.args" ]; then
                unset VMARGS_PATH
            else
                export VMARGS_PATH="$SRC_VMARGS_PATH"
            fi
        fi
        if [ "$SRC_SYS_CONFIG_PATH" = "$RELEASE_MUTABLE_DIR/sys.config" ]; then
            unset SYS_CONFIG_PATH
        else
            if [ "$SRC_SYS_CONFIG_PATH" = "$RELEASE_ROOT_DIR/releases/$SOURCE_VERSION/sys.config" ]; then
                unset SYS_CONFIG_PATH
            else
                export SYS_CONFIG_PATH="$SRC_SYS_CONFIG_PATH"
            fi
        fi
        _init_configs
        # We have to do some juggling to ensure the correct config is used by the upgrade handler
        # First, we detect if there was a failed upgrade, so we can start over
        if [ -f "$REL_DIR/sys.config.bak" ]; then
            mv "$REL_DIR/sys.config.bak" "$REL_DIR/sys.config"
        fi
        if [ -f "$REL_DIR/vm.args.bak" ]; then
            mv "$REL_DIR/vm.args.bak" "$REL_DIR/vm.args"
        fi
        # Then, backup the packaged configs
        cp "$REL_DIR/sys.config" "$REL_DIR/sys.config.bak"
        cp "$REL_DIR/vm.args" "$REL_DIR/vm.args.bak"
        # Then, substitute in the prepared configs
        cp "$SYS_CONFIG_PATH" "$REL_DIR/sys.config"
        cp "$VMARGS_PATH" "$REL_DIR/vm.args"
        # Make sure any pre-configuration hooks are run
        run_hooks pre_configure
        # Run any pre-upgrade tasks
        run_hooks pre_upgrade

        "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "install_release" "$REL_NAME" "$NAME_TYPE"  "$NAME" "$COOKIE" "$TARGET_VERSION"

        # We were successful, clean up the configs
        mv "$REL_DIR/sys.config.bak" "$REL_DIR/sys.config"
        mv "$REL_DIR/vm.args.bak" "$REL_DIR/vm.args"

        # Run any post-upgrade hooks
        run_hooks post_upgrade

        ;;
    unpack)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        exec "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "unpack_release" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
        ;;

    console|console_clean|console_boot)
        # .boot file typically just $REL_NAME (ie, the app name)
        # however, for debugging, sometimes start_clean.boot is useful.
        # For e.g. 'setup', one may even want to name another boot script.
        case "$1" in
            console)
                if [ -f "$REL_DIR/$REL_NAME.boot" ]; then
                  BOOTFILE="$REL_DIR/$REL_NAME"
                else
                  BOOTFILE="$REL_DIR/start"
                fi
                ;;
            console_clean)
                BOOTFILE="$ROOTDIR/bin/start_clean"
                __code_paths=$(_get_code_paths)
                EXTRA_CODE_PATHS=${__code_paths}
                ;;
            console_boot)
                shift
                BOOTFILE="$1"
                shift
                ;;
        esac
        # Setup beam-required vars
        EMU="beam"
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$*"

        _check_cookie

        # Start the VM, executing pre_start hook along
        # the way. We can't run the post_start hook because
        # the console will crash with no TTY attached
        run_hooks pre_configure
        run_hooks pre_start

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" \
            -boot "$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            ${EXTRA_CODE_PATHS} \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -user Elixir.IEx.CLI \
            -extra --no-halt +iex

        # Dump environment info for logging purposes
        if [ ! -z "$VERBOSE" ]; then
            echo "Exec: $*" -- "${1+$ARGS}" "${EXTRA_OPTS}"
            echo "Root: $ROOTDIR"

            # Log the startup
            echo "$RELEASE_ROOT_DIR"
        fi;

        logger -t "$REL_NAME[$$]" "Starting up"

        exec "$@" -- "${1+$ARGS}" "${EXTRA_OPTS}"
        ;;

    foreground)
        # start up the release in the foreground for use by runit
        # or other supervision services

        [ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start
        FOREGROUNDOPTIONS="-noshell -noinput +Bd"

        # Setup beam-required vars
        EMU=beam
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$*"

        _check_cookie

        # Start the VM, executing pre and post start hooks
        run_hooks pre_configure
        run_hooks pre_start

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
            -boot "$REL_DIR/$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -extra ${EXTRA_OPTS}

        # Dump environment info for logging purposes
        if [ ! -z "$VERBOSE" ]; then
            echo "Exec: $*" -- "${1+$ARGS}"
            echo "Root: $ROOTDIR"
        fi;

        "$@" -- "${1+$ARGS}" &
        __bg_pid=$!
        run_hooks post_start
        wait $__bg_pid
        __exit_code=$?
        run_hooks post_stop
        exit $__exit_code
        ;;
    rpc)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpc "$@"
        ;;
    rpcterms)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpcterms "$@"
        ;;
    eval)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        nodetool "eval" "$@"
        ;;
    command)
        # Execute as command-line utility
        #
        # Like the escript command, this does not start the OTP application.
        # If your command depends on a running OTP application,
        # use
        #
        #     {:ok, _} = Application.ensure_all_started(:your_app)

        _check_cookie

        run_hooks pre_configure

        shift
        MODULE="$1"; shift
        FUNCTION="$1"; shift

        # Save extra arguments
        ARGS=$*

        # Build arguments for erlexec
        __code_paths=$(_get_code_paths)
        set -- "$ERL_OPTS"
        [ "$SYS_CONFIG_PATH" ] && set -- "$@" -config "$SYS_CONFIG_PATH"
        set -- "$@" -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR"
        set -- "$@" -noshell
        set -- "$@" -boot start_clean
        set -- "$@" -pa "$CONSOLIDATED_DIR"
        set -- "$@" ${__code_paths}
        set -- "$@" -s "$MODULE" "$FUNCTION"

        "$BINDIR"/erlexec "$@" -extra "$ARGS"
        exit "$?"
        ;;
    reload_config)
        # Reload the running system's configuration
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        run_hooks pre_configure

        shift
        nodetool "reload_config" "$SYS_CONFIG_PATH"
        ;;
    describe)
        ## Print a summary of information about this release
        echo "$REL_NAME-$REL_VSN\n"
        echo "erts:        $ERTS_VSN"
        echo "path:        $REL_DIR"
        echo "sys.config:  $SYS_CONFIG_PATH"
        echo "vm.args:     $VMARGS_PATH"
        echo "name:        $NAME"
        echo "cookie:      $COOKIE"
        echo "erl_opts:    ${ERL_OPTS:-none provided}"
        echo "run_erl_env: ${RUN_ERL_ENV:-none provided}"
        echo ""
        echo "hooks:"
        __has_hooks=0
        for hook in "$REL_DIR"/hooks/*.d/[0-9a-zA-Z]*.sh; do
            [ -f "$hook" ] || continue
            __has_hooks=1
            echo "$hook"
        done
        if [ $__has_hooks -eq 0 ]; then
            echo "No custom hooks found."
        fi
        echo ""
        echo "commands:"
        __has_commands=0
        for command in "$REL_DIR"/commands/*.sh; do
            [ -f "$command" ] || continue
            __has_commands=1
            echo "$command"
        done
        if [ $__has_commands -eq 0 ]; then
            echo "No custom commands found."
        fi
        exit 0
        ;;
    *)
        __command_path="$REL_DIR/commands/$1.sh"
        if [ -f "$__command_path" ]; then
            _check_cookie
            . "$__command_path"
        else
            echo "Usage: $REL_NAME <task>"
            echo
            echo "Service Control"
            echo "======================="
            echo "start                          # start $REL_NAME as a daemon"
            echo "start_boot <file>              # start $REL_NAME as a daemon, but supply a custom .boot file"
            echo "foreground                     # start $REL_NAME in the foreground"
            echo "console                        # start $REL_NAME with a console attached"
            echo "console_clean                  # start a console with code paths set but no apps loaded/started"
            echo "console_boot <file>            # start $REL_NAME with a console attached, but supply a custom .boot file"
            echo "stop                           # stop the $REL_NAME daemon"
            echo "restart                        # restart the $REL_NAME daemon without shutting down the VM"
            echo "reboot                         # restart the $REL_NAME daemon"
            echo "reload_config                  # reload the current system's configuration from disk"
            echo
            echo "Upgrades"
            echo "======================="
            echo "upgrade <version>              # upgrade $REL_NAME to <version>"
            echo "downgrade <version>            # downgrade $REL_NAME to <version>"
            echo "install <version>              # install the $REL_NAME-<version> release, but do not upgrade to it"
            echo
            echo "Utilities"
            echo "======================="
            echo "attach                         # attach the current TTY to $REL_NAME's console"
            echo "remote_console                 # remote shell to $REL_NAME's console"
            echo "pid                            # get the pid of the running $REL_NAME instance"
            echo "ping                           # checks if $REL_NAME is running, pong is returned if successful"
            echo "pingpeer <peer>                # check if a peer node is running, pong is returned if successful"
            echo "escript <file>                 # execute an escript"
            echo "rpc <mod> <fun> [<args..>]     # execute an RPC call using the given MFA"
            echo "rpcterms <mod> <fun> [<expr>]  # execute an RPC call using the given Erlang expression for args"
            echo "eval <expr>                    # execute the given Erlang expression on the running node"
            echo "command <mod> <fun> [<args..>] # execute the given MFA"
            echo "describe                       # print useful information about the $REL_NAME release"
            echo
            echo "Custom Commands"
            echo "======================="
            __has_commands=0
            for command in "$REL_DIR"/commands/*.sh; do
                [ -f "$command" ] || continue
                __has_commands=1
                echo "$command"
            done
            if [ $__has_commands -eq 0 ]; then
                echo "No custom commands found."
            fi
            echo ""
            exit 1
        fi
        ;;
esac

exit 0


Mapping over years

Mapping over years

Yearly Statistics

<%= for s <- @stats do %>
<%= render "statistic_card.html", conn: @conn, stat: s, title: "2018", type: "years" %>
<% end %>

Yearly Statistics

<%= for s <- @stats do %>
<%= render "statistic_card.html", conn: @conn, stat: @s, title: "2018", type: "years" %>
<% end %>


add twitter feed

add twitter feed

<%= gettext "Why Unf Swuber?" %>

It started in parking lot 14; on the way to class I asked a friend if they could give me a ride. the friend was not leaving but also going to class. As a result we walked together and not alone. Later when leaving the library I was forced to walk alone by lack of communication and lack of traffic at that hour.

I did not want to walk to my car. I waited outside the library for someone I knew. Eventually I gave up but the idea was born. Generosity(reputation) and the capital of my parking spot could be used to get me to my car without having to walk alone.

For years people have tried to solve the problem of finding a parking spot at the University of North Florida.

Tweets by SwuberCorp


Add a newline to the home page html

Add a newline to the home page html

<img src='<%= static_path(@conn, "/images/readerl-icon-text.png") %>' alt='ReadErl' width='227' height='48'/>™

An RSS feed aggregator written in Elixir/Phoenix

I'm working on it: github.com/billstclair/readerl

  <%= :erlang.system_info(:system_version) %>

  Erlang: <%= {:ok, version} = :file.read_file(:filename.join([:code.root_dir(), "releases", :erlang.system_info(:otp_release), "OTP_VERSION"])); Regex.named_captures(~r/(?<v>.*)\n*/, version)["v"] %>,
  Elixir: <%= System.version %>,
  Phoenix: <%= {:ok, vsn} = :application.get_key(:phoenix, :vsn); vsn %>


add input field to send chat messages

add input field to send chat messages

<%= gettext "Welcome to %{name}", name: "Phoenix!" %>

A productive web framework that
does not compromise speed and maintainability.

<input id="chat-input" type="text"></input>

Resources

        Guides

        Docs

        Source

Help

        Mailing list

        #elixir-lang on freenode IRC

        @elixirphoenix

<%= gettext "Welcome to %{name}", name: "Phoenix!" %>

A productive web framework that
does not compromise speed and maintainability.

Resources

        Guides

        Docs

        Source

Help

        Mailing list

        #elixir-lang on freenode IRC

        @elixirphoenix


fix typo for subdivision

fix typo for subdivision

Congrats!

Expect a copy of your grant proposal coming from eef-grant-submissions@beam.eco

Grant request process

          Intro
          FAQ
          Form

Introduction

The current focus of the foundation is on increasing and
              expanding the
              community so we will favour grants that are targeted to
              beneficiaries that
              are new to Erlang/Elixir and the ecosystem. We prefer grants that
              support
              online workshops, online training materials, hands-on trainings,
              development
              work (open source) and diversity efforts. On non-beam focused
              events where
              there is a clear Beam language component of the event, the grant
              will only
              support the Beam language component of the event. The EEF will
              consider
              supporting a hackathon if the event has hands-on Beam languages
              education
              for a minimum of 6 hours. We will not fund prizes for hackathons
              or swag.

We recommend that you submit grant proposals via our form at
              least 12
              weeks prior to the event. Proposals should be concise and have a
              clear
              objective. We encourage those applying for funding to try and get
              sponsorship
              from corporations or local sponsors as we want to encourage
              sustainable, long
              term relationships with them.

The EEF could limit the number of events per organizer and/or
              city that are
              granted within a given year. If you have any questions reach out
              to
              education@erlef.org

FAQ

                          <button class="btn btn-link" type="button"
                            data-toggle="collapse"
                            data-target="#accordion-tab-1-content-1"
                            aria-expanded="false"
                            aria-controls="accordion-tab-1-content-1"> When
                            should I submit my grant request?</button>

                          We recommend that grant requests be submitted at least
                          12 weeks before the funding is needed.

                          <button class="btn btn-link" type="button"
                            data-toggle="collapse"
                            data-target="#accordion-tab-1-content-2"
                            aria-expanded="false"
                            aria-controls="accordion-tab-1-content-2">What grant
                            can I ask for organizing a
                            conference?</button>

The maximum conference grant size is typically
                            around 10 USD per
                            attendee. We prefer to help new events get
                            established in their community
                            and we encourage them to apply for different funding
                            local options as well.
                            Bigger conferences might be assigned a lower amount
                            per attendee.
                            Educational programs run within the conference
                            should request a separate
                            budget.

                          <button class="btn btn-link" type="button"
                            data-toggle="collapse"
                            data-target="#accordion-tab-1-content-3"
                            aria-expanded="false"
                            aria-controls="accordion-tab-1-content-3">
                            I am organizing a workshop. What grant can I ask
                            for?
                          </button>

Our maximum educational program grant size is
                            typically USD 25 per
                            student, provided the students each receive at least
                            6 hours of BEAM
                            languages instruction as part of it, however we are
                            open to
                            review this amount on a case by case basis. Please
                            note that
                            subsequent requests for workshops in the same area
                            may be
                            funded at a lower rate to encourage sustainable,
                            long-term
                            relationships with local sponsors.

When submitting your workshop grant request, it
                            helps us to see a brief budget as this example:

                              Items
                              Unit Cost
                              Quantity
                              Total Cost

                                Lunch and drinks
                                9
                                50
                                450

                                Travel expenses
                                20
                                3
                                60

                                Hotel expenses
                                50
                                2
                                100

                                Total

                                610

<button class="btn btn-link" type="button"
                            data-toggle="collapse"
                            data-target="#accordion-tab-1-content-4"
                            aria-expanded="false"
                            aria-controls="accordion-tab-1-content-4">
                            Is there a maximum grant size that can be
                            awarded?</button>

There is no maximum, however bear in mind that the
                            foundation has a limited budget and we reserve the
                            right of giving a grant smaller than requested, let
                            us know if this is a problem for you.

Grant Proposal Form

  <%= form_for @conn, Routes.grant_path(@conn, :create), [id: "grant_form", multipart: true, class: "dropzone"], fn _f -> %>

                  * First name
                  <input type="text" name="first_name" class="form-control"
                    id="first_name" placeholder="First name" required>

                  * Last name
                  <input type="text" class="form-control"
                    id="last_name" name="last_name" placeholder="Last name" required>

                  * Nick Name

                    <input type="text" class="form-control" name="nick_name"
                      id="nick_name" placeholder="Nick Name"
                      aria-describedby="inputGroupPrepend3" required>

                  * Email address
                  <input type="email" name="email_address" class="form-control"
                    id="email_address" aria-describedby="emailHelp"
                    placeholder="Enter email" required>

                  * Phone Number
                  <input type="text" name="phone_number" class="form-control" id="phone_number"
                    placeholder="Phone Number" required>

                  Organization Name
                  <input type="text" name="org_name" class="form-control" id="org_name"
                    placeholder="Organization Name">

                  Organization Email
                  <input type="text" name="org_email" class="form-control" id="org_email"
                    placeholder="Organization Email">

                  * City
                  <input type="text"  name="city" class="form-control"
                    id="city" placeholder="City" required>

                    Please provide a valid city.

                  * Country Subdivision
                  <input type="text" name="subdivision" class="form-control"
                                                     id="subdivision" placeholder="Subdivison" required>
                  ISO 3166-2 code for your country's subdivsion (e.g., state or province)

                  * Postal Code
                  <input type="text" name="postal_code" class="form-control"
                    id="postal_code" placeholder="Postal Code" required>

                  * Country
                  <input type="text" name="country" class="form-control"
                                                    id="country" placeholder="Country" required>
                  ISO 3166-1 for your country

                  Twitter Handle
                  <input type="text" name="twitter" class="form-control" id="twitter"
                    placeholder="Twitter Handle">

                  LinkedIn
                  <input type="text" class="form-control" name="linkedin" id="linkedin"
                    placeholder="LinkedIn">

                  WebSite
                  <input type="text" class="form-control" name="website" id="website"
                    placeholder="WebSite">

                  * Small Bio
                  <textarea class="form-control"
                            id="bio" rows="3"
                                     name="bio"
                                     maxlength="5000"
                    placeholder="Small Bio" required></textarea>

                  * Grant Type
                  <select name="grant_type" class="form-control" id="grant_type" required>
                    <option data-type="none" data-requires-coc="false" value="">--</option>
                    <option data-type="conference" data-requires-coc="true"  value="Conference">Conference</option>
                    <option data-type="devel_work" data-requires-coc="false" value="Development Work">Development Work</option>
                    <option data-type="event_site_sub" data-requires-coc="true" value="Event Site Description">Event Site Description</option>
                    <option data-type="kids_camp" data-requires-coc="true" value="Kids Coding Camp">Kids Coding Camp</option>
                    <option data-type="sprint" data-requires-coc="false" value="Sprint">Sprint</option>
                    <option data-type="training" data-requires-coc="false" value="Training Program">Training Program</option>
                    <option data-type="workshop-edu" data-requires-coc="true" value="Workshop-Education">Workshop-Educational</option>
                    <option data-type="workshop-women" data-requires-coc="true" value="Workgroup-Women">Workshop-Women</option>
                    <option data-type="other" value="Other">Other</option>
                  </select>

A gathering including talks and other events to promote Beam languages in the local community. A separate grant should be submitted for educational programs that are a subset of conference events.

                    Develop a Beam languages-based open source program or library.

                      The subscription cost of a service providing advertising services for Beam languages-related events.

                    Teach aspiring Beam language coders under age 18 coding skills.

                    Development of an open-source project for 2+ days in a team environment.

                    Multiple weeks or month course on Beam languages that is principally hands-on

                    An interactive, hands-on, training into one or more specific Beam languages topics/themes/goals, which supports and mentors women.

                      An interactive, hands-on, training into one or more specific Beam languages topics/themes/goals. It should include at least 6 hours of instruction

                  * Link to code of conduct of the event
                    (required for workshops and conferences)
                  <input id="coc_input" name="code_of_conduct_link" type="text" class="form-control"
                    placeholder="">

                  File attachment(s) :

Click here or drag 'n drop to append file attachments

                  * Purpose

Describe
                    the purpose of the grant, location and date, including the
                    date in which the funds must be received. We recommend to
                    send the requests at minimum 12 weeks before the
                    event so we have enough time to review, ask questions and
                    send you the funds.
                    Make sure you explain how this grant is designed to help
                    grow the community. Also let us know what other forms of
                    sponsorship you have applied for.
                    For workshops/trainings please include the staff:student
                    ratio, the amount of hands-on training time and a lesson
                    plan with learning outcomes for participants.

                  <textarea class="form-control"
                    id="purpose" name="purpose" rows="3"
                    placeholder="Purpose" maxlength="5000" required></textarea>

                      Specify here the grant amount in detail. Please note that
                      the EEF may only be able to provide partial funding for a
                      proposal so let us know if this is acceptable to you. Be
                      sure to include a breakdown of the amount you are
                      requesting. We prefer to see what you plan on using the
                      funds for.
                      Example: 1200$ total ($700 for venue, $300 for trav
                      el, $200 for food). To thank you for your sponsorship, we
                      will place the EEF logo on our site and offer you 3 free
                      tickets to the event to distribute as you see fit.

                  * Amount

                      $

                    <input id="grant_amount" name="grant_amount" type="text" value="" min="0.00" step="1.00"
                      data-number-to-fixed="2" data-number-stepfactor="100"
                      class="form-control currency" required>

                    Preferred payment
                      method
                    <select class="form-control" id="payment_method" name="payment_method" required>
                      <option value="">--</option>
                      <option value="Paypal">Paypal</option>
                      <option value="Zelle">Zelle</option>
                      <option value="Check">Check</option>
                      <option value="Wire">Wire</option>
                    </select>
                    We can do checks only within
                      the US. If the request is for $500 or less, PayPal is
                      suggested.

                      * Beneficiaries

                        Describe who will be the beneficiaries of the grant and
                        the expected size of the event.
                        For onsite events we would love to have an overview of
                        other Beam related
                        activities/meetups/trainings/conferences located in that
                        area, the number of attendees, frequency and such.

                      <textarea class="form-control"
                        id="beneficiaries" name="beneficiaries" rows="3"
                        placeholder="Beneficiaries" maxlength="5000" required></textarea>

                    * Report

The EEF would like to
                      see how the grant was used so we require that we receive a
                      report that will help us understand the impact that the
                      grants are having and how the activities are received
                      by the community. We require to receive this report within
                      one month of the event. Please describe in this section
                      what items you will include on the report and what follow
                      up activities do you plan on. For example: blog posts,
                      post events write-ups, web pages, project updates, lessons
                      learned (what went well and what needs to improve), the
                      feedback from the participants, social media, number of
                      attendees, demographics, and such.

                    <textarea class="form-control"
                              id="report" rows="3"
                                          name="report"
                                          maxlength="5000"
                      placeholder="Report" required></textarea>

                <button id="submit_form" class="btn btn-primary mt-2" type="submit">Submit</button>

            <% end %>

Congrats!

Expect a copy of your grant proposal coming from eef-grant-submissions@beam.eco

Grant request process

          Intro
          FAQ
          Form

Introduction

The current focus of the foundation is on increasing and
              expanding the
              community so we will favour grants that are targeted to
              beneficiaries that
              are new to Erlang/Elixir and the ecosystem. We prefer grants that
              support
              online workshops, online training materials, hands-on trainings,
              development
              work (open source) and diversity efforts. On non-beam focused
              events where
              there is a clear Beam language component of the event, the grant
              will only
              support the Beam language component of the event. The EEF will
              consider
              supporting a hackathon if the event has hands-on Beam languages
              education
              for a minimum of 6 hours. We will not fund prizes for hackathons
              or swag.

We recommend that you submit grant proposals via our form at
              least 12
              weeks prior to the event. Proposals should be concise and have a
              clear
              objective. We encourage those applying for funding to try and get
              sponsorship
              from corporations or local sponsors as we want to encourage
              sustainable, long
              term relationships with them.

The EEF could limit the number of events per organizer and/or
              city that are
              granted within a given year. If you have any questions reach out
              to
              education@erlef.org

FAQ

                          <button class="btn btn-link" type="button"
                            data-toggle="collapse"
                            data-target="#accordion-tab-1-content-1"
                            aria-expanded="false"
                            aria-controls="accordion-tab-1-content-1"> When
                            should I submit my grant request?</button>

                          We recommend that grant requests be submitted at least
                          12 weeks before the funding is needed.

                          <button class="btn btn-link" type="button"
                            data-toggle="collapse"
                            data-target="#accordion-tab-1-content-2"
                            aria-expanded="false"
                            aria-controls="accordion-tab-1-content-2">What grant
                            can I ask for organizing a
                            conference?</button>

The maximum conference grant size is typically
                            around 10 USD per
                            attendee. We prefer to help new events get
                            established in their community
                            and we encourage them to apply for different funding
                            local options as well.
                            Bigger conferences might be assigned a lower amount
                            per attendee.
                            Educational programs run within the conference
                            should request a separate
                            budget.

                          <button class="btn btn-link" type="button"
                            data-toggle="collapse"
                            data-target="#accordion-tab-1-content-3"
                            aria-expanded="false"
                            aria-controls="accordion-tab-1-content-3">
                            I am organizing a workshop. What grant can I ask
                            for?
                          </button>

Our maximum educational program grant size is
                            typically USD 25 per
                            student, provided the students each receive at least
                            6 hours of BEAM
                            languages instruction as part of it, however we are
                            open to
                            review this amount on a case by case basis. Please
                            note that
                            subsequent requests for workshops in the same area
                            may be
                            funded at a lower rate to encourage sustainable,
                            long-term
                            relationships with local sponsors.

When submitting your workshop grant request, it
                            helps us to see a brief budget as this example:

                              Items
                              Unit Cost
                              Quantity
                              Total Cost

                                Lunch and drinks
                                9
                                50
                                450

                                Travel expenses
                                20
                                3
                                60

                                Hotel expenses
                                50
                                2
                                100

                                Total

                                610

<button class="btn btn-link" type="button"
                            data-toggle="collapse"
                            data-target="#accordion-tab-1-content-4"
                            aria-expanded="false"
                            aria-controls="accordion-tab-1-content-4">
                            Is there a maximum grant size that can be
                            awarded?</button>

There is no maximum, however bear in mind that the
                            foundation has a limited budget and we reserve the
                            right of giving a grant smaller than requested, let
                            us know if this is a problem for you.

Grant Proposal Form

  <%= form_for @conn, Routes.grant_path(@conn, :create), [id: "grant_form", multipart: true, class: "dropzone"], fn _f -> %>

                  * First name
                  <input type="text" name="first_name" class="form-control"
                    id="first_name" placeholder="First name" required>

                  * Last name
                  <input type="text" class="form-control"
                    id="last_name" name="last_name" placeholder="Last name" required>

                  * Nick Name

                    <input type="text" class="form-control" name="nick_name"
                      id="nick_name" placeholder="Nick Name"
                      aria-describedby="inputGroupPrepend3" required>

                  * Email address
                  <input type="email" name="email_address" class="form-control"
                    id="email_address" aria-describedby="emailHelp"
                    placeholder="Enter email" required>

                  * Phone Number
                  <input type="text" name="phone_number" class="form-control" id="phone_number"
                    placeholder="Phone Number" required>

                  Organization Name
                  <input type="text" name="org_name" class="form-control" id="org_name"
                    placeholder="Organization Name">

                  Organization Email
                  <input type="text" name="org_email" class="form-control" id="org_email"
                    placeholder="Organization Email">

                  * City
                  <input type="text"  name="city" class="form-control"
                    id="city" placeholder="City" required>

                    Please provide a valid city.

                  * Country Subdivision
                  <input type="text" name="subdivison" class="form-control"
                                                     id="subdivision" placeholder="Subdivison" required>
                  ISO 3166-2 code for your country's subdivsion (e.g., state or province)

                  * Postal Code
                  <input type="text" name="postal_code" class="form-control"
                    id="postal_code" placeholder="Postal Code" required>

                  * Country
                  <input type="text" name="country" class="form-control"
                                                    id="country" placeholder="Country" required>
                  ISO 3166-1 for your country

                  Twitter Handle
                  <input type="text" name="twitter" class="form-control" id="twitter"
                    placeholder="Twitter Handle">

                  LinkedIn
                  <input type="text" class="form-control" name="linkedin" id="linkedin"
                    placeholder="LinkedIn">

                  WebSite
                  <input type="text" class="form-control" name="website" id="website"
                    placeholder="WebSite">

                  * Small Bio
                  <textarea class="form-control"
                            id="bio" rows="3"
                                     name="bio"
                                     maxlength="5000"
                    placeholder="Small Bio" required></textarea>

                  * Grant Type
                  <select name="grant_type" class="form-control" id="grant_type" required>
                    <option data-type="none" data-requires-coc="false" value="">--</option>
                    <option data-type="conference" data-requires-coc="true"  value="Conference">Conference</option>
                    <option data-type="devel_work" data-requires-coc="false" value="Development Work">Development Work</option>
                    <option data-type="event_site_sub" data-requires-coc="true" value="Event Site Description">Event Site Description</option>
                    <option data-type="kids_camp" data-requires-coc="true" value="Kids Coding Camp">Kids Coding Camp</option>
                    <option data-type="sprint" data-requires-coc="false" value="Sprint">Sprint</option>
                    <option data-type="training" data-requires-coc="false" value="Training Program">Training Program</option>
                    <option data-type="workshop-edu" data-requires-coc="true" value="Workshop-Education">Workshop-Educational</option>
                    <option data-type="workshop-women" data-requires-coc="true" value="Workgroup-Women">Workshop-Women</option>
                    <option data-type="other" value="Other">Other</option>
                  </select>

A gathering including talks and other events to promote Beam languages in the local community. A separate grant should be submitted for educational programs that are a subset of conference events.

                    Develop a Beam languages-based open source program or library.

                      The subscription cost of a service providing advertising services for Beam languages-related events.

                    Teach aspiring Beam language coders under age 18 coding skills.

                    Development of an open-source project for 2+ days in a team environment.

                    Multiple weeks or month course on Beam languages that is principally hands-on

                    An interactive, hands-on, training into one or more specific Beam languages topics/themes/goals, which supports and mentors women.

                      An interactive, hands-on, training into one or more specific Beam languages topics/themes/goals. It should include at least 6 hours of instruction

                  * Link to code of conduct of the event
                    (required for workshops and conferences)
                  <input id="coc_input" name="code_of_conduct_link" type="text" class="form-control"
                    placeholder="">

                  File attachment(s) :

Click here or drag 'n drop to append file attachments

                  * Purpose

Describe
                    the purpose of the grant, location and date, including the
                    date in which the funds must be received. We recommend to
                    send the requests at minimum 12 weeks before the
                    event so we have enough time to review, ask questions and
                    send you the funds.
                    Make sure you explain how this grant is designed to help
                    grow the community. Also let us know what other forms of
                    sponsorship you have applied for.
                    For workshops/trainings please include the staff:student
                    ratio, the amount of hands-on training time and a lesson
                    plan with learning outcomes for participants.

                  <textarea class="form-control"
                    id="purpose" name="purpose" rows="3"
                    placeholder="Purpose" maxlength="5000" required></textarea>

                      Specify here the grant amount in detail. Please note that
                      the EEF may only be able to provide partial funding for a
                      proposal so let us know if this is acceptable to you. Be
                      sure to include a breakdown of the amount you are
                      requesting. We prefer to see what you plan on using the
                      funds for.
                      Example: 1200$ total ($700 for venue, $300 for trav
                      el, $200 for food). To thank you for your sponsorship, we
                      will place the EEF logo on our site and offer you 3 free
                      tickets to the event to distribute as you see fit.

                  * Amount

                      $

                    <input id="grant_amount" name="grant_amount" type="text" value="" min="0.00" step="1.00"
                      data-number-to-fixed="2" data-number-stepfactor="100"
                      class="form-control currency" required>

                    Preferred payment
                      method
                    <select class="form-control" id="payment_method" name="payment_method" required>
                      <option value="">--</option>
                      <option value="Paypal">Paypal</option>
                      <option value="Zelle">Zelle</option>
                      <option value="Check">Check</option>
                      <option value="Wire">Wire</option>
                    </select>
                    We can do checks only within
                      the US. If the request is for $500 or less, PayPal is
                      suggested.

                      * Beneficiaries

                        Describe who will be the beneficiaries of the grant and
                        the expected size of the event.
                        For onsite events we would love to have an overview of
                        other Beam related
                        activities/meetups/trainings/conferences located in that
                        area, the number of attendees, frequency and such.

                      <textarea class="form-control"
                        id="beneficiaries" name="beneficiaries" rows="3"
                        placeholder="Beneficiaries" maxlength="5000" required></textarea>

                    * Report

The EEF would like to
                      see how the grant was used so we require that we receive a
                      report that will help us understand the impact that the
                      grants are having and how the activities are received
                      by the community. We require to receive this report within
                      one month of the event. Please describe in this section
                      what items you will include on the report and what follow
                      up activities do you plan on. For example: blog posts,
                      post events write-ups, web pages, project updates, lessons
                      learned (what went well and what needs to improve), the
                      feedback from the participants, social media, number of
                      attendees, demographics, and such.

                    <textarea class="form-control"
                              id="report" rows="3"
                                          name="report"
                                          maxlength="5000"
                      placeholder="Report" required></textarea>

                <button id="submit_form" class="btn btn-primary mt-2" type="submit">Submit</button>

            <% end %>


Display company name small on the access log

This makes it easier to focus on the names of the people accessing the doors

Access Log

<%= if length(@page.entries) > 0 do %>

      Allowed
      Why
      When
      Who
      Where

    <%= for access_attempt <- @page.entries do %>
      <tr class="door_access_attempt_allowed_<%= access_attempt.access_allowed %>">

          <%= if access_attempt.access_allowed do %>

            Yes
          <% else %>
            No
          <% end %>

        <%= access_attempt.reason %>

          <%=
            time_zone = Timex.Timezone.get("America/New_York")
            local_time = Timex.Timezone.convert(access_attempt.inserted_at, time_zone)
            {:ok, time} = Timex.format(local_time, "%a, %b %e @ %l:%M:%S%P", :strftime)
            time
          %>

          <%= if member = access_attempt.member do %>
            <%= link member.name, to: company_member_path(@conn, :show, member.company, member) %>

            <%= link member.company.name, to: company_path(@conn, :show, member.company) %>
          <% else %>
            <%= link "Unassigned Token: #{access_attempt.rfid_token.identifier}", to: rfid_token_path(@conn, :show, access_attempt.rfid_token) %>
          <% end %>

        <%= link access_attempt.door.name, to: door_path(@conn, :show, access_attempt.door) %>

    <% end %>

  <%= pagination_links @page %>
<% else %>

No attempts to access a door

<% end %>

Access Log

<%= if length(@page.entries) > 0 do %>

      Allowed
      Why
      When
      Who
      Where

    <%= for access_attempt <- @page.entries do %>
      <tr class="door_access_attempt_allowed_<%= access_attempt.access_allowed %>">

          <%= if access_attempt.access_allowed do %>

            Yes
          <% else %>
            No
          <% end %>

        <%= access_attempt.reason %>

          <%=
            time_zone = Timex.Timezone.get("America/New_York")
            local_time = Timex.Timezone.convert(access_attempt.inserted_at, time_zone)
            {:ok, time} = Timex.format(local_time, "%a, %b %e @ %l:%M:%S%P", :strftime)
            time
          %>

          <%= if member = access_attempt.member do %>
            <%= link member.name, to: company_member_path(@conn, :show, member.company, member) %> (<%= link member.company.name, to: company_path(@conn, :show, member.company) %>)
          <% else %>
            <%= link "Unassigned Token: #{access_attempt.rfid_token.identifier}", to: rfid_token_path(@conn, :show, access_attempt.rfid_token) %>
          <% end %>

        <%= link access_attempt.door.name, to: door_path(@conn, :show, access_attempt.door) %>

    <% end %>

  <%= pagination_links @page %>
<% else %>

No attempts to access a door

<% end %>