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) - bash

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")"

Related

Bash function returns an unexpected value

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
}

Awk print exact fields when finding an exact match

I have a persons.dat file containing information.
Here's an example line.
1129|Lepland|Carmen|female|1984-02-18|228T04:39:58.781+0000|81.25.252.111|Internet Explorer
1129 is the ID.
I am asked to display the information of anyone based on their ID,in particular their firstname (Carmen), (Lastname = Lepland) and date of Birth (1984-02-18) separated by a space.
I have stored the id in a shell variable IDNumber as shown below:
for arg1 in $#;do # Retrieve ID Number
if [ $1 = "-id" ];then
IDNumber="$2"
fi
shift
done
How can I use awk to display the exact fields of one ID?
The command line argument parsing of the shell script is a bit confusing like that, since arg1 is not used.
And even after it finds -id and assigns $2 to IDNumber,
the iteration continues.
For example when the arguments are -id 3,
after IDNumber=3,
the iteration continues, checking if [ 3 = "-id" ].
Also, the "$1" in if [ $1 = ... ] should be double-quoted,
otherwise the script will crash if there is an empty argument.
Here's one way to fix these issues:
while [ $# -gt 0 ]; do
if [ "$1" = -id ]; then
id=$2
fi
shift
done
Then you can use id with Awk like this:
awk -F'|' -v id="$id" '$1 == id {print $3, $2, $5}' persons.dat
That is:
Set | as the field separator
Set id variable in Awk to the value of $id in the shell
Find the record in the input where the first field ($1) is equal to id
Print the columns you need

Improving knowledge in Bash

This is more directed to learning about BASH rather than creating a specific code.
---Problem: Write a Bash script that takes a list of login names on your computer system as command line arguments, and displays these login names, full names and user-ids of the users who own these logins (as contained in the /etc/passwd file), one per line. If a login name is invalid (not found in the /etc/passwd file), display the login name and an appropriate error message. ---
If I needed to create a code to fulfill this problem could I do it using a "choice" list like this:
read -p "Enter choice: " ch
if [ "$ch" = "1" ]; then
function_1
else
if [ "$ch" = "2" ]; then
function_2
else
if [ "$ch" = "3" ]; then
function_3
else
if [ "$ch" = "4" ]; then
function_4
else
if [ "$ch" = "5" ]; then
function_5
fi x5
or would it have to be completed using a grep and test method where by the user read input must be taken into variables Name1 Name2.... NameN and are tested to the ect/passwd file via grep command.
#!/bin/bash
# pgroup -- first version
# Fetch the GID from /etc/group
gid=$(grep "$̂1:" /etc/group | cut -d: -f3)
# Search users with that GID in /etc/passwd
grep "^[^:]*:[^:]*:[^:]*:$gid:" /etc/passwd | cut -d: -f1`enter code here`
Please explain the best you can with some generic code. I am still learning the basics and testing different ideas. I apologize if these are very vague concepts, I am still getting the hang of BASH.
You would:
Accept (read) from the user the username,
Check if the username exists by retrieving the record using grep,
If positive result (i.e. you got data), display it as needed,
Otherwise, display an error message (or whatever you need).
You are almost there (got how to get input, how to search using grep). What you need is to get the result of the grep into a variable that you can check. You may try something like:
Result=$(grep....)
and then check the contents of Result.
To me it looks like you're missing an important part of the problem: the names are passed as arguments to the script:
./script.sh name1 name2 name3
If this is the case, then a loop would be the most appropriate thing to use:
for login; do
printf '%s: %s\n' "$login" "$(grep "^$login" /etc/passwd)"
done
Note that a for loop iterates over the list of arguments passed to the script $# by default.

simple password cracker in scripting doesn't end when it find the correct password

#!/bin/bash
commonguess(){
for guess in $(cat passwordlist)
do
try=$(echo "$guess" | sha256sum | awk '{print $1}' )
if [ "$try" == "$xxx" ]
then
echo "$name:$try"
break
fi
done
}
dict(){...}
brute(){...}
while IFS=':' read -r name hashing;do
commonguess
dict
brute
done
I have tested all 3 functions, they work fine. The only problem is in the bottom.
a:123
b:234
c:111
For example, i have this file named "user". If i run my code with this file, my code will test value of a(123) through 3 functions even it found answer in the first one. I don't want to do that, i want to do something like testing the value, if not found in function1 then move to next function, if it find answer then just move to next value.
Replace break in commonguess for "return 0", add "return 1" to the end of the function, do the same for the other functions and change the while loop to:
while IFS=':' read -r name hashing;do
commonguess || dict || brute
done
More information about the bash conditional short circuit evaluation here:
http://wresch.github.io/2014/04/24/bash-short-circuit-evaluation.html

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).

Resources