/*
* @OSF_FREE_FREE_COPYRIGHT@
*
*/
/*
* HISTORY
* $Log: parent_linux.c,v $
* Revision 1.1.2.2 1996/11/18 18:16:14 barbou
* Changed the syscall exception mask for second servers from
* EXC_MASK_BAD_INSTRUCTION to EXC_MASK_SYSCALL.
* Use the ioperm() syscall instead of iopl() to get Mach privileges.
* In parent_linux_exit(), terminate the Mach task instead of using exit()
* because exit() terminates only the current thread.
* [1996/11/18 18:00:04 barbou]
*
* Revision 1.1.2.1 1996/09/09 17:18:43 barbou
* Created.
* [1996/08/30 17:01:30 barbou]
*
* $EndLog$
*/
#include <mach/exception.h>
#include <mach/mach_interface.h>
#include <osfmach3/mach3_debug.h>
#include <osfmach3/parent_server.h>
#include <osfmach3/mach_init.h>
#include <linux/unistd.h>
#include <linux/signal.h>
#include <linux/kernel.h>
#include <linux/termios.h>
extern int errno;
#define __NR_parent_linux_getpid __NR_getpid
#define __NR_parent_linux_sigaction __NR_sigaction
#define __NR_parent_linux_write __NR_write
#define __NR_parent_linux_read __NR_read
#define __NR_parent_linux_ioctl __NR_ioctl
#define __NR_parent_linux__exit __NR_exit
#define __NR_parent_linux_ioperm __NR_ioperm
_syscall0(int, parent_linux_getpid)
_syscall3(int, parent_linux_sigaction,
int, sig,
const struct sigaction *, nsa,
struct sigaction *, osa)
_syscall3(int, parent_linux_write,
int, fd,
char *, buf,
int, count);
_syscall3(int, parent_linux_read,
int, fd,
char *, buf,
int, count);
_syscall3(int, parent_linux_ioctl,
int, fd,
int, request,
char *, data);
_syscall1(int, parent_linux__exit,
int, error_code);
_syscall3(int, parent_linux_ioperm,
unsigned long, from,
unsigned long, num,
int, on);
void
parent_linux_sig_handler(
int sig)
{
printk("** SERVER RECEIVED SIGNAL %d. Calling Debugger...\n", sig);
Debugger("signal");
}
void
parent_linux_catchall_signals(void)
{
struct sigaction sa;
int sig;
sa.sa_handler = parent_linux_sig_handler;
sa.sa_mask = 0;
sa.sa_flags = 0;
for (sig = 1; sig < NSIG; sig++) {
(void) parent_linux_sigaction(sig, &sa, (struct sigaction *) 0);
}
}
struct termios parent_linux_console_termios;
int
parent_linux_grab_console(void)
{
struct termios termios;
if (parent_server_ioctl(0, TCGETS,
(char *) &parent_linux_console_termios) < 0) {
printk("parent_linux_grab_console:ioctl(TCGETS) -> %d\n",
errno);
}
termios = parent_linux_console_termios;
termios.c_iflag = IGNBRK;
termios.c_oflag = 0;
termios.c_cflag = CS8|CREAD|PARENB;
termios.c_lflag = 0;
termios.c_cc[VMIN] = 1;
termios.c_cc[VTIME] = 0;
if (parent_server_ioctl(0, TCSETS, (char *) &termios) < 0) {
printk("parent_linux_grab_console: ioctl(TCSETS) -> %d\n",
errno);
}
return 0;
}
int
parent_linux_release_console(void)
{
if (parent_server_ioctl(0, TCSETS,
(char *) &parent_linux_console_termios) < 0) {
printk("parent_linux_release_console: ioctl(TCSETS) -> %d\n",
errno);
}
return 0;
}
exception_mask_t
parent_linux_syscall_exc_mask(void)
{
return EXC_MASK_SYSCALL;
}
int
parent_linux_get_mach_privilege(void)
{
return parent_linux_ioperm(0, 0, 1); /* see sys_ioperm() */
}
int parent_linux_exit(
int code)
{
kern_return_t kr;
/*
* exit() doesn't work very well for multi-threaded processes
* in Linux: it exits only the calling thread.
* Terminate the Mach task: this should cause the Linux processes
* to exit thanks to the dead-name notifications.
*/
kr = task_terminate(mach_task_self());
if (kr != KERN_SUCCESS) {
MACH3_DEBUG(1, kr, ("parent_linux_server: task_terminate"));
}
/* try an exit if this fails... but I doubt it fails ! */
parent_linux__exit(code);
/*NOTREACHED*/
return code;
}