Bashing Away

UUASC-LA, 2 May 2002

(hit 'NEXT', 'PREVIOUS' to move between slides)


NEXT
















































































































































































































































Audience and Assumptions


NEXT PREVIOUS
















































































































































































































































korn vrs. bash / Some Differences

Probably obsolete list

functionkornbash
simple outputprintecho
discipline functionsyesno
POSIX character classesyesno
helpnoyes
'cd' spelling correctionnoyes
arithmetic (C-style) foryesno
arithmetic bases2-362-64
array initializationset -A USERVAR value1 ....USERVAR=(value1 ....)
array sizelimitedunlimited
associative arraysyesno
compond arraysyesno

NEXT PREVIOUS
















































































































































































































































shell vrs scripting languages


history file vrs. byte tokens


NEXT PREVIOUS
















































































































































































































































Stopping the bash Shell


NEXT PREVIOUS
















































































































































































































































Invoking the bash Shell


NEXT PREVIOUS
















































































































































































































































Invoking Shell Scripts

Inevitable scripts you will run:


NEXT PREVIOUS
















































































































































































































































/etc/init.d / /etc/rc.* Run Level scripts


NEXT PREVIOUS
















































































































































































































































/etc/profile

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).


#    <- the comment indicator

trap ""  2 3

#     This was suggested by a note in Linux Journal
#     to make it harder to stop the execution of this script
#     trap  =  internal shell command to set response to signals
#     "..." =  'double quoted' string literal, contains commands to run
#     2 3   =  SIGINT SIGQUIT  signals, run kill -l for complete list

PATH="/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games"
#     PATH   =  Search path for commands

if [ "$BASH" ]; then

#     if  <command>     Basic ALGOL derived selection structure
#     then
#     .....
#     elif <command>
#     then
#     .....
#     else
#     .....
#     fi                  "
#
#     [...] =  synonymn for the test command
#     "..." =  'double quoted' string literal,
#              with variable interpolation
#     $     =  variable 'expansion' - access the value
#     BASH  =  pathname of the running instance of bash,
#              one of several miscellaneous shell status variables
#              typically '/bin/bash'
#     ;     =  command seperator

  PS1='\u@\h:\w\$ '
#     PS1 =  basic command line prompt
#     \u  =  user name
#     \h  =  host name up to first '.'
#     \w  =  current working directory
#     \$  =  If the effective UID is 0 print #, otherwise print $

else
# run this branch if not BASH shell

  if [ "`id -u`" -eq 0 ]; then

#  `...`   =  command substitution operators
#             capture the output into a variable,
#             replacing end of lines with blanks

    PS1='# '

#  '...'   =  string literal with no interpolation

  else
    PS1='$ '
  fi
fi

export PATH PS1

#   export  =  move these variables/values into the 'environment'
#              they can now be inherited by child processes

umask 022

#   umask   =  sets file permissions turned off by default when file created

alias ls='/bin/ls -lF '
alias w3m='/usr/bin/w3m -F -M '

#   alias   =  defines a shorthand label for a command
#              trailing blank allows alias to follow alias on command line

export  ls w3m


#  From Tansley, page 190

case $LOGNAME in

#     case $variable in          ALGOL derived selection structure
#     pattern1 )
#     ;;
#     pattern2 )
#     ;;
#     ....
#     * )
#     esac

  dallas )
  ;;

  * )
    PID=${$};  export PID

#   '$' =  Process ID shell variable

#   Original in Tansley:
#   Connected=$( who | awk '{print $1}' | fgrep -xc ${LOGNAME} )
#             $(...)     synonymn for `....`

    Connected=` who | awk '{print $1}' | fgrep -xc ${LOGNAME} `
#     -- modified for Bourne/sh compatibility

    if [ "$Connected" -gt 1 ]
    then
      echo
      echo  'You are logged in more than once.'
      echo
      who -u | grep $LOGNAME
      echo
      echo  'Enter <CR> to exit \c'
      read FRED
      kill -1  $PID
      exit

#     Note that Bash uses 'echo' for most output, not ksh style 'print'

    fi
  ;;

esac

#  End of Tansley

###########################################################
#       runsocks:
###########################################################


#  This part was originally a seperate command for
#  'tricking' normal network client commands to
#  run as 'SOCKSified' through SOCKS proxy servers.
#  (for use with LAFN.org)
#  By incorporating it here, it allowed the commands
#  to be run transparently, without having to
#  prefix every invocation with 'runsocks'.
#  A similar approach might be used for other
#  library version compatability problems.
#
#  Was typically run by:
#  runsocks lynx http://...


#        !/bin/sh
#
# Put the path to the socks shared library in our LD_LIBRARY_PATH so when we
# preload the library, ld.so will find it...
#
if test -n "${SOCKS5_SHLIB_RUNPATH}" ; then
	SOCKS5_SHLIB_RUNPATH="${SOCKS5_SHLIB_RUNPATH}/"
elif test -n "/usr/lib"; then
	SOCKS5_SHLIB_RUNPATH="/usr/lib/"
else
	SOCKS5_SHLIB_RUNPATH="./"
fi

#
# Some OS's use PRELOADS=lib while others use _RLD_LIST=lib:DEFAULT.  Hopefully
# this can handle all those cases.  At any rate, this is basically causing the
# socks5 shared libary to be used to resolve symbols before other libraries,
# hence we get socks's connect before we get libc's connect...
#
# Also, on SunOS 4*, LD_LIBRARY_PATH has no effect on, so we need to put the path
# in front of it.  We make the path overridable with SOCKS5_SHLIB_RUNPATH...
#
case `uname -rs` in
SunOS*4.*)
	LD_PRELOAD=${SOCKS5_SHLIB_RUNPATH}libsocks5_sh.so
	export LD_PRELOAD
	;;
*)
	if test -z "$LD_LIBRARY_PATH" ; then
		LD_LIBRARY_PATH=${SOCKS5_SHLIB_RUNPATH}
	else
		LD_LIBRARY_PATH=${SOCKS5_SHLIB_RUNPATH}:${LD_LIBRARY_PATH}
		export LD_LIBRARY_PATH
	fi

	LD_PRELOAD=libsocks5_sh.so
	export LD_LIBRARY_PATH
	;;
esac
#
# Run the actual program...
#
export LD_PRELOAD
#  exec "$@"

#  This last point is not needed by incorporating these
#  steps in this command.

#    End of RunSOCKS

trap 2 3

#    Resetting signal response to defaults

NEXT PREVIOUS
















































































































































































































































.bash_profile

# ~/.bash_profile: executed by bash(1) for login shells.


umask 002
#    umask set the default permissions turned off with file creation

echo in .bash_profile

# ~/.profile: executed by bash(1) for login shells if .bash_profile
#             not present.

if [ -f ~/.bashrc ]; then
  source ~/.bashrc
#    'source' reads and executes commands in file as if typed in
#             it does not create another shell process
#             synonymn for more cryptic '.'
#             Some languages use '#include', 'load' etc.
fi

#  original:  PATH=/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin
PATH=/usr/local/bin:/usr/bin:/bin
export PATH

CDPATH=/usr/local:~/:
export CDPATH

#  CDPATH  variable, similar to the PATH variable, but it
#          provides directories where the 'cd' command
#          searches if it does not immediately find the
#          directory to switch to.

mesg n
#    mesg   allow/disallow various chat programs to write to terminal

#         below d.e.l. customizations:

set -o vi
#  Setting vi style command editing


LOCKPRG=/usr/bin/lockvc

/usr/bin/screen  -wipe
#  First, clean up the sockets used by screen
#  sometimes they may be in a confused state, not assigning
#  pseudo terminals in the appropriate order.

exec  /usr/bin/screen  -d -RR
#  And finally reconnect to any lost sessions
#  putting screen in place as my 'meta-shell'

NEXT PREVIOUS
















































































































































































































































~/.bashrc

# ~/.bashrc: executed by bash(1) for non-login shells.



CDPATH=/usr/local/:/usr/loca/bin:~/:.:
#  export CDPATH     --  d.e.l.  export apparently not needed
#                                special shell variables.


HISTIGNORE=' *:&'
#  do not log in the history (file) commands with leading spaces,
#  or duplicates of previous commands


# Set up some variables to identify what console is in use:
VCI=$(tty)
export VCI
VC=${VCI#?*/}
#     Note:  '#?*/' part of variable expansion strips out
#                   leading parts of variable to the first '/'
export VC
#   end of console variable setting

# Now include in one in the prompt:
export PS1="\n\e[7m\e[24;1H  \d | \@ | \h | $VC | \u | \s | \! | \# |\
       \e[0m\n\
  \w \$  "

#     PS1 / Main prompt special sequences used:

# \n             =  newline escape
# \e             =  the escape character (^[ / C-[ / Cntl-[)
# \e[7m          =  go to reverse video (ANSI escape sequence)
# \e[24;1H       =  move cursor to line 24, row 1 (ANSI escape sequence)
# \d             =  date
# \@             =  time in 12 hour am/pm format
# \h             =  host name up to first '.'
# $VC            =  tty console name (see above)
# \u             =  current user name
# \s             =  name of the shell (bash :-) )
# \!             =  history number of current command
# \#             =  command number of the current command
# \e[0m          =  restore normal video (ANSI escape sequence)
# \w             =  the current working directory
# \$             =  if effective uid=0,'#', otherwise literal '$'

#      -- See O'Reilly bash book, 2nd edition p. 71-72 for complete list.


#  PROMPT_COMMAND='echo -n ^[[0J'
PROMPT_COMMAND=''

umask 022
set -o vi

#  SHOPT  settings, defualts unless otherwise stated ************************
#  NOTE:  'ad:'  == 'apparent default:'
#
#  ad:  shopt -u cdable_vars
shopt -s cdable_vars
#    These variables require no leading '$' for interpretation, so
#    this adds greatly to the capability of the 'cd' command
#    allowing simple '&lt;variable&gt;=&lt;dir&gt;'  definitions to make quick shortcuts

#  ad: shopt -u cdspell
shopt -s cdspell
#  --  This checks, and corrects for slop in directory spelling.

#  ad:  shopt -u checkhash
shopt -s checkhash
#  --  this shouldn't cause any problem, and might speed things up,
#      so why not?
#      it provides a sticky-bit like feature for shell functions

#  ad:  shopt -u checkwinsize
shopt -s checkwinsize
#  -- Keep COLUMNS and LINES updated, seems a good idea when splitting
#     the screen with 'screen'.

shopt -s cmdhist
#  -- bash attempts to save all lines of
#     a multiple-line command in the same history entry.
#     This  allows  easy  re-editing  of multi-line commands.

#  ad:  shopt -u dotglob
shopt -s dotglob
#  -- Look at *all* the files by default.
#     including those hidden with leading '.' in name

#  ad:  shopt -u execfail
shopt -s execfail
#     so exec will not cause failure

#  apparent default:  shopt -u expand_aliases
shopt -s expand_aliases
#     to expand aliases in scripts

#  ad:  shopt -u extglob
shopt -s extglob
#    -- to enable *(...), +(...), @(...), ?(...), !(...) patterns

shopt -u histreedit
shopt -u histappend
shopt -u histverify
shopt -s hostcomplete
shopt -u huponexit
shopt -s interactive_comments
shopt -u lithist
shopt -u mailwarn
shopt -u nocaseglob
shopt -u nullglob
shopt -s promptvars
shopt -u restricted_shell
shopt -u shift_verbose
shopt -s sourcepath
#  END of SHOPT settings  ****************************************

export HISTFILESIZE=1000

#  Start Aliases **********************************************************

# You may uncomment the following lines if you want `ls' to be colorized:
# export LS_OPTIONS='--color=auto'
# eval `dircolors`
# alias ls='ls $LS_OPTIONS'
# alias ll='ls $LS_OPTIONS -l'
# alias l='ls $LS_OPTIONS -lA'
#
# Some more alias to avoid making mistakes:
# alias rm='rm -i'
# alias cp='cp -i'
# alias mv='mv -i'

#  From  'The UNIX Companion' p. 187
alias a='alias'

#  From  'The UNIX Companion' p. 641 -642
a ls='ls -F'
a ll='ls -l'
a la='ls -a'
a lla='ls -la'

#  because this seems very usefull to me,
a reference='lynx /var/cache/www/refdesk.html'
a refdesk='lynx   /var/cache/www/refdesk.html'
a m-w='lynx       /var/cache/www/m-w.html'
#   cd ~/download ; lynx -source  http://www.refdesk.com  >  refdesk.html


#  quoting and escaping is critical on this (both of these worked):
alias base642txt="perl -MMIME::Base64  -pe '\$_=decode_base64(\$_)'"

alias lynx='/usr/bin/lynx -image_links '


#  End Aliases **********************************************************


#  Start Functions **********************************************************

cdcleanup ()  {

if [[ 0 != $? ]]
then
  POSSDIR=${_##*;}
  #   $_  =  last argument to previous command
  #   '##*;'  strips out maximum length leading string that includes
  #           a trainling ';' command seperator
  if [[ -n ${POSSDIR} ]]
  then
    echo "Changing to directory: ${POSSDIR}"   2> /dev/null
    cd  ${POSSDIR}   2> /dev/null
  fi
fi

#  Possibly put some other function calls etc. here....

}

PROMPT_COMMAND=cdcleanup
#  -- to execute function cdcleanup automaticly
#     it may be necessary to nest other function calls inside
#     cdcleanup if further automatic execution fuctionality
#     is needed.


#  End Functions **********************************************************

export LANG=C

export FTP_PASSIVE=1
#  to make Net::FTP work behind my ipchains/packet filtering firewall

#   To make sure lynx works properly:
ln -sf  ~/.lynxrc.works  ~/.lynxrc


NEXT PREVIOUS
















































































































































































































































Wild PS1 'Screenshot'

(Thanks to the wonders of 'screen')


  Sun May  5 | 08:16pm | dxmcgyver | pts/5 | dallas | bash | 900 | 17 |
  ~/download $

  Sun May  5 | 08:16pm | dxmcgyver | pts/5 | dallas | bash | 900 | 17 |
  ~/download $

  Sun May  5 | 08:16pm | dxmcgyver | pts/5 | dallas | bash | 900 | 17 |
  ~/download $

  Sun May  5 | 08:16pm | dxmcgyver | pts/5 | dallas | bash | 900 | 17 |
  ~/download $

  Sun May  5 | 08:16pm | dxmcgyver | pts/5 | dallas | bash | 900 | 17 |
  ~/download $

  Sun May  5 | 08:16pm | dxmcgyver | pts/5 | dallas | bash | 900 | 17 |
  ~/download $  ls my*.txt
my0102a.txt  my0302a.txt  my0402a.txt  my0502a.txt  myaddr1.txt
my0102b.txt  my0302b.txt  my0402b.txt  my0502b.txt  mysug1.txt
my0202a.txt  my0302c.txt  my0402c.txt  myaddr.txt

  Sun May  5 | 08:17pm | dxmcgyver | pts/5 | dallas | bash | 901 | 18 |
  ~/download $  _


NEXT PREVIOUS
















































































































































































































































~/.bash_logout

I really don't have any example here, but it is available. It might be used to cleanup temporary files or personal recording of session time.


NEXT PREVIOUS
















































































































































































































































emacs vrs. vi editing

Your choice:
NEXT PREVIOUS
















































































































































































































































10 Basic emacs editing commands

Suggested by O'Reilly bash book:

CTRL-A Start of line
CTRL-E End of line
CTRL-F Forward one character
CTRL-B Backward one character
CTRL-D/DEL Delete one character
CTRL-K Kill line
CTRL-P Previous command in history
CTRL-N Next command in history
CTRL-R Search for command in history
CTRL-I/TAB File name completion

NEXT PREVIOUS
















































































































































































































































bind

\C-Control key prefix
\M-Escape/Meta key prefix
\eEscape character
\\\
\""
\''

NEXT PREVIOUS
















































































































































































































































~/.inputrc

# /etc/inputrc - global inputrc for libreadline
# See readline(3readline) and `info readline' for more information.

# Be 8 bit clean.
set input-meta on
set output-meta on

# To allow the use of 8bit-characters like the german umlauts, comment out
# the line below. However this makes the meta key not work as a meta key,
# which is annoying to those which don't need to type in 8-bit characters.

# set convert-meta off

#   Start  D.E.L. customizations:
$if bash
$if mode=vi
#  from 'Learning the Bash Shell', 1rst ed., p. 58
set keymap vi-command
Control-a: beginning-of-line
Control-e: end-of-line
Control-f: forward-char
Control-b: backward-char

Control-d: delete-char
#  Control-c: reverse-search-history
Control-c: kill-whole-line

Control-p: previous-history
Control-n: next-history

Control-r: reverse-search-history
#  TAB: reverse-search-history
TAB: complete

set keymap vi-insert

#  These basic emacs motions/commands don't seem to conflict
#  with vi insert mode, so why not?

Control-a: beginning-of-line
Control-e: end-of-line
Control-f: forward-char
Control-b: backward-char

Control-d: delete-char
#  Control-c: reverse-search-history
#  Control-c: kill-whole-line

Control-p: previous-history
Control-n: next-history

Control-r: reverse-search-history
#     TAB: complete

$endif
$endif
#   End of D.E.L. customizations:


NEXT PREVIOUS
















































































































































































































































Ways to Run Non-Special Scripts


NEXT PREVIOUS
















































































































































































































































Comments


NEXT PREVIOUS
















































































































































































































































Variables


NEXT PREVIOUS
















































































































































































































































Positional Parameters


NEXT PREVIOUS
















































































































































































































































Built-In Variables


NEXT PREVIOUS
















































































































































































































































Local Variables

variable=value


NEXT PREVIOUS
















































































































































































































































Environmental Variables

export somevariable


NEXT PREVIOUS
















































































































































































































































Quoting: String Literals

\ single following character quoted
'...' string literal, no interpolation
"..." string literal, interpolates
`...` -> should be using $(...) command output to string, interpolates
$(< file ) file contents into a string
$((...arithmetic...)) creates a number string
number literals:
  • number (base defaults to '10' (ten, 9+1)
    example: 13
  • base#number ('number' in 'base') inside ((..))'s
    example: 8#15 # still thirteen

NEXT PREVIOUS
















































































































































































































































fc Command


NEXT PREVIOUS
















































































































































































































































Turing Completness Features


NEXT PREVIOUS
















































































































































































































































Turing Completness: Sequential Execution of Commands


NEXT PREVIOUS
















































































































































































































































Turing Completness: Selective Execution of Commands


NEXT PREVIOUS
















































































































































































































































if


    if [ ..globbing test.. ]                      # required
    then                                          # required
      ...
    elif [[ ..pattern test.. ]]
    then
      ...
    elif (( ..math test.. ))  ; then
#                                   ------   a common idiom
      ...
    else
      ...
    fi                                            # required


NEXT PREVIOUS
















































































































































































































































case


case variable in
pattern1 ) ....
                  ;;    # == 'break'
pattern2 ) ....
                  #  ;;  -- now fall through to pattern3
pattern3 | pattern4 ) ....
                  ;;
* ) ....                # 'else/otherwise'
   ......
esac


NEXT PREVIOUS
















































































































































































































































Case example


Excerpted from an e-mail script.

case $KMHIST1 in
#          Take care of network specifier dollar 1
#
#  print  'A - Usenet (via alpha.jpunix.com)'
  'A' | 'a' )
#               KMPREFIX='INT:M2N\45\V(NDATE)\45'
                KMPREFIX=${form}'M2N\45\V(NDATE)\45'
#  REM         \V(NDATE) IS A KERMIT TIME/DATE VARIABLE THAT
#  REM              PRODUCES THE YYYYMMDD REQUIRED BY
#  REM              THIS TYPE OF MAIL TO NEWS GATEWAYS
                KMPOSTFIX='@ALPHA.JPUNIX.COM'
                KADDR="$1"
                shift
                ;;

#  print  'B - Usenet (nospam via alpha.jpunix.com)'
  'B' | 'b' )
#               KMPREFIX='INT:M2N_NOSPAM\45\V(NDATE)\45'
                KMPREFIX=${form}'M2N_NOSPAM\45\V(NDATE)\45'
#  REM         \V(NDATE) IS A KERMIT TIME/DATE VARIABLE THAT
#  REM              PRODUCES THE YYYYMMDD REQUIRED BY
#  REM              THIS TYPE OF MAIL TO NEWS GATEWAYS
              KMPOSTFIX='@ALPHA.JPUNIX.COM'
              KADDR="$1"
              shift
              ;;



#  print  'D - distribution list'
  'D' | 'd' )
                KMPREFIX=''
                KADDR="$1"
                shift
                ;;

#  print  'F - forum'
  'F' | 'f' | '\' )
                KMPREFIX='\'
                KADDR="$1"
                shift
                ;;


#  print  'I - Internet (U.S.A./Canada/United Kingdom/Germany)'
  'I' | 'i' | 'INT:' )
#                      KMPREFIX='INT:'
                       KMPREFIX=${form}

#  REM  CHECK NOW FOR A COMMON ADDRESS ERROR:
                       case $1 in
                         ?*@?*  ) :  ;  ;;
                         *            ) noatsign   $1  ;  return 13  ; ;;
                       esac

                       case ${1##*.} in
                         [Cc][Oo][Mm] )  : ;;
                         [Gg][Oo][Vv] )  : ;;
                         [Ee][Dd][Uu] )  : ;;
                         [Oo][Rr][Gg] )  : ;;
                         [Nn][Ee][Tt] )  : ;;
                         [Mm][Ii][Ll] )  : ;;
                         [Uu][Ss]     )  : ;;
                         [Cc][Aa]     )  : ;;
                         [Uu][Kk]     )  : ;;
                         [Dd][Ee]     )  : ;;
                         [Nn][Ll]     )  : ;;
                         *            )
                           print
                           print -r "   %2, Which you gave as the Internet address,"
                           print -r "       \i\s not valid - it does not have a valid domain."
                           print
                           kmdereg  13
                           return 13
                           ;;
                       esac
                       KADDR="$1"
                       shift

                       ;;
##################################################


#  print  'J - Internet (Rest of the World)'
  'J' | 'j' | 'INT:' )
#                      KMPREFIX='INT:'
                       KMPREFIX=${form}
#                      REM  CHECK NOW FOR A COMMON ADDRESS ERROR:
                       case $1 in
                         ?*@?* )  : ;;
                         *   )  noatsign  $1  ;  return 13 ;;
                        esac

                        case $1 in
                          *[.]* )  : ;;
                          *     )  print
                                   print -r "   $1, Which you gave as the Internet address,"
                                   print -r "      is not valid - it does not have a '.'"
                                   print
                                   kmdereg  13
                                   return 13
                                    ;;
                        esac
                        KADDR="$1"
                        shift
                        ;;

#  print  'L - local'
  'L' | 'l' )
                KMPREFIX=''
                KADDR="$1"
                shift
                ;;


#  print  'M - Major Net'
  'M' | 'm' | 'ML:' )
                KMPREFIX='ML:'
                KADDR="$1"
                shift
                ;;



#  print  'N - FAXinet               ###10DigitFAX###+Full_Name'
  'N' | 'n'  )
#               KMPREFIX='INT:'
                KMPREFIX=${form}
#  REM   ###10DIGITFAX###+Full_Name
#  REM    _ = SPACE
#  REM  CHECK NOW FOR A COMMON ADDRESS ERROR:
#  REM * ECHO %2 | FIND "+"  >  %SCRATCH%:\FQTEST.TMP
                case $1 in
                  *[+]*  )  :  ;;
                  *    )  print
                          print 'Not a valid Faxinet address... '
                          print
                          kmdreg
                esac

                case ${1##*[+]} in
                  [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ) : ;;
                  * ) print
                      print -r 'Not a valid Faxinet 10 digit number'
                      print
                      kmdereg  13
                      return 13
                      ;;
                esac
                KMPOSTFIX='+5111@FAX.AWA.COM'
                KADDR="$1"
                shift
                ;;

#  print  'P - FidoNet               Zone:Net/Node.Point'
  'p' | 'P'  )
#               KMPREFIX="INT:${1}@"
                KMPREFIX="${form}${1}@"
                shift
                zonenet=${1%%/[0-9.]*}
                zone=${zonenet%%:[0-9]*}
                net=${zonenet##[0-9]*:}
                fnodepoint=${1##[0-9:]*/}
                fnode=${fnodepoint%%.[0-9]*}
                point=${fnodepoint##[0-9]*.}
                for i in $zone $net $fnode $point
                do
                  case $i in
                    [0-9]* ) : ;;
                    * )  print
                         print 'Improper FidoNet address'
                         print
                         return 13
                         ;;
                  esac
                done
                KADDR=p${point}.f${fnode}.n${net}.z${zone}
                KMPOSTFIX='.fidonet.org'

                unset -v zonenet
                unset -v zone
                unset -v net
                unset -v nodepoint
                unset -v node
                unset -v point
                shift
                # for testing
                print $KMPREFIX
                print $KADDR
                print $KMPOSTFIX
                exit      # to test
                ;;





#  print  'T - TPC FAX gateway       Full_Name/Rm_###@###11DigitFAX###'
  'T' | 't' )
#              KMPREFIX='INT:remote-printer.'
               KMPREFIX=${form}'remote-printer.'
#  REM   FULL_NAME@###11DigitFAX####
#  REM    _ = SPACE, /=NEWLINE IN USERNAME (suggested for Rm. #
#  REM  CHECK NOW FOR A COMMON ADDRESS ERROR:
               case $1 in
                 ?*@?*  )  :  ;;
                 *      )  noatsign  $1  ;  return 13  ;;
               esac

               case ${1##*@} in
                 1[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ) : ;;
                 * ) print
                     print -r 'Not a valid TPC 11 digit number'
                     print
                     kmdereg  13
                     return 13
                     ;;
               esac
               KMPOSTFIX='.iddd.tpc.int'
               KADDR="$1"
               shift
               ;;

###############################

#  print  'U - Usenet (via MIT)'
  'U' | 'u' )
#               KMPREFIX='INT:MAIL2NEWS\45\V(NDATE)\45'
                KMPREFIX=${form}'MAIL2NEWS\45\V(NDATE)\45'
#  REM         \V(NDATE) IS A KERMIT TIME/DATE VARIABLE THAT
#  REM              PRODUCES THE YYYYMMDD REQUIRED BY
#  REM              THIS TYPE OF MAIL TO NEWS GATEWAYS
               KMPOSTFIX='@ANON.LCS.MIT.EDU'
               ;;

#  print  'V - Usenet (nospam via MIT)'
  'V' | 'v' )
#               KMPREFIX='INT:MAIL2NEWS_NOSPAM\45\V(NDATE)\45'
                KMPREFIX=${form}'MAIL2NEWS_NOSPAM\45\V(NDATE)\45'
#  REM         \V(NDATE) IS A KERMIT TIME/DATE VARIABLE THAT
#  REM              PRODUCES THE YYYYMMDD REQUIRED BY
#  REM              THIS TYPE OF MAIL TO NEWS GATEWAYS
              KMPOSTFIX='@ANON.LCS.MIT.EDU'
              KADDR="$1"
              shift
              ;;

#  print  'W - World Link'
  'W' | 'w' | 'WL:' )
                KMPREFIX='WL:'
                KADDR="$1"
                shift
                ;;



#  print  'X - Faxaway               Full_Name.###11DigitFAX###'
  'X' | 'x' )
#              KMPREFIX='INT:'
               KMPREFIX=${form}
#  REM   FULL_NAME.###11DigitFAX###
#  REM    _ = SPACE
#  REM  CHECK NOW FOR A COMMON ADDRESS ERROR:
              case $1 in
                *1[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ) : ;;
                * ) print
                    print -r 'Not a valid Faxaway 11 digit number'
                    print
                    kmdereg  13
                    return 13
                    ;;
              esac
              KMPOSTFIX='@FAXAWAY.COM'
              KADDR="$1"
              shift
              ;;


#  print  'Z - Usenet (via ZIPPO)'
  'Z' | 'z' )
#               KMPREFIX='INT:POST\45'
                KMPREFIX=${form}'POST\45'
#  REM           Another mail to Usenet gateway.
                KMPOSTFIX='@NEWSPOST.ZIPPO.COM'
                ;;

#  GOTO NONET
  *         )  print
#  :NONET
               print  -r 'You failed to specify a Network:'
               print
               kmnetlist
               return
               KADDR="$1"
               shift
               ;;
esac

NEXT PREVIOUS
















































































































































































































































Turing Completness: Iterative Execution of Commands


NEXT PREVIOUS
















































































































































































































































while


while [[ ... ]] && [[ ... ]] || (( ..math test.. ))
do
....
done

Example:

 while read file ; do echo ${file%%.raw} ; done  < mail.lst


NEXT PREVIOUS
















































































































































































































































until


until ls | grep auntie | wc
do
....
done


NEXT PREVIOUS
















































































































































































































































for


for variable in value1 value2 ... valuex
do
....
....
done < something

Example:

 for file in $(< mail.lst ) ; do  echo ${file%%.raw} ; done


NEXT PREVIOUS
















































































































































































































































select (Menus)


    PS3='What do you want?'
#         -- defaults to '#?'

    #  Note 'for' like syntax:
    select some_variable in value1 value2 ... valuex
    do
    ....
    echo $some_variable $REPLY
      case some_variable in
      value1 )
         echo "$some_variable, the value1 picked"
         ;;
      value2 )
         echo "$REPLY, the number picked"
         ;;
      * )
         break
         ;;
      esac

    done


Discussion in Blog Narrative and script comments at http://isthereanotherquestion.blogspot.com/2008/06/lynx-http-external-menu-script.html
NEXT PREVIOUS
















































































































































































































































Getopts - Script Option Processing


  while getopts ':ab:c'  opt
  do
    # leading  ':' or OPTERR=0 turns off weird error message
    #  for invalid options

    case  $opt  in
    a ) process option -a       ;;
    b ) process option -b
        ...$OPTARG...       ;;
        #  ':' following b indicates an argument stored in OPTARG
    c ) process option -c       ;;
    \? ) echo $USAGE ; exit       ;;
    esac
  done

  shift  $(( $OPTIND  -  1 ))
  #  --  a piece of boilerplate to sweep options out of the way
  #      typically leaving file names


NEXT PREVIOUS
















































































































































































































































Aliasing


NEXT PREVIOUS
















































































































































































































































Functions


    function  something
    {
    local myvar='avalue'
    ....
      return 1
    ....
    return 0
    }

    otherthing ()
    {
    local yourvar
    ....
    return n  ;
    }


NEXT PREVIOUS
















































































































































































































































Alias/Function Examples


# .kshrc for OS/2 version of ksh
#  NOW CALLED os2.ksh  -- d.e.l. 30/10/98

#  the below 4 lines expriment for shelling from k2
# if [[ $1 = '/C:' ]]
# then
# shift
# fi

set -o trackall
set -o ignoreeof
#   set -o noglob
set +o noglob


alias a:='cd a:.'
alias b:='cd b:.'
alias c:='cd c:.'
alias d:='cd d:.'
alias e:='cd e:.'
alias f:='cd f:.'
alias g:='cd g:.'
#         Below (to z:) added by D.E.L.   25/10/98
alias h:='cd h:.'
alias i:='cd i:.'
alias j:='cd j:.'
alias k:='cd k:.'
alias l:='cd l:.'
alias m:='cd m:.'
alias n:='cd n:.'
alias o:='cd o:.'
alias p:='cd p:.'
alias q:='cd q:.'
alias r:='cd r:.'
alias s:='cd s:.'
alias t:='cd t:.'
alias u:='cd u:.'
alias v:='cd v:.'
alias w:='cd w:.'
alias x:='cd x:.'
alias y:='cd y:.'
alias z:='cd z:.'
#         end of alias added by D.E.L. 25/10/98

alias h='fc -l'
alias j='jobs'
#alias which='type'
alias back='cd -'
alias cls='print -n "\033[H\033[2J"'

alias dir='cmd /c dir'
alias del='cmd /c del'
alias copy='cmd /c copy /v'
#  alias start='cmd /c start'
function start {
   cmd /c $*  &
}

# d.e.l. alias ll='ls -lsAFk'
# d.e.l. alias lf='ls -CAFk'
# d.e.l. alias cp='cp -p'
# d.e.l. alias ls='ls -F'

# d.e.l. clock_p () {
# d.e.l. PS1='${__[(H=SECONDS/3600%24)==(M=SECONDS/60%60)==(S=SECONDS%60)]-$H:$M:$S}>'
# d.e.l. typeset -Z2 H M S; let SECONDS=`date '+(%H*60+%M)*60+%S'`
# d.e.l. }

unalias login newgrp

if [ "$KSH_VERSION" = "" ]
then PS1='$PWD>'
     return
fi

set -o emacs
# d.e.l. bind ^Q=quote
# d.e.l. bind ^I=complete
## d.e.l. bind ^[^[=list-file

#The next four have been preprogrammed
# d.e.l. bind ^0H=up-history
# d.e.l. bind ^0P=down-history
# d.e.l. bind ^0K=backward-char
# d.e.l. bind ^0M=forward-char

# d.e.l. bind ^0s=backward-word
# d.e.l. bind ^0t=forward-word
# d.e.l. bind ^0G=beginning-of-line
# d.e.l. bind ^0O=end-of-line
# d.e.l. bind ^0w=beginning-of-history
# d.e.l. bind ^0u=end-of-history
# d.e.l. bind ^0S=eot-or-delete


typeset -u RW=${RUNWORKPLACE%%.EXE*}
RW=${RW##*\\}
case  ${RW} in
  EMACS )
          FCEDIT=emacsclient
          EDITOR=emacsclient
          VISUAL=emacsclient
           ;;
     *  )
          FCEDIT=t2
          EDITOR=t2
          VISUAL=t2
           ;;
esac
unset RW
#    PS1='[!]$PWD: '
#    PS1='[$$:!]$PWD: '     #  B. Rosenberg, p. 297 suggested change
PS1='[$PPID:$$:!:$!!]$PWD: '     #  B. Rosenberg, p. 297 suggested change
# done for a test PS1='[$!!]$PWD: '     #  B. Rosenberg, p. 297 suggested change
#                       ###---needed for the value of '$!' - shell
#                                     changes mere $! to $<some#>
function pushd {
        if [ $# -eq 0 ]
        then    d=~
                set -A dirstk ${dirstk[*]} $PWD
                cd $d
        else    for d in $*
                do      if [ -d $d ] && [ -r $d ] && [ -x $d ]
                        then    set -A dirstk ${dirstk[*]} $PWD
                                cd $d
                        else    echo "$d: Cannot change directory"
                                break
                        fi
                done
        fi
        echo ${dirstk[*]} $PWD
        unset d ;
}

function popd {
        if [ ${#dirstk[*]} -gt 0 ]
        then    let n=${#dirstk[*]}-1
                cd ${dirstk[$n]}
                unset dirstk[$n]
                echo ${dirstk[*]} $PWD
        else    echo "popd: Directory stack empty"
        fi
        unset n ;
}

###################################### below stuff added by D.E.L.

function find {
#   d.e.l. 31/10/98  part of fix for find problem
#    echo ${@+"$@"}
#    echo $3

#    f.cmd  ${*+"$*"}
#     print ${*+"$*"}
#     f.cmd  ${*+"$*"}
#     f.cmd  ${*+"$*"}
#     f.cmd  $*
#     print  ${*+"$* "}
     f.cmd  ${*+" $* "}
     #           A--A------ note that spaces here is critical
     #                         or strip in ReXX wrapper function
     #                            will strip the parameter of needed quotes
}

#  function find {
#  #       d.e.l.  30/10/98     part of fix for find problem
#    target=$1
#    shift
#    prs=''
#    while [[ ! $1 = '' ]]
#    do
#      prs="$prs $1"
#      shift
#  #   echo "f.cmd $target $prs"
#      f.cmd  $target $prs
#    done
#
#  }

# alias dir='set +o noglob ; cmd /c dir ; set -o noglob'

function  head
{
typeset -i lines
case $1 in
  [1-9]*([0-9])  )  (( lines = $1 ))
                    shift
                    ;;
  -[1-9]*([0-9]) )  (( lines = 0 - $1 ))
                    shift
                    ;;
  [0-]           )  (( lines = 10  ))
                    shift
                    ;;
  ''             )  (( lines = 10 ))
                    ;;
  *              )  (( lines = 10  ))
                    ;;
esac

for file
do
  sed  "$lines""q"  $file
done
unset file

}

function tail
{

typeset -i lines
case $1 in
  [1-9]*([0-9])  )  (( lines = $1 + 1 ))
                    shift
                    ;;
  -[1-9]*([0-9]) )  (( lines = 0 - $1 + 1 ))
                    shift
                    ;;
  [0-]           )  (( lines = 11 ))
                    shift
                    ;;
  ''             )  (( lines = 11 ))
                    ;;
  *              )  (( lines = 11  ))
                    ;;
esac


# print last 10 lines of file (emulates "tail")
# sed -e :a -e '$q;N;11,$D;ba'


for file
do
# print last 10 lines of file (emulates "tail")
  sed -e ":a; \$q;N;$lines,\$D;ba" $file
done
unset file
}

function rev {
if [[ $1 = @(*([/-])*42|*([/-])*[hH?]|*([/-])[hH][eE][lL][pP])  ]]
then
  print
  print 'usage: rev <filename>  # reverses characters on each line of stdin or file'
  print
  return 1
fi

 sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//' $*
 return
}

function html2txt {

 # remove most HTML tags (accommodates multiple-line tags)
 sed -e ':a' -e 's/<[^>]*>//g;/</N;//ba'  $*

}

function ansi2txt {

# from     ANSI2TXT.SED
#
#     CAREFUL -- note the EOL escapes
sed -e ':p' -e \
's/^[[[=?c]/^[/g;t p;s/^[[0-9r]*[:;]/^[/g;t p;s/^[[0-9fH]*[A-Za-z]//g;s/[^[^A^H]//g' \
$*
# sed -e ':p;s/^[[[=?c]/^[/g;t p;s/^[[0-9r]*[:;]/^[/g;t p;s/^[[0-9fH]*[A-Za-z]//g;s/[^[^A^H]//g' \ $*

}

function uniq {

 # delete duplicate lines from a sorted file (emulates "uniq"). First
 # line in a set of duplicate lines is kept, the rest are deleted
 sed '$!N; /^\(.*\)\n\1$/!P; D'

}

function sgrep  {

  #  echo "$*"
  #  echo "'/$*/p;'"
  #  sed.exe  -e '/^/d;'
  ${SCRATCH}:/sed.exe -n -e "/$*/p;"

}


#   seders

function  manual {

# pushd c:/os2/apps
  #  unzip manual.zip  $1  -d ${SCRATCH:-M}:/
  #  del ${SCRATCH:-M}:\\$1
  #  echo   ${SCRATCH:-M}:\\$1
  #  echo enter return to continue
  #  read
#  popd
cd ${SCRATCH:-M}:/


case ${1:-?} in

-? | /? | ? | 42 | /h )
   #  unzip -Z -1  c:/os2/apps/manual.zip -d ${SCRATCH:-M}:/  |  sort  ;;
   unzip -Z -1  c:/os2/apps/manual.zip    |  sort  ;;

* )

  unzip c:/os2/apps/manual.zip  $1  -d ${SCRATCH:-M}:/   >  NUL
  #  tk  $1
  #  ${FCEDIT}  $1
  ${FCEDIT}  $1
  del $1
  ;;

esac

cd -      >  NUL
}

function tee {

#  set -x
#       above for debugging

if [[ $1 = '-a' ]] || [[ $1 = '-A' ]]
then
   shift 1
   set apptrigger=on
   print -u2  'Append switch not implimented yet...'
   return 13
fi

#  I thought the below would be needed, but
#  apparently OS/2 port of SED does not have the 10 file write limit.
#  D.E.L.  12/11/98
# if ((  $# > 10  ))
# then
#   print -u2  'Too many files (more then 10) specified....'
#  return 13
# fi


cmd=
for i in ${@:-con}
  do
  if [[ $i = '-' ]]
  then
    cmd="$cmd -e \"w con\""
  else
    cmd="$cmd -e \"w $i\""
  fi
  done

eval sed  $cmd

}

function iwget  {

echo $1  >>  k:/www/wget${2:-3}.lst

# for a default wget recursion level of 3

}

function expr {
# from "UNIX Shell Programming", revised edition, Kochan & Wood
# p. 356
  integer local="$*"  # local integer variable
  echo $local         # print out result
}

#  function   tkill  {
#    pkill=${1}
#    #  for tbkilled in  $( ps  |  sed -n "/ $$ /s/$$.*//p" )
#    echo $( ps  |  sed -n "/ ${pkill} /s/${pkill}.*//p" )
#
#  #   for tbkilled in  $( ps  |  sed -n "/ ${pkill} /s/${pkill}.*//p" )
#  #   do
#  #   #  ps -9  ${tbkilled}  2>&1 > NUL  &
#  #   start ps -9  ${tbkilled}  2>&1 > NUL  &
#  }
#
#
#  trap  "tkill $$ &"  2 3

alias ren='cmd /c ren'
alias detatch='cmd /c detach'
# alias wps='cd c:\os2 ; cp pmshell.exe dodge.exe ; start /n dodge'
# alias spw='cd c:\os2 ; go -ka dodge.exe ; rm  dodge.exe'
alias cd..='cd ..'
alias cd.='cd .'
alias cd/='cd /'
alias cd-='cd -'
alias cd~='cd ~'
alias md='cmd.exe /c md'
alias rd='cmd.exe /c rd'
alias mkdir='md'
alias rmdir='rd'
alias zipinfo='unzip -Z'
alias cp='cmd.exe /c copy /v'
alias move='cmd.exe /c move '
alias mv='cmd.exe /c move '
alias fg='go -j'
alias vi='vile '
alias view='vile -R '
alias viewinf='c:/os2/view.exe '

#    experimental:
function xcp {
echo $*
xcopy.exe  $* /v
}

alias cat='sed -n "/^/p"'
#  alias rm='cmd.exe /c del /n'
alias source='.'
alias cx='cmd.exe /c'
alias ctype='cmd.exe /c type'
#      These next two are in developement
# alias ctime='cmd.exe /c \( echo.  |  time \)'
# alias cdate='cmd.exe /c \( echo.  |  date \)'
alias ctime='cmd.exe /c time'
alias cdate='cmd.exe /c date'
# alias \/C='-c '    #  for testing    05/12/98 d.e.l.
# alias \/c='-c '    #  for testing    05/12/98 d.e.l.
alias remove='. remove.ksh'      # to more safely remove the ATAPI zip disk
#  alias t2='tk'
alias tk='t2'
alias infozip='unzip -Z '
alias lynx='. lynx.ksh'
#   function ls { set -o noglob ;  dir $*  /N ;  set +o noglob ;   }
#   ils ==  Inside ls
function ils { dir $*  /N /L ;  set +o noglob ;   }
alias lss='set -o noglob ; ils '
#  function ls { lss $* | sed  '/-.*-/!d' ;  }
function ls { lss $* | sed -n '/-.*-/p;/^.:\\/p;' ;  }
#  alias rm='cmd.exe /c del /n'
function irm { cmd.exe /c del /n $* ; set +o noglob ;  }
alias rm='set -o noglob ; irm '

if [[ ! -a $SCRATCH:\cmd.exe ]]
then
  xcopy c:\os2\cmd.exe  $SCRATCH:\*.* /v  2>  NUL  1>  NUL
  if [[  $- =  'i' ]]
  then
    print 'CMD.EXE installed on the scratch volume....'
  fi
else
  if [[  $- = 'i'  ]]
  then
    print 'CMD.EXE already installed on scratch volume....'
  fi
fi
export OS2_SHELL=$SCRATCH:\CMD.EXE

# NATURAL=C:\OS2\CMD.EXE

if [[ ! -a $SCRATCH:\sed.exe ]]
then
  xcopy c:\os2\sed.exe  $SCRATCH:\*.* /v  2>  NUL  1>  NUL
  if [[  $- =  'i' ]]
  then
    print 'SED.EXE installed on the scratch volume....'
  fi
else
  if [[  $- = 'i'  ]]
  then
    print 'SED.EXE already installed on scratch volume....'
  fi
fi

# export NATURAL
export NATURAL=C:\OS2\CMD.EXE
# COMSPEC='c:\os2\ksh.exe'
# export COMSPEC
export COMSPEC='c:\os2\ksh.exe'  #  so far, the normal setting
#  export COMSPEC='c:\os2\ksh.exe -i'  #  this seemed to work better with k2
#  export ENV=c:\kshrc.ksh  -- replaced with patch to KSH environmental variable
alias cn="COMSPEC=$SCRATCH:\\cmd.exe "
#        'Comspec Native'     to enable shelling out & calling outside
#                                programs more easily with some apps
# HOME=C:/
# export HOME
export HOME=C:/

if [[  $-  =  'i'  ]]
then
  print 'Hello, this is os2.ksh....'
fi


# set -o emacs   -- emacs?  is this guy crazy?   d.e.l.  28/10/98
set -o vi

#     Stuff for U2/Until  support:
export UNTIL_SYM='c:/os2/apps'


#     Stuff for PERL5 support:
#  export PERL5LIB='c:/os2/apps/perl/mine;c:/os2/apps/perl/lib;l:/perl/lib'
#  export PERL5LIB='L:/PERL/LIB;l:/perl/lib'
export PERL5LIB='l:/perl/lib;l:/perl/lib/auto/OS2/REXX'
#  export PATH="l:\perl;$PATH"
#  export SETBEGINLIBPATH=''
#  export BEGINLIBPATH='l:\perls\lib\auto\OS2\REXX'
#  export PERL5LIB='l:\perl\lib'
#  export PERL5LIB='c:/os2/apps/perl/mine;c:/os2/apps/perl/lib;l:/perl/lib;l:/perl/lib/auto/OS2/REXX'
#  export PERL5LIB='c:\os2\apps\perl\mine;c:\os2\apps\perl\lib;l:\perl\lib'
export PERL5LOAD=10
export PATH="$PATH\.;\..;"

export CDPATH="./;c:/;c:/os2;e:/;e:/tcpip"

#         temp
#  alias -x xxcp='xcp  k:*.*  l:*.*  /s /v /e  '


alias /c=''
alias help='COMSPEC=c:\os2\cmd.exe    help  '
alias emacs='emacsclient '


#  alias stty="echo "
#  alias  stty="ansi on "



NEXT PREVIOUS
















































































































































































































































Underutilized Features


NEXT PREVIOUS
















































































































































































































































Wild Cards

ABCstring literals
?single character
*zero or more characters
[abco-s]character class
[!k-l]negated character class

NEXT PREVIOUS
















































































































































































































































Extended Wild Cards / Patterns / 'Regular Expressions'

?(pat1|pat2|...)0 or 1 patterns
@(pat1|pat2|...)exactly 1 patterns
*(pat1|pat2|...)zero or more of patterns
+(pat1|pat2|...)one or more of patterns
!(pat1|pat2|...)none of patterns

NEXT PREVIOUS
















































































































































































































































Brace Expansion

abc{e,f,g}hij -> abcehij abcfhij abcghij


NEXT PREVIOUS
















































































































































































































































Parameter Expansion

${variablename} - basic form


NEXT PREVIOUS
















































































































































































































































exec Command

Two orthogonal purposes:


NEXT PREVIOUS
















































































































































































































































Traps

again:
trap "echo 'Hello, world'" 2 3


NEXT PREVIOUS
















































































































































































































































Here documents

  cat <<very_special_message
   yadda, yadda, yadda
   yadda, yadda, yadda
   yadda, yadda, yadda
  very_special_message
<<end_labelbasic - interpolates
<<'end_label'turn off interpolation
<<"end_label"turn off interpolation
<<- strip leading tabs

NEXT PREVIOUS
















































































































































































































































Misc.


NEXT PREVIOUS
















































































































































































































































what to run in shell scripts

man -k/apropos

suggested list from Linux Magazine, May 2001 p. 24 Bill McCarty


NEXT PREVIOUS
















































































































































































































































AT&T Unix 'First Edition', (p. 41-42, Salus)


NEXT PREVIOUS
















































































































































































































































Version 7 additions, (Salus, p. 146)


NEXT PREVIOUS
















































































































































































































































Resources

man pages

Some Suggested Books

(* - I haven't actually read yet.)

c) web sites

First Previous

mailto:legan@acm.org

Valid HTML 4.01!