LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-15-2014, 12:50 PM   #1
boygenuis
Member
 
Registered: Oct 2007
Location: The Fire Swamp
Distribution: SUSE 12.3, Fuduntu, Fedora 18, Ubuntu 12.04
Posts: 39

Rep: Reputation: 26
Homework Help: customized mail message to logged in users


Good morrow, everybody. I'm working on another homework assignment and getting stuck. The basic principle is to write a shell script to send a customized mail message to the users listed on the command line by name only if they are currently logged on. My first draft was WAAAY off, so I've got another one which is also kicking my butt.

Here's the outline from the teacher:
Code:
If there are no position parameters (usernames) listed on the command line
        then
        print an error message
        exit the script
   endif
#cool, that I got, inshallah

#get the real name of the user running the script
#($USER) from field 5 of the password file
#and remember that when you look in the password file #you must exactly match field 1 or if you are
#using NIS, then you must exactly match the username

#Also remember that you can get false positive matches #if you are not careful. For example
#say you had these usernames maryjane, mary, and #maryann, and you were were looking for mary, if your
#matching is not right, you may also match maryjane #and maryann

for each username listed from positional parameters
    do
    if the username exists in the password file or NIS password (see note above about maching)
                then
                if the username is logged in (see not above about matching)
                        then
                    send the mail message
            else
                     print a message that the username is not logged into the system
                         endif
        else
                print a message that the username does not exist
                endif


    done
And here's what I've been able to gen up.
Code:
#! /bin/sh -xv

USER="getent passwd `whoami` | cut -d ':' -f5 | cut -d ',' -f1"

	#if there are no POSIT PARAMS, i.e.
	#usernames, listed, print an error 
	#MSG and bounce out
	if [ "$1" -eq 0 ]
		then
		echo "no user specified"
	fi

	#I want to protect against false positives,
	#e.g. don't match maryjane or maryann to 
	#mary
		for user
			do
			case $1 in
			#this matches ONLY the correct username
			"")
				if who | cut -c1-8 | sed 's/ .*//g' | sort -u | grep -w $1 > /dev/null
					then
					echo "$1 is logged in"
					mail "$1" << message
				Hello `awk -F: '{print $5}' /etc/passwd`. 
				This e-mail was generated by `whoami`. My instructor requires that I send this message as part of an assignment for class 90.321. The current time and date is `date`. Have a nice day.

					Sincerely,
					$USER
					END
				fi
				;;
			#this matches examples maryjane or maryann
			*$1|$1*)
				echo "$1 is not logged in"
				;;
			#And now we're matching everything else, and I don't care about them
			*)
				echo "$1 does not exist"
				;;
			esac
			done

	else
		echo "$1 not logged in"
	fi
done
If I post this much code, does it get cumbersome for others to read? Thanks for the help.
 
Old 03-15-2014, 01:46 PM   #2
Ser Olmy
Senior Member
 
Registered: Jan 2012
Distribution: Slackware
Posts: 3,340

Rep: Reputation: Disabled
I don't see you parsing arguments beyond $1 anywhere, and I don't quite see why you'd need explicit logic to check against partially matching usernames. getent passwd <user> will return the relevant user details if and only if the user exists. Otherwise, there will be no output and the exit code will be non-zero.

Same goes for the who command. The first field contains the username, and can easily be isolated with cut or sed, as a username can never contain spaces.

I'd probably just run a check on $1 against getent passwd to see if the user exists, then check again against who | cut -d " " -f 1 to see if the user is logged in:
Code:
#!/bin/bash

if [[ "$1" == "" ]]; then
  echo Usage: $0 \<user1\> \[\<user2\> \[...\]\]
  exit 1
fi

while [[ ! "$1" == "" ]]; do
  if ! getent passwd $1 > /dev/null ; then
    # no such user
  else
    if who | cut -d " " -f 1 | grep "^$1\$" > /dev/null; then
      # user is logged in, send mail here
    else
      # user is not currently logged in
    fi
  fi
  shift
done
(As you can see, I just use shift to get the next command line argument until I run out of data.)

Last edited by Ser Olmy; 03-15-2014 at 01:49 PM.
 
1 members found this post helpful.
Old 03-15-2014, 05:00 PM   #3
boygenuis
Member
 
Registered: Oct 2007
Location: The Fire Swamp
Distribution: SUSE 12.3, Fuduntu, Fedora 18, Ubuntu 12.04
Posts: 39

Original Poster
Rep: Reputation: 26
So, using shift runs through all the users put into the command line? If I'm interpreting that correctly.

I'm also not grasping some of the code you're using. IDK if it's just a simple difference between bash and sh (the [[ as opposed to [), but I'd like to understand it better. For instance, this first bit:
Code:
echo Usage: $0 \<user1\> \[\<user2\> \[...\]\]
We're not quoting the Usage: why? I'm not familiar with it as a command. And then I don't get why we run through the users like we do. \<user1>\ would make sense to me, cuz we're quoting the value of user1, but I'm at a loss with how you do it. And I'm also confused by how we run through users2 - whatever...No, I think that makes sense. I wouldn't have thought of it on my own, I guess.

I'm also lost-in-the-sauce on this loop.
Code:
while [[ ! "$1" == "" ]]; do
  if ! getent passwd $1 > /dev/null ; then
I don't get why the exclamation point comes before positional parameter $1, as we want to check that it doesn't equal null. And then, is the exclamation point in the if-statement an error and we should put brackets?

Yeah, man. I'm just all-around lost in this one. It's a strong lesson in humility, right?
 
Old 03-15-2014, 05:37 PM   #4
Ser Olmy
Senior Member
 
Registered: Jan 2012
Distribution: Slackware
Posts: 3,340

Rep: Reputation: Disabled
Quote:
Originally Posted by boygenuis View Post
For instance, this first bit:
Code:
echo Usage: $0 \<user1\> \[\<user2\> \[...\]\]
That was just me creating a simple "help" message to be displayed if the batch file is called without any argument. The echo command simply writes everything to the screen, but since the text contains characters that have special meaning to the shell (like >, <, [ and ]), I had escape them with backslashes.

Quote:
Originally Posted by boygenuis View Post
I'm also lost-in-the-sauce on this loop.
Code:
while [[ ! "$1" == "" ]]; do
  if ! getent passwd $1 > /dev/null ; then
I don't get why the exclamation point comes before positional parameter $1, as we want to check that it doesn't equal null. And then, is the exclamation point in the if-statement an error and we should put brackets?
The ! is a general negation operator. Sometimes "is not equal" may be slightly easier to read than "is unequal". For instance, here are two versions of the same test:
Code:
if [ "foo" != "bar" ]; then
  echo The strings are not equal.
fi

if [ ! "foo" == "bar" ]; then
  echo The strings are not equal.
fi
I tend to use negation a lot rather than switching to the "is not equal" comparison operator, but it's really a matter of personal taste.

Anyway, the main loop in the script is this:
Code:
while [[ ! "$1" == "" ]]; do
   # stuff
   shift
done
The idea is pretty simple: We loop while $1 is not equal to "" (nothing). At the end of the loop, $1 gets shifted into $0 (the original $0 is lost) and the new value of $1 is whatever was held in $2. We do this until an empty value is shifted into $1, which means we've run out of command-line arguments.

The shift command shuffles the contents of the command line variables one step "to the left", that is, $0 becomes $1, $1 becomes $2 and so on, and $9 becomes whatever was the 10th argument (if that many arguments were given).

As for the if statement, the basic statement is this:
Code:
if command; then something
If you've never encountered that syntax, it may certainly look confusing. What it actually means, is "if command returns an exit code of 0, then something". I'm exploiting the fact that commands return an exit code of 0 if the operation completed successfully (whatever that means in the context of any given command).

getent passwd <user> returns 0 if it's able to find the account <user> in the user database. Try this:
Code:
if getent passwd root ; then echo The root account exists ; fi
Replace the "root" argument to getent passwd with a non-existent account and you'll see that the "then" part doesn't get executed.

In the script I used an exclamation mark to invert the result, so:
Code:
if ! getent passwd $1 > /dev/null ; then
...really means "if the command getent passwd $1 does not returns an exit code of zero, meaning the account doesn't exist, do <whatever>". Since the getent command will generate output if it does find the account, I redirect all output to /dev/null.

(The "!" actually works on the command line as well. If you run ls (which is exceedingly likely to succeed) and then read the exit code with echo $?, you'll get zero. Now try it with ! ls.)
 
Old 03-16-2014, 11:07 AM   #5
boygenuis
Member
 
Registered: Oct 2007
Location: The Fire Swamp
Distribution: SUSE 12.3, Fuduntu, Fedora 18, Ubuntu 12.04
Posts: 39

Original Poster
Rep: Reputation: 26
I'm not gonna lie, it is mind bottling how many different ways there are to write a script. Thanks for the instruction, brother.
 
  


Reply

Tags
homework, mail, matching



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:31 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration