summaryrefslogtreecommitdiffstats
path: root/src/fd.sh
diff options
context:
space:
mode:
Diffstat (limited to 'src/fd.sh')
-rw-r--r--src/fd.sh92
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
+}