5.6 Exercise: Biffing

Team-FLY

Some systems have a facility called biff that enables mail notification. When a user who is logged in receives mail, biff notifies the user in some way (e.g., beeping at the terminal or displaying a message). UNIX folklore has it that biff 's original author had a dog named Biff who barked at mail carriers .

Program 5.4 shows the code for a C program called simplebiff.c that beeps at the terminal at regular intervals if the user ostudent has pending mail. The program beeps by sending a Ctrl-G (ASCII 7) character to standard error. Most terminals handle the receipt of Ctrl-G by producing a short beep. The program continues beeping every 10 seconds, until it is killed or the mail file is removed. This simple version assumes that if the mail file exists, it has mail in it. On some systems the mail file may exist but contain zero bytes when there is no mail. Program 8.10 on page 281 gives a version that does not have this problem.

Example 5.27

The following command starts simplebiff .

 simplebiff & 

The & tells the shell to run simplebiff in the background so that ostudent can do something else.

Exercise 5.28

What happens if you execute the command of Example 5.27 and then log off?

Answer:

The simplebiff program continues to run after you log off, since it was started in the background. Execute ps -a to determine simplebiff 's process ID. Kill the simplebiff process by entering the command kill -KILL pid . Make sure simplebiff is gone by doing another ps -a .

Program 5.4 simplebiff.c

A simple program to notify ostudent of pending mail .

 #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #define MAILFILE "/var/mail/ostudent" #define SLEEPTIME 10 int main(void) {    int mailfd;    for( ; ; ) {       if ((mailfd = open(MAILFILE, O_RDONLY)) != -1) {          fprintf(stderr, "%s", " 
 #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #define MAILFILE "/var/mail/ostudent" #define SLEEPTIME 10 int main(void) { int mailfd; for( ; ; ) { if ((mailfd = open (MAILFILE, O_RDONLY)) != -1) { fprintf(stderr, "%s", "\007"); while ((close(mailfd) == -1) && (errno == EINTR)) ; } sleep(SLEEPTIME); } } 
7"); while ((close(mailfd) == -1) && (errno == EINTR)) ; } sleep(SLEEPTIME); } }

Mail is usually stored in a file in the /var/mail or /var/spool/mail directory. A file in that directory with the same name as the user's login name contains all unread mail for that user. If ostudent has mail, an open of /var/mail/ostudent succeeds; otherwise , the open fails. If the file exists, the user has unread mail and the program beeps. In any case, the program sleeps and then repeats the process indefinitely.

Exercise 5.29

Run Program 5.4 after replacing the user name and mail directory names so that they are appropriate for your system.

Program 5.4 is not very general because the user name, mail directory and sleep time are hardcoded. In addition, the stat function provides more information about a file without the overhead of open .

Exercise 5.30

Modify Program 5.4 to use stat instead of open .

Exercise 5.31

On some systems, a user's new mail file always exists but has zero bytes if the user has no mail. Modify simplebiff to account for this case.

The POSIX-approved way of getting the user name is to call getuid to find out the user ID and then call getpwuid to retrieve the user's login name. The getpwuid function takes the user's numerical ID as a parameter and retrieves a passwd structure that has the user's name as a member.

  SYNOPSIS  #include <pwd.h>    struct passwd *getpwuid(uid_t uid);  POSIX  

If unsuccessful , getpwuid returns a NULL pointer and sets errno .

The struct passwd structure is defined in pwd.h . The POSIX base definition specifies that the struct passwd structure have at least the following members .

 char   *pw_name      /* user's login name */ uid_t  pw_uid        /* numerical user ID */ gid_t  pw_gid        /* numerical group ID */ char   *pwd_dir      /* initial working directory */ char   *pw_shell     /* program to use as shell */ 
Exercise 5.32

Find out the base directory name of the directory in which unread mail is stored on your system. (The base directory in Program 5.4 is /var/mail/ .) Construct the pathname of the unread mail by concatenating the base mail directory and the program's user name. Use getuid and getpwuid in combination to determine the user name at run time.

The directory used for mail varies from system to system, so you must determine the location of the system mail files on your system in order to use simplebiff . A better version of the program would allow the user to specify a directory on the command line or to use system-specific information communicated by environment variables if this information is available. The POSIX:Shell and Utilities standard specifies that the sh shell use the MAIL environment variable to determine the pathname of the user's mail filefor the purpose of incoming mail notification. The same standard also specifiesthat the MAILCHECK environment variable be used to specify how often (in seconds) the shell should check for the arrival of new messages for notification. The standard states that the default value of MAILCHECK should be 600.

Exercise 5.33

Rewrite Program 5.4 so that it uses the value of MAILCHECK for the sleep time if that environment variable is defined. Otherwise, it should use a default value of 600.

Exercise 5.34

Rewrite your program of Exercise 5.33 so that it uses the value passed on the command line as the pathname for the user's mailbox. If simplebiff is called with no command-line arguments, the program should use the value of the MAIL environment variable as the pathname. If MAIL is undefined and there were no command-line arguments, the program should use a default path of /var/mail/user . Use the method of Exercise 5.32 to find the value of user .

Exercise 5.35

Rewrite Program 5.4 so that it has the following synopsis.

 simplebiff [-s n] [-p pathname] 

The [ ] in the synopsis indicates optional command-line arguments. The first command-line argument specifies a sleep interval. If -s n is not provided on the command line and MAILCHECK is not defined, use thevalue of SLEEPTIME as a default. The -p pathname specifies a pathname for the system mail directory. If this option is not specified on the command line, use the MAIL environment variable value as a default value. If MAIL is not defined, use the MAILFILE defined in the program. Read the man page for the getopt function and use it to parse the command-line arguments.

Team-FLY


Unix Systems Programming
UNIX Systems Programming: Communication, Concurrency and Threads
ISBN: 0130424110
EAN: 2147483647
Year: 2003
Pages: 274

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net