#! /bin/sh # # /usr/sbin/dahdi_span_assignments: # # this script can be used both from udev and # from the command line to assign/unassign and list # current span assignments. # # It uses a configuration file: $DAHDICONFDIR/assigned-spans.conf # (default DAHDICONFDIR=/etc/dahdi) # # The first argument is an action: # "auto" - trigger driver auto_assign attribute for given devices # (no configuration file is used) # "add" - assign (spans which are not already assigned), according # to /etc/dahdi/assigned-spans.conf configuration file # "remove" - unassign spans which are not already unassigned # "list" - human-readable list of all spans (with/without assignments) # "dumpconfig" - dump current assignments in a /etc/dahdi/assigned-spans.conf # compatible format # # Without further arguments, it operates on all existing spans # With one or more sysfs dahdi_devices it is limited to those. # # We may use alternative "keys" for device matching: # * Available keys: # - "hwid" - Hardware id attribute from sysfs # - "@location" - Location attribute from sysfs (embeded inside '<>') # - "/devpath" - The sysfs absolute devpath # # * During "dumpconfig", for each device we take the first available key: # - The preference is: "hwid" or else "@location" or else "/devpath" # - This can be overriden via the SPAN_ASSIGNMENTS_KEY environment variable # or the '{-k|--key} key' command line option. # # * During "add": # - Any key match is valid (hwid/location/devpath) # - Shell globs (wildcards: '*', '?', '[...]') may be optionally used. # # Command line options: # - The '-h|--help' show a usage message. # - The '-n|--dry-run' affects the "add" and "remove" operations. # - The '-v|--verbose' currently shows device matches during "add" operation. # - The '-k |--key ' overrides the SPAN_ASSIGNMENTS_KEY environment # variable. # # Examples: # dahdi_span_assignments list # dahdi_span_assignments add # all unassigned devices # dahdi_span_assignments add /sys/bus/dahdi_devices/devices/astribanks:xbus-00 # dahdi_span_assignments remove # all assigned devices # dahdi_span_assignments -k location dumpconfig # devbase='/sys/bus/dahdi_devices/devices' DAHDICONFDIR="${DAHDICONFDIR:-/etc/dahdi}" DAHDISASSIGNEDSPANSCONF="${DAHDIASSIGNEDSPANSCONF:-"${DAHDICONFDIR}/assigned-spans.conf"}" SPAN_ASSIGNMENTS_KEY=${SPAN_ASSIGNMENTS_KEY:-hwid} dry_run= verbose= usage() { echo >&2 "Usage: $0 [options] action [devpath ...]" echo >&2 " action:" echo >&2 " auto - trigger driver auto_assign attribute for given devices" echo >&2 " add - assign spans, according to /etc/dahdi/assigned-spans.conf" echo >&2 " remove - unassign spans" echo >&2 " list - human-readable list of all spans" echo >&2 " matched - found spans matched in configuration" echo >&2 " unmatched - found spans not matched in configuration" echo >&2 " dumpconfig - dump current state as new configuration" echo >&2 "" echo >&2 " options:" echo >&2 " -h|--help - Show this help" echo >&2 " -n|--dry-run - For 'add/remove' actions" echo >&2 " -v|--versbose - Show matches during 'add' action" echo >&2 " -k|--key - Override prefered key during dumpconfig action" exit 1 } # Parse command line options TEMP=`getopt -o hnvk: --long help,dry-run,verbose,key: -n "$0" -- "$@"` if [ $? != 0 ]; then echo >&2 "Bad options" usage fi # Note the quotes around `$TEMP': they are essential! eval set -- "$TEMP" while true ; do case "$1" in -h|--help) usage ;; -n|--dry-run) dry_run='true' shift ;; -v|--verbose) verbose='true' shift ;; -k|--key) SPAN_ASSIGNMENTS_KEY="$2" shift shift ;; --) shift break ;; *) echo >&2 "Internal error!" exit 1 ;; esac done if [ "$#" -eq 0 ]; then echo >&2 "Missing action argument" usage fi action="$1" shift # Validate SPAN_ASSIGNMENTS_KEY case "$SPAN_ASSIGNMENTS_KEY" in hwid|location|devpath) ;; *) echo >&2 "Bad SPAN_ASSIGNMENTS_KEY='$SPAN_ASSIGNMENTS_KEY' (should be: hwid|location|devpath)" usage ;; esac if [ ! -d "$devbase" ]; then echo >&2 "$0: Missing '$devbase' (DAHDI driver unloaded?)" exit 1 fi # Use given devices or otherwise, all existing devices if [ "$#" -gt 0 ]; then DEVICES="$@" else DEVICES=`ls -d $devbase/* 2>/dev/null` fi # Beware of special characters in attributes attr_clean() { cat "$1" 2>/dev/null | tr -d '\n' | tr '!' '/' | tr -c 'a-zA-Z0-9/:.-' '_' } show_devices() { for device in $DEVICES do devpath=`cd "$device" && pwd -P` location='@'`attr_clean "$device/location"` hardware_id=`attr_clean "$device/hardware_id"` for local_spanno in `cut -d: -f1 "$device/spantype"` do span=`grep 2>/dev/null -Hw "$local_spanno" "$device/span-"*"/local_spanno" | \ sed -e 's,/local_spanno:.*,,' -e 's,.*/,,'` if [ "$span" != '' ]; then spanno=`echo $span | sed 's/^.*-//'` name=`cat 2>/dev/null "$device/$span/name"` basechan=`cat 2>/dev/null "$device/$span/basechan"` else spanno='-' basechan='-' fi printf "%-8s %-14s %s %s\n" "$local_spanno:$spanno:$basechan" "[$hardware_id]" "$location" "$devpath" done | sort -n done } dump_config() { echo '#' echo "# Autogenerated by $0 on `date`" echo "# Map devices + local spans to span + base channel number" echo '' for device in $DEVICES do devpath=`cd "$device" && pwd -P` location=`attr_clean "$device/location"` hardware_id=`attr_clean "$device/hardware_id"` if [ "$SPAN_ASSIGNMENTS_KEY" = 'hwid' -a "$hardware_id" != '' ]; then id="$hardware_id" elif [ "$SPAN_ASSIGNMENTS_KEY" = 'location' -a "$location" != '' ]; then id="@$location" else id="$devpath" fi echo "# Device: [$hardware_id] @$location $devpath" for local_spanno in `cut -d: -f1 "$device/spantype"` do span=`grep 2>/dev/null -Hw "$local_spanno" "$device/span-"*"/local_spanno" | \ sed -e 's,/local_spanno:.*,,' -e 's,.*/,,'` if [ "$span" != '' ]; then spanno=`echo $span | sed 's/^.*-//'` name=`cat 2>/dev/null "$device/$span/name"` basechan=`cat 2>/dev/null "$device/$span/basechan"` printf "%-30s %s\n" "$id" "$local_spanno:$spanno:$basechan" else echo "# Skipped unassigned local span $local_spanno" fi done | sort echo '' done } unassign_all_spans() { for device in $DEVICES do find "$device" -follow -maxdepth 1 -name 'span-*' -type d | \ sort | while read spandir; do local_spanno=`cat "$spandir/local_spanno"` if [ "$dry_run" = true ]; then echo >&2 "(dry-run) unassign $device $local_spanno" continue fi echo >&2 "unassign $device $local_spanno" if ! echo "$local_spanno" > "$device/unassign_span"; then echo >&2 "$0: failed unassigning '$local_spanno' in '$device'" fi done done } # Allow comments and empty lines in config file filter_conf() { sed -e 's/#.*//' -e '/^[ \t]*$/d' "$DAHDISASSIGNEDSPANSCONF" } assign_device_spans() { device="$1" for s in $spanspecs do local_spanno=`echo "$s" | cut -d: -f1` spanno=`echo "$s" | cut -d: -f2` span="$device/span-$spanno" if [ "$dry_run" = true ]; then echo "(dry-run) assign $device: $s" continue fi if [ -d "$span" ]; then span_local_spanno=`cat "$span/local_spanno"` if [ "$span_local_spanno" != "$local_spanno" ]; then echo >&2 "WARNING: $span_local_spanno != $local_spanno" fi echo >&2 "$device [$local_spanno] already assigned to span $spanno. Skipping..." continue fi echo >&2 "assign $device: $s" if ! echo "$s" > "$device/assign_span"; then echo >&2 "$0: failed assigning '$s' to '$device'" fi done } match_device() { device="$1" devpath=`cd "$device" && pwd -P` location='@'`attr_clean "$device/location"` hardware_id=`attr_clean "$device/hardware_id"` filter_conf | while read id spanspecs do # We use case to enable shell-style globbing in configuration case "$hardware_id" in $id) [ "$verbose" = true ] && echo >&2 "match by hwid ($id ~ $hardware_id): $spanspecs" assign_device_spans "$device" ;; esac # We use case to enable shell-style globbing in configuration case "$location" in $id) [ "$verbose" = true ] && echo >&2 "match by location ($id ~ $location): $spanspecs" assign_device_spans "$device" ;; esac # We use case to enable shell-style globbing in configuration case "$devpath" in $id) [ "$verbose" = true ] && echo >&2 "match by devpath ($id ~ $devpath): $spanspecs" assign_device_spans "$device" ;; esac done } assign_devices() { if [ ! -f "$DAHDISASSIGNEDSPANSCONF" ]; then echo >&2 "$0: Missing '$DAHDISASSIGNEDSPANSCONF'" exit 1 fi echo >&2 "using '$DAHDISASSIGNEDSPANSCONF'" for device in $DEVICES do match_device "$device" done } auto_assign_devices() { for device in $DEVICES do echo >&2 "auto-assign $device" if [ "$dry_run" != true ]; then echo 1 > "$device/auto_assign" fi done } dev_match_conf() { local devpath="$1" local location="$2" local hardware_id="$3" local local_spanno="$4" filter_conf | while read id spanspecs do spanno=`echo "$spanspecs" | cut -d: -f1` match_dev=no # We use case to enable shell-style globbing in configuration case "$hardware_id" in $id) match_dev=yes ;; esac # We use case to enable shell-style globbing in configuration case "$location" in $id) match_dev=yes ;; esac # We use case to enable shell-style globbing in configuration case "$devpath" in $id) match_dev=yes ;; esac if [ "$match_dev" = 'yes' -a "$local_spanno" = "$spanno" ]; then #printf "%-8s (%s) %-14s %s %s\n" "$local_spanno" "$spanno" "[$hardware_id]" "$location" "$devpath" echo "[$hardware_id]:$local_spanno" fi done } list_devices() { wanted="$1" if [ ! -f "$DAHDISASSIGNEDSPANSCONF" ]; then echo >&2 "$0: Missing '$DAHDISASSIGNEDSPANSCONF'" exit 1 fi echo >&2 "using '$DAHDISASSIGNEDSPANSCONF'" for device in $DEVICES do devpath=`cd "$device" && pwd -P` location='@'`attr_clean "$device/location"` hardware_id=`attr_clean "$device/hardware_id"` for local_spanno in `cut -d: -f1 "$device/spantype"` do found=`dev_match_conf "$devpath" "$location" "$hardware_id" "$local_spanno"` if [ "$wanted" = "unmatched" ]; then [ -z "$found" ] && echo "[$hardware_id]:$local_spanno" else [ -z "$found" ] || echo "[$hardware_id]:$local_spanno" fi done done } case "$action" in auto) auto_assign_devices ;; add) assign_devices ;; remove) unassign_all_spans ;; list) show_devices ;; dumpconfig) dump_config ;; matched) list_devices "matched" ;; unmatched) list_devices "unmatched" ;; *) echo >&2 "Bad action='$action'" usage ;; esac