grotwin (Part 3 of 7)

nwh at hrc63.UUCP nwh at hrc63.UUCP
Sat Jul 12 00:04:54 AEST 1986


#!	/bin/sh
#	This is a shell archive. To extract the files type 'sh file'
#	This archive created on Thu Jul 10 16:38:32 WET 1986

echo 'shar: extracting 'manager.c' ( 22349 characters)'
if test -f 'manager.c'
then
	echo "shar: will not overwrite existing file 'manager.c'"
else
	cat << \SHAR_EOF > 'manager.c'
#ifndef lint
static char sccsid[] = "@(#)manager.c  2.2  [ (C) Nigel Holder 1986 ]";
#endif

/***************************************
*
*	Author  :  Nigel Holder
*
*	Date    :  10 July 1986
*
*
*	Copyright (C) 1986  by Nigel Holder 
* 
*	   Permission to use this program is granted, provided it is not
*	sold, or distributed for direct commercial advantage, and includes
*	the copyright notice and this clause.
* 
*	   Grotwin - provides a somewhat primitive windowing capability
*	for people unfortunate enough to use the standard 24 x 80 type
*	of terminal when the console is in use.  Definitely written for
*	4.[2,3] at the present time, as Sys V.2 does not cater for pseudo
*	terminals or have the select() facility (amongst other things !)
*	(version 8 should fix this).
*
*	Files used :-
*
*	   grotwin.c	 -	window system initialisation
*				deals with startup files
*
*	   manager.c	 -	window manager
*				deals with input and output
*
*	   window.c	 -	window manipulator
*				deals with aspects concerning windows
*				during normal usage
*
*	   update.c	 -	simulates dumb terminal for use
*				with window manager.
*
*	   grotwin.h	 -	header file for above
*
*	   utmp.c	 -	utmp manipulator
*				updates utmp entries for each window
*
*	   grotwin.make  -	makefile for above
*	   
*	Bugs :-
*
*	   Can't have the situation where no windows are present !
*	   Needs a vt100 like terminal type
*
***************************************/



#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <errno.h>
#include "grotwin.h"



extern int	errno;			/*  system error  */

/*  externals defined in grotwin.c  */

extern struct windowdetails	win[MAX_WINDOWS_PLUS];	/*  window details  */

extern struct sgttyb	masterterm;	/*  used to store initial tty state  */
extern struct tchars	mtchars;
extern int		mlocalmode;

extern int	startup;		/*  program startup period  */
extern int	confused;		/*  for when program hangs up  */
extern int	timeon;			/*  display clock on top edge  */
extern int	time_start;		/*  where time string is placed  */

extern char	*progname;		/*  program name stripped  of any /'s*/
extern char	timestring[];		/*  time on top edge of b/g window  */
extern char	nottimestring[];	/*  used when time is not displayed  */


unsigned int	child_died = 0;		/*  flag to catch SIGCHLD  */

/*  slavemask used to form mask of active file descriptors for select()  */
int	slavemask = 1 << 0;		/*  standard input (fd = 0)  */
int	active_windows = 0;		/*  number of user windows active  */
int	input_winno = 0;		/*  current window  */
int	input_changed = FALSE;		/*  to force cursor to be redrawn  */
int	alldead = FALSE;		/*  no user window active  */
int	exit_forced = FALSE;		/*  forced exit of program  */

long	clock;				/*  time in seconds of last minute  */

/*  list of priorities - end referenced by tail variable  */
int	window_priorities[MAX_WINDOWS_PLUS];




manager()	/*  manage input from active window and output from all  */

{
	/*******************
	*   Nice largeish timeout to make select() return only when something
	*   is ready (stops eating up cpu time).
	*   Must be less than 30 seconds for detection of hangup.
	*******************/

	static struct timeval	timeout = { 10L, 0L };
	static unsigned int	children_dead = 0;

	struct windowdetails	*ptr;
	int	 i, readfds, waiting;

	/*  make corners indicate indicate this input window  */
	top_corners(input_winno);

	while (1)   {
		/*  used to locate internal hangup  */
		if (confused == TRUE)   {
			confused = FALSE;
			if (timeon == TRUE)   {		/*  time changed  */
				display_time(DISPLAY);
			}
		}

		/*******************
		*   Check for dead children.  Even though child_died
		*   may be incremented asynchronously, having another
		*   count that is incremented until it is equal to
		*   child_died will overcome any problems of reading
		*   an out of date value of child_died being used.
		*******************/
   
		while (children_dead != child_died)   {
			++children_dead;
			check_exit();		/*  remove window  */
		}
		/*  place cursor in active window if moved  */
		if (input_changed == TRUE)   {
			ptr = &(win[input_winno]);
			wmove(stdscr, ptr->y_current + ptr->y_start,
				ptr->x_current + ptr->x_start);
			touchwin(stdscr);
			wrefresh(stdscr);
			input_changed = FALSE;
		}

		/*******************
		*  Check if their is any keyboard input and obey - then
		*  check each window for any output and display it .
		*  Order is important since user expects response to input
		*  immediately (this does mean that window tty could be closed
		*  after select has said there is input waiting though !).
		*******************/

		readfds = slavemask;
		if (select(NOFILE, &readfds, 0, 0, &timeout) <= 0)   {
			continue;
		}

		/*  keyboard input waiting  */
		if (readfds & (1 << 0))   {
			get_input();
		}
		touchwin(stdscr);
		wrefresh(stdscr);
		ptr = win;

		/*******************
		*   need to check if window is active since it may
		*   have been removed by action of keyboard input !
		*******************/

		for (i = 0 ; i < MAX_WINDOWS ; ++i, ++ptr)   {
			if (! ptr->active)   {
				continue;
			}
			/*  check for previous output still waiting  */
			if (ptr->page_buf_length > 0)   {
				update_screen(i);
				input_changed = TRUE;
				continue;
			}
			else   {	/*  read current output waiting  */
				if (readfds & ptr->slavemaskfd)   {
					waiting = read(ptr->masterfd,
							ptr->page_buf,
							ptr->readgrain);
					if (waiting != -1)   {
						ptr->page_buf[waiting] = '\0';
						ptr->page_buf_length = waiting;
						update_screen(i);
						input_changed = TRUE;
					}
				}
			}
		}
	}
}



/*  fire off window of specified dimensions running named program within it  */

win_instance(lines, columns, ystart, xstart, program)

int	lines, columns, ystart, xstart;
char	*program;

{
	struct windowdetails	*ptr;
	int	winno;
	char	*calloc();

	if ((winno = freewin()) == -1)   {
		return(-1);
	}
	if (newtty(winno) == -1)   {
		return(-1);
	}
	ptr = &(win[winno]);
	ptr->progy = calloc(strlen(program) + 1, sizeof(char));
	strcpy(ptr->progy, program);

	switch (ptr->slavepid = fork())   {
		case  -1  :		/*  too many system processes !  */
			/*  can't use removewin since haven't used createwin  */
			close(ptr->masterfd);
			close(ptr->slavefd);
			ptr->active = FALSE;
			return(-1);
			break;

		case  0  :		/*  child  */
			action_slave(ptr->slavefd, ptr->progy,
							lines - 2, columns - 2);
			/*  _exit to stop flushing buffers twice (apparently) */
			_exit(10);
			break;

		default  :		/*  parent  */
			/*****************
			*   In case any old (still running) processes started
			*   on pty have not been disassociated from it.
			*****************/

			ioctl(ptr->masterfd, TIOCSPGRP, &(ptr->slavepid));
			ioctl(ptr->slavefd, TIOCSPGRP, &(ptr->slavepid));
			/*  rendezvous with child (see comment in child)  */
			write(ptr->masterfd, "\n", 1);
			break;
	}
	/*  must be after fork (faster startup with createwin here)  */
	slavemask |= ptr->slavemaskfd;		/*  tty now accessible  */
	createwin(winno, lines, columns, ystart, xstart);
	return(winno);
}



static
freewin()			/*  return win[] location not in use  */

{
	register int	i;
	register struct windowdetails	*ptr;

	for (i = 0, ptr = win ; i < MAX_WINDOWS ; ++i, ++ptr)  {
		if (! ptr->active)   {
			return(i);
		}
	}
	return(-1);
}



static
newtty(winno)		/*  return number of a free pseudo tty (cyclic ish)  */

int	winno;

{
	/*  not very efficient for pty[q-r] at present, to be changed  */

	static char	*pseudo_termlist[] = {
				"0", "1", "2", "3", "4", "5", "6", "7",
				"8", "9", "a", "b", "c", "d", "e", "f"
	};
	static char	*masterside[] = {
				"/dev/ptyp", "/dev/ptyq", "/dev/ptyr"
	};
	static char	*slaveside[] = {
				"/dev/ttyp", "/dev/ttyq", "/dev/ttyr"
	};
	static int	elements = sizeof(pseudo_termlist) / sizeof(char *);
	static int	i = (sizeof(pseudo_termlist) / sizeof(char *)) - 1;
	static int	pty_groups = sizeof(masterside) / sizeof(char *);
	static int	j = (sizeof(masterside) / sizeof(char *)) - 1;

	register struct windowdetails	*ptr;
	char	temp[20];
	int	pty, tty_element, fd;

	ptr = &(win[winno]);
	/*  if pseudo tty in use, assume can't open either master or slave  */
	for (pty = 0 ; pty < pty_groups ; ++pty)   {
		for (tty_element = 0 ; tty_element < elements ; ++tty_element) {
			i = (i + 1) % elements;
			sprintf(temp, "%s%s", masterside[j],pseudo_termlist[i]);
			if ((fd = open(temp, O_RDWR)) != -1)   {
				ptr->masterfd = fd;
				sprintf(temp, "%s%s", slaveside[j],
							pseudo_termlist[i]);
				if ((fd = open(temp, O_RDWR)) != -1)   {
					ptr->slavemaskfd = 1 << ptr->masterfd;
					ptr->slavefd = fd;
					strcpy(ptr->pseudo_ttyname, temp);
					return(0);
				}
				close(ptr->masterfd);
			}
		}
		/*  start at the beginning for next pty group  */
		if (i != 0)   {
			i = elements - 1;
		}
		j = (j + 1) % pty_groups;
	}
	return(-1);
}



child_exit()		/*  increment global flag of dead children  */

{
	++child_died;
}



check_exit()				/*  check for terminated shells  */

{
	register int	i;
	register struct windowdetails	*ptr;
	int pid;

	for (i = 0, ptr = win ; i < MAX_WINDOWS ; ++i, ++ptr)   {
		if (ptr->active)   {
			if (kill(ptr->slavepid, 0) == -1 && errno == ESRCH)   {
				/*******************
				*   Should really check that pid is equal
				*   to ptr->slaveppid, but what could
				*   be done if it wasn't.
				*******************/
				pid = shell_cleanup(i);
			}
		}
	}

	/*  if no shells left - exit program  */
	if (alldead  &&  ! startup)   {
		alarm(0);
		signal(SIGALRM, SIG_IGN);
		signal(SIGCHLD, SIG_IGN);
		signal(SIGINT, SIG_IGN);
		die();
	}
}



update_time()		/*  called via SIGALRM - update global time  */

{
	static long	last_clock = 0L;
	char	*ctime();

	time(&clock);

	/*******************
	*   Following is a simple little check to ensure that if program
	*   will terminate within a minute if it hangs up badly.
	*   Relies on manager taking less than 30 seconds on select timeout !
	*******************/

	if (clock - last_clock > 30)   {	/*  internal hangup  */
		if (confused == TRUE  &&  startup == FALSE)   {
			confused = REALLY_CONFUSED;
			forced_die();
		}
		last_clock = clock;
	}
	alarm(60 - (int) (clock % 60));
	confused = TRUE;			/*  until proven otherwise  */
}



display_time(command)		/*  display or remove time on top border  */

int	command;

{
	wmove(stdscr, 0, time_start);
	if (command == DISPLAY)   {
		/*  isolate hours and mins  */
		strncpy(timestring + 1, ctime(&clock) + 11, 5);
		waddstr(stdscr, timestring);
	}
	else   {	/*  REMOVE  */
		waddstr(stdscr, nottimestring);
	}
	input_changed = TRUE;	/*  place cursor back in input window  */
}



static
shell_cleanup(winno)		/* remove all references to a now dead window */

int	winno;

{
	union wait	status;			/*  different from sysV  */
	int pid;

	/*******************
	*   Stop child waiting for parent to perform a wait.
	*   Otherwise child becomes zombie and hogs a place in process
	*   list table.
	*******************/
	pid = wait(&status);
	removewin(winno);
	/*  place cursor in current window  */
	if (! alldead)  {
		/*  was current window one terminated  */
		if (winno == input_winno)   {
			next_input_window(window_priorities[0]);
			top_dog(input_winno);
		}
	}
	return(pid);
}


kill_all_shells()

{
	int	i;

	exit_forced = TRUE;
	for (i = 0 ; i < MAX_WINDOWS ; ++i)   {
		if (win[i].active)   {
			if (kill_shell(i) == -1)   {
				printf(" window %d process wouldn't die ", i);
				sleep(2);
			}
			removewin(i);
		}
	}
	die();
}



/*  kill process within window - tries gently and then with brute force  */

static
kill_shell(winno)

int	winno;

{
	static int	kill_list[] = { SIGHUP, SIGINT, SIGTERM, SIGKILL };
	int		i;

	kill(win[winno].slavepid, SIGCONT);	/*  wake up just in case  */
	for (i = 0 ; i < (sizeof(kill_list) / sizeof(int)) ; ++i)   {
		if (kill(win[winno].slavepid, kill_list[i]) == 0)   {
			return(kill_list[i]);
		}
	}
	return(-1);
}



static
removewin(winno)			/*  remove window from existance  */

int	winno;

{
	struct windowdetails	*ptr;
	char	*rindex(), *tty;

	ptr = &(win[winno]);
	ptr->active = FALSE;
	slavemask &= ~ ptr->slavemaskfd;
	if (--active_windows <= 0)   {
		alldead = TRUE;
	}
	close(ptr->masterfd);
	close(ptr->slavefd);
	tty = 1 + rindex(ptr->pseudo_ttyname, '/');
	utmp_delete(tty);
	free_virt_win(ptr->screenptr);
	free(ptr->progy);
	/*  test to stop needless screen redrawing if quiting program  */
	if (! exit_forced)   {		/*  clear screen where window was  */
		bottom_dog(winno, REMOVE);
		touchwin(stdscr);
		wrefresh(stdscr);
	}
}



next_input_window(value)

int	value;

{
	static int	prev_winno = MAX_WINDOWS - 1;
	register struct windowdetails	*ptr;
	int		i, oldinput;

	oldinput = input_winno;
	if (value == -1)   {
		for (i = 0 ; i < MAX_WINDOWS ; ++i)  {
			prev_winno = (prev_winno + 1) % MAX_WINDOWS;
			if (win[prev_winno].active)   {
				input_winno = prev_winno;
				break;
			}
		}
	}
	else   {
		/*  check for illegal window number or inactive window  */
		if (value >= 0  &&  value < MAX_WINDOWS)   {
			if (win[value].active)   {
				input_winno = value;
				prev_winno = value;
			}
			else   {
				return(-1);
			}
		}
		else   {
			return(-1);
		}
	}

	/*  remove active indicators in top corners of old acitive window  */
	if (oldinput >= 0)   {
		ptr = &(win[oldinput]);
		if (ptr->active)   {
			ptr->screenptr[ptr->y_start - 1][ptr->x_start - 1] =' ';
			ptr->screenptr[ptr->y_start - 1][ptr->x_end] = ' ';
			top_corners(oldinput);
		}
	}
	/*  add active indicators to top corners of active window  */
	ptr = &(win[input_winno]);
	ptr->screenptr[ptr->y_start - 1][ptr->x_start - 1] = '+';
	ptr->screenptr[ptr->y_start - 1][ptr->x_end] = '+';
	top_corners(input_winno);

	input_changed = TRUE;

	/*  bodge for now to force corners to be indicated !  */
	/*  should go before ptr = ...  */
 	if (oldinput == input_winno)   {
		return(-1);
	}
	return(oldinput);
}



static
get_input()

{
	int	length, i;
	char	input[BUFSIZ + 1];

	length = read(0, input, BUFSIZ);
	for (i = 0 ; i < length ; ++i)   {
		put_char((unsigned char) input[i]);
	}
}



static
put_char(c)

unsigned char	c;

{
	extern int	window_info(), help_info();

	static unsigned int	prev_c = '\0';
	static int	new_winno = 0;	/*  in case c == WIN_SWITCH_NUMBER  */

	struct windowdetails	*ptr;
	int	upper_case, temp;
	unsigned char	c_orig;

	c &=  0x7F;		/*  strip off top bit for WIN_SELECT_NUMBER  */
	ptr = &(win[input_winno]);
	if (prev_c == SELECT)   {
		c_orig = c;
		/*******************
		*   to help distinguish between upper case only commands,
		*   make upper_case variable FALSE in order to execlude
		*  lower case and control instances
		*******************/
		upper_case = FALSE;		/*  until proved otherwise  */
		if (isdigit(c))   {
			new_winno = c - '0';
			if (new_winno < MAX_WINDOWS)   {
				c = WIN_SWITCH_NUMBER;
			}
		}
		else   {
			if (isalpha(c))   {
				if (isupper(c))   {
					upper_case = TRUE;
				}
				/*  to allow 'n' and CTRL-N to be the same  */
				c = c & CTRL_MASK;
			}
		}
		switch(c)   {
			case  WIN_SWITCH  :
				new_winno = -1;
			case  WIN_SWITCH_NUMBER  :
				temp = input_winno;
				if (next_input_window(new_winno) == -1  ||
						temp == input_winno)   {
					write(1, "\007", 1);
					break;		/*  nasty practice  */
				}
				top_dog(input_winno);
				touchwin(stdscr);
				wrefresh(stdscr);
				break;

			case  NEW_WINDOW  :
				new_window();
				break;

			case  SCREEN_REDRAW  :
				touchwin(curscr);
				wrefresh(curscr);
				break;

			case  EXPAND  :
				widen_window(input_winno, VERTICAL_EXPAND);
				widen_window(input_winno, HORIZONTAL_EXPAND);
				touchwin(stdscr);
				wrefresh(stdscr);
				break;

			case  VERTICAL_EXPAND  :
				widen_window(input_winno, VERTICAL_EXPAND);
				touchwin(stdscr);
				wrefresh(stdscr);
				break;

			case  HORIZONTAL_EXPAND  :
				widen_window(input_winno, HORIZONTAL_EXPAND);
				touchwin(stdscr);
				wrefresh(stdscr);
				break;

			case  PAGE_MODE  :
				if (upper_case)   {	/*  page off  */
					ptr->output_paged = FALSE;
					if (ptr->paged_page_full)   {
						ptr->paged_page_full = FALSE;
					}
				}
				else   {		/*  page on  */
					if (! ptr->output_paged)   {
						ptr->output_paged = TRUE;
						ptr->paged_page_full = FALSE;
						ptr->line_count = 0;
					}
				}
				break;

			case  REMOVE_WIN  :
				/*  only look for upper case   */
				if (upper_case)   {
					if (kill_shell(input_winno) == -1)   {
						/*  failed (why ?)  */
						write(1, "\007", 1);
					}
					break;
				}
				/*  fall through to default case (nasty)  */
				goto fallthru;

			case  FORCED_EXIT  :
				if (upper_case)   {
					forced_die();
					break;
				}
				/*  only look for upper case   */
				/*  fall through to default case (nasty)  */
				goto fallthru;

			case  XON  :
				ptr->output_blocked = FALSE;
				break;

			case  XOFF  :
				ptr->output_blocked = TRUE;
				break;

			case  OVERWRITE_MODE  :
				if (upper_case)   {	/*  overwrite off  */
					ptr->overwrite = FALSE;
				}
				else   {		/*  overwrite on  */
					ptr->overwrite = TRUE;
				}
				break;

			case  TIME_TOGGLE  :
				/*  toggle time between on and off  */
				if (timeon == TRUE)   {
					timeon = FALSE;
					display_time(REMOVE);
				}
				else   {
					timeon = TRUE;
					update_time();
				}
				break;

			case  INFORM  :
				inform(window_info, input_winno);
				break;

			case  HELP  :
				inform(help_info, input_winno);
				break;

			case  CLEAR  :
				mywclear(input_winno);
				input_changed = TRUE;
				touchwin(stdscr);
				wrefresh(stdscr);
				break;

			case  EXPOSE_WINDOW  :
				top_dog(input_winno);
				touchwin(stdscr);
				wrefresh(stdscr);
				break;

			case  HIDE_WINDOW  :
				bottom_dog(input_winno, HIDE);
				touchwin(stdscr);
				wrefresh(stdscr);
				break;

	fallthru :
			default  :
				if (ptr->paged_page_full)   {
					ptr->paged_page_full = FALSE;
				}
				else   {
					c = c_orig;
					write(ptr->masterfd, &c, 1);
					if (c == SELECT)   {
						c = ~c;
					}
				}
				break;
		}
	}
	else   {
		if (c != SELECT)   {
			if (ptr->paged_page_full)   {
				ptr->paged_page_full = FALSE;
			}
			else   {
				write(ptr->masterfd, &c, 1);
			}
		}
	}
	prev_c = c;
}



/*  fire off slave process within window  */

static
action_slave(slavefd, progy, lines, columns)

int	slavefd;
char	*progy;
int	lines, columns;

{
	extern char	**environ;
	extern char	termcap[];
	extern char	term[];		/*  my very own terminal type !  */

	int	fd, ldisc, pgrp, i, j, k;
	char	**argv, **envp, *calloc();
	char	c, buffer[BUFSIZ + 1], *ptr1, *ptr2;

	signal(SIGALRM, SIG_IGN);
	alarm(0);		/*  turn off clock signal  */

	/*  reset all caught signals  */
	for (i = 1 ; i <= NSIG ; ++i)   {
		signal(i, SIG_DFL);
	}

	/*  make pseudo tty connection  */
	close(0);
	dup(slavefd);
	close(1);
	dup(slavefd);
	close(2);
	dup(slavefd);
	for (i = 3 ; i < NOFILE ; ++i)   {	/*  close all other files  */
		close(i);
	}
	/*  disassociate /dev/tty from parent control group  */
	if ((fd = open("/dev/tty", O_RDWR, 0)) != -1)   {
		ioctl(fd, TIOCNOTTY, 0);
		close(fd);
	}

	/*******************
	*      From experience, it would appear that the master side of a
	*   pseudo tty must set the process group for the master side (pty)
	*   before the slave side sets its process group equal to its
	*   own pid (master is also set to this value, obtained via fork
	*   of child).
	*      This is achieved by the parent writing '\n' (specifically '\n'
	*   to overcome buffering), on its tty when it has set its
	*   own tty and its childs tty (action duplicated by child) to the
	*   process group equal to the childs process number, thereby
	*   achieving a simple rendezvous.
	*******************/

	/*  rendezvous with parent  */
	read(0, &c, 1);

	/*  set up tty in a usable state as parent tty may not be  */
	ldisc = NTTYDISC;
	masterterm.sg_flags |= ECHO;
	masterterm.sg_flags |= CRMOD;
	masterterm.sg_flags &= ~CBREAK;
	masterterm.sg_flags &= ~RAW;
	ioctl(0, TIOCSETP, &masterterm);
	ioctl(0, TIOCSETD, &ldisc);
	ioctl(0, TIOCLBIS, &mlocalmode);
	ioctl(0, TIOCSETC, &mtchars);

	/*  set up unique process group and attach to process and tty  */
	pgrp = getpid();
	setpgrp(pgrp, pgrp);
	ioctl(0, TIOCSPGRP, &pgrp);	/*  parent also performs this  */
	set_tty_size(0, lines, columns, FALSE);		/*  set tty size  */

	for (i = 0 ; environ[i] ; ++i)   {	/*  find last entry  */
		;
	}
	/*  form new environment for progy  */
	envp = (char **) calloc(i + 2, sizeof(char *));
	/*  comb through and remove TERM and TERMCAP entries  */
	for (k = 0, j = 0 ; j < i ; ++j)   {
		if (strncmp(environ[j], "TERMCAP", 7) != 0  &&
				strncmp(environ[j], "TERM", 4) != 0)   {
			envp[k++] = environ[j];
		}
	}

	/*******************
	*   Now add grotwin terminal type.
	*   Could be clever and place these at start of environment
	*   for quick access !
	*******************/

	envp[k] = calloc(strlen(term) + 1, sizeof(char));
	strcpy(envp[k++], term);
	sprintf(buffer, termcap, columns, lines);
	envp[k] = calloc(strlen(buffer) + 1, sizeof(char));
	strcpy(envp[k], buffer);
	envp[++k] = (char *) NULL;

	environ = envp;
	argv = (char **) calloc(MAXARGS + 1, sizeof(char *));

	strcpy(buffer, progy);
	i = 0;
	ptr1 = buffer;
	while (i < MAXARGS)   {
		for(ptr2 = ptr1 ; *ptr1 != ' '  &&  *ptr1 ; ++ptr1)   {
			;
		}
		argv[i++] = ptr2;
		if (! *ptr1)   {
			break;
		}
		*ptr1++ = '\0';
	}
	argv[i] = (char *) NULL;
	execvp(argv[0], argv);

	/*  exec failed  */
	fprintf(stderr, "\r\n%s: can't find %s  ", progname, argv[0]);
	fflush(stderr);
	free(argv);
	free(envp[k - 1]);
	free(envp[k - 2]);
	free(envp);
	close(0);	/*  close files  */
	close(1);
	close(2);
	sleep(5);
}



/*******************
*   Set tty size and inform associated control group
*   via SIGWINCH that the tty size has changed.
*******************/

set_tty_size(fd, lines, columns, inform)

int fd, lines, columns, inform;

{
	struct ttysize	tty_size;
	int	pgrp;

	tty_size.ts_lines = lines;		/*  set up new tty size  */
	tty_size.ts_cols = columns;
	if (ioctl(fd, TIOCSSIZE, &tty_size) == -1)   {
		return;			/*  can't change tty size  */
	}
	if (inform == TRUE)   {		/*  inform process  */
		if (ioctl(fd, TIOCGPGRP, &pgrp) == 0)   {
			killpg(pgrp, SIGWINCH);
		}
	}
}
SHAR_EOF
if test 22349 -ne `wc -c < 'manager.c'`
then
	echo 'shar: error transmitting 'manager.c' (should have been  22349 charcaters)'
fi
fi

exit

Nigel Holder			UK JANET:       yf21 at uk.co.gec-mrc.u
Marconi Research,		ARPA:           yf21%u.gec-mrc.co.uk at ucl-cs
Chelmsford,
Essex. CM2 8HN.

+44 245 73331   ext. 3219 / 3214



More information about the Comp.sources.unix mailing list