#!/bin/bash
# -*- coding: utf-8 -*-
#set -x

# antiX setup SAMBA shares script; part of antiX SAMBA manager.
# Version 0.89
# GPL v.3
# Written 2/2024 by Robin for antiX community
# questions, suggestions and bug reporting please to www.antixforum.com


TEXTDOMAINDIR=/usr/share/locale
TEXTDOMAIN=antiX-samba-manager
export TEXTDOMAINDIR TEXTDOMAIN
source gettext.sh

# declare variables
config='/etc/samba/smb.conf'
SAMBA_DOC='https://wiki.samba.org/index.php/User_Documentation'
CheckUsers="/dev/shm/asm-$$02"
acc_install_lock="/dev/shm/asm-install-lock-$$04"
dlg_fifo="/dev/shm/asm-$$12"
err_urxvt="/dev/shm/asm-$$13"
tmp_config="/dev/shm/asm-$$14"
tmp_shares="/dev/shm/asm-$$15"
tmp_entry="/dev/shm/asm-$$16"
export flag_01="/dev/shm/asm-$$22"
export flag_02="/dev/shm/asm-$$23"
export flag_03="/dev/shm/asm-$$24"
export flag_04="/dev/shm/asm-$$25"
restart=false

#setup fifo buffers
mkfifo "$dlg_fifo"
exec 7<> "$dlg_fifo" 


# do some housekeeping on leaving
function cleanup() {
    rm -f "$CheckUsers" >/dev/null
    rm -f "$dlg_fifo" >/dev/null
    rm -f "$err_urxvt" >/dev/null
    rm -f "$flag_01" >/dev/null
    rm -f "$flag_02" >/dev/null
    rm -f "$flag_03" >/dev/null
    rm -f "$flag_04" >/dev/null
    rm -f "$acc_install_lock" >/dev/null
    rm -f "$tmp_config" >/dev/null
    rm -f "$tmp_shares" >/dev/null
    rm -f "$tmp_entry" >/dev/null
}
trap cleanup EXIT

# make sure user must authenticate
sudo -k

# user info dialog popup, expects positionals:
# width (int), height (int), timeout (int)/buttons (-1),
# header (str), text (str)
function infobox() {
    case $3 in
      '-1') yad --skip-taskbar --on-top \
             --borders=10 \
             --center --width=$1 --height=$2 --fixed \
             --button="$(eval_gettext "Will do so later.")" \
             --window-icon="dialog-warning" \
             --title="! CAUTION !" \
             --text="<big><big><b>$4</b></big>\n\n$5</big>" >/dev/null;;
      *) yad --skip-taskbar --on-top \
             --undecorated --borders=15 \
             --center --width=$1 --height=$2 --fixed \
             --no-buttons --timeout=$3 \
             --window-icon="dialog-warning" \
             --title="! CAUTION !" \
             --text="<big><big><b>$4</b></big>\n\n$5</big>" >/dev/null;;
    esac
}

# Cehck whether prerequisites are present.
# make sure SAMBA server is installed.
prerequisites() {
TEXTDOMAIN=antixcc
    # this convenience function provides a full install dialog and expects all packages meant to be installed as positional parameters and cares for creation of an install dialog to be applied in entries which are in need of some additional helper tools not installed by default on some antiX flavours. Don't forget to set the $prerequesite_icon and $prerequisites_msg variables before calling.
    # if prerequisites is used in an entry please make sure to wait with reload of acc main window until you find this lockfile removed, so changed button functionality is processed properly at reload:

    # prepare textstring for output
    if [ $# -gt 1 ]; then
        for i in $@; do
            text="$text, $i"
        done
        text="$(sed 's/^\(.*\), \(.*\)$/\1 '$(eval_gettext "and")' \2/' <<<"${text:2}")"
    else
        text="$1"
    fi
    yad --center --fixed --undecorated --borders=10 \
        --window-icon=antiX-smb-mgr05 \
        --image=antiX-smb-mgr05 \
        --title="$(eval_gettext "Install \$text")" \
        --text="$prerequisites_msg\n\n""$(eval_gettext "Please install \$text packages first.\nDo you want to install the packages now?")""\n" \
        --button="$(eval_gettext "No thanks")":1 \
        --button="$(eval_gettext "Install")":0
        if [ $? -eq 0 ]; then
        #set -x
            urxvt -e bash -c '{ echo $$ > "'$acc_install_lock'"; success=false; sudo apt-get update; if [ $? = 0 ]; then sudo apt-get install '"$*"'; if [ $? = 0 ]; then echo -e \\\n"'$"Done."'"; success=true; fi; fi; if ! $success; then echo -e \\\n\"'$"Error. Please install $text packages yourself."'\"; fi; rm '$acc_install_lock'; sleep 4; }'
        #set +x
        fi
}

# check for samba server
if ! ls -la /usr/bin | grep samba >/dev/null; then
    prerequisites_icon="antiX-smb-mgr05"
    prerequisites_msg="$(eval_gettext "SAMBA Server not found.")"
    prerequisites samba
    TEXTDOMAIN=antiX-samba-manager # reset textdomain.
    sleep 1
    p='undefined'; [ -f $acc_install_lock ] && p=$(<$acc_install_lock)
    while [ -f $acc_install_lock ]; do sleep .1; if ! ps -p $p >/dev/null 2>&1; then break; fi; done # + catch for user exits prematurely by X in window border
        if ! ls -la /usr/bin | grep samba >/dev/null; then
        infobox 300 160 5 "$(eval_gettext "Install-error:")" "$(eval_gettext "SAMBA not installed.\nCan’t proceed.")"
        exit 1
    fi
fi

# make sure we have root permission for writing to system files later when using
# sudoed commands not visible to user if not running from within console window.
gksu --sudo-mode -- smbstatus >/dev/null
if [ $? != 0 ]; then infobox 300 160 5 "$(eval_gettext "Sudo-Error:")" "$(eval_gettext "No sudo permissions.\nCan’t proceed.")"; exit 1; fi

# check whether config file exists and we are allowed to write to it
if ! gksu --sudo-mode -- [ -w "$config" ]; then
    infobox 300 160 5 "$(eval_gettext "Samba-error:")" "$(eval_gettext "Can’t write to config file\n\t$config\nPlease check your SAMBA installation.")"
fi

# check whether smbd is running
gksu --sudo-mode -- service smbd status
if [ $? -ne 0 ]; then
    # try to fire service up
    gksu --sudo-mode -- service smbd start
    sleep .5
    gksu --sudo-mode -- service smbd status
    if [ $? -ne 0 ]; then
        infobox 300 160 5 "$(eval_gettext "Samba-error:")" "$(eval_gettext "Can’t start smbd service.\nPlease check your SAMBA installation.")"
    fi
fi


# put up functions

function show_current() {
# get currently shared folders
    # build up user shares dialog, run it in endless loop
    while :; do
    # retrieve current samba status, write available user accounts and system accounts into variables
>"$tmp_shares"
    propagated="$(smbclient -g -N -L $HOSTNAME | grep '^Disk' | grep '|' | cut -d'|' -f2 | sed '/^print\$.*\|^IPC\$.*\|^nobody.*/d' | tr '|' '\n')"
    echo "propagated: $propagated"
    for i in $(echo $propagated | sed -n '1~2p'); do testparm -s -l --section-name="${i}" >> "$tmp_shares"; echo "Tip = Double click for Details " >> "$tmp_shares"; done
    sambastatus="$(sed -n 's/^[[:space:]]*\[\(.*\)\][[:space:]]*\|^[[:space:]]*valid users =[[:space:]]*\(..*\)\|^[[:space:]]*comment =[[:space:]]*\(..*\)\|^Tip = \(..*\)/\1\2\3  \4  /p' $tmp_shares)"
    sambastatus_tmp="$(echo $sambastatus | sed -n 's/^[[:space:]]*\(..*\)$/\1/p' | rev | sed -n 's/^[[:space:]]*\(..*\)$/\1/p' | rev)"  # remove trailing and leading blanks; sed is greedy, so rev.
    if [ -z "$sambastatus_tmp" ]; then sambastatus="$(eval_gettext "No user shares.")"; fi
    # setup exported tooltip function for yad
    # function show_entry() {
    cat <<SHOW_ENTRY >"$tmp_entry"
         a="\$(echo \$1 | cut -d' ' -f1 )"
         yad --on-top --center --undecorated \
         --close-on-unfocus --skip-taskbar --no-buttons \
         --width=300 --height=250 --borders=20 \
         --form --scroll \
         --field="\$(testparm -s -l --section-name=\$a | sed -E '\${/^$/d;};/^[[:space:]]*$/d;s/$/\n/;s/^[[:space:]]*(comment|path|read only|valid users|guest ok)[[:blank:]]*=/\t<b>\1:\t<\/b>/;s/^[[:space:]]*(\[..*\]|test)/<big><big><b>\1<\/b><\/big><\/big>/')":lbl
    # }
    # export show_entry # even when exported, function is not present within bash subshell yad provides in dialog fields
    # workaround: write to temp script file
SHOW_ENTRY
    chmod 755 "$tmp_entry"
    dlg_result="$(yad --fixed --center --borders=10 \
        --width=500 --height=250 \
        --title="$(eval_gettext "antiX Samba manager")"" – ""$(eval_gettext "User shares")" \
        --window-icon="antiX-smb-mgr02" \
        --text="$(eval_gettext "Local user shares configured, and accessible from remote:")" \
        --list \
        --print-column=1 --separator="|" \
        --tooltip-column=4 --hide-column=4 \
        --dclick-action="bash -c "\""bash "$tmp_entry" %s"\""" \
        --column="Shares" \
        --column="Description" \
        --column="Accredited" \
        --column="Tip":TIP \
        --button="$(eval_gettext "Show System Shares")"!!"$(eval_gettext "Shows you the current system shares. Those are protected SAMBA defaults.")":2 \
        --button="$(eval_gettext "Add Share")"!!"$(eval_gettext "Lets you create a share of an arbitrary folder and its subfolders of your system for any user or multiple users you define and accredit.")":8 \
        --button="$(eval_gettext "Delete Share")"!!"$(eval_gettext "This purges the highlighted share from your SAMBA config")":4 \
        --button="$(eval_gettext "Back")"!!"$(eval_gettext "Brings you back to antiX Samba mount-manager main window.")":6 <<<"${sambastatus}")"
        x=$?
        ! [ -z "$dlg_result" ] && dlg_result="${dlg_result::-1}"
        [ "$sambastatus" = "$(eval_gettext "No user shares.")" ] && sambastatus=''
        case $x in
            2) sysaccounts;;
            4) remove_entry "$dlg_result"
               if $restart; then
                   restart_samba
               fi;;
            1|6) break ;;
            252) exit 252;;
            8) dlg_new_share;;
        esac
    done
    return 0
}

# function building up the system accounts dialog
function sysaccounts() {
    sambastatus_sys="$(smbclient -g -N -L $HOSTNAME | grep -v '^Printer' | grep '|' | cut -d'|' -f2,3 | sed '/^print\$|..*\|^IPC\$|..*\|^nobody|..*/!d' | tr '|' '\n')"
    while :; do
    yad --fixed --center --borders=10 \
        --width=500 --height=250 \
        --title="$(eval_gettext "antiX Samba manager")"" – ""$(eval_gettext "Default system shares")" \
        --window-icon="antiX-smb-mgr01" \
        --text="$(eval_gettext "Local default system shares configured, and accessible from remote:")" \
        --list \
        --no-selection \
        --print-column=1 --separator="|" \
        --column="$(eval_gettext "Shares")" \
        --column="$(eval_gettext "Description")" \
        --button="$(eval_gettext "Show printers")"!!"$(eval_gettext "Shows you shared printers currently available to account users")":8 \
        --button="$(eval_gettext "Samba Manual")"!!"$(eval_gettext "This opens the most recent SAMBA user and config manual at samba.org in your default web browser (online connection needed, only English language available.)")":6 \
        --button="$(eval_gettext "Edit Config")"!!"$(eval_gettext "This lets you edit your SAMBA config file manually in a text editor to control these system shares. Be carefully, refer to SAMBA manual how to treat them.")":2 \
        --button="$(eval_gettext "Back")"!!"$(eval_gettext "Brings you back to removable user shares.")":4 <<<"$sambastatus_sys" >/dev/null
        case $? in
            2) ([ ! -e "${config}.original" ] && gksu --sudo-mode -- "cp $config ${config}.original"); coproc gksu --sudo-mode -- "geany -i $config";;
            1|4) break;;
            6) xdg-open "$SAMBA_DOC" &;;
            8) while :; do
                   show_printers
                   if [ $? -ne 4 ]; then
                       break
                   else
                      wmctrl -F -c "$(eval_gettext "antiX Samba manager")"" – ""$(eval_gettext "Shared printers")"
                      sleep .2
                   fi
               done;;
            252) exit 252;;
        esac
    done
    return 0
}


function expert_settings() {
    yad --width=200 --height=100 --text-info --wrap --center --button="back" <<<"not implemented yet"
	# --- todo ---
	# enable/disable NetBIOS
	# set Workgroup name
	# set Hostname
	# show current active connections
	# start/stop SAMBA server
}

function smb_user_manager() {
    yad --width=200 --height=100 --text-info --wrap --center --button="back" <<<"not implemented yet"
    # --- todo ---
    # show accredited samba share users
       #gksu --sudo-mode -- pdbedit -L -v
    # add user to samba server config
       #gksu --sudo-mode -- smbpasswd -a <username>
    # remove user from samba server config
       #gksu --sudo-mode -- smbpasswd -x <username>
    # change password for a samba user 
}


function show_printers() {
    while :; do
        if grep '^[[:space:]]*load printers[[:space:]]*=[[:space:]]*no' "$config" >/dev/null; then
            #is_enabled=false
            rm -f "$flag_04" >/dev/null
            button01_txt="$(eval_gettext "Enable")"
            button01_tt="$(eval_gettext "This enables sharing of system printers by SAMBA.")"" ""$(eval_gettext "After print service startup it may take some minutes to sync the Samba server, before the change of shares is displayed.")"
            text01="$(eval_gettext "SAMBA printer sharing service is disabled.")"
            #sambastatus_prn="No printers shared."
        #elif grep "^[[:space:]]*load printers[[:space:]]*=[[:space:]]*yes" "$config" >/dev/null || grep -v "^[[:space:]]*load printers[[:space:]]*=" "$config" >/dev/null; then
        else  # since samba defaults to yes, it is enough to grep for the explicite "= no" here.
            #is_enabled=true
            touch "$flag_04" >/dev/null
            button01_txt="$(eval_gettext "Disable")"
            button01_tt="$(eval_gettext "This disables sharing of system printers by SAMBA.")"" ""$(eval_gettext "After shutdown of print service it may take 5 to 8 minutes to sync the Samba server, before the change of print shares takes effect. This can’t be accelerated by any means, even a full SAMBA restart doesn’t enforce an instantaneous change.")"
            text01="$(eval_gettext "SAMBA printer sharing service is enabled.")"
            #if [ "$(LANG=C rpcclient -U "" -N -c "enumprinters 5" $HOSTNAME)" != "No printers returned." ]; then
            #sambastatus_prn="$(smbclient -g -N -L $HOSTNAME | grep '^Printer' | grep '|' | cut -d'|' -f2,3 | tr '|' '\n')"
            #if [ -z "$sambastatus_prn" ]; then
            #    sambastatus_prn="No printers shared."
            #fi    
        fi
        # is there a workaround for lagging samba server sync? new printers may take up to 5 minutes to be propagated,
        # even when server is stopped completely and restarted. Somewhere must be a cache in need to be flushed.
        # possibly sending a sighup? or possibly send explicitely service smbd stop; sleep 2; service smbd start
        # instead of service smbd restart? Nothing seems to speed up or force an immediate update.
        # For now a cycle read loop as workaround.
        touch "$flag_01" "$flag_02" "$flag_03"  # flag files for loop management from within coprocessed yad window.
        # build up printer shares dialog
        (yad --fixed --center --borders=10 \
            --text="$text01" \
            --width=500 --height=250 \
            --title="$(eval_gettext "antiX Samba manager")"" – ""$(eval_gettext "Shared printers")" \
            --window-icon="antiX-smb-mgr03" \
            --list \
            --cycle-read \
            --no-selection \
            --print-column=1 --separator="|" \
            --column="$(eval_gettext "Shares")" \
            --column="$(eval_gettext "Description")" \
            --button="$(eval_gettext "Force reload")"!!"$(eval_gettext "This enforces a full restart of the SAMBA server, e.g. after you have added or removed a printer in your CUPS printer config. It may take some minutes before changes are propagated by SAMBA and show up.")":6 \
            --button="$button01_txt"!!"$button01_tt":2 \
            --button="$(eval_gettext "Back")"!!"$(eval_gettext "Brings you back to SAMBA system service shares")":4 >/dev/null <&7
        case $? in
            4) rm "$flag_01"
               rm "$flag_02"
               exit 0;;
            2) rm "$flag_01"
               #if $is_enabled; then
               if [ -e "$flag_04" ]; then
                   #is_enabled=false
                   rm -f "$flag_04" >/dev/null  # changed is_enabled status can't be transported back via the variable
                   disable_printers
                   exit 0 # exit coprocess
               else
                   #is_enabled=true
                   touch "$flag_04" >/dev/null
                   enable_printers
                   exit 0
               fi;;
            6) rm "$flag_01"
               restart_samba
               rpcclient -U "" -N -c "enumprinters 5" $HOSTNAME >/dev/null  # forces reload of printers in smbclient for some reason
               exit 0;;
            252) rm "$flag_01"
                 rm "$flag_02"
                 rm "$flag_03"
                 exit 252;;
        esac) &
        # feed changing info from samba server to dialog using fifo buffer
        while [ -e "$flag_01" ]; do
            if [ -e "$flag_04" ]; then
                check_cups_status
                if [ ! -e "$flag_04" ]; then
                  return 4 # we have to reload the window to change buttons and text
                fi
                sambastatus_prn="$(smbclient -g -N -L $HOSTNAME | grep '^Printer' | grep '|' | cut -d'|' -f2,3 | tr '|' '\n')"
                echo -e "\f\n${sambastatus_prn}" >&7
                if [ -z "$sambastatus_prn" ]; then
                    for ((m=0; m<10; m++)); do
                        ! [ -e "$flag_01" ] && break
                        sleep .5
                    done
                else
                    for ((m=0; m<480; m++)); do
                        ! [ -e "$flag_01" ] && break
                        sleep .5   # using sleep 240 instead of looping through short sleep periods prohibits resuming of processing after dialog was closed, until processor's nap has ended.
                    done
                fi
            else
                echo -e "\f\n""$(eval_gettext "No printers shared.")" >&7
                for ((m=0; m<480; m++)); do   # asking smbclient in shorter intervals results in never changing its state. ridiculous!
                    ! [ -e "$flag_01" ] && break # leave inner loop
                    sleep .5
                done
            fi
        done
        ! [ -e "$flag_02" ] && break # leave outer loop
    done
    if ! [ -e "$flag_03" ]; then # leave function either by return or exit
        exit 252
    else
        return 0
    fi
}


function check_cups_status() {
	# check whether cups is up while printers are shared by Samba
    if ! pidof cupsd >/dev/null; then
        yad --skip-taskbar --on-top --undecorated --borders=5 --center --text-info --width=300 --height=200 --button="$(eval_gettext "Disable")"!!"$(eval_gettext "This will disable SAMBA Printer sharing.")":2 --button="$(eval_gettext "Re-Enable")"!!"$(eval_gettext "This will re-enable CUPS printing service.")":4 >/dev/null <<<"$(eval_gettext "CUPS not detected.
Either disable SAMBA Printer
Sharing or re-enable CUPS.
Until Cups is not re-enabled,
all incoming print jobs sent
from remote will pile up in
SAMBA's server internal
print spooler queue.")"
        case $? in
             2) rm -f "$flag_04" >/dev/null
                disable_printers
                return 1;;
             4) touch "$flag_04" >/dev/null
                enable_printers
                return 0;;
        esac
    fi
}


function init_print_entry01() {
	# if [global] section of smb.conf has already a "load printers" entry, activate it
    if grep '^[[:space:]]*[#;]*[[:space:]]*load printers =' "$config" >/dev/null; then
        gksu --sudo-mode -- sed -i 's/^[[:space:]]*[;#]*[[:space:]]*\(load printers =\).*/   \1 yes/' "$config"
    else
        # if [global] section of smb.conf lacks of a printer entry, add the needed lines.
        glob_printers='
   
########## Printers ###########

#
# The following entries control whether and how system printers are
# shared by Samba. 

# This option controls whether local printers are available via Samba.
# valid: yes, no
# If entry is missing or commented out, Samba defaults to yes.
    load printers = yes

# This option controls what type of printer service should be applied.
# valid: BSD, SYSV, CUPS, AIX, HPUX, QNX, LPRNG, SOFTQ, PLP
# Default depends on what was set at compile time; Samba sets additionally
# the variables '"'"'print command'"'"', '"'"'lpq command'"'"', and '"'"'lprm command'"'"' when
# this option is not set, so if setting this manually here, you’ll need
# to take care of these. (Default on antiX: CUPS)
;   printing = CUPS

'
        # find last line of global section and append load printer entry.
        awk -v u="[global]" -v v="$glob_printers" '
            m && $0!=u && $0~"^[[].*[]]" { a[++x]=v; m=0 }
            $0==u { m=1 }
                { a[++x]=$0 }
            END {
            for (k=1; k<=x; k++)
                print a[k]}' "$config" > "$tmp_config" # workaround since tee doesn’t work with gksu in GUI.
            gksu --sudo-mode -- mv "$tmp_config" "$config"            

    fi
    # loops through lines read from config file, copying line by line
    # to array a. If pattern [global] is detected, set flag m, continue
    # until next pattern match [...] is found. Unset flag m, insert new
    # block v to array a and continue.
    # fixme: comment lines of next entry living above entry start are
    # not treated properly; print entry is placed between the premature
    # comments and the actual next entry start.
}


function init_print_entry02() {
    # if printers entry is missing we need to add it.
    if ! grep '[[]printers[]]' "$config" >/dev/null; then
        new_entry='
[printers]
    comment = All Printers
    browseable = no
    path = /var/tmp
    printable = yes
    guest ok = no
    read only = yes
    create mask = 0700
'
        # add entry to config file
        #echo "$new_entry" | gksu --sudo-mode -- tee -a "$config"
        cp "$config" "$tmp_config" # workaround since tee -a doesn’t work with gksu in GUI.
        echo "$new_entry" >> "$tmp_config"
        gksu --sudo-mode -- mv "$tmp_config" "$config"
    fi
}


function enable_printers() {
    # make sure smb.conf has proper entries, set 'load printers = yes'
    init_print_entry01
    init_print_entry02
    # check whether cups service is up
    text="<big><b>""$(eval_gettext "Cups not running.")""</b></big>"
    while :; do
        pidof cupsd >/dev/null
        if [ $? -ne 0 ]; then
            gksu --sudo-mode -- service cups start
            if [ $? -eq 0 ]; then
                yad --skip-taskbar --on-top --undecorated --borders=5 --center --timeout=2 --no-buttons --text-info --width 300 >/dev/null <<<"$(eval_gettext "Cups successfully started.")"
                break
            else
                yad --fixed --center --borders=10 \
                    --width=220 --height=250 \
                    --window-icon="antiX-smb-mgr05" \
                    --title="$(eval_gettext "antiX Samba manager")"" – ""$(eval_gettext "Enable printer share")" \
                    --text="$text""\n\n""$(eval_gettext "Please add CUPS to startup services\nin antiX control centre, section\n»System« → »Startup-services« and\nmake sure cups service is up before\nproceeding.")" \
                    --button="$(eval_gettext "antiXcc")":2 \
                    --button="$(eval_gettext "Retest")":4 \
                    --button="$(eval_gettext "Back")":6 >/dev/null
                case $? in
                    1|2) antixcc.sh &
                       sleep 1
                       (which sysv-rc-conf >/dev/null && gksu --sudo-mode -- rc-conf-wrapper.sh) &
                       (which runit-service-manager.sh >/dev/null && gksu --sudo-mode -- runit-service-manager.sh) &;;
                    4) pidof cupsd >/dev/null
                       if [ $? -ne 0 ]; then
                           text="$(eval_gettext "Cups still not running.\nThis is needed to share printers via SAMBA.")"
                       else
                           yad --skip-taskbar --on-top --undecorated --borders=5 --center --timeout=2 --no-buttons --text-info --width 300 >/dev/null <<<"$(eval_gettext "Cups detected. Proceeding.")"
                           break
                       fi;;
                    6) break;;
                  252) wmctrl -F -c "$(eval_gettext "antiX Samba manager")"" – ""$(eval_gettext "Shared printers")"
                       exit 252;;
                esac
            fi
        else
           restart_samba
           break
        fi
    done
    # check whether samba can access local printers.
    while :; do
        lpstat -h $HOSTNAME -v >/dev/null
        if [ $? -ne 0 ]; then
                text="<big><b>""$(eval_gettext "No Printer in CUPS configured.")""</b></big>"
                yad --fixed --center --borders=10 \
                    --text="$text01" \
                    --width=220 --height=250 \
                    --window-icon="antiX-smb-mgr05" \
                    --title="$(eval_gettext "antiX Samba manager")"" – ""$(eval_gettext "Enable printer share")" \
                    --text="$text""\n\n""$(eval_gettext "You can’t share something what\ndoesn’t exist. Please add at least\none local printer to CUPS services\nin antiX control centre, section\n»Hardware« → »Print settings« and\nmake sure it is available before\proceeding.")" \
                    --button="$(eval_gettext "antiXcc")":2 \
                    --button="$(eval_gettext "Retest")":4 \
                    --button="$(eval_gettext "Back")":6 >/dev/null
               case $? in
                    1|2) antixcc.sh &
                       sleep 1
                       (which sysv-rc-conf >/dev/null && system-config-printer) &
                       (which runit-service-manager.sh >/dev/null && system-config-printer) &;;
                    4) lpstat -h $HOSTNAME -v >/dev/null
                       if [ $? -ne 0 ]; then
                           text="$(eval_gettext "Still no printers configured. This is needed to share printers via SAMBA.")"
                       else
                           yad --skip-taskbar --on-top --undecorated --borders=5 --center --timeout=2 --no-buttons --text-info --width 300 >/dev/null <<<"$(eval_gettext "Printers detected. Proceeding.")"
                           break
                       fi;;
                    6) break;;
                  252) exit 252;;
                esac
        fi
    done
}


function disable_printers() {
    if ! grep '^[[:space:]]*[#;]*[[:space:]]*load printers =' "$config" >/dev/null; then
        # make sure smb.conf has proper entries (sets 'load printers = yes' if not present already)
        init_print_entry01
    fi
    # change 'load printers = no'
    gksu --sudo-mode -- sed -i 's/^[[:space:]]*[;#]*[[:space:]]*\(load printers =\).*/   \1 no/' "$config"
    # no need to remove printers entry if load printers is disabled.
    # reload config 
    restart_samba
}


# Register users to system and samba both as needed.
# to have the native password setup commands, do it in a console window.
cat<<CHECK_CURRENT_USERS >"$CheckUsers"
#!/bin/bash
# -*- coding: utf-8 -*-

TEXTDOMAINDIR=/usr/share/locale
TEXTDOMAIN=antiX-samba-manager
export TEXTDOMAINDIR TEXTDOMAIN
source gettext.sh

err=0
err_smb=false
field3="\$1"
if [ -z "\$field3" ]; then echo "err:asm:CheckUsers=no_user:field3"; exit 1; fi
echo -e "\n"\$"Checking System- and SAMBA accounts for the following users:""\n  \${field3}"

while :; do
    smbstatus >/dev/null 2>&1
    if [ \$? != 0 ]; then
        err_smb=true
        echo \$"No sudo permissions. Retry? [y/n]"
        while :; do
            read -N1 -s -r yn
            case \$yn in
                [\$"y"\$"Y"] ) skip=false; break;;
                [\$"n"\$"N"] ) skip=true; break;;
                   * ) :;;
            esac
        done     
        if \$skip; then
            echo -e "\n!!! "\$"Can’t read current sambastatus due to missing permissions."" !!!\n!!! "\$"No SAMBA accounts have been neither created nor checked.""   !!!"
            sleep 4
            exit 1
        fi
    else
        err_smb=false
        break
    fi
done

#function check_current_users() {
    # get current registered samba users
    ifsbak="\$IFS"; IFS=\$(echo -e "\n\r")
    for i in \$(pdbedit -L); do
        sambausers+=("\${i%%:*}")
    done
    echo -e "\n"\$"Creating accounts if not present already."
    # check whether the shareusernames are already registered
    # if not, ask user to register.
    IFS=', '
    for i in \$field3; do
        if ! [[ "\${sambausers[@]}" =~ "\$i" ]]; then
        # user has no samba account
            let err++   # error counter
            skip=false
            if ! id "\$i" >/dev/null 2>&1; then
            # user has no local account also.
                while :; do
                    skip=false
                    echo -e "\n-----------------------------------------------------------------------\n"\$"Creating System account for  \${i}  (mandatory)""\n"\$"Do you want user \${i} to have a local home directory?""\n"\$"The latter not necessarily needed. [y/n]"
                    read -N1 -s -r yn  # user doesn’t necessarily own a home directory; so ask user what to do.
                    case \$yn in
                        [\$"y"\$"Y"] ) useradd -m "\$i";;  # create local account with homedirectory
                        [\$"n"\$"N"] ) useradd "\$i";;     # create local account
                           * ) :;;
                    esac
                    echo "\$yn"
                    if ! id "\$i" >/dev/null 2>&1; then
                        while :; do
                            echo -e "\n"\$"Setup of System account  \$i  has failed.""\n"\$"This step is mandatory to create a SAMBA account.""\n"\$"Can’t proceed without. Retry? [y/n]"
                            read -N1 -s -r yn
                            case \$yn in
                                [\$"y"\$"Y"] ) skip=false;break;;
                                [\$"n"\$"N"] ) skip=true;break;;
                                   * ) :;;
                            esac
                            echo "\$yn"
                        done
                        if \$skip; then break; fi
                    else
                        break
                    fi
                done
                while :; do
                    echo -e \$"Key in initial password for System account \$i twice, each\ntime followed by the enter key:""\n              *"\$"Better use a strong one""*"
                    passwd "\$i"  # set password for new local account
                    if [ \$? -ne 0 ]; then
                        while :; do
                            echo -e "\n"\$"Password setup of System account \$i has failed. User won’t\nbe able to login."" "\$"This is mandatory to create a SAMBA account\nfor user \$i. Retry [y/n]"
                            read -N1 -s -r yn
                            case \$yn in
                                [\$"y"\$"Y"] ) skip=false;break;;
                                [\$"n"\$"N"] ) skip=true;break;;
                                   * ) :;;
                            esac
                            echo "\$yn"
                        done
                        if \$skip; then
                            echo -e "\n!!! "\$"Error: No system account for user \$i was created"" !!!"
                            echo -e "\n!!! "\$"Error: No SAMBA account for user \$i was created"" !!!"
                            echo -e "\n!!! "\$"User will not be able to access the share.""            !!!"
                            break
                        fi
                    else
                        break
                    fi
                done
            else
                echo -e "\n-----------------------------------------------------------------------\n"\$"User \$i holds already a System account on this machine."
                # Does he have a homefolder also?
                homedir=\$( getent passwd "\$i" | cut -d: -f6 )
                if [ -d "\$homedir" ]; then
                    echo \$"His/her homefolder is \$homedir".
                else
                    echo -e "\n"\$"This is an account without a local homefolder. (A homefolder is not\nnecessarily needed for him/her accessing shared files via SAMBA.)"
                fi
                # we don’t need to know or care for. Samba doesn’t need this just for sharing a folder.
            fi
            if \$skip; then continue; fi
            while :; do
                echo -e "\n"\$"Creating SAMBA account for user \${i}."" "\$"Please key in the new password\ntwice, each time followed by the enter key:""\n              *"\$"Better use a strong one""*"
                smbpasswd -a \$i
                if [ \$? -ne 0 ]; then
                    echo -e "\n"\$"Setup of SAMBA account \$i has failed. Retry? [y/n]"
                    while :; do
                        read -N1 -s -r yn
                        case \$yn in
                            [\$"y"\$"Y"] ) skip=false;break;;
                            [\$"n"\$"N"] ) skip=true;break;;
                               * ) :;;
                        esac
                        echo "\$yn"
                    done     
                    if \$skip; then 
                        echo -e  "\n!!! "\$"Error: SAMBA Account creation for \$i has failed."" !!!\n!!! "\$"No account was created for this user.""                !!!"
                        echo -e "\n!!! "\$"User will not be able to access the share.""            !!!"
                        break
                    fi
                else
                    break
                    let err-- # for this user account everything has been fixed.
                fi
            done
        else
        echo -e "\n-----------------------------------------------------------------------\n"\$"User \$i holds already a SAMBA account on this machine, no account\nsetup needed for him/her."
        fi
    done
    IFS="\$ifsbak"
    echo -e "\n-----------------------------------------------------------------------\n"\$"Done. Press any key to continue after having read the above carefully.""\n"\$"That will close this window."
    read -N1 -s -r yn

    if err_smb || [ $err -ne 0 ]; then
        exit 1
        #return 1
    else
        exit 0
        #return 0
    fi
#}
CHECK_CURRENT_USERS
chmod 755 "$CheckUsers"


# dialog new samba config entry
function dlg_new_share() {
    # get current system users
    sysusers="$(getent passwd | grep -v 'nologin\|sync\|root' | cut -d: -f1)"
    # declare initial values for dialog
    field1="$HOME"    # new shared folder
    field2="$(eval_gettext "MyShare")" # sharename
    field3="$(whoami)"   # allowed user(s)
    field4="FALSE"    # is readonly
    field5="TRUE"     # is browsable
    field6="FALSE"    # guest access
    # display dialog in infinite loop, exited when done.
    while :; do
        # make sure to keep user selection if he returns to dialog window.
        field3n="$(sort -u <<<"$sysusers$(echo -e \\n$field3)")"
        field3n="$(sed "s/\($field3\)/^\1/" <<<"$field3n" | tr '\n' '!')"
        field3n="${field3n::-1}"
        # build "new entry" dialog
        dlg_result="$(yad --borders=10 --center \
            --title="$(eval_gettext "antiX Samba manager")"" – ""$(eval_gettext "New Share")" \
            --window-icon="antiX-smb-mgr05" \
            --text="\n<b>""$(eval_gettext "Create new SAMBA share:")""</b>\n" \
            --form \
            --field="$(eval_gettext "Directory to share:")":DIR "$field1" \
            --field="$(eval_gettext "Sharename:")" "$field2" \
            --field="$(eval_gettext "Users:")":CBE "$field3n" \
            --field=" ""$(eval_gettext "Readonly")":CHK "$field4" \
            --field=" ""$(eval_gettext "Browsable")":CHK "$field5" \
            --field=" ""$(eval_gettext "Guest access")":CHK "$field6" \
            --button="$(eval_gettext "Abort")":2 \
            --button="$(eval_gettext "Help")":4 \
            --button="$(eval_gettext "Create")":6)"
        exitstatus=$?
        # extract fields from yad output string
        for i in 1 2 3 4 5 6; do
            declare field${i}="$(awk -v i=$i 'BEGIN { FS = "|" }; { print $i }' <<<"${dlg_result}")"
        done
        # analyse exit code
        case $exitstatus in
            1|2) break;;
            4) help_create_new;;
            6) if evaluate_data; then
                   if create_new_share; then
                       echo 0 > "$err_urxvt" # reset urxvt error transport file
                       gksu --sudo-mode -- urxvt -title "$(eval_gettext "antiX Samba manager")"" – ""$(eval_gettext "User accreditation")" -n "antiX-smb-mgr05" -e bash -c 'bash "'$CheckUsers'" "'"$field3"'"; echo $? > '"$err_urxvt"''
                       cat "$err_urxvt"
                       [ $(<$err_urxvt) -ne 0 ] && infobox 300 300 '-1' "$(eval_gettext "Account- or Password setup has failed.")" "$(eval_gettext "At least for one user no system account was set\nup or no password was assigned in either System \nor Samba account. Please take care yourself for\ninitial password assignment for the user(s)\ndecried in the former window.")""\n\n→ ""$(eval_gettext "System account creation terminal command:\n\tsudo useradd <i>username</i>")""\n\n→ ""$(eval_gettext "System user password terminal command:\n\tsudo passwd <i>username</i>")""\n\n  ""$(eval_gettext "Or head for antiX control center,\n  section maintenance → user management.")""\n\n→ ""$(eval_gettext "SAMBA user password terminal command:\n\tsudo smbpasswd -a <i>username</i>")""\n"
                       restart_samba
                       manage_ufw
                       check_dir_permissions
                       break
                   else
                       infobox 300 200 6 "$(eval_gettext "Samba config error.")" "$(eval_gettext "Please check your SAMBA installation\nand make sure the file\n\t\$config\nexists and is writable for root. If edited\nmanually, please recheck with a virgin\nsmb.conf file.")"
                   fi
               fi;;
            252) exit 252
        esac
    done
}


function restart_samba() {
    #gksu --sudo-mode -- smbcontrol all reload-config  # supposed to work following samba manual,
        # but wasn’t reliable in some testings: printer services still propagated.
        # hence full server restart instead.

    # Restart samba service with changed config entry.
    gksu --sudo-mode -- service smbd restart
    restart=false
}


function manage_ufw() {
# switch rule for samba to "allow" in ufw in case it is installed and active.
if which ufw; then
    gksu --sudo-mode -- bash -c 'LANG=C ufw status' | grep "inactive"
    ufw="${PIPESTATUS[@]}"
    if [ $((${ufw%% *})) -eq 0 ]; then
        if ! [ $((${ufw##* })) -eq 0 ]; then
            gksu --sudo-mode -- ufw allow samba
            infobox 300 200 8 "$(eval_gettext "UFW firewall active.")" "$(eval_gettext "Firewall detected. Switched\n\t<b>›allow samba‹</b> in ufw rules\nto enable SAMBA shares access.")"
            echo "$(eval_gettext "Firewall detected. Switched 'allow samba' in ufw rules")"
        else
            infobox 300 200 8 "$(eval_gettext "UFW firewall detected.")" "$(eval_gettext "Your firewall seems to be inactive.\nConsider to enable it and then please\nadd <b>›allow samba‹</b> to your ufw rules on\nyour own, to enable SAMBA shares access\nwith active firewall.")"
            echo "$(eval_gettext "Firewall detected but inactive. No change to ufw rules")"
        fi
    else
        infobox 300 200 8 "$(eval_gettext "Lacking of sudo permissions.")" "$(eval_gettext "Can’t detect Firewall.\nCan’t switch <b>›allow samba‹</b> in ufw rules to\nenable SAMBA shares access. Please take care\nfor this on your own, otherwise your share will\nnot be accessible from within your LAN if you\nhave a firewall running.")"
        echo "$(eval_gettext "No sudo permissions. Can’t add ufw rule for samba.")"
    fi
else
    infobox 300 250 8 "$(eval_gettext "UFW firewall check")" "$(eval_gettext "No firewall detected. If you run\na firewall which wasn’t detected,\nplease make sure to add a rule to\n<b>allow samba server access from\nremote</b>. Otherwise you will not\nbe able to connect a share.")"
    echo "$(eval_gettext "No firewall detected. If you run a firewall which wasn’t detected, please make sure to add a rule to allow samba server access from remote.")"  # todo: check for some other firewalls
fi
}


function check_dir_permissions() {
  retry=false
  while :; do
    retry_ok=true
    if ! $retry; then
        msg="<big><b><big>""$(eval_gettext "SAMBA share was created successfully.")""</big>\n\n""$(eval_gettext "To be able to connect to it, you still need to change some folder permissions in your file system, which have been detected not to match.")""</b>"
    else
        msg="<big><b>""$(eval_gettext "File permissions on local file system have been rechecked for remote SAMBA access to folder \$field1 by user(s) \$field3.")""</b>"
    fi
    declare -a users  # users who need access, indexed.
    declare -A user   # group memberships of user, assoc., key=user.
    declare -A owner  # ownership of folders, asoc., key=folder.
    declare -A group  # group of folders, asoc., key=folder.
    ifsbak="$IFS"; IFS=', '
    for i in $field3; do # build arrays user and users
        users+=("$i")
        k="$(groups $i)"
        user["${i}"]="${k#*: }"
    done
    IFS="$ifsbak"
    dir="$field1"
    # shared folder itself:
        perms="$(stat --printf \0%a $dir)" # look up permissions
        perm_own=$((${perms:1:1}))
        perm_grp=$((${perms:2:1}))
        perm_oth=$((${perms:3:1}))
        ext_bit=$((${perms:0:1}))
        owner["${dir}"]="$(stat -c %U $dir)" # look up owner
        group["${dir}"]="$(stat -c %G $dir)" # look up group
        for i in "${users[@]}"; do
            folder_ok=false
            # check owner
            if [ "${owner["${dir}"]}" == "$i" ] ; then  # user is owner set for this folder
                if [ "$field4" == "FALSE" ]; then # user needs write, read and exec access.
                    if [ "$perm_own" -eq 7 ]; then folder_ok=true; fi # user can access folder by ownership if write, read and exec access is set.
                else  # user needs read and exec access at least
                    case $perm_own in # user can access folder by group policy if at least read and exec access is set.
                        7|5) folder_ok=true;;
                    esac
                fi
            fi
            # check group
            if [[ "${user["${i}"]}" =~ "${group["${dir}"]}" ]]; then   # user is member of group set for this folder
                if [ "$field4" == "FALSE" ]; then # user needs write, read and exec access.
                    if [ "$perm_grp" -eq 7 ]; then folder_ok=true; fi # user can access folder by group policy if write, read and exec access is set.
                else    # user needs read and exec access at least
                    case $perm_grp in # user can access folder by group policy if at least read and exec access is set.
                        7|5) folder_ok=true;;
                    esac
                fi
            fi
            # check other
            # user is neither owner nor member of group set for this folder
                if [ "$field4" == "FALSE" ]; then # user needs write, read and exec access
                    if [ "$perm_oth" -eq 7 ]; then folder_ok=true; fi # user can access folder by policy for others if write, read and exec access is set.
                else  # user needs read and exec access at least
                    case $perm_oth in # user can access folder by policy for others if at least read and exec access is set.
                       7|5) folder_ok=true;;
                    esac
                fi
            # don’t care for extended permission bits for now
        # generate messages for shared folder
        if ! $folder_ok; then
            if [ "$field4" == "FALSE" ]; then # user needs write, read  and exec access
                msg="$msg""\n\n""$(eval_gettext "Folder \$dir was shared with write access.")"" <b>""$(eval_gettext "Currently access permissions for user \$i in your file system don’t match. Please make sure user \$i has write, read and exec access to folder \$dir in local file system.")""</b> "$"This can be achieved e.g. either by changing the ownership of the folder (if only a single user needs access to it), or by adding the user to group ›${group[${dir}]}‹ in antiX control centre (section maintenance, entry user management, tab group membership, choose user from pulldown), or by changing the group of the folder to a group user $i is (or all users who need access are) member of, in antiX zzzFM file manager (Context menu of folder, properties → permissions; currently user $i is member of group(s): ${user[${i}]})."" ""$(eval_gettext "Or you may allow everybody (others) full access to the folder itself, if that suits.")"" ""$(eval_gettext "In any case make sure that the folder permissions for either owner, group or others (depending on your former choice) are set to allow write, read and execute access (7 = rwx).")"" ""$(eval_gettext "Same goes for its subfolders if you want user(s) being able to access them from remote.")"" ""$(eval_gettext "User \$i needs at least write and read access (6 = rw-) for the files living in it, either via permission for ownership, group or others.")"" ""$(eval_gettext "You also may further restrict (also remote) access to individual files or subfolders within the shared folder for him/her or any individual users by setting the permissions of files and folders accordingly.")"
            else # user needs read and exec access to folder
                msg="$msg""\n\n""$(eval_gettext "Folder \$dir was shared read-only.")"" <b>""$(eval_gettext "Currently access permissions for user \$i in your file system don’t match. Please make sure user \$i has read and exec access to folder \$dir in local file system.")""</b> "$"This can be achieved e.g. either by changing the ownership of the folder (if only a single user needs access to it), or by adding the user to group ›${group[${dir}]}‹ in antiX control centre (section maintenance, entry user management, tab group membership, choose user from pulldown), or by changing the group of the folder to a group user $i is (or all users who need access are) member of, in antiX zzzFM file manager (Context menu of folder, properties → permissions; currently user $i is member of group(s): ${user[${i}]})."" ""$(eval_gettext "Or you may allow everybody (others) read and execute access to the folder itself, if that suits.")"" ""$(eval_gettext "In any case make sure that the folder permissions of the folder \$dir itself for either owner, group or others (depending on your former choice) are set to allow read and execute access (5 = r-x).")"" ""$(eval_gettext "Same goes for its subfolders if you want user(s) being able to access them from remote.")"" ""$(eval_gettext "User \$i needs at least read access (4 = r--) for the files living in it, either via permission for ownership, group or others.")"" ""$(eval_gettext "You also may further restrict (also remote) access to individual files or subfolders within the shared folder for him/her or any individual users by setting the permissions of files and folders accordingly.")"
            fi
            retry_ok=false
        fi
        done
    # parent folders:
    dir="${dir%/*}"
    while [ ! -z "$dir" ]; do  # loop through parents
        perms="$(stat --printf \0%a $dir)" # look up permissions
        perm_own=$((${perms:1:1}))
        perm_grp=$((${perms:2:1}))
        perm_oth=$((${perms:3:1}))
        ext_bit=$((${perms:0:1}))
        owner["${dir}"]="$(stat -c %U $dir)" # look up owner
        group["${dir}"]="$(stat -c %G $dir)" # look up group
        is_system=false
        is_owner=false
        is_group=false
        for i in "${users[@]}"; do
            folder_ok=false
            # check owner
            if [ "${owner["${dir}"]}" == "$i" ]; then  # user is owner
                is_owner=true
                case $perm_own in  # owner needs to traverse, at least exec must be set.
                    1|3|5|7) folder_ok=true;;
                esac
            fi
            # check group
            if [[ "${user["${i}"]}" =~ "${group["${dir}"]}" ]]; then   # user is member of group set for this folder
                is_group=true
                case $perm_grp in   # user can traverse by group policy, at least exec must be set.
                   1|3|5|7) folder_ok=true;;
                esac
            fi
            # check other
            case $perm_oth in   # user can traverse by policy for others, at least exec must be set.
               1|3|5|7) folder_ok=true;;
            esac
            # don’t care for extended permission bits for now
        done
   # todo: check agains /media/<user> folders of all users of system
        case $dir in  # check whether folder is a system folder or a base mount folder
           '/media'| "/media/$(whoami)" |'/mnt') is_system=true;;
                         *) if [[ "${target}" = '/' ]]; then
                                is_system=true
                            else
                                if $(case "$(echo $target | awk -F/ '{print FS $2}')" in ('/media')false;;('/mnt')false;; ('/home')false;; esac); then
                                is_system=true
                                fi  # case returns inverted logic only, so false exit state means true!
                            fi;;
        esac
        # generate messages for parent folders: user can’t/traverse (exec)
        if ! $folder_ok; then
            msg="$msg""\n\n<b>""$(eval_gettext "For using the SAMBA share from remote, \$i must be able to <i>traverse</i> (not read or write necessarily) the folder \$dir locally. Currently she/he can’t.")""</b>"
            if $is_owner; then
                msg="$msg""\n""$(eval_gettext "Since user \$i is owner of the folder \$dir, traversability can be achieved for him by setting folder's execute permission flag x (7,5,3 or 1) for him. You can do this e.g. in antiX zzzFM file manager via context menu of this folder, properties → permissions, make sure exec is checked for owner.")"
            fi
            if $is_group; then
                if $is_owner; then
                    msg="$msg""\n"$"User is also member of the group »${group[${dir}]}« this folder belongs to, so you may alternatively or additionally set the exec permission flag x (7,5,3 or 1) for the group also, depending on your needs. For this make sure exec is checked for group."
                else
                    msg="$msg""\n"$"Since user $i is member of the group »${group[${dir}]}« the folder $dir belongs to, this can be achieved by setting its execute permission flag x (7,5,3 or 1) for the group. You can do this in antiX zzzFM file manager via context menu of this folder, properties → permissions, make sure exec is checked for group."
                fi
            fi 
            if ! ($is_owner || $is_group); then
                msg="$msg""\n"$"This can be achieved either by taking over ownership (if that suits), or by adding the user to the group »${group[${dir}]}« this folder belongs to (this can be done e.g. in in antiX control centre {section maintenance, entry user management, tab group membership, choose user from pulldown}), or by changing the group the folder belongs to to a group user $i is member of (if that suits. You can do this e.g. in antiX zzzFM file manager context menu of the folder, properties → permissions), or by allowing everybody (others) to traverse the folder; in all cases you’ll have to set the exec flag to the folder for either owner, group or others, depending on your former choice."
            fi            
            if $is_system; then
                msg="$msg""\n\n""$(eval_gettext "The directory \$dir is a system folder.")""\n<span foreground='red'>""$(eval_gettext "Be carefully when adding permissions for others to system folders or taking over ownership! Think twice whether this is what you actually want to do. Consider side effects.")""</span>"
            fi
            retry_ok=false
        fi
        dir="${dir%/*}"
    done
    singlebutton=false
    if $retry; then
        if $retry_ok; then
            msg="$msg""\n\n""$(eval_gettext "File system permissions set up properly for remote access of the new share [\${field2}] by user(s) \${field3}.")"
            dlg_title="$(eval_gettext "antiX Samba manager")"" – ""$(eval_gettext "Set up shares")"
            button_txt="$(eval_gettext "OK")"
            button_tt=""
            singlebutton=true
        else
            dlg_title="$(eval_gettext "Still missing some needed file system permissions.")"
            button1_txt="$(eval_gettext "Retest")"
            button1_tt="$(eval_gettext "After having fixed the above issues you might want to recheck possibly whether everything matches now.")"
            button2_txt="$(eval_gettext "Will do so.")"
            button2_tt="$(eval_gettext "Clicking this means you have understood how to set up properly the permissions for the shared folder and his parents in your file system. You won’t be able to connect the share if local permissions are not set accordingly.")"
        fi
    else
        if $retry_ok; then
            break  # in good old unix manner don’t bother user with needless info if everything is fine already.
        else
            dlg_title="$(eval_gettext "Needed file system permissions missing.")"   
            button1_txt="$(eval_gettext "Retest")"
            button1_tt="$(eval_gettext "After having fixed the above issues you might want to recheck possibly whether everything matches now.")"
            button2_txt="$(eval_gettext "Will do so.")"
            button2_tt="$(eval_gettext "Clicking this means you have understood how to set up properly the permissions for the shared folder and his parents in your file system. You won’t be able to connect the share if local permissions are not set accordingly.")"
        fi
    fi
    # display mesage dialog, two forms.
    # dialog form 1: list errors and provide buttons to resolve them
    if ! $singlebutton; then
        yad --borders=10 --center --width=550 --height=600 \
        --window-icon="dialog-warning" --title="$dlg_title" \
        --form --scroll \
        --field="$msg""</big>":lbl \
        --button="$(eval_gettext "zzzFM")"!!"$(eval_gettext "This opens antiX zzzFM file manager with parent folder of \${field1}, right click the folder and select »Properties«, from second level select »Permissions«")":6 \
        --button="$(eval_gettext "antiXcc")"!!"$(eval_gettext "This opens antiX Control Centre, head to section »Maintenance«, click »Manage Users«, select tab »Users and Groups«, select user(s) from pulldown and add them to the groups as needed. Also you may create completely new (userlevel-)groups for individual share user clusters in tab »Add/Remove Groups« beforehand, if that suits.")":8 \
        --button="$button1_txt"!!"$button1_tt":2 \
        --button="$button2_txt"!!"$button2_tt":4 >/dev/null
        x=$?
    else
        # dialog form 2: retest was error free. single OK button is enough here.
        yad --borders=10 --center --width=550 --height=600 \
        --window-icon="dialog-warning" --title="$dlg_title" \
        --form --scroll \
        --field="$msg""</big>":lbl \
        --button="$button_txt":4 >/dev/null
        x=$?
    fi
    case $x in
        2) retry=true;;
        4|252) break;;
        6) zzzfm -w "$field1" &;;
        8) antixcc.sh &
           sleep 1
           gksu --sudo-mode -- antix-user &;;
    esac
    unset users
    unset user
    unset owner
    unset group
    unset others
  done
  return 0
}


# display help on creating new share
function help_create_new() {
    yad --borders=10 --center --width=550 --height=600 \
        --window-icon='face-surprise' --title="$(eval_gettext "Program Help")" \
        --form --scroll \
        --field="$txt_help_create_new":lbl \
        --button="$(eval_gettext "Back")":1 >/dev/null
}


# check user input data for integrity and validity
function evaluate_data() {
    #check whether target folder exists and is not relative.
    if [ "${field1::1}" == '.' ]; then
        infobox 200 160 3 "$(eval_gettext "Path Error:")" "$(eval_gettext "Folder path must\nnot be relative.")"
        return 1
    elif ! [ -e "$field1" ]; then
        echo "$(eval_gettext "creating \${field1} for processing")"
        mkdir -p "$field1"
        if [ $? -ne 0 ]; then
            infobox 300 260 10 "$(eval_gettext "Insufficient permissions:")" "$(eval_gettext "Can’t create folder\n\n\${field1}\n\nin your file system.")""\n""$(eval_gettext "You need write and execute access in\nits direct parent folder and execute\naccess for all its parents up to root\ndirectory / to proceed.")"
            return 1
        fi
    else
        if ! [ -d "$field1" ]; then
        infobox 250 200 3 "$(eval_gettext "File type error:")" "$(eval_gettext "\${field1}\n\nnot a directory.")"
        return 1
        fi
    fi
    #check whether the requested share name is a reserved samba system share.
    case "$field2" in
        'homes'|'nobody'|'print$'|'IPC$') \
              infobox 300 180 5 "$(eval_gettext "Samba error:")" "$(eval_gettext "\t»\${field2}«\n\nis a default Samba system share!\nYou can’t use this share name.")"
              return 1;;
    esac
    # check whether sharename already exists in the config.
    if grep '^\['"$field2"'\]' "$config" >/dev/null; then
        content="$(testparm -s -l --section-name="$field2" | grep -v "^[[]"$field2"[]]")"
        yad --on-top --center --borders=10 \
        --width=270 --height=300 --fixed \
        --title="! CAUTION !" \
        --window-icon="dialog-warning" \
        --text="<big><big><b>""$(eval_gettext "Share name error:")""</b></big>\n\n""$(eval_gettext "The share »\${field2}« exists already\nin your SAMBA configuration:")""</big>\n$content\n\n<big>""$(eval_gettext "Do you want to replace it?")""</big>" \
        --button="$(eval_gettext "Back")"!!"$(eval_gettext "This will take you back to the settings menu so you may change the sharename.")":2 \
        --button="$(eval_gettext "Replace")"!!"$(eval_gettext "This will overwrite the existing entry.")":4 >/dev/null
        case $? in
          1|2|252) return 1;;
          4) remove_entry "$field2"
             restart=true;;
        esac
    fi
    echo "$(eval_gettext "using \${field1} for processing")"
    # check whether the requested user name is a reserved system account.
    a=$(($(grep -E '^UID_MIN' /etc/login.defs | awk '{print $2}')))
    b=$(($(grep -E '^UID_MAX' /etc/login.defs | awk '{print $2}')))
    re='[^:]+:[^:]+:([^:]+)'
    declare -a sys
    declare -a usr
    declare -a fail
    declare -a exist
    while IFS= read c; do
        [[ $c =~ $re ]] || continue; (( ${BASH_REMATCH[1]} < $a || ${BASH_REMATCH[1]} > $b )) && \
        sys+=("$(awk 'BEGIN { FS = ":" } ;{print $1}'<<<"$c")")
    done <<< $(getent passwd)
    while IFS= read c; do
        [[ $c =~ $re ]] || continue; (( ${BASH_REMATCH[1]} >= $a && ${BASH_REMATCH[1]} <= $b )) && \
        usr+=("$(awk 'BEGIN { FS = ":" } ;{print $1}'<<<"$c")")
    done <<< $(getent passwd)
    for i in $field3; do # check user names one by one whether this request matches a system account or an existing username
        if [[ "${sys[@]}" =~ "$i" ]]; then
            fail+=("$i")
        elif [[ "${usr[@]}" =~ "$i" ]]; then
            exist+=("$i")
        fi
    done
    # printout results
    if [ "${#fail[@]}" -ne 0 ]; then
        infobox 300 200 6 "$(eval_gettext "Can’t register the accounts:")" "\t$(echo -e ${fail[@]})\n\n""$(eval_gettext "These are system accounts.\nPlease enter other names.")"
        return 1
    fi
    if [ "${#exist[@]}" -ne 0 ]; then
        echo $"The accounts(s) ${exist[@]} are registered already. Setting up the the SAMBA shares for them."
    fi
    return 0 # if we've made it hither, everything is ok with the data.
}


function remove_entry() {
# remove entry from config file; expects name in first positional
    u="$(echo $1 | sed -n 's/^[[:space:]]*\(..*\)$/\1/p' | rev | sed -n 's/^[[:space:]]*\(..*\)$/\1/p' | rev)"  # remove trailing and leading blanks; sed is greedy, so rev.
    if grep "^\[$u\]" "$config" >/dev/null; then
        echo $"removing entry [$u] from smb.conf"
        awk -v u="[$u]" '
        m && $0!=u && $0!~"[[].*[]]" { b[++y]=$0; next }
        m && $0!=u && $0~"[[].*[]]" {
            w=z=y;
            while (b[y]~"^[#].*") {
                c[z++]=b[y--] };
	        while (z>=w) {
                a[++x]=c[z--] } ;  m = 0 }
        $0==u { m=1; next }
            { a[++x]=$0 }                          
        END {                                            
        for (k=1; k<=x; k++)
            print a[k]}' "$config" > "$tmp_config"  # workaround since tee doesn’t work with gksu in GUI.
        gksu --sudo-mode -- mv "$tmp_config" "$config"
        restart=true
    fi
# can’t comment lines, awk doesn’t like that. But...
# it works that way: reads file line by line, check lines and write them
# to array a. If search entry start u is found, skip the line, set flag m,
# proceed. While m is set, skip lines for a but write them into array b.
# If a next entry start u is found, transfer last lines starting with #
# from array b to array a (since they presumably belong as comments to the
# next entry), fix sort order (reverse), unset m, and continue with writing
# lines to a. Finally print out array a back to file.
# Known issue: blank line preceeding the removed entry isn’t removed for now.
}


function create_new_share() {
    # translate field entries as needed
    folder="${field1##*/}"
    if ${field4,,}; then rdonly=yes; else rdonly=no; fi  # read only
    if ${field5,,}; then brwsbl=yes; else brwsbl=no; fi  # browsable
    if ${field6,,}; then gastok=yes; else gastok=no; fi  # browsable
    # create entry
    new_entry='
['"$field2"']
    comment = '"$folder"' '$(eval_gettext "on")' '"$HOSTNAME"'
    path = '"$field1"'
    read only = '"$rdonly"'
    browsable = '"$brwsbl"'
    valid users = '"$field3"'
    guest ok =  '"$gastok"'
'
    # add entry to config file
    # echo "$new_entry" | gksu --sudo-mode -- tee -a "$config"  # fails with gksu in gui, while works with sudo on console.
    cp "$config" "$tmp_config" # workaround since tee -a doesn’t work with gksu in GUI.
    echo "$new_entry" >> "$tmp_config"
    gksu --sudo-mode -- mv "$tmp_config" "$config"
    return $?
}

# prepare program help text in a variable
txt_help_create_new=$(cat<<HELPTEXT
<b>How to create a new share</b>

<b>Directory to share</b>

   Select from the pulldown »Directory to share« the folder you want to
   have available for other PCs in your Network. You must have at least
   read access to the folder. Be carefully with sharing the root folder
   or any other system folders.

<u>Naming Fields</u>

   For the naming fields below prefer using ASCII characters. This gua-
   rantees interoperability with computers not runing Linux.

   - Enter the name you want to show up your share with on other computers
     into the field <b>Sharename</b>. The sharename must NOT contain the
     following characters: " ／ ＼ : ; | ＜ ＞ , ? * =

<u>Workgroup:</u>
   To change the workgroup, please edit the samba config file manually.

## not implemented yet ##
#   - Enter your Windows <b>Workgroup</b> name used in your network for
#     the  workgroup or NT-domain you are member of and your SAMBA share
#     will be part of. This MUST not exceed 15 characters.
#     You should use UPPER CASE letters. You should NOT use any special
#     characters. This might break compatibility with some Windows versions.
#     The following are strictly PROHIBITED: ／ ＼ * , . " @ : ? ＜ ＞ |
#     Make sure the workgroup name is not used for any other PC in your
#     network. Make sure to have the hostname of your PC set unique in
#     your network.
## not implemented yet ##

   For detailed information about naming conventions in Windows networks
   please see https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/naming-conventions-for-computer-domain-site-ou

<u>Users:</u>
   Enter one or more users you want to grant access to the selected
   folder. The names must be separated by a comma and a single blank,
   and must NOT contain blanks itself. Avoid using accented characters,
   since Microsoft has a problem with them, users can’t login.
   To get access, the shared folder and files to be accessed must be set
   either to alow "others" read or write access, or the users entered here
   must have an account on the system, and have read or write acess to
   the folder and the content.
   - The users will be created locally on the system, if not present. You
     may decide whether they get a home directory or not. A home directory
     is not necessarily needed to access the shared folder and the files
     in it. You need to set an initial local user password for them. Key
     in the local password for the new user twice when asked.
   - The usernames will be registered in the SAMBA user database, and you
     need to create the initial credentials for them, if not already pre-
     sent in the SAMBA database. In the upcoming console window key in
     the password twice. Users not registered this way won’t get access
     via SAMBA even when they have a system login account already on the
     very PC.
   If your session takes more time than the sudo timeout on your system
   is set, you will be asked for giving your own sudo credentials amidst
   the setup process again. Don’t mix up your sudo credentials with the
   credentials expected by the account creation routine. 
   ! Do not give a user the same name as a printer. Otherwise, users end
   up connecting to a disk share when they might have expected to be
   connected to a printer share actually ! (Printer names are automati-
   cally retrieved by SAMBA from the local CUPS setup)

<u>Checkboxes:</u>

   - <b>Readonly</b> Tick this checkbox to allow read-only access for this
     share only. If unchecked, users will have read and write access.
   
   - <b>Browsable</b> Tick this checkbox to have the directory showing
     up in Network neighbourhood in some file managers.
     
   - <b>Guest access</b>Tick this checkbox to allow guest users access to
     this share. If checked, guest users will not need to enter a password,
     the share and all its content can be accessed by everybody.


<u>Examples</u>

   Directory to share:\t'/home/demo/My personal shared folder'
   Sharename:         \t'MyPersonalShare'
   Users:             \t'Marcelo, Svea, Ododi'
   Readonly:          \t□
   Browsable:         \t✅
   Guest access:      \t□

   Directory to share:\t'/media/cd-rom'
   Sharename:         \t'CD-ROM-drive'
   Users:             \t
   Readonly:          \t✅
   Browsable:         \t✅
   Guest access:      \t✅


Even when SAMBA is the way to share folders with other OS like Apple/Mac
or Windows, you can use it for sharing folders with other Linux systems
as well. There are some restrictions and drawbacks in this case, filenames
might be shred to MS-DOS 8+3 style on transport. Use NFS shares instead
to avoid this.

<u>Warning:</u>
Do not share NFS mounts with Samba!
Sharing NFS mounts with SAMBA may result in data loss, since it is not
supported. Install SAMBA directly on the PC serving the files instead.

<u>Hint on file- and foldernames on your Linux filesystems when sharing
them to Windows clients:</u>
When files or folders are transported to Windows, you might notice SAMBA
changes names if they don’t match the limitations of Windows systems.
e.g. names containing double points or backslashes can’t be handled by
Windows, so these will be mangled on transport.

<u>Print shares</u>


SAMBA by default automatically shares all local printers. To disable this
behaviour, click the »disable« button in printer menu (→ Show System
shares → Show Printers)
If CUPS goes down after SAMBA has made its propagation of shared printers,
it will not remove the shared printer, but queue all incoming remote
print jobs instead until CUPS is up again.


HELPTEXT
)

# References:
# https://www.samba.org/samba/docs/current/man-html/samba.7.html
# https://www.samba.org/samba/docs/current/man-html/smb.conf.5.html
# https://techcommunity.microsoft.com/t5/windows-11/smb-access-denied-for-users-with-accented-characters/m-p/3641227


# Main (script starts here)

show_current
#expert_settings
#smb_user_manager


exec 7>&-

#set +x
exit 0

