1 #!/bin/bash
   2 #
   3 # /home/lantw44/.bash_include
   4 #
   5 # -- UTF-8 --
   6 #
   7 # 設定用外部檔案:
   8 #     (1) 若 .bash_title 存在且未設定自動修改視窗標題,則依照本檔案內定規則修改
   9 #     (2) 若 .bash_addps 存在,則第一行的的內容會加到 colorprompting 變數,第二
  10 #         行的內容會加到 nocolorprompting 變數
  11 
  12 #### if tty -s; then interactive_shell=1; fi
  13 if [[ "$-" == *i* ]] ; then interactive_shell=1; fi
  14 
  15 [ "$interactive_shell" ] && echo "Running .bash_include"
  16 [ "$interactive_shell" ] && default_tty_setting="`stty -g`"
  17 
  18 # Internal Variables
  19 
  20 colorprompting='\[\e[1;31m\]\!\[\e[m\] [\[\e[1;33m\]\u\[\e[m\]@\[\e[1;32m\]\h\[\e[m\] \[\e[1;36m\]\w\[\e[m\]]'
  21 nocolorprompting='\! [\u@\h \w]'
  22 
  23 if [ "$SSH_CONNECTION" ]
  24 then
  25     colorprompting="\[\e[1;44m\]*\[\e[m\]$colorprompting"
  26     nocolorprompting="*$nocolorprompting"
  27 fi
  28 
  29 if [ -f "$HOME/.bash_addps" ]
  30 then
  31     exec 3< "$HOME/.bash_addps"
  32     read -u 3 -r oneline
  33     colorprompting="$oneline $colorprompting"
  34     read -u 3 -r oneline
  35     nocolorprompting="$oneline $nocolorprompting"
  36     exec 3<&-
  37     unset oneline
  38 fi
  39 
  40 if [ "$WINDOW" ]
  41 then
  42     colorprompting="$colorprompting<$WINDOW>"
  43     nocolorprompting="$nocolorprompting<$WINDOW>"
  44 fi
  45 
  46 colorprompting="${colorprompting}\$ "
  47 nocolorprompting="${nocolorprompting}\$ "
  48 
  49 historycountfile="$HOME/.bash_history.count"
  50 historybackupfile="$HOME/.bash_history.bak"
  51 bgrunfiledir="$HOME/tmp/bgrun-`whoami`"
  52 trashdir="$HOME/trash"
  53 
  54 HISTSIZE=2147483647
  55 HISTFILESIZE=2147483647
  56 HISTCONTROL=ignoredups:ignorespace
  57 HISTTIMEFORMAT="%F %T "
  58 
  59 REALPATH_PROGRAM="realpath"
  60 
  61 CFLAGS="-Wall -pipe -g"
  62 
  63 
  64 # Environment Variables
  65 
  66 export EDITOR=vim
  67 export FCEDIT=vim
  68 export PAGER=less
  69 
  70 
  71 
  72 
  73 # Aliases
  74 
  75 alias startcolor='PS1=$colorprompting'
  76 alias stopcolor='PS1=$nocolorprompting'
  77 
  78 alias ll='ls -l'
  79 alias grep='grep --color=always'
  80 alias rm='rm -i'
  81 alias cp='cp -pi'
  82 alias mv='mv -i'
  83 alias jobs='jobs -l'
  84 alias less='less -RS'
  85 
  86 alias cccc='LANG=C;LANGUAGE=C;LC_ALL=C'
  87 alias enus='LANG=en_US.UTF-8;LANGUAGE=en_US:en;LC_ALL=en_US.UTF-8'
  88 alias big5='LANG=zh_TW.Big5;LANGUAGE=zh_TW:zh;LC_ALL=zh_TW.Big5'
  89 alias zhtw='LANG=zh_TW.UTF-8;LANGUAGE=zh_TW:zh;LC_ALL=zh_TW.UTF-8'
  90 
  91 alias savetty='default_tty_setting=`stty -g`'
  92 alias resetty='stty $default_tty_setting'
  93 
  94 alias vimhtml='vim -c "set ts=2" -c "set sw=2"'
  95 
  96 
  97 # Functions
  98 
  99 function compile_all ()
 100 {
 101     local noask=0
 102     [ "$1" = '' ] && echo "Which file(s) do you want to compile? " && return 1
 103     [ "$1" = "-n" ] && noask=1
 104     if [ "$noask" = "0" ]; then
 105         read -e -p "CFLAGS: " -i "$CFLAGS" NEWCFLAGS
 106         read -e -p "LDFLAGS: " -i "$LDFLAGS" NEWLDFLAGS
 107         [ "$NEWCFLAGS" '!=' '' ] && CFLAGS=$NEWCFLAGS
 108         [ "$NEWLDFLAGS" '!=' '' ] && LDFLAGS=$NEWLDFLAGS
 109     else
 110         shift
 111     fi
 112     while [ "$1" '!=' '' ]
 113     do
 114         local TARGETFILE="`echo "$1" | cut -d . -f 1`"
 115         local SUFFIX="`echo "$1" | cut -d . -f 2`"
 116         if [ -f "$1" ]; then
 117             true
 118         else
 119             printf\
 120             "\e[1;33mWarning\e[0m: $1 Non-existent file or not a regular file\n"
 121             shift ; continue
 122         fi
 123         [ "$TARGETFILE" = "$1" ] && shift && continue
 124         if [ "$SUFFIX" = "c" ]; then
 125             echo "[CC] $1 -> $TARGETFILE"
 126             gcc $CFLAGS "$1" $LDFLAGS -o "$TARGETFILE"
 127         elif [ "$SUFFIX" = "cpp" ]; then
 128             echo "[CXX] $1 -> $TARGETFILE"
 129             g++ $CFLAGS "$1" $LDFLAGS -o "$TARGETFILE"
 130         else
 131             printf "$1: Unknown suffix (\e[1;33mskipped\e[0m)\n"
 132         fi
 133         [ "$?" '!=' "0" ] && printf\
 134             '\e[1;31mError\e[0m while compiling file\n'
 135         shift
 136     done
 137     return 0
 138 }
 139 
 140 
 141 function convert_to_html ()
 142 {
 143     while [ "$1" '!=' '' ]
 144     do
 145         for i in "$1"
 146         do
 147             vim $i -c 'set background=dark' \
 148                 -c 'highlight PreProc ctermfg=darkcyan' \
 149                 -c "$BEFORE_CONVERT_TO_HTML" \
 150                 -c "$BEFORE_CONVERT_TO_HTML1" \
 151                 -c "$BEFORE_CONVERT_TO_HTML2" \
 152                 -c TOhtml \
 153                 -c :w \
 154                 -c :qa
 155         done
 156         shift
 157     done
 158 }
 159 
 160 function mkscreenacl ()
 161 {
 162     PERMIT_COMMAND="select windowlist other meta detach reset hardcopy info redisplay lastmsg next prev xon xoff windows suspend help colon copy paste writebuf readbuf displays stuff attach"
 163     while [ "$1" '!=' '' ]
 164     do
 165         for i in $PERMIT_COMMAND
 166         do
 167             echo "aclchg $1 +x $i"
 168         done
 169         echo "aclchg $1 -rw \"#?\"" 
 170         shift
 171     done
 172 }
 173 
 174 function get_file_size () 
 175 {
 176     split_arguments "$@"
 177     "${prefixlist[@]}" du -s "${arglist[@]}" | {
 178         read -d "   " dirsize
 179         echo "$dirsize"
 180         read throwaway
 181     }
 182     unset arglist
 183     unset prefixlist
 184 }
 185 
 186 ########## Background ##########
 187 
 188 alias bgr=bgrun
 189 alias bgv=bgview
 190 alias bgl=bglist
 191 alias bgc=bgcount
 192 alias bgls=bglist
 193 alias bgrm=bgclean
 194 
 195 function bgrun ()
 196 {
 197     [ "$#" = "0" ] && return 1
 198     [ '!' -d "$bgrunfiledir" ] && createdir_askmode "$bgrunfiledir" 0750
 199     local current_time=`date "+%Y%m%d-%H%M%S"`
 200     local cmdname=`echo "$1" | sed -e 's/-/_/g' -e 's/\\//_/g' -e 's/ /_/g'`
 201     if [ "`echo "$cmdname" | cut -c 1`" == "_" ]
 202     then
 203         cmdname=`echo "$cmdname" | cut -c 2-`
 204     fi
 205     local filename="$bgrunfiledir/$current_time-$cmdname"
 206     echo "Writing to $filename"
 207     {
 208         echo -n "$BASHPID " > "$filename"
 209         echo "$@" >> "$filename"
 210         exec "$@" &>> "$filename"
 211     } &
 212 }
 213 
 214 function bglist ()
 215 {
 216     local viewtime=0
 217     [ "$1" = "--full" ] && viewtime=1
 218     {
 219         for i in `find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort`
 220         do
 221             [ "$viewtime" = "1" ] && echo "$i"
 222             head -n 1 "$i" | {
 223                 local procpid
 224                 local cmdline
 225                 read -d ' ' procpid
 226                 read cmdline
 227                 printf "(%5d) %s\n" "$procpid" "$cmdline"
 228             }
 229         done
 230     } | {
 231         if [ "$viewtime" = "1" ]
 232         then
 233             echo " INDEX         TIME          PID   COMMAND"
 234             local readstat=0
 235             local -i i=1
 236             while true
 237             do
 238                 local dateandtime_long
 239                 local cmdline
 240                 read dateandtime_long
 241                 read cmdline
 242                 [ "$?" '!=' "0" ] && break
 243                 local dateandtime=`basename "$dateandtime_long"`
 244     ####        local part_year=`echo $dateandtime | cut -c 1-4`
 245     ####        local part_month=`echo $dateandtime | cut -c 5-6`
 246     ####        local part_date=`echo $dateandtime | cut -c 7-8`
 247     ####        local part_hour=`echo $dateandtime | cut -c 10-11`
 248     ####        local part_minute=`echo $dateandtime | cut -c 12-13`
 249     ####        local part_second=`echo $dateandtime | cut -c 14-15`
 250                 echo "$dateandtime" | {
 251                     read -n 4 part_year
 252                     read -n 2 part_month
 253                     read -n 2 part_date
 254                     read -n 1 drop_this_char; unset drop_this_char
 255                     read -n 2 part_hour
 256                     read -n 2 part_minute
 257                     read -n 2 part_second
 258                     printf '%6d' "$i"
 259                     echo " $part_year-$part_month-$part_date $part_hour:$part_minute:$part_second $cmdline"
 260                 }
 261                 i=$i+1
 262             done
 263         else
 264             echo " INDEX    PID   COMMAND"
 265             cat -n
 266         fi
 267     } | $PAGER
 268 }
 269 
 270 function bgview ()
 271 {
 272     local -i yourchoice
 273     if [ "$1" = "" ]
 274     then
 275         yourchoice=`bgcount`
 276     else
 277         if [ "$1" -le "0" ]
 278         then
 279             yourchoice=$((`bgcount`+$1))
 280         else
 281             yourchoice=$1
 282         fi
 283     fi
 284     echo "Your choice is $yourchoice."
 285     local realfilename=`find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort | sed -n ${yourchoice}p`
 286     head -n 1 "$realfilename" | {
 287         read -d ' ' procpid
 288         read cmdline
 289         echo "PID: $procpid"
 290         echo "Command Line: $cmdline"
 291     }
 292     read -e -p "View '$realfilename' ? " confirm
 293     if [ "$confirm" = "n" ] || [ "$confirm" = "N" ]
 294     then
 295         return 1
 296     fi
 297     {
 298         printf "===> Process Information: "
 299         cat "$realfilename"
 300     } | $PAGER
 301 }
 302 
 303 function bgcount ()
 304 {
 305     find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | cut -d - -f 2,3 | wc | awk '{print $2}'
 306 }
 307 
 308 function bgclean ()
 309 {
 310     if [ "$1" = "all" ]
 311     then
 312         echo "Removing the directory $bgrunfiledir"
 313         rm -rf "$bgrunfiledir" &
 314         return 0
 315     else
 316         split_arguments "$@"
 317         local -i i=0
 318         while [ "${arglist[$i]}" ]
 319         do
 320             arglist[$i]="-e ${arglist[$i]}p"
 321             i=$i+1
 322         done
 323         local oneline
 324         find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort | sed -n ${arglist[*]} | {
 325             while read oneline
 326             do
 327                 echo "Removing $oneline"
 328                 rm -f "$oneline"
 329             done
 330         }
 331     fi
 332     unset arglist
 333     unset prefixlist
 334 }
 335 
 336 function bgdu () 
 337 {
 338     local -i j=1
 339     {
 340         echo " INDEX     SIZE   PID   COMMAND"
 341         for i in `find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort`
 342         do
 343             head -n 1 "$i" | {
 344                 local procpid
 345                 local cmdline
 346                 read -d ' ' procpid
 347                 read cmdline
 348                 printf "%6d %8d (%5d) %s\n" "$j" \
 349                     "`get_file_size "$i"`" \
 350                     "$procpid" "$cmdline"
 351             }
 352             j=$j+1
 353         done
 354     } | $PAGER
 355 }
 356 
 357 ########## Background End ##########
 358 
 359 function check_dmesg ()
 360 {
 361     [ "$#" = "0" ] && return 1
 362 
 363     while true
 364     do
 365         PREVIOS_DMESG_BUF="$DMESG_BUF"
 366         DMESG_BUF="`dmesg`"
 367         [ "$PREVIOS_DMESG_BUF" '!=' "$DMESG_BUF" ] && [ "$FIRST_RUN" = "0" ] && echo '===> You should check the system message buffer <==='
 368         sleep $1
 369         [ "$?" '!=' "0" ] && return 1
 370         FIRST_RUN=0
 371     done
 372 }
 373 
 374 function check_system_status ()
 375 {
 376     [ "$#" = "0" ] && return 1
 377 
 378     filename_mail="$MAIL"
 379     filename_messages="/var/log/messages"
 380     filename_audit="/var/log/audit/audit.log"
 381 
 382     while true
 383     do
 384         previous_dmesg_buf="$current_dmesg_buf"
 385         current_dmesg_buf="`dmesg`"
 386         previous_mail_info="$current_mail_info"
 387         current_mail_info="`ls -l "$filename_mail"`"
 388         previous_messages_info="$current_messages_info"
 389         current_messages_info="`ls -l "$filename_messages"`"
 390         previous_audit_info="$current_audit_info"
 391         current_audit_info="`ls -l "$filename_audit"`"
 392         if [ "$first_run" = "0" ]
 393         then
 394             [ "$previous_dmesg_buf" '!=' "$current_dmesg_buf" ] && echo "===> The system message buffer is modified (dmesg) <==="
 395             [ "$previous_mail_info" '!=' "$current_mail_info" ] && echo "===> Your mailbox $filename_mail is modified <==="
 396             [ "$previous_messages_info" '!=' "$current_messages_info" ] && echo "===> $filename_messages is modified <==="
 397             [ "$previous_audit_info" '!=' "$current_audit_info" ] && echo "===> $filename_audit is modified <==="
 398         fi
 399         sleep $1
 400         first_run=0
 401     done
 402 }
 403 
 404 function prehistory_backup ()
 405 {
 406     echo "Checking your current history file"
 407     local -i currentcount=`cat "$HISTFILE" | wc -l`
 408     [ '!' -f "$historycountfile" ] && touch "$historycountfile"
 409     local -i previoushistorycount
 410     previoushistorycount=`cat "$historycountfile"`
 411     if [ "$currentcount" -lt "$previoushistorycount" ]
 412     then
 413         printf "\e[1;31mWarning\e[m: Your $HISTFILE may be TRUNCATED OR OVERWRITTEN BY OTHER PROGRAMS!\n"
 414         printf "Note: \e[1;33m$currentcount\e[m < $previoushistorycount\n"
 415         echo "Your $historycountfile and $historybackupfile will not be overwritten until this problem is fixed."
 416         echo " 1. Check your $HISTFILE."
 417         echo " 2. Edit your $HISTFILE manually if some unexpected changes are found." 
 418         echo "    (You may need $historybackupfile to do it) "
 419         echo " 3. Remove the file $historycountfile."
 420         echo " 4. Run the command \`prehistory_backup' again."
 421         return 3
 422     fi
 423     echo -n "Backing up your current history file ($previoushistorycount -> $currentcount, "
 424     if [ "$previoushistorycount" = "$currentcount" ]
 425     then
 426         echo "no modification)"
 427     else
 428         echo "+$(($currentcount-$previoushistorycount)))"
 429     fi
 430     echo "$currentcount" > "$historycountfile"
 431     \cp -f "$HISTFILE" "$historybackupfile"
 432 }
 433 
 434 ########## Trash Manager ##########
 435 
 436 alias trash_put=trash_mv
 437 alias trash_add=trash_mv
 438 alias trash_list=trash_ls
 439 alias trash_ct=trash_count
 440 alias trash_restore=trash_recover
 441 alias trash_rc=trash_recover
 442 alias trash_drop=trash_rm
 443 alias trash_clean=trash_rm
 444 
 445 function trash_mv ()
 446 {
 447     [ "$#" = "0" ] && return 1
 448     [ '!' -d "$trashdir" ] && createdir_askmode "$trashdir" 0700
 449     local original_path
 450     local current_time
 451     local -i i=0
 452     split_arguments "$@"
 453     while [ "${arglist[$i]}" ]
 454     do
 455         original_path="`$REALPATH_PROGRAM "${arglist[$i]}"`"
 456         current_time=`date "+%Y%m%d-%H%M%S"`
 457         better_time=`date "+%Y-%m-%d %H:%M:%S"`
 458         dirname="`basename "${arglist[$i]}" | sed -e 's/-/_/g' -e 's/ /_/g'`"
 459         fulldirname="$trashdir/$current_time-$dirname"
 460         mkdir -p "$fulldirname"
 461         echo "Move: ${arglist[$i]} -> $fulldirname"
 462         "${prefixlist[@]}" mv "${arglist[$i]}" "$fulldirname"
 463         if [ "$?" = "0" ]
 464         then
 465             echo "$better_time" > "$fulldirname/information.date"
 466             echo "$original_path" > "$fulldirname/information.path"
 467         else
 468             rmdir "$fulldirname"
 469         fi
 470         i=$i+1
 471         shift
 472     done
 473     unset arglist
 474     unset prefixlist
 475 }
 476 
 477 function trash_rm ()
 478 {
 479     split_arguments "$@"
 480     local -i i=0
 481     while [ "${arglist[$i]}" ]
 482     do
 483         arglist[$i]="-e ${arglist[$i]}p"
 484         i=$i+1
 485     done
 486     trash_dirname=`find "$trashdir" -mindepth 1 -maxdepth 1 | sort | sed -n ${arglist[*]} `
 487     echo 'Type rm -rf $trash_dirname to remove them.'
 488     unset arglist
 489     unset prefixlist
 490 }
 491 
 492 function trash_ls ()
 493 {
 494     local -i i=1
 495     local oneline
 496     find "$trashdir" -mindepth 1 -maxdepth 1 | sort | {
 497         while read oneline
 498         do
 499             printf "%6d %s %s\n" "$i" \
 500                 "`cat "$oneline/information.date"`" \
 501                 "`cat "$oneline/information.path"`"
 502             i=$i+1
 503         done
 504     } | $PAGER
 505 }
 506 
 507 function trash_pushd ()
 508 {
 509     [ -z "$1" ] && return 1
 510     pushd `find "$trashdir" -mindepth 1 -maxdepth 1 | sort | sed -n $1p`
 511 }
 512 
 513 function trash_cd ()
 514 {
 515     [ -z "$1" ] && return 1
 516     cd `find "$trashdir" -mindepth 1 -maxdepth 1 | sort | sed -n $1p`
 517 }
 518 
 519 function trash_recover ()
 520 {
 521     [ -z "$1" ] && return 1
 522     split_arguments "$@"
 523     local -i i=0
 524     while [ "${arglist[$i]}" ]
 525     do
 526         arglist[$i]="-e ${arglist[$i]}p"
 527         i=$i+1
 528     done
 529     find "$trashdir" -mindepth 1 -maxdepth 1 | sort | sed -n ${arglist[*]} | {
 530         while read oneline
 531         do
 532             local fromfile="$oneline/`basename "$(cat "$oneline/information.path")"`"
 533             local tofile="`dirname "$(cat "$oneline/information.path")"`"
 534             if [ -e "`cat "$oneline/information.path"`" ]
 535             then
 536                 echo "Destination file exists."
 537                 continue
 538             fi
 539             echo "Move: $fromfile -> $tofile"
 540             "${prefixlist[@]}" mv -f "$fromfile" "$tofile"
 541             if [ "$?" = "0" ]
 542             then
 543                 echo "Remove: $oneline"
 544                 \rm -rf "$oneline"
 545             fi
 546         done
 547     }
 548     unset arglist
 549     unset prefixlist
 550 }
 551 
 552 function trash_count () 
 553 {
 554     find "$trashdir" -mindepth 1 -maxdepth 1 | wc | awk '{print $2}'
 555 }
 556 
 557 function trash_du ()
 558 {
 559     split_arguments "$@"
 560     local oneline
 561     local -i i=1
 562     find "$trashdir" -maxdepth 1 -mindepth 1 | sort | {
 563         while read oneline
 564         do
 565             printf "%6d %8d %s\n" "$i" \
 566                 "`get_file_size "$oneline" -- "${prefixlist[@]}"`" \
 567                 "`cat "$oneline/information.path"`"
 568             i=$i+1
 569         done
 570     } | $PAGER
 571     unset arglist
 572     unset prefixlist
 573 }
 574 
 575 ########## Trash Manager End ##########
 576 
 577 function split_arguments ()
 578 {
 579     local argcount=$#
 580     local -i i=0
 581     local prefix_start=0
 582     while [ "$1" ]
 583     do
 584         if [ "$prefix_start" == "0" ]
 585         then
 586             if [ "$1" = "--" ]
 587             then
 588                 prefix_start=1
 589                 i=0
 590                 shift
 591                 continue
 592             else
 593                 arglist[$i]="$1"
 594             fi
 595         else
 596             prefixlist[$i]="$1"
 597         fi
 598         i=$i+1
 599         shift
 600     done
 601 }
 602 
 603 function check_important_files ()
 604 {
 605     IMPORTANT_FILES="$HOME/.screenrc $HOME/.vimrc"
 606     for i in $IMPORTANT_FILES
 607     do
 608         [ '!' -f "$i" ] && printf "\e[1;31mWarning\e[m: \e[1;33m$i\e[m does not exist.\n"
 609     done
 610 }
 611 
 612 ########## PATH Editor ##########
 613 
 614 function split_path_core ()
 615 {
 616     echo "$current_path" | {
 617         while read -d : oneline
 618         do
 619             [ '!' "$oneline" = '^' ] && echo "$oneline"
 620         done
 621         [ '!' "$oneline" = '^' ] && echo "$oneline"
 622     }
 623     unset oneline
 624 }
 625 
 626 function split_path () 
 627 {
 628     coproc split_path_core
 629     readarray -t -u ${COPROC[0]} patharr
 630     wait $COPROC_PID
 631 }
 632 
 633 function update_path ()
 634 {
 635     current_path=''
 636     local -i i=0
 637     local firsttime="yes"
 638     while [ "${patharr[$i]}" ]
 639     do
 640         if [ '!' "${patharr[$i]}" = "^" ]
 641         then
 642             if [ "$firsttime" ]
 643             then
 644                 firsttime=''
 645             else
 646                 current_path+=':'
 647             fi
 648             current_path+="${patharr[$i]}"
 649         fi
 650         i=$i+1
 651     done
 652 }
 653 
 654 function old_path_editor ()
 655 {
 656     old_path_editor_core
 657 }
 658 
 659 function old_ldpath_editor ()
 660 {
 661     old_path_editor_core ld
 662 }
 663 
 664 function old_path_editor_core ()
 665 {
 666     if [ "$1" = "ld" ]
 667     then
 668         export current_path="$LD_LIBRARY_PATH"
 669     else
 670         export current_path="$PATH"
 671     fi
 672     local should_continue="yes"
 673     local command
 674     local command_sub
 675     local command_sub2
 676     local -i i
 677     while [ "$should_continue" ]
 678     do
 679         split_path
 680         i=0
 681         echo "========================================"
 682         while [ "${patharr[$i]}" ]
 683         do
 684             echo "$i: ${patharr[$i]}"
 685             i=$i+1
 686         done
 687         [ "$i" = '0' ] && echo "(Empty or not declared)"
 688         echo "========================================"
 689         read -e -p "[A]ppend/(D)elete/(E)dit/(M)ove/(R)eset/(Q)uit ? " command
 690         case "$command" in
 691             ''|A|a)
 692                 read -e -p "Type a new entry: " patharr[$i]
 693                 update_path
 694                 ;;
 695             D|d)
 696                 read -e -p "Index: " command_sub
 697                 patharr[$command_sub]='^'
 698                 update_path
 699                 ;;
 700             E|e)
 701                 read -e -p "Index: " command_sub
 702                 read -e -p "Modify this entry: " -i "${patharr[$command_sub]}" patharr[$command_sub]
 703                 update_path
 704                 ;;
 705             M|m)
 706                 read -e -p "From: " command_sub
 707                 read -e -p "To: " command_sub2
 708                 swaptmp="${patharr[$command_sub]}"
 709                 patharr[$command_sub]="${patharr[$command_sub2]}"
 710                 patharr[$command_sub2]="$swaptmp"
 711                 unset swaptmp
 712                 update_path
 713                 ;;
 714             R|r)
 715                 if [ "$1" = "ld" ]
 716                 then
 717                     current_path="$LD_LIBRARY_PATH"
 718                 else
 719                     current_path="$PATH"
 720                 fi
 721                 ;;
 722             Q|q)
 723                 if [ "$1" = "ld" ]
 724                 then
 725                     export LD_LIBRARY_PATH="$current_path"
 726                     echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
 727                     history -s "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
 728                 else
 729                     export PATH="$current_path"
 730                     echo "PATH=$PATH"
 731                     history -s "PATH=$PATH"
 732                 fi
 733                 should_continue=''
 734                 ;;
 735             *)
 736                 printf " \e[33m*** Unknown command ***\e[m \n"
 737                 ;;
 738         esac
 739     done
 740     unset patharr
 741     unset current_path
 742 }
 743 
 744 ########## PATH Editor End ##########
 745 
 746 ########## New PATH Editor ##########
 747 
 748 function ldpath_editor ()
 749 {
 750     path_editor LD_LIBRARY_PATH
 751 }
 752 
 753 function newpath_init ()
 754 {
 755     unset newpath
 756     local pathsp="$pathorgval"
 757     local pathentry
 758     local -i i
 759     eval pathsp='"${pathsp// /\\}"'
 760     pathsp="${pathsp//:/ }"
 761     i=0
 762     for pathentry in $pathsp
 763     do
 764         newpath[$i]="${pathentry//\\/ }"
 765         i=$i+1
 766     done
 767 }
 768 
 769 function newpath_gen ()
 770 {
 771     local -i i
 772     pathmodval=""
 773     i=0
 774     while [ "${newpath[$i]}" ]
 775     do
 776         if [ "$i" != 0 ]; then pathmodval+=":"; fi
 777         pathmodval+="${newpath[$i]}"
 778         i=$i+1
 779     done
 780 }
 781 
 782 function path_editor ()
 783 {
 784     local newpathvarname
 785     local badcommand
 786     local command
 787     local command_sub
 788     local command_sub2
 789     local should_continue="yes"
 790     local -i i
 791 
 792     if [ -z "$1" ]
 793     then
 794         newpathvarname="PATH"
 795     else
 796         newpathvarname="$1"
 797     fi
 798 
 799     eval pathorgval=\${${newpathvarname}}
 800     newpath_init
 801 
 802     while [ "$should_continue" ]
 803     do
 804         i=0
 805         echo -n $'\e[2J\e[0;0H'
 806         if [ "$badcommand" = "yes" ]; then
 807             printf " \e[33m*** Command \`$command' is unknown ***\e[m \n"
 808             badcommand=""
 809         fi
 810         echo "        New PATH Editor for BASH        "
 811         echo "========================================"
 812         echo "Environment Variable: $newpathvarname"
 813         echo "----------------------------------------"
 814         while [ "${newpath[$i]}" ]
 815         do
 816             echo "$i: ${newpath[$i]}"
 817             i=$i+1
 818         done
 819         [ "$i" = '0' ] && echo "(Empty or not declared)"
 820         echo "========================================"
 821         read -e -p "[A]ppend/(I)nsert/(D)elete/(E)dit/(M)ove/(S)wap/(R)eset/(Q)uit ? " command
 822         case "$command" in
 823             ''|A|a)
 824                 read -e -p "Type a new entry: " newpath[$i]
 825                 ;;
 826             I|i)
 827                 read -e -p "Type a new entry: " command_sub
 828                 if [ -z "$command_sub" ]; then continue; fi
 829                 newpath_tmp=( "${newpath[@]}" )
 830                 unset newpath
 831                 newpath="$command_sub"
 832                 i=0
 833                 while [ "${newpath_tmp[$i]}" ]
 834                 do
 835                     newpath[$i+1]="${newpath_tmp[$i]}"
 836                     i=$i+1
 837                 done
 838                 unset newpath_tmp
 839                 ;;
 840             D|d)
 841                 read -e -p "Index: " command_sub
 842                 if [ -z "$command_sub" ]; then continue; fi
 843                 i="$command_sub"
 844                 i=$i+1
 845                 while [ "${newpath[$i]}" ]
 846                 do
 847                     newpath[$i-1]="${newpath[$i]}"
 848                     i=$i+1
 849                 done
 850                 unset newpath[$i-1]
 851                 ;;
 852             E|e)
 853                 read -e -p "Index: " command_sub
 854                 read -e -p "Modify this entry: " -i "${newpath[$command_sub]}" newpath[$command_sub]
 855                 ;;
 856             M|m)
 857                 read -e -p "From: " command_sub
 858                 read -e -p "To: " command_sub2
 859                 if [ "$command_sub" -eq "$command_sub2" ]; then continue; fi
 860                 cmdsubval="${newpath[$command_sub]}"
 861                 if [ "$command_sub" -gt "$command_sub2" ]; then
 862                     i="$command_sub"
 863                     while [ "$i" -gt "$command_sub2" ]
 864                     do
 865                         newpath[$i]="${newpath[$i-1]}"
 866                         i=$i-1
 867                     done
 868                     newpath[$command_sub2]="$cmdsubval"
 869                 else
 870                     i="$command_sub"
 871                     while [ "$i" -lt "$command_sub2" ]
 872                     do
 873                         newpath[$i]="${newpath[$i+1]}"
 874                         i=$i+1
 875                     done
 876                     newpath[$command_sub2]="$cmdsubval"
 877                 fi
 878                 unset cmdsubval
 879                 ;;
 880             S|s)
 881                 read -e -p "First entry: " command_sub
 882                 read -e -p "Second entry: " command_sub2
 883                 swaptmp="${newpath[$command_sub]}"
 884                 newpath[$command_sub]="${newpath[$command_sub2]}"
 885                 newpath[$command_sub2]="$swaptmp"
 886                 unset swaptmp
 887                 ;;
 888             R|r)
 889                 read -e -p "Discard all changes [y/N] ? " command_sub
 890                 if [ "$command_sub" = "y" ]; then
 891                     eval pathorgval=\${${newpathvarname}}
 892                     newpath_init
 893                 fi
 894                 ;;
 895             Q|q)
 896                 newpath_gen
 897                 eval export ${newpathvarname}=\"$pathmodval\"
 898                 echo "${newpathvarname}=$pathmodval"
 899                 history -s "${newpathvarname}=$pathmodval"
 900                 should_continue=''
 901                 ;;
 902             *)
 903                 badcommand="yes"
 904                 ;;
 905         esac
 906     done
 907     unset newpath
 908     unset pathorgval
 909     unset pathmodval
 910 }
 911 
 912 ########## New PATH Editor End ##########
 913 
 914 function backup_file ()
 915 {
 916     split_arguments "$@"
 917     local current_time=`date +%Y%m%d`
 918     local rootfilename
 919     local -i i=0
 920     local -i j
 921     while [ "${arglist[$i]}" ]
 922     do
 923         if [ '!' -f "${arglist[$i]}" ]
 924         then
 925             printf "\e[1;31mError\e[m: ${arglist[$i]} does not exist or it is not a regular file.\n"
 926             i=$i+1
 927             continue
 928         fi
 929         rootfilename="${arglist[$i]}.$current_time"
 930         if [ -e "$rootfilename" ]
 931         then
 932             j=0
 933             while [ "$j" -lt "10" ]
 934             do
 935                 if [ -e "$rootfilename.$j" ]
 936                 then
 937                     j=$j+1
 938                     continue
 939                 else
 940                     "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename.$j"
 941                     history -s "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename.$j"
 942                     "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename.$j"
 943                     history -s "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename.$j"
 944                     break
 945                 fi
 946             done
 947             if [ '!' "$j" -lt "10" ]
 948             then
 949                 printf "\e[1;31mError\e[m: Can not create a backup file for ${arglist[$i]}.\n"
 950                 printf "\e[1;33mPlease delete some backup file because I only use 0 - 9.\e[m\n"
 951             fi
 952         else
 953             "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename"
 954             history -s "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename"
 955             "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename"
 956             history -s "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename"
 957         fi
 958         i=$i+1
 959     done
 960     unset arglist
 961     unset prefixlist
 962 }
 963 
 964 function keep_sudo_credential ()
 965 {
 966     if [ "$1" ]
 967     then
 968         update_sudo_interval="$1"
 969     else
 970         update_sudo_interval="280"
 971     fi
 972     while true
 973     do
 974         sudo -v
 975         sleep "$update_sudo_interval"
 976     done
 977 }
 978 
 979 function get_memory_info ()
 980 {
 981     if [ "`uname`" = "Linux" ]
 982     then
 983         local meminfoline="`free -m | \grep -i mem`"
 984         local swapinfoline="`free -m | \grep -i swap`"
 985         local memtotal="`echo "$meminfoline" | awk '{print $2}'`"
 986         local memused="`echo "$meminfoline" | awk '{print $3}'`"
 987         local membuf="`echo "$meminfoline" | awk '{print $6}'`"
 988         local memcache="`echo "$meminfoline" | awk '{print $7}'`"
 989         local memprog=$(($memused-$membuf-$memcache))
 990         local swaptotal="`echo "$swapinfoline" | awk '{print $2}'`"
 991         local swapused="`echo "$swapinfoline" | awk '{print $3}'`"
 992         echo "Memory: $memused / $memtotal MB (`printf %2d $(($memused*100/$memtotal))`%)"
 993         echo "Detail:"
 994         echo "    Used:    `printf %5d $memprog` MB (`printf %2d $(($memprog*100/$memtotal))`%)"
 995         echo "    Buffers: `printf %5d $membuf` MB (`printf %2d $(($membuf*100/$memtotal))`%)"
 996         echo "    Cached:  `printf %5d $memcache` MB (`printf %2d $(($memcache*100/$memtotal))`%)"
 997         if [ "$swaptotal" = "0" ]
 998         then
 999             echo "Swap: not available"
1000         else
1001             echo "Swap: $swapused / $swaptotal MB (`printf %2d $(($swapused*100/$swaptotal))`%)"
1002         fi
1003     else
1004         echo "Current operating system is not Linux."
1005     fi
1006 }
1007 
1008 function set_console_title ()
1009 {
1010     case "$TERM" in
1011         screen)
1012             printf "\033]0;"
1013             echo -n "$*"
1014             printf "\033\\"
1015             ;;
1016         xterm*)
1017             printf "\033]0;"
1018             echo -n "$*"
1019             printf "\007"
1020             ;;
1021         *)
1022             echo "Your terminal may not have the hardstatus line."
1023             echo "Note: TERM=$TERM"
1024             ;;
1025     esac
1026 }
1027 
1028 function mvfile ()
1029 {
1030     local nocheck=0
1031     [ "$1" = "-n" ] && nocheck=1 && shift
1032     split_arguments "$@"
1033     local -i i=0
1034     while [ "${arglist[$i]}" ] 
1035     do
1036         if [ "$nocheck" = "0" ] && [ '!' -e "${arglist[$i]}" ]
1037         then
1038             printf "\e[33mWarning\e[m: ${arglist[$i]} does not exist. (Use -n to override)\n"
1039             i=$i+1
1040             continue
1041         fi
1042         echo "Old name: ${arglist[$i]}"
1043         read -p "New name: " -e -i "${arglist[$i]}" new_file_name
1044         if [ "$new_file_name" ] && [ "${arglist[$i]}" != "$new_file_name" ]
1045         then
1046             "${prefixlist[@]}" mv -iv "${arglist[$i]}" "$new_file_name"
1047             history -s "${prefixlist[@]}" mv -iv "${arglist[$i]}" "$new_file_name"
1048         fi
1049         i=$i+1
1050     done
1051     unset arglist
1052     unset prefixlist
1053     unset new_file_name
1054 }
1055 
1056 function createdir_askmode ()
1057 {
1058     newdir_mode="$2"
1059     if mkdir -p "$1"
1060     then
1061         echo "Directory $1 is created." 
1062         printf "Change the mode of the directory... "
1063         read -i "$newdir_mode" -p ">>> Mode: " -e newdir_mode
1064         chmod "$newdir_mode" "$1"
1065     else
1066         echo "Cannot create directory $1!"
1067         return 1
1068     fi
1069 }
1070 
1071 ########## Help ##########
1072 
1073 alias helpf='help_function'
1074 alias helpm='help_myself'
1075 
1076 function print_iconv ()
1077 {
1078     [ "$1" = "$2" ] && cat && return 0
1079     iconv -f "$1" -t "$2"
1080 }
1081 
1082 function help_myself () 
1083 {
1084     echo "argc = $#"
1085     echo "argv[0] = $0"
1086     i=1
1087     while [ "$1" ]
1088     do
1089         echo "argv[$i] = $1"
1090         i=$(($i+1))
1091         shift
1092     done
1093 }
1094 
1095 function help_obsolete ()
1096 {
1097     cat << ENDHELPMSG
1098  @@@ Obsolete Group: PATH Editor @@@
1099     old_path_editor
1100     old_ldpath_editor
1101  x  split_path
1102  x  split_path_core
1103  x  update_path 
1104  x  old_path_editor_core
1105 ENDHELPMSG
1106 }
1107 
1108 function help_function ()
1109 {
1110     [ "$#" = "0" ] && {
1111         cat << ENDHELPMSG
1112  <<< Help >>>
1113     help_myself [arguments ...]                            (helpm)
1114     help_function [functions ...]                          (helpf)
1115     help_obsolete
1116  x  print_iconv
1117  <<< Group: Background >>>
1118     bgrun command [arguments ...]                          (bgr)
1119     bglist [--full]                                        (bgl, bgls)
1120     bgview [number]                                        (bgv)
1121     bgclean [all | numbers ...]                            (bgrm)
1122     bgcount                                                (bgc)
1123     bgdu
1124  <<< Group: Trash >>>
1125     trash_mv [filenames ...] [-- sudo_prefix ...]     (trash_put, trash_add)
1126     trash_ls                                          (trash_list)
1127     trash_cd number
1128     trash_pushd number
1129     trash_recover numbers ... [-- sudo_prefix ...]    (trash_restore, trash_rc)
1130     trash_rm numbers ...                              (trash_drop, trash_clean)
1131     trash_count                                       (trash_ct)
1132     trash_du [-- sudo_prefix ...]
1133  <<< Group: New PATH Editor >>>
1134     path_editor [variable]
1135     ldpath_editor
1136  x  newpath_init
1137  x  newpath_gen
1138  <<< Other >>>
1139     backup_file filename ... [-- sudo_prefix ]
1140     check_dmesg seconds
1141     check_system_status seconds
1142     check_important_files
1143     compile_all [-n] filenames ...
1144     convert_to_html filename ...
1145     get_memory_info
1146     keep_sudo_credential [seconds]
1147     mkscreenacl usernames ...
1148     mvfile [-n] filenames ... [-- sudo_prefix]
1149     prehistory_backup
1150     set_console_title
1151  x  createdir_askmode dirname
1152  x  split_arguments [arguments ...]
1153  x  get_file_size filename [-- sudo_prefix]
1154 
1155 Obsolete functions are not printed. Type \`help_obsolete' to print them. 
1156 ENDHELPMSG
1157     } && return 0
1158     local current_charset=`echo "$LC_ALL" | cut -d . -f 2`
1159     local -i i
1160     while [ "$1" ]
1161     do
1162         case "$1" in
1163             help_myself|helpm)
1164                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1165 help_myself
1166     一個測試命令列的小函式
1167 ENDHELPMSG
1168                 ;;
1169             help_function|helpf)
1170                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1171 help_function
1172     顯示 .bash_include 提供的額外函式清單
1173     註:前方加上「x」符號者表示此為內部使用的函式,不宜直接使用
1174 ENDHELPMSG
1175                 ;;
1176             bgrun|bgr)
1177                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1178 bgrun command [arguments ...]
1179     執行指令 command 並將輸出導入檔案
1180     註:此函式會自動以目前時間和指令名稱為檔案命名
1181 ENDHELPMSG
1182                 ;;
1183             bglist|bgl|bgls)
1184                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1185 bglist [--full]
1186     列出所有使用 bgrun 執行的指令
1187     若加上 --full 選項,則可同時察看時間
1188 ENDHELPMSG
1189                 ;;
1190             bgview|bgv)
1191                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1192 bgview [number]
1193     顯示以 bgrun 執行指令的輸出,若省略 number,表示是最近一次執行的指令
1194     若 number >  0,
1195         表示第 number 個指令 (此數值可由 bglist 函式取得)
1196     若 number <= 0,
1197         表示第「指令總數-number」個指令 (指令總數可由 bgcount 函式取得)
1198 ENDHELPMSG
1199                 ;;
1200             bgclean|bgrm)
1201                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1202 bgclean [all | numbers ...]
1203     bgclean all 可清除所有指令的輸出檔
1204     bgclean 3 5 7 10 表示清除第 3、5、7、10 個指令輸出檔 (編號可由 bglist 取得)
1205 ENDHELPMSG
1206                 ;;
1207             bgcount|bgc)
1208                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1209 bgcount
1210     顯示指令輸出檔總數
1211 ENDHELPMSG
1212                 ;;
1213             bgdu)
1214                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1215 bgdu
1216     顯示每個指令輸出檔的檔案大小 (單位:KB)
1217 ENDHELPMSG
1218                 ;;
1219             *)
1220                 echo "Help message for $1 is not found"
1221                 ;;
1222         esac
1223         shift
1224     done
1225 }
1226 
1227 ########## Help End ##########
1228 
1229 # Doing something
1230 
1231 umask 0022
1232 
1233 if [ "$interactive_shell" ]
1234 then
1235     echo "Running interactive shell configuration"
1236     check_important_files
1237     startcolor
1238     prehistory_backup
1239     bind '"\e[A":history-search-backward'
1240     bind '"\e[B":history-search-forward'
1241     if [ -z "$PROMPT_COMMAND" ] && [ -e "$HOME/.bash_title" ]; then
1242         case "$TERM" in
1243             xterm*)
1244                 PROMPT_COMMAND='printf "\033]0;%s@%s:%s (%s)\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" "`date "+%H:%M:%S"`"'
1245                 ;;
1246             screen)
1247                 PROMPT_COMMAND='printf "\033]0;%s@%s:%s (%s)\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" "`date "+%H:%M:%S"`"'
1248                 ;;
1249         esac
1250     fi
1251 fi
1252 
1253 if [ "`uname`" = "Linux" ]
1254 then
1255     [ "$interactive_shell" ] && echo "Setting special things for Linux"
1256     REALPATH_PROGRAM="readlink -f"
1257     ulimit -c unlimited
1258 fi
1259 
1260 [ "$interactive_shell" ] && echo "Setting shell options"
1261 
1262 shopt -s histappend
1263 shopt -s checkwinsize
1264 shopt -s checkjobs
1265 shopt -s checkhash
1266 shopt -s cmdhist
1267 shopt -s mailwarn
1268 
1269 [ "$interactive_shell" ] && {
1270     echo "Done"
1271     if [ "$UID" = "0" ] || [ "$EUID" = "0" ]
1272     then
1273         printf "\nNote: You may be \e[1;32mprivileged\e[m now!\n\n"
1274     fi
1275 }
1276