diff options
-rw-r--r-- | lib/fd.sh | 95 | ||||
-rw-r--r-- | lib/local.mk | 1 | ||||
-rw-r--r-- | locale/en_US.sh | 4 |
3 files changed, 100 insertions, 0 deletions
diff --git a/lib/fd.sh b/lib/fd.sh new file mode 100644 index 0000000..0f78a40 --- /dev/null +++ b/lib/fd.sh @@ -0,0 +1,95 @@ +# ProteanOS Development Kit +# lib/fd.sh +# Functions for opening and closing file descriptors +# +# Copyright (C) 2013 Patrick "P. J." McDermott +# +# This program 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. +# +# This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + +[ "x${_FD_SM+set}" = 'xset' ] && return 0 +_FD_SM=1 + +_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 + FD='' + return 1 + 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 +} diff --git a/lib/local.mk b/lib/local.mk index f0ccd5c..2525d10 100644 --- a/lib/local.mk +++ b/lib/local.mk @@ -2,4 +2,5 @@ pkgdata_sources = \ lib/output.sh \ lib/locale.sh \ lib/getopt.sh \ + lib/fd.sh \ lib/cmd.sh diff --git a/locale/en_US.sh b/locale/en_US.sh index 103f6e2..02f82a9 100644 --- a/locale/en_US.sh +++ b/locale/en_US.sh @@ -21,6 +21,10 @@ msg_prokit_opt_h_summary='print this help message' msg_prokit_opt_V_summary='print version information' +# lib/fd.sh +msg_prokit_emfile='Too many open files' +msg_prokit_ebadf='Bad file descriptor' + # lib/cmd.sh msg_prokit_cmd_not_found='Command "%s" not found' msg_prokit_cmd_usage='Usage: %s [<option> ...] %s %s' |