Updates for 1.3.7x kernels.
Fixes to TLI/XTI emulation. TLI/XTI option management.
This commit is contained in:
parent
f4b7176596
commit
bb6d03d8f6
26
CONFIG
26
CONFIG
|
@ -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
|
||||
|
||||
|
||||
|
|
36
ChangeLog
36
ChangeLog
|
@ -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.
|
||||
|
|
41
MAKEDEV.ibcs
41
MAKEDEV.ibcs
|
@ -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
6
TODO
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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
51
iBCSemul/binfmt_lib.c
Normal 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
6
iBCSemul/binfmt_lib.h
Normal 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
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
347
iBCSemul/timod.c
347
iBCSemul/timod.c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue