+(/usr/local/bin/automount.sh:9): ExpectDebug='log_user 1' #security add-internet-password \ # -a ACCOUNT \ # -l LABEL (same as SERVER) \ # -D DESCRIPTION (eg. Networkpassword) \ # -j COMMENT (${SCRIPTNAME}) \ # -r PROTOCOL ("afp "/"cifs"/"ftp "/"http"/"htps"/"smb ") \ # -s SERVER \ # -w PASSWORD \ # -U \ # -T /usr/bin/security \ # -T /System/Library/Extensions/webdav_fs.kext/Contents/Resources/webdavfs_agent \ # -T /System/Library/CoreServices/NetAuthAgent.app/Contents/MacOS/NetAuthSysAgent \ # -T /System/Library/CoreServices/NetAuthAgent.app \ # -T group://NetAuth \ # ${LOGINHOME}/Library/Keychains/login.keychain #Server="SERVER"; Label="${Server}"; Description="DESCRIPTION"; Protocol="PROTOCOL"; Account="$(id -p | awk '/^login/ { print $2; exit } /^uid/ { print $2 }')"; UserHomeDirectory="$(dscl . read /Users/${Account} NFSHomeDirectory | cut -d' ' -f2-)"; security add-internet-password -a "${Account}" -l "${Label}" -D "${Description:-Netzwerkpasswort}" -j "automount" -r "$(printf "%-4s" ${Protocol})" -s "${Server}" -w "$(read -p "Password: " -s && echo "${REPLY}")" -U -T /usr/bin/security -T /System/Library/CoreServices/NetAuthAgent.app/Contents/MacOS/NetAuthSysAgent -T /System/Library/CoreServices/NetAuthAgent.app -T group://NetAuth ${UserHomeDirectory}/Library/Keychains/login.keychain # when error "User interaction is not allowed." occurs, unlock keychain # RC=36 (security error 36 -> Error: 0x00000024 36 CSSM_ERRCODE_OBJECT_ACL_REQUIRED) #security unlock-keychain -p "LOGINNAME_PASSWORD" ${LOGINHOME}/Library/Keychains/login.keychain #/usr/local/bin/automount.sh #chown root:admin /usr/local/bin/automount.sh #chmod 755 /usr/local/bin/automount.sh # CONSTANTS declare -r SCRIPTLASTMOD="2017-02-12" +(/usr/local/bin/automount.sh:38): declare -r SCRIPTLASTMOD=2017-02-12 declare -r SCRIPTVERSION="0.90.5" +(/usr/local/bin/automount.sh:39): declare -r SCRIPTVERSION=0.90.5 declare -ri YES=0 +(/usr/local/bin/automount.sh:40): declare -ri YES=0 declare -ri SUCCESS=${YES} +(/usr/local/bin/automount.sh:41): declare -ri SUCCESS=0 declare -ri TRUE=${YES} +(/usr/local/bin/automount.sh:42): declare -ri TRUE=0 declare -ri FOUND=${YES} +(/usr/local/bin/automount.sh:43): declare -ri FOUND=0 declare -ri NO=1 +(/usr/local/bin/automount.sh:44): declare -ri NO=1 declare -ri ERROR=${NO} +(/usr/local/bin/automount.sh:45): declare -ri ERROR=1 declare -ri FALSE=${NO} +(/usr/local/bin/automount.sh:46): declare -ri FALSE=1 declare -ri MISSING=${NO} +(/usr/local/bin/automount.sh:47): declare -ri MISSING=1 # os x version array major minor patch declare -air OSVERSION=( $(sw_vers | awk -F'[: |.]' '/ProductVersion/ { printf("%d %d %d", $2, $3, $4) }') ) +(/usr/local/bin/automount.sh:49): OSVERSION=($(sw_vers | awk -F'[: |.]' '/ProductVersion/ { printf("%d %d %d", $2, $3, $4) }')) sw_vers | awk -F'[: |.]' '/ProductVersion/ { printf("%d %d %d", $2, $3, $4) }' ++(/usr/local/bin/automount.sh:49): sw_vers ++(/usr/local/bin/automount.sh:49): awk '-F[: |.]' '/ProductVersion/ { printf("%d %d %d", $2, $3, $4) }' +(/usr/local/bin/automount.sh:49): declare -air OSVERSION # os x version as integer declare -ir OSVERSION_INTEGER=10#$(printf '%02d%02d%02d' "${OSVERSION[0]}" "${OSVERSION[1]}" "${OSVERSION[2]}") printf '%02d%02d%02d' "${OSVERSION[0]}" "${OSVERSION[1]}" "${OSVERSION[2]}" ++(/usr/local/bin/automount.sh:51): printf %02d%02d%02d 10 12 3 +(/usr/local/bin/automount.sh:51): declare -ir OSVERSION_INTEGER=10#101203 # script path name SCRIPT_PN="${0%/*}" +(/usr/local/bin/automount.sh:53): SCRIPT_PN=/usr/local/bin if [ "${SCRIPT_PN}" == "." ]; then SCRIPT_PN="${PWD}" elif [ "${SCRIPT_PN:0:1}" != "/" ]; then SCRIPT_PN="$(which ${0})" fi +(/usr/local/bin/automount.sh:54): '[' /usr/local/bin == . ']' +(/usr/local/bin/automount.sh:56): '[' / '!=' / ']' # script filename declare -r SCRIPT_FN="${0##*/}" +(/usr/local/bin/automount.sh:60): declare -r SCRIPT_FN=automount.sh # script name SCRIPTNAME="${SCRIPT_FN%.*}" +(/usr/local/bin/automount.sh:62): SCRIPTNAME=automount # script filename extension SCRIPTEXTENSION=${SCRIPT_FN##*.} +(/usr/local/bin/automount.sh:64): SCRIPTEXTENSION=sh if [ "${SCRIPTNAME}" == "" ]; then SCRIPTNAME=".${SCRIPTEXTENSION}" SCRIPTEXTENSION="" fi +(/usr/local/bin/automount.sh:65): '[' automount == '' ']' declare -r SCRIPT_PN SCRIPTNAME SCRIPTEXTENSION +(/usr/local/bin/automount.sh:69): declare -r SCRIPT_PN SCRIPTNAME SCRIPTEXTENSION # user name declare -r USERNAME="$(id -p | awk -F' ' '/^uid/ { print $2 }')" id -p | awk -F' ' '/^uid/ { print $2 }' ++(/usr/local/bin/automount.sh:71): id -p ++(/usr/local/bin/automount.sh:71): awk '-F ' '/^uid/ { print $2 }' +(/usr/local/bin/automount.sh:71): declare -r USERNAME=sadrian # user id declare -ir USERID="$(dscl . read /Users/${USERNAME} UniqueID | awk -F': ' '{ print $2 }')" dscl . read /Users/${USERNAME} UniqueID | awk -F': ' '{ print $2 }' ++(/usr/local/bin/automount.sh:73): dscl . read /Users/sadrian UniqueID ++(/usr/local/bin/automount.sh:73): awk '-F: ' '{ print $2 }' +(/usr/local/bin/automount.sh:73): declare -ir USERID=501 # user primary group id declare -ir USERPRIMARYGROUPID="$(dscl . read /Users/${USERNAME} PrimaryGroupID | awk -F': ' '{ print $2 }')" dscl . read /Users/${USERNAME} PrimaryGroupID | awk -F': ' '{ print $2 }' ++(/usr/local/bin/automount.sh:75): dscl . read /Users/sadrian PrimaryGroupID ++(/usr/local/bin/automount.sh:75): awk '-F: ' '{ print $2 }' +(/usr/local/bin/automount.sh:75): declare -ir USERPRIMARYGROUPID=20 # user home declare -r USERHOME="$(dscl . read /Users/${USERNAME} NFSHomeDirectory | awk -F': ' '{ print $2 }')" dscl . read /Users/${USERNAME} NFSHomeDirectory | awk -F': ' '{ print $2 }' ++(/usr/local/bin/automount.sh:77): dscl . read /Users/sadrian NFSHomeDirectory ++(/usr/local/bin/automount.sh:77): awk '-F: ' '{ print $2 }' +(/usr/local/bin/automount.sh:77): declare -r USERHOME=/Users/sadrian # login name LOGINNAME="$(id -p | awk -F' ' '/^login/ { print $2 }')" id -p | awk -F' ' '/^login/ { print $2 }' ++(/usr/local/bin/automount.sh:79): id -p ++(/usr/local/bin/automount.sh:79): awk '-F ' '/^login/ { print $2 }' +(/usr/local/bin/automount.sh:79): LOGINNAME= if [ -z "${LOGINNAME}" ]; then LOGINNAME="${USERNAME}" # login id declare -i LOGINID="${USERID}" # login primary group id declare -i LOGINPRIMARYGROUPID=${USERPRIMARYGROUPID} # login home LOGINHOME="${USERHOME}" # launch as user LAUNCHASUSER="" else declare -i LOGINID="$(dscl . read /Users/${LOGINNAME} UniqueID | awk -F': ' '{ print $2 }')" declare -i LOGINPRIMARYGROUPID="$(dscl . read /Users/${LOGINNAME} PrimaryGroupID | awk -F': ' '{ print $2 }')" LOGINHOME="$(dscl . read /Users/${LOGINNAME} NFSHomeDirectory | awk -F': ' '{ print $2 }')" LAUNCHASUSER="launchctl asuser ${LOGINID} chroot -u ${LOGINID} -g ${LOGINPRIMARYGROUPID} /" fi +(/usr/local/bin/automount.sh:80): '[' -z '' ']' +(/usr/local/bin/automount.sh:81): LOGINNAME=sadrian +(/usr/local/bin/automount.sh:83): declare -i LOGINID=501 +(/usr/local/bin/automount.sh:85): declare -i LOGINPRIMARYGROUPID=20 +(/usr/local/bin/automount.sh:87): LOGINHOME=/Users/sadrian +(/usr/local/bin/automount.sh:89): LAUNCHASUSER= declare -r LOGINNAME LOGINID LOGINPRIMARYGROUPID LOGINHOME LAUNCHASUSER +(/usr/local/bin/automount.sh:96): declare -r LOGINNAME LOGINID LOGINPRIMARYGROUPID LOGINHOME LAUNCHASUSER # case $(ps -o state= -p ${$}) in if [ -t 0 ]; then # interactive shell (not started from launch daemon) declare -ri BACKGROUND=${NO} else # background shell declare -ri BACKGROUND=${YES} fi +(/usr/local/bin/automount.sh:98): '[' -t 0 ']' +(/usr/local/bin/automount.sh:100): declare -ri BACKGROUND=1 # log dir (absolute path name) declare -r LOG_APN="${LOGINHOME}/Library/Logs" +(/usr/local/bin/automount.sh:106): declare -r LOG_APN=/Users/sadrian/Library/Logs # log file (absolute file name) declare -r LOG_AFN="${LOG_APN}/${SCRIPTNAME}.log" +(/usr/local/bin/automount.sh:108): declare -r LOG_AFN=/Users/sadrian/Library/Logs/automount.log # temp dir (absolute path name) declare -r TMP_APN="/tmp" +(/usr/local/bin/automount.sh:110): declare -r TMP_APN=/tmp # lock dir (absolute path name) declare -r LOCK_APN="${TMP_APN}/${SCRIPTNAME}.lock" +(/usr/local/bin/automount.sh:112): declare -r LOCK_APN=/tmp/automount.lock # lock file (absolute file name) declare -r LOCK_AFN="${LOCK_APN}/pid" +(/usr/local/bin/automount.sh:114): declare -r LOCK_AFN=/tmp/automount.lock/pid # log levels declare -a LOG_LEVEL +(/usr/local/bin/automount.sh:116): declare -a LOG_LEVEL declare -ir LOG_EMERGENCY=${#LOG_LEVEL[@]} +(/usr/local/bin/automount.sh:117): declare -ir LOG_EMERGENCY=0 LOG_LEVEL[${#LOG_LEVEL[@]}]="Emergency" +(/usr/local/bin/automount.sh:118): LOG_LEVEL[${#LOG_LEVEL[@]}]=Emergency declare -ir LOG_ALERT=${#LOG_LEVEL[@]} +(/usr/local/bin/automount.sh:119): declare -ir LOG_ALERT=1 LOG_LEVEL[${#LOG_LEVEL[@]}]="Alert" +(/usr/local/bin/automount.sh:120): LOG_LEVEL[${#LOG_LEVEL[@]}]=Alert declare -ir LOG_CRITICAL=${#LOG_LEVEL[@]} +(/usr/local/bin/automount.sh:121): declare -ir LOG_CRITICAL=2 LOG_LEVEL[${#LOG_LEVEL[@]}]="Critical" +(/usr/local/bin/automount.sh:122): LOG_LEVEL[${#LOG_LEVEL[@]}]=Critical declare -ir LOG_ERROR=${#LOG_LEVEL[@]} +(/usr/local/bin/automount.sh:123): declare -ir LOG_ERROR=3 LOG_LEVEL[${#LOG_LEVEL[@]}]="Error" +(/usr/local/bin/automount.sh:124): LOG_LEVEL[${#LOG_LEVEL[@]}]=Error declare -ir LOG_WARNING=${#LOG_LEVEL[@]} +(/usr/local/bin/automount.sh:125): declare -ir LOG_WARNING=4 LOG_LEVEL[${#LOG_LEVEL[@]}]="Warning" +(/usr/local/bin/automount.sh:126): LOG_LEVEL[${#LOG_LEVEL[@]}]=Warning declare -ir LOG_NOTICE=${#LOG_LEVEL[@]} +(/usr/local/bin/automount.sh:127): declare -ir LOG_NOTICE=5 LOG_LEVEL[${#LOG_LEVEL[@]}]="Notice" +(/usr/local/bin/automount.sh:128): LOG_LEVEL[${#LOG_LEVEL[@]}]=Notice declare -ir LOG_INFO=${#LOG_LEVEL[@]} +(/usr/local/bin/automount.sh:129): declare -ir LOG_INFO=6 LOG_LEVEL[${#LOG_LEVEL[@]}]="Info" +(/usr/local/bin/automount.sh:130): LOG_LEVEL[${#LOG_LEVEL[@]}]=Info declare -ir LOG_DEBUG=${#LOG_LEVEL[@]} +(/usr/local/bin/automount.sh:131): declare -ir LOG_DEBUG=7 LOG_LEVEL[${#LOG_LEVEL[@]}]="Debug" +(/usr/local/bin/automount.sh:132): LOG_LEVEL[${#LOG_LEVEL[@]}]=Debug declare -r LOG_LEVEL +(/usr/local/bin/automount.sh:133): declare -r LOG_LEVEL # automount plist (absolute file name) declare -r AUTOMOUNTPLIST_AFN="${LOGINHOME}/Library/Preferences/it.niemetz.automount.plist" +(/usr/local/bin/automount.sh:135): declare -r AUTOMOUNTPLIST_AFN=/Users/sadrian/Library/Preferences/it.niemetz.automount.plist # login keychain (absolute file name) declare -r LOGINKEYCHAIN_AFN="${LOGINHOME}/Library/Keychains/login.keychain" +(/usr/local/bin/automount.sh:137): declare -r LOGINKEYCHAIN_AFN=/Users/sadrian/Library/Keychains/login.keychain # max pings declare -ir MAXRETRYINSECONDS=10 +(/usr/local/bin/automount.sh:139): declare -ir MAXRETRYINSECONDS=10 # mount options declare -r MOUNTOPTIONS="nodev,nosuid" +(/usr/local/bin/automount.sh:141): declare -r MOUNTOPTIONS=nodev,nosuid # map protocol to value in keychain declare -ra PROTOCOLMAPPING=( 'afp="afp "' 'cifs="cifs"' 'ftp="ftp "' 'http="http"' 'https="htps"' 'smb="smb "' ) +(/usr/local/bin/automount.sh:143): PROTOCOLMAPPING=('afp="afp "' 'cifs="cifs"' 'ftp="ftp "' 'http="http"' 'https="htps"' 'smb="smb "') +(/usr/local/bin/automount.sh:143): declare -ra PROTOCOLMAPPING # ping -t timeout declare -ir PINGTIMEOUT=1 +(/usr/local/bin/automount.sh:145): declare -ir PINGTIMEOUT=1 if [[ ${OSVERSION_INTEGER} -ge 101200 && ${LOGINID} -ne 0 ]]; then # mountpoint absolute pathname MOUNTPOINT_APN="${LOGINHOME}/Volumes" else MOUNTPOINT_APN="/Volumes" fi +(/usr/local/bin/automount.sh:146): [[ 101203 -ge 101200 ]] +(/usr/local/bin/automount.sh:146): [[ 501 -ne 0 ]] +(/usr/local/bin/automount.sh:148): MOUNTPOINT_APN=/Users/sadrian/Volumes # Global variables # index counter declare -i MountlistIndex +(/usr/local/bin/automount.sh:155): declare -i MountlistIndex # is ip in valid range declare -i IsInValidRange=${TRUE} +(/usr/local/bin/automount.sh:157): declare -i IsInValidRange=0 # exit code declare -i EC=${TRUE} +(/usr/local/bin/automount.sh:159): declare -i EC=0 # array of ip addresses declare -a IPAddresses=() +(/usr/local/bin/automount.sh:161): IPAddresses=() +(/usr/local/bin/automount.sh:161): declare -a IPAddresses # late bound variables declare -i CommonMaxRetryInSeconds +(/usr/local/bin/automount.sh:163): declare -i CommonMaxRetryInSeconds CommonValidIPRanges="" +(/usr/local/bin/automount.sh:164): CommonValidIPRanges= CommonMountOptions="" +(/usr/local/bin/automount.sh:165): CommonMountOptions= CommonAccount="" +(/usr/local/bin/automount.sh:166): CommonAccount= ValidIPRanges="" +(/usr/local/bin/automount.sh:167): ValidIPRanges= MountOptions="" +(/usr/local/bin/automount.sh:168): MountOptions= declare -i MaxRetryInSeconds +(/usr/local/bin/automount.sh:169): declare -i MaxRetryInSeconds Protocol="" +(/usr/local/bin/automount.sh:170): Protocol= Account="" +(/usr/local/bin/automount.sh:171): Account= Server="" +(/usr/local/bin/automount.sh:172): Server= Share="" +(/usr/local/bin/automount.sh:173): Share= MountPoint="" +(/usr/local/bin/automount.sh:174): MountPoint= declare -i MountedShares=0 +(/usr/local/bin/automount.sh:175): declare -i MountedShares=0 # Action to do Action="" +(/usr/local/bin/automount.sh:177): Action= # verbose Verbose="" +(/usr/local/bin/automount.sh:179): Verbose= # redirect stdout RedirectStdout="/dev/null" +(/usr/local/bin/automount.sh:181): RedirectStdout=/dev/null # Function definitions function log { local _DateFormat='%Y-%m-%d %T %z' local _Delimiter="|" local -i _Priority=6 while :; do case ${1} in -p|--priority) if [[ -n "${2}" && "${2:0:1}" != "--" && "${2:0:1}" != "-" ]]; then if ! _Priority=${2} 2>/dev/null; then printf 'ERROR: "%s" requires a numeric option argument.\n' "${1}" >&2 exit 1 fi shift else printf 'ERROR: "%s" requires a non-empty option argument.\n' "${1}" >&2 exit 1 fi ;; --priority=?*) if ! _Priority=${1#*=} 2>/dev/null; then printf 'ERROR: "%s" requires a numeric option argument.\n' "${1}" >&2 exit 1 fi ;; --priority=) printf 'ERROR: "%s" requires a non-empty option argument.\n' "${1}" >&2 exit 1 ;; --) # End of all options. shift break ;; -?*) printf 'WARN: Unknown option (ignored): %s\n' "${1}" >&2 ;; *) # Default case: If no more options then break out of the loop. break esac shift done set -- "${1:-$(&2 else echo "${1}" fi echo "$(date +"${_DateFormat}")${_Delimiter}${$}${_Delimiter}${LOG_LEVEL[${_Priority}]}${_Delimiter}${1}" >>"${LOG_AFN}" } function cleanup { rm -rf "${LOCK_APN}" >/dev/null 2>&1 exit ${1} } function showUsage { cat <&1 _RC=${?} if [ ${_RC} -ne ${SUCCESS} ]; then log --priority=${LOG_ERROR} "getPasswordFromKeychain failed (RC=${_RC})" fi return ${_RC} } function pingServer { # server to ping local _Server="${1}" # retry counter local -i _Try=0 # return value local _RV="" if [ -n "${_Server}" ]; then while ! _RV="$(ping -c 1 -t ${PINGTIMEOUT} -o -q "${_Server}" 2>&1)" && [ ${_Try} -le ${MaxRetryInSeconds} ]; do ((_Try++)) done if [ ${_Try} -gt ${MaxRetryInSeconds} ]; then log --priority=${LOG_ERROR} "Could not ping ${Server} within ${MaxRetryInSeconds} (RC=${RC}, RV=${_RV})" return ${ERROR} fi fi return ${SUCCESS} } function initCommonValues { # set global common values CommonMaxRetryInSeconds="$(/usr/libexec/PlistBuddy -c "Print CommonMaxRetryInSeconds" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null)" declare -i CommonMaxRetryInSeconds="${CommonMaxRetryInSeconds:-${MAXRETRYINSECONDS}}" CommonValidIPRanges="$(/usr/libexec/PlistBuddy -c "Print CommonValidIPRanges" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null)" CommonMountOptions="$(/usr/libexec/PlistBuddy -c "Print CommonMountOptions" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null)" CommonMountOptions="${CommonMountOptions:-${MOUNTOPTIONS}}" CommonAccount="$(/usr/libexec/PlistBuddy -c "Print CommonAccount" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null)" CommonAccount="${CommonAccount:-${LOGINNAME}}" return ${SUCCESS} } function readMountlistValues { local -i _Index=${1} # first clear old values unset ValidIPRanges MountOptions MaxRetryInSeconds Protocol Account Server Share MountPoint # get values ValidIPRanges="$(/usr/libexec/PlistBuddy -c "Print Mountlist:${_Index}:ValidIPRanges" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null)" ValidIPRanges="${ValidIPRanges:-${CommonValidIPRanges}}" MountOptions=$(/usr/libexec/PlistBuddy -c "Print Mountlist:${_Index}:MountOptions" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null) MountOptions="${MountOptions:-${CommonMountOptions}}" MaxRetryInSeconds="$(/usr/libexec/PlistBuddy -c "Print Mountlist:${_Index}:MaxRetryInSeconds" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null)" declare -i MaxRetryInSeconds="${MaxRetryInSeconds:-${CommonMaxRetryInSeconds}}" Protocol="$(/usr/libexec/PlistBuddy -c "Print Mountlist:${_Index}:Protocol" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null)" Account="$(/usr/libexec/PlistBuddy -c "Print Mountlist:${_Index}:Account" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null)" Account="${Account:-${CommonAccount}}" Server="$(/usr/libexec/PlistBuddy -c "Print Mountlist:${_Index}:Server" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null)" Share="$(/usr/libexec/PlistBuddy -c "Print Mountlist:${_Index}:Share" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null)" MountPoint="$(/usr/libexec/PlistBuddy -c "Print Mountlist:${_Index}:MountPoint" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null)" MountPoint="${MountPoint:-${Share##*/}}" if [[ -n "${Protocol}" && -n "${Account}" && -n "${Server}" && -n "${Share}" ]]; then return ${SUCCESS} else log --priority=${LOG_ERROR} "Protocol \"${Protocol}\"/Account \"${Account}\"/Server \"${Server}\"/Share \"${Share}\" empty" return ${ERROR} fi } function isInValidIPRange { local _ValidIPRanges="${1}" local _IPAddress _IPAddressPart if [ -n "${_ValidIPRanges}" ]; then for _IPAddress in "${IPAddresses[@]}"; do _IPAddressPart="$(echo "${_IPAddress}" | cut -d'.' -f1-3)" if [[ "${_ValidIPRanges}" =~ (^|,)"${_IPAddressPart}"(,|$) ]]; then return ${YES} fi done log --priority=${LOG_WARNING} "Not allowed to mount \"${Share}\" because \"${IPAddresses[@]}\" not in range of \"${_ValidIPRanges}\"" return ${NO} fi return ${YES} } function isMounted { local _RV="" if _RV="$(mount | egrep "//.*${Server}/(${Share})? on ${MOUNTPOINT_APN}/${Share} \(.*(, mounted by ${LOGINNAME})?\)$" 2>&1)"; then log --priority=${LOG_WARNING} "Share \"${Share}\" already mounted (RV=${_RV})" return ${YES} fi return ${NO} } function createMountpoint { local _Share="${1}" local _RV="" local -i _RC=${TRUE} if [ -n "${_Share}" ]; then if [ ! -d "${MOUNTPOINT_APN}/${_Share}" ]; then _RV="$( { mkdir -p ${Verbose} "${MOUNTPOINT_APN}/${_Share}" && chown "${LOGINID}:${LOGINPRIMARYGROUPID}" "${MOUNTPOINT_APN}/${_Share}" && chmod 755 "${MOUNTPOINT_APN}/${_Share}"; } 2>&1 )" _RC=${?} if [ ${_RC} -ne ${SUCCESS} ]; then log --priority=${LOG_ERROR} "Could not create \"${MOUNTPOINT_APN}/${_Share}\" (RC=${_RC}, RV=${_RV})" rmdir "${MOUNTPOINT_APN}/${_Share}" >/dev/null 2>&1 return ${ERROR} fi fi fi return ${SUCCESS} } function processMountlist { local _RV="" local -i _RC=${TRUE} local -i _EC=${TRUE} # check all files exits if [ ! -s "${AUTOMOUNTPLIST_AFN}" ] || [ ! -s "${LOGINKEYCHAIN_AFN}" ]; then log --priority=${LOG_ERROR} "${AUTOMOUNTPLIST_AFN} or ${LOGINKEYCHAIN_AFN} are missing" return ${ERROR} fi # get local ip address(es) getIPAddresses _RC=${?} if [ ${_RC} -ne ${SUCCESS} ]; then return ${_RC} fi # initialize common values initCommonValues # process automount plist file MountlistIndex=0 while /usr/libexec/PlistBuddy -c "Print Mountlist:${MountlistIndex}" "${AUTOMOUNTPLIST_AFN}" >/dev/null 2>&1; do # get the values if ! readMountlistValues ${MountlistIndex}; then ((MountlistIndex++)) continue fi # check if in valid ip range if ! isInValidIPRange "${ValidIPRanges}"; then ((MountlistIndex++)) continue fi # is share already mounted? if isMounted; then ((MountlistIndex++)) continue fi # create mountpoint if ! createMountpoint "${MountPoint}"; then ((MountlistIndex++)) continue fi case ${Protocol} in http|https) _RV="$(expect -c ' set timeout 15 '"${ExpectDebug}"' spawn /sbin/mount_webdav -s -i'"${MountOptions:+ -o ${MountOptions}}"' '"${Protocol}"'://'"${Server}"' '"${MOUNTPOINT_APN}"'/'"${MountPoint}"' expect "name:" { send "'"${Account}"'\r" } expect timeout { exit 1 } "word:" { send "'$(getPasswordFromKeychain)'\r" exp_continue } eof catch wait result exit [lindex $result 3] ' 2>&1)" _RC=${?} ;; ftp) _RV="$(expect -c ' set timeout 15 '"${ExpectDebug}"' spawn /sbin/mount_ftp -i'"${MountOptions:+ -o ${MountOptions}}"' '"${Protocol}"'://'"${Server}"' '"${MOUNTPOINT_APN}"'/'"${MountPoint}"' expect "name:" { send "'"${Account}"'\r" } expect timeout { exit 1 } "word:" { send "'$(getPasswordFromKeychain)'\r" exp_continue } eof catch wait result exit [lindex $result 3] ' 2>&1)" _RC=${?} ;; nfs) _RV="$(mount -t ${Protocol}${MountOptions:+ -o ${MountOptions}} "${Server}:/${Share}" "${MOUNTPOINT_APN}/${MountPoint}" 2>&1)" _RC=${?} ;; afp) _RV="$(mount_afp -s ${MountOptions:+ -o ${MountOptions}} "${Protocol}://${Account}:$(getPasswordFromKeychain)@${Server}/${Share}" "${MOUNTPOINT_APN}/${MountPoint}" 2>&1)" _RC=${?} ;; smb) _RV="$(mount_smbfs -o soft${MountOptions:+,${MountOptions}} "${Protocol}://${Account}:$(getPasswordFromKeychain)@${Server}/${Share}" "${MOUNTPOINT_APN}/${MountPoint}" 2>&1)" _RC=${?} ;; cifs) _RV="$(mount -t ${Protocol}${MountOptions:+ -o ${MountOptions}} "${Protocol}://${Account}:$(getPasswordFromKeychain)@${Server}/${Share}" "${MOUNTPOINT_APN}/${MountPoint}" 2>&1)" _RC=${?} ;; *) log --priority=${LOG_ERROR} "Unknown protocol ${Protocol}" ((MountlistIndex++)) continue ;; esac if [ ${_RC} -eq ${SUCCESS} ]; then log --priority=${LOG_INFO} "${Share} mounted successfully" ((MountedShares++)) else log --priority=${LOG_ERROR} "mount of ${Share} failed (RC=${_RC}, RV=${_RV})" fi _EC=$((_EC||_RC)) ((MountlistIndex++)) done if [ ${_EC} -eq ${SUCCESS} ]; then if [ ${MountedShares} -eq ${MountlistIndex} ]; then log --priority=${LOG_INFO} "automount runned successfully." fi if [ ${BACKGROUND} -eq ${YES} ]; then ${LAUNCHASUSER} /usr/bin/osascript -e "display notification \"automount runned successfully.\" with title \"automount\" subtitle \"\"" fi else log --priority=${LOG_ERROR} "automount runned with errors." if [ ${BACKGROUND} -eq ${YES} ]; then ${LAUNCHASUSER} /usr/bin/osascript -e "display notification \"automount runned with errors.\" with title \"automount\" subtitle \"\"" fi fi return ${_EC} } function addPassword { local _Account="${Account:-${LOGINNAME}}" local _AccountHomeDirectory="$(dscl . read /Users/${_Account} NFSHomeDirectory | cut -d' ' -f2-)" local _AppAccess="" local _RV="" local -i RC=0 if [[ "${Protocol}" =~ ^http(s)+ ]]; then _AppAccess="-T /System/Library/Extensions/webdav_fs.kext/Contents/Resources/webdavfs_agent" fi _RV="$(security add-internet-password \ -a "${_Account}" \ -l "${Server}" \ -D "${Description:-Netzwerkpasswort}" \ -j "${SCRIPTNAME}" \ -r "$(getKeychainProtocol)" \ -s "${Server}" \ -w "$(read -p "Password: " -s && echo "${REPLY}"; unset REPLY)" \ -U \ -T /usr/bin/security \ -T /System/Library/CoreServices/NetAuthAgent.app/Contents/MacOS/NetAuthSysAgent \ -T /System/Library/CoreServices/NetAuthAgent.app \ -T group://NetAuth \ ${_AppAccess} \ "${_AccountHomeDirectory}"/Library/Keychains/login.keychain 2>&1)" _RC=${?} if [ ${_RC} -eq ${SUCCESS} ]; then log --priority=${LOG_INFO} "successfully added password to keychain." else log --priority=${LOG_ERROR} "error adding password to keychain. (RC=${_RC}, RV=${_RV})" fi exit ${_RC} } function create_lock { local _RV _RunningPID local -i _RC=${TRUE} _RV="$( { mkdir "${LOCK_APN}" && echo "${$}" > "${LOCK_AFN}"; } 2>&1 || false )" _RC=${?} if [ ${_RC} -ne ${SUCCESS} ]; then if [ -s "${LOCK_AFN}" ]; then _RunningPID="$(cat "${LOCK_AFN}")" _RV="$(pgrep -f -l -F "${LOCK_AFN}" "${SCRIPT_FN}" 2>&1)" _RC=${?} else _RunningPID="" _RV="$(pgrep -f -l "${SCRIPT_FN}" 2>&1)" _RC=${?} fi if [ ${_RC} -eq ${FOUND} ]; then log --priority=${LOG_ERROR} "${SCRIPT_FN} is already running${_RunningPID:+ with PID ${_RunningPID}}" exit 1 else _RV="$( { rm -rf "${LOCK_APN}" && mkdir "${LOCK_APN}" && echo "${$}" > "${LOCK_AFN}"; } 2>&1 || false )" _RC=${?} if [ ${_RC} -ne ${SUCCESS} ]; then log --priority=${LOG_ERROR} "Could not create \"${LOCK_AFN}\", exiting (RC=${_RC}, RV=${_RV})" exit 1 fi fi fi } # Main # catch traps trap 'cleanup' SIGHUP SIGINT SIGQUIT SIGTERM EXIT +(/usr/local/bin/automount.sh:631): trap cleanup SIGHUP SIGINT SIGQUIT SIGTERM EXIT create_lock +(/usr/local/bin/automount.sh:632): create_lock +(/usr/local/bin/automount.sh:600): create_lock(): local _RV _RunningPID +(/usr/local/bin/automount.sh:601): create_lock(): local -i _RC=0 { mkdir "${LOCK_APN}" && echo "${$}" > "${LOCK_AFN}"; } 2>&1 || false +(/usr/local/bin/automount.sh:603): create_lock(): _RV='++(/usr/local/bin/automount.sh:603): create_lock(): mkdir /tmp/automount.lock ++(/usr/local/bin/automount.sh:603): create_lock(): echo 5042' +(/usr/local/bin/automount.sh:604): create_lock(): _RC=0 +(/usr/local/bin/automount.sh:605): create_lock(): '[' 0 -ne 0 ']' while :; do case ${1} in -h|-\?|--help) # Call a "showUsage" function to display a synopsis, then exit. showUsage exit ;; -a|--account) if [[ -n "${2}" && "${2:0:1}" != "--" && "${2:0:1}" != "-" ]]; then Account="${2}" shift else printf 'ERROR: "%s" requires a non-empty option argument.\n' "${1}" >&2 exit 1 fi ;; --account=?*) Account=${1#*=} # Delete everything up to "=" and assign the remainder. ;; --account=) # Handle the case of an empty --account= printf 'ERROR: "%s" requires a non-empty option argument.\n' "${1}" >&2 exit 1 ;; -d|--description) if [[ -n "${2}" && "${2:0:1}" != "--" && "${2:0:1}" != "-" ]]; then Description="${2}" shift else printf 'ERROR: "%s" requires a non-empty option argument.\n' "${1}" >&2 exit 1 fi ;; --description=?*) Description=${1#*=} ;; --description=) printf 'ERROR: "%s" requires a non-empty option argument.\n' "${1}" >&2 exit 1 ;; -p|--protocol) if [[ -n "${2}" && "${2:0:1}" != "--" && "${2:0:1}" != "-" ]]; then Protocol="${2}" shift else printf 'ERROR: "%s" requires a non-empty option argument.\n' "${1}" >&2 exit 1 fi ;; --protocol=?*) Protocol=${1#*=} ;; --protocol=) printf 'ERROR: "%s" requires a non-empty option argument.\n' "${1}" >&2 exit 1 ;; -s|--server) if [[ -n "${2}" && "${2:0:1}" != "--" && "${2:0:1}" != "-" ]]; then Server="${2}" shift else printf 'ERROR: "%s" requires a non-empty option argument.\n' "${1}" >&2 exit 1 fi ;; --server=?*) Server=${1#*=} ;; --server=) printf 'ERROR: "%s" requires a non-empty option argument.\n' "${1}" >&2 exit 1 ;; --addpassword) Action="addPassword" ;; -m|--mountall) Action="processMountlist" ;; -v|--verbose) Verbose="-v" ;; --) # End of all options. shift break ;; -?*) printf 'WARN: Unknown option (ignored): %s\n' "${1}" >&2 ;; *) # Default case: If no more options then break out of the loop. break esac shift done +(/usr/local/bin/automount.sh:634): : +(/usr/local/bin/automount.sh:635): case ${1} in +(/usr/local/bin/automount.sh:708): Action=processMountlist +(/usr/local/bin/automount.sh:723): shift +(/usr/local/bin/automount.sh:634): : +(/usr/local/bin/automount.sh:635): case ${1} in +(/usr/local/bin/automount.sh:721): break case "${Action}" in processMountlist) ${Action} RC=${?} exit ${RC} ;; addPassword) if [[ -z "${Protocol}" || -z "${Server}" ]]; then showUsage exit fi ${Action} ;; *) showUsage exit ;; esac +(/usr/local/bin/automount.sh:726): case "${Action}" in +(/usr/local/bin/automount.sh:728): processMountlist +(/usr/local/bin/automount.sh:431): processMountlist(): local _RV= +(/usr/local/bin/automount.sh:432): processMountlist(): local -i _RC=0 +(/usr/local/bin/automount.sh:433): processMountlist(): local -i _EC=0 +(/usr/local/bin/automount.sh:436): processMountlist(): '[' '!' -s /Users/sadrian/Library/Preferences/it.niemetz.automount.plist ']' +(/usr/local/bin/automount.sh:436): processMountlist(): '[' '!' -s /Users/sadrian/Library/Keychains/login.keychain ']' +(/usr/local/bin/automount.sh:442): processMountlist(): getIPAddresses +(/usr/local/bin/automount.sh:247): getIPAddresses(): local _IPAddresses= +(/usr/local/bin/automount.sh:248): getIPAddresses(): local -i _Sleep=0 +(/usr/local/bin/automount.sh:250): getIPAddresses(): [[ -z '' ]] +(/usr/local/bin/automount.sh:250): getIPAddresses(): [[ 0 -lt 10 ]] +(/usr/local/bin/automount.sh:251): getIPAddresses(): sleep 0 +(/usr/local/bin/automount.sh:252): getIPAddresses(): (( _Sleep++ )) /sbin/ifconfig | /usr/bin/awk ' BEGIN { device="" } /(^en[0-9]*:|^utun[0-9]*).*UP.*RUNNING/ { device=$1 next } $1 == "inet" && device != "" { output=sprintf("%s%s", (output == "" ? "" : output " "), $2) device="" next } END { print output } ' ++(/usr/local/bin/automount.sh:276): getIPAddresses(): /sbin/ifconfig ++(/usr/local/bin/automount.sh:292): getIPAddresses(): /usr/bin/awk ' BEGIN { device="" } /(^en[0-9]*:|^utun[0-9]*).*UP.*RUNNING/ { device=$1 next } $1 == "inet" && device != "" { output=sprintf("%s%s", (output == "" ? "" : output " "), $2) device="" next } END { print output } ' +(/usr/local/bin/automount.sh:275): getIPAddresses(): _IPAddresses=192.168.0.14 +(/usr/local/bin/automount.sh:250): getIPAddresses(): [[ -z 192.168.0.14 ]] +(/usr/local/bin/automount.sh:250): getIPAddresses(): [[ 192.168.0.14 =~ (^| )169\.[0-9]+\.[0-9]+\.[0-9]+( |$) ]] +(/usr/local/bin/automount.sh:278): getIPAddresses(): '[' -n 192.168.0.14 ']' +(/usr/local/bin/automount.sh:279): getIPAddresses(): IPAddresses=(${_IPAddresses}) +(/usr/local/bin/automount.sh:280): getIPAddresses(): return 0 +(/usr/local/bin/automount.sh:443): processMountlist(): _RC=0 +(/usr/local/bin/automount.sh:444): processMountlist(): '[' 0 -ne 0 ']' +(/usr/local/bin/automount.sh:449): processMountlist(): initCommonValues /usr/libexec/PlistBuddy -c "Print CommonMaxRetryInSeconds" "${AUTOMOUNTPLIST_AFN}" 2>/dev/null ++(/usr/local/bin/automount.sh:346): initCommonValues(): /usr/libexec/PlistBuddy -c 'Print CommonMaxRetryInSeconds' /Users/sadrian/Library/Preferences/it.niemetz.automount.plist +(/usr/local/bin/automount.sh:346): initCommonValues(): CommonMaxRetryInSeconds='Error Reading File: /Users/sadrian/Library/Preferences/it.niemetz.automount.plist' /usr/local/bin/automount.sh: line 346: Error Reading File: /Users/sadrian/Library/Preferences/it.niemetz.automount.plist: syntax error in expression (error token is "Reading File: /Users/sadrian/Library/Preferences/it.niemetz.automount.plist") cleanup +(/usr/local/bin/automount.sh:729): initCommonValues(): cleanup +(/usr/local/bin/automount.sh:236): cleanup(): rm -rf /tmp/automount.lock +(/usr/local/bin/automount.sh:237): cleanup(): exit