# Functions for managing prokit sessions # # Copyright (C) 2014 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${_SESSION_SM+set}" = 'xset' ] && return 0 _SESSION_SM=1 use rand use mutex use output use locale use profile session_id= session_root= session_arch= session_plat= session_mountdir= session_atexit= session_begin() { local root="${1}" local mountdir="${2}" local atexit="${3}" rand session_id=${rand_x} session_root="${root}" session_arch="$(cat "${root}/etc/proteanos_arch")" session_plat="$(cat "${root}/etc/proteanos_plat")" session_mountdir="${mountdir}" session_atexit="${atexit}" if ! mutex_lock_timeout "${session_root}/prokit/sessions.lock" 5; then error 2 "$(get_msg 'cant_lock_sessions')" fi # Check for a sessions pool. if [ -d "${session_root}/prokit/sessions" ]; then if ! profile_file_systems_mounted "${session_root}" \ "${session_arch}" "${session_plat}"; then # If a sessions pool exists but the file systems aren't # mounted, clean up the old sessions and mount the file # systems. rmdir "${session_root}/prokit/sessions/"* session_mount fi else # If the sessions pool doesn't exist, create it and mount the # file systems. mkdir "${session_root}/prokit/sessions" session_mount fi # Register the session. mkdir "${session_root}/prokit/sessions/${session_id}" profile_bind_mount "${session_arch}" "${session_plat}" \ "${session_mountdir}" \ "${session_root}/prokit/sessions/${session_id}" mutex_unlock "${session_root}/prokit/sessions.lock" } session_end() { # Unregister the session. profile_bind_umount "${session_arch}" "${session_plat}" \ "${session_mountdir}" \ "${session_root}/prokit/sessions/${session_id}" rmdir "${session_root}/prokit/sessions/${session_id}" if ! mutex_lock_timeout "${session_root}/prokit/sessions.lock" 5; then error 2 "$(get_msg 'cant_lock_sessions')" fi # Clear the sessions pool. If there are no more sessions, unmount the # file systems. if rmdir "${session_root}/prokit/sessions" 2>/dev/null; then session_umount fi mutex_unlock "${session_root}/prokit/sessions.lock" } session_id() { printf '%d\n' ${session_id} return 0 } session_exec() { local args= local session_dir= args='' for arg in "${@}"; do arg="'$(printf '%s\n' "${arg}" | sed "s/'/'\\\\''/g")'" args="${args} ${arg}" done session_dir="/prokit/sessions/${session_id}" chroot "${session_root}" /bin/sh -c "cd ${session_dir}; ${args}" } session_mount() { local fs= local dir= local fstype= local options= while read fs dir fstype options; do [ "x${dir}" = 'x' ] && continue mount -t "${fstype}" -o "${options}" "${fs}" \ "${session_root}/${dir}" done <<-EOF $(profile_get_fstab "${session_arch}" "${session_plat}") EOF } session_umount() { local fs= local dir= local fstype= local options= while read fs dir fstype options; do [ "x${dir}" = 'x' ] && continue # umount sometimes complains that the /dev file system is busy. # Here's a kludge to try to handle that. We better make sure # bind mounts get unmounted; otherwise, `rm -Rf ${root}` can be # painful. while ! umount "${session_root}/${dir}"; do sleep 1 done done <<-EOF $(profile_get_fstab "${session_arch}" "${session_plat}" | \ sed -n '1!G;h;$p') EOF }