1488 lines
52 KiB
Bash
Executable File
1488 lines
52 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Free implementation of nxserver components
|
|
# Copyright (c) 2004 by Fabian Franz.
|
|
# (c) 2008-23 by Dmitry Borisov <i@dimbor.ru>
|
|
# License: GNU GPL, version 2
|
|
|
|
shopt -s extglob
|
|
|
|
SHARED_CONFS="/usr/share/freenx-server"
|
|
. $SHARED_CONFS/nxfuncs
|
|
|
|
[ "$1" = "--admin" ] && { # simple wrapper to start nxserver in admin mode
|
|
if stringinstring " nxadmin " " $(groups) "; then
|
|
/usr/bin/sudo -p "" /bin/bash -c '/usr/bin/nxserver --admin' 2>&1
|
|
exit $?
|
|
else
|
|
echo "NX> 2004 admin mode start failed"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
#
|
|
# -----------------------------------------------------------------------------
|
|
# Various helper functions
|
|
# -----------------------------------------------------------------------------
|
|
#
|
|
nxlog() {
|
|
[ "$NX_LOG_LEVEL" != "0" ] || return
|
|
echo "$(date "+%T.%3N"): ${@/password=+([^&])&/password=*&}" >> "$nxuser_logfile"
|
|
}
|
|
|
|
cp_conv() {
|
|
# arg: <string>
|
|
# Used config vars: $COMMAND_ICONV $WIN_CP_CONVERT_CHAIN
|
|
# successively convert string charset
|
|
#local lp="$FUNCNAME ($$/$BASHPID):"; #debug
|
|
#nxlog "$lp starting with args \"$@\"" #debug
|
|
local res=${1//+/ } cp_pair cp_from cp_to;
|
|
[ -n "$COMMAND_ICONV" ] || { echo "$res"; return 1; }
|
|
for cp_pair in $WIN_CP_CONVERT_CHAIN ; do
|
|
cp_from=$(cutfn "$cp_pair" 0 '>'); [ -n "$cp_from" ] || cp_from="latin1"
|
|
cp_to=$(cutfn "$cp_pair" 1 '>'); [ -n "$cp_to" ] || cp_to="UTF-8"
|
|
res=$(echo "$res" | $COMMAND_ICONV -f $cp_from -t $cp_to)
|
|
#nxlog "$lp converting $cp_from > $cp_to == \"$res\"" #debug
|
|
done
|
|
#nxlog "$lp return res='$res'" #debug
|
|
echo "$res"
|
|
}
|
|
|
|
# =================== sqlite3 stuff =====================
|
|
|
|
declare -g sqcols_usess="session_id, status, display, type, client,\
|
|
agent_pid, cookie, tail_pid, userip, acc_ip, mmport, cupsport, smbport"
|
|
|
|
declare -g sqcols_usvcs="svc, type, status, port, share, username, pass,\
|
|
data, comp, addr"
|
|
#svc: internal service name
|
|
#type: smb-share | smb-prn | ipp-prn | media-pa | ...
|
|
#status: starting|on|stopping|off
|
|
#port: tunneled/remote port
|
|
#share: incomming share name
|
|
#data: options depended of service type eg mount dir...
|
|
#comp: remote computer name
|
|
#addr: ip address is 127.0.0.1 typically, another if remote connection used
|
|
|
|
init_usessions_db() {
|
|
local usess_cols="session_id TEXT PRIMARY KEY, status TEXT, display TEXT,\
|
|
type TEXT, client TEXT, agent_pid INT, cookie TEXT, tail_pid INT,\
|
|
userip TEXT, acc_ip TEXT, mmport INT, cupsport INT, smbport INT"
|
|
local svcs_cols="svc TEXT PRIMARY KEY, type TEXT, status TEXT, port INT,\
|
|
share TEXT, comp TEXT, addr TEXT, username TEXT, pass TEXT, data TEXT"
|
|
local qstr="CREATE TABLE IF NOT EXISTS usessions.usess($usess_cols);"
|
|
qstr+="CREATE TABLE IF NOT EXISTS usessions.usvcs($svcs_cols);"
|
|
q_dbe "$qstr"
|
|
}
|
|
|
|
# ------------------ user session (usess) control --------
|
|
usess_add() { q_row_ins "usess" "$1" "$2"; }
|
|
#usess_add() args: <col1,col2...> <val1&val2...>
|
|
|
|
usess_set() { q_rows_upd "usess" "session_id='$1'" "$2" "$3"; }
|
|
#usess_set() args: <session_id> <col1,col2...> <val1&val2...>
|
|
|
|
usess_get() { q_vals_str_get "usess" "session_id='$1'" "$2" "$3"; }
|
|
#usess_get() args: <session_id> <col1,col2...> [values_delim='&']
|
|
|
|
usess_close() {
|
|
#args: <session_id> <status>
|
|
if [ "$SESSION_LOG_CLEAN" = "1" ]; then
|
|
q_dbe "DELETE FROM usess WHERE session_id='$1';"
|
|
else
|
|
q_rows_upd "usess" "session_id='$1'" "status" "$2"
|
|
fi
|
|
}
|
|
|
|
# -------------- user services (uservices) control --------
|
|
#usvcs_add() args: <col1,col2...> <val1&val2...>
|
|
usvcs_add() { q_row_ins "usvcs" "$1" "$2"; }
|
|
|
|
#usvcs_set() args: <service> <col1,col2...> <val1&val2...>
|
|
usvcs_set() { q_rows_upd "usvcs" "svc='$1'" "$2" "$3"; }
|
|
|
|
#usvcs_get() args: <service> <col1,col2...> [values_delim='&']
|
|
usvcs_get() { q_vals_str_get "usvcs" "svc='$1'" "$2" "$3"; }
|
|
|
|
#
|
|
# -----------------------------------------------------------------------------
|
|
# Node functions module
|
|
# -----------------------------------------------------------------------------
|
|
#
|
|
|
|
sess_lport_name() {
|
|
#arg: <svc_type>
|
|
case $1 in
|
|
smb-share|smb-prn) echo "smbport";;
|
|
ipp-prn) echo "cupsport";;
|
|
media-pa) echo "mmport";;
|
|
esac
|
|
}
|
|
|
|
norm_dir() {
|
|
#args: <share_dir> [parent_dir]
|
|
# exclude potential parts to exec and set dir path from given parent_dir
|
|
local r=${1//\`/}; r=${r//\$[(\{]*[)\}]/$2}; r=${r/\.\.\//$2\/};
|
|
r=${r/\.\//$2\/}; r=${r/\~\//$2\/}
|
|
[[ "${r:0:1}" =~ [[:alnum:]] ]] && r="$2/$r"
|
|
echo "$r"
|
|
}
|
|
|
|
uservice_mounted() {
|
|
#args: <type> <service/sharename/mountpoint> [port]
|
|
local rc=0 txt="" pattern port=""
|
|
local patt_addr="127.0.0.1"; [ -n "$4" ] && patt_addr=$4
|
|
case $1 in
|
|
smb-share)
|
|
# output of mount cmd not contains mount.cifs port option value
|
|
# because we need to port arg ($3)
|
|
txt=$(env LC_ALL=C $COMMAND_MOUNT_LIST 2>/dev/null)
|
|
if stringinstring "//" "$2"; then pattern="($2)"
|
|
elif ! stringinstring "/" "$2"; then pattern="//$patt_addr/($2)"
|
|
else pattern="($2)"
|
|
fi
|
|
[ -n "$(rematchfn "$pattern" "$txt")" ] || return 1
|
|
if [ -n "$3" ]; then
|
|
port_is_listening $3 || rc=1
|
|
fi
|
|
;;
|
|
smb-prn|ipp-prn)
|
|
txt=$(env LC_ALL=C $COMMAND_LPSTAT -v 2>/dev/null)
|
|
pattern=".*$2.*//$patt_addr:("
|
|
[ -n "$3" ] && pattern+="$3)" || pattern+="$num_pattern)"
|
|
port=$(rematchfn "$pattern" "$txt"); rc=$?
|
|
[ -n "$port" ] || return $rc
|
|
port_is_listening "$port" || rc=1
|
|
;;
|
|
media-pa)
|
|
case $2 in
|
|
pa) # tunneled pa
|
|
#$COMMAND_PA --check || return 1
|
|
txt=$(env LC_ALL=C $COMMAND_PACTL list short 2>/dev/null)
|
|
pattern="server=$patt_addr:("
|
|
[ -n "$3" ] && pattern+="$3)" || pattern+="[0-9]+)"
|
|
port=$(rematchfn "$pattern" "$txt"); rc=$?
|
|
#nxlog "$1 port=$port" #debug
|
|
[ -n "$port" ] || return $rc
|
|
port_is_listening "$port" || rc=1
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
return $rc
|
|
}
|
|
|
|
uservice_configure() {
|
|
#args:
|
|
# smb-share <svc> <port> <username> <password> <dir> <computername>
|
|
# *-prn <svc> <port> <username> <password> <opts> <computername> <share>
|
|
# opts="model=;public=;defaultprinter="
|
|
# media-pa <svc> <port> <""> <""> <opts>
|
|
local lp="$FUNCNAME ($$/$BASHPID):";
|
|
local cmdstr optstr comp rc=0 txt errstr uri
|
|
case $1 in
|
|
smb-share)
|
|
# create/check mountpoint
|
|
mkdir -p "$6" &>/dev/null
|
|
[ -d "$6" ] || { nxlog "$lp unable to create dir='$6'"; return 1; }
|
|
local egroup=$(id -gn "$USER") tmpopts=${SMB_MOUNT_OPTIONS//,/&}
|
|
local dir_mode=$(getparam "$tmpopts" dir_mode)
|
|
dir_mode=${dir_mode:(-3)}; [ -n "$dir_mode" ] || dir_mode="700"
|
|
[ "$(stat -c %a "$6")" != "$dir_mode" ] && chown "0$dir_mode" "$6" &>/dev/null
|
|
# mount options string
|
|
optstr="uid=$USER,gid=$egroup,ip=127.0.0.1,port=$3,username=$4"
|
|
[ -n "$5" ] && optstr+=",password=$5"
|
|
[ -n "$SMB_MOUNT_OPTIONS" ] && optstr+=",$SMB_MOUNT_OPTIONS"
|
|
cmdstr="$COMMAND_SUDO $COMMAND_SMBMOUNT $2 $6 -o $optstr"
|
|
echo "$cmdstr"
|
|
;;
|
|
smb-prn|ipp-prn)
|
|
local model=$(getparam "$6" "model" "" ';')
|
|
[ "$model" = "NULL" ] && model=""
|
|
local ppdn=${2#$USER}; ppdn=${ppdn:1}; ppdn=${ppdn%#[0-9]*}
|
|
local ppdfn="$NX_PPD_DIR/$ppdn.ppd"
|
|
[ -r "$ppdfn" ] || { # ppd is not found, search for driver in CUPS
|
|
txt=$($COMMAND_LPINFO -m 2>/dev/null)
|
|
local str drv=""
|
|
[ -n "$model" ] && {
|
|
while read str; do
|
|
[[ "$str" =~ "$model" ]] && { drv="${str%% *}"; break; }
|
|
done <<< "$txt"
|
|
}
|
|
[ -n "$drv" ] || {
|
|
while read str; do
|
|
[[ "$str" =~ "$ppdn" ]] && { drv="${str%% *}"; break; }
|
|
done <<< "$txt"
|
|
}
|
|
[ -n "$drv" ] || {
|
|
nxlog "$lp '$svc'; CUPS driver for service is not found";
|
|
return 1; }
|
|
$COMMAND_PPDCAT cat "$drv" > "$ppdfn" || {
|
|
nxlog "$lp Can't save $ppdfn"; return 1; }
|
|
}
|
|
[ "${1:0:3}" = "smb" ] && \
|
|
uri="nxsmb://$4:$5@127.0.0.1:$3/cifs/$8" || \
|
|
uri="ipp://$4:$5@127.0.0.1:$3/printers/$8"
|
|
cmdstr="$COMMAND_SUDO $COMMAND_LPADMIN -p $svc -P $ppdfn -v $uri -E"
|
|
echo "$cmdstr"
|
|
;;
|
|
media-pa)
|
|
case $2 in
|
|
pa) # tunneled pa
|
|
local uri="127.0.0.1:$3"
|
|
# get sink and source from remote pa
|
|
local rmods=$(env LC_ALL=C $COMMAND_PACTL -s $uri list short 2>/dev/null)
|
|
[ -n "$rmods" ] || {
|
|
nxlog "$lp '$svc'; can't get module list from remote PA ($uri)";
|
|
return 1; }
|
|
local rsink=$(rematchfn "(ts_receiver)" "$rmods") #"
|
|
local rsource=$(rematchfn "(ts_sender.monitor)" "$rmods") #"
|
|
[ -n "$rsink" -a -n "$rsource" ] || {
|
|
local rinfo=$(env LC_ALL=C $COMMAND_PACTL -s $uri info 2>/dev/null)
|
|
[ -n "$rsink" ] || \
|
|
rsink=$(rematchfn "Default Sink:[[:blank:]]+(.+)" "$rinfo") #"
|
|
[ -n "$rsource" ] || \
|
|
rsource=$(rematchfn "Default Source:[[:blank:]]+(.+)" "$rinfo") #"
|
|
}
|
|
echo "$rsink $rsource"
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
return $rc
|
|
}
|
|
|
|
uservice_mount() {
|
|
#args:
|
|
# smb-share <svc> <port> <username> <password> <dir> <computername>
|
|
# *-prn <svc> <port> <username> <password> <opts> <computername> <share>
|
|
# media-pa <svc> <port> "" "" <mode> <computername>
|
|
local lp="$FUNCNAME ($$/$BASHPID):" rc=0 cmdstr errstr
|
|
local i ok="" step=0.25 timeo=28 #7sec
|
|
for (( i=0; i<=timeo; i++ )); do
|
|
port_is_listening $3 && { ok="1"; break; }
|
|
sleep $step"s"
|
|
done
|
|
[ -n "$ok" ] || \
|
|
{ nxlog "$lp '$svc'; port $3 is not listen after $((timeo/4))s";
|
|
return 1; }
|
|
|
|
cmdstr=$(uservice_configure "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8") || return 1
|
|
case $1 in
|
|
smb-share)
|
|
#nxlog "$lp share cmdstr='$cmdstr'" #debug
|
|
errstr=$($cmdstr 2>&1) || \
|
|
{ nxlog "$lp $2 ($3) share mount failed: $errstr"
|
|
rmdir "$6" &>/dev/null; return 1; }
|
|
nxlog "$lp $2 ($3) share mounted"
|
|
;;
|
|
smb-prn|ipp-prn)
|
|
#nxlog "$lp add printer cmdstr='$cmdstr'" #debug
|
|
errstr=$($cmdstr 2>&1) || \
|
|
{ nxlog "$lp $2 ($3) printer installing failed: $errstr"; return 1; }
|
|
# post-configure
|
|
local public=$(getparam "$6" "public" "" ';')
|
|
[ "$public" != "1" ] && {
|
|
errstr=$($COMMAND_SUDO $COMMAND_LPADMIN -p $svc -u allow:$USER,guest,root 2>&1) || \
|
|
{ nxlog "$lp $2 ($3) printer set permission failed: $errstr"; }
|
|
}
|
|
local defp=$(getparam "$6" "defaultprinter" "" ';')
|
|
[ "$defp" = "1" ] && {
|
|
errstr=$($COMMAND_SUDO $COMMAND_LPADMIN -d $svc 2>&1) || \
|
|
{ nxlog "$lp $2 ($3) printer set to default failed: $errstr"; }
|
|
}
|
|
nxlog "$lp $2 ($3) printer installed"
|
|
;;
|
|
media-pa)
|
|
if ! $COMMAND_PA --check &>/dev/null; then
|
|
$COMMAND_PA --start --exit-idle-time=-1 &>/dev/null || {
|
|
#--log-target=file:$nx_dir/pa-$3.log --log-level=4 || { #debug
|
|
nxlog "$lp '$svc' can't start local pulseaudio server";
|
|
return 1; }
|
|
# automatic null-sink will be disabled
|
|
# unload unnecessary local modules here too
|
|
local rmmods="module-always-sink module-rescue-streams module-systemd-login \
|
|
module-device-restore module-stream-restore module-card-restore \
|
|
module-default-device-restore module-switch-on-port-available \
|
|
module-udev-detect module-suspend-on-idle module-console-kit"
|
|
local txt=$($COMMAND_PACTL list short 2>/dev/null)
|
|
local midpat="([0-9]+)[[:blank:]]+" mid rmod
|
|
for rmod in $rmmods; do
|
|
mid=$(rematchfn "$midpat$rmod" "$txt") && {
|
|
$COMMAND_PACTL unload-module $mid &>/dev/null
|
|
#nxlog "$lp ! $mid" #debug
|
|
}
|
|
done
|
|
else nxlog "$lp '$svc' local pulseaudio server already started" #debug
|
|
fi
|
|
case $2 in
|
|
pa) # tunneled pa
|
|
local rsink=$(cutfn "$cmdstr" 0) rsource=$(cutfn "$cmdstr" 1)
|
|
local mname="module-tunnel-sink" opts="server=127.0.0.1:$3" oo args ok2=""
|
|
oo=$(cutfn "$6" 1 '-'); [ -n "$oo" ] && opts+=" rate=$oo"
|
|
oo=$(cutfn "$6" 2 '-'); [ -n "$oo" ] && opts+=" channels=$oo"
|
|
[ "$oo" = "1" ] && opts+=" channel_map=mono"
|
|
if [ "$rsink" != "(null)" ]; then
|
|
args="sink_name=tcl_out sink=$rsink $opts"
|
|
errstr=$($COMMAND_PACTL load-module $mname $args 2>&1)
|
|
[ $? -eq 0 ] && ok="tcl_out" || \
|
|
nxlog "$FUNCNAME ($$): $2 ($3) can't load $mname $args; '$errstr'"
|
|
[ -n "$ok" ] && $COMMAND_PACTL set-default-sink "tcl_out" &>/dev/null
|
|
else nxlog "$lp $2 ($3) can't load $name with rsink=$rsink"
|
|
fi
|
|
mname="module-tunnel-source"
|
|
if [ "$rsource" != "(null)" ]; then
|
|
args="source_name=tcl_in source=$rsource $opts"
|
|
errstr=$($COMMAND_PACTL load-module $mname $args 2>&1)
|
|
[ $? -eq 0 ] && ok2="tcl_in" || \
|
|
nxlog "$FUNCNAME ($$): $2 ($3) can't load $mname $args; '$errstr'"
|
|
[ -n "$ok2" ] && $COMMAND_PACTL set-default-source "tcl_in" &>/dev/null
|
|
else nxlog "$lp $2 ($3) can't load $name with rsource=$rsource"
|
|
fi
|
|
if [ -n "$ok" -o -n "$ok2" ]; then
|
|
nxlog "$lp $2 ($3) tunnel modules loaded: $ok $ok2"
|
|
else rc=1
|
|
fi
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
return $rc
|
|
}
|
|
|
|
uservice_umount() {
|
|
#args: <type> <svc/mountpoint> [data] [port]
|
|
local lp="$FUNCNAME ($$/$BASHPID):" errstr=""
|
|
local i ok="" step="0.5" ct=4
|
|
case $1 in
|
|
smb-share)
|
|
local mdir=$3 res ffl=""
|
|
if stringinstring "//" "$2"; then res="$2" # svc
|
|
elif ! stringinstring "/" "$2"; then res="//127.0.0.1/$2" # sharename
|
|
else mdir="$2" res="$2" # dir
|
|
fi
|
|
#[ -z "$mdir" ] && { # get mount dir directly
|
|
# local txt=$(LC_ALL=C mount 2>/dev/null)
|
|
# pattern="$res""[[:blank:]]+on[[:blank:]]+([^[:blank:]]+)"
|
|
# mdir=$(remathfn "$pattern" "$txt")
|
|
# nxlog "$lp share $res: given empty mount dir, loaded mdir='$mdir' "
|
|
#}
|
|
for (( i=1; i<=ct; i++ )); do
|
|
(( i>=ct/2 )) && ffl="-f"
|
|
errstr+=$($COMMAND_SUDO $COMMAND_SMBUMOUNT $ffl "$res" 2>&1) && \
|
|
{ ok="1"; break; }
|
|
sleep $step"s"
|
|
done
|
|
[ -n "$ok" ] || \
|
|
{ nxlog "$lp $res share umount failed: $errstr"; return 1; }
|
|
[ -n "$mdir" ] && [ -d "$mdir" ] && rmdir "$mdir" &>/dev/null
|
|
nxlog "$lp $res share umounted"
|
|
;;
|
|
smb-prn|ipp-prn)
|
|
for (( i=1; i<=ct; i++ )); do
|
|
errstr+=$($COMMAND_SUDO $COMMAND_LPADMIN -x "$2" 2>&1) && \
|
|
{ ok="1"; break; }
|
|
sleep $step"s"
|
|
done
|
|
[ -n "$ok" ] || \
|
|
{ nxlog "$lp $2 printer deleting failed: $errstr"; return 1; }
|
|
nxlog "$lp $2 printer deleted"
|
|
;;
|
|
media-pa)
|
|
case $2 in
|
|
pa) # tunneled pa
|
|
local midpat="([0-9]+)[[:blank:]]+module-" uri="127.0.0.1"
|
|
[ -n "$4" ] && uri+=":$4"
|
|
txt=$(env LC_ALL=C $COMMAND_PACTL list short 2>/dev/null)
|
|
[ -n "$txt" ] || {
|
|
nxlog "$lp '$svc'; local PA already stopped"; return 0; }
|
|
local mid es mids=$(rematchfn "$midpat.+server=$uri" "$txt" all);
|
|
#nxlog "$lp '$2'; rmids: "$mids; #debug
|
|
for mid in $mids; do
|
|
es=$($COMMAND_PACTL unload-module $mid 2>&1)
|
|
[ $? -ne 0 ] && errstr+="\n$es"
|
|
done
|
|
[ -n "$errstr" ] && {
|
|
nxlog "$lp '$2'; unload some local PA modules failed: $errstr";
|
|
}
|
|
nxlog "$lp $2 remote tunnel disconnected"
|
|
#nxlog "$lp $2 remote tunnel: $($COMMAND_PACTL list short 2>/dev/null)" #debug
|
|
;;
|
|
esac
|
|
[ -n "$3" ] && {
|
|
$COMMAND_PA --kill || {
|
|
nxlog "$lp '$2'; unable to kill local PA"; return 0; }
|
|
}
|
|
;;
|
|
esac
|
|
return 0
|
|
}
|
|
|
|
uservice_start() {
|
|
#args:
|
|
# <svc> [port] [type] [sharename] [username] [password] [data] [comp]
|
|
# [addr=127.0.0.1]
|
|
# if type is empty try to operate params from usess db
|
|
# if port not empty try to start on him
|
|
# Used config vars: COMMAND_HIDE COMMAND_UNHIDE
|
|
local lp="$FUNCNAME ($$/$BASHPID):" errstr="" qs svcport
|
|
local st startfl="" checkfl="" updvars="" updvals="" hpass
|
|
local svc="$1" port="$2" type="$3" share="$4"
|
|
local username="$5" pass="$6" data="$7" comp="$8"
|
|
local addr="$9"; [ -z "$addr" ] && addr="127.0.0.1";
|
|
[ "$type" = "smb-share" -a -n "$data" ] && data=$(norm_dir "$data" $HOME)
|
|
|
|
local i ok="" step="0.25" timeo="28" #4sec
|
|
[ -n "$type" -a -z "$port" ] && {
|
|
# starting no restarting - we wait for session listening port just in case
|
|
local lport_name=$(sess_lport_name $type)
|
|
local wstr="session_id='$session_id' AND $lport_name>0"
|
|
for (( i=0; i<=timeo; i++ )); do
|
|
port=$(q_vals_str_get "usess" "$wstr" "$lport_name") && break
|
|
sleep $step"s"
|
|
done
|
|
[ -n "$port" ] || {
|
|
nxlog "$lp $svc session $lport_name no declared after $((timeo/4)) s";
|
|
return 1; }
|
|
}
|
|
|
|
# waiting for suitable service status: on/off/""
|
|
ok="" step="0.25" timeo="28" #7sec
|
|
for (( i=0; i<=timeo; i++ )); do
|
|
st=$(usvcs_get $svc "status") || { ok="1"; break; }
|
|
stringinstring "$st" "starting|stopping" || { ok="1"; break; }
|
|
sleep $step"s"
|
|
done
|
|
[ -n "$ok" ] || {
|
|
nxlog "$lp service $svc ($port) still set in \"$st\" state after $((timeo/4)) s";
|
|
# FIXME!
|
|
[ "$st" = "stopping" ] || return 1;
|
|
nxlog "$lp service $svc ($port) set state 'off' ultimately";
|
|
usvcs_set $svc "status" "off"; st="off"
|
|
}
|
|
|
|
[ -z "$type" -a -z "$st" ] && {
|
|
nxlog "$lp '$svc': params for service are not found in usess db";
|
|
return 1; }
|
|
[ -z "$type" ] && { #load params from usess db
|
|
qs="$(usvcs_get $svc "type,port,share,username,pass,data,comp,addr")" || {
|
|
nxlog "$lp '$svc': can't get service params from usess db"; return 1; }
|
|
type=$(cutfn "$qs" 0 '&');
|
|
[ -z "$port" ] && port=$(cutfn "$qs" 1 '&');
|
|
share=$(cutfn "$qs" 2 '&'); username=$(cutfn "$qs" 3 '&');
|
|
pass=$(cutfn "$qs" 4 '&'); pass=$(echo "$pass" | $COMMAND_UNHIDE);
|
|
data=$(cutfn "$qs" 5 '&'); comp=$(cutfn "$qs" 6 '&');
|
|
addr=$(cutfn "$qs" 7 '&');
|
|
#nxlog "$lp service $svc ($st) load qs='$qs'" #debug
|
|
}
|
|
|
|
if [ "$st" = "on" ]; then
|
|
if uservice_mounted $type $svc; then
|
|
nxlog "$lp service $svc is allready mounted, skipping"; return 0
|
|
else
|
|
nxlog "$lp $svc service status is \"$st\", but it's not mounted. Try to start again";
|
|
startfl=1; [ -n "$type" ] && checkfl=1;
|
|
st="starting"; usvcs_set $svc "status" $st
|
|
fi
|
|
else
|
|
if uservice_mounted $type $svc; then
|
|
usvcs_set $svc "status" "stopping"
|
|
nxlog "$lp $svc service status is \"$st\", but it's mounted. Try to stop";
|
|
uservice_umount $type $svc $data || { return 1; }
|
|
fi
|
|
if [ "$st" = "off" ]; then
|
|
startfl=1; [ -n "$type" ] && checkfl=1;
|
|
st="starting"; usvcs_set $svc "status" $st
|
|
else # svc is not found in usess table
|
|
hpass=$(echo $pass | $COMMAND_HIDE)
|
|
usvcs_add "svc,type,status,port,share,comp,addr,username,pass,data" \
|
|
"$svc&$type&starting&$port&$share&$comp&$addr&$username&$hpass&$data"
|
|
startfl=1;
|
|
fi
|
|
fi
|
|
|
|
[ -n "$startfl" ] && {
|
|
[ -n "$checkfl" ] && {
|
|
local s_share s_username s_pass s_data s_comp s_addr
|
|
qs="$(usvcs_get $svc "share,username,pass,data,comp,addr")" || {
|
|
nxlog "$lp can't get service $svc params from usess _db"; return 1; }
|
|
s_share=$(cutfn "$qs" 0 '&'); s_username=$(cutfn "$qs" 1 '&');
|
|
s_pass=$(cutfn "$qs" 2 '&'); s_pass=$(echo $s_pass | $COMMAND_UNHIDE);
|
|
s_data=$(cutfn "$qs" 3 '&'); s_comp=$(cutfn "$qs" 4 '&');
|
|
s_addr=$(cutfn "$qs" 5 '&');
|
|
[ "$share" != "$s_share" ] && {
|
|
nxlog "$lp $svc share strings are different '$s_share' > '$share'"
|
|
updvars+=",share"; updvals+="&$share"; }
|
|
[ "$username" != "$s_username" ] && {
|
|
nxlog "$lp $svc username strings are different '$s_username' > '$username'"
|
|
updvars+=",username"; updvals+="&$username"; }
|
|
[ "$pass" != "$s_pass" ] && {
|
|
nxlog "$lp $svc password strings are different"
|
|
hpass=$(echo $pass | $COMMAND_HIDE)
|
|
updvars+=",pass"; updvals+="&$hpass"; }
|
|
[ "$data" != "$s_data" ] && {
|
|
nxlog "$lp $svc share strings are different '$s_data' > '$data'"
|
|
updvars+=",data"; updvals+="&$data"; }
|
|
[ "$comp" != "$s_comp" ] && {
|
|
nxlog "$lp $svc comp strings are different '$s_comp' > '$comp'"
|
|
updvars+=",comp"; updvals+="&$comp"; }
|
|
[ "$addr" != "$s_addr" ] && {
|
|
nxlog "$lp $svc addr strings are different '$s_addr' > '$addr'"
|
|
updvars+=",addr"; updvals+="&$addr"; }
|
|
|
|
}
|
|
|
|
#nxlog "$lp _$st _$type _$svc _$port _$username _$pass _$data _$comp" _$share" #debug
|
|
if uservice_mount $type $svc $port "$(echo -e "${username//\%/\\x}")" \
|
|
"$pass" "$data" "$(echo -e "${comp//\%/\\x}")" "$share";
|
|
then
|
|
usvcs_set $svc "status,port""$updvars" "on&"$port$updvals
|
|
return 0
|
|
else usvcs_set $svc "status,port" "off&0"
|
|
fi
|
|
}
|
|
return 1
|
|
}
|
|
|
|
uservice_stop() {
|
|
#arg: svc [type] [norestart]
|
|
# Used gvars: session_id
|
|
local lp="$FUNCNAME ($$/$BASHPID):"
|
|
local i ok="" st type=$2 lport_name lport="" data="" hardstop=$3
|
|
# waiting for suitable service status: on
|
|
local step=0.25 timeo=28 #7sec
|
|
for (( i=0; i<=timeo; i++ )); do
|
|
st=$(usvcs_get $svc "status")
|
|
[ "$st" = "on" ] && { ok="1"; break; }
|
|
sleep $step"s"
|
|
done
|
|
[ -n "$ok" ] || {
|
|
nxlog "$lp service $svc still set in \"$st\" state after $((timeo/4))s waitng";
|
|
return 1; }
|
|
[ -z "$type" ] && type=$(usvcs_get $svc "type")
|
|
usvcs_set $svc "status" "stopping"
|
|
[ -n "$hardstop" ] || { # get suitable session first
|
|
lport_name=$(sess_lport_name $type)
|
|
local wstr="status='Running' AND session_id!='$session_id' AND $lport_name>0"
|
|
#nxlog "$lp $svc wstr='$wstr'" #debug
|
|
lport=$(q_vals_str_get "usess" "$wstr" "$lport_name") || {
|
|
hardstop=1
|
|
nxlog "$lp '$svc': other suitable listening port is not found" #; wstr='$wstr'" #debug
|
|
}
|
|
}
|
|
[ -n "$hardstop" ] && { # if unable to restart we must known data
|
|
data=$(usvcs_get $svc "data"); }
|
|
#nxlog "$lp '$svc': hs=$hardstop; data=$data" #debug
|
|
uservice_umount $type $svc "$data" "$port" || return 1
|
|
[ -n "$hardstop" ] && {
|
|
if [ "$SESSION_LOG_CLEAN" = "1" ]; then
|
|
q_dbe "DELETE FROM usvcs WHERE svc='$1';"
|
|
else usvcs_set $1 "status,port" "off&0"
|
|
fi
|
|
return 0;
|
|
}
|
|
usvcs_set $svc "status,port" "off&0"
|
|
uservice_start $svc $lport #|| return 1
|
|
return 0
|
|
}
|
|
|
|
node_stop_services() {
|
|
# Used gvars: session_id
|
|
#local lp="$FUNCNAME ($$/$BASHPID):"
|
|
local lports=",$(usess_get $session_id "smbport,cupsport,mmport" ',')"
|
|
lports=${lports//,0/}; lports=${lports:1}
|
|
[ -n "$lports" ] || return # no services in session
|
|
local svc svcs
|
|
svcs=$(q_vals_strs_get "usvcs" "status='on' AND port IN ($lports)" "svc") #"
|
|
#nxlog "$lp lports=($lports) services list to stop: '$svcs'"; #debug
|
|
for svc in $svcs; do uservice_stop $svc; done
|
|
}
|
|
|
|
node_terminate_session() {
|
|
#args: <session_id> [status]
|
|
# Used gvars: nx_dir
|
|
# Used config vars: COMMAND_XAUTH, SESSION_LOG_CLEAN SERVER_NAME
|
|
local lp="$FUNCNAME ($$/$BASHPID):";
|
|
#nxlog "$lp Start terminating session_id='$1' with status '$2'" #debug
|
|
local qs=$(usess_get "$1" "display,agent_pid,tail_pid,status")
|
|
[ -z "$qs" ] && {
|
|
nxlog "$lp session_id='$1' not found in usess db. Bye."; return;
|
|
}
|
|
local status=$(cutfn "$qs" 3 '&')
|
|
stringinstring "$status" "Terminating|Finished|Failed" && {
|
|
nxlog "$lp Session status is already '$status'. Bye."; return;
|
|
}
|
|
local display=$(cutfn "$qs" 0 '&'); local sess_id="$SERVER_NAME-$display-$1"
|
|
[ -d "$nx_dir/C-$sess_id" ] || {
|
|
nxlog "$lp Session dir '$nx_dir/C-$sess_id' not found. Bye."; return;
|
|
}
|
|
usess_set "$1" "status" "Terminating"
|
|
|
|
local agent_pid=$(cutfn "$qs" 1 '&') tail_pid=$(cutfn "$qs" 2 '&')
|
|
local t_status="$2"; [ -z "$2" ] && t_status="Finished"
|
|
node_stop_services
|
|
kill -0 $agent_pid 2>/dev/null && {
|
|
#nxlog "$lp start killing of nxagent ($agent_pid)" #debug
|
|
kill $agent_pid 2>/dev/null
|
|
wait $agent_pid 2>/dev/null
|
|
kill -0 $agent_pid 2>/dev/null ||
|
|
nxlog "$lp nxagent ($agent_pid) is dead now"
|
|
}
|
|
((tail_pid>0)) && kill -0 $tail_pid 2>/dev/null && { # Kill tail process
|
|
#nxlog "$lp kill tail process ($tail_pid)" #debug
|
|
kill $tail_pid 2>/dev/null
|
|
wait $tail_pid 2>/dev/null
|
|
kill -0 $tail_pid 2>/dev/null || {
|
|
nxlog "$lp tail ($tail_pid) is dead now"; tail_pid="0"
|
|
usess_set "$session_id" "tail_pid" "0"
|
|
}
|
|
}
|
|
|
|
#nxlog "$lp Remove session information" #debug
|
|
rm -f /tmp/.X$display-lock; rm -f /tmp/.X11-unix/X$display
|
|
# Remove magic cookie information
|
|
$COMMAND_XAUTH remove "localhost:$display" >/dev/null 2>&1
|
|
$COMMAND_XAUTH remove ":$display" >/dev/null 2>&1
|
|
if [ "$SESSION_LOG_CLEAN" = "1" ]; then
|
|
#nxlog "$lp Clean session information." #debug
|
|
rm -rf "$nx_dir/C-$sess_id/"
|
|
rm -f "$nx_dir/nxnode-$1.log"
|
|
rm -f "$nx_dir/nxnode.log"
|
|
elif [ "$2" = "Failed" ]; then mv "$nx_dir/C-$sess_id/" "$nx_dir/F-C-$sess_id"
|
|
else mv "$nx_dir/C-$sess_id/" "$nx_dir/T-C-$sess_id"
|
|
fi
|
|
usess_close "$1" "$t_status"
|
|
#nxlog "$lp end" #debug
|
|
}
|
|
|
|
node_fail_restore_session() {
|
|
#arg: <session_id>
|
|
#local lp="$FUNCNAME ($$/$BASHPID):"; nxlog "$lp starting" #debug
|
|
echo "NX> 1004 Error: Could not resume session. nxagent process could not be found."
|
|
node_terminate_session "$1" "Failed"
|
|
#nxlog "$lp end. Next is 'exit 1'" #debug
|
|
exit_proc 1
|
|
}
|
|
|
|
node_suspend_session() {
|
|
#arg: <session_id>
|
|
local lp="$FUNCNAME ($$/$BASHPID):";
|
|
#nxlog "$lp starting" #debug
|
|
local agent_pid=$(usess_get "$1" "agent_pid")
|
|
nxlog "$lp Killing (HUP) agent_pid ($agent_pid)..."
|
|
kill -0 $agent_pid 2>/dev/null || {
|
|
nxlog "$lp nxagent is already dead. end (1)"; return 1;
|
|
}
|
|
kill -HUP $agent_pid 2>/dev/null && {
|
|
nxlog "$lp end (HUP)"; return 0;
|
|
}
|
|
return 1
|
|
}
|
|
|
|
node_find_application() {
|
|
#args: <type>
|
|
# Used config vars: $COMMAND_START_KDE, $COMMAND_START_GNOME,
|
|
# $COMMAND_START_CDE, $COMMAND_XTERM, $USER_X_STARTUP_SCRIPT,$DEFAULT_X_SESSION
|
|
local lp="$FUNCNAME ($$/$BASHPID):";
|
|
#nxlog "$lp starting with args \"$@\"" #debug
|
|
local node_startx=""
|
|
case $1 in
|
|
shadow|windows|vnc) return
|
|
;;
|
|
unix-kde) node_startx=$COMMAND_START_KDE
|
|
;;
|
|
unix-gnome) node_startx=$COMMAND_START_GNOME
|
|
;;
|
|
unix-cde) node_startx=$COMMAND_START_CDE
|
|
;;
|
|
windows-helper)
|
|
node_startx="$COMMAND_RDESKTOP /v:$agent_server /u:$agent_user"
|
|
[ -n "$agent_domain" ] && node_startx+=" /d:$agent_domain"
|
|
node_startx+=" /t:NX-$session-RDP-$agent_server@$agent_user"
|
|
node_startx+=" /p:$agent_password /size:$geometry $EXTRA_OPTIONS_RDP"
|
|
;;
|
|
vnc-helper)
|
|
if [ ! -x "$COMMAND_VNCVIEWER" ]; then
|
|
echo "$COMMAND_XMSG 'vncviwer not found'"
|
|
else
|
|
mkdir -p "$NXSESSION_DIRECTORY/scripts/"
|
|
echo "$agent_password" | \
|
|
$COMMAND_VNCPASSWD $NXSESSION_DIRECTORY/scripts/.passwd doit
|
|
node_startx="$COMMAND_VNCVIEWER -passwd \
|
|
$NXSESSION_DIRECTORY/scripts/.passwd $EXTRA_OPTIONS_RFB $agent_server"
|
|
fi
|
|
;;
|
|
unix-application)
|
|
[ "$application" = "xterm" ] && application=$COMMAND_XTERM
|
|
node_startx=$application
|
|
;;
|
|
unix-console) node_startx=$COMMAND_XTERM
|
|
;;
|
|
unix-default|*)
|
|
if [ -x "$HOME/$USER_X_STARTUP_SCRIPT" ]; then
|
|
node_startx="$HOME/$USER_X_STARTUP_SCRIPT"
|
|
elif [ -x "$DEFAULT_X_SESSION" ]; then
|
|
node_startx="$DEFAULT_X_SESSION"
|
|
else node_startx=$COMMAND_XTERM
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
# dimbor: another personalyzed way to ACLS control and replace X-application
|
|
[ -n "$NX_ACL_DIR" ] || { echo "$node_startx"; return; }
|
|
|
|
local ucond=$(groups); ucond="'#$USER','*${ucond// /\',\'\*}','@all'"
|
|
local mode=".mode csv settings\n.separator '&'\n"
|
|
local qstr="SELECT key,value,val_depend FROM settings WHERE user IN ($ucond) \
|
|
AND key NOT IN ('@shadow@') ORDER BY user ASC, val_check ASC;"
|
|
#nxlog "$lp qstr='$qstr'" #debug
|
|
local ts=$(qa_dbe "$mode" "$qstr")
|
|
#nxlog "$lp ts='$ts'" #debug
|
|
local l tpl inv pm l2="" app_match="" app_rep="$COMMAND_XMSG '$NX_ACL_WARN'"
|
|
while read l; do
|
|
tpl="${l%%&*}"; tpl="$(sq2s "$tpl")"
|
|
inv=0; [ "${tpl:0:1}" = "!" ] && { tpl="${tpl:1}"; inv=1; }
|
|
pm=0; [[ "$node_startx" =~ $tpl ]] && pm=1
|
|
#nxlog "$lp $node_startx -> \"$l\" -> $tpl $inv $pm" #debug
|
|
((inv+pm==1)) && { l2=$l; app_match=1; break; }
|
|
done <<< "$ts"
|
|
if [ -n "$app_match" ]; then
|
|
tpl=$(cutfn "$l2" 1 '&'); tpl=$(sq2s "$tpl")
|
|
[ -n "$tpl" ] && { # process list checking
|
|
app_match=""
|
|
inv=0; [ "${tpl:0:1}" = "!" ] && { tpl="${tpl:1}"; inv=1; }
|
|
local psall=""; [ "${tpl:0:2}" = "@@" ] && { tpl="${tpl:2}"; psall=1; }
|
|
local psl;
|
|
if [ -n "$psall" ]; then psl="$(ps ax -o cmd=)"
|
|
else psl="$(ps -o cmd= -U $USER)"
|
|
fi
|
|
pm=0; rematchfn "($tpl)" "$psl" &>/dev/null && pm=1
|
|
((inv+pm==1)) && app_match=1
|
|
#nxlog "$lp $l - $tpl $inv $pm" #debug
|
|
}
|
|
local msg=$(cutfn "$l2" 2 '&'); msg=$(sq2s "$msg")
|
|
[ -n "$msg" ] && { # exe/msg checking
|
|
# need absolute path here?
|
|
[ -x "${msg%% *}" ] && app_rep="$msg" || app_rep="$COMMAND_XMSG '$msg'"
|
|
}
|
|
fi
|
|
if [ -n "$app_match" ]; then
|
|
echo "$node_startx";
|
|
else
|
|
nxlog "$lp App '$node_startx' replaced to '$app_rep'"
|
|
echo "$app_rep"
|
|
fi
|
|
}
|
|
|
|
node_start_applications() {
|
|
# Used glob vars: $type, $application, $sess_id, $mediahelper,
|
|
# $virtualdesktop, $rootless, $display
|
|
# Used config vars: <several>
|
|
local lp="$FUNCNAME ($$/$BASHPID):";
|
|
#nxlog "$lp starting" #debug
|
|
local app node_app napp;
|
|
local slave_apps psess sess_ps sapp;
|
|
local node_app_pid node_wm_pid;
|
|
local ok step timeo
|
|
local q=0 i s l
|
|
|
|
# Prepare application startup
|
|
export DISPLAY=:$display
|
|
|
|
#nxlog "$lp display='$display', waiting for it's ready" #debug
|
|
ok="" step="0.01" timeo=$((AGENT_STARTUP_TIMEOUT*100))
|
|
for (( i=0; i<=timeo; i++ )); do
|
|
[ -f /tmp/.X$display-lock ] && { ok="1"; break; }
|
|
sleep $step"s"
|
|
done
|
|
[ -n "$ok" ] || {
|
|
nxlog "$lp /tmp/.X$display-lock not found after $AGENT_STARTUP_TIMEOUT s";
|
|
return 1; }
|
|
|
|
#numlockx
|
|
if [ "$NUMLOCK_METHOD" != "system" ]; then
|
|
#nxlog "$lp Run \"$NUMLOCKX $NUMLOCKX_STATUS\"" #debug
|
|
"$NUMLOCKX" "$NUMLOCKX_STATUS"
|
|
fi
|
|
|
|
# Which application do we start?
|
|
app=$(node_find_application "$type")
|
|
# For rdesktop/VNC, there is no application to start
|
|
[ -n "$app" ] || return
|
|
|
|
if [ "$ENABLE_SAMBA_PRELOAD" = "1" ]; then
|
|
NXSAMBA_PORT=$(usess_get "$session_id" "smbport")
|
|
((NXSAMBA_PORT>0)) && {
|
|
export NXSAMBA_PORT
|
|
#nxlog "$lp Preload SAMBA using nxredir. NXSAMBA_PORT is '$NXSAMBA_PORT'" #debug
|
|
node_app="$PATH_BIN/nxredir $node_app"
|
|
echo "Info: NXNODE - Using nxredir wrapper script to forward \
|
|
SMB ports 139 and 445 to port $NXSAMBA_PORT." >> "$NXSESSION_DIRECTORY/session"
|
|
}
|
|
fi
|
|
#nxlog "$lp app is $app" #debug
|
|
|
|
# do fake eval for params
|
|
q=0; l=$app; node_app=()
|
|
while [ -n "$l" ]; do
|
|
s=${l%%[\'\"]*}; l=${l#*[\'\"]}
|
|
[ "$s" = "$l" ] && l=""
|
|
[ -n "$s" ] || continue
|
|
((q==0)) && { node_app+=($s); q=1; } || { node_app+=("$s"); q=0; }
|
|
done
|
|
#nxlog "$lp ${#node_app[@]}" #debug
|
|
#for ((i=0; i<${#node_app[@]}; i++)); do nxlog "$lp ${node_app[$i]}"; done #debug
|
|
|
|
[ "$cups" = "1" -o "$samba" = "1" ] && {
|
|
#nxlog "$lp export CUPS_SERVER=$CUPS_DEFAULT_SOCK" #debug
|
|
export CUPS_SERVER=$CUPS_DEFAULT_SOCK
|
|
}
|
|
|
|
# Use Xsession to execute the Desktop session
|
|
case $type in
|
|
unix-gnome)
|
|
export STARTUP="${node_app[@]}"
|
|
[ "$BOOTSTRAP_X_SESSION" = "1" ] && node_app=($COMMAND_GDM_X_SESSION)
|
|
;;
|
|
unix-kde|unix-cde)
|
|
export STARTUP="${node_app[@]}"
|
|
[ "$BOOTSTRAP_X_SESSION" = "1" ] && node_app=($DEFAULT_X_SESSION)
|
|
;;
|
|
esac
|
|
|
|
[ $ENABLE_ROOTLESS_TERMINATE_SESSION = "1" -a "$rootless" = "1" ] && {
|
|
psess=$($COMMAND_PS -wo sess= -p $$)
|
|
napp=${node_app[0]}; napp=${napp##*/}
|
|
slave_apps=$(rematchfn "$napp:(.+)" "${APP_WAIT_MAP//;/$'\n'}") #"
|
|
#nxlog "$lp slave(s) will be waiting too. Initial apps: '$slave_apps'" #debug
|
|
}
|
|
|
|
# Do we need to PRELOAD any libraries?
|
|
[ "$virtualdesktop" = "0" -a "$rootless" != "1" ] && export LD_PRELOAD="$APPLICATION_LIBRARY_PRELOAD:$LD_PRELOAD"
|
|
|
|
# close input and output file descriptors
|
|
exec 0<&-; exec 1>&-; exec 2>&-
|
|
|
|
# Should we start a window manager?
|
|
if [ "$virtualdesktop" = "1" -a "$type" = "unix-application" -a \
|
|
-x "$DEFAULT_X_WM" ]; then
|
|
#nxlog "$lp start a window manager - \"DISPLAY=:$display $DEFAULT_X_WM\"" #debug
|
|
DISPLAY=:$display $DEFAULT_X_WM >>"$NXSESSION_DIRECTORY/session" 2>&1 &
|
|
node_wm_pid=$!
|
|
#nxlog "$lp node_wm_pid='$node_wm_pid'" #debug
|
|
fi
|
|
|
|
# Startup the application
|
|
#nxlog "$lp Starting node_app with /etc/nxserver/Xsession" #debug
|
|
DISPLAY=:$display /etc/nxserver/Xsession "${node_app[@]}" >> \
|
|
"$NXSESSION_DIRECTORY/session" 2>&1 &
|
|
node_app_pid=$!
|
|
nxlog "$lp Start '${node_app[@]}'. Waiting for node_app_pid='$node_app_pid'"
|
|
wait $node_app_pid
|
|
nxlog "$lp node_app_pid finished"
|
|
|
|
# Kill or wait for the started window manager
|
|
[ -n "$node_wm_pid" ] && {
|
|
nxlog "$lp node_wm_pid is not empty"
|
|
# kill the WM after application is finished?
|
|
[ "$KILL_DEFAULT_X_WM" = "1" ] && { nxlog "$lp killing $node_wm_pid"
|
|
kill $node_wm_pid 2>/dev/null; }
|
|
# or just wait until it finishes?
|
|
[ "$KILL_DEFAULT_X_WM" = "1" ] || { nxlog "$lp wait for $node_wm_pid is dead"
|
|
wait $node_wm_pid; }
|
|
}
|
|
sleep "$NODE_APP_WAIT_TIMEOUT"s
|
|
|
|
[ $ENABLE_ROOTLESS_TERMINATE_SESSION = "1" -a "$rootless" = "1" ] && {
|
|
if [ -n "$slave_apps" ] ; then
|
|
nxlog "$lp slave(s) will be waiting too. Initial: '$slave_apps'"
|
|
sapp=$napp
|
|
while [ -n "$sapp" ]; do
|
|
sess_ps=$($COMMAND_PS -wo user=,cmd= -s $psess); sapp=""
|
|
#nxlog "$lp '$sess_ps'" #debug
|
|
while read l; do
|
|
[ "$(cutfn "$l" 0)" = "$USER" ] || continue
|
|
s=$(cutfn "$l" 1); s=${s##*/}
|
|
stringinstring "$s," "$slave_apps," && {
|
|
sapp=$s;
|
|
#nxlog "$lp >> $sapp '$l'" #debug
|
|
break;
|
|
}
|
|
done <<< "$sess_ps"
|
|
sleep "$NODE_APP_WAIT_TIMEOUT"s
|
|
done
|
|
nxlog "$lp Session app(s) are finished"
|
|
fi
|
|
node_terminate_session "$session_id"
|
|
}
|
|
|
|
# Do not terminate agent in case of rootless agent mode.
|
|
# The agent times out after a while by itself anyway.
|
|
if [ "$virtualdesktop" = "1" -o "$rootless" != "1" ] ; then
|
|
#nxlog "$lp Call node_terminate_session for non-rootless or virtualdesktop session type" #debug
|
|
node_terminate_session "$session_id"
|
|
fi
|
|
#nxlog "$lp end" #debug
|
|
}
|
|
|
|
node_agent_persistent_session() {
|
|
# Is the user allowed to run a persistent session?
|
|
local username IFS="," p="-nopersistent"
|
|
[ "$ENABLE_PERSISTENT_SESSION" = "all" ] && p="-persistent" || {
|
|
for username in $ENABLE_PERSISTENT_SESSION; do
|
|
[ "${username:0:1}" != "@" ] && [ "$USER" = "$username" ] && \
|
|
p="-persistent" && break;
|
|
[ "${username:0:1}" = "@" ] && \
|
|
[ -z $(groups "$USER" | egrep "^${username:1}:") ] && \
|
|
p="-persistent" && break;
|
|
done
|
|
}
|
|
for username in $DISABLE_PERSISTENT_SESSION; do
|
|
[ "${username:0:1}" != "@" ] && [ "$USER" = "$username" ] && \
|
|
p="-nopersistent" && break;
|
|
[ "${username:0:1}" = "@" ] && \
|
|
[ -z $(groups "$USER" | egrep "^${username:1}:") ] && \
|
|
p="-nopersistent" && break;
|
|
done
|
|
echo "$p"
|
|
}
|
|
|
|
node_start_agent() {
|
|
# Ok, now we do some wicked fd magic.
|
|
# first part: nxagent's fd #2 -> fd #3
|
|
# second part: fd #1 -> #4; fd #3 -> #1; tee | node_start_monitor
|
|
# third part: fd #4 -> #1
|
|
# => all output of nxagent goes to tee | node_start_monitor, while
|
|
# leaving all other output flow through like normally.
|
|
|
|
# preparations
|
|
local lp="$FUNCNAME ($$/$BASHPID):";
|
|
local k g b r fp vncfullscreen u p d agent_port viewonly
|
|
local agent_exit_status node_failed
|
|
#nxlog "$lp starting" #debug
|
|
exec 3>&2; exec 4>&1;
|
|
|
|
{
|
|
|
|
{
|
|
|
|
export DISPLAY="nx/nx,options=$NXSESSION_DIRECTORY/options:$display"
|
|
export XAUTHORITY="$NXSESSION_DIRECTORY/authority"
|
|
export HOME
|
|
export NX_CLIENT="$PATH_BIN/nxdialog"
|
|
|
|
# Setup optional parameters for nxagent
|
|
# keyboard
|
|
k=""
|
|
# backwards compatibility
|
|
[ -n "$keyboard" ] && k="-keyboard $keyboard"
|
|
[ -n "$kbtype" ] && k="-kbtype $kbtype"
|
|
# backingstore
|
|
b=""
|
|
if [ -n "$backingstore" ]; then
|
|
[ "$backingstore" != 1 ] && b="-bs $backingstore"
|
|
[ "$backingstore" = 1 ] && b="+bs"
|
|
fi
|
|
|
|
# geometry
|
|
g=""
|
|
[ -n "$geometry" ] && g="-geometry $geometry"
|
|
|
|
# type of session
|
|
r="-D"; [ "$rootless" = "1" ] && r="-R"
|
|
|
|
# Setup fullscreen parameters
|
|
[ "$geometry" = "fullscreen" ] && \
|
|
[ "$type" = "vnc-helper" -o "$type" = "windows-helper" ] && \
|
|
g="-geometry $(rematchfn '^([[:digit:]]+x[[:digit:]]+)' $screeninfo)"
|
|
|
|
if [ "$r" = "-R" -a "$rootless" != "1" ]; then
|
|
#nxlog "$lp Start nxproxy for single application session mode" #debug
|
|
[ "$SET_LD_LIBRARY_PATH" = "1" ] && \
|
|
export LD_LIBRARY_PATH="$PROXY_LIBRARY_PATH:$LD_LIBRARY_PATH"
|
|
nxlog "$lp Start nxproxy by command: '$PATH_BIN/nxproxy -C :$display $PROXY_EXTRA_OPTIONS'"
|
|
$PATH_BIN/nxproxy -C :$display $PROXY_EXTRA_OPTIONS 2>&3 &
|
|
else
|
|
#nxlog "$lp nxagent session type (X11)" #debug
|
|
[ "$SET_LD_LIBRARY_PATH" = "1" ] && \
|
|
export LD_LIBRARY_PATH="$AGENT_LIBRARY_PATH:$LD_LIBRARY_PATH"
|
|
# Setup optional parameters
|
|
p=$(node_agent_persistent_session)
|
|
fp=""; [ -n "$AGENT_FONT_SERVER" ] && fp="-fp $AGENT_FONT_SERVER"
|
|
if [ "$type" = "shadow" ]; then
|
|
nxlog "$lp Type \"shadow\". Add some args to nxagent"
|
|
local shmode=$ENABLE_INTERACTIVE_SESSION_SHADOWING
|
|
[ "$shmode" = "1" ] && [ "$shadowviewonly" = "1" ] && shmode="0"
|
|
r="-S -shadow $shadowhost:$shadowdisplay -shadowmode $shmode"
|
|
p="-nopersistent"
|
|
fi
|
|
# Start the agent
|
|
#nxlog "$lp env start `env`"; nxlog "$lp env end"
|
|
nxlog "$lp Start nxagent by command: '$COMMAND_NXAGENT $p $r -name \"NX - $user@$SERVER_NAME:$display - $session (GPL Edition)\" -option \"$NXSESSION_DIRECTORY/options\" $b $fp $AGENT_EXTRA_OPTIONS_X :$display'"
|
|
#PATH="$PATH_BIN:$PATH" $COMMAND_NXAGENT $p $r -name "NX - $user@$SERVER_NAME:$display - $session (GPL Edition)" -option "$NXSESSION_DIRECTORY/options" $k $g $b $fp $AGENT_EXTRA_OPTIONS_X :$display 2>&3 &
|
|
PATH="$PATH_BIN:$PATH" $COMMAND_NXAGENT $p $r \
|
|
-name "NX - $user@$SERVER_NAME:$display - $session (GPL Edition)" \
|
|
-option "$NXSESSION_DIRECTORY/options" $b $fp \
|
|
$AGENT_EXTRA_OPTIONS_X :$display 2>&3 &
|
|
fi
|
|
|
|
# Wait for the agent
|
|
agent_pid=$!
|
|
usess_set "$session_id" "agent_pid" "$agent_pid"
|
|
echo "NX> 733 Agent pid: $agent_pid:"
|
|
nxlog "$lp Waiting for agent_pid='$agent_pid'"
|
|
wait $agent_pid; agent_exit_status=$?
|
|
nxlog "$lp agent_exit_status='$agent_exit_status'"
|
|
node_failed=""
|
|
if [ $agent_exit_status -ne 0 ]; then
|
|
echo "NX> 1004 Error: NX Agent exited with exit status $agent_exit_status. To troubleshoot set SESSION_LOG_CLEAN=0 in node.conf and investigate \"$nx_dir/F-C-$sess_id/session\". You might also want to try: ssh -X myserver; $PATH_BIN/nxnode --agent to test the basic functionality. Session log follows:"
|
|
echo "$(< $NXSESSION_DIRECTORY/session)" >&2
|
|
node_failed="Failed"
|
|
nxlog "$lp node_failed='$node_failed'"
|
|
fi
|
|
#nxlog "$lp close session" #debug
|
|
echo "NX> 1006 Session status: closed"
|
|
# Cleanup session information
|
|
#nxlog "$lp cleanup session information '$sess_id'" #debug
|
|
#nxlog "$lp call 'node_terminate_session \"$session_id\" \"$node_failed\"'" #debug
|
|
node_terminate_session "$session_id" "$node_failed"
|
|
|
|
# remove possible leftovers of nxagent
|
|
#nxlog "$FUNCNAME ($$):remove /tmp/.X$display-lock" #debug
|
|
rm -f /tmp/.X$display-lock
|
|
#nxlog "$lp remove /tmp/.X11-unix/X$display" #debug
|
|
rm -f /tmp/.X11-unix/X$display
|
|
|
|
} 3>&1 1>&4 | tee "$NXSESSION_DIRECTORY/session" | \
|
|
node_start_monitor; } 4>&1
|
|
}
|
|
|
|
|
|
node_emergency_exit() {
|
|
local lp="$FUNCNAME ($$/$BASHPID):";
|
|
#nxlog "$lp starting" #debug
|
|
#nxlog "$lp call 'node_terminate_session \"$session_id\" \"Failed\"'" #debug
|
|
node_terminate_session "$session_id" "Failed"
|
|
echo "NX> 1004 Error: Emergency exit due to kill signal."
|
|
#nxlog "$lp end" #debug
|
|
}
|
|
|
|
node_start_monitor() {
|
|
#arg: <start|restore>
|
|
# Monitoring the nxagent: Its also kind of a "state-machine"
|
|
# as it has to keep track of different
|
|
# connection states and react differently.
|
|
local lp="$FUNCNAME ($$/$BASHPID):";
|
|
#nxlog "$lp starting with arg: $@" #debug
|
|
local tail_pid="" watchdog_pid tosend pars_sent=""
|
|
local smbport="0" mmport="0" cupsport="0"
|
|
|
|
while read line; do
|
|
case "$line" in
|
|
*"Info: Waiting for connection from"*)
|
|
[ -n "$pars_sent" ] && continue; # send params only once
|
|
tosend="NX> 700 Session id: $sess_id
|
|
NX> 705 Session display: $display\nNX> 703 Session type: $type
|
|
NX> 701 Proxy cookie: $cookie\nNX> 702 Proxy IP: $proxyip
|
|
NX> 706 Agent cookie: $cookie\nNX> 704 Session cache: $type
|
|
NX> 707 SSL tunneling: $encryption\n"
|
|
# File-sharing port options
|
|
[ "$samba" = "1" ] &&
|
|
tosend+="NX> 709 File-sharing port: 445\n"
|
|
echo -e "$tosend""NX> 710 Session status: running
|
|
NX> 1002 Commit\nNX> 1006 Session status: running"
|
|
pars_sent="1"; continue;
|
|
;;
|
|
*"Info: Listening"*"SMB connections on port"*)
|
|
# Catch NXAGENT SMB Port (sometimes the port differs from what we got from nxserver)
|
|
smbport=$(cutfn "$line" 1 "'"); smbport=${smbport##*:}
|
|
usess_set "$session_id" "smbport" "$smbport"
|
|
continue;
|
|
;;
|
|
*"Info: Listening"*"multimedia connections on port"*)
|
|
# Catch NXAGENT Multimedia Port
|
|
mmport=$(cutfn "$line" 1 "'"); mmport=${mmport##*:}
|
|
usess_set "$session_id" "mmport" "$mmport"
|
|
continue;
|
|
;;
|
|
*"Info: Listening"*"CUPS connections on port"*)
|
|
# Catch NXAGENT CUPS Port
|
|
cupsport=$(cutfn "$line" 1 "'"); cupsport=${cupsport##*:}
|
|
usess_set "$session_id" "cupsport" "$cupsport"
|
|
continue;
|
|
;;
|
|
*"Info: Watchdog running with pid"*)
|
|
# Watchdog termination
|
|
watchdog_pid=$(cutfn "$line" 1 "'")
|
|
continue;
|
|
;;
|
|
*"Info: Waiting the watchdog process to complete"*)
|
|
# Kill the watchdog
|
|
kill $watchdog_pid 2>/dev/null
|
|
continue;
|
|
;;
|
|
esac
|
|
|
|
if [ "$1" != "restore" ]; then # "start" instance
|
|
case "$line" in
|
|
*"Session: Starting session at"*)
|
|
echo "NX> 1009 Session status: starting"
|
|
usess_set "$session_id" "status" "Starting"
|
|
;;
|
|
*"Session: Session started at"*)
|
|
usess_set "$session_id" "status" "Running"
|
|
;;
|
|
*"Session: Suspending session at"*)
|
|
echo "NX> 1009 Session status: suspending"
|
|
usess_set "$session_id" "status" "Suspending"
|
|
;;
|
|
*"Session: Terminating session at"*)
|
|
echo "NX> 1009 Session status: terminating"
|
|
;;
|
|
*"Session: Session suspended at"*)
|
|
# Session suspend
|
|
echo "NX> 1005 Session status: suspended"
|
|
#nxlog "$lp $line" #debug
|
|
((mmport+smbport+cupsport>0)) && {
|
|
#nxlog "$lp call node_stop_services" #debug
|
|
node_stop_services
|
|
}
|
|
usess_set "$session_id" "status,userip,acc_ip" "Suspended&&"
|
|
;;
|
|
esac
|
|
else # "restore" instance
|
|
#nxlog "$lp nxagent output: $line"
|
|
case "$line" in
|
|
*"Info: tail -f running with pid"*)
|
|
# Catch tail pid
|
|
tail_pid=$(cutfn "$line" 1 "'")
|
|
usess_set "$session_id" "tail_pid" "$tail_pid"
|
|
#echo "$node_tail_pid" >"$nx_dir/C-$sess_id/pids/tail"
|
|
;;
|
|
*"Session: Resuming session at"*)
|
|
echo "NX> 1009 Session status: resuming"
|
|
usess_set "$session_id" "status" "Resuming"
|
|
;;
|
|
*"Session: Session resumed at"*)
|
|
# Reconnection success!
|
|
echo "NX> 718 Session restore succeded"
|
|
usess_set "$session_id" "status,userip,acc_ip"\
|
|
"Running&$userip&$accept"
|
|
kill $tail_pid 2>/dev/null; break
|
|
;;
|
|
*"Session: Display failure detected at"*)
|
|
# Reconnection failure
|
|
echo "NX> 596 Error: Session $1 failed. Reason was: $line"
|
|
kill $tail_pid 2>/dev/null; break
|
|
;;
|
|
esac
|
|
fi
|
|
done
|
|
|
|
trap "" EXIT
|
|
|
|
[ "$1" != "restore" -a "$rootless" != "1" ] && {
|
|
nxlog "$lp call node_stop_services at ending"
|
|
node_stop_services;
|
|
}
|
|
# close all open file descriptors
|
|
exec 0<&-; exec 1>&-; exec 2>&-;
|
|
#nxlog "$lp end" #debug
|
|
exit_proc 0
|
|
}
|
|
|
|
startsession() { # Start a new session.
|
|
# 1.5.0 options: rdpcolors,rdpcache,http
|
|
# nxclient > 1.5.0-106 variables: resize,keybd
|
|
# FreeNX specific variables: clientproto,status,host
|
|
# NX 3.0 shadow mode related variables: shadowusername,shadowcookie,
|
|
# shadowdisplay,shadowhost
|
|
# dimbor: additional extra-channels extra[1-3], patched nxcomp both
|
|
# on server and client are required
|
|
|
|
local lp="$FUNCNAME ($$/$BASHPID):";
|
|
local opt_vars opt_str pack cleanup product clipboard menu;
|
|
local id fullscreen accept vn;
|
|
local i ok step timeo
|
|
#nxlog "$lp starting with args \"$@\"" #debug
|
|
|
|
[ "$1" = "start" ] && mkdir -p -m700 "$NXSESSION_DIRECTORY"
|
|
# Setup environment
|
|
[ -n "$SOURCE_SYS_PROFILE" ] && . $SOURCE_SYS_PROFILE
|
|
[ -n "$SOURCE_USER_PROFILE" ] && {
|
|
if [ "${SOURCE_USER_PROFILE:0:1}" != "/" ]; then
|
|
. $HOME/$SOURCE_USER_PROFILE
|
|
else . $SOURCE_USER_PROFILE
|
|
fi
|
|
}
|
|
|
|
[ "$PROXY_TCP_NODELAY" = "0" ] && nodelay=0
|
|
[ "$ENABLE_ROOTLESS_MODE" = "0" ] && rootless=0
|
|
[ -z "$samba" ] && samba=0; [ -z "$media" ] && media=0
|
|
[ -z "$shmem" ] && shmem=0; [ -z "$shpix" ] && shpix=0
|
|
[ "$geometry" = "fullscreen" ] && fullscreen="1" || fullscreen="0"
|
|
[ -z "$nodelay" ] && nodelay=1 # ???
|
|
cleanup=10; product=LFE/None/LFEN/None; id=$sess_id;
|
|
clipboard="$ENABLE_CLIPBOARD"; menu="$ENABLE_PULLDOWN_MENU"
|
|
windows_app=$application
|
|
[ -z "$keybd" ] && keybd=$aux # backwards compatibility for keybd parameter
|
|
|
|
[ "$EXPORT_USERIP" = "1" ] && export NXUSERIP="$userip"
|
|
[ "$EXPORT_SESSIONID" = "1" ] && export NXSESSIONID="$sess_id"
|
|
export SHADOW_XAUTHORITY="$NXSESSION_DIRECTORY/authority"
|
|
if [ "$type" = "vnc-helper" -o "$type" = "windows-helper" ]; then
|
|
# We do not want to suspend such a session
|
|
# as RDP/RFB are both suspendable as well
|
|
ENABLE_PERSISTENT_SESSION=""
|
|
fi
|
|
|
|
if [ "$encryption" = "1" ]; then
|
|
# we need to use the IP of the "calling" server now
|
|
accept=$(rematchfn "($ip4_pattern)" "$SSH_CLIENT $SSH2_CLIENT") #"
|
|
# If host is the same, use 127.0.0.1, else fallback to default
|
|
[ -z "$accept" -a "$host" = "127.0.0.1" ] && accept="127.0.0.1"
|
|
else encryption=0; accept=$userip
|
|
fi
|
|
|
|
# We need our own external IP
|
|
proxyip="$EXTERNAL_PROXY_IP"; [ -z "$proxyip" ] && proxyip="127.0.0.1"
|
|
|
|
pack=""
|
|
if [ -z "$imagecompressionlevel" ]; then imagecompressionlevel="9"
|
|
elif [ "$imagecompressionmethod" = "0" ]; then pack="nopack"
|
|
elif [ "$imagecompressionmethod" = "1" ]; then pack="16m-jpeg-$imagecompressionlevel"
|
|
elif [ "$imagecompressionmethod" = "2" ]; then pack="16m-png-9"
|
|
fi
|
|
|
|
if [ "$1" = "start" ]; then
|
|
cookie=$(echo $[$RANDOM*$RANDOM] | $COMMAND_MD5SUM); cookie=${cookie%% *}
|
|
# add row to usses with defaults: session_id, status, display, type,
|
|
# client, agent_pid, cookie, tail_pid, userip, acc_ip, mmport, cupsport,\
|
|
# smbport
|
|
usess_add "$sqcols_usess" "$session_id&Starting&$display&$type&$client&\
|
|
0&$cookie&0&$userip&$accept&0&0&0&"
|
|
elif [ "$1" = "restore" ]; then
|
|
cookie=$(usess_get "$session_id" "cookie")
|
|
fi
|
|
|
|
if [ "$1" = "application" ]; then
|
|
# This needs to be set, else nxagent is terminated
|
|
rootless="1"; virtualdesktop="0"
|
|
#nxlog "$lp call 'node_start_applications'" #debug
|
|
node_start_applications &
|
|
echo "NX> 596 Application $application started successfully."
|
|
return
|
|
fi
|
|
|
|
#nxlog "$lp generate \"$NXSESSION_DIRECTORY/options\"" #debug
|
|
opt_vars="keyboard kbtype kbload keymap geometry\
|
|
client resize cache images pack link nodelay type clipboard composite\
|
|
cleanup product shmem backingstore shpix accept cookie id samba media\
|
|
sync cups keybd aux http extra1 extra2 extra3 rdpcolors rdpcache\
|
|
fullscreen menu"
|
|
opt_str="nx/nx";
|
|
for vn in $opt_vars; do [ -n "${!vn}" ] && opt_str+=",$vn=${!vn}"; done
|
|
#[ "$type" = "shadow" ] && opt_str+=",shadow=1"
|
|
opt_str+=":$display"
|
|
# write options file
|
|
umask 0077; echo "$opt_str" > "$NXSESSION_DIRECTORY/options"; umask $umask0
|
|
|
|
if [ "$1" = "start" ]; then # write xauth script file
|
|
#nxlog "$lp write xauth script file" #debug
|
|
txt="add localhost:$display MIT-MAGIC-COOKIE-1 $cookie
|
|
add :$display MIT-MAGIC-COOKIE-1 $cookie
|
|
exit"
|
|
echo "$txt" | $COMMAND_XAUTH >/dev/null 2>&1
|
|
echo "$txt" | $COMMAND_XAUTH -f "$NXSESSION_DIRECTORY/authority" >/dev/null 2>&1
|
|
fi
|
|
|
|
if [ -n "$shadowcookie" ]; then
|
|
#nxlog "$lp If we have a shadow cookie, we add it to xauth session authority file as well" #debug
|
|
$COMMAND_XAUTH -f "$SHADOW_XAUTHORITY" add "$shadowhost:$shadowdisplay" MIT-MAGIC-COOKIE-1 "$shadowcookie"
|
|
elif [ -n "$shadowdisplay" ]; then
|
|
# we need to merge in the normal .Xauthority file
|
|
#nxlog "$lp we need to merge in the normal .Xauthority file" #debug
|
|
$COMMAND_XAUTH -f "$SHADOW_XAUTHORITY" merge "$HOME/.Xauthority"
|
|
fi
|
|
|
|
if [ "$1" = "restore" ]; then
|
|
#nxlog "$lp restore session" #debug
|
|
#echo > "$NXSESSION_DIRECTORY/session" #this cause to damage file
|
|
sh -c 'echo "Info: tail -f running with pid '\'\$$\''."; exec tail -n1 -f '"$NXSESSION_DIRECTORY"'/session' | node_start_monitor "restore" &
|
|
MONITOR_PID=$!; export MONITOR_PID
|
|
#nxlog "$lp call 'node_suspend_session \"$session_id\"'" #debug
|
|
node_suspend_session "$session_id" || {
|
|
echo "Info: Reconnection failed: NX Agent process could not be found." >> \
|
|
"$NXSESSION_DIRECTORY/session";
|
|
node_fail_restore_session "$session_id";
|
|
return 1;
|
|
}
|
|
else # start
|
|
#nxlog "$lp call 'node_start_agent'" #debug
|
|
node_start_agent &
|
|
#nxlog "$lp call 'node_start_applications'" #debug
|
|
node_start_applications &
|
|
if [ -x "$NODE_AUTOSTART" ]; then
|
|
#nxlog "$lp NODE_AUTOSTART: waiting for nxagent" #debug
|
|
ok="" step="0.01" timeo=$((AGENT_STARTUP_TIMEOUT*100))
|
|
for (( i=0; i<=timeo; i++ )); do
|
|
[ -f /tmp/.X$display-lock ] && { ok="1"; break; }
|
|
sleep $step"s"
|
|
done
|
|
[ -n "$ok" ] || {
|
|
nxlog "$lp /tmp/.X$display-lock not found after $AGENT_STARTUP_TIMEOUT s";
|
|
}
|
|
|
|
# go into background immediately
|
|
NXSESSIONID="$sess_id" DISPLAY=:$display "$NODE_AUTOSTART" "$1" >/dev/null 2>&1 &
|
|
disown $! # dont't wait for this child!
|
|
fi
|
|
fi
|
|
|
|
if [ -n "$mediahelper" -a "$1" != "application" ]; then
|
|
#nxlog "$lp display='$display', waiting for it's ready" #debug
|
|
ok="" step="0.01" timeo=$((AGENT_STARTUP_TIMEOUT*100))
|
|
for (( i=0; i<=timeo; i++ )); do
|
|
[ -f /tmp/.X$display-lock ] && { ok="1"; break; }
|
|
sleep $step"s"
|
|
done
|
|
[ -n "$ok" ] || \
|
|
nxlog "$lp /tmp/.X$display-lock not found after $AGENT_STARTUP_TIMEOUT s";
|
|
[ -n "$ok" ] && {
|
|
#nxlog "$lp env: $(env)" #debug
|
|
uservice_start ${mediahelper%%-*} "" "media-pa" "" "" "" "$mediahelper"
|
|
}
|
|
fi
|
|
|
|
if [ -n "$MONITOR_PID" ]; then
|
|
wait "$MONITOR_PID"
|
|
usess_set "$session_id" "tail_pid" "0"
|
|
fi
|
|
wait # for all children
|
|
#nxlog "$lp end" #debug
|
|
}
|
|
|
|
cmd_node_terminate() {
|
|
echo "$delim 716 Terminating session $session_id on user request."
|
|
node_terminate_session "$session_id"
|
|
}
|
|
|
|
cmd_node_suspend() {
|
|
echo "$delim 716 Suspending session $session_id on user request."
|
|
node_suspend_session "$session_id"
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Startup of nxnode
|
|
# -----------------------------------------------------------------------------
|
|
declare -g delim="NX>" CMDLINE="" nx_dir nxuser_logfile umask0=$(umask);
|
|
open_dbe $$
|
|
attach_db "$sq_settings_fn" ro || {
|
|
echo "$delim 500 Error: NXNODE: Unable to attach db file $sq_settings_fn";
|
|
exit_proc 1;
|
|
}
|
|
set_vars_from_db "" $USER
|
|
|
|
[ -n "$2" ] && delim="NX-$2>"
|
|
echo "$delim 1000 NXNODE - Version $NX_VERSION $NX_LICENSE"
|
|
|
|
if [ "$USER" = "nx" ]; then
|
|
nx_dir="/var/lib/nxserver/home" # ???
|
|
nxuser_logfile="/var/log/nx/nxnode.log"
|
|
else
|
|
nx_dir="$HOME/.nx"
|
|
[ -d $nx_dir ] || { umask 0077; mkdir -p $nx_dir; umask $umask0; }
|
|
nxuser_logfile="$nx_dir/nxnode.log"
|
|
fi
|
|
|
|
attach_db "$nx_dir/usessions.sq3" && {
|
|
init_usessions_db; chmod 0600 "$nx_dir/usessions.sq3" >/dev/null 2>&1; }
|
|
|
|
if ! stringinstring "$1" "--check|--setkey|--agent"; then
|
|
read CMDLINE;
|
|
set_vars_from_ampstr "$CMDLINE" "" "recode"
|
|
if [ -z "$session_id" ]; then
|
|
echo "NX> 500 Error: Fatal - Missing parameter session id." 1>&2
|
|
exit_proc 1
|
|
fi
|
|
declare -g sess_id="$SERVER_NAME-$display-$session_id"
|
|
declare -g NXSESSION_DIRECTORY="$nx_dir/C-$sess_id"
|
|
nxuser_logfile="$nx_dir/nxnode-$session_id.log"
|
|
nxlog "$0 ($$): run nxnode with PARAMS:\"$@\"; CMDLINE='$CMDLINE'"
|
|
else
|
|
nxlog "$0 ($$): run nxnode with \"$@\""
|
|
fi
|
|
|
|
case "$1" in
|
|
--startsession)
|
|
startsession "start"
|
|
;;
|
|
--resumesession)
|
|
startsession "restore"
|
|
;;
|
|
--applicationsession)
|
|
startsession "application"
|
|
;;
|
|
--terminate)
|
|
cmd_node_terminate
|
|
;;
|
|
--suspend)
|
|
cmd_node_suspend
|
|
;;
|
|
--smbmount)
|
|
[ "$(usess_get $session_id "client")" = "winnt" ] && {
|
|
username=$(getparam "$CMDLINE" "username") # reread with no hex recode
|
|
computername=$(getparam "$CMDLINE" "computername")
|
|
username=$(cp_conv "$username"); password=$(cp_conv "$password")
|
|
share=$(cp_conv "$share"); dir=$(cp_conv "$dir")
|
|
computername=$(cp_conv "$computername")
|
|
}
|
|
uservice_start "//127.0.0.1/$share" "" "smb-share" "$share" \
|
|
"$username" "$password" "$dir" "$computername"
|
|
;;
|
|
--addprinter)
|
|
[ "$(usess_get $session_id "client")" = "winnt" ] && {
|
|
username=$(getparam "$CMDLINE" "username") # reread with no hex recode
|
|
computername=$(getparam "$CMDLINE" "computername")
|
|
username=$(cp_conv "$username"); password=$(cp_conv "$password")
|
|
share=$(cp_conv "$share"); computername=$(cp_conv "$computername")
|
|
}
|
|
[ -n "$defaultPrinter" ] && defaultprinter=$defaultPrinter
|
|
opts="model=$model;public=$public;defaultprinter=$defaultprinter"
|
|
[ "$type" = "ipp" ] && share=$printer; svc=$share
|
|
|
|
[ "${svc:0:1}" = "@" ] && svc=${svc:1} # for backward compatibility
|
|
svc=${svc%-nocheck}; svc="$USER""_${svc%%__*}"
|
|
|
|
uservice_start "$svc" "" "$type-prn" "$share"\
|
|
"$username" "$password" "$opts" "$computername"
|
|
;;
|
|
--check)
|
|
echo "NX> 716 finished"
|
|
;;
|
|
--agent)
|
|
echo "NX> 716 Starting NX Agent ..."
|
|
shift
|
|
[ "$SET_LD_LIBRARY_PATH" = "1" ] && export LD_LIBRARY_PATH="$AGENT_LIBRARY_PATH:$LD_LIBRARY_PATH"
|
|
PATH="$PATH:$PATH_BIN" $COMMAND_NXAGENT \
|
|
-name "NX Agent Test - Args: $@" $@
|
|
echo "NX> 716 NX Agent exited with status: $?"
|
|
;;
|
|
--setkey)
|
|
mkdir -m 700 -p $HOME/.ssh
|
|
if ! grep -q "$(cat $NX_ETC_DIR/users.id_dsa.pub)" $HOME/.ssh/$SSH_AUTHORIZED_KEYS 2>/dev/null; then
|
|
cat $NX_ETC_DIR/users.id_dsa.pub >> $HOME/.ssh/$SSH_AUTHORIZED_KEYS
|
|
chmod 600 $HOME/.ssh/$SSH_AUTHORIZED_KEYS
|
|
echo "NX> 716 Public key added to: $HOME/.ssh/$SSH_AUTHORIZED_KEYS"
|
|
else
|
|
echo "NX> 716 Public key is already present in: $HOME/.ssh/$SSH_AUTHORIZED_KEYS"
|
|
fi
|
|
;;
|
|
*)
|
|
echo "NX> 500 Error: Command not found"
|
|
;;
|
|
esac
|
|
|
|
echo "$delim 1001 Bye."
|
|
exit_proc 0
|