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