# 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 # . [ "x${_FD_SM+set}" = 'xset' ] && return 0 _FD_SM=1 use output use locale _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 }