Bash function returns an unexpected value - bash

I wrote this function in BASH, and it returns an unexpected value:
checkIfUserFound()
{
isUserFound=$( cat user_uid.txt | grep $ADMIN_TO_UPDATE -B 1 | grep "uid" )
return $isUserFound
}
the user_uid.txt file is empty (I enter invalid admin).
but for some reason, it returns "1":
checkIfUserFound
isUserFound=$?
if [ "$isUserFound" -eq "0" ];
then
echo "Searching..."
else
echo "User found..."
fi
This prints "User found..."
Does anyone know how come that is the returning value ? Shouldn't I get "0" when returning from the function ?

The argument to return needs to be a number (a small integer -- the range is 0 through 255). But grep already sets its return code to indicate whether it found a match, and functions already return the return code of the last command in the function; so all you really need is
checkIfUserFound()
{
grep "$ADMIN_TO_UPDATE" -B 1 user_uid.txt |
grep -q "uid"
}
(Notice also how we get rid of the useless use of cat).
The script could probably usefully be refactored to Awk. Perhaps I am guessing correctly what you want:
checkIfUserFound()
{
awk -v user="$ADMIN_TO_UPDATE" '/uid/ { p=1; next }
p { if ($0 ~ user) found=1; p=0 }
END { exit 1-found }' user_uid.txt
}
Finally, the code which calls this function should check whether it succeeded, not whether it printed 0.
if ! checkIfUserFound
then
echo "Searching..."
else
echo "User found..."
fi
Notice perhaps that [ is not part of the if command's syntax (though [ is one of the commands whose result code if is often used to check).

The main problem is that you don't check for failure of any of the commands in the pipe.
The failure (exit code) of the last command in the pipe will be the exit value of the whole pipe. That exit code is available in the $? variable.
And since you want to return the success/failure of the pipe from the function, that's the value you need to return:
return $?
If the pipe doesn't fail then the result of the pipe will be the output on stdout, which will be put into the $isUserFound variable. Since it will not be a valid exit code (which must be numeric) then it can't be returned.
Since you don't need the $isUserFound variable, and you want to return the result of the pipe, your function could be simplified as
checkIfUserFound() {
cat user_uid.txt | grep $ADMIN_TO_UPDATE -B 1 | grep "uid" 2>&1 >/dev/null
}

Related

how to check whether the input is found or not found in the directory using pinky (there are inputs, but the user is not there)

what I want is to input a username and if the user cannot be found, the FNAME should be not found, but when I did the tester, the NOTFOUND never shows up, the tester was made by someone else and should have no problem.
function fname()
{
#if argument passed canot be found among sessions logged in
result=$(pinky -f "$1")
result_length="${#result}"
#if the result length is not equal to zero means there are some values
elif [ "$result_length" != 0 ]
then
FNAME="$(pinky -f $1 | awk '{print $2}')"
return 0
elif [ ! -f "$result" ]
then
FNAME="NOTFOUND"
return 0
fi
}
I tried to check the result but only ERROR and the user's first name can be displayed, the NOTFOUND never shows up even when I put a wrong input. is it because the ${# result} never display 0?
fname
Function status code is ==1== FNAME value is ==ERROR==
[[[[ WORKS - but user id is not found ]]]]
fname nouser
Function status code is ==0== FNAME value is ====
[[[[ WORKS - user id is found ]]]]
fname zo9
Function status code is ==0== FNAME value is ==Zo==
Your issue is on this line:
elif [ ! -f "$result" ]
This literally means "else if $result is not a file." Since you are setting result to the output of pinky, this is obviously not doing what you think it does. Since you are checking whether the variable result is blank or not in the original if statement, all you need here is else.
Also, there is a built in way to check for a blank variable using test ([). You could test with the -n option. It would be cleaner to use that in your if block like this:
if [ -n "$result" ]; then
# found
else
# not found
fi
Then, there is no need for the result_length variable.
Also, there is no need to re-run pinky for awk. You have the result of pinky stored in your result variable. All you need to do is send the variable into awk with a here-string. Something like this:
FNAME="$(awk '{print $2}' <<< "$result")"

How to store return value from function with argument in a variable? [duplicate]

This question already has answers here:
Return value in a Bash function
(11 answers)
Closed 3 years ago.
I'm struggling with storing the return value (0 or 1) of my function in a variable. Whatever I try, $var ends up being empty or I run into error messages.
Here is my specific code:
function screen_exists() {
if screen -list | grep -q "${1}"; then
return 0
else
return 1
fi
}
VAR=$(screen_exists "${PLAYER_SCREEN_NAME}")
echo ${VAR}
I've also tried with a super simple function that always returns 0, but same outcome.
$(...) is command substitution syntax that is used to capture output of given command. If you want to store return value of a function then use $?:
screen_exists() {
screen -list | grep -q "$1"
# implicit here is: return $?
}
screen_exists "${PLAYER_SCREEN_NAME}"
ret=$?
Also note that this function will return 1 if grep doesn't find search patter and 0 if it is success which is the standard norm in shell utilities.

Find FileVault2 user in fdesetup output with Awk

I have 2 user profiles (fred, fredmoo) with filevault 2 enabled.
I have the following bash:
## Get the logged in user's name
userName=$(/usr/bin/stat -f%Su /dev/console)
This first user check sees if the logged in account is already authorized with FileVault 2
userCheck=`fdesetup list | awk -v usrN="$userName" -F, 'index($0, usrN) {print $1}'`
if [ "${userCheck}" != "${userName}" ]; then
echo "This user is not a FileVault 2 enabled user."
exit 3
fi
If I do echo $userName, I get
fred
If I do echo $userCheck, I get
fred fredmoo
The conditional statement above works well if there's only 1 profile. Unix or Linux Image, however since my mac has more than 1 user profile, the statement will echo "This user is not a FileVault 2 enabled user." and exit.
userCheck has both profiles.
How do I modify the if statement to say if userName does NOT equal to the 1st userCheck or 2nd userCheck, then echo "This user is not a FileVault 2 enabled user." and exit?
The output from fdesetup list looks like this:
fredmoo,485A09Cf-B0D5-469A-8224-2DD1877E780B
administrator,DDB87E8D-8150-4D06-A59D-774AD28D119C
gollum,8AE6C365-E38F-49E2-998C-F4742CC9980C
Your Awk script looks for fred anywhere in the fdesetup output, which of course it also finds when the output contains fredmoo.
You seem to have a comma-separated output that you are comparing against, so your Awk script should probably be something like awk -v user="$(whoami)" -F , '$1 == user { print $1 }' (where I assume output looks like in the sample here: https://derflounder.wordpress.com/2013/10/22/managing-mavericks-filevault-2-with-fdesetup/).
Also, a common antipattern is storing stuff you only need once in a variable, which just complicates things and pollutes your namespace. Try to change your Awk script so that it sets the correct exit code; then you can use that directly in a conditional. Maybe even refactor that into a reusable function.
warn () {
echo "$0: $#" >&2
}
die () {
rc=$1
shift
warn "$#"
exit $rc
}
canihazfv2 () {
fdesetup list |
awk -v user="$1" -F , '$1 == user { print $1; exit 0 } END { exit 1 }'
}
me=$(whoami)
canihazfv2 "$me" || die 3 "$me is not enabled to use FileVault 2"
Notice also how the script identifies itself in the error message (so that when you build new scripts which call other scripts which call this script, you can see which one is actually failing three years from now) as well as the actual input which triggered the error, and prints the error message to standard error through redirection.
As always, this || that is shorthand for if ! this; then that; fi where of course the longhand might be preferable if that is something moderately complex (which I avoid here by also encapsulating die in a function).

Passing and return value of external function in awk

I am calling function from another script from awk.
Why i need to press enter even after adding /dev/null
Why the passed argument is not displayed. I am getting spaces.
I am not getting the return value from external function.
cat mainpgm.sh
#!/bin/bash
key="09"
awk -v dk="$key" ' { ma = system(". /home/ott/functions.sh;derived dk")</dev/null ; "print returned value" ma } '
cat functions.sh
#!/bin/bash
derived () {
echo "outside function" $dk
return 9
}
If you don't want to process input in awk, redirect its input to /dev/null, and do everything in the BEGIN block. Also, for the dk variable to be replaced with its value, it has to be outside the quotes.
awk -v dk="$key" 'BEGIN {
ma = system(". /home/ott/functions.sh;derived " dk);
print "returned value", ma
}' < /dev/null
To answer your questions:
You put /dev/null in the wrong place. It's supposed to be the input of the script, not the system function.
Two reasons: First, you put dk inside the quotes, so its value is not substituted. Second, the derived function doesn't print its argument, it prints $dk, which is a nonexistent shell variable. The argument to a function is $1, so it should do:
echo "outside function $1"
You had print inside the quotes, so it wasn't being executed as a statement.

User Defined Function in Awk

I am facing as issue in below mentioned call to User Defined function using AWK
awk '{
if ("${PROS}" == "" )
wq_fm_exception ${FILE_SEQ_NBR}
#exit 1
HEAD="TRUE"
}
where wq_fm_exception is a user defined function being written in same script in which awk is being called. The parameter name ${FILE_SEQ_NBR} passed to function wq_fm_exception is defined globally.
Can anyone suggest?
AWK cannot call functions defined in the spawning shell. You could, however, have it write its error to a file and exit with failure, and have the spawning shell then deal with that:
if ! awk '{
if(...) {
print "can't frobnicate the bar" > "/tmp/errors"
exit 1
}
}'; then
wq_fm_exception "$(cat /tmp/errors)"
exit $?
fi
(If you choose to go with this method, you’d probably want to use mktemp to generate a filename for /tmp/errors rather than hardcoding it.)

Resources