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.