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 [ "$UNDER_JHBUILD" = "true" ]
  30 then
  31     colorprompting="$colorprompting[\[\e[1;35m\]JHBuild\[\e[m\]]"
  32     nocolorprompting="$nocolorprompting[JHBuild]"
  33 fi
  34 
  35 if [ -f "$HOME/.bash_addps" ]
  36 then
  37     exec 3< "$HOME/.bash_addps"
  38     read -u 3 -r oneline
  39     colorprompting="$oneline $colorprompting"
  40     read -u 3 -r oneline
  41     nocolorprompting="$oneline $nocolorprompting"
  42     exec 3<&-
  43     unset oneline
  44 fi
  45 
  46 if [ "$WINDOW" ]
  47 then
  48     colorprompting="$colorprompting<$WINDOW>"
  49     nocolorprompting="$nocolorprompting<$WINDOW>"
  50 fi
  51 
  52 if [ "$TMUX_PANE" ]
  53 then
  54     colorprompting="$colorprompting$TMUX_PANE"
  55     nocolorprompting="$nocolorprompting$TMUX_PANE"
  56 fi
  57 
  58 colorprompting="${colorprompting}\\$ "
  59 nocolorprompting="${nocolorprompting}\\$ "
  60 
  61 historycountfile="$HOME/.bash_history.count"
  62 historybackupfile="$HOME/.bash_history.bak"
  63 bgrunfiledir="$HOME/tmp/bgrun-`whoami`"
  64 trashdir="$HOME/trash"
  65 
  66 HISTSIZE=2147483647
  67 HISTFILESIZE=2147483647
  68 HISTCONTROL=ignoredups:ignorespace
  69 HISTTIMEFORMAT="%F %T "
  70 
  71 REALPATH_PROGRAM="realpath"
  72 
  73 CFLAGS="-Wall -pipe -g"
  74 
  75 
  76 # Environment Variables
  77 
  78 export EDITOR=vim
  79 export FCEDIT=vim
  80 export PAGER=less
  81 
  82 
  83 
  84 
  85 # Aliases
  86 
  87 alias startcolor='PS1=$colorprompting'
  88 alias stopcolor='PS1=$nocolorprompting'
  89 
  90 alias ll='ls -l'
  91 alias grep='grep --color=always'
  92 alias rm='rm -i'
  93 alias cp='cp -pi'
  94 alias mv='mv -i'
  95 alias jobs='jobs -l'
  96 alias less='less -RS'
  97 
  98 alias cccc='LANG=C;LANGUAGE=C;LC_ALL=C'
  99 alias enus='LANG=en_US.UTF-8;LANGUAGE=en_US:en;LC_ALL=en_US.UTF-8'
 100 alias big5='LANG=zh_TW.Big5;LANGUAGE=zh_TW:zh;LC_ALL=zh_TW.Big5'
 101 alias zhtw='LANG=zh_TW.UTF-8;LANGUAGE=zh_TW:zh;LC_ALL=zh_TW.UTF-8'
 102 
 103 alias savetty='default_tty_setting=`stty -g`'
 104 alias resetty='stty $default_tty_setting'
 105 
 106 alias vimhtml='vim -c "set ts=2" -c "set sw=2"'
 107 alias screen256='screen -T screen-256color'
 108 
 109 
 110 # Functions
 111 
 112 function compile_all ()
 113 {
 114     local noask=0
 115     local mycc="${CC}"
 116     local mycxx="${CPP}"
 117     [ "$1" = '' ] && echo "Which file(s) do you want to compile? " && return 1
 118     [ "$1" = "-n" ] && noask=1
 119     if [ "$noask" = "0" ]; then
 120         read -e -p "CFLAGS: " -i "$CFLAGS" NEWCFLAGS
 121         read -e -p "LDFLAGS: " -i "$LDFLAGS" NEWLDFLAGS
 122         [ "$NEWCFLAGS" '!=' '' ] && CFLAGS=$NEWCFLAGS
 123         [ "$NEWLDFLAGS" '!=' '' ] && LDFLAGS=$NEWLDFLAGS
 124     else
 125         shift
 126     fi
 127     [ -z "${mycc}" ] && mycc=cc
 128     [ -z "${mycxx}" ] && mycxx=c++
 129     while [ "$1" '!=' '' ]
 130     do
 131         local TARGETFILE="`echo "$1" | cut -d . -f 1`"
 132         local SUFFIX="`echo "$1" | cut -d . -f 2`"
 133         if [ -f "$1" ]; then
 134             true
 135         else
 136             printf\
 137             "\e[1;33mWarning\e[0m: $1 Non-existent file or not a regular file\n"
 138             shift ; continue
 139         fi
 140         [ "$TARGETFILE" = "$1" ] && shift && continue
 141         if [ "$SUFFIX" = "c" ]; then
 142             echo "[${mycc}] $1 -> $TARGETFILE"
 143             ${mycc} $CFLAGS "$1" $LDFLAGS -o "$TARGETFILE"
 144         elif [ "$SUFFIX" = "cpp" ]; then
 145             echo "[${mycxx}] $1 -> $TARGETFILE"
 146             ${mycxx} $CFLAGS "$1" $LDFLAGS -o "$TARGETFILE"
 147         else
 148             printf "$1: Unknown suffix (\e[1;33mskipped\e[0m)\n"
 149         fi
 150         [ "$?" '!=' "0" ] && printf\
 151             '\e[1;31mError\e[0m while compiling file\n'
 152         shift
 153     done
 154     return 0
 155 }
 156 
 157 
 158 function convert_to_html ()
 159 {
 160     while [ "$1" '!=' '' ]
 161     do
 162         for i in "$1"
 163         do
 164             vim $i -c 'set background=dark' \
 165                 -c 'highlight PreProc ctermfg=darkcyan' \
 166                 -c "$BEFORE_CONVERT_TO_HTML" \
 167                 -c "$BEFORE_CONVERT_TO_HTML1" \
 168                 -c "$BEFORE_CONVERT_TO_HTML2" \
 169                 -c TOhtml \
 170                 -c :w \
 171                 -c :qa
 172         done
 173         shift
 174     done
 175 }
 176 
 177 function mkscreenacl ()
 178 {
 179     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"
 180     while [ "$1" '!=' '' ]
 181     do
 182         for i in $PERMIT_COMMAND
 183         do
 184             echo "aclchg $1 +x $i"
 185         done
 186         echo "aclchg $1 -rw \"\#?\""
 187         shift
 188     done
 189 }
 190 
 191 function get_file_size ()
 192 {
 193     split_arguments "$@"
 194     "${prefixlist[@]}" du -s "${arglist[@]}" | {
 195         read -d "   " dirsize
 196         echo "$dirsize"
 197         read throwaway
 198     }
 199     unset arglist
 200     unset prefixlist
 201 }
 202 
 203 ########## Background ##########
 204 
 205 alias bgr=bgrun
 206 alias bgv=bgview
 207 alias bgl=bglist
 208 alias bgc=bgcount
 209 alias bgls=bglist
 210 alias bgrm=bgclean
 211 
 212 function bgrun ()
 213 {
 214     [ "$#" = "0" ] && return 1
 215     [ '!' -d "$bgrunfiledir" ] && createdir_askmode "$bgrunfiledir" 0750
 216     local current_time=`date "+%Y%m%d-%H%M%S"`
 217     local cmdname=`echo "$1" | sed -e 's/-/_/g' -e 's/\\//_/g' -e 's/ /_/g'`
 218     if [ "`echo "$cmdname" | cut -c 1`" == "_" ]
 219     then
 220         cmdname=`echo "$cmdname" | cut -c 2-`
 221     fi
 222     local filename="$bgrunfiledir/$current_time-$cmdname"
 223     echo "Writing to $filename"
 224     {
 225         echo -n "$BASHPID " > "$filename"
 226         echo "$@" >> "$filename"
 227         exec "$@" &>> "$filename"
 228     } &
 229 }
 230 
 231 function bglist ()
 232 {
 233     local viewtime=0
 234     [ "$1" = "--full" ] && viewtime=1
 235     {
 236         for i in `find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort`
 237         do
 238             [ "$viewtime" = "1" ] && echo "$i"
 239             head -n 1 "$i" | {
 240                 local procpid
 241                 local cmdline
 242                 read -d ' ' procpid
 243                 read cmdline
 244                 printf "(%5d) %s\n" "$procpid" "$cmdline"
 245             }
 246         done
 247     } | {
 248         if [ "$viewtime" = "1" ]
 249         then
 250             echo " INDEX         TIME          PID   COMMAND"
 251             local readstat=0
 252             local -i i=1
 253             while true
 254             do
 255                 local dateandtime_long
 256                 local cmdline
 257                 read dateandtime_long
 258                 read cmdline
 259                 [ "$?" '!=' "0" ] && break
 260                 local dateandtime=`basename "$dateandtime_long"`
 261     ####        local part_year=`echo $dateandtime | cut -c 1-4`
 262     ####        local part_month=`echo $dateandtime | cut -c 5-6`
 263     ####        local part_date=`echo $dateandtime | cut -c 7-8`
 264     ####        local part_hour=`echo $dateandtime | cut -c 10-11`
 265     ####        local part_minute=`echo $dateandtime | cut -c 12-13`
 266     ####        local part_second=`echo $dateandtime | cut -c 14-15`
 267                 echo "$dateandtime" | {
 268                     read -n 4 part_year
 269                     read -n 2 part_month
 270                     read -n 2 part_date
 271                     read -n 1 drop_this_char; unset drop_this_char
 272                     read -n 2 part_hour
 273                     read -n 2 part_minute
 274                     read -n 2 part_second
 275                     printf '%6d' "$i"
 276                     echo " $part_year-$part_month-$part_date $part_hour:$part_minute:$part_second $cmdline"
 277                 }
 278                 i=$i+1
 279             done
 280         else
 281             echo " INDEX    PID   COMMAND"
 282             cat -n
 283         fi
 284     } | $PAGER
 285 }
 286 
 287 function bgview ()
 288 {
 289     local -i yourchoice
 290     if [ "$1" = "" ]
 291     then
 292         yourchoice=`bgcount`
 293     else
 294         if [ "$1" -le "0" ]
 295         then
 296             yourchoice=$((`bgcount`+$1))
 297         else
 298             yourchoice=$1
 299         fi
 300     fi
 301     echo "Your choice is $yourchoice."
 302     local realfilename=`find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort | sed -n ${yourchoice}p`
 303     head -n 1 "$realfilename" | {
 304         read -d ' ' procpid
 305         read cmdline
 306         echo "PID: $procpid"
 307         echo "Command Line: $cmdline"
 308     }
 309     read -e -p "View '$realfilename' ? " confirm
 310     if [ "$confirm" = "n" ] || [ "$confirm" = "N" ]
 311     then
 312         return 1
 313     fi
 314     {
 315         printf "===> Process Information: "
 316         cat "$realfilename"
 317     } | $PAGER
 318 }
 319 
 320 function bgcount ()
 321 {
 322     find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | cut -d - -f 2,3 | wc | awk '{print $2}'
 323 }
 324 
 325 function bgclean ()
 326 {
 327     if [ "$1" = "all" ]
 328     then
 329         echo "Removing the directory $bgrunfiledir"
 330         rm -rf "$bgrunfiledir" &
 331         return 0
 332     else
 333         split_arguments "$@"
 334         local -i i=0
 335         while [ "${arglist[$i]}" ]
 336         do
 337             arglist[$i]="-e ${arglist[$i]}p"
 338             i=$i+1
 339         done
 340         local oneline
 341         find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort | sed -n ${arglist[*]} | {
 342             while read oneline
 343             do
 344                 echo "Removing $oneline"
 345                 rm -f "$oneline"
 346             done
 347         }
 348     fi
 349     unset arglist
 350     unset prefixlist
 351 }
 352 
 353 function bgdu ()
 354 {
 355     local -i j=1
 356     {
 357         echo " INDEX     SIZE   PID   COMMAND"
 358         for i in `find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort`
 359         do
 360             head -n 1 "$i" | {
 361                 local procpid
 362                 local cmdline
 363                 read -d ' ' procpid
 364                 read cmdline
 365                 printf "%6d %8d (%5d) %s\n" "$j" \
 366                     "`get_file_size "$i"`" \
 367                     "$procpid" "$cmdline"
 368             }
 369             j=$j+1
 370         done
 371     } | $PAGER
 372 }
 373 
 374 ########## Background End ##########
 375 
 376 function check_dmesg ()
 377 {
 378     [ "$#" = "0" ] && return 1
 379 
 380     while true
 381     do
 382         PREVIOS_DMESG_BUF="$DMESG_BUF"
 383         DMESG_BUF="`dmesg`"
 384         [ "$PREVIOS_DMESG_BUF" '!=' "$DMESG_BUF" ] && [ "$FIRST_RUN" = "0" ] && echo '===> You should check the system message buffer <==='
 385         sleep $1
 386         [ "$?" '!=' "0" ] && return 1
 387         FIRST_RUN=0
 388     done
 389 }
 390 
 391 function check_system_status ()
 392 {
 393     [ "$#" = "0" ] && return 1
 394 
 395     filename_mail="$MAIL"
 396     filename_messages="/var/log/messages"
 397     filename_audit="/var/log/audit/audit.log"
 398 
 399     while true
 400     do
 401         previous_dmesg_buf="$current_dmesg_buf"
 402         current_dmesg_buf="`dmesg`"
 403         previous_mail_info="$current_mail_info"
 404         current_mail_info="`ls -l "$filename_mail"`"
 405         previous_messages_info="$current_messages_info"
 406         current_messages_info="`ls -l "$filename_messages"`"
 407         previous_audit_info="$current_audit_info"
 408         current_audit_info="`ls -l "$filename_audit"`"
 409         if [ "$first_run" = "0" ]
 410         then
 411             [ "$previous_dmesg_buf" '!=' "$current_dmesg_buf" ] && echo "===> The system message buffer is modified (dmesg) <==="
 412             [ "$previous_mail_info" '!=' "$current_mail_info" ] && echo "===> Your mailbox $filename_mail is modified <==="
 413             [ "$previous_messages_info" '!=' "$current_messages_info" ] && echo "===> $filename_messages is modified <==="
 414             [ "$previous_audit_info" '!=' "$current_audit_info" ] && echo "===> $filename_audit is modified <==="
 415         fi
 416         sleep $1
 417         first_run=0
 418     done
 419 }
 420 
 421 function prehistory_backup ()
 422 {
 423     echo "Checking your current history file"
 424     local -i currentcount=`cat "$HISTFILE" | wc -l`
 425     [ '!' -f "$historycountfile" ] && touch "$historycountfile"
 426     local -i previoushistorycount
 427     previoushistorycount=`cat "$historycountfile"`
 428     if [ "$currentcount" -lt "$previoushistorycount" ]
 429     then
 430         printf "\e[1;31mWarning\e[m: Your $HISTFILE may be TRUNCATED OR OVERWRITTEN BY OTHER PROGRAMS!\n"
 431         printf "Note: \e[1;33m$currentcount\e[m < $previoushistorycount\n"
 432         echo "Your $historycountfile and $historybackupfile will not be overwritten until this problem is fixed."
 433         echo " 1. Check your $HISTFILE."
 434         echo " 2. Edit your $HISTFILE manually if some unexpected changes are found."
 435         echo "    (You may need $historybackupfile to do it) "
 436         echo " 3. Remove the file $historycountfile."
 437         echo " 4. Run the command \`prehistory_backup' again."
 438         return 3
 439     fi
 440     echo -n "Backing up your current history file ($previoushistorycount -> $currentcount, "
 441     if [ "$previoushistorycount" = "$currentcount" ]
 442     then
 443         echo "no modification)"
 444     else
 445         echo "+$(($currentcount-$previoushistorycount)))"
 446     fi
 447     echo "$currentcount" > "$historycountfile"
 448     \cp -f "$HISTFILE" "$historybackupfile"
 449 }
 450 
 451 ########## Trash Manager ##########
 452 
 453 alias trash_put=trash_mv
 454 alias trash_add=trash_mv
 455 alias trash_list=trash_ls
 456 alias trash_ct=trash_count
 457 alias trash_restore=trash_recover
 458 alias trash_rc=trash_recover
 459 alias trash_drop=trash_rm
 460 alias trash_clean=trash_rm
 461 
 462 function trash_mv ()
 463 {
 464     [ "$#" = "0" ] && return 1
 465     [ '!' -d "$trashdir" ] && createdir_askmode "$trashdir" 0700
 466     local original_path
 467     local current_time
 468     local -i i=0
 469     split_arguments "$@"
 470     while [ "${arglist[$i]}" ]
 471     do
 472         original_path="`"${prefixlist[@]}" $REALPATH_PROGRAM "${arglist[$i]}"`"
 473         current_time=`date "+%Y%m%d-%H%M%S"`
 474         better_time=`date "+%Y-%m-%d %H:%M:%S"`
 475         dirname="`basename "${arglist[$i]}" | sed -e 's/-/_/g' -e 's/ /_/g'`"
 476         fulldirname="$trashdir/$current_time-$dirname"
 477         mkdir -p "$fulldirname"
 478         echo "Move: ${arglist[$i]} -> $fulldirname"
 479         "${prefixlist[@]}" mv "${arglist[$i]}" "$fulldirname"
 480         if [ "$?" = "0" ]
 481         then
 482             echo "$better_time" > "$fulldirname/information.date"
 483             echo "$original_path" > "$fulldirname/information.path"
 484         else
 485             rmdir "$fulldirname"
 486         fi
 487         i=$i+1
 488         shift
 489     done
 490     unset arglist
 491     unset prefixlist
 492 }
 493 
 494 function trash_rm ()
 495 {
 496     split_arguments "$@"
 497     local -i i=0
 498     while [ "${arglist[$i]}" ]
 499     do
 500         arglist[$i]="-e ${arglist[$i]}p"
 501         i=$i+1
 502     done
 503     trash_dirname=`find "$trashdir" -mindepth 1 -maxdepth 1 | sort | sed -n ${arglist[*]} `
 504     echo 'Type rm -rf $trash_dirname to remove them.'
 505     unset arglist
 506     unset prefixlist
 507 }
 508 
 509 function trash_ls ()
 510 {
 511     local -i i=1
 512     local oneline
 513     find "$trashdir" -mindepth 1 -maxdepth 1 | sort | {
 514         while read oneline
 515         do
 516             printf "%6d %s %s\n" "$i" \
 517                 "`cat "$oneline/information.date"`" \
 518                 "`cat "$oneline/information.path"`"
 519             i=$i+1
 520         done
 521     } | $PAGER
 522 }
 523 
 524 function trash_pushd ()
 525 {
 526     [ -z "$1" ] && return 1
 527     pushd `find "$trashdir" -mindepth 1 -maxdepth 1 | sort | sed -n $1p`
 528 }
 529 
 530 function trash_cd ()
 531 {
 532     [ -z "$1" ] && return 1
 533     cd `find "$trashdir" -mindepth 1 -maxdepth 1 | sort | sed -n $1p`
 534 }
 535 
 536 function trash_recover ()
 537 {
 538     [ -z "$1" ] && return 1
 539     split_arguments "$@"
 540     local -i i=0
 541     while [ "${arglist[$i]}" ]
 542     do
 543         arglist[$i]="-e ${arglist[$i]}p"
 544         i=$i+1
 545     done
 546     find "$trashdir" -mindepth 1 -maxdepth 1 | sort | sed -n ${arglist[*]} | {
 547         while read oneline
 548         do
 549             local fromfile="$oneline/`basename "$(cat "$oneline/information.path")"`"
 550             local tofile="`dirname "$(cat "$oneline/information.path")"`"
 551             if [ -e "`cat "$oneline/information.path"`" ]
 552             then
 553                 echo "Destination file exists."
 554                 continue
 555             fi
 556             echo "Move: $fromfile -> $tofile"
 557             "${prefixlist[@]}" mv -f "$fromfile" "$tofile"
 558             if [ "$?" = "0" ]
 559             then
 560                 echo "Remove: $oneline"
 561                 \rm -rf "$oneline"
 562             fi
 563         done
 564     }
 565     unset arglist
 566     unset prefixlist
 567 }
 568 
 569 function trash_count ()
 570 {
 571     find "$trashdir" -mindepth 1 -maxdepth 1 | wc | awk '{print $2}'
 572 }
 573 
 574 function trash_du ()
 575 {
 576     split_arguments "$@"
 577     local oneline
 578     local -i i=1
 579     find "$trashdir" -maxdepth 1 -mindepth 1 | sort | {
 580         while read oneline
 581         do
 582             printf "%6d %8d %s\n" "$i" \
 583                 "`get_file_size "$oneline" -- "${prefixlist[@]}"`" \
 584                 "`cat "$oneline/information.path"`"
 585             i=$i+1
 586         done
 587     } | $PAGER
 588     unset arglist
 589     unset prefixlist
 590 }
 591 
 592 ########## Trash Manager End ##########
 593 
 594 function split_arguments ()
 595 {
 596     local argcount=$#
 597     local -i i=0
 598     local prefix_start=0
 599     while [ "$1" ]
 600     do
 601         if [ "$prefix_start" == "0" ]
 602         then
 603             if [ "$1" = "--" ]
 604             then
 605                 prefix_start=1
 606                 i=0
 607                 shift
 608                 continue
 609             else
 610                 arglist[$i]="$1"
 611             fi
 612         else
 613             prefixlist[$i]="$1"
 614         fi
 615         i=$i+1
 616         shift
 617     done
 618 }
 619 
 620 function check_important_files ()
 621 {
 622     IMPORTANT_FILES="$HOME/.screenrc $HOME/.vimrc"
 623     for i in $IMPORTANT_FILES
 624     do
 625         [ '!' -f "$i" ] && printf "\e[1;31mWarning\e[m: \e[1;33m$i\e[m does not exist.\n"
 626     done
 627 }
 628 
 629 ########## PATH Editor ##########
 630 
 631 function split_path_core ()
 632 {
 633     echo "$current_path" | {
 634         while read -d : oneline
 635         do
 636             [ '!' "$oneline" = '^' ] && echo "$oneline"
 637         done
 638         [ '!' "$oneline" = '^' ] && echo "$oneline"
 639     }
 640     unset oneline
 641 }
 642 
 643 function split_path ()
 644 {
 645     coproc split_path_core
 646     readarray -t -u ${COPROC[0]} patharr
 647     wait $COPROC_PID
 648 }
 649 
 650 function update_path ()
 651 {
 652     current_path=''
 653     local -i i=0
 654     local firsttime="yes"
 655     while [ "${patharr[$i]}" ]
 656     do
 657         if [ '!' "${patharr[$i]}" = "^" ]
 658         then
 659             if [ "$firsttime" ]
 660             then
 661                 firsttime=''
 662             else
 663                 current_path+=':'
 664             fi
 665             current_path+="${patharr[$i]}"
 666         fi
 667         i=$i+1
 668     done
 669 }
 670 
 671 function old_path_editor ()
 672 {
 673     old_path_editor_core
 674 }
 675 
 676 function old_ldpath_editor ()
 677 {
 678     old_path_editor_core ld
 679 }
 680 
 681 function old_path_editor_core ()
 682 {
 683     if [ "$1" = "ld" ]
 684     then
 685         export current_path="$LD_LIBRARY_PATH"
 686     else
 687         export current_path="$PATH"
 688     fi
 689     local should_continue="yes"
 690     local command
 691     local command_sub
 692     local command_sub2
 693     local -i i
 694     while [ "$should_continue" ]
 695     do
 696         split_path
 697         i=0
 698         echo "========================================"
 699         while [ "${patharr[$i]}" ]
 700         do
 701             echo "$i: ${patharr[$i]}"
 702             i=$i+1
 703         done
 704         [ "$i" = '0' ] && echo "(Empty or not declared)"
 705         echo "========================================"
 706         read -e -p "[A]ppend/(D)elete/(E)dit/(M)ove/(R)eset/(Q)uit ? " command
 707         case "$command" in
 708             ''|A|a)
 709                 read -e -p "Type a new entry: " patharr[$i]
 710                 update_path
 711                 ;;
 712             D|d)
 713                 read -e -p "Index: " command_sub
 714                 patharr[$command_sub]='^'
 715                 update_path
 716                 ;;
 717             E|e)
 718                 read -e -p "Index: " command_sub
 719                 read -e -p "Modify this entry: " -i "${patharr[$command_sub]}" patharr[$command_sub]
 720                 update_path
 721                 ;;
 722             M|m)
 723                 read -e -p "From: " command_sub
 724                 read -e -p "To: " command_sub2
 725                 swaptmp="${patharr[$command_sub]}"
 726                 patharr[$command_sub]="${patharr[$command_sub2]}"
 727                 patharr[$command_sub2]="$swaptmp"
 728                 unset swaptmp
 729                 update_path
 730                 ;;
 731             R|r)
 732                 if [ "$1" = "ld" ]
 733                 then
 734                     current_path="$LD_LIBRARY_PATH"
 735                 else
 736                     current_path="$PATH"
 737                 fi
 738                 ;;
 739             Q|q)
 740                 if [ "$1" = "ld" ]
 741                 then
 742                     export LD_LIBRARY_PATH="$current_path"
 743                     echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
 744                     history -s "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
 745                 else
 746                     export PATH="$current_path"
 747                     echo "PATH=$PATH"
 748                     history -s "PATH=$PATH"
 749                 fi
 750                 should_continue=''
 751                 ;;
 752             *)
 753                 printf " \e[33m*** Unknown command ***\e[m \n"
 754                 ;;
 755         esac
 756     done
 757     unset patharr
 758     unset current_path
 759 }
 760 
 761 ########## PATH Editor End ##########
 762 
 763 ########## New PATH Editor ##########
 764 
 765 function ldpath_editor ()
 766 {
 767     path_editor LD_LIBRARY_PATH
 768 }
 769 
 770 function newpath_init ()
 771 {
 772     unset newpath
 773     local pathsp="$pathorgval"
 774     local pathentry
 775     local -i i
 776     eval pathsp='"${pathsp// /\\}"'
 777     pathsp="${pathsp//:/ }"
 778     i=0
 779     for pathentry in $pathsp
 780     do
 781         newpath[$i]="${pathentry//\\/ }"
 782         i=$i+1
 783     done
 784 }
 785 
 786 function newpath_gen ()
 787 {
 788     local -i i
 789     pathmodval=""
 790     i=0
 791     while [ "${newpath[$i]}" ]
 792     do
 793         if [ "$i" != 0 ]; then pathmodval+=":"; fi
 794         pathmodval+="${newpath[$i]}"
 795         i=$i+1
 796     done
 797 }
 798 
 799 function path_editor ()
 800 {
 801     local newpathvarname
 802     local badcommand
 803     local command
 804     local command_sub
 805     local command_sub2
 806     local should_continue="yes"
 807     local -i i
 808 
 809     if [ -z "$1" ]
 810     then
 811         newpathvarname="PATH"
 812     else
 813         newpathvarname="$1"
 814     fi
 815 
 816     eval pathorgval=\${${newpathvarname}}
 817     newpath_init
 818 
 819     while [ "$should_continue" ]
 820     do
 821         i=0
 822         echo -n $'\e[2J\e[0;0H'
 823         if [ "$badcommand" = "yes" ]; then
 824             printf " \e[33m*** Command \`$command' is unknown ***\e[m \n"
 825             badcommand=""
 826         fi
 827         echo "        New PATH Editor for BASH        "
 828         echo "========================================"
 829         echo "Environment Variable: $newpathvarname"
 830         echo "----------------------------------------"
 831         while [ "${newpath[$i]}" ]
 832         do
 833             echo "$i: ${newpath[$i]}"
 834             i=$i+1
 835         done
 836         [ "$i" = '0' ] && echo "(Empty or not declared)"
 837         echo "========================================"
 838         read -e -p "[A]ppend/(I)nsert/(D)elete/(E)dit/(M)ove/(S)wap/(R)eset/(Q)uit ? " command
 839         case "$command" in
 840             ''|A|a)
 841                 read -e -p "Type a new entry: " newpath[$i]
 842                 ;;
 843             I|i)
 844                 read -e -p "Type a new entry: " command_sub
 845                 if [ -z "$command_sub" ]; then continue; fi
 846                 newpath_tmp=( "${newpath[@]}" )
 847                 unset newpath
 848                 newpath="$command_sub"
 849                 i=0
 850                 while [ "${newpath_tmp[$i]}" ]
 851                 do
 852                     newpath[$i+1]="${newpath_tmp[$i]}"
 853                     i=$i+1
 854                 done
 855                 unset newpath_tmp
 856                 ;;
 857             D|d)
 858                 read -e -p "Index: " command_sub
 859                 if [ -z "$command_sub" ]; then continue; fi
 860                 i="$command_sub"
 861                 i=$i+1
 862                 while [ "${newpath[$i]}" ]
 863                 do
 864                     newpath[$i-1]="${newpath[$i]}"
 865                     i=$i+1
 866                 done
 867                 unset newpath[$i-1]
 868                 ;;
 869             E|e)
 870                 read -e -p "Index: " command_sub
 871                 read -e -p "Modify this entry: " -i "${newpath[$command_sub]}" newpath[$command_sub]
 872                 ;;
 873             M|m)
 874                 read -e -p "From: " command_sub
 875                 read -e -p "To: " command_sub2
 876                 if [ "$command_sub" -eq "$command_sub2" ]; then continue; fi
 877                 cmdsubval="${newpath[$command_sub]}"
 878                 if [ "$command_sub" -gt "$command_sub2" ]; then
 879                     i="$command_sub"
 880                     while [ "$i" -gt "$command_sub2" ]
 881                     do
 882                         newpath[$i]="${newpath[$i-1]}"
 883                         i=$i-1
 884                     done
 885                     newpath[$command_sub2]="$cmdsubval"
 886                 else
 887                     i="$command_sub"
 888                     while [ "$i" -lt "$command_sub2" ]
 889                     do
 890                         newpath[$i]="${newpath[$i+1]}"
 891                         i=$i+1
 892                     done
 893                     newpath[$command_sub2]="$cmdsubval"
 894                 fi
 895                 unset cmdsubval
 896                 ;;
 897             S|s)
 898                 read -e -p "First entry: " command_sub
 899                 read -e -p "Second entry: " command_sub2
 900                 swaptmp="${newpath[$command_sub]}"
 901                 newpath[$command_sub]="${newpath[$command_sub2]}"
 902                 newpath[$command_sub2]="$swaptmp"
 903                 unset swaptmp
 904                 ;;
 905             R|r)
 906                 read -e -p "Discard all changes [y/N] ? " command_sub
 907                 if [ "$command_sub" = "y" ]; then
 908                     eval pathorgval=\${${newpathvarname}}
 909                     newpath_init
 910                 fi
 911                 ;;
 912             Q|q)
 913                 newpath_gen
 914                 eval export ${newpathvarname}=\"$pathmodval\"
 915                 echo "${newpathvarname}=$pathmodval"
 916                 history -s "${newpathvarname}=$pathmodval"
 917                 should_continue=''
 918                 ;;
 919             *)
 920                 badcommand="yes"
 921                 ;;
 922         esac
 923     done
 924     unset newpath
 925     unset pathorgval
 926     unset pathmodval
 927 }
 928 
 929 ########## New PATH Editor End ##########
 930 
 931 ########## Configuration File ##########
 932 
 933 function configfile_fetch ()
 934 {
 935     local cgit_mirror_list=(
 936         "http://www.tfcis.org/~lantw44/cgit/cgit.cgi/configfile/plain"
 937         "http://phantom.tfcis.org/~lantw44/cgit/cgit.cgi/configfile/plain"
 938         "http://master.lant.com.tw/~lantw44/cgit/cgit.cgi/configfile/plain")
 939     local github_mirror_list=(
 940         "https://raw.github.com/lantw44/configfile"
 941         "http://raw.github.com/lantw44/configfile")
 942     local args
 943     local file_url
 944     local file_version
 945     local completed
 946     local -a file_name
 947     local -i i
 948     local -i j
 949 
 950     if [ "$1" ]; then
 951         file_version="$1"
 952     else
 953         file_version="master"
 954     fi
 955 
 956     args=("$@")
 957     for((i=2, j=0; i<=$#; i++, j++)){
 958         file_name[$j]="${args[$i]}"
 959     }
 960 
 961     if [ -z "$file_name"]; then
 962         file_name=("bash_include" "vimrc" "screenrc")
 963     fi
 964 
 965     for file in ${file_name[@]}
 966     do
 967         completed="false"
 968 
 969         for site in ${cgit_mirror_list[@]}
 970         do
 971             [ "$completed" = "true" ] && break
 972             file_url="$site/$file?id=$file_version"
 973             if fetch_and_merge "$HOME/.${file}" "$file_url"
 974             then
 975                 completed="true"
 976                 break
 977             fi
 978         done
 979 
 980         for site in ${github_mirror_list[@]}
 981         do
 982             [ "$completed" = "true" ] && break
 983             file_url="$site/$file_version/$file"
 984             if fetch_and_merge "$HOME/.${file}" "$file_url"
 985             then
 986                 completed="true"
 987                 break
 988             fi
 989         done
 990 
 991     done
 992 }
 993 
 994 function configfile_initial_setup ()
 995 {
 996     cat >> ~/.bashrc << EOF
 997 if [ -f ~/.bash_include ]; then
 998     . ~/.bash_include
 999 fi
1000 EOF
1001     if [ "`uname`" = "FreeBSD" ]; then
1002         cat >> ~/.bash_login << EOF
1003 GET_TTY_NAME=`tty | cut -c 9`
1004 [ "$GET_TTY_NAME" = 'v' ] && echo "Login from local virtual terminal: `tty`"
1005 [ "$GET_TTY_NAME" = 'p' ] && echo "Login from pseudo terminal: `tty`"
1006 [ "$GET_TTY_NAME" = '/' ] && echo "Login from pseudo terminal: `tty`"
1007 unset GET_TTY_NAME
1008 EOF
1009     fi
1010     cat >> ~/.bash_login << EOF
1011 if [ -f ~/.bash_include ]; then
1012     . ~/.bashrc
1013 fi
1014 EOF
1015 }
1016 
1017 function fetch_remote_file ()
1018 {
1019     local rval
1020     printf "==> Fetch remote file \e[1;33m$2\e[m as \e[1;35m$1\e[m ...\n"
1021     if check_command_existent curl; then
1022         curl -f -o "$1" "$2"
1023         rval=$?
1024     elif check_command_existent fetch; then
1025         fetch -o "$1" "$2"
1026         rval=$?
1027     elif check_command_existent wget; then
1028         wget --progress=dot -O "$1" "$2"
1029         rval=$?
1030     else
1031         echo "<== Sorry, I don't know how to fetch remote files on your system"
1032         return 1
1033     fi
1034     if [ "$rval" = "0" ]; then
1035         printf "<== \e[1;32mDone\e[m\n"
1036     else
1037         printf "<== \e[1;31mFailed\e[m\n"
1038     fi
1039     return $rval
1040 }
1041 
1042 function fetch_and_merge ()
1043 {
1044     local merge_cmd
1045     local merge_cmd_prog
1046     local local_file="$1"
1047     local remote_file="$2"
1048     if fetch_remote_file "${local_file}.new" "${remote_file}"
1049     then
1050         if [ '!' -e "${local_file}" ]; then
1051             mv -vf "${local_file}.new" "${local_file}"
1052         else
1053             while true
1054             do
1055                 echo ""
1056                 printf "Configuration files update tool: "
1057                 printf "Updating \e[1;35m${local_file}\e[m\n"
1058                 echo ""
1059                 echo " Install: Install the new version"
1060                 echo " Keep:    Keep the old version"
1061                 echo " Retry:   Give up downloaded file and try the next mirror"
1062                 echo ""
1063                 echo " Diff:    View the difference between versions"
1064                 echo " Merge:   Merge two files by yourself"
1065                 echo ""
1066                 read -e -p "[I]nstall/(K)eep/(R)etry/(D)iff/(M)erge ? " merge_cmd
1067                 case "${merge_cmd}" in
1068                     ''|I|i)
1069                         mv -vf "${local_file}.new" "${local_file}"
1070                         break
1071                         ;;
1072                     K|k)
1073                         rm -f "${local_file}.new"
1074                         break
1075                         ;;
1076                     R|r)
1077                         rm -f "${local_file}.new"
1078                         return 1
1079                         ;;
1080                     D|d)
1081                         diff -u "${local_file}" "${local_file}.new" | $PAGER
1082                         ;;
1083                     M|m)
1084                         read -e -p "Merge tool: " -i "$merge_cmd_prog" merge_cmd_prog
1085                         if $merge_cmd_prog "${local_file}" "${local_file}.new"; then
1086                             break
1087                         else
1088                             echo "Command is exited with error. Please try again."
1089                         fi
1090                         ;;
1091                     *)
1092                         printf " \e[33m*** Unknown command ***\e[m \n"
1093                         ;;
1094                 esac
1095             done
1096         fi
1097         return 0
1098     fi
1099     return 1
1100 }
1101 
1102 ########## Configuration File End  ##########
1103 
1104 function varset ()
1105 {
1106     local varoldvalue
1107     local varnewvalue
1108     while [ "$1" ]
1109     do
1110         eval varoldvalue=\${$1}
1111         read -r -e -p "$1=" -i "$varoldvalue" varnewvalue
1112         eval $1=\"$varnewvalue\"
1113         shift
1114     done
1115 }
1116 
1117 function is_file_type ()
1118 {
1119     local filename="$1"
1120     local typename="$2"
1121     shift 2
1122     [ "`"$@" find "$filename" -maxdepth 0 -type "$typename"`" ] && return 0
1123     return 1
1124 }
1125 
1126 function editlink ()
1127 {
1128     local newdest
1129     local orgdest
1130     split_arguments "$@"
1131     local -i i=0
1132     while [ "${arglist[$i]}" ]
1133     do
1134         if is_file_type "${arglist[$i]}" "l" "${prefixlist[@]}"; then
1135             orgdest="`${prefixlist[@]} readlink "${arglist[$i]}"`"
1136             read -e -p "EditLink: ${arglist[$i]} -> " -i "$orgdest" newdest
1137         else
1138             printf "\e[1;33mWarning\e[m: ${arglist[$i]} is not a symbolic link.\n"
1139             i=$i+1
1140             continue
1141         fi
1142         if [ "$newdest" ] && [ "$newdest" '!=' "$orgdest" ]; then
1143             "${prefixlist[@]}" rm -f "${arglist[$i]}"
1144             "${prefixlist[@]}" ln -sv "$newdest" "${arglist[$i]}"
1145         fi
1146         i=$i+1
1147     done
1148     unset arglist
1149     unset prefixlist
1150 }
1151 
1152 function backup_file ()
1153 {
1154     split_arguments "$@"
1155     local current_time=`date +%Y%m%d`
1156     local rootfilename
1157     local -i i=0
1158     local -i j
1159     while [ "${arglist[$i]}" ]
1160     do
1161         if [ '!' -f "${arglist[$i]}" ]
1162         then
1163             printf "\e[1;31mError\e[m: ${arglist[$i]} does not exist or it is not a regular file.\n"
1164             i=$i+1
1165             continue
1166         fi
1167         rootfilename="${arglist[$i]}.$current_time"
1168         if [ -e "$rootfilename" ]
1169         then
1170             j=0
1171             while [ "$j" -lt "10" ]
1172             do
1173                 if [ -e "$rootfilename.$j" ]
1174                 then
1175                     j=$j+1
1176                     continue
1177                 else
1178                     "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename.$j"
1179                     history -s "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename.$j"
1180                     "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename.$j"
1181                     history -s "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename.$j"
1182                     break
1183                 fi
1184             done
1185             if [ '!' "$j" -lt "10" ]
1186             then
1187                 printf "\e[1;31mError\e[m: Can not create a backup file for ${arglist[$i]}.\n"
1188                 printf "\e[1;33mPlease delete some backup file because I only use 0 - 9.\e[m\n"
1189             fi
1190         else
1191             "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename"
1192             history -s "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename"
1193             "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename"
1194             history -s "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename"
1195         fi
1196         i=$i+1
1197     done
1198     unset arglist
1199     unset prefixlist
1200 }
1201 
1202 function keep_sudo_credential ()
1203 {
1204     if [ "$1" ]
1205     then
1206         update_sudo_interval="$1"
1207     else
1208         update_sudo_interval="280"
1209     fi
1210     while true
1211     do
1212         sudo -v
1213         sleep "$update_sudo_interval"
1214     done
1215 }
1216 
1217 function get_memory_info ()
1218 {
1219     case "`uname`" in
1220         "Linux"|"GNU")
1221             local meminfoline="`free -m | \grep -i mem`"
1222             local swapinfoline="`free -m | \grep -i swap`"
1223             local memtotal="`echo "$meminfoline" | awk '{print $2}'`"
1224             local memused="`echo "$meminfoline" | awk '{print $3}'`"
1225             local membuf="`echo "$meminfoline" | awk '{print $6}'`"
1226             local memcache="`echo "$meminfoline" | awk '{print $7}'`"
1227             local memprog=$(($memused-$membuf-$memcache))
1228             local swaptotal="`echo "$swapinfoline" | awk '{print $2}'`"
1229             local swapused="`echo "$swapinfoline" | awk '{print $3}'`"
1230             echo "Memory: $memused / $memtotal MB (`printf %2d $(($memused*100/$memtotal))`%)"
1231             echo "Detail:"
1232             echo "    Used:    `printf %5d $memprog` MB (`printf %2d $(($memprog*100/$memtotal))`%)"
1233             echo "    Buffers: `printf %5d $membuf` MB (`printf %2d $(($membuf*100/$memtotal))`%)"
1234             echo "    Cached:  `printf %5d $memcache` MB (`printf %2d $(($memcache*100/$memtotal))`%)"
1235             if [ "$swaptotal" = "0" ]
1236             then
1237                 echo "Swap: not available"
1238             else
1239                 echo "Swap: $swapused / $swaptotal MB (`printf %2d $(($swapused*100/$swaptotal))`%)"
1240             fi
1241             ;;
1242         "FreeBSD")
1243             local mempagesize="`sysctl -n hw.pagesize`"
1244             local mempagecount="`sysctl -n hw.availpages`"
1245             local memactive="`sysctl -n vm.stats.vm.v_active_count`"
1246             local meminactive="`sysctl -n vm.stats.vm.v_inactive_count`"
1247             local memwire="`sysctl -n vm.stats.vm.v_wire_count`"
1248             local memcache="`sysctl -n vm.stats.vm.v_cache_count`"
1249             local memfree="`sysctl -n vm.stats.vm.v_free_count`"
1250             local swapenabled="`sysctl -n vm.swap_enabled`"
1251             echo "Memory (Active):   `printf %5d $(($memactive*$mempagesize/1048576))` MB (`printf %2d $(($memactive*100/$mempagecount))`%)"
1252             echo "Memory (Inactive): `printf %5d $(($meminactive*$mempagesize/1048576))` MB (`printf %2d $(($meminactive*100/$mempagecount))`%)"
1253             echo "Memory (Wired):    `printf %5d $(($memwire*$mempagesize/1048576))` MB (`printf %2d $(($memwire*100/$mempagecount))`%)"
1254             echo "Memory (Cache):    `printf %5d $(($memcache*$mempagesize/1048576))` MB (`printf %2d $(($memcache*100/$mempagecount))`%)"
1255             echo "Memory (Free):     `printf %5d $(($memfree*$mempagesize/1048576))` MB (`printf %2d $(($memfree*100/$mempagecount))`%)"
1256             echo "Total Memory:      `printf %5d $(($mempagecount*$mempagesize/1048576))` MB"
1257             if [ "$swapenabled" = "1" ]; then
1258                 echo ""
1259                 echo "Swap devices:"
1260                 swapinfo -m
1261             else
1262                 echo "Swap: not enabled"
1263             fi
1264             ;;
1265         *)
1266             echo "Unsupported operating system."
1267             ;;
1268     esac
1269 }
1270 
1271 function set_console_title ()
1272 {
1273     case "$TERM" in
1274         screen*)
1275             printf "\033]0;"
1276             echo -n "$*"
1277             printf "\033\\"
1278             ;;
1279         xterm*)
1280             printf "\033]0;"
1281             echo -n "$*"
1282             printf "\007"
1283             ;;
1284         *)
1285             echo "Your terminal may not have the hardstatus line."
1286             echo "Note: TERM=$TERM"
1287             ;;
1288     esac
1289 }
1290 
1291 function mvfile ()
1292 {
1293     local nocheck=0
1294     [ "$1" = "-n" ] && nocheck=1 && shift
1295     split_arguments "$@"
1296     local -i i=0
1297     while [ "${arglist[$i]}" ]
1298     do
1299         if [ "$nocheck" = "0" ] && [ '!' -e "${arglist[$i]}" ]
1300         then
1301             printf "\e[33mWarning\e[m: ${arglist[$i]} does not exist. (Use -n to override)\n"
1302             i=$i+1
1303             continue
1304         fi
1305         echo "Old name: ${arglist[$i]}"
1306         read -p "New name: " -e -i "${arglist[$i]}" new_file_name
1307         if [ "$new_file_name" ] && [ "${arglist[$i]}" != "$new_file_name" ]
1308         then
1309             "${prefixlist[@]}" mv -iv "${arglist[$i]}" "$new_file_name"
1310             history -s "${prefixlist[@]}" mv -iv "${arglist[$i]}" "$new_file_name"
1311         fi
1312         i=$i+1
1313     done
1314     unset arglist
1315     unset prefixlist
1316     unset new_file_name
1317 }
1318 
1319 function createdir_askmode ()
1320 {
1321     newdir_mode="$2"
1322     if mkdir -p "$1"
1323     then
1324         echo "Directory $1 is created."
1325         printf "Change the mode of the directory... "
1326         read -i "$newdir_mode" -p ">>> Mode: " -e newdir_mode
1327         chmod "$newdir_mode" "$1"
1328     else
1329         echo "Cannot create directory $1!"
1330         return 1
1331     fi
1332 }
1333 
1334 function get_terminal_size ()
1335 {
1336     # ESC 7              = 儲存游標位置和屬性
1337     # ESC [r             = 啟用全螢幕捲動
1338     # ESC [{row};{col}H  = 移動游標
1339     # ESC 6n             = 回報目前游標位置
1340     # ESC 8              = 還原游標位置和屬性
1341     echo -n $'\e7\e[r\e[999;999H\e[6n\e8' 1>&2
1342     read -s -d R getsize
1343     echo $getsize | sed 's#..\([0-9]*\);\([0-9]*\)#LINES=\1 COLUMNS=\2#'
1344 }
1345 
1346 function set_terminal_size ()
1347 {
1348     eval "export `get_terminal_size`"
1349     stty cols $COLUMNS rows $LINES
1350 }
1351 
1352 function unzip_nomac ()
1353 {
1354     unzip "$@" -x '__MACOSX/*' '*.DS_Store'
1355     return $?
1356 }
1357 
1358 function gen_ms_inet_shortcut () {
1359     [ "$#" != "2" ] && {
1360         echo "Usage: $FUNCNAME filename url"
1361     } && return 1
1362 
1363     {
1364         echo "[InternetShortcut]"
1365         echo "URL=$2"
1366     } > "$1"
1367 }
1368 
1369 function check_command_existent ()
1370 {
1371     which "$1" &> /dev/null
1372     return $?
1373 }
1374 
1375 function rpmdu () {
1376     local div_base=1
1377     local div_name="KB"
1378     local total=0
1379     if [ "`echo "$1" | cut -c 1`" = "-" ]
1380     then
1381         local optname=`echo "$1" | cut -c 2-`
1382         case "$optname" in
1383             "k")
1384                 ;;
1385             "m")
1386                 div_base=1024
1387                 div_name=MB
1388                 ;;
1389             "g")
1390                 div_base=1048576
1391                 div_name=GB
1392                 ;;
1393             *)
1394                 echo "Usage: $FUNCNAME [OPTION] package_name..."
1395                 echo "    -k KB"
1396                 echo "    -m MB"
1397                 echo "    -g GB"
1398                 return 1
1399                 ;;
1400         esac
1401         shift
1402     fi
1403 
1404     while [ "$1" ]
1405     do
1406         rpm -ql "$1" | {
1407             while read oneline
1408             do
1409                 if [ -f "$oneline" ]
1410                 then
1411                     du -k "$oneline"
1412                 fi
1413             done
1414         } | {
1415             while read -d $'\t' filesize
1416             do
1417                 total=$((${total}+${filesize}))
1418                 read
1419             done
1420             printf "%9d %s %s\n" "$(($total/$div_base))" "$div_name" "$1"
1421         }
1422 
1423         shift
1424     done
1425 }
1426 
1427 function rpmsize () {
1428     local div_base=1
1429     local div_name="Bytes"
1430     local total=0
1431     local filesize
1432     if [ "`echo "$1" | cut -c 1`" = "-" ]
1433     then
1434         optname=`echo "$1" | cut -c 2-`
1435         case "$optname" in
1436             "b")
1437                 ;;
1438             "k")
1439                 div_base=1024
1440                 div_name=KB
1441                 ;;
1442             "m")
1443                 div_base=1048576
1444                 div_name=MB
1445                 ;;
1446             "g")
1447                 div_base=1073741824
1448                 div_name=GB
1449                 ;;
1450             *)
1451                 echo "Usage: $FUNCNAME [OPTION] package_name..."
1452                 echo "    -b Byte"
1453                 echo "    -k KB"
1454                 echo "    -m MB"
1455                 echo "    -g GB"
1456                 return 1
1457                 ;;
1458         esac
1459         shift
1460     fi
1461     while [ "$1" ]
1462     do
1463         total=0
1464         filesize=`rpm -q "$1" --queryformat "%{SIZE} "`
1465         for i in $filesize
1466         do
1467             total=$((${total}+${i}))
1468         done
1469         printf "%12d %s %s\n" "$(($total/$div_base))" "$div_name" "$1"
1470         shift
1471     done
1472 }
1473 
1474 function freebsd_ports_should_rebuild () {
1475     reqcomp=$(ldd -f '%a %o %p\n' /usr/local/bin/* /usr/local/sbin/* \
1476         2>/dev/null | grep 'not found' | \
1477         { while read oneline; do echo ${oneline} | cut -d ' ' -f 1; done; } | uniq)
1478     reqpkg=$({ for i in $reqcomp; do pkg_info -q -W $i; done } | sort | uniq)
1479     echo $reqpkg
1480 }
1481 
1482 ########## Help ##########
1483 
1484 alias helpf='help_function'
1485 alias helpm='help_myself'
1486 
1487 function print_iconv ()
1488 {
1489     [ "$1" = "$2" ] && cat && return 0
1490     iconv -f "$1" -t "$2"
1491 }
1492 
1493 function help_myself ()
1494 {
1495     echo "argc = $#"
1496     echo "argv[0] = $0"
1497     i=1
1498     while [ "$1" ]
1499     do
1500         echo "argv[$i] = $1"
1501         i=$(($i+1))
1502         shift
1503     done
1504 }
1505 
1506 function help_obsolete ()
1507 {
1508     cat << ENDHELPMSG
1509  @@@ Obsolete Group: PATH Editor @@@
1510     old_path_editor
1511     old_ldpath_editor
1512  x  split_path
1513  x  split_path_core
1514  x  update_path 
1515  x  old_path_editor_core
1516 ENDHELPMSG
1517 }
1518 
1519 function help_function ()
1520 {
1521     [ "$#" = "0" ] && {
1522         cat << ENDHELPMSG
1523  <<< Help >>>
1524     help_myself [arguments ...]                            (helpm)
1525     help_function [functions ...]                          (helpf)
1526     help_obsolete
1527  x  print_iconv
1528 
1529  <<< Group: Background >>>
1530     bgrun command [arguments ...]                          (bgr)
1531     bglist [--full]                                        (bgl, bgls)
1532     bgview [number]                                        (bgv)
1533     bgclean [all | numbers ...]                            (bgrm)
1534     bgcount                                                (bgc)
1535     bgdu
1536  <<< Group: Trash >>>
1537     trash_mv [filenames ...] [-- sudo_prefix ...]     (trash_put, trash_add)
1538     trash_ls                                          (trash_list)
1539     trash_cd number
1540     trash_pushd number
1541     trash_recover numbers ... [-- sudo_prefix ...]    (trash_restore, trash_rc)
1542     trash_rm numbers ...                              (trash_drop, trash_clean)
1543     trash_count                                       (trash_ct)
1544     trash_du [-- sudo_prefix ...]
1545  <<< Group: New PATH Editor >>>
1546     path_editor [variable]
1547     ldpath_editor
1548  x  newpath_init
1549  x  newpath_gen
1550  <<< Group: Configuration File >>>
1551     configfile_fetch [git_tag [file_name_list ...]]
1552     configfile_initial_setup
1553  x  fetch_remote_file local_file_name remote_url
1554  x  fetch_and_merge local_file_name remote_url
1555 
1556  <<< System: Terminal >>>
1557     set_console_title
1558     set_terminal_size
1559  <<< System: Information >>>
1560     get_memory_info
1561  <<< System: Packages Management >>>
1562     rpmdu [-kmg] packages ...
1563     rpmsize [-bkmg] packages ...
1564     freebsd_ports_should_rebuild
1565  <<< System: Privileges >>>
1566     keep_sudo_credential [seconds]
1567 
1568  <<< Tools: Interactive >>>
1569     compile_all [-n] filenames ...
1570     editlink filenames ... [-- sudo_prefix ...]
1571     mvfile [-n] filenames ... [-- sudo_prefix ...]
1572     varset variables ...
1573  <<< Tools: Non-interactive >>>
1574     backup_file filename ... [-- sudo_prefix ...]
1575     convert_to_html filename ...
1576     mkscreenacl usernames ...
1577 
1578  <<< Miscellaneous: Background Jobs >>>
1579     check_dmesg seconds
1580     check_system_status seconds
1581  <<< Miscellaneous: Compatibility >>>
1582     gen_ms_inet_shortcut filename url
1583     unzip_nomac filenames ...
1584  <<< Miscellaneous: Personal >>>
1585     check_important_files
1586     prehistory_backup
1587 
1588  <<< Shared Internal Functions >>>
1589  x  createdir_askmode dirname
1590  x  check_command_existent program
1591  x  is_file_type filename type [-- sudo_prefix ...]
1592  x  get_file_size filename [-- sudo_prefix ...]
1593  x  get_terminal_size
1594  x  split_arguments [arguments ...]
1595 
1596 Obsolete functions are not printed. Type \`help_obsolete' to print them.
1597 ENDHELPMSG
1598     } && return 0
1599     local current_charset=`echo "$LC_ALL" | cut -d . -f 2`
1600     local -i i
1601     while [ "$1" ]
1602     do
1603         case "$1" in
1604             help_myself|helpm)
1605                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1606 help_myself
1607     一個測試命令列的小函式
1608 ENDHELPMSG
1609                 ;;
1610             help_function|helpf)
1611                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1612 help_function
1613     顯示 .bash_include 提供的額外函式清單
1614     註:前方加上「x」符號者表示此為內部使用的函式,不宜直接使用
1615 ENDHELPMSG
1616                 ;;
1617             bgrun|bgr)
1618                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1619 bgrun command [arguments ...]
1620     執行指令 command 並將輸出導入檔案
1621     註:此函式會自動以目前時間和指令名稱為檔案命名
1622 ENDHELPMSG
1623                 ;;
1624             bglist|bgl|bgls)
1625                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1626 bglist [--full]
1627     列出所有使用 bgrun 執行的指令
1628     若加上 --full 選項,則可同時察看時間
1629 ENDHELPMSG
1630                 ;;
1631             bgview|bgv)
1632                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1633 bgview [number]
1634     顯示以 bgrun 執行指令的輸出,若省略 number,表示是最近一次執行的指令
1635     若 number >  0,
1636         表示第 number 個指令 (此數值可由 bglist 函式取得)
1637     若 number <= 0,
1638         表示第「指令總數-number」個指令 (指令總數可由 bgcount 函式取得)
1639 ENDHELPMSG
1640                 ;;
1641             bgclean|bgrm)
1642                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1643 bgclean [all | numbers ...]
1644     bgclean all 可清除所有指令的輸出檔
1645     bgclean 3 5 7 10 表示清除第 3、5、7、10 個指令輸出檔 (編號可由 bglist 取得)
1646 ENDHELPMSG
1647                 ;;
1648             bgcount|bgc)
1649                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1650 bgcount
1651     顯示指令輸出檔總數
1652 ENDHELPMSG
1653                 ;;
1654             bgdu)
1655                 cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset"
1656 bgdu
1657     顯示每個指令輸出檔的檔案大小 (單位:KB)
1658 ENDHELPMSG
1659                 ;;
1660             *)
1661                 echo "Help message for $1 is not found"
1662                 ;;
1663         esac
1664         shift
1665     done
1666 }
1667 
1668 ########## Help End ##########
1669 
1670 # Doing something
1671 
1672 umask 0022
1673 
1674 if [ "$interactive_shell" ]
1675 then
1676     echo "Running interactive shell configuration"
1677     check_important_files
1678     startcolor
1679     prehistory_backup
1680     bind '"\e[A":history-search-backward'
1681     bind '"\e[B":history-search-forward'
1682     if [ -z "$PROMPT_COMMAND" ] && [ -e "$HOME/.bash_title" ]; then
1683         case "$TERM" in
1684             xterm*)
1685                 PROMPT_COMMAND='printf "\033]0;%s@%s:%s (%s)\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" "`date "+%H:%M:%S"`"'
1686                 ;;
1687             screen*)
1688                 PROMPT_COMMAND='printf "\033]0;%s@%s:%s (%s)\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" "`date "+%H:%M:%S"`"'
1689                 ;;
1690         esac
1691     fi
1692     [ "$TERM" = xterm ] && TERM=xterm-256color
1693     [ "$TERM" = screen ] && TERM=screen-256color
1694 fi
1695 
1696 if [ "`uname`" = "Linux" ]
1697 then
1698     [ "$interactive_shell" ] && echo "Setting special things for Linux"
1699     REALPATH_PROGRAM="readlink -f"
1700     ulimit -c unlimited
1701 fi
1702 
1703 [ "$interactive_shell" ] && echo "Setting shell options"
1704 
1705 shopt -s histappend
1706 shopt -s checkwinsize
1707 shopt -s checkjobs
1708 shopt -s checkhash
1709 shopt -s cmdhist
1710 shopt -s mailwarn
1711 
1712 [ "$interactive_shell" ] && {
1713     if [ "$WINDOW" ] && type screen &> /dev/null; then
1714         if [[ "`screen --version`" == *4.01* ]]; then
1715             echo "Setting options for GNU screen 4.1.0"
1716             screen -X cjkwidth off
1717         fi
1718     fi
1719 }
1720 
1721 [ "$interactive_shell" ] && {
1722     echo "Done"
1723     if [ "$UID" = "0" ] || [ "$EUID" = "0" ]
1724     then
1725         printf "\nNote: You may be \e[1;32mprivileged\e[m now!\n\n"
1726     fi
1727 }
1728