2
0
Fork 0

Updates for 1.3.7x kernels.

Fixes to TLI/XTI emulation.
TLI/XTI option management.
This commit is contained in:
mike 1996-03-29 17:33:41 +00:00
parent f4b7176596
commit bb6d03d8f6
19 changed files with 697 additions and 246 deletions

26
CONFIG
View file

@ -64,17 +64,27 @@ EMU_SPX = yes
EMU_XTI = yes
# XTI options.
# XTI/TLI options.
#
# Option management is the single biggest change between TLI and XTI.
# Unfortunately the header structures used in the options list are
# significantly differenet leading to incompatibilities from the
# application right down in to the kernel. For now you should almost
# certainly only enable the TLI option management.
#
# EMU_TLI_OPTMGMT Options handling exists in TLI implementations
# and is used by existing programs.
#
# EMU_XTI_OPTMGMT None of SCO 3.2.x, SCO OS5, Interactive SVR4 or
# UnixWare 1.x appear to support t_optmgmt (i.e.
# they have no struct t_opthdr definition). The SCO
# OS5 man page states that t_optmgmt is not currently
# supported and will give a TNOTSUPPORT error.
# UnixWare 1.x appear to support t_optmgmt for XTI.
# The SCO man page states that t_optmgmt is not
# currently supported for XTI and will give a
# TNOTSUPPORT error.
# Since X/Open mandates t_optmgmt we can expect it
# to be added soon. I also know that some programs
# (e.g. Informix) do try to use t_optmgmt.
# (Currently there is no real support for it in iBCS)
# to be added soon - although how we will tell the
# difference between a TLI options request and an
# XTI options request remains to be seen.
EMU_TLI_OPTMGMT = yes
EMU_XTI_OPTMGMT = no

View file

@ -1,3 +1,39 @@
Fri Mar 29 17:11:35 GMT/BST 1996
* Committing the all new TLI/XTI options handling. Note that
TLI and XTI option handling is mutually exclusive at the
moment. The default is to enable TLI options handling since
that is what existing SVR3/4 systems use. I haven't found
one that actually handles X/Open format (they use the
TNOTSUPPORT cop out) so I don't know how the stack is
told to use XTI format instead of TLI.
Note that only SOL_SOCKET/* and SOL_TCP/TCP_NDELAY are
known to work to any extent at the moment. Others may (or
may not need mapping) but I can't find the motivation to
wade through the headers and create yet another table of
magic numbers. Hopefully everyone just nicked the BSD
reference code...
-- Mike
* Some more 1.3.7x changes related to process accounting
(fork but no exec etc.).
-- Mike
Wed Mar 20 13:36:07 GMT/BST 1996
* I seem to have forgotten to add a comment about merging
changes from mid 1.3.7x kernels.
-- Mike
Wed Feb 28 14:53:00 GMT/BST 1996
* Fix to shared library loader in binfmt_aout.c from kernel
patch 1.3.69.
-- Mike
Wed Jan 24 09:58:34 GMT/BST 1996
* Implemented I_PEEK.

View file

@ -13,29 +13,46 @@ if [ -r /proc/devices ]; then
fi
rm -f socksys nfsd
mknod -m 0666 socksys c $(SOCKSYS_MAJOR) 0
mknod -m 0666 socksys c ${SOCKSYS_MAJOR} 0
ln socksys nfsd
rm -f spx X0R
mknod -m 0666 spx c $(SOCKSYS_MAJOR) 1
mknod -m 0666 spx c ${SOCKSYS_MAJOR} 1
ln spx X0R
rm -fr inet
rm -f ip icmp ggp ipip tcp egp pup udp idp rawip arp rip
mkdir -m 0755 inet
mknod -m 0666 inet/ip c $(SOCKSYS_MAJOR) 32
mknod -m 0666 inet/icmp c $(SOCKSYS_MAJOR) 33
mknod -m 0666 inet/ggp c $(SOCKSYS_MAJOR) 34
mknod -m 0666 inet/ipip c $(SOCKSYS_MAJOR) 35
mknod -m 0666 inet/tcp c $(SOCKSYS_MAJOR) 36
mknod -m 0666 inet/egp c $(SOCKSYS_MAJOR) 37
mknod -m 0666 inet/pup c $(SOCKSYS_MAJOR) 38
mknod -m 0666 inet/udp c $(SOCKSYS_MAJOR) 39
mknod -m 0666 inet/idp c $(SOCKSYS_MAJOR) 40
mknod -m 0666 inet/rawip c $(SOCKSYS_MAJOR) 41
mknod -m 0666 inet/ip c ${SOCKSYS_MAJOR} 32
mknod -m 0666 inet/icmp c ${SOCKSYS_MAJOR} 33
mknod -m 0666 inet/ggp c ${SOCKSYS_MAJOR} 34
mknod -m 0666 inet/ipip c ${SOCKSYS_MAJOR} 35
mknod -m 0666 inet/tcp c ${SOCKSYS_MAJOR} 36
mknod -m 0666 inet/egp c ${SOCKSYS_MAJOR} 37
mknod -m 0666 inet/pup c ${SOCKSYS_MAJOR} 38
mknod -m 0666 inet/udp c ${SOCKSYS_MAJOR} 39
mknod -m 0666 inet/idp c ${SOCKSYS_MAJOR} 40
mknod -m 0666 inet/rawip c ${SOCKSYS_MAJOR} 41
ln inet/udp inet/arp
ln inet/udp inet/rip
for i in ip icmp ggp ipip tcp egp pup udp idp rawip arp rip
do
ln inet/$i $i
done
# SCO compatible pseudo terminal names:
n=0
for a in p q r # s t u v w x y z a b c d e
do
for b in 0 1 2 3 4 5 6 7 8 9 a b c d e f
do
if [ ! -e ptyp$n -a ! -e ttyp$n ] || [ -L ptyp$n -a -L ttyp$n ]
then
rm -f ptyp$n ttyp$n
ln -s pty$a$b ptyp$n
ln -s tty$a$b ttyp$n
fi
n=`expr $n + 1`
done
done

Binary file not shown.

6
TODO
View file

@ -34,6 +34,7 @@ in libnsl_s.
The T_MORE flag on t_snd() and t_rcv() marks message boundaries. Strictly
these should be preserved end-to-end. Possible across sockets?
(X/Open specify that message boundaries shouldn't be relied on with TCP)
Need I_SETSIG ioctl to enable SIGPOLL on available input etc. Note that
a control message counts as input. This should interface with poll() too.
@ -51,6 +52,9 @@ events? Should we assume that any getmsg() on an idle SOCK_STREAM with
no outstanding control messages is an attempt to get a connection event?
It will probably work with most code even if it isn't strictly correct
I think...
(A T_BIND_REQ contains a CONIND_number that, I think, gives the number
of outstanding connections to allow at once. If it is non-zero we should
do a listen but not otherwise. I think.)
Could we make socksys/TLI a separate module?
@ -60,7 +64,7 @@ you have T_BIND_REQ in the message but TI_GETINFO as the ioctl command
timod will do a bind. Currently we use the TI_* by preference. This
needs to change to avoid breaking programs that worked on SCO even
though broken. It shouldn't be _essential_ though as all this is
normally hidden in libnsl_s.
normally hidden in libnsl_s so should be consistent.
Connects are currently forced synchronous. It wouldn't be too much
to allow them to happen asynchronously but the async confirmation

View file

@ -1,7 +1,7 @@
#
# Makefile for the iBCS emulator files
#
# $Id: Makefile,v 1.53 1996/01/18 16:10:25 mike Exp $
# $Id: Makefile,v 1.54 1996/03/29 17:33:22 mike Exp $
# $Source: /nfs4/sophia/home/mjagdis/src/ibcs.cvs/ibcs/iBCSemul/Makefile,v $
#
@ -18,7 +18,8 @@ EMUOPTS =
OBJS = emulate.o map.o coff.o hrtsys.o ioctl.o ipc.o mmap.o open.o \
secureware.o socket.o poll.o ptrace.o signal.o socksys.o stat.o \
stream.o sysconf.o sysfs.o sysi86.o sysinfo.o sysisc.o syslocal.o \
timod.o ulimit.o utsname.o vtkd.o wysev386.o xnx.o xstat.o
timod.o ulimit.o utsname.o vtkd.o wysev386.o xnx.o xstat.o \
binfmt_lib.o
ifeq ($(HAVE_QUOTA),yes)
EMUOPTS := $(EMUOPTS) -DHAVE_QUOTA
@ -54,6 +55,9 @@ endif
ifeq ($(EMU_XTI),yes)
EMUOPTS := $(EMUOPTS) -DEMU_XTI
endif
ifeq ($(EMU_TLI_OPTMGMT),yes)
EMUOPTS := $(EMUOPTS) -DEMU_TLI_OPTMGMT
endif
ifeq ($(EMU_XTI_OPTMGMT),yes)
EMUOPTS := $(EMUOPTS) -DEMU_XTI_OPTMGMT
endif

View file

@ -1,7 +1,7 @@
/*
* Copyright 1995 Mike Jagdis (jaggy@purplet.demon.co.uk)
* Copyright 1995-1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
*
* $Id: binfmt_aout.c,v 1.2 1996/01/12 17:27:15 mike Exp $
* $Id: binfmt_aout.c,v 1.3 1996/03/29 17:33:23 mike Exp $
* $Source: /nfs4/sophia/home/mjagdis/src/ibcs.cvs/ibcs/iBCSemul/binfmt_aout.c,v $
*
* Derived from original Linux code:
@ -47,6 +47,8 @@
#include <ibcs/trace.h>
#endif
#include "binfmt_lib.h"
static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout_library(int fd);
@ -184,6 +186,9 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->mm->mmap = NULL;
current->suid = current->euid = current->fsuid = bprm->e_uid;
current->sgid = current->egid = current->fsgid = bprm->e_gid;
#ifdef PF_FORKNOEXEC
current->flags &= ~PF_FORKNOEXEC;
#endif
/* If the file offset is not on a filesystem block boundary treat
* the file as impure and slurp the lot in. Theory says we should
@ -272,6 +277,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)++;
#if LINUX_VERSION_CODE < 66375
p += setup_arg_pages(ex.a_text,bprm->page);
p -= MAX_ARG_PAGES*PAGE_SIZE;
#ifdef __NR_getsid
@ -282,6 +288,12 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
bprm->argc, bprm->envc,
current->personality != PER_LINUX);
#endif
#else
p = setup_arg_pages(p, bprm);
p = (unsigned long)create_ibcs_tables((char *)p, bprm,
current->personality != PER_LINUX);
#endif
current->mm->start_stack = p;
start_thread(regs, ex.a_entry, p);
if (current->flags & PF_PTRACED)
@ -354,10 +366,15 @@ static int load_aout_library(int fd)
}
len = PAGE_ALIGN(ex.a_text + ex.a_data);
bss = ex.a_text + ex.a_data + ex.a_bss;
if (bss > len)
do_mmap(NULL, start_addr + len, bss-len,
if (bss > len) {
error = do_mmap(NULL, start_addr + len, bss-len,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_FIXED, 0);
if (error != start_addr + len) {
MOD_DEC_USE_COUNT;
return error;
}
}
MOD_DEC_USE_COUNT;
return 0;
}

View file

@ -60,6 +60,8 @@
#include <ibcs/trace.h>
#endif
#include "binfmt_lib.h"
static int load_coff_binary(struct linux_binprm *bprm, struct pt_regs *regs);
static int load_coff_library(int fd);
@ -206,6 +208,7 @@ load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok)
short int aout_size = 0; /* Size of the a.out header area */
short int flags; /* Flag bits from the COFF header */
char not_pageable = 0; /* Can we demand page the executable? */
unsigned long p = bprm->p;
#ifdef COFF_TRACE
if (ibcs_trace & TRACE_COFF_LD)
@ -562,19 +565,23 @@ load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok)
/*
* Construct the parameter and environment string table entries.
*/
#if LINUX_VERSION_CODE < 66375
#ifdef STACK_TOP
bprm->p += setup_arg_pages (0, bprm->page);
bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
bprm->p = (unsigned long) create_tables ((char *) bprm->p,
bprm, 1);
p += setup_arg_pages (0, bprm->page);
p -= MAX_ARG_PAGES*PAGE_SIZE;
p = (unsigned long) create_tables ((char *) p, bprm, 1);
#else
bprm->p += change_ldt (0, bprm->page);
bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
bprm->p = (unsigned long) create_tables ((char *) bprm->p,
p += change_ldt (0, bprm->page);
p -= MAX_ARG_PAGES*PAGE_SIZE;
p = (unsigned long) create_tables ((char *) p,
bprm->argc,
bprm->envc,
1);
#endif
#else
p = setup_arg_pages(p, bprm);
p = (unsigned long)create_ibcs_tables((char *)p, bprm, 1);
#endif
/*
* Do the end processing once the stack has been constructed
*/
@ -583,7 +590,7 @@ load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok)
current->MM(end_data) = data_vaddr + data_size;
current->MM(start_brk) =
current->MM(brk) = bss_vaddr + bss_size;
current->MM(start_stack) = bprm->p;
current->MM(start_stack) = p;
#ifdef INIT_MM
current->suid = current->euid = current->fsuid = bprm->e_uid;
current->sgid = current->egid = current->fsgid = bprm->e_gid;
@ -591,6 +598,9 @@ load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok)
current->suid = current->euid = bprm->e_uid;
current->sgid = current->egid = bprm->e_gid;
#endif
#ifdef PF_FORKNOEXEC
current->flags &= ~PF_FORKNOEXEC;
#endif
#ifndef VM_STACK_FLAGS
current->executable = bprm->inode; /* Store inode for file */
++bprm->inode->i_count; /* Count the open inode */
@ -957,7 +967,6 @@ parse_comments (struct linux_binprm *exe_bprm, COFF_SCNHDR * sect)
{
unsigned long offset, nbytes;
char *buffer;
int old_fs;
int status;
/*
@ -980,7 +989,7 @@ parse_comments (struct linux_binprm *exe_bprm, COFF_SCNHDR * sect)
status = read_exec(exe_bprm->inode, offset, buffer,
nbytes > PAGE_SIZE ? PAGE_SIZE : nbytes, 1);
#else
old_fs = get_fs();
int old_fs = get_fs();
set_fs(get_ds());
status = read_exec(exe_bprm->inode, offset,
buffer,
@ -1098,7 +1107,9 @@ load_coff_library (int fd)
else {
struct file *file; /* Pointer to the file table */
struct pt_regs regs; /* Register work area */
#ifndef STACK_TOP
int old_fs = get_fs (); /* Previous FS register value */
#endif
memset (bprm, '\0', sizeof (struct linux_binprm));

View file

@ -125,6 +125,7 @@ unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exe
{
unsigned long *argv,*envp, *dlinfo;
unsigned long * sp;
#if LINUX_VERSION_CODE < 66375
struct vm_area_struct *mpnt;
mpnt = (struct vm_area_struct *)kmalloc(sizeof(*mpnt), GFP_KERNEL);
@ -159,6 +160,7 @@ unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exe
current->MM(stk_vma) = mpnt;
#endif
}
#endif
sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
if(exec) sp -= DLINFO_ITEMS*2;
dlinfo = sp;
@ -226,7 +228,8 @@ static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
int retval;
unsigned int last_bss;
int error;
int i, k;
int i;
unsigned int k;
elf_bss = 0;
last_bss = 0;
@ -275,26 +278,28 @@ static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
if (interp_elf_ex->e_type == ET_EXEC) {
if (interp_elf_ex->e_type == ET_EXEC || load_addr != 0) {
elf_type |= MAP_FIXED;
vaddr = eppnt->p_vaddr;
}
error = do_mmap(file,
vaddr & 0xfffff000,
load_addr + (vaddr & 0xfffff000),
eppnt->p_filesz + (vaddr & 0xfff),
elf_prot,
elf_type,
eppnt->p_offset & 0xfffff000);
#else
error = do_mmap(file,
eppnt->p_vaddr & 0xfffff000,
load_addr + (eppnt->p_vaddr & 0xfffff000),
eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
PROT_READ | PROT_WRITE | PROT_EXEC,
#ifdef MAP_EXECUTABLE
MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE | (interp_elf_ex->e_type == ET_EXEC ? MAP_FIXED : 0),
#else
# ifdef MAP_DENYWRITE
MAP_PRIVATE | MAP_DENYWRITE | (interp_elf_ex->e_type == ET_EXEC ? MAP_FIXED : 0),
MAP_PRIVATE | MAP_DENYWRITE |
((interp_elf_ex->e_type == ET_EXEC || load_addr)
? MAP_FIXED : 0),
# else
MAP_PRIVATE | (interp_elf_ex->e_type == ET_EXEC ? MAP_FIXED : 0),
# endif
@ -540,7 +545,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
elf_stack = 0xffffffff;
elf_interpreter = NULL;
start_code = 0;
start_code = 0xffffffff;
end_code = 0;
end_data = 0;
@ -556,6 +561,16 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
GFP_KERNEL);
if (elf_interpreter == NULL) {
#ifndef STACK_TOP
set_fs(old_fs);
#endif
kfree (elf_phdata);
kfree(elf_interpreter);
SYS(close)(elf_exec_fileno);
MOD_DEC_USE_COUNT;
return -ENOMEM;
}
#ifdef STACK_TOP
retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter,
@ -601,6 +616,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
#endif
kfree (elf_phdata);
kfree(elf_interpreter);
SYS(close)(elf_exec_fileno);
MOD_DEC_USE_COUNT;
return retval;
}
@ -618,6 +634,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if(retval < 0) {
kfree(elf_interpreter);
kfree(elf_phdata);
SYS(close)(elf_exec_fileno);
MOD_DEC_USE_COUNT;
return -ELIBACC;
}
@ -635,6 +652,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
kfree(elf_interpreter);
kfree(elf_phdata);
SYS(close)(elf_exec_fileno);
MOD_DEC_USE_COUNT;
return -ELIBBAD;
}
@ -660,6 +678,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
kfree(elf_interpreter);
}
kfree (elf_phdata);
SYS(close)(elf_exec_fileno);
MOD_DEC_USE_COUNT;
return -E2BIG;
}
@ -677,8 +696,12 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
current->MM(rss) = 0;
#if LINUX_VERSION_CODE < 66375
#ifndef STACK_TOP
bprm->p += setup_arg_pages(0, bprm->page);
#endif
#else
bprm->p = setup_arg_pages(bprm->p, bprm);
#endif
current->MM(start_stack) = bprm->p;
@ -756,10 +779,14 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if(!load_addr)
load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
k = elf_ppnt->p_vaddr;
if(k > start_code) start_code = k;
if(k < start_code) start_code = k;
k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
if(k > elf_bss) elf_bss = k;
#ifdef PF_X
if((elf_ppnt->p_flags & PF_X) && end_code < k)
#else
if((elf_ppnt->p_flags | PROT_WRITE) && end_code < k)
#endif
end_code = k;
if(end_data < k) end_data = k;
k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
@ -791,9 +818,11 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
bprm->inode->i_count++;
#endif
#ifdef LOW_ELF_STACK
current->start_stack = p = elf_stack - 4;
current->start_stack = bprm->p = elf_stack - 4;
#endif
#if LINUX_VERSION_CODE < 66375
bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
#endif
bprm->p = (unsigned long)
create_elf_tables((char *)bprm->p,
bprm->argc,
@ -816,6 +845,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->suid = current->euid = bprm->e_uid;
current->sgid = current->egid = bprm->e_gid;
#endif
#ifdef PF_FORKNOEXEC
current->flags &= ~PF_FORKNOEXEC;
#endif
/* Calling sys_brk effectively mmaps the pages that we need for the bss and break
sections */

51
iBCSemul/binfmt_lib.c Normal file
View file

@ -0,0 +1,51 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/a.out.h>
#include <linux/malloc.h>
#include <linux/sched.h>
#include <linux/user.h>
#include <asm/pgtable.h>
#if LINUX_VERSION_CODE >= 66375
unsigned long *
create_ibcs_tables(char *p, struct linux_binprm *bprm, int ibcs)
{
unsigned long *argv,*envp;
unsigned long * sp;
int argc = bprm->argc;
int envc = bprm->envc;
sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
sp -= envc+1;
envp = sp;
sp -= argc+1;
argv = sp;
if (!ibcs) {
put_user(envp,--sp);
put_user(argv,--sp);
}
put_user(argc,--sp);
current->mm->arg_start = (unsigned long) p;
while (argc-->0) {
put_user(p,argv++);
while (get_user(p++)) /* nothing */ ;
}
put_user(NULL,argv);
current->mm->arg_end = current->mm->env_start = (unsigned long) p;
while (envc-->0) {
put_user(p,envp++);
while (get_user(p++)) /* nothing */ ;
}
put_user(NULL,envp);
current->mm->env_end = (unsigned long) p;
return sp;
}
#endif

6
iBCSemul/binfmt_lib.h Normal file
View file

@ -0,0 +1,6 @@
#if LINUX_VERSION_CODE >= 66375
extern unsigned long *
create_ibcs_tables(char *p, struct linux_binprm *bprm, int ibcs);
#endif

View file

@ -3,7 +3,7 @@
*
* Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk)
*
* $Id: binfmt_xout.c,v 1.29 1995/06/22 12:11:23 mike Exp $
* $Id: binfmt_xout.c,v 1.30 1996/03/29 17:33:30 mike Exp $
* $Source: /nfs4/sophia/home/mjagdis/src/ibcs.cvs/ibcs/iBCSemul/binfmt_xout.c,v $
*
* This file is based upon code written by Al Longyear for the COFF file
@ -42,6 +42,8 @@
#include <ibcs/trace.h>
#endif
#include "binfmt_lib.h"
/* If you compile with XOUT_FORCE_PAGE defined (the default)
* then if all segments are aligned on 1k bounaries within the
@ -388,6 +390,7 @@ load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok)
/*
* Construct the parameter and environment string table entries.
*/
#if LINUX_VERSION_CODE < 66375
bprm->p += change_ldt(0, bprm->page);
bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
#ifdef __NR_getdents
@ -398,6 +401,10 @@ load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok)
bprm->argc,
bprm->envc,
#endif
#else
bprm->p = setup_arg_pages(bprm->p, bprm);
bprm->p = (unsigned long)create_ibcs_tables((char *)bprm->p, bprm,
#endif
#ifdef EMU_X286
(xexec->x_cpu & XC_CPU) == XC_386
? 1 : 0);
@ -431,6 +438,9 @@ load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok)
current->suid = current->euid = bprm->e_uid;
current->sgid = current->egid = bprm->e_gid;
#endif
#ifdef PF_FORKNOEXEC
current->flags &= ~PF_FORKNOEXEC;
#endif
#ifndef VM_STACK_FLAGS
current->executable = bprm->inode; /* Store inode for file */
++bprm->inode->i_count; /* Count the open inode */
@ -706,6 +716,7 @@ seg_again:
}
}
}
#ifdef XOUT_SEGMENTS
if (status >= 0 && !ntext && s->xs_seg == 0x47) {
/* Uh oh, impure binary. Mirror this data
* segment to the text segment.
@ -715,6 +726,7 @@ seg_again:
s->xs_type = XS_TTEXT;
goto seg_again;
}
#endif
}
}

View file

@ -6,7 +6,7 @@
* Written by Drew Sullivan.
* Rewritten by Mike Jagdis.
*
* $Id: ioctl.c,v 1.44 1996/01/24 10:22:29 mike Exp $
* $Id: ioctl.c,v 1.45 1996/03/29 17:33:31 mike Exp $
* $Source: /nfs4/sophia/home/mjagdis/src/ibcs.cvs/ibcs/iBCSemul/ioctl.c,v $
*/
#include <linux/config.h>
@ -774,7 +774,7 @@ static int ibcs_ioctl_termiox(int fd, unsigned int func, void *arg) {
}
memcpy_fromfs(&tx, arg, sizeof(struct termiox));
if ((tx.x_hflag != 0 && tx.x_hflag != RTSXOFF|CTSXON)
if ((tx.x_hflag != 0 && tx.x_hflag != (RTSXOFF|CTSXON))
|| tx.x_cflag || tx.x_rflag[0] || tx.x_rflag[1]
|| tx.x_rflag[2] || tx.x_rflag[3] || tx.x_rflag[4]
|| tx.x_sflag)

View file

@ -94,7 +94,7 @@ static int check(int flag, select_table * wait, struct file * file)
int ibcs_poll(struct poll * ufds, size_t nfds, int timeout)
{
int i,j, count, fdcount, error, retflag;
int i,j, count, fdcount, error;
struct poll * fdpnt;
struct poll * fds, *fds1;
select_table wait_table, *wait;
@ -155,15 +155,17 @@ repeat:
#endif
if ((fdpnt->events & LINUX_POLLIN)
&& check(SEL_IN, wait, current->FD[i])) {
int event = 0;
if (fdpnt->events & POLLIN)
retflag = POLLIN;
event = POLLIN;
if (fdpnt->events & POLLRDNORM)
retflag = POLLRDNORM;
event = POLLRDNORM;
#if 0
if (fdpnt->events & POLLRDBAND)
retflag = POLLRDBAND;
event = POLLRDBAND;
#endif
fdpnt->revents |= retflag;
fdpnt->revents |= event;
count++;
wait = NULL;
}

View file

@ -1,9 +1,9 @@
/*
* linux/ibcs/socket.c
*
* Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk)
* Copyright (C) 1994, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
*
* $Id: socket.c,v 1.6 1995/03/02 11:48:41 mike Exp $
* $Id: socket.c,v 1.7 1996/03/29 17:33:33 mike Exp $
* $Source: /nfs4/sophia/home/mjagdis/src/ibcs.cvs/ibcs/iBCSemul/socket.c,v $
*/
@ -28,7 +28,7 @@
#include <ibcs/ibcs.h>
#include <ibcs/socket.h>
#include <ibcs/map.h>
#include <ibcs/trace.h>
int
@ -43,63 +43,51 @@ ibcs_setsockopt(unsigned long *sp)
if (error)
return error;
/* As far as I can see SCO doesn't support anything other than
* socket level options and uses 0xffff for these.
* XXXXX This may need mapping.
*/
level = (int)get_fs_long(((unsigned long *)sp)+1);
if (level != 0xffff)
return -ENOPROTOOPT;
put_fs_long(SOL_SOCKET, ((unsigned long *)sp)+1);
optname = (int)get_fs_long(((unsigned long *)sp)+2);
optname = map_value(sopt_map, optname, 0);
put_fs_long(optname, ((unsigned long *)sp)+2);
switch (optname) {
/* The following are all supported by Linux and seem to take compatible
* arguments.
*/
case SO_DEBUG:
case SO_REUSEADDR:
case SO_TYPE:
case SO_ERROR:
case SO_DONTROUTE:
case SO_BROADCAST:
case SO_SNDBUF:
case SO_RCVBUF:
case SO_KEEPALIVE:
case SO_OOBINLINE:
case SO_NO_CHECK:
case SO_PRIORITY:
case SO_LINGER:
case SO_ACCEPTCONN:
return SYS(socketcall)(SYS_SETSOCKOPT, sp);
switch (level) {
case 0xffff:
put_fs_long(SOL_SOCKET, ((unsigned long *)sp)+1);
optname = map_value(sopt_map, optname, 0);
put_fs_long(optname, ((unsigned long *)sp)+2);
/* The following are not currently implemented under Linux so we
* must fake them in reasonable ways. (Only SO_PROTOTYPE is documented
* in SCO's man page).
*/
switch (optname) {
/* The following are not currently implemented
* under Linux so we must fake them in
* reasonable ways. (Only SO_PROTOTYPE is
* documented in SCO's man page).
*/
case SO_PROTOTYPE:
case SO_ORDREL:
case SO_SNDTIMEO:
case SO_RCVTIMEO:
return -ENOPROTOOPT;
case SO_PROTOTYPE:
case SO_ORDREL:
case SO_SNDTIMEO:
case SO_RCVTIMEO:
return -ENOPROTOOPT;
case SO_USELOOPBACK:
case SO_SNDLOWAT:
case SO_RCVLOWAT:
return 0;
case SO_USELOOPBACK:
case SO_SNDLOWAT:
case SO_RCVLOWAT:
return 0;
/* The following are not currenty implemented
* under Linux and probably aren't settable
* anyway.
*/
case SO_IMASOCKET:
return -ENOPROTOOPT;
}
/* The following are not currenty implemented under Linux and probably
* aren't settable anyway.
*/
case SO_IMASOCKET:
return -ENOPROTOOPT;
default:
/* FIXME: We assume everything else uses the
* same level and option numbers. This is true
* for IPPROTO_TCP(/SOL_TCP) and TCP_NDELAY
* but is known to be incorrect for other
* potential options :-(.
*/
break;
}
return -ENOPROTOOPT;
return SYS(socketcall)(SYS_SETSOCKOPT, sp);
}
@ -108,6 +96,8 @@ ibcs_getsockopt(unsigned long *sp)
{
int error;
int level, optname;
char *optval;
long *optlen;
error = verify_area(VERIFY_READ,
((unsigned long *)sp),
@ -115,92 +105,90 @@ ibcs_getsockopt(unsigned long *sp)
if (error)
return error;
/* As far as I can see SCO doesn't support anything other than
* socket level options and uses 0xffff for these.
* XXXXX This may need mapping.
*/
level = (int)get_fs_long(((unsigned long *)sp)+1);
if (level != 0xffff)
return -ENOPROTOOPT;
put_fs_long(SOL_SOCKET, ((unsigned long *)sp)+1);
optname = (int)get_fs_long(((unsigned long *)sp)+2);
optname = map_value(sopt_map, optname, 0);
put_fs_long(optname, ((unsigned long *)sp)+2);
optval = (char *)get_fs_long(((unsigned long *)sp)+3);
optlen = (long *)get_fs_long(((unsigned long *)sp)+4);
switch (optname) {
/* The following are all supported by Linux and seem to take compatible
* arguments.
*/
case SO_DEBUG:
case SO_REUSEADDR:
case SO_TYPE:
case SO_ERROR:
case SO_DONTROUTE:
case SO_BROADCAST:
case SO_SNDBUF:
case SO_RCVBUF:
case SO_KEEPALIVE:
case SO_OOBINLINE:
case SO_NO_CHECK:
case SO_PRIORITY:
case SO_LINGER:
case SO_ACCEPTCONN:
return SYS(socketcall)(SYS_GETSOCKOPT, sp);
#ifdef IBCS_TRACE
if ((ibcs_trace & (TRACE_STREAMS|TRACE_SOCKSYS))) {
printk(KERN_DEBUG "iBCS: getsockopt level=%d, "
"optname=%d, optval=0x%08lx, optlen=0x%08lx\n",
level, optname, (unsigned long)optval,
(unsigned long)optlen);
}
#endif
/* The following are not currently implemented under Linux so we
* must fake them in reasonable ways. (Only SO_PROTOTYPE is documented
* in SCO's man page).
*/
switch (level) {
case 0xffff:
put_fs_long(SOL_SOCKET, ((unsigned long *)sp)+1);
optname = map_value(sopt_map, optname, 0);
put_fs_long(optname, ((unsigned long *)sp)+2);
case SO_PROTOTYPE: {
char *optval = (char *)get_fs_long(((unsigned long *)sp)+3);
char *optlen = (char *)get_fs_long(((unsigned long *)sp)+4);
switch (optname) {
/* The following are not currently implemented
* under Linux so we must fake them in
* reasonable ways. (Only SO_PROTOTYPE is
* documented in SCO's man page).
*/
case SO_PROTOTYPE: {
error = verify_area(VERIFY_WRITE,
(char *)optlen,
sizeof(long));
if (error)
return error;
if (get_fs_long(optlen) < sizeof(long))
return -EINVAL;
error = verify_area(VERIFY_WRITE, (char *)optlen,
sizeof(long));
if (error)
return error;
if (get_fs_long(optlen) < sizeof(long))
return -EINVAL;
error = verify_area(VERIFY_WRITE,
(char *)optval,
sizeof(long));
if (!error) {
put_fs_long(0, optval);
put_fs_long(sizeof(long),
optlen);
}
return error;
}
error = verify_area(VERIFY_WRITE, (char *)optval,
sizeof(long));
if (!error) {
put_fs_long(0, optval);
put_fs_long(sizeof(long), optlen);
case SO_ORDREL:
case SO_SNDTIMEO:
case SO_RCVTIMEO:
return -ENOPROTOOPT;
case SO_USELOOPBACK:
case SO_SNDLOWAT:
case SO_RCVLOWAT:
case SO_IMASOCKET: {
error = verify_area(VERIFY_WRITE,
(char *)optlen,
sizeof(long));
if (error)
return error;
if (get_fs_long(optlen) < sizeof(long))
return -EINVAL;
error = verify_area(VERIFY_WRITE,
(char *)optval,
sizeof(long));
if (!error) {
put_fs_long(1, optval);
put_fs_long(sizeof(long),
optlen);
}
return error;
}
}
return error;
}
case SO_ORDREL:
case SO_SNDTIMEO:
case SO_RCVTIMEO:
return -ENOPROTOOPT;
case SO_USELOOPBACK:
case SO_SNDLOWAT:
case SO_RCVLOWAT:
case SO_IMASOCKET: {
char *optval = (char *)get_fs_long(((unsigned long *)sp)+3);
char *optlen = (char *)get_fs_long(((unsigned long *)sp)+4);
error = verify_area(VERIFY_WRITE, (char *)optlen,
sizeof(long));
if (error)
return error;
if (get_fs_long(optlen) < sizeof(long))
return -EINVAL;
error = verify_area(VERIFY_WRITE, (char *)optval,
sizeof(long));
if (!error) {
put_fs_long(1, optval);
put_fs_long(sizeof(long), optlen);
}
return error;
}
default:
/* FIXME: We assume everything else uses the
* same level and option numbers. This is true
* for IPPROTO_TCP(/SOL_TCP) and TCP_NDELAY
* but is known to be incorrect for other
* potential options :-(.
*/
break;
}
return -ENOPROTOOPT;
return SYS(socketcall)(SYS_GETSOCKOPT, sp);
}

View file

@ -1,9 +1,9 @@
/*
* linux/ibcs/socksys.h
*
* Copyright 1994, 1995 Mike Jagdis (jaggy@purplet.demon.co.uk)
* Copyright 1994-1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
*
* $Id: socksys.c,v 1.44 1996/01/24 10:22:32 mike Exp $
* $Id: socksys.c,v 1.45 1996/03/29 17:33:35 mike Exp $
* $Source: /nfs4/sophia/home/mjagdis/src/ibcs.cvs/ibcs/iBCSemul/socksys.c,v $
*/
@ -54,7 +54,7 @@ static int socksys_select(struct inode *ino, struct file *filep,
int sel_type, select_table *wait);
static int spx_write(struct inode *ino, struct file *filep,
char *buf, int count);
const char *buf, int count);
/* spx_fops defines the file operations that can be applied to the
* /dev/spx server devices.
@ -647,7 +647,7 @@ ibcs_ioctl_socksys(int fd, unsigned int cmd, void *arg)
static int
spx_write(struct inode *ino, struct file *filep, char *buf, int count)
spx_write(struct inode *ino, struct file *filep, const char *buf, int count)
{
int newfd, err, args[3];
struct sockaddr_un addr = {
@ -851,7 +851,7 @@ socksys_open(struct inode *ino, struct file *filep)
MOD_DEC_USE_COUNT;
return err;
}
priv->state = T_UNBND;
priv->state = TS_UNBND;
priv->offset = 0;
priv->pfirst = priv->plast = NULL;
#endif

View file

@ -1,9 +1,9 @@
/*
* linux/ibcs/timod.c
*
* Copyright 1995 Mike Jagdis (jaggy@purplet.demon.co.uk)
* Copyright 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
*
* $Id: timod.c,v 1.18 1996/01/24 10:22:34 mike Exp $
* $Id: timod.c,v 1.19 1996/03/29 17:33:36 mike Exp $
* $Source: /nfs4/sophia/home/mjagdis/src/ibcs.cvs/ibcs/iBCSemul/timod.c,v $
*/
@ -134,12 +134,26 @@ timod_error(int fd, int prim, int terr, int uerr)
}
#ifdef EMU_XTI_OPTMGMT
#if defined(EMU_XTI_OPTMGMT) || defined(EMU_TLI_OPTMGMT)
# if defined(EMU_XTI_OPTMGMT) && defined(EMU_TLI_OPTMGMT)
# error unable to support _both_ TLI and XTI option management
/* This is because TLI and XTI options buffers are
* incompatible and there is no clear way to detect
* which format we are dealing with here. Existing
* systems appear to have TLI options management
* implemented but return TNOTSUPPORT for XTI requests.
*/
# endif
static int
timod_optmgmt(int fd, int flags, char *opt_buf, int opt_len,
char *ret_buf, int ret_len)
timod_optmgmt(int fd, struct pt_regs *regs,
int flag, char *opt_buf, int opt_len, int do_ret)
{
int error;
int is_tli, error, failed;
unsigned long old_esp, *tsp;
char *ret_buf, *ret_base;
int ret_len, ret_space;
if (opt_buf && opt_len > 0) {
error = verify_area(VERIFY_READ, opt_buf, opt_len);
@ -147,45 +161,273 @@ timod_optmgmt(int fd, int flags, char *opt_buf, int opt_len,
return error;
}
if (opt_buf) while (opt_len >= sizeof(struct t_opthdr)) {
struct t_opthdr opt;
/* FIXME: We should be able to detect the difference between
* TLI and XTI requests at run time?
*/
#ifdef EMU_TLI_OPTMGMT
is_tli = 1;
#else
is_tli = 0;
#endif
memcpy_fromfs(&opt, opt_buf, sizeof(struct t_opthdr));
if (opt.len > opt_len)
return -EINVAL;
if (!do_ret && (!opt_buf || opt_len <= 0))
return 0;
/* Grab some space on the user stack to work with. We need 6 longs
* to build an argument frame for [gs]etsockopt calls. We also
* need space to build the return buffer. This will be at least
* as big as the given options buffer but the given options
* buffer may not include space for option values so we allow one
* long for each option multiple of the option header size
* and hope that big options will not exhaust our space and
* trash the stack.
*/
ret_space = 4*PAGE_SIZE + opt_len
+ sizeof(long)*(opt_len / (is_tli ? sizeof(struct opthdr) : sizeof(struct t_opthdr)));
ret_buf = ret_base = (char *)(regs->esp - ret_space);
ret_len = 0;
old_esp = regs->esp;
regs->esp -= ret_space + 6*sizeof(long);
tsp = (unsigned long *)(regs->esp);
error = verify_area(VERIFY_WRITE, tsp, 6*sizeof(long));
if (error) {
regs->esp = old_esp;
return error;
}
failed = 0;
#ifndef EMU_TLI_OPTMGMT
if (is_tli) {
printk(KERN_WARNING
"iBCS: TLI optmgmt requested but not supported\n");
}
#else
if (is_tli) while (opt_len >= sizeof(struct opthdr)) {
struct opthdr opt;
#ifdef IBCS_TRACE
if ((ibcs_trace & TRACE_STREAMS)) {
printk(KERN_DEBUG "iBCS: optmgmt fd=%d, level=%ld,"
printk(KERN_DEBUG "iBCS: TLI optmgmt opt_len=%d, "
"ret_buf=0x%08lx, ret_len=%d, ret_space=%d\n",
opt_len, (unsigned long)ret_buf,
ret_len, ret_space);
}
#endif
memcpy_fromfs(&opt, opt_buf, sizeof(struct opthdr));
if (opt.len > opt_len) {
failed = TBADOPT;
break;
}
#ifdef IBCS_TRACE
if ((ibcs_trace & TRACE_STREAMS)) {
printk(KERN_DEBUG "iBCS: TLI optmgmt fd=%d, level=%ld,"
" name=%ld, value=%ld\n",
fd, opt.level, opt.name,
get_fs_long(opt_buf+sizeof(struct opthdr)));
}
#endif
/* Check writable space in the return buffer. */
error = verify_area(VERIFY_WRITE, ret_buf, sizeof(struct opthdr));
if (error) {
failed = TSYSERR;
break;
}
/* Flag values:
* T_NEGOTIATE means try and set it.
* T_DEFAULT means get the default value.
* (return the current for now)
* T_CHECK means get the current value.
*/
error = 0;
if (flag == T_NEGOTIATE) {
put_fs_long(fd, tsp);
put_fs_long(opt.level, tsp+1);
put_fs_long(opt.name, tsp+2);
put_fs_long((int)(opt_buf+sizeof(struct opthdr)), tsp+3);
put_fs_long(opt_len, tsp+4);
error = ibcs_setsockopt(tsp);
#ifdef IBCS_TRACE
if (error && (ibcs_trace & TRACE_STREAMS)) {
printk(KERN_DEBUG "iBCS: setsockopt failed: %d\n",
error);
}
#endif
if (error) {
failed = TBADOPT;
break;
}
}
if (!error) {
put_fs_long(fd, tsp);
put_fs_long(opt.level, tsp+1);
put_fs_long(opt.name, tsp+2);
put_fs_long((int)(ret_buf+sizeof(struct opthdr)), tsp+3);
put_fs_long((int)(tsp+5), tsp+4);
put_fs_long(ret_space, tsp+5);
error = ibcs_getsockopt(tsp);
#ifdef IBCS_TRACE
if (error && (ibcs_trace & TRACE_STREAMS)) {
printk(KERN_DEBUG "iBCS: getsockopt failed: %d\n",
error);
}
#endif
if (error) {
failed = TBADOPT;
break;
}
error = get_fs_long(tsp+5);
memcpy_tofs(ret_buf, &opt, sizeof(opt));
put_fs_long(error,
&((struct opthdr *)opt_buf)->len);
ret_space -= sizeof(struct opthdr) + error;
ret_len += sizeof(struct opthdr) + error;
ret_buf += sizeof(struct opthdr) + error;
}
opt_len -= sizeof(struct opthdr) + opt.len;
opt_buf += sizeof(struct opthdr) + opt.len;
}
#endif /* EMU_TLI_OPTMGMT */
#ifndef EMU_XTI_OPTMGMT
else {
printk(KERN_WARNING
"iBCS: XTI optmgmt requested but not supported\n");
}
#else
else while (opt_len >= sizeof(struct t_opthdr)) {
struct t_opthdr opt;
memcpy_fromfs(&opt, opt_buf, sizeof(struct t_opthdr));
if (opt.len > opt_len) {
failed = 1;
break;
}
#ifdef IBCS_TRACE
if ((ibcs_trace & TRACE_STREAMS)) {
printk(KERN_DEBUG "iBCS: XTI optmgmt fd=%d, level=%ld,"
" name=%ld, value=%ld\n",
fd, opt.level, opt.name,
get_fs_long(opt_buf+sizeof(struct t_opthdr)));
}
#endif
/* Check writable space in the return buffer. */
if (verify_area(VERIFY_WRITE, ret_buf, sizeof(struct t_opthdr))) {
failed = 1;
break;
}
/* Flag values:
* T_NEGOTIATE means try and set it.
* T_CHECK means see if we could set it.
* T_DEAFULT means get the default value.
* T_CURRENT means get the current value.
* (so we just set it for now)
* T_DEFAULT means get the default value.
* (return the current for now)
* T_CURRENT means get the current value (SCO xti.h has
* no T_CURRENT???).
*/
error = 0;
if (flag == T_NEGOTIATE || flag == T_CHECK) {
put_fs_long(fd, tsp);
put_fs_long(opt.level, tsp+1);
put_fs_long(opt.name, tsp+2);
put_fs_long((int)(opt_buf+sizeof(struct t_opthdr)), tsp+3);
put_fs_long(opt_len-sizeof(struct t_opthdr), tsp+4);
error = ibcs_setsockopt(tsp);
}
if (!error) {
put_fs_long(fd, tsp);
put_fs_long(opt.level, tsp+1);
put_fs_long(opt.name, tsp+2);
put_fs_long((int)(ret_buf+sizeof(struct t_opthdr)), tsp+3);
put_fs_long((int)(tsp+5), tsp+4);
put_fs_long(ret_space, tsp+5);
error = ibcs_getsockopt(tsp);
if (!error) {
int len = get_fs_long(tsp+5);
/* FIXME: opt.status should be set... */
memcpy_tofs(ret_buf, &opt, sizeof(opt));
put_fs_long(len+sizeof(struct t_opthdr),
&((struct t_opthdr *)opt_buf)->len);
ret_space -= sizeof(struct t_opthdr) + len;
ret_len += sizeof(struct t_opthdr) + len;
ret_buf += sizeof(struct t_opthdr) + len;
}
}
failed |= error;
opt_len -= opt.len;
opt_buf += opt.len;
}
#endif /* EMU_XTI_OPTMGMT */
if (opt_len)
#if 0
/* If there is left over data the supplied options buffer was
* formatted incorrectly. But we might have done some work so
* we must fall through and return an acknowledgement I think.
*/
if (opt_len) {
regs->esp = old_esp;
return -EINVAL;
}
#endif
if (do_ret) {
struct T_primsg *it;
if (failed) {
timod_error(fd, T_OPTMGMT_REQ, failed, -error);
regs->esp = old_esp;
return 0;
}
#ifdef IBCS_TRACE
if ((ibcs_trace & TRACE_STREAMS)) {
printk(KERN_DEBUG "iBCS: optmgmt returns %d bytes,"
" failed=%d\n",
ret_len, failed);
}
#endif
/* Convert the return buffer in the user stack to a
* T_OPTMGMT_ACK
* message and queue it.
*/
it = timod_mkctl(sizeof(struct T_optmgmt_ack) + ret_len);
if (it) {
struct T_optmgmt_ack *ack
= (struct T_optmgmt_ack *)&it->type;
ack->PRIM_type = T_OPTMGMT_ACK;
ack->OPT_length = ret_len;
ack->OPT_offset = sizeof(struct T_optmgmt_ack);
ack->MGMT_flags = (failed ? T_FAILURE : flag);
memcpy_fromfs(((char *)ack)+sizeof(struct T_optmgmt_ack),
ret_base, ret_len);
it->pri = MSG_HIPRI;
it->length = sizeof(struct T_optmgmt_ack) + ret_len;
it->next = Priv(fd)->pfirst;
Priv(fd)->pfirst = it;
if (!Priv(fd)->plast)
Priv(fd)->plast = it;
timod_socket_wakeup(fd);
}
}
regs->esp = old_esp;
return 0;
}
#else /* EMU_XTI_OPTMGMT */
#else /* no EMU_XTI_OPTMGMT or EMU_TLI_OPTMGMT */
static int
timod_optmgmt(int fd, int flags, char *opt_buf, int opt_len,
char *ret_buf, int ret_len)
timod_optmgmt(int fd, struct pt_regs *regs,
int flag, char *opt_buf, int opt_len, int do_ret)
{
return -EINVAL;
}
#endif /* EMU_XTI_OPTMGMT */
#endif /* EMU_XTI_OPTMGMT or EMU_TLI_OPTMGMT */
static inline void
@ -228,22 +470,26 @@ do_getmsg(int fd, struct pt_regs *regs,
* avoid (most?) potential blocking after the select().
*/
old_esp = regs->esp;
tsp = (unsigned long *)(regs->esp - 4*PAGE_SIZE);
regs->esp -= 4*PAGE_SIZE;
tsp = (unsigned long *)regs->esp;
error = verify_area(VERIFY_WRITE, tsp, 6*sizeof(long));
regs->esp = old_esp;
if (error)
return error;
/* If this a SOCK_STREAM and is in the T_IDLE state and we want
/* If this a SOCK_STREAM and is in the TS_IDLE state and we want
* control data but none is available we assume this is a probe
* for incoming connection events. If we haven't previously
* done a listen() we need to do one now.
*/
if (ctl_maxlen > 0 && !Priv(fd)->pfirst
&& current->FD[fd]->f_inode->u.socket_i.type == SOCK_STREAM
&& Priv(fd)->state == T_IDLE) {
&& Priv(fd)->state == TS_IDLE) {
regs->esp = (unsigned long)tsp;
put_fs_long(fd, tsp);
put_fs_long(-1, tsp+1);
SYS(socketcall)(SYS_LISTEN, tsp);
regs->esp = old_esp;
}
/* If the TEP is non-blocking we must use select() to test
@ -349,12 +595,12 @@ repeat:
* an event to process or the socket has data.
*/
if (ctl_maxlen >= 0) {
/* If this a SOCK_STREAM and is in the T_IDLE state
/* If this a SOCK_STREAM and is in the TS_IDLE state
* we assume we are supposed to be looking for an
* incoming connection.
*/
if (current->FD[fd]->f_inode->u.socket_i.type == SOCK_STREAM
&& Priv(fd)->state == T_IDLE) {
&& Priv(fd)->state == TS_IDLE) {
struct T_conn_ind ind;
/* FIXME: We are going to assume the user supplied buffer is big enough.
@ -426,7 +672,7 @@ repeat:
put_fs_long((unsigned long)dat_buf, tsp+1);
put_fs_long((dat_maxlen < 0 ? 0 : dat_maxlen), tsp+2);
put_fs_long(0, tsp+3);
if (ctl_maxlen > (int)sizeof(udi) && Priv(fd)->state == T_IDLE) {
if (ctl_maxlen > (int)sizeof(udi) && Priv(fd)->state == TS_IDLE) {
put_fs_long((unsigned long)ctl_buf+sizeof(udi), tsp+4);
put_fs_long(ctl_maxlen-sizeof(udi), ctl_len);
put_fs_long((int)ctl_len, tsp+5);
@ -449,7 +695,7 @@ repeat:
return error;
if (error
&& ctl_maxlen > (int)sizeof(udi)
&& Priv(fd)->state == T_IDLE) {
&& Priv(fd)->state == TS_IDLE) {
udi.PRIM_type = T_UNITDATA_IND;
udi.SRC_length = get_fs_long(ctl_len);
udi.SRC_offset = sizeof(udi);
@ -524,8 +770,7 @@ if (i != dat_len) printk(KERN_ERR "dat: ...\n");
if (error)
return error;
if (Priv(fd)->state != T_UNINIT
&& Priv(fd)->state != T_UNBND) {
if (Priv(fd)->state != TS_UNBND) {
timod_error(fd, T_BIND_REQ, TOUTSTATE, 0);
return 0;
}
@ -560,7 +805,7 @@ if (i != dat_len) printk(KERN_ERR "dat: ...\n");
it->pri = MSG_HIPRI;
it->length = ctl_len;
it->next = NULL;
Priv(fd)->state = T_IDLE;
Priv(fd)->state = TS_IDLE;
timod_ok(fd, T_BIND_REQ);
Priv(fd)->plast->next = it;
Priv(fd)->plast = it;
@ -624,9 +869,8 @@ if (i != dat_len) printk(KERN_ERR "dat: ...\n");
if (error)
return error;
if (Priv(fd)->state != T_UNINIT
&& Priv(fd)->state != T_UNBND
&& Priv(fd)->state != T_IDLE) {
if (Priv(fd)->state != TS_UNBND
&& Priv(fd)->state != TS_IDLE) {
timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);
return 0;
}
@ -696,7 +940,7 @@ if (i != dat_len) printk(KERN_ERR "dat: ...\n");
con = (struct T_conn_con *)&it->type;
memcpy_fromfs(con, ctl_buf, ctl_len);
con->PRIM_type = T_CONN_CON;
Priv(fd)->state = T_DATAXFER;
Priv(fd)->state = TS_DATA_XFER;
} else {
struct T_discon_ind *dis;
@ -757,7 +1001,7 @@ if (i != dat_len) printk(KERN_ERR "dat: ...\n");
current->pid,
(unsigned long)current->FD[fd]);
#endif
if (Priv(fd)->state != T_DATAXFER) {
if (Priv(fd)->state != TS_DATA_XFER) {
return 0;
}
@ -793,8 +1037,8 @@ if (i != dat_len) printk(KERN_ERR "dat: ...\n");
if (error)
return error;
if (Priv(fd)->state != T_IDLE
&& Priv(fd)->state != T_DATAXFER) {
if (Priv(fd)->state != TS_IDLE
&& Priv(fd)->state != TS_DATA_XFER) {
timod_error(fd, T_UNITDATA_REQ, TOUTSTATE, 0);
return 0;
}
@ -826,7 +1070,7 @@ if (i != dat_len) printk(KERN_ERR "dat: ...\n");
}
case T_UNBIND_REQ:
Priv(fd)->state = T_UNBND;
Priv(fd)->state = TS_UNBND;
timod_ok(fd, T_UNBIND_REQ);
return 0;
@ -843,12 +1087,12 @@ if (i != dat_len) printk(KERN_ERR "dat: ...\n");
return error;
memcpy_fromfs(&req, ctl_buf, sizeof(req));
return timod_optmgmt(fd, req.MGMT_flags,
return timod_optmgmt(fd, regs, req.MGMT_flags,
req.OPT_offset > 0
? ctl_buf+req.OPT_offset
: NULL,
req.OPT_length,
NULL, 0);
1);
}
}
#if IBCS_TRACE
@ -1006,13 +1250,13 @@ timod_ioctl(struct pt_regs *regs,
}
case 3: /* TI_UNBIND */
if (Priv(fd)->state != T_IDLE)
if (Priv(fd)->state != TS_IDLE)
return TOUTSTATE;
Priv(fd)->state = T_UNBND;
Priv(fd)->state = TS_UNBND;
return 0;
case 1: { /* TI_OPTMGMT */
#ifdef EMU_XTI_OPTMGMT
#if defined(EMU_XTI_OPTMGMT) || defined(EMU_TLI_OPTMGMT)
int i;
long prim;
#ifdef IBCS_TRACE
@ -1026,9 +1270,7 @@ timod_ioctl(struct pt_regs *regs,
if (error)
return (-error << 8) | TSYSERR;
/* Get the response. This should be either
* T_OK_ACK or T_ERROR_ACK.
*/
/* Get the response to the optmgmt request. */
i = MSG_HIPRI;
error = do_getmsg(fd, regs,
arg, len, len_p,
@ -1041,22 +1283,11 @@ timod_ioctl(struct pt_regs *regs,
if (prim == T_ERROR_ACK)
return (get_fs_long(((unsigned long *)arg)+3) << 8)
| get_fs_long(((unsigned long *)arg)+2);
if (prim != T_OK_ACK)
return TBADSEQ;
/* Get the response to the optmgmt request. */
i = MSG_HIPRI;
error = do_getmsg(fd, regs,
arg, len, len_p,
NULL, -1, NULL,
&i);
if (error)
return (-error << 8) | TSYSERR;
return 0;
#else /* EMU_XTI_OPTMGMT */
#else /* no EMU_XTI_OPTMGMT or EMU_TLI_OPTMGMT */
return TNOTSUPPORT;
#endif /* EMU_XTI_OPTMGMT */
#endif /* EMU_XTI_OPTMGMT or EMU_TLI_OPTMGMT */
}
#ifdef EMU_SVR4

View file

@ -3,7 +3,7 @@
*
* Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk)
*
* $Id: socksys.h,v 1.6 1995/07/03 12:52:12 mike Exp $
* $Id: socksys.h,v 1.7 1996/03/29 17:33:41 mike Exp $
* $Source: /nfs4/sophia/home/mjagdis/src/ibcs.cvs/ibcs/include/ibcs/socksys.h,v $
*/
@ -13,6 +13,7 @@
#include <linux/route.h>
/* Get struct arpreq from linux/if_arp.h - this should be compatible. */
#include <linux/netdevice.h>
#include <linux/if_arp.h>
/* Get struct ifreq and struct ifconf from linux/if.h - these should

View file

@ -35,7 +35,7 @@ struct t_info {
#define TSTATECHNG 19
/* States. */
/* User level states (maintained internally by libnsl_s). */
#define T_UNINIT 0
#define T_UNBND 1
#define T_IDLE 2
@ -47,6 +47,26 @@ struct t_info {
#define T_FAKE 8
#define T_HACK 12
/* Kernel level states of a transport end point. */
#define TS_UNBND 0 /* unbound */
#define TS_WACK_BREQ 1 /* waiting for T_BIND_REQ ack */
#define TS_WACK_UREQ 2 /* waiting for T_UNBIND_REQ ack */
#define TS_IDLE 3 /* idle */
#define TS_WACK_OPTREQ 4 /* waiting for T_OPTMGMT_REQ ack */
#define TS_WACK_CREQ 5 /* waiting for T_CONN_REQ ack */
#define TS_WCON_CREQ 6 /* waiting for T_CONN_REQ confirmation */
#define TS_WRES_CIND 7 /* waiting for T_CONN_IND */
#define TS_WACK_CRES 8 /* waiting for T_CONN_RES ack */
#define TS_DATA_XFER 9 /* data transfer */
#define TS_WIND_ORDREL 10 /* releasing read but not write */
#define TS_WREQ_ORDREL 11 /* wait to release write but not read */
#define TS_WACK_DREQ6 12 /* waiting for T_DISCON_REQ ack */
#define TS_WACK_DREQ7 13 /* waiting for T_DISCON_REQ ack */
#define TS_WACK_DREQ9 14 /* waiting for T_DISCON_REQ ack */
#define TS_WACK_DREQ10 15 /* waiting for T_DISCON_REQ ack */
#define TS_WACK_DREQ11 16 /* waiting for T_DISCON_REQ ack */
#define TS_NOSTATES 17
/* Messages used by "timod". */
#define T_CONN_REQ 0
@ -285,6 +305,8 @@ union T_primitives {
* data buffer. This is specified in the X/Open specs but does not
* appear to exist in SCO 3.2.x, SCO OS5, Interactive SVR4 or UnixWare 1.x.
* There are programs that make options request however.
* The older TLI uses struct opthdr which is different and incompatible
* (see below).
*/
struct t_opthdr {
unsigned long len; /* *Total* length including header */
@ -294,6 +316,13 @@ struct t_opthdr {
char value[0]; /* and onwards... */
};
struct opthdr {
long level;
long name;
long len; /* Length of option value */
char value[0]; /* and onwards... */
};
struct T_primsg {
struct T_primsg *next;