DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T m

⟦6e1b0a00f⟧ TextFile

    Length: 12000 (0x2ee0)
    Types: TextFile
    Names: »mysystem.c«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦e7f64e0c0⟧ »EurOpenD3/mail/vmh.tar.Z« 
        └─⟦dcb95597f⟧ 
            └─⟦this⟧ »mysystem.c« 

TextFile

#ifndef lint
static char rcsid[] =
	"$Header: mysystem.c,v 2.12 88/01/13 19:10:51 deboor Exp $";

static char notice[] =
	"This program is in the public domain and is available for unlimited \
distribution as long as this notice is enclosed.";
#endif

/*
 * new system routines for vmh. old ones weren't sufficient.
 *
 * $Source: /c/support/deboor/usr/src/old/vmh/RCS/mysystem.c,v $
 * $Revision: 2.12 $
 * $Author: deboor $
 *
 * FUNCTIONS:
 *	Pcmd		execute a command with a shell and page output in
 *			bottom window.
 *	call_prepare	prepare for executing an external command with messages
 *			and the resetting of the tty state
 *	call_recover	recover from an external command.
 *	do_refresh	interrupt routine to worry about refreshing the screen
 *			after vmh has been suspended
 *	flushinput	nuke any typeahead
 *	my_system	system() with terminal reset, etc.
 *	my_tstp		^Z catcher
 *	my_vfork	vfork with terminal reset, etc.
 *	newtty		initialize/set tty modes to those desired by vmh
 *	oldtty		reset tty to initial state
 *	system		vmh version of the system() library call (probably un-
 *			nec'y)
 */

#include "vmh.h"                 /* Mine */
#include <sys/wait.h>
#include <sys/resource.h>
/* #include <sys/param.h>       /* For NOFILES parameter (given by ff) */

extern struct tchars chars;     /* Filled initially by init.c */
extern struct ltchars lchars;	/* ditto */

extern char *KS, *KE;

my_system(cmd, pause)
	char	*cmd;
	int	pause;
{
	register int rc;

	if( !*cmd ) return -1;

	call_prepare();         /* Prepare for system call */
	rc = system(cmd);       /* Go do the cmd */
	call_recover(pause, 0);    /* Recover from system call */

	return( rc );
}

my_vfork(argv, pause)
	char	*argv[];
	int	pause;               /* non zero if need to wait 1 more char */
{
	
	int pid;
	register int (*istat)(), (*qstat)();

	call_prepare();

	pid = vfork();
	if (pid == 0)
	{
		int i, j;
		j  = getdtablesize();
		for (i=3; i < j ; i++)     /* Close all the extra fd's */
			(void) close(i);
		execvp(argv[0], argv);
		printf(" *** Unable to exec %s\n", argv[0]);
		(void) fflush(stdout);
		_exit(1); /*NOTREACHED*/
	} else {                            /* Parent */
		int	cpid;
		union	wait	CStat;

					/* Copied from system(3) */
		istat = signal(SIGINT, SIG_IGN);
		qstat = signal(SIGQUIT, SIG_IGN);

		do {
			while ((cpid = wait3 (&CStat, WUNTRACED, (struct rusage *)0)) == 0)
				;
			if ((cpid == pid) && WIFSTOPPED (CStat)) {
				(void) kill (pid, SIGCONT);
				cpid = 0;
			}
		} while (cpid != -1 && cpid != pid);

		(void) signal(SIGINT, istat);
		(void) signal(SIGQUIT, qstat);
					/* If non-zero rc (i.e. error) */
		if (WIFSIGNALED (CStat) || WIFEXITED (CStat))
			sleep(2);            /* then sleep 2 to show err msg */

		call_recover(pause, 0); /* Recover from call & do pause logic */

		return( CStat.w_retcode );
	}
}

/*
 * fflush on an input stream is undefined; and in 4.1bsd, fflush on
 * an input stream is a nop.
 */
flushinput()
{
	stdin->_cnt = 0;        /* Discard any in the stdin buffer */
	(void) Ioctl(fileno(stdin), TIOCFLUSH, 0);   /* Discard any in kernal */
}



/*
 *   Run cmd via popen() managing any output in the bottom window.
 *
 *      (note: popen invokes a shell, which closes off excess fd's)
 */
Pcmd( cmd )
	register char *cmd;
{
	FILE		*fp,
			*popen(),
			*pclose();
	char		line[150];


	if( !*cmd )
		return;

	syncfolders();          /* Refresh .infos to disk */

	(void) sprintf( line, " Command: %s ", cmd );
	dotitle( botHdr, line );
	wclear( botWin );
	wrefresh( botWin );
	wmove( botWin, 1, 0 );

	/*
	 *  Execute it
	 */

	/*** Bug! distributed popen leaves stderr going to the screen.
	     Modified version of it joins it with stdout to the pipe,
	     but that's not that great either.          -- guyton ***/

	fp = popen( cmd, "r" );
	if( fp == NULL ) {
		(void) sprintf( line, "Can't open pipe to execute %s", cmd);
		errormsg( line, 1 );
		startwatch();
		return;
	}

	init_pager ((FILE *) NULL, botWin);
	while( fgets( line, sizeof(line), fp )) {
		if (putstr (line))
			break;
	}

	end_pager();

	wrefresh( botWin );

	pclose( fp );
   /*   startwatch();           was broken, seems ok again */
   /** recheck the folders?? **/
#ifdef notdef
	window.ws_row = rows; window.ws_col = cols;
	(void) Ioctl (0, TIOCSWINSZ, &window);
#endif
	return;
}


# ifdef SIGTSTP

static	struct	itimerval bg_timer = {	/* clock for continuous refreshes */
	{0, 0},		/* interval */
	{0, 0},		/* value */
};
int	no_tty	= 0;	/* if this is one, then we don't have a tty */
			/* used by updatetop() */

/*
** do_refresh()
**	called by my_tstp and used for SIGVTALRM catching. If the
**	tty attached to descriptor 1's process group is our
**	process group, we are in the foreground. If
**	so, then refreshes the screen, disables the timer and
**	returns. Otherwise, if the timer isn't going, then starts
**	it to expire in one half second and reset to one half second after
**	each expiration.
*/
static	struct	sigvec	oldvt;
static	struct	itimerval oldvtt;
static	int		initial_mask;

do_refresh (not_init)
	int	not_init;	/* called w/non-0 sig when catching */
{
	int	_putchar();
	int	pgrp;

		

	if ( ! not_init) {
		bg_timer.it_value.tv_sec = bg_timer.it_interval.tv_sec = 0;
		/*
		 * set interval to 1/2 second
		 */
		bg_timer.it_value.tv_usec = bg_timer.it_interval.tv_usec = 500000;
		(void) Setitimer (ITIMER_VIRTUAL, &bg_timer, &oldvtt);
		initial_mask = sigblock(0);
		(void) sigsetmask(0);
	}

	(void) Ioctl (0, TIOCGPGRP, &pgrp);	/* get process group */
	if ( pgrp == getpgrp(0)) {		/* == => we're back */
		(void) sigsetmask (initial_mask);

		(void) sigvec (SIGVTALRM, &oldvt, (struct sigvec *) 0);
		(void) Setitimer(ITIMER_VIRTUAL, &oldvtt, (struct itimerval *) 0);

		do_autoclear();
		wrefresh(curscr);               /* Repaint the entire screen */
		newtty();                     /* Set my tty parms and signals */
		no_tty = 0;
	
		      /* Put cursor back */
		tputs(tgoto(CM, curscr->_curx, curscr->_cury), 1, _putchar);
		(void) fflush(stdout);
	} else
		no_tty = 1;
}
			
/*
 * handle stop and start signals
 * modified from curses sources for vmh.
 */

my_tstp(signo)
	int	signo;
{
	int oldx, oldy;         /* Old cursor position */
	int  do_refresh();
	struct sigvec	refr;
	int	mask;

	oldx = curscr->_curx;   /* Save for after continue */
	oldy = curscr->_cury;

	syncfolders();          /* Refresh .infos to disk */

	mvcur(0, COLS - 1, LINES - 1, 0);       /* Move to bottom of scr */

	oldtty();                       /* Reset tty/signals to init state */
					/* also resets start/stop signal */
	refr.sv_handler = do_refresh;
	refr.sv_mask = refr.sv_onstack = 0;

	(void) sigvec (SIGVTALRM, &refr, &oldvt);

	mask = sigblock (0);
	(void) sigsetmask(mask & ~sigmask(signo));
	(void) kill(0, signo);                 /* Stop me */

	(void) sigsetmask (mask);
					/* Have returned from stop */
	do_refresh (0);			/* set up refresh loop */

	curscr->_curx  = oldx;
	curscr->_cury  = oldy;

/***    infomsg("Welcome back!"); sleep(2);     ***/
	recheckfldrs();                 /* See if .infos changed on me! */

}

# endif SIGTSTP

int (*oldtstp)();               /* Old value of tstp handler (fix types!) */

call_prepare()
{
	infomsg("Wait ...\n", 1);
	mvcur (0,COLS-1, LINES-1,0);
	(void) fflush (stdout);
	endwatch();               /* Turn off mailcheck daemon */
	holdclock();
	syncfolders();          /* Refresh .infos to disk */
	oldtty();               /* Fixup tty & signals to initial state */
}

call_recover(pause, check)
	int	pause;                      /* Non-zero if want to pause */
	int	check;                   /* Non-zero if want to check folders */
{
	register	i;
	char		jc;

	newtty();               /* Set my tty parms and signals */

	wclear(cmdWin);
	mvcur (0, COLS-1, LINES-1, 0);
	if (pause) {            /* If want to discard next char */
				/* echo turned off by newtty() */
		(void) write(1, ":", 1);
		(void) read (0, &jc, 1);
	}

	do_autoclear();
	wrefresh(curscr);       /* Redisplay the entire screen */

	startwatch();           /* Restart the new-mail daemon */
	startclock();

	if (check)              /* Should do this all the time someday */
	     recheckfldrs();    /* See if .infos changed on me! */

	dotitle (botHdr, HELPMSG);

}

/*
 * Set up tty parms the way vmh want's 'em
 * assumes a couple of Ioctl's in init.c
 */

extern char start, stop;	/*XXX: should be in vmh.h */
newtty()
{
	chars.t_intrc = -1;             /* Disable the del key */
	chars.t_stopc = -1;
	chars.t_startc = -1;
	lchars.t_lnextc = -1;		/* and the literal-next */
	lchars.t_dsuspc = -1;		/* and the delayed-suspend key */
	(void) Ioctl(_tty_ch, TIOCSETC, &chars);
	(void) Ioctl(_tty_ch, TIOCSLTC, &lchars);
	(void) Fchmod(_tty_ch, new_tty_mode);	/* set biff properly */

	crmode();                       /* Set cbreak mode */
	noecho();                       /* Turn off echo */
	nonl();				/* don't want newline mapping */
	_puts (KS);			/* switch to application keypad */
	flushinput();                   /* Throw away typeahead */

#ifdef SIGTSTP
	(void) signal(SIGTSTP, my_tstp);       /* Install my start/stop routine */
#endif
}

/*
 * Restore tty parms to what they were on entry
 */
oldtty()
{
	extern SGTTY	ttyb;

	chars.t_intrc = quit;           /* Restore original DEL key */
	chars.t_startc = start;
	chars.t_stopc = stop;
	lchars.t_lnextc = litnext;	/* and original litnext char */
	lchars.t_dsuspc = dsuspc;	/* and original ^Y char */
	(void) Ioctl(_tty_ch, TIOCSETC, &chars);
	(void) Ioctl(_tty_ch, TIOCSLTC, &lchars);
	(void) Ioctl(_tty_ch, TIOCSETP, &ttyb);	/* and original modes */
	(void) Fchmod(_tty_ch, init_tty_mode); /* reset biff */
	_puts (KE);			/* back to normal keypad */

	endwin();                       /* Turn off cbreak, turn on echo */

#ifdef COMMENT
  Turns out the fflush is not what is wanted here.  The ambassador termcap
  entry TE (sent by the endwin routine) is enough to clear the bottom line
  and get rid of the "Waiting ..." msg that was so carefully put up.  So,
  for now lets just leave out the fflush and it will get sent later.
#endif COMMENT

	(void) fflush(stdout);                 /* Wonder if this line is required? */


#ifdef SIGTSTP
	(void) signal(SIGTSTP, SIG_DFL);       /* Install default start/stop */
#endif
}


/*
   This is just system(3) except with csh instead of sh.  Not
   just that I like csh (I do), but "sh" doesn't close excess
   open fd's across exec's and vmh was running out of fd's.
						 -- Guyton 2/83
*/

system(s)
	char *s;
{
	union	wait	status;
	int		pid,
			w;
	register int	(*istat)(),
			(*qstat)();

	if ((pid = vfork()) == 0) {
		execl("/bin/csh", "csh", "-c", s, 0);
		_exit(127);
	}
	istat = signal(SIGINT ,SIG_IGN);
	qstat = signal(SIGQUIT, SIG_IGN);

	/* do WUNTRACED here ? */
	while ((w = wait(&status)) != pid && w != -1)
		;
	if (w == -1)
		status.w_retcode = -1;
	(void) signal(SIGINT, istat);
	(void) signal(SIGQUIT, qstat);
	return(status.w_retcode);
}

/*
 * do_autoclear()
 *	this function is used to speed things up <= 1200 baud. if the auto_clear
 *	flag is set, then don't want to redisplay the contents of the bottom
 *	window. But if just do a wclear() wrefresh() sequence, curses prints
 *	a row of spaces. This is designed to alleviate that since the screen
 *	has already been cleared by a clear-screen terminal sequence. Whether
 *	it will work is up to curses, though.
 */
do_autoclear()
{
	register int	i;
	register int	j;
	int		endx = botWin->_begx + botWin->_maxx;
	int		endy = botWin->_begy + botWin->_maxy;

	if (! auto_clear)
		return;

	werase (botWin);/* do it now */
	/*
	 * THIS IS A HACK!!! It should work only for this
	 * specific implementation of curses...if then.
	 */
	for (i = botWin->_begy; i < endy; i++) {
		for (j = botWin->_begx; j < endx; j++) {
			curscr->_y[i][j] = ' ';
		}
	}
	for (i=0; i < botWin->_maxy; i++)
		botWin->_lastch[i] = botWin->_firstch[i] =
			curscr->_lastch[curscr->_begy+i] =
			curscr->_firstch[curscr->_begy+i] = _NOCHANGE;
}