diff options
Diffstat (limited to 'src/fd.sh')
-rw-r--r-- | src/fd.sh | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/fd.sh b/src/fd.sh new file mode 100644 index 0000000..0d5a50e --- /dev/null +++ b/src/fd.sh @@ -0,0 +1,92 @@ +# Functions for opening and closing file descriptors +# +# Copyright (C) 2013 Patrick "P. J." McDermott +# +# This file is part of the ProteanOS Development Kit. +# +# The ProteanOS Development Kit is free software: you can redistribute +# it and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# The ProteanOS Development Kit is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the ProteanOS Development Kit. If not, see +# <http://www.gnu.org/licenses/>. + +_FD_MIN=3 +# Shells and the file descriptors they reserve for the user: +# * Debian Almquist Shell +# - The shell doesn't understand any file descriptor greater than 9. +# - File descriptors starting at 10 are used for I/O redirection. +# * BusyBox ash +# - File descriptors starting at 10 are used for job control and I/O +# redirection. +# * GNU Bash: +# - GNU Readline uses file descriptor 255 in interactive shells. +# - File descriptors starting at 10 are used for I/O redirection. +# * MirOS Korn Shell +# - File descriptors starting at either 10 or 24 are used for the shell's +# tty_fd and shl_dbg_fd. +# * Solaris ksh +# - The shell doesn't understand any file descriptor greater than 9. +_FD_MAX=9 + +FD= + +fopen() +{ + local path="${1}" + local mode="${2}" + local i= + local fd= + + case "${mode}" in + 'r') mode='<' ;; + 'w') mode='>' ;; + 'a') mode='>>';; + 'rw') mode='<>';; + *) return 125;; + esac + + # Find first available file descriptor. + i=${_FD_MIN} + while [ ${i} -le ${_FD_MAX} ]; do + if [ "x$(eval echo "\${_fd_${i}+set}")" != 'xset' ]; then + fd=${i} + break + fi + i=$(($i + 1)) + done + if [ "x${fd:+set}" != 'xset' ]; then + error 2 "$(get_msg 'emfile')" + return + fi + + if eval "exec ${fd}${mode}'${path}'"; then + eval "_fd_${fd}='${mode}${path}'" + FD="${fd}" + return 0 + else + error 2 "$(get_msg 'cant_fopen')" + fi +} + +fclose() +{ + local fd="${1}" + + # Make sure the file descriptor is open. + if [ "x$(eval echo "\${_fd_${fd}+set}")" != 'xset' ]; then + error 2 "$(get_msg 'ebadf')" + fi + + eval "exec ${fd}>&-" + unset "_fd_${fd}" + + return 0 +} |