OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [peripheral/] [channels/] [xterm.c] - Rev 1070

Go to most recent revision | Compare with Previous | Blame | View Log

/* xterm.c -- Definition of functions and structures for 
   peripheral to communicate with host through an xterm.
   Inspired from SWI-Prolog by Jan Wielemaker (GPL too)
   even if there is really few in common.
 
   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/*
 *  I really dislike using stuff beginning with '_' 
 *  They are suppose to be reserved for the compiler
 *  as explained in C standards.
 */
#define _XOPEN_SOURCE		/* grantpt() and al. */
#define _GNU_SOURCE		/* on_exit */
 
#include <sys/types.h>		/* waitpid() */
#include <sys/wait.h>		/* waitpid() */
#include <stdio.h>		/* sprintf() */
#include <stdlib.h>		/* kill(), on_exit() */
#include <unistd.h>		/* close() */
#include <fcntl.h>		/* O_RDWR */
#include <string.h>		/* strchr() */
#include <sys/stropts.h>	/* grantpt(), unlockpt() */
#include <termios.h>		/* struct termios and al. */
#include <signal.h>		/* signal() and al. */
#include <libgen.h>		/* basename() */
#include <errno.h>		/* errno and al. */
 
#include "channel.h"
#include "generic.h"
#include "fd.h"
 
 
struct xterm_channel
{
	struct fd_channel fds;
	int pid;
};
 
 
static void xterm_close(void * data)
{
	struct xterm_channel * xt = data;
 
	if(!xt)
		return;
 
	if(xt->fds.fdin != -1)
		close(xt->fds.fdin);
 
	if(xt->pid != -1)
	{
		kill(xt->pid, SIGKILL);
		waitpid(xt->pid, NULL, 0);
	}
 
	xt->fds.fdin = -1;
	xt->fds.fdout = -1;
	xt->pid = -1;
}
 
static void xterm_exit(int i, void * data)
{
	xterm_close(data);
}
 
static void * xterm_init(const char * input)
{
	struct xterm_channel * retval = malloc(sizeof(struct xterm_channel));
	if(retval)
	{
		retval->fds.fdin = -1;
		retval->fds.fdout = -1;
		retval->pid = -1;
		/* reset cause exit(1), leaving an xterm opened */
		on_exit(xterm_exit, retval);	
	}
	return (void*)retval;
}
 
 
 
static int xterm_open(void * data)
{
	struct xterm_channel * xt = data;
	int master, retval;
	char * slavename;
	struct termios termio;
	char arg[64], * fin;
 
	if(!data)
	{
		errno = ENODEV;
		return -1;
	}
 
 
	master = open("/dev/ptmx", O_RDWR);
 
	if(master < 0)
		return -1;
 
	grantpt(master);                             
	unlockpt(master);
	slavename = (char*)ptsname(master);
 
	if(!slavename)
	{
		errno = ENOTTY;
		goto closemastererror;
	}
 
	xt->fds.fdout = xt->fds.fdin = open(slavename, O_RDWR);
	if(xt->fds.fdout < 0) goto closemastererror;
 
	retval = ioctl(xt->fds.fdin, I_PUSH, "ptem"); 
	if(retval < 0) goto closeslaveerror;
 
	retval = ioctl(xt->fds.fdin, I_PUSH, "ldterm");
	if(retval < 0) goto closeslaveerror;
 
	retval = tcgetattr(xt->fds.fdin, &termio);
	if(retval < 0) goto closeslaveerror;
 
 
	termio.c_lflag &= ~ECHO;
	retval = tcsetattr(xt->fds.fdin, TCSADRAIN, &termio);
	if(retval < 0) goto closeslaveerror;
 
	xt->pid = fork();
 
	if(xt->pid == -1) goto closeslaveerror;
 
	if(xt->pid == 0)
	{
		/* Ctrl-C on sim still kill the xterm, grrr */
		signal(SIGINT, SIG_IGN);
 
		fin = slavename+strlen(slavename)-2;
		if (strchr(fin, '/' ))
		{
			sprintf(arg, "-S%s/%d",
				basename(slavename),
				master);
		}
		else
		{
		      sprintf(arg, "-S%c%c%d", fin[0], fin[1], master);
		}
		execlp("xterm", "xterm", arg, NULL);
		write(master, "\n", 1);
		exit(1);
	}
 
	do retval = read(xt->fds.fdin, &arg, 1);
	while(retval >= 0 && arg[0] != '\n');
 
	if(retval < 0) goto closeslaveerror;
 
	termio.c_lflag |= ECHO;
	retval = tcsetattr(xt->fds.fdin, TCSADRAIN, &termio);
 
	if(retval < 0) goto closeslaveerror;
 
	return 0;
 
closeslaveerror:
	close(xt->fds.fdin);
 
closemastererror:
	close(master);
	xt->pid = xt->fds.fdin = xt->fds.fdout = -1;
	return -1;
}
 
struct channel_ops xterm_channel_ops =
{
	init:	xterm_init,
	open:	xterm_open,
	close:	xterm_close,
	read:	fd_read,
	write:	fd_write,
	free:	generic_free,
};
 
/*
 * Local variables:
 * c-file-style: "linux"
 * End:
 */
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.