PROGRAM 4
/*************************************************************************/
/* file name: prog4.c */
/* brief description: process launcher */
/* name: anthony f. ortiz */
/* assignment number: 4 */
/* class: cs3560-01 */
/* quarter: spring */
/* date completed: june 5, 1997 */
/* date compiled: june 5, 1997 */
/* version of compiler: csuh compiler */
/*************************************************************************/
/*****************************************************************************/
/* this program acts as a interactive process launcher. up to 5 processes */
/* can be createdd at any one time. the parent maintains a list of its */
/* children and displays information about them on the screen. the children */
/* do calculations and return via pipes. */
/*****************************************************************************/
/* headers */
#include
#include
#include
#include
/* important variables and structures of this program */
int max = 5;
int current = 0;
int parent;
int flag = 0;
int fd [2], fd2 [2];
char g_buf [10];
struct pcb
{
int pid;
char status [8];
}
children [5];
/* procedures and functions */
void print_menu ();
void print_children ();
void print_message ();
void print_choice ();
void initialize_pcb ();
char get_action ();
void perform_action (char action);
void move_pointer (char action);
void move_forward ();
void move_backward ();
void launch_process ();
void kill_process ();
void update_screen ();
void stop_process ();
void resume_process ();
void quit_program ();
void redraw_screen ();
void display_ps ();
void tell_child ();
void signal_handler ();
void clear_screen ();
/* main program */
void main ()
{
char action;
signal (SIGUSR1, signal_handler);
initscr ();
crmode ();
noecho ();
nonl ();
pipe (fd);
pipe (fd2);
parent = getpid ();
print_menu ();
print_children ();
print_message ();
print_choice ();
initialize_pcb ();
do
{
if (parent == getpid ())
{
action = get_action ();
perform_action (action);
}
}
while (action != 'Q');
endwin ();
}
/* print the program menu. */
void print_menu ()
{
clear ();
move (1, 1);
printw ("--process control menu--------------------------------------");
refresh ();
move (2, 1);
printw ("L)aunch S)top R)esume K)ill N)ext P)status T)ell Q)uit");
refresh ();
move (3, 1);
printw ("C)lear & redraw 0-4) moves pointer: ");
refresh ();
move (4, 1);
printw ("------------------------------------------------------------");
refresh ();
}
/* print the initial screen (open slots). */
void print_children ()
{
int i;
for (i = 0; i < max; i++)
{
move (7 + i, 8);
printw ("slot: %d ", i);
refresh ();
move (7 + i, 16);
printw ("open -----------------------------------");
refresh ();
}
move (7, 1);
printw ("----->");
refresh ();
move (12, 1);
printw ("------------------------------------------------------------");
refresh ();
}
/* print initial message screen. */
void print_message ()
{
move (13, 1);
printw ("special message: ");
refresh ();
move (14, 1);
printw ("------------------------------------------------------------");
refresh ();
move (24, 1);
printw ("------------------------------------------------------------");
refresh ();
}
/* get one of the menu actions. */
void print_choice ()
{
move (5, 1);
printw ("enter a choice: ");
refresh ();
move (6, 1);
printw ("------------------------------------------------------------");
refresh ();
}
/* initilize the children processes. */
void initialize_pcb ()
{
int i;
for (i = 0; i < max; i++)
{
children [i].pid = 0;
strcpy (children [i].status, "-------");
}
}
/* get a menu action. */
char get_action ()
{
char action;
action = mvgetch (5, 17);
refresh ();
return action;
}
/* perform an action from the menu. */
void perform_action (char action)
{
switch (action)
{
case 'L': launch_process ();
break;
case 'S': stop_process ();
break;
case 'R': resume_process ();
break;
case 'N': move_backward ();
break;
case 'n': move_forward ();
break;
case 'K': kill_process ();
break;
case 'P': display_ps ();
break;
case 'T': tell_child ();
break;
case 'Q': quit_program ();
break;
case 'C': redraw_screen ();
break;
case '0':
case '1':
case '2':
case '3':
case '4': move_pointer (action);
break;
}
}
/* move pointer to one of children's slots (0-4). */
void move_pointer (char action)
{
move (7 + current, 1);
printw (" ");
refresh ();
current = action - 48;
move (7 + current, 1);
printw ("----->");
refresh ();
}
/* move the pointer forwards. */
void move_forward ()
{
char move;
if (current == 4)
{
move = '0';
move_pointer (move);
}
else
{
move = 48 + current + 1;
move_pointer (move);
}
}
/* move the pointer backwards. */
void move_backward ()
{
char move;
if (current == 0)
{
move = '4';
move_pointer (move);
}
else
{
move = 48 + current - 1;
move_pointer (move);
}
}
/* launch a new process. */
void launch_process ()
{
int apid, i;
char move;
int result, n, n1, n2, fd [2];
char operation, line [10];
for (i = 0; i < max; i++)
{
if (children [i].pid == 0)
{
move = 48 + i;
move_pointer (move);
break;
}
}
if (i == max)
{
move (13, 20);
printw ("there are too many processes. ");
refresh ();
}
else
{
if ((apid = fork ()) > 0)
{
children [current].pid = apid;
strcpy (children [current].status, "ready ");
update_screen ();
refresh ();
}
else
{
while (1) {}
}
}
}
/* terminate a process. */
void kill_process ()
{
if (children [current].pid == 0)
{
move (13, 20);
printw ("this process is already dead or never created.");
refresh ();
}
else
{
kill (children [current].pid, SIGTERM);
children [current].pid = 0;
strcpy (children [current].status, "-------");
update_screen ();
}
}
/* update the screen. */
void update_screen ()
{
if (children [current].pid == 0)
{
move (7 + current, 16);
printw ("open -----------------------------------");
refresh ();
}
else
{
move (7 + current, 16);
printw ("pid: %d ", children [current].pid);
refresh ();
move (7 + current, 27);
printw ("status: %s ", children [current].status);
refresh ();
}
}
/* stop a process. */
void stop_process ()
{
if (strcmp (children [current].status, "stopped") == 0)
{
move (13, 20);
printw ("this process is already stopped. ");
refresh ();
}
else if (strcmp (children [current].status, "ready ") == 0)
{
kill (children [current].pid, SIGSTOP);
strcpy (children [current].status, "stopped");
update_screen ();
}
else if (strcmp (children [current].status, "-------") == 0)
{
move (13, 20);
printw ("this process is not created. ");
refresh ();
}
}
/* make a stopped process resume. */
void resume_process ()
{
if (strcmp (children [current].status, "stopped") == 0)
{
kill (children [current].pid, SIGCONT);
strcpy (children [current].status, "ready ");
update_screen ();
}
else if (strcmp (children [current].status, "ready ") == 0)
{
move (13, 20);
printw ("this process is not stopped. ");
refresh ();
}
else if (strcmp (children [current].status, "-------") == 0)
{
move (13, 20);
printw ("this process is not created. ");
refresh ();
}
}
/* quit the program (make sure all children processes are terminated). */
void quit_program ()
{
int i;
for (i = 0; i < max; i++)
{
if (strcmp (children [i].status, "-------") == 1)
{
kill (children [i].pid, SIGTERM);
}
}
}
/* redraw the screen (in case it gets messed up). */
void redraw_screen ()
{
int i;
char move;
print_menu ();
print_children ();
print_message ();
print_choice ();
for (i = 0; i < max; i++)
{
move = 48 + i;
move_pointer (move);
update_screen ();
}
clear_screen ();
}
/* display the ps command on the screen. */
void display_ps ()
{
char line [80];
FILE *infile, *outfile;
int count = 0;
char ch;
if ((infile = popen ("ps -ef", "r")) == NULL)
{
move (13, 20);
printw ("there is an error in opening the file ");
refresh ();
}
else
{
while (fgets (line, 80, infile) != NULL)
{
if (count == 8)
{
move (15 + count, 1);
printw ("press enter key to continue. ");
ch = getch ();
count = 0;
}
move (15 + count, 1);
printw (" %s ", line);
refresh ();
count++;
}
if (pclose (infile) == - 1)
{
move (13, 20);
printw ("there is a error in closing the file. ");
refresh ();
}
}
}
/* send a message to the child in the form (num num operation) and have the
child do a calculation, and then send it back to the parent. */
void tell_child ()
{
int n;
char message [20];
if (strcmp (children [current].status, "ready ") == 0)
{
strcpy (children [current].status, "busy ");
update_screen ();
move (20, 1);
kill (parent, SIGUSR1);
kill (children [current].pid, SIGUSR1);
move (13, 20);
printw ("%s ", message);
refresh ();
n = read (fd2 [0], message, 20);
move (13, 20);
printw (message);
refresh ();
strcpy (children [current].status, "ready ");
update_screen ();
}
else
{
move (13, 20);
printw ("the child process is not in the ready state. ");
refresh ();
}
}
/* signal handler for parent and child */
void signal_handler ()
{
int n, n1, n2, result;
char line [20], operation;
signal (SIGUSR1, signal_handler);
if (getpid () == parent)
{
echo ();
move (13, 20);
printw ("enter 2 numbers and an operation: ");
refresh ();
move (13, 60);
getstr (line);
refresh ();
noecho ();
write (fd [1], line, 20);
}
else
{
n = read (fd [0], line, 20);
sscanf (line, "%d %d %c", &n1, &n2, &operation);
switch (operation)
{
case '*': result = n1 * n2; break;
case '/': result = n1 / n2; break;
case '-': result = n1 - n2; break;
case '+': result = n1 + n2; break;
}
strcpy (line, "\0");
sprintf (line, "the result is: %d ", result);
write (fd2 [1], line, 20);
}
}
/* clear part of the screen. */
void clear_screen ()
{
int i;
move (13, 20);
printw (" ");
refresh ();
for (i = 0; i < 9; i++)
{
move (15 + i, 1);
printw (" ");
refresh ();
move (15 + i, 40);
printw (" ");
refresh ();
}
}
/* outfile: prog4.out */
--process control menu--------------------------------------
L)aunch S)top R)esume K)ill N)ext P)status T)ell Q)uit
C)lear & redraw 0-4) moves pointer:
------------------------------------------------------------
enter a choice: Q
------------------------------------------------------------
slot: 0 open -----------------------------------
slot: 1 open -----------------------------------
slot: 2 open -----------------------------------
slot: 3 open -----------------------------------
-----> slot: 0 open -----------------------------------
slot: 1 open -----------------------------------
slot: 2 open -----------------------------------
slot: 3 open -----------------------------------
slot: 4 open -----------------------------------
------------------------------------------------------------
special message:
------------------------------------------------------------
BACK TO CS3560 PAGE.