|
Page 2 of 3 I’ll leave the main program code – menu.c – right to the last page. The two configuration files needed are the list of users and authorisation levels, and the menu definition itself.
The list of users is defined in user.list with a username, an encrypted password, and a privilege level.
#
# username password access (0 is lowest)
#
# Blank lines and lines beginning with a '#' are treated as comments
davidw daDDC5rpKNN5c 5
fred frL8GUupUeU6A 1
The passwords can be generated using this simple program which calls the Linux crypt API function. As this is intended only for internal use it is extremely simple and doesn’t have any error checking. If you require usernames of more than 50 characters or passwords of more than 10 characters then you ought to change the code below or else a buffer overrun will occur.
#include <crypt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main ()
{
char *username;
char *password;
username = (char *) malloc (sizeof (char) * 50);
password = (char *) malloc (sizeof (char) * 10);
printf (" Login: ");
scanf ("%s", username);
strcpy (password, getpass ("Password: "));
printf ("Encrypted password is %s\n", crypt (password, username));
free (username);
free (password);
}
The menu is defined in menu.list and this has a more complex structure. Each line defines either a submenu or a genuine command. Commands provide the name of a program to be invoked as well as a flag indicating if super-user access is necessary for that program. Whether a submenu or a command, a minimum access level is given.
# Menu configuration file
#
# Blank lines and lines beginning with a '#' are treated as comments
#
# Lines beginning with 'Menu' indicate a new main menu entry
# These lines will also specify the access level required for entry to
# that menu option, and the following line will contain a textual description
# to be displayed.
#
# Lines that begin with 'Option' indicate an entry for the current menu
# item. These lines will also specify the access level required to use the
# item, whether the item requires root privileges (1 = yes) and the name of
# the script to run. The following line contains the textual description to
# be displayed.
#
# The scripts are all prefixed with the SCRIPTDIR prefix (from menu.h)
#
# Scripts must handle parameters and crashes themselves
Menu 3
Manage mail boxes
Option 3 1 viEditMailBox
Edit a specified mail box using vi
Option 3 1 EditMailBox
Read (and manage) a specified mail box
Menu 1
Testing stuff
Option 1 0 sayHi
Say Hi
Option 1 0 testRead
Read a number
Menu 1
Passwords
Option 1 1 chmenupass
Change password for this menu system
From here on in the rest is simple. All functionality can be implemented as simple, individual, stand-alone scripts. For instance, to allow staff to view a mailbox the following can be used:
#!/bin/sh
MAILPATH=/var/spool/mail
echo -n "What is the name of the mailbox to list? "
read MailBoxName
if [ -r $MAILPATH/$MailBoxName ]; then
Mail -f $MAILPATH/$MailBoxName
else
echo No such mailbox
fi
Instead, however, to let the help desk users edit and modify a mailbox, the following will work:
#!/bin/sh
MAILPATH=/var/spool/mail
echo -n "What is the name of the mailbox to edit? "
read MailBoxName
if [ -r $MAILPATH/$MailBoxName ]; then
/bin/vi $MAILPATH/$MailBoxName
else
echo No such mailbox
fi
The functionality need not be constrained to shell scripts, or indeed trite programs. Here’s one example of something more complex, namely adding new items to the end of the reverse DNS ARPA file, which is something web hosting services routinely require.
/*
* arg 1 is the name of the Web node to create,
* arg 2 is the full path of the ARPA file
* returns an IP address
*/
#define SENTINEL "# New entries will be placed here - do not remove this line\n"
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
int main (int argc, char **argv)
{
FILE *Infp;
FILE *Outfp;
char line [80];
char ArpaFile [PATH_MAX];
char TmpFile [PATH_MAX];
int LastIp = 0;
int NewIp = -1;
if (argc != 3)
{
fprintf (stderr, "Bad parameters\n");
exit (1);
}
// Open the ARPA file and make a temporary file for writing
strcpy (ArpaFile, argv [2]);
strcpy (TmpFile, ArpaFile);
strcat (TmpFile, ".tmp");
if ((Infp = fopen (ArpaFile, "r")) <= 0)
{
fprintf (stderr, "Cannot open %s\n", ArpaFile);
exit (1);
}
if ((Outfp = fopen (TmpFile, "w")) <= 0)
{
fprintf (stderr, "Cannot write to %s\n", TmpFile);
fclose (Infp);
exit (1);
}
// Copy every line from the ARPA file to the temporary file
// If the line begins with a number, grab it as it is an IP address
// If the line is our SENTINEL line then insert a new line with a new IP
// address for the Web node specified.
while (!feof (Infp))
{
fgets (line, 80, Infp);
if (strcmp (line, SENTINEL) == 0) // Add our line
{
NewIp = LastIp + 1;
fprintf (Outfp, "%-d\t\tIN\tPTR\t%s\n", NewIp,argv [1]);
}
else if (isdigit (line [0]))
sscanf (line, "%d", &LastIp);
fprintf (Outfp, "%s", line);
}
fclose (Infp);
fclose (Outfp);
if (NewIp == -1)
{
fprintf (stderr, "Could not find sentinel line.\n");
unlink (TmpFile);
exit (0);
}
// Copy the new file back over the original arpa file
rename (TmpFile, ArpaFile);
printf ("192.168.1.%-d", NewIp);
exit (0);
}
CONTINUED
|