#! /bin/bash # genzaptelconf: generate as smartly as you can: # /etc/zaptel.conf # /etc/asterisk/zapata-channels.conf (to be #include-d into zapata.conf) # update: # /etc/default/zaptel (list of modules to load) # # $Id:$ # # The script uses a number of bash-specific features # TODO: either ditch them or convert to perl # Revision History: # I don't know who the original author of this file is. # but he deserves all the credit for the real work. # # July 25, 2005 - JEB # - Tweak 1.0 # # Aug 15, 2005 - JEB # - Tweak 1.1 # - removed reference to incorrect variables # /etc/default/zaptel may override the following variables lc_country=us #method=ls #method=ks base_exten=6000 ZAPCONF_FILE=/etc/zaptel.conf ZAPATA_FILE=/etc/asterisk/zapata-auto.conf ZAPTEL_BOOT=/etc/default/zaptel exten_base_dir=/etc/asterisk/extensions-phones.d exten_defs_file=/etc/asterisk/extensions-defs.conf ztcfg_cmd=ztcfg # a temporary directory. Created when the switch -r is parsed on getopts # and deleted in the end on update_extensions_defs tmp_dir= # read default configuration from /etc/default/zaptel if [ -r $ZAPTEL_BOOT ]; then . $ZAPTEL_BOOT; fi # work around a bug (that was already fixed) in the installer: if [ "$lc_country" = '' ]; then lc_country=us; fi ALL_MODULES="wctdm wcfxo wcfxs pciradio tor2 torisa wct1xxp wct4xxp wcte11xp wcusb ztd_eth ztdummy" force_stop_ast=no do_detect=no do_unload=no verbose=no rapid_extens='' # global: current extension number in extensions list. Should only be # changed in print_pattern: rapid_cur_exten=1 # set the TRUNK in extensidialplan dialplan defs file rapid_conf_mode=no die() { echo "$@" >&2 exit 1 } say() { if [ "$verbose" = no ]; then return fi echo "$@" >&2 } run_ztcfg() { if [ "$verbose" = no ]; then $ztcfg_cmd "$@" else say "Reconfiguring identified channels" $ztcfg_cmd -vv "$@" fi } do_update() { sed -i.bak "s/^$1=.*\$/$1=\"$2\"/" ${ZAPTEL_BOOT} if ! grep -q "^$1=" ${ZAPTEL_BOOT}; then echo "$1=\"$2\"" >> ${ZAPTEL_BOOT} fi } update_extensions_defs() { if [ "$rapid_conf_mode" = 'yes' ] then say "DEBUG: Updating dialplan defs file $exten_defs_file" if [ "`echo $tmp_dir/fxo_* | grep -v '*'`" != '' ] then trunk_nums=`cat $tmp_dir/fxo_* | sort -n | xargs` say "Configuring TRUNK to be [first of] zaptel channels: $trunk_nums" trunk_dev=`echo $trunk_nums| sed -e 's/ /\\\\\\&/g' -e 's/[0-9a-zA-Z]\+/Zap\\\\\\/&/g'` echo >&2 sed -i "s/^TRUNK.*=>.*/TRUNK => $trunk_dev/" $exten_defs_file sed -i "s/^TRUNK.*=>.*/TRUNK => $trunk_dev/" $exten_defs_file if ! grep -q "^TRUNK =>" $exten_defs_file; then trunk_dev=`echo $trunk_nums| sed -e 's/ /&/g' -e 's/[0-9a-zA-Z]*/Zap\\/&/g'` echo "TRUNK => $trunk_dev" >> $exten_defs_file fi else say "Warning: No FXO channel for trunk. Moving on." fi if [ "`echo $tmp_dir/fxs_* | grep -v '*'`" != '' ] then fxs_nums=`cat $tmp_dir/fxs_* | sort -n | xargs` zap_nums=`grep '^[^;].*Zap/\${CHAN_ZAP_' $exten_base_dir/*.conf | \ sed -e 's/.*Zap\/\${CHAN_ZAP_\([0-9]*\)}.*/\1/' | sort -u | xargs` say "Configuring channels: $fxs_nums as channel placeholders: $zap_nums" j=1 for i in $zap_nums do chan=`echo $fxs_nums | awk "{print \\$$i}"` if [ "$chan" = '' ] then # if the result is empty, we probably got past the last one. # bail out. say "Warning: No FXS channel for CHAN_ZAP_$i. Moving on" break fi say "DEBUG: setting channel $chan to placeholder $i" if grep -q "^CHAN_ZAP_$i " $exten_defs_file then sed -i -e "s/^CHAN_ZAP_$i .*/CHAN_ZAP_$i => Zap\/$chan/" $exten_defs_file else echo "CHAN_ZAP_$i => Zap/$chan" >> $exten_defs_file fi done fi # cleaning up the temp dir if [ -d "$tmp_dir" ]; then rm -rf "$tmp_dir"; fi fi } usage() { program=`basename $0` echo >&2 "$program: generate zaptel.conf" echo >&2 "usage:" echo >&2 " $program [-sdv] [-m k|l|g] [-c ] [-r |-e ] " echo >&2 " $program [-sdv] -l" echo >&2 " $program -su" echo >&2 " $program -h (this screen)" echo >&2 "" echo >&2 "Options:" echo >&2 " -c CODE: set the country code (default: $lc_country)" echo >&2 " -e NUM: set the base extension number (default: $base_exten)" echo >&2 " -m: set signalling method (gs/ks/ls, default: $method)" echo >&2 " -l: output a list of detected channels instead of zaptel.conf" echo >&2 " -d: Perform hardware detection -- update /etc/default/zaptel" echo >&2 " -u: Unload zaptel modules" echo >&2 " -v: verbose" echo >&2 " -s: Don't fail if asterisk is running. Stop it" echo >&2 " -r: rapid configuration mode: configure Zaptel FXS channels from " echo >&2 " existing Rapid extension files. FXOs will all be TRUNK " } # $1: channel number print_pattern() { local chan=$1 local sig=$2 #fxs/fxo local mode=$3 case "$mode" in zaptel) echo "${sig}$method=$chan" ;; list) echo $chan $sig;; zapata) echo "signalling=${sig}_$method" if [ "$sig" = 'fxo' ] then echo "; Note: this is an extension. Create a ZAP extension in AMP for Channel $chan" echo "context=from-internal" echo "rxgain=0" echo "txgain=0" echo "group=1" # to preconfigure channel 1's extension to 550, set # chan_1_exten=550 # in, e.g, /etc/default/zaptel var_name=`echo chan_${chan}_exten` cfg_exten=`echo ${!var_name} | tr -d -c 0-9` var_name=`echo chan_${chan}_vmbox` cfg_vmbox=`echo ${!var_name} | tr -d -c 0-9` var_name=`echo chan_${chan}_cntxt` cfg_cntxt=`echo ${!var_name} | tr -d -c 0-9` # if option -E was given, get configuration from current extension if [ "$rapid_conf_mode" = 'yes' ] then rap_exten=`echo $rapid_extens |awk "{print \\$$rapid_cur_exten}"` if [ "$rap_exten" != '' ] then rap_cfgfile="$exten_base_dir/$rap_exten.conf" if [ -r "$rap_exten" ] then cfg_exten=$rap_exten # the vmbox is the third parameter to stdexten rap_vmbox=`grep '^[^;].*Macro(stdexten' $rap_exten | cut -d, -f3 \ | cut -d')' -f1 | tr -d -c '0-9@a-zA-Z'` if [ "$rap_vmbox" ]!= '' ; then cfg_vmbox=$rap_vmbox; fi fi fi rapid_cur_exten=$(($rapid_cur_exten + 1)) fi if [ "$cfg_exten" = '' ] then # No extension number set for this channel exten=$(($chan+$base_exten)) else # use the pre-configured extension number exten=$cfg_exten fi # is there any real need to set 'mailbox=' ? if [ "x$cfg_vmbox" = x ] then # No extension number set for this channel vmbox=$exten else # use the pre-configured extension number vmbox=$cfg_vmbox fi # echo "callerid=\"Channel $chan\" <$exten>" # echo "mailbox=$exten" else # we have may have set it. So reset it: echo "; Note: this is a trunk. Create a ZAP trunk in AMP for Channel $chan" echo "group=0" echo "context=from-pstn" echo "rxgain=0" echo "txgain=0" # echo "callerid=\"\" <0>" # echo "mailbox=" fi # allows global default settings (e.g. rxgain txgain) to be # be user customized (i.e. won't be lost if you run # genzaptelconf again) echo "#include zapata_custom_chan_default.conf" # allows channel specific customization # e.g. you can set "group=5" for an unused incoming line # e.g. you could have channel specific volume settings echo "#include zapata_custom_chan_$chan.conf" echo "channel => $chan" echo "" # Keep a note of what channels we have identified say "DEBUG: adding to channels list: channel: $chan, sig: $sig" case "$sig" in fxs) echo $chan >$tmp_dir/fxo_$chan say "DEBUG: FXO list now contains: `cat $tmp_dir/fxo_* |xargs`" ;; fxo) echo $chan >$tmp_dir/fxs_$chan say "DEBUG: FXS list now contains: `cat $tmp_dir/fxs_* |xargs`" ;; esac ;; esac } # the number of channels from /proc/zaptel # must always print a number as its output. count_proc_zap_lines() { # if zaptel is not loaded there are 0 channels: if [ ! -d /proc/zaptel ]; then echo '0'; return; fi ( for file in `echo /proc/zaptel/* |grep -v '\*'` do sed -e 1,2d $file # remove the two header lines done ) | wc -l # the total number of lines } load_modules() { say "Test Loading modules:" for i in zaptel $ALL_MODULES do if [ "$i" = ztdummy ]; then continue # No hardware to detect fi lines_before=`count_proc_zap_lines` args="${i}_args" eval "args=\$$args" # a module is worth listing if it: # a. loaded successfully, and # b. added channels lines under /proc/zaptel/* if /sbin/modprobe $i $args 2> /dev/null && \ [ $lines_before -lt `count_proc_zap_lines` ] then probed_modules="$probed_modules $i" say " ok $i $args" else say " - $i $args" fi done } unload_modules() { if pids="$(pgrep asterisk)" [ "$pids" != '' ] then die "Before unloading -- STOP asterisk (pids=$pids)." fi say "Unloading zaptel modules:" modlist='' for i in $ALL_MODULES zaptel do if lsmod | grep "^$i *" > /dev/null; then modlist="$modlist $i" say -n "$i " fi done /sbin/modprobe -r $modlist say '' } detect() { unload_modules load_modules modlist="$probed_modules" #for i in $ALL_MODULES #do # if lsmod | grep "^$i *" > /dev/null; then # modlist="$modlist $i" # fi #done modlist="$(echo $modlist)" # clean spaces if [ "$modlist" = '' ]; then modlist=ztdummy # Fallback fi say "Updating '${ZAPTEL_BOOT}'" do_update ZAPTEL_MODS "$modlist" } check_tdm_sigtype() { chan_num=$1 sig_type=$2 mode=$3 case "$sig_type" in fxs)chan_sig_type=fxo;; fxo)chan_sig_type=fxs;; esac # print_pattern $chan_num $chan_sig_type $mode $ztcfg_cmd -c <(print_pattern $chan_num $chan_sig_type zaptel) 2>/dev/null \ || return 1 if head -c1 /dev/zap/$chan_num >/dev/null 2>/dev/null then print_pattern $chan_num $chan_sig_type $mode return 0 else return 1 fi } # output a list of extensions that need a channel get_rapid_extens() { if [ "$rapid_conf_mode" = 'yes' ] then rapid_extens=`grep -l '^[^;].*Zap/\${CHAN_ZAP_' $exten_base_dir/*.conf 2>/dev/null | \ rev | cut -d/ -f1 | cut -d. -f2- | rev | xargs` say "Need to configure extensions: $rapid_extens" fi } genconf() { local mode=$1 # reset FXO list (global) say "DEBUG: resetting channels lists" rm -f $tmp_dir/fx{s,o}_* if [ "$mode" = 'zapata' ] then rem_char=';' else rem_char='#' fi spanlist=`echo /proc/zaptel/* | grep -v '\*'` #if [ "$spanlist" == "" ]; then # die "No zapata interfaces in /proc/zaptel" #fi case "$mode" in zaptel) cat <&2 "unknown signalling method ${OPTARG}s, defaulting to \"$method\"";; esac ;; s) force_stop_ast=yes ;; r) rapid_conf_mode=yes tmp_dir=`mktemp -d` || die "$0: failed to create temporary directory. Aborting" ;; *) echo >&2 "unknown parameter -$arg, Aborting"; usage; exit 1;; esac done shift $(( $OPTIND-1 )) if [ $# != 0 ]; then echo >&2 "$0: too many parameters" usage exit 1 fi case "$lc_country" in # the list was generated from the source of zaptel: #grep '{.*[0-9]\+,.*"[a-z][a-z]"' zonedata.c | cut -d'"' -f 2 | xargs |tr ' ' '|' us|au|fr|nl|uk|fi|es|jp|no|at|nz|it|gr|tw|cl|se|be|il) :;; *) lc_country=us echo >&2 "unknown country-code $lc_country, defaulting to \"us\"";; esac # any reason for loadzone and defaultzone to be different? If so, this is # the place to make that difference loadzone=$lc_country defaultzone=$loadzone # Choose reasonable default for signaling method (by country) if [ "" = "$method" ]; then case "$lc_country" in il) method=ls ;; *) method=ks ;; esac fi # make sure asterisk is not in our way if [ "$force_stop_ast" = 'yes' ] then # /etc/init.d/asterisk stop 1>&2 /usr/sbin/amportal stop 1>&2 else if ps auxww |grep asterisk | grep -v -- -r | grep -q -v grep then echo >&2 "Asterisk is already running. Configuration left untouched" echo >&2 "You can use the option -s to shut down Asterisk for the" echo >&2 "duration of the detection." exit 1 fi fi if [ "$do_unload" = yes ] then unload_modules exit fi if [ "$do_detect" = yes ] then detect fi if [ "$mode" = list ]; then genconf list else get_rapid_extens say "Generating '${ZAPCONF_FILE}'" mv "${ZAPCONF_FILE}" "${ZAPCONF_FILE}.bak" genconf zaptel > "${ZAPCONF_FILE}" say "Generating '${ZAPATA_FILE}'" mv "${ZAPATA_FILE}" "${ZAPATA_FILE}.bak" genconf zapata > "${ZAPATA_FILE}" run_ztcfg fi if [ "$force_stop_ast" = 'yes' ] then # /etc/init.d/asterisk start 1>&2 /etc/init.d/zaptel stop /etc/init.d/zaptel start /usr/sbin/amportal start 1>&2 fi # if in verbose mode: verify that asterisk is running if [ "$verify" != 'no' ] then say "Checking channels configured in Asterisk:" sleep 1 # give it some time. This is enough on our simple test server ast-cmd cmd "zap show channels" fi