Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- readv() { IFS='' read -rd '' $1; }
- readv LICENSE << 'EOT'
- ttycomfy v0.2.0
- Copyright (c) 2020 Benjamin Isaac McCann
- ---D1TW Fair Distribution License v0.7.0---
- 1)
- The Licensor, henceforth the "Original Publisher,"
- of the work hereby provided as Consideration,
- henceforth the "Original Work," hereby grants any person,
- henceforth an "Original Recipient," unrestricted permission
- to use, copy, and/or produce private derivative works
- of the Original Work, without being charged royalties.
- 2)
- The Original Publisher hereby grants all Original Recipients
- limited permission to publish and/or sell copies and/or derivative
- works of the Original Work, without being charged royalties,
- subject to the following restrictions:
- 2.a)
- The Original Publisher hereby reserves the exclusive right
- to relicense or sublicense the Original Work.
- 2.b)
- Pursuant to paragraph 2.a, the Original Publisher hereby denies
- the publisher, henceforth a "Sub-Publisher," of any copy
- or derivative work, henceforth a "Sub-Publication,"
- of the Original Work, the permission to sublicense any portion
- of the Original Work, whether in distributing their Sub-Publication
- or otherwise.
- 2.b.i)
- Pursuant to paragraph 2.b, a Sub-Publisher shall not misconstrue,
- explicitly or otherwise, any portion of the Original Work
- as being a consideration to any license agreement applicable
- to the Sub-Publisher's own Sub-Publication.
- 2.b.ii)
- Pursuant to paragraph 2.b.i, in order to avoid so misconstruing
- any such portion of the Original Work, the Sub-Publisher shall
- explicitly disclaim from the license agreement applicable
- to the Sub-Publication all portions of the Original Work,
- and shall provide, separately, a verbatim copy of the text
- of this license agreement, accompanied by a written statement
- identifying said text as applicable to said portions
- of the Original Work, and identifying the Original Publisher
- as the Licensor of said portions.
- 2.b.iii)
- Pursuant to paragraph 2.b, a Sub-Publisher shall respect,
- and not modify or elaborate upon, the permissions and restrictions
- which paragraph 1 has already extended to any potential recipient
- of the Sub-Publication, henceforth a "Sub-Recipient," with respect
- to the Sub-Recipient's use of any portion of the Original Work,
- including any portion provided to the Sub-Recipient
- via the Sub-Publication.
- 3)
- Any license formed in violation of paragraphs 2.a through 2.b.iii,
- henceforth a "Noncompliant Sub-Publication License," is hereby
- null and void, insofar as it concerns, explicitly or otherwise,
- any portion of the Original Work. Insofar as the Original Work
- is not concerned, this license agreement shall not be taken
- to invalidate the Noncompliant Sub-Publication License in question;
- that is, only those portions concerning the Original Work
- are invalidated.
- 3.a)
- Any Sub-Publisher acting in violation of paragraphs
- 2.a through 2.b.iii shall be the sole liable party to any and all
- civil disputes brought by the Sub-Publisher, at the Sub-Publisher's
- behest, or on the Sub-Publisher's consenting behalf, on the grounds
- that the Sub-Recipient has violated any null and void portion
- (pursuant to paragraph 3) of the Noncompliant Sub-Publication License
- under which the Sub-Publication in question is provided. If any such
- dispute is brought on the Sub-Publisher's behalf, but without
- their consent, whoever brought the dispute shall be the sole
- liable party.
- 4)
- In paragraphs 1 and 2, "without being charged royalties" shall not
- be understood to excuse an Original Recipient from paying a flat
- compensation fee charged by the Original Publisher prior
- to the formation of this license agreement, nor from paying
- any fees for optional services or privileges beyond those already
- guaranteed in paragraphs 1 and 2.
- 5)
- The Original Work is provided "as is," without warranty of any kind,
- express or implied, including but not limited to the warranties
- of merchantability, fitness for a particular purpose,
- and noninfringement. In no event shall the Original Publisher
- be liable for any claim, damages, or other liability,
- whether in an action of contract, tort, or otherwise,
- arising from, out of, or in connection with the Original Work
- or the use or other dealings in the Original Work.
- 6)
- Pursuant to paragraph 2.b.ii, the Licensor is required
- to inform the Licensee as now they shall: namely, that this specific
- license agreement does not cover as Consideration the text
- of the license agreement itself, which is licensed separately,
- but under the same terms. In this regard, the author, and licensor,
- of the text of this license agreement, is one Benjamin Isaac McCann,
- born in California in the United States in the year 1994,
- having authored the text of this license agreement in the year 2020,
- and having licensed it under itself to the general public.
- EOT
- catv() {
- if [[ "$1" == '-i' ]]; then
- echo "${!2}"
- else
- local line blanks
- echo "${!1}" | while read -r line; do
- if [[ "${line}" == '' ]]; then
- if [[ "${blanks}" != '' ]]; then
- blanks=$((blanks + 1))
- fi
- else
- if [[ "${blanks}" != '' ]]; then
- while [[ blanks -gt 0 ]]; do
- echo
- blanks=$((blanks - 1))
- done
- fi
- echo "${line}"
- blanks=0
- fi
- done
- fi
- }
- terminit() {
- clear
- tput rmam
- tput civis
- stty -echo
- }
- termcleanup() {
- clear
- tput smam
- tput cnorm
- stty echo
- }
- getkey() {
- local key full
- if IFS= read -rsn1 key; then while true; do
- full+=$(echo -n "${key}" | cat -v)
- if IFS= read -rst0 key; then IFS= read -rsn1 key
- else
- echo "${full}"
- [[ "${full}" != "^D" ]]
- return $?
- fi
- done; else
- return 1
- fi
- }
- # =====================
- # LINE BUFFER FUNCTIONS
- # =====================
- TERM_WIDTH=$(tput cols)
- TERM_HEIGHT=$(($(tput lines) - 2))
- LINE_BUFFER=()
- LINE_BUFFER_SIZE=
- LINE_BUFFER_SCROLL=0
- LINE_BUFFER_ROW_INDEX=0
- LINE_BUFFER_COLUMN_INDEX=0
- LINE_BUFFER_DISPLAY_HEIGHT=$(($TERM_HEIGHT*3/4))
- LINE_BUFFER_DISPLAY_ROW_OFFSET=$(($TERM_HEIGHT/5))
- LINE_BUFFER_DISPLAY_COLUMN_OFFSET=$(($TERM_WIDTH/12))
- LINE_BUFFER_NEEDS_REDRAW=true
- LINE_BUFFER_ROW_SELECTED_SGR="\e[44m\e[37m"
- LINE_BUFFER_COLUMN_SELECTED_SGR="\e[47m\e[34m"
- LINE_BUFFER_DISABLE_COLUMNS=false
- repositionlinebuf() {
- #echo "repositionlinebuf start" 1>&2
- # get variables and parameters
- local -n buf=LINE_BUFFER
- local -n count=LINE_BUFFER_SIZE
- local -n scroll=LINE_BUFFER_SCROLL
- local -n row=LINE_BUFFER_ROW_INDEX
- local -n col=LINE_BUFFER_COLUMN_INDEX
- local -n height=LINE_BUFFER_DISPLAY_HEIGHT
- local -n firstrow=LINE_BUFFER_DISPLAY_ROW_OFFSET
- local -n firstcol=LINE_BUFFER_DISPLAY_COLUMN_OFFSET
- local -n needredraw=LINE_BUFFER_NEEDS_REDRAW
- local -n rowselsgr=LINE_BUFFER_ROW_SELECTED_SGR
- local -n colselsgr=LINE_BUFFER_COLUMN_SELECTED_SGR
- local -n nocolumn=LINE_BUFFER_DISABLE_COLUMNS
- local width=$(($TERM_WIDTH - $firstcol))
- # update size
- count=${#buf[@]}
- # parse options
- local drow dcol
- local absolute=false
- #echo "parsing options" 1>&2
- while [[ ${1:0:2} == '--' ]]; do
- case "$1" in
- '--absolute') absolute=true ;;
- '--nocolumn') nocolumn=true ;;
- '--rowselsgr') shift; rowselsgr=$1 ;;
- '--colselsgr') shift; colselsgr=$1 ;;
- esac
- shift
- done
- if $absolute; then
- drow=$(($1 - $row))
- dcol=$(($2 - $col))
- else
- drow=$1
- dcol=$2
- fi
- #echo "calculation and bounds-checking" 1>&2
- # bounds-check display height
- #if [[ $height -gt $count ]]; then
- # height=$count
- #fi
- # bounds-check deltas
- if [[ $drow == '' ]]; then drow=0; fi
- if [[ $dcol == '' ]]; then dcol=0; fi
- # declare calculation variables
- local newrow newcol scrollbottom newscroll newscrollbottom
- # don't have to do calculations if no movement
- if [[ ${drow}${dcol} == 00 ]]; then
- newrow=$row
- newcol=$col
- newscroll=$scroll
- scrollbottom=$(($scroll + $height - 1))
- newscrollbottom=$scrollbottom
- else
- # calculate initial new coords
- local newrow=$(($row + $drow))
- local newcol=$(($col + $dcol))
- # bounds-check new coords
- #echo "bounds-check loop" 1>&2
- while true; do
- # past last line -> lower-right
- if [[ $newrow -ge ${#buf[@]} ]]; then
- newrow=$((${#buf[@]} - 1))
- newcol=${#buf[newrow]}
- break
- # before first line -> upper-left
- elif [[ $newrow -lt 0 ]]; then
- newrow=0
- newcol=0
- break
- # past last column -> next line
- elif [[ $newcol -gt ${#buf[newrow]} ]]; then
- newcol=0
- newrow=$(($newrow + 1))
- # before first column -> previous line
- elif [[ $newcol -lt 0 ]]; then
- newrow=$(($newrow - 1))
- if [[ $newrow -lt 0 ]]; then
- newrow=0
- fi
- newcol=${#buf[newrow]}
- else
- break
- fi
- done
- # recalculate deltas from bounds-checked new coords
- drow=$(($newrow - $row))
- dcol=$(($newcol - $col))
- # change scrolling based on index
- local scrollbottom=$(($scroll + $height - 1))
- local newscroll=$scroll
- # index above scroll top -> scroll up
- if [[ $newrow -lt $scroll ]]; then
- newscroll=$newrow
- fi
- # index below scroll bottom -> scroll down
- if [[ $newrow -gt $scrollbottom ]]; then
- newscroll=$(($newrow - $height + 1))
- fi
- # bounds-check scrolling
- if [[ $newscroll -lt 0 ]]; then
- newscroll=0
- fi
- local newscrollbottom=$((newscroll + $height - 1))
- if [[ $newscrollbottom -ge $count ]]; then
- newscroll=$(($count - $height))
- newscrollbottom=$(($count - 1))
- fi
- # end of coord / scroll calculations
- fi
- # post-calculations
- local srow=$(($row - $scroll + $firstrow))
- local snewrow=$(($newrow - $newscroll + $firstrow))
- local scol=$(($col + $firstcol))
- local snewcol=$(($newcol + $firstcol))
- # if scrolled or need redraw, do a full redraw
- local didfullredraw=false
- if [[ $scroll != $newscroll ]] || $needredraw; then
- # get in position
- echo -en "\e[${firstrow};${firstcol}H"
- # erase drawn characters
- for i in $(seq $scroll $scrollbottom); do
- printf "\e[0m%${width}s\e[${width}D\e[B" ''
- done
- # draw over them
- for i in $(seq $newscroll $newscrollbottom | tac); do
- if [[ ($i -ge ${#buf[@]}) || ($i -lt 0) || ("${buf[$i]}" == "") ]]; then
- echo -en "\e[A"
- else
- echo -en "\e[A"
- echo -En "${buf[$i]}"
- if [[ ${#buf[$i]} -ge $width ]]; then
- echo -en "\e[$((${firstrow}+${i}));${firstcol}H"
- else
- echo -en "\e[${#buf[$i]}D"
- fi
- fi
- done
- # done with full redraw
- needredraw=false
- didfullredraw=true
- fi
- # if did full redraw or changed row, redraw row selection
- local didrowredraw=false
- if [[ $newrow != $row ]] || $didfullredraw; then
- # only need to redraw previous selection
- # if it's not already redrawn
- if ! $didfullredraw; then
- echo -en "\e[${srow};${firstcol}H"
- if [[ "${buf[$row]}" == "" ]]; then
- echo -En " "
- else
- echo -En "${buf[$row]} "
- fi
- fi
- # always need to redraw new selection to show it's selected
- echo -en "\e[${snewrow};${firstcol}H${rowselsgr}"
- echo -En "${buf[$newrow]} "
- echo -en "\e[0m"
- # done with row redraw
- didrowredraw=true
- fi
- # if did row redraw or changed column, redraw column selection
- if [[ $newcol != $col ]] || $didrowredraw && ! $nocolumn; then
- # only need to redraw previous selection
- # if it's not already redrawn
- if ! $didrowredraw; then
- if [[ $newrow == $row ]]; then
- echo -en "\e[${srow};${scol}H${rowselsgr}"
- echo -En "${buf[$row]:$col:1}"
- echo -en "\e[0m"
- else
- echo -en "\e[${srow};${scol}H\e[0m"
- echo -En "${buf[$row]:$col:1}"
- fi
- fi
- # always need to redraw new selection to show it's selected
- local chr=${buf[newrow]:$newcol:1}
- # make sure it shows even at end of line
- if [[ $chr == '' ]]; then chr=' '; fi
- # draw it
- echo -en "\e[${snewrow};${snewcol}H"`
- `"${colselsgr}${chr}\e[0m"
- fi
- # update coords
- scroll=$newscroll
- row=$newrow
- col=$newcol
- }
- redrawlinebuf() {
- LINE_BUFFER_NEEDS_REDRAW=true
- repositionlinebuf
- }
- putlinebuf() {
- local -n buf=LINE_BUFFER
- local chr=$1
- local row=$2
- local col=$3
- # split line at position
- local line="${buf[$row]}"
- local firstpart="${line:0:$col}"
- local restpart="${line:$col}"
- # the line buffer is changing so needs redraw
- LINE_BUFFER_NEEDS_REDRAW=true
- # enter -> split line into two lines
- if [[ $chr == '' ]]; then
- buf=( "${buf[@]:0:$row}"
- "$firstpart"
- "$restpart"
- "${buf[@]:$(($row + 1))}"
- );
- repositionlinebuf --absolute $(($row + 1)) 0
- # backspace at beginning of line
- # -> merge line with previous
- elif [[ ($chr == '^?') && ($col == 0) && ($row != 0) ]]; then
- repositionlinebuf --absolute `
- ` $(($row - 1)) ${#buf[$(($row - 1))]}
- buf=( "${buf[@]:0:$(($row - 1))}"
- "${buf[$(($row - 1))]}${buf[$row]}"
- "${buf[@]:$(($row + 1))}"
- );
- LINE_BUFFER_NEEDS_REDRAW=true
- repositionlinebuf
- # backspace elsewhere
- # -> reconstruct line with character missing
- elif [[ ($chr == '^?') && ($col != 0) ]]; then
- buf=( "${buf[@]:0:$row}"
- "${firstpart:0:-1}${restpart}"
- "${buf[@]:$(($row + 1))}"
- );
- repositionlinebuf --absolute $row $(($col - 1))
- # single printable character
- # -> reconstruct line with character inserted
- elif [[ ${#chr} == 1 ]]; then
- buf=( "${buf[@]:0:$row}"
- "${firstpart}${chr:0:1}${restpart}"
- "${buf[@]:$(($row + 1))}"
- );
- repositionlinebuf --absolute $row $(($col + 1))
- fi
- }
- loadlinebuf() {
- mapfile -t LINE_BUFFER
- LINE_BUFFER_SCROLL=0
- LINE_BUFFER_NEEDS_REDRAW=true
- repositionlinebuf --absolute 0 0
- }
- dumplinebuf() {
- for line in "${LINE_BUFFER[@]}"; do
- echo "${line}"
- done
- }
- # =======================
- # LINEBUF MASTER FUNCTION
- # =======================
- linebuf() {
- # parse options
- local readonly=false
- while [[ "${1:0:2}" == "--" ]]; do
- case "$1" in
- '--ro') readonly=true ;;
- esac
- shift
- done
- # logic
- case $1 in
- load) loadlinebuf ;;
- dump) dumplinebuf ;;
- loadfile) loadlinebuf "$(cat $1)" ;;
- dumpfile) dumplinebuf > "$1" ;;
- go) repositionlinebuf --absolute "${@:1}" ;;
- move) repositionlinebuf "${@:1}" ;;
- redraw) LINE_BUFFER_NEEDS_REDRAW=true; repositionlinebuf ;;
- nocol) LINE_BUFFER_DISABLE_COLUMNS=true ;;
- yescol) LINE_BUFFER_DISABLE_COLUMNS=false ;;
- row) echo $LINE_BUFFER_ROW_INDEX ;;
- col) echo $LINE_BUFFER_COLUMN_INDEX ;;
- put) putlinebuf "$2" `
- `$LINE_BUFFER_ROW_INDEX `
- `$LINE_BUFFER_COLUMN_INDEX ;;
- get)
- echo "${LINE_BUFFER[$LINE_BUFFER_ROW_INDEX]:$LINE_BUFFER_COLUMN_INDEX:1}"
- ;;
- up) repositionlinebuf -1 0 ;;
- down) repositionlinebuf 1 0 ;;
- left) repositionlinebuf 0 -1 ;;
- right) repositionlinebuf 0 1 ;;
- home)
- if [[ $LINE_BUFFER_COLUMN_INDEX == 0 ]]; then
- local c=0
- while [[ "${LINE_BUFFER[$LINE_BUFFER_ROW_INDEX]:$c:1}" == ' ' ]]; do
- c=$((c + 1))
- done
- repositionlinebuf 0 $c
- else
- repositionlinebuf 0 -$LINE_BUFFER_COLUMN_INDEX
- fi ;;
- end)
- repositionlinebuf 0 `
- ` $((${#LINE_BUFFER[$LINE_BUFFER_ROW_INDEX]} `
- ` - $LINE_BUFFER_COLUMN_INDEX)) ;;
- pageup) repositionlinebuf $((-$LINE_BUFFER_DISPLAY_HEIGHT/2 - 1)) ;;
- pagedown) repositionlinebuf $(($LINE_BUFFER_DISPLAY_HEIGHT/2 + 1)) ;;
- key)
- case "$2" in
- '^[[A') linebuf up ;;
- '^[[B') linebuf down ;;
- '^[[C')
- if ! $LINE_BUFFER_DISABLE_COLUMNS; then
- linebuf right
- fi ;;
- '^[[D')
- if ! $LINE_BUFFER_DISABLE_COLUMNS; then
- linebuf left
- fi ;;
- '^[[1~'|'^[[7~')
- if ! $LINE_BUFFER_DISABLE_COLUMNS; then
- linebuf home
- fi ;;
- '^[[4~'|'^[[8~')
- if ! $LINE_BUFFER_DISABLE_COLUMNS; then
- linebuf end
- fi ;;
- '^[[5~') linebuf pageup ;;
- '^[[6~') linebuf pagedown ;;
- $(echo -e "\t"))
- if ! { $readonly || $LINE_BUFFER_DISABLE_COLUMNS; }; then
- for i in $(seq $((4 - $LINE_BUFFER_COLUMN_INDEX%4))); do
- linebuf put ' '
- done
- fi ;;
- '^[^?')
- if ! { $readonly || $LINE_BUFFER_DISABLE_COLUMNS; }; then
- if [[ $LINE_BUFFER_COLUMN_INDEX -gt 0 ]]; then
- for i in $(seq $((($LINE_BUFFER_COLUMN_INDEX + 3)%4 + 1))); do
- linebuf put '^?'
- done
- fi
- fi ;;
- *)
- if ! { $readonly || $LINE_BUFFER_DISABLE_COLUMNS; }; then
- linebuf put "$2"
- fi ;;
- esac ;;
- height) LINE_BUFFER_DISPLAY_HEIGHT=$2 ;;
- firstrow) LINE_BUFFER_DISPLAY_ROW_OFFSET=$2 ;;
- firstcol) LINE_BUFFER_DISPLAY_COLUMN_OFFSET=$2 ;;
- esac
- }
- linebuftest() {
- terminit
- linebuf load < <(echo "${LICENSE}")
- local key; while key=$(getkey); do case $key in
- *) linebuf key "$key" ;;
- esac; done
- termcleanup
- linebuf dump
- }
- # ====================
- # STATUS BAR FUNCTIONS
- # ====================
- STATUS_BAR_ROW=$(($TERM_HEIGHT - 2))
- STATUS_BAR_SGR="\e[47m\e[30m"
- STATUS_BAR_ERROR_SGR="\e[41m\e[37m"
- STATUS_BAR_PROMPT_SGR="\e[43m\e[30m"
- STATUS_BAR_TEXT=
- statusbar() {
- # opts
- local sgr=$STATUS_BAR_SGR
- local nosleep=false
- while [[ "${1:0:2}" == '--' ]]; do
- case "$1" in
- '--sgr') shift; sgr="$1" ;;
- '--nosleep') nosleep=true ;;
- esac
- shift
- done
- # logic
- local resp ret
- if [[ "$1" == '' ]]; then
- echo "${STATUS_BAR_TEXT}"
- else
- case "$1" in
- 'clear')
- echo -en "\e[${STATUS_BAR_ROW};0H" 1>&2
- printf "%$((${TERM_WIDTH} - 1))s" '' 1>&2
- echo -en "\e[${STATUS_BAR_ROW};0H" 1>&2
- STATUS_BAR_TEXT=
- ;;
- 'error')
- statusbar --sgr "${STATUS_BAR_ERROR_SGR}" "Error: $2"
- ;;
- 'Y/n')
- statusbar --nosleep --sgr "${STATUS_BAR_PROMPT_SGR}" "$2 [Y/n]"
- local ret=0
- case $(getkey) in
- N|n) ret=1 ;;
- esac
- statusbar clear
- return $ret
- ;;
- 'y/N')
- statusbar --nosleep --sgr "${STATUS_BAR_PROMPT_SGR}" "$2 [y/N]"
- local ret=1
- case $(getkey) in
- Y|y) ret=0 ;;
- esac
- statusbar clear
- return $ret
- ;;
- 'prompt')
- statusbar --nosleep --sgr "${STATUS_BAR_PROMPT_SGR}" "$2:"
- stty echo
- read -r resp
- ret=$?
- stty -echo
- echo "${resp}"
- return $ret
- ;;
- 'password')
- statusbar --nosleep --sgr "${STATUS_BAR_PROMPT_SGR}" "$2:"
- read -rs resp
- ret=$?
- echo "${resp}"
- return $ret
- ;;
- *)
- local msg=" $1 "
- echo -en "\e[${STATUS_BAR_ROW};0H" 1>&2
- printf "%$((${TERM_WIDTH} - 1))s" '' 1>&2
- echo -en "\e[${STATUS_BAR_ROW};0H" 1>&2
- STATUS_BAR_TEXT="$1"
- printf "%$((${TERM_WIDTH}/2 - ${#msg}/2))s" '' 1>&2
- echo -en "${sgr}${msg}\e[0m" 1>&2
- if ! $nosleep; then
- read -rst1.1 -n1
- fi
- ;;
- esac
- fi
- }
- # =====================
- # PERMISSIONS FUNCTIONS
- # =====================
- subypass() {
- local user=$1
- local pass=$2
- local cmd="${@:3}"
- { sleep 0.25; echo $pass; } |
- script -eqc "su -c "'"'"${cmd}"'"'" - $user 2>&1 > /dev/null" > /dev/null
- return $?
- }
- auth() {
- local admin=
- local pass=
- if ! admin=$(statusbar prompt "System administrator username"); then
- statusbar "Cancelled"
- return 1
- fi
- if ! pass=$(statusbar password "Password for ${admin}"); then
- statusbar "Cancelled"
- return 1
- fi
- statusbar --nosleep "Authenticating. "
- if ! subypass "$admin" "$pass" ":"; then
- statusbar error "Incorrect username or password"
- return 1
- fi
- statusbar --nosleep "Authenticating.. "
- if ! subypass "$admin" "$pass" "echo '""$pass""' | sudo -lS 2>&1 > /dev/null"; then
- statusbar error "User $admin is not a system administrator"
- return 1
- fi
- local action="$@"
- statusbar --nosleep "Authenticating..."
- if ! subypass "$admin" "$pass" "echo '""$pass"`
- `"' | sudo -S 2>&1 ${action}"; then
- statusbar error "Privileged command returned a nonzero exit code"
- return 1
- fi
- return 0
- }
- promptchmod() {
- # opts
- local usesu=false
- while [[ "${1:0:2}" == '--' ]]; do
- case "$1" in
- '--su') usesu=true ;;
- esac
- shift
- done
- # logic
- local mode="$1"
- local fname="$2"
- if statusbar y/N "Force access (chmod ${mode})?"; then
- if [[ -O "$fname" ]]; then
- if chmod "u$mode" "$fname"; then
- statusbar "Performed chmod."
- return 0
- else
- statusbar error "Couldn't chmod."
- return 1
- fi
- elif $usesu; then
- if auth chmod "o$mode" "$fname"; then
- statusbar "Performed chmod."
- return 0
- else
- return 1
- fi
- else
- statusbar error "No permission to chmod this file."
- return 1
- fi
- else
- return 1
- fi
- }
- realpath_if_allowed() {
- if ! realpath "$1" 2>/dev/null; then echo "$1"; fi
- }
- fileperms() {
- # opts
- local usepromptchmod=false
- local promptchmodopts=''
- local create=false
- while [[ "${1:0:2}" == '--' ]]; do
- case "$1" in
- '--chmod') usepromptchmod=true ;;
- '--su') promptchmodopts='--su' ;;
- '--create') create=true ;;
- esac
- shift
- done
- # logic
- local fname="$1"
- local dname="$(dirname $(readlink -m $fname))"
- local cont
- if [[ (-e "$dname") && (! -d "$dname") ]]; then
- statusbar error "$(basename $dname) is not a directory."
- echo '---'
- return 1
- elif [[ (! -e "$dname") ]]; then
- statusbar error "Directory $(basename $dname) does not exist."
- echo '---'
- return 1
- elif [[ (! -e "$fname") ]] && ! $create; then
- statusbar error "File $(basename $fname) does not exist."
- echo '---'
- return 1
- elif [[ (! -e "$fname") && (-w "$dname") && (-x "$dname") ]]; then
- statusbar "File $(basename $fname) to be created."
- echo '-w-'
- return 0
- elif [[ (! -e "$fname") ]] && $usepromptchmod; then
- if promptchmod $promptchmodopts +wx "$dname"; then
- statusbar "File $(basename $fname) to be created."
- echo '-w-'
- return 0
- else
- echo '---'
- return 1
- fi
- elif [[ (! -e "$fname") ]]; then
- statusbar error "No permission to create file $(basename $fname)."
- echo '---'
- return 1
- else
- local r=- w=- x=-
- if [[ -r "$fname" ]]; then
- r=r
- fi
- if [[ -w "$fname" ]]; then
- w=w
- fi
- if [[ -x "$fname" ]]; then
- x=x
- fi
- echo "$r$w$x"
- return 0
- fi
- }
- # =========================
- # LINEBUF-BASED SUBPROGRAMS
- # =========================
- texteditor() {
- # opts
- local readonly=false
- while [[ "${1:0:2}" == '--' ]]; do
- case "$1" in
- '--ro') readonly=true ;;
- esac
- shift
- done
- # logic
- clear
- local fname="$@"
- local perms=$(fileperms --create --chmod --su "$fname")
- if $readonly; then
- perms="${perms:0:1}-${perms:2:1}"
- fi
- case "${perms:0:2}" in
- 'rw') linebuf yescol
- linebuf load < <(cat "$fname")
- statusbar --nosleep "Editing $fname" ;;
- '-w') linebuf yescol
- linebuf load < <(echo)
- statusbar --nosleep "Editing $fname (new)" ;;
- 'r-') linebuf nocol
- linebuf load < <(cat "$fname")
- statusbar --nosleep "Viewing $fname" ;;
- '--') statusbar error "Cannot access $fname"
- clear
- return 1 ;;
- esac
- local key; while key=$(getkey); do case $key in
- '^W')
- if [[ ${perms:1:1} == 'w' ]]; then :
- linebuf dump > "$fname"
- statusbar --nosleep "Saved $fname"
- else :
- statusbar error "Read-only mode"
- fi ;;
- *)
- statusbar clear
- if [[ ${perms:1:1} == 'w' ]]; then
- linebuf key "$key"
- else
- linebuf --ro key "$key"
- fi ;;
- esac; done
- clear
- return 0
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement