|
Page 3 of 3 Finally, here is menu.c, the main program file for the menu application. This reads in the menu configuration file, displays a text-based menu on screen, prompts the user for input, then performs the appropriate command with privilege elevation if required.
/*
* Simple menu program
*
* David M. Williams
*/
#include "menu.h"
// ----------------------------------------------------------------------------
int main (int argc, char **argv)
{
char *username;
char *password;
int access = -1;
ScriptTree theMenu = NULL;
#ifdef DISABLE_INTERRUPTS
signal (SIGINT, SIG_IGN);
#endif
username = (char *) malloc (sizeof (char) * 50);
password = (char *) malloc (sizeof (char) * 10);
// Ask for a login
login (username, password);
// Verify username and password, getting access level
if (verify (username, password, &access) < 0)
noAccess (username);
else
{
// Generate a list of menu options
buildMenu (access, &theMenu);
// Repeatedly display menu and process input
DoMenu (username, theMenu, 0);
// Tidy up
}
printf ("\nBye.\n");
free (username);
free (password);
Destroy (theMenu);
}
// ----------------------------------------------------------------------------
void clrscrn ()
{
#ifdef CLEAR_SCREEN
system ("/bin/clear");
#endif
}
// ----------------------------------------------------------------------------
void login (char *username, char *password)
{
char tempPassword [10];
clrscrn ();
#ifdef BANNER
if (strlen (BANNER) > 0)
puts (BANNER);
#endif
printf (" Login: ");
scanf ("%s", username);
#ifdef HIDE_PASSWORD
strcpy (tempPassword, getpass ("Password: "));
#else
printf ("Password: ");
scanf ("%s", tempPassword);
#endif
log ("Login attempt by %s\t%s\n", username, tempPassword);
strcpy (password, crypt (tempPassword, username));
}
// ----------------------------------------------------------------------------
void noAccess (char *username)
{
clrscrn ();
printf ("%s, you do not have permission to access this system\n"
"or your password was wrong.\n", username);
}
// ----------------------------------------------------------------------------
int verify (char *username, char *password, int *access)
{
FILE *fp;
int Found = 0;
char line [80];
char tempUser [50];
char tempPass [10];
int tempAccess;
*access = -1;
if ((fp = fopen (USERLIST, "r")) > 0)
{
while ((!Found) && (!feof (fp)))
{
fgets (line, 80, fp);
if ((line [0] != '\n') && (line [0] != '#'))
{
sscanf (line, "%s%s%d", tempUser, tempPass,
&tempAccess);
if ((strcmp (tempUser, username) == 0) &&
(strcmp (tempPass, password) == 0))
{
Found = 1;
*access = tempAccess;
}
}
}
fclose (fp);
}
else
log ("Cannot open %s\n", USERLIST);
log ("%s has an access level of %d\n", username, *access);
return *access;
}
// ----------------------------------------------------------------------------
void buildMenu (int access, ScriptTree *theMenu)
{
FILE *fp;
char *line;
char *line2;
char *scriptName;
char *LineType;
int userLevel;
int useSudo;
ScriptTree subMenu;
line = (char *) malloc (sizeof (char) * 80);
line2 = (char *) malloc (sizeof (char) * 80);
scriptName = (char *) malloc (sizeof (char) * 80);
LineType = (char *) malloc (sizeof (char) * 10);
subMenu = *theMenu;
if ((fp = fopen (MENULIST, "r")) > 0)
{
while (!feof (fp))
{
line [0] = '#';
while (((line [0] == '\n') || (line [0] == '#')) &&
(!feof (fp)))
fgets (line, 80, fp);
line2 [0] = '#';
while (((line2 [0] == '\n') || (line2 [0] == '#')) &&
(!feof (fp)))
fgets (line2, 80, fp);
if (!feof (fp))
{
sscanf (line, "%s", LineType);
if (strcmp (LineType, "Menu") == 0)
{
sscanf (line, "%s%d", LineType,
&userLevel);
if (userLevel <= access)
subMenu = AddMenu
(theMenu, line2);
}
else if (strcmp (LineType, "Submenu") == 0)
{
sscanf (line, "%s%d", LineType,
&userLevel);
if (userLevel <= access)
subMenu = AddMenu
(&subMenu, line2);
}
else if (strcmp (LineType, "Option") == 0)
{
sscanf (line, "%s%d%d%s", LineType,
&userLevel, &useSudo,
scriptName);
if (userLevel <= access)
AddNode (&subMenu, line2,
scriptName, useSudo);
}
}
}
fclose (fp);
}
else
log ("Cannot open %s\n", MENULIST);
#ifdef DEBUGGING
DumpMenu (0, *theMenu);
exit (0);
#endif
free (line);
free (line2);
free (scriptName);
free (LineType);
}
// ----------------------------------------------------------------------------
void DoMenu (char *username, ScriptTree theMenu, int InSub)
{
int DoExit = 0;
int userChoice;
int MenuItems;
while (!DoExit)
{
// Display the menu
MenuItems = DisplayMenu (theMenu, InSub);
// Get input
userChoice = getChoice (MenuItems);
// Process command
if (userChoice == 0)
DoExit = 1;
else
ProcessChoice (userChoice, theMenu, username, InSub);
}
}
// ----------------------------------------------------------------------------
ScriptTree AddMenu (ScriptTree *theMenu, char *ItemText)
{
// Make a new node
ScriptTree aNode;
aNode = (ScriptTree) malloc (sizeof (ScriptNode));
strcpy (aNode->MenuText, ItemText);
strcpy (aNode->ScriptName, "");
aNode->Next = NULL;
aNode->Submenu = NULL;
// Find the last node in the list and set its next pointer to this node.
if (*theMenu == NULL)
*theMenu = aNode;
else
{
ScriptTree iterator = *theMenu;
while (iterator->Submenu != NULL)
iterator = (void *) iterator->Submenu;
iterator->Submenu = aNode;
}
return aNode;
}
// ----------------------------------------------------------------------------
void AddNode (ScriptTree *theMenu, char *ItemText,
char *ScriptCommand, int UseSudo)
{
// Make a new node
ScriptTree aNode;
aNode = (ScriptTree) malloc (sizeof (ScriptNode));
strcpy (aNode->MenuText, ItemText);
strcpy (aNode->ScriptName, ScriptCommand);
aNode->RunAsRoot = UseSudo;
aNode->Next = NULL;
aNode->Submenu = NULL;
// Find the last node in the list and set its next pointer to this node.
if (*theMenu == NULL)
*theMenu = aNode;
else
{
ScriptTree iterator = *theMenu;
while (iterator->Next != NULL)
iterator = (void *) iterator->Next;
iterator->Next = aNode;
}
}
// ----------------------------------------------------------------------------
void Destroy (ScriptTree theMenu)
{
ScriptTree iterator = theMenu;
if (iterator != NULL)
{
Destroy (iterator->Next);
Destroy (iterator->Submenu);
free (iterator);
}
}
// ----------------------------------------------------------------------------
void DoCommand (char *username, char *ScriptName, int UseSudo)
{
char c = ' ';
char FullPath [PATH_MAX];
puts ("\n\n");
log ("%s is running %s %s sudo\n", username, ScriptName,
(UseSudo ? "with" : "without"));
if (strlen (ScriptName) > 0)
{
sprintf (FullPath, "%s/%s", SCRIPTSDIR, ScriptName);
if (fork () == 0)
{
#ifdef USE_EXECL
if (UseSudo)
execl (SUDO, SUDO, FullPath, NULL);
else
execl (FullPath, FullPath, NULL);
#else
if (UseSudo)
{
char SudoCmnd [PATH_MAX];
sprintf (SudoCmnd, "%s %s", SUDO, FullPath);
system (SudoCmnd);
}
else
system (FullPath);
#endif
exit (0);
}
#ifdef USE_EXECL
else
{
int status;
wait3 (&status, NULL, (struct rusage *) 0);
}
#endif
}
// Wait for a key to be pushed
printf ("\n\n\tPlease press return : ");
while (c != '\n')
c = getchar ();
}
// ----------------------------------------------------------------------------
void log (const char *format, ...)
{
#ifdef LOGGING_ENABLED
va_list args;
char logmsg [255];
FILE *fp;
time_t now;
char nowtime [30];
va_start (args, format);
vsprintf (logmsg, format, args);
if ((fp = fopen (LOGFILE, "a")) > 0)
{
time (&now);
strcpy (nowtime, ctime (&now));
nowtime [strlen (nowtime) - 1] = '\0';
fprintf (fp, "%s\t%s", nowtime, logmsg);
fclose (fp);
}
va_end (args);
#endif
}
// ----------------------------------------------------------------------------
int DisplayMenu (ScriptTree theMenu, int InSub)
{
int MenuItems = 0;
ScriptTree iterator;
clrscrn ();
if (!InSub)
puts ("\tAdministrative services main menu");
else
printf ("\tAdministative sub-menu\n\t%s", theMenu->MenuText);
puts ("\n\n");
if (!InSub)
puts ("\t0)\tExit the program\n");
else
puts ("\t0)\tExit this menu level\n");
if (theMenu != NULL)
{
if (!InSub)
{
MenuItems = 1;
printf ("\t1)\t%s", theMenu->MenuText);
}
if (!InSub)
{
iterator = (void *) theMenu->Submenu;
while (iterator != NULL)
{
MenuItems++;
printf ("\t%d)\t%s", MenuItems,
iterator->MenuText);
iterator = (void *) iterator->Submenu;
}
}
else
{
iterator = (void *) theMenu->Next;
while (iterator != NULL)
{
MenuItems++;
printf ("\t%d)\t%s", MenuItems,
iterator->MenuText);
iterator = (void *) iterator->Next;
}
}
}
return MenuItems;
}
// ----------------------------------------------------------------------------
int getChoice (int MenuItems)
{
int userChoice = -1;
char temp [5];
char c = ' ';
do
{
printf ("\n\t\tChoice (0-%d) : ", MenuItems);
scanf ("%s", temp);
userChoice = atoi (temp);
} while ((userChoice < 0) || (userChoice > MenuItems));
// Consume all remaining input
while (c != '\n')
c = getchar ();
return userChoice;
}
// ----------------------------------------------------------------------------
void ProcessChoice (int userChoice, ScriptTree theMenu, char *username,
int InSub)
{
int itemNum = 0;
ScriptTree iterator = theMenu;
ScriptTree theChoice = NULL;
if (!InSub)
{
if (userChoice == 1)
theChoice = theMenu;
else
itemNum = 1;
}
if ((theChoice == NULL) && (!InSub))
{
iterator = (void *) theMenu->Submenu;
while ((iterator != NULL) && (theChoice == NULL))
{
itemNum++;
if (userChoice == itemNum)
theChoice = iterator;
else
iterator = (void *) iterator->Submenu;
}
}
if ((theChoice == NULL) && (InSub))
{
iterator = (void *) theMenu->Next;
while ((iterator != NULL) && (theChoice == NULL))
{
itemNum++;
if (userChoice == itemNum)
theChoice = iterator;
else
iterator = (void *) iterator->Next;
}
}
if (theChoice == NULL)
puts ("\nInvalid choice.\n");
else
{
if (strcmp (theChoice->ScriptName, "") != 0)
DoCommand (username, theChoice->ScriptName,
theChoice->RunAsRoot);
else
DoMenu (username, theChoice, 1);
}
}
// ----------------------------------------------------------------------------
void DumpMenu (int level, ScriptTree theMenu)
{
ScriptTree iterator;
if (theMenu != NULL)
{
indent (level);
printf ("%d\t%s", level, theMenu->MenuText);
level++;
iterator = (void *) theMenu->Next;
while (iterator != NULL)
{
indent (level);
printf ("%d\t%s", level, iterator->MenuText);
iterator = (void *) iterator->Next;
}
level--;
iterator = (void *) theMenu->Submenu;
while (iterator != NULL)
{
DumpMenu (level, iterator);
iterator = (void *) iterator->Submenu;
}
}
}
// ----------------------------------------------------------------------------
void indent (int level)
{
int i;
for (i = 0; i < level * 2; i++)
putchar (' ');
}
Get stories like this delivered daily - FREE - subscribe now
<< First page < 1 2 3 Next page > Last page - Post your comment >> |