diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/00-INDEX linux/Documentation/abi/00-INDEX --- linux-2.4.3/Documentation/abi/00-INDEX Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/00-INDEX Fri Mar 30 16:12:20 2001 @@ -0,0 +1,28 @@ +00-INDEX + - this file +COMPAT + - a list of software that has run succesfull under iBCS +CREDITS + - a list of people that have contributed to linux-abi or iBCS +ChangeLog + - changelog of linux-abi +ChangeLog.ibcs + - changelog of the iBCS project (up to 1998) +Error.map + - mapping of error codes from Linux to various personalities +HINTS + - FAQ-style Q&A +Local-X + - help on local X interfaces +Notes.Signal + - some notes on signal handling +Personality + - an introduction into Linux personality support +README.first + - read this first! +Syscall.map + - the syscall mapping for certain personalities +TODO.ibcs + - things to be done, leftovers from iBCS + +$Id$ diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/COMPAT linux/Documentation/abi/COMPAT --- linux-2.4.3/Documentation/abi/COMPAT Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/COMPAT Fri Mar 30 16:12:20 2001 @@ -0,0 +1,181 @@ +C: This file contains details of programs that have been run under +C: Linux using the iBCS emulator. An entry here is no guarantee that +C: the program works 100% but does indicate that the major elements +C: of the program have been unable to exercise bugs in the emulator +C: unless otherwise noted. +C: +C: An entry in this file does not necessarily indicate that the vendor +C: or anyone else actually supports the package under Linux unless +C: there is a specific entry to that effect. +C: +C: Please add to this file - new entries, other releases, amendments +C: to existing entries etc. +C: +C: The layout of this file is intended to be both easy to browse and +C: easy to parse, allowing it to be formatted into documents in the +C: future. This hasn't happened yet though and might never happen :-). +C: +C: Key: +C: C = Comment +C: V = Vendor +C: S = Support details +C: O = Operating system compiled for +C: P = Product +C: R = Release(s) known to work +C: L = Libraries required +C: D = Description +C: N = Notes +C: T = Tester + +V: Applied Information Systems, Inc. (info@ais.com) +O: SCO +P: Xess (MOTIF Spreadsheet) +R: current +L: statically linked +N: A save-disabled demo is available in ftp.uu.net:/vendor/ais/ +N: Get three files: README, gen.tar, and sco.tar. +N: Don't add a .Z or .gz to the end of the filenames; the files +N: inside are compressed. ~300K of online documentation is in +N: gen.tar. +N: If anyone decides to actually *buy* this product, *please* +N: mention that you will be running it under Linux. I promise +N: you that you will still get technical support (the majority +N: of our technical support staff run Linux at home) -- but if +N: enough people buy the product asking for a Linux version, my +N: employer will be willing to make the investment. Pass the +N: word on if you want to see a native-mode, high-quality +N: spreadsheet for Linux as much as I do... +N: michaelkjohnson +T: Michael K.Johnson + +V: Corel +O: SCO ODT +P: CorelDraw! 3.0 and friends. +R: 3.0 +N: Requires X11, no character versions of these apps. +N: Everything seems to be statically linked, no extra libs +N: necessary. I had a few problems with my .xmodmap file +N: since CorelDraw wants all of the lower function keys to +N: be mapped to functions in the CorelDraw program. Uses a +N: networked license manager, it worked fine. My programs +N: did not install properly due to an install bug. The dir. +N: that contains the washes.3fx file and others must be hand +N: changed to mode 777 for CorelChart to work (This from +N: Corel tech support). +T: Doug Ledford + +V: Informix +O: SCO +P: Informix SQL Standard Engine +R: 4.00 & 5.01 +L: /shlib/libc_s +T: Mike Jagdis + +V: Informix +O: SCO +P: Informix SQL Online Dynamic Server +R: 7.20.UD5 +T: Mike Jagdis + +P: Informix INET +R: ??? +N: INET is reputed to work too but I can't remember who +N: said that... +T: ??? + +V: IXI +O: SCO +P: X.desktop +R: ??? +L: /shlib/libnsl_s +N: The version of X.desktop tested is that shipped with +N: Uniplex Windows. Functionality is at least enough to +N: support Uniplex Windows. +T: Mike Jagdis + +V: Oracle +O: Interactive +P: Oracle +R: V6 +L: /shlib/libnsl_s +T: Remete Gabor + +V: Soft-Tek +O: SCO +P: Tactician Plus (character and X) +R: 3.0 +T: Brandon S. Allbery + +V: SPSS Inc. +O: SCO +P: SPSS 5.0 for SCO UNIX +L: Motif, if you want to use the GUI +D: Statistical Package for the Social Sciences +N: SCO's cpio is not compatible with GNU's -- I had to dd all +N: floppys onto my hd and to concatenate them into one file. +N: I couldn't test the GUI since I had no Motif available. +T: Joerg Rade + +V: Uniplex Limited +O: SCO +P: Uniplex / Uniplex Windows +R: 7.02 +L: statically linked (Uniplex Windows requires libnsl_s) +N: Uniplex Windows is implemented using a version of IXI +N: X.desktop. It is this that requires libnsl_s. +T: Mike Jagdis + +V: V-Systems, Inc. +O: SCO +P: VSI*FAX (FxServer, FxScript, FxVision) (character and X) +R: FxServer 2.0.19, FxScript 1.1.05, FxVision 1.0.16 +L: Statically linked +N: Needs localhost in the X server's access control list +N: even when using a local X connection. +N: This has not been tested with a modem connected as I +N: don't have a Multitech... +T: Mike Jagdis + +V: ViaCrypt +O: SCO +P: ViaCrypt PGP +R: 2.4 +T: Mark C. Henderson + +V: WordPerfect Corporation +O: SCO +P: WordPerfect (character and X) +R: 5.1 +L: Statically linked +N: Installation under Linux may require changes to some of +N: the WP install scripts. See the PROD.Patches/WP file +N: for details. +N: +N: WP uses a network license manager. +N: +N: For some reason WP use a partition floppy device rather +N: than the full block device. Linux does not have this so +N: you need to use dd to skip the first cylinder (track?) +N: when loading the floppies under Linux. See the HINTS +N: file for details. +N: +N: Fonts appear corrupt. See the HINTS file for a cure. +T: Mike Jagdis + +V: Z-Code Inc +O: SCO +P: Z-Mail +R: 3.2 +L: Statically linked - Motif based. +N: Installation scripts work correctly. +N: +N: ZMail can use a network license manager or a license file. +N: Both are known to work. +N: +N: ZMail is a GUI-based mail program. +N: +N: You can download the binaries for ZMail via anonymous ftp +N: ftp@ncd.com +N: You will have to contact Z-Code to obtain an evaluation +N: license if you wish to try it out. +T: Eric Youngdale diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/CREDITS linux/Documentation/abi/CREDITS --- linux-2.4.3/Documentation/abi/CREDITS Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/CREDITS Fri Mar 30 16:12:20 2001 @@ -0,0 +1,79 @@ +A (non-definitive) list of people who appear to have worked on the +emulator and, in some cases, what they appear to have done. + +This list is in no particular order. + +This list should probably be better maintained :-). + +If anyone feels that they are not properly credited here, send diffs to +this file. + + +======================================================================== + +Brandon S. Allbery or + +Graham Adams + +Tor Arntsen or + Emulator as of pl13 + +Philip Balister + Emulator as of pl13 + gdb for coff + +Alfred Longyear + COFF loader + Emulator as of pl12 + Original author of libc_s. COFF version. + +Mike Jagdis + Changes for loadable module version of the emulator. + Multi-personality detection and syscall mapping. + Error code mapping. + Wyse V/386 socket interface. + /dev/socksys socket interface. + /dev/spx to Unix domain socket for local X connections. + Named pipe to Unix domain socket open kludge. + XTI/TLI STREAMS based networking interface. + X.out loader for 386 Xenix binaries. + BSD support. + Trace dummy device. + Segment (LDT) mapping for x.out binaries. + Xenix 286 emulator overlay. + Current source maintainer and primary developer. + +Joseph L. Portman III + Major emulator developer. + libc_s + +Drew Sullivan + Past emulator source maintainer. + +Eric Youngdale (prev. & ) + First cut of the emulator. + ELF loader, plus memory manager and fs/exec.c modifications + to allow multiple binary formats to be loaded. + Keeper of the tsx-11 archive. + libc_s (elf version), plus bugfixes, reorganization, etc. + SVr4 portions of emulator. + +Karl Kiniger + Interactive 4.0 binary recognition and special support. + +Remete Gabor + Miscellaneous patches. + +Scott Michel + SCO multiscreen ioctls. + +Stephan Riess + SCO tape ioctls. + +Peter Polte + Xenix fcntl() file locking facilities. + +C.A. Lademann + +Miguel de Icaza + Sparc support. diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/ChangeLog linux/Documentation/abi/ChangeLog --- linux-2.4.3/Documentation/abi/ChangeLog Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/ChangeLog Fri Mar 30 16:26:49 2001 @@ -0,0 +1,9 @@ +2001-03-30 Christoph Hellwig + + linux-abi 2.4.3.0 + + * fix shared library support for COFF + * x.out is now supported (again) + * redo setting of personality based on ELF headers + * get rid of CONFIG_ABI_TRACE (and a lot of nasty ifdefs) + * added documentation, mostly from iBCS diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/ChangeLog.ibcs linux/Documentation/abi/ChangeLog.ibcs --- linux-2.4.3/Documentation/abi/ChangeLog.ibcs Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/ChangeLog.ibcs Fri Mar 30 16:12:20 2001 @@ -0,0 +1,2769 @@ +Thu Nov 5 21:45:41 GMT 1998 + + * Fixed the bug that lets reads and writes on /dev/socksys + take out the kernel. + -- Mike + + * Added a kludge around for Sybase isql which appears to + have initialised a struct sockaddr using: + sa.sa_family = htons(AF_INET); + I guess this works on SCO? + -- Mike + + +Sat Oct 31 14:15:44 GMT 1998 + + * Documentation update. + + * If we are doing a T_BIND_REQ with a null address we can + ignore the connection backlog. Listening makes no sense + but some software seems to set it 1 for the hell of it. + -- Mike + + +Tue Oct 20 20:34:20 BST 1998 + + * Changed the debug messages printed when exec tracing + sees a pointer error on an arg or env entry. It may not + be a "real" error. It could be that we just cannot get + a free page or perhaps the entry is too long for getname(). + Whatever, we do not really care at this point anyway. + -- Mike + + +Sat Oct 17 20:24:59 BST 1998 + + * Documentation update for today's release. + -- Mike + + +Thu Oct 15 21:39:16 BST 1998 + + * When checking personality only look at the base personality + and ignore the flags. There is at least one case I can + think of, PER_SHORT_INODE, where the personality should + be considered the same even when the flags are different. + -- Mike + + * Added the location of the kernel source as an option + in the CONFIG. Hopefully this will make it a little + more obvious that iBCS is *dependant* on the kernel. + -- Mike + + * Set SO_BSDCOMPAT on sockets. SYSV has BSD handling of + ICMP errors on UDP sockets rather than RFC conformance. + I think... + -- Mike + + +Wed Oct 14 22:50:48 BST 1998 + + * When using some user stack as temporary work space we + only leave 1k between the work space and the real user + stack. This is because Informix Dynamic Server uses + threads with limited stack space and the idea of dropping + 16k below what would normally be touched on a SCO system + worries me a bit. + -- Mike + + +Sun Oct 11 11:58:58 BST 1998 + + * Changed the Tools Makefile to install mkmnttab in + /usr/bin. Informix Dynamic Server _requires_ a + valid /etc/mnttab. + -- Mike + + +Sun Oct 11 11:44:58 BST 1998 + + * When doing an I_PEEK or I_NREAD STREAMS ioctl we have + to do a probe on sockets in case we need to generate + a control message (e.g. T_CONN_IND) which should then + be offered. This also allows T_CONN_IND messages to be + returned in several MORECTL divided pieces should it + ever be necessary. This is required by Informix Dynamic + Server which does a poll then I_PEEK on a listening + socket before actually picking up the connection. Dynamic + Server is system call hell :-). + -- Mike + + * When we do a timod operation via an ioctl there seems + to be no way to cope if the returned message is larger + than the original request. We can't expect the app to + come back for the extra and returning MORECTL to the + app seems to confuse things. Therefore we just discard + the excess. This case is required when an app (e.g. + Informix Dynamic Server) tries to set SO_LINGER using + an int instead of a struct linger via an ioctl. + -- Mike + + * Added some debug to the poll handler so we can see what + is being polled. + -- Mike + + * More debug message changes. + -- Mike + + * Wrap SO_LINGER handling so we can survive if an int is + passed instead of s struct linger. It seems that other + systems do not do such robust error checking as Linux. + Note that if an int is passed we probably do not do what + other systems would but at least we don't give unexpected + errors to broken applications. + -- Mike + + +Sat Oct 10 15:58:29 BST 1998 + + * Added an entry to Doc/HINTS noting the the Informix + Dynamic Server install requires an /etc/mnttab. + -- Mike + + * Wrong option length being passed through to setsockopt() + from the TLI/XTI optmgmt routine. + -- Mike + + * When stating files only map "ext2" to "HTFS" for SCO + programs - and then only if the filesystem name really + was "ext2". + -- Mike + + * SCO has a different value for the _SC_PAGESIZE argument + to sysconf() than SVR4. Informix wants it to work. + -- Mike + + * Hmmm, Informix Dynamic Server may or may not be looking + at the major number on a socket. (I _think_ it does + sometimes). It definitely checks that sockets have + S_IFCHR set in their file modes though... + -- Mike + + * Changed some debug messages to make it easier to read + logs when more than one iBCS handled process is running. + -- Mike + + * If we get a STREAMS ioctl on a file descriptor only + initialize the socksys handler on it if it is not + already a socket but does belong to the socksys device. + -- Mike + + +Thu Oct 8 21:20:43 BST 1998 + + * When punting a pseudo device transport provider to a + socket copy the device numbers between the inodes. This + is because Informix Dynamic Server stats the pseudo + device node (/dev/socksys) then stats the socket it + gets and compares the major numbers. Sheesh... + -- Mike + + * If socksys_close gets something that is not a socket + it is probably the original pseudo device which was + opened just for an ioctl or two. This is not an error. + -- Mike + + * Some programs, notably the Informix Dynamic Server + install program compare the filesystem name from a + stat or sysfs against their own hard coded list of + known "real" filesystems. Hence we call "ext2" "HTFS" + instead for SCO processes. + -- Mike + + * Informix DS also checks the release part of the utsname + data to make sure it says "3.2v5.0.0". So now the + utsname struct looks even more like SCO. + -- Mike + + * Only dump the ctl part of messages in timod if + tracing is enabled. + -- Mike + + * SCO has statvfs in the same place as SVR4 but they have + added a field slap bang in the middle of the struct to + allow some inodes to be reserved for root in much the + same way that some blocks may be reserved. + -- Mike + + +Thu Oct 8 20:48:46 BST 1998 + + * On timod bind and connect the size of the address is + allowed to be the _used_ bytes whereas the underlying + socket functions require the _total_ bytes. This is + a problem for Sybase. + -- Mike + + +Sun Aug 30 21:49:46 BST 1998 + + * Changed socksys.c to handle new file_operations struct + in kernel 2.1.119 and later. + -- Mike + + +Sat Aug 22 19:57:01 BST 1998 + + * Fixes and additions to user pointer checking in ipc.c + -- Mike + + * Changed some more KERN_ERRs to KERN_DEBUGs in the + STREAMS ioctl support. + -- Mike + + +Fri Aug 21 20:24:32 BST 1998 + + * Somehow fchdir had been missed from the main iBCS call + map even though it had been put in the BSD map. Oops. + -- Mike + + +Wed Aug 19 23:12:47 BST 1998 + + * ALPHA 2.1 release number 2... + -- Mike + + +Wed Aug 19 20:43:09 BST 1998 + + * Avoid calling rt_sigaction if the mapped signal number + is -1. It is not strictly necessary but why bother? + -- Mike + + * Added David Bruce's updated x286emul. + -- Mike + + +Mon Aug 17 21:29:53 BST 1998 + + * Avoid calling fput with a NULL file pointer. + -- Mike + + +Sun Aug 16 17:32:20 BST 1998 + + * Fix to copy_{to,from}_user return checking. In many + cases we do not care because they are behind verify_area + checks but in some we do - and copy_{to,from}_user + returns the number of bytes _uncopied_. + -- Mike + + +Sat Aug 15 23:39:42 BST 1998 + + * Change the flock handling to bounce the flock struct + through kernel space rather than using an in place + modification. The assumptions we were making about + segment registers seem to have become invalid at some + point. We could go to put_user(get_user()) but moving + the whole struct is probably more robust. Which is + faster? I dunno... + -- Mike + + +Sat Aug 15 22:30:41 BST 1998 + + * Changes to signal functions. Previous code confused old and + new sigsets and could have lead to memory corruption and + was likely the cause of signals getting blocked unexpectedly. + Now we use the rt_sig* and new sigset interface to the + kernel exclusively (in a few years the old stuff may be + removed). This does means that a non-Linux program may + now operate on signals >32 which may not have existed + (and therefore would have errored) in the native environment. + This may be considered a bug or a feature as appropriate... + -- Mike + + +Mon Jul 20 22:23:14 BST 1998 + + * ALPHA 2.1 release... + -- Mike + + +Mon Jul 20 20:55:47 BST 1998 + + * Added support for I_FDINSERT in the STREAMS/TLI message + protocol handling. This allows TLI server code to work + using a _real_ libnsl_s (tested briefly) but will break + server code using my replacement libnsl_s until I update + it. (It should probably use an I_FDINSERT simply so it + can still run under SYSV if ever necessary.) + -- Mike + + * Use TIOCINQ instead of FIONREAD in the STREAMS ioctl handler. + FIONREAD isn't actually supported on sockets. The socksys + code already had this right. + -- Mike + + * Do the MOD_INC, MOD_DEC calls for sockets in the inherit + and release handling only to reduce the opportunity for, + ah, "oversights". + -- Mike + + +Thu Jul 16 22:11:48 BST 1998 + + * Finally got round to adding a GNU CopyLeft! + -- Mike + + * Set up an XTI/TLI private state struct on all sockets at + the same time we plug our own file operations in. This + costs a small amount of extra memory per socket. However + this is strictly correct (although unlikely to be actually + _required_ by anything). It also allows us to set up TEPs + created by XTI/TLI listen/accept easily so they have a + chance of working. + -- Mike + + * XTI/TLI fixes: + Do not auto-listen in getmsg() - listen() after connect() + appears to crash some 2.1 kernels(?). + Change the probe for activity in getmsg() to use the + new poll handler directly. + Handle listening TEPs slightly better. + -- Mike + + * Changed a stray KERN_ERR to KERN_DEBUG in ioctl.c + -- Mike + + +Fri Jul 3 23:20:37 BST 1998 + + * Fixed the initial set up of the argument and environment + lists which were broken during the change to 2.1 style + user memory access. + -- Mike + + +Mon Jun 29 22:50:11 BST 1998 + + * Put kernel_version definition back in emulate.c + -- Mike + + * Change loaders to set start_text, end_text, start_data, + end_data, start_brk, brk fully. + -- Mike + + +Thu Jun 25 21:18:11 BST 1998 + + * Added support for the "fat" IPC structures which use + 32 bit uids, gids etc. + -- Mike + + +Wed Jun 24 21:30:09 BST 1998 + + * Change suser() checks to use the new capable() calls. + -- Mike + + * Changed the CONFIG default to NOT support Xenix 286. It + is an ever increasing build problem. It needs a volunteer + to rewrite it. + -- Mike + + * Add locking around system_utsname data using the uts_sem. + -- Mike + + * Changed to use dentry stuff. Use fget()/fput() to get + file pointers rather than accessing task fd tables + directly. Use poll interface for SYSV poll and timod + blocking checks. Use lock_kernel()/unlock_kernel() + around stat routines and other namei stuff. Use dput() + to release dentries obtained with namei(). Other + incidental fixes to what went before as I noticed them. + -- Mike + + +Tue Jun 9 20:02:56 BST 1998 + + * More changes for new module conventions. + -- Mike + + * Changed signal stuff to new conventions. + -- Mike + + * Changed getname() calling convention. + -- Mike + + * Changed fs type to mm_segment_t. + -- Mike + + * Changed user VM accesses to use new conventions. + -- Mike + + +Sat Jun 6 20:30:00 BST 1998 + + * Changed to new module conventions. + -- Mike + + +Thu May 28 22:30:45 BST 1998 + + * Removed VM_STACK_FLAGS tests. + -- Mike + + * Remove VM_GROWSDOWN tests. + -- Mike + + * Removed MAP_EXECUTABLE tests. + -- Mike + + * Removed MAP_DENYWRITE tests. + -- Mike + + * Removed STACK_TOP tests. + -- Mike + + * Removed FORKNOEXEC tests. + -- Mike + + * Removed INIT_MM tests. + -- Mike + + +Mon May 18 22:49:56 BST 1998 + + * Fixed xnx_rdchk() return value. + -- Mike + + * The serial number returned in the SCO utsname struct + can now be set with sco_serial="..." as a module + option. Some program apparently want to find a real, + believable serial number there. This should be documented + somewhere other than here I guess... + -- Mike + + +Mon May 18 22:03:49 BST 1998 + + * A class 't' ioctl with no arg type stuff in the top + word is either an SVR4 tape ioctl a Coherent BSD-ish + termios ioctl. + -- Mike + + +Mon Feb 2 22:57:45 GMT 1998 + + * Other relatively minor changes to allow compilation + under glibc (specifically 2.0.6 but it shouldn't + matter). + -- Mike + + * Added an explicit -I flag to search /usr/src/linux/include + since glibc doesn't necessarily require the kernel + includes to be symlinked under /usr/include. + -- Mike + + * The personality defaults in binfmt_coff should probably + select short inodes on the assumption that newer stuff + is likely to be built as ELF anyway. I hope. + -- Mike + + +Wed Nov 19 19:28:07 GMT/BST 1997 + + * Attempt to work around problems with sign extension + when programs believe that the fs magic in a sysfs() + call is short rather than long. + -- Mike + + * Added IPPROTO_IP/SOL_IP option name mapping for + {get,set}sockopt. This is correct for SCO OS5 and + hopefully for other SYSV derived Unices. Note that + SCO OS5 ping still doesn't work because it uses an + unsigned char for the IP_TTL value whereas Linux + wants an int - and it objects to getting an error + return. Apparently POSIX 1003g says IP_TTL should + be an unsigned char so OS5, or at least its ping, + is at fault. This probably isn't worth hacking + around unless someone _really_ needs it. + -- Mike + + +Wed Nov 12 22:28:19 GMT/BST 1997 + + * Added the SCO-ish syscall shortcut to the socksys + networking code. + -- Mike + + +Fri Nov 7 20:13:05 GMT/BST 1997 + + * Oops, I installed the SCO signal tables in the old + personality mapping but forgot to create a specific + SCO personality using them. + -- Mike + + +Thu Nov 6 08:04:37 GMT/BST 1997 + + * No, it really should be USR1 for URG under SCO, not + USR2. This is according to the SCO Network Programmer's + documentation. The previous problem was because + confusion between the SVR4 and SCO/SVR3 requirements + prevented a SCO program from registering a handler + for the right signal, I think. + -- Mike + + +Wed Nov 5 14:23:22 GMT/BST 1997 + + * Created a new signal mapping for SCO and mapped + Linux SIGURG to SCO SIGUSR2. Also changed the + plain ibcs mapping for SIGURG back to IBCS_SIGURG. + Previously I had SIGURG mapped to SIGUSR1 for + what my subconscious says was a good reason but + I can't figure out where I got it from. The USR2 + mapping is according to Peter Brueckner - and if + it works for him... + -- Mike + + +Wed Nov 5 09:14:27 GMT/BST 1997 + + * Repair the STREAMS based socket code. The new socket + hashing in 2.0.30 and beyond means the old code no + longer works. We now delay replacing the fd with + a socket until the first read, write or ioctl. Since + the open has completed at this stage and the fd is + fully initialized we can then use dup() to do the + fd switch, which should always work. As a side effect + this allows us to auto-connect an SPX pipe to X :0 + if the first operation is other than a single character + write - which should allow us to handle v. old SVR3 + X programs side by side with their more modern, and + common, multi-SPX pipe descendants. + This does mean that some error returns from an + open of a TLI special file might be delayed until + the first operation, however a) these are unlikely + to occur (they are things like no such protocol) + and b) most opens of such files are hidden in + functions like t_open() anyway so if there is a + problem a simple fix to libnsl to check the first + ioctl is all that is needed. + -- Mike + + * sysfs() used to enumerate available filesystems seems + to be 0 based on Linux but 1 based on SYSV. + -- Mike + + +Sun Oct 12 00:18:33 GMT/BST 1997 + * Ioctls on the NFS pseudo device need to go via the + emulation code rather than the native ioctl handler. + -- Mike + + +Sat Aug 16 14:56:24 GMT/BST 1997 + + * Changed the use of errno in a prototype in ibcs.h to + avoid possible conflict with an SMP errno definition + which could get inherited from an include file if we + aren't careful. + -- Mike + + +Sat Jul 12 01:00:00 GMT/BST 1997 + + * Added Xenix locking() modes 5, 6, 7 as per patch from + David Bruce (there were others + too). I rewrote it to be a bit cleaner but I haven't + tested it (it's late...). Some one will tell me I guess. + -- Mike + +Fri Jul 11 22:27:13 GMT/BST 1997 + + * Added more console ioctl traps to discourage programs + from trying to do funky stuff with the console without + logging unsupported ioctl messages. + -- Mike + + * sysfs() can, apparently, map an fs magic number to + an fs name. We do this outside the kernel sysfs() + because there seems no clean way to do it. We simply + have a list of known magic numbers hard coded :-(. + -- Mike + + * Implemented sysconfig(). This is appears to be the SVR4 + forerunner to the POSIX sysconf(). + -- Mike + + +Tue May 13 20:52:05 GMT/BST 1997 + + * Hand off xmknod calls via ibcs_mknod so that we can + create a directory if that is what the flags imply. + I have not tested to see if xmknod is allowed to create + directories - I just noticed it in passing. + -- Mike + + * Added SCO's F_GETHFDO (get highest fd open) fcntl. This is + used by /bin/csh on SCO OS5 to save a few syscalls. + -- Mike + + +Tue May 13 00:10:09 GMT/BST 1997 + + * More changes to handle long/short inode environments + plus more explanation in the code. Are we having fun yet? + -- Mike + + +Sat May 10 15:19:39 GMT/BST 1997 + + * Added socketpair() to the socksys emulation. This is + as implemented by SCO OpenServer 5. + -- Mike + + * Change binfmt_coff.c to recognise programs compiled for + SCO OpenServer 5, programs compiled for SCO 3.2.4 and + programs compiled under SCO OpenServer 5 but with + compatibility for ODT3.0. Why? Well, sometimes we + should be giving long inodes in returns from getdents, + sometimes short inodes. We don't just want to mask + off the high part because that can lead to some + things becoming invisible. We don't want that. + -- Mike + + +Fri May 9 23:29:37 GMT/BST 1997 + + * Added some more tape ioctls. + -- Mike + + +Wed Apr 16 23:12:37 GMT/BST 1997 + + * Fix memory leaks in poll.c and change ENOMEM return + to EAGAIN. + -- Mike + + +Tue Mar 11 21:29:15 GMT/BST 1997 + + * Add {get,set}rlimit to the SYSV personalities. + -- Mike + + +Fri Mar 7 21:04:24 GMT/BST 1997 + + * Only build x286emul if EMU_X286 is enabled in CONFIG. There + are many insallations which appear to either not have the + a.out compiler support or have it installed incorrectly. + -- Mike + + +Tue Feb 18 22:04:39 GMT/BST 1997 + + * Removed unnecessary and incorrect includes. + -- Mike + + +Wed Feb 12 22:03:13 GMT/BST 1997 + + * Documentation updates for release. + -- Mike + + +Mon Feb 10 22:36:27 GMT/BST 1997 + + * Dammit! The inode folding in stat() and getdents() was + out of step _again_ :-(. + -- Mike + + +Sun Jan 5 17:20:20 GMT/BST 1997 + + * sysconf(_SC_CLK_TCK) should return the value of HZ. + -- Mike + + * Small clarification to README concerning shared libraries. + -- Mike + + * Removed the bit about UnixWare X binaries not working from + Doc/HINTS. Now we have STREAMS/TLI emulation this is no + longer true (and hasn't been for a while). + -- Mike + + +Sat Jan 4 19:31:26 GMT/BST 1997 + + * If we open() something that is really a socket we close + it and reopen it using socket(), connect(). This allows + a Unix domain socket to look like a named pipe which + enables more SYSV X clients to connect to a local X + server using the local method (with suitable symlinks + to map the pathnames). + -- Mike + + +Fri Jan 3 22:39:15 GMT/BST 1997 + + * Added a (simplistic) implementation of the I_CANPUT SVR4 + STREAMS ioctl. + -- Mike + + * Changed CONFIG.i386 to note that a correct setting of SMP + is now necessary. + -- Mike + + +Wed Oct 2 16:28:39 GMT/BST 1996 + + * Intercept mknod() and allow it to create directories. Linux + doesn't allow this but SYSV does. (What about BSD?) + -- Mike + + +Wed Oct 2 15:56:57 GMT/BST 1996 + + * Separated out the spx connect code so we can support old, + single connection spx implementations once we know how to + recognise them. + -- Mike + +Wed Oct 2 15:54:45 GMT/BST 1996 + + * At some stage I add some binfmt_elf.c changes that were + made to the kernel ELF loader in some 2.0.x patch. I forget + which now but no one should be using the iBCS ELF loader + currently anyway. + -- Mike + + +Fri Aug 23 15:42:04 GMT/BST 1996 + + * Moved svr4sig to the right place. + -- Mike + + * Moved error message strings to a separate file so they can + be shared by emulate.c and solaris.c. + -- Mike + + * CONFIG files now define ARCH to be the CPU architecture. This + is used to ensure that architecture specific files are only + used when necessary. + -- Mike + + * Changed the getdents routine in open.c to use the same + rules for folding 32 bit inodes to 16 as stat and read. + -- Mike + + +Mon Aug 19 13:33:42 GMT/BST 1996 + + * Correct IPC problem introduced with Sparc changes. + -- Mike + + +Fri Aug 9 13:27:49 GMT/BST 1996 + + * Fix the inode swapping for /dev/spx and XTI/TLI transports. + -- Mike + + * If a COFF binary doesn't have a .comment section we have no + way to tell what personality we should be using. Switch to + SCO anyway - odds on it is. + -- Mike + + +Wed Aug 7 14:22:11 GMT/BST 1996 + + * On SCO at least lseek on a character or block device + returns 0 not -ESPIPE. + -- C.A. Lademann + + * Some problems with /dev/spx and TLI end point handling that + could leak descriptors, memory and leave the lists of file + locks in an inconsistent state. Not to mention the fact that + the socket data in an inode also contains a pointer back to + the process' file structure. I _think_ I have this sorted + out now... + -- Mike + + * Sparc changes broke select. While I was at it I changed it + to use the newselect Linux call as well. If we build without + tracing we'll save a few more bytes of code now too. + -- Mike + + +Wed Jul 31 14:16:38 GMT/BST 1996 + + * Map EAGAIN to EWOULDBLOCK for recv*() and send*() syscalls. + Linux seems to return EAGAIN. X/Open allows either EAGAIN + or EWOULDBLOCK. SVR4 and Wyse V/386 specify EWOULDBLOCK in + their man pages. SCO doesn't admit to non-blocking possibilities + in their man pages but some code seems to expect only + EWOULDBLOCK. + -- Mike + + +Mon Jul 29 16:58:11 GMT/BST 1996 + + * Added a CONFIG option for SMP. This is enabled by default. + I don't think this is a problem for non-SMP systems? + -- Mike + + * Minor change to the SCO error map. + -- Mike + + +Fri Jul 26 09:13:43 GMT/BST 1996 + + * Updated README and RELEASE + -- Mike + + * Merged Sparc patches from: + Miguel de Icaza + -- Mike + + +Thu Jul 4 12:24:06 GMT/BST 1996 + + * The default is now *not* to build a versioned module. I got + too many questions about why it wouldn't compile. + -- Mike + + * Fix to binfmt_xout.c when Xenix 286 is emulation is not + configured. + -- Mike + + +Fri Jun 14 13:36:18 GMT/BST 1996 + + * Added code to explicitly fail the SCO LD?MAP ioctls used + for channel mapping. + -- Mike + + +Thu Jun 6 17:21:00 GMT/BST 1996 + + * Cleaned up Stephans SCO tape ioctls and added the + corresponding SVR4 versions (untested). + -- Mike + + +Wed Jun 5 10:47:24 GMT/BST 1996 + + * Rewritten the Xenix locking() syscall. The previous one + was crap. + -- Mike + + * Change the read on directory emulation to fold long inodes + to shorts in the same way as stat and getdents. This may + help old programs that use stat and read to do a getcwd + rather than a stat and getdents. + -- Mike + + * Use __get_free_page instead of get_free_page in getdents + since we don't need the buffer cleared initially (I think). + -- Mike + + +Sat Jun 1 09:50:30 MET DST 1996 + * Added some tape ioctrls for SCO to iBCSemul/ioctl.c. + -- Stephan + + +Fri May 31 08:44:51 GMT/BST 1996 + + * Move bsdioctl.c to the main group of source files from + than the BSD specifics. Just about everything else has + BSD style sgtty stuff and some seemingly modern code + actually depends on it (e.g. ISC SVR4 telnet)! + -- Mike + + * Add CONFIG option to build a versioned module. + -- Mike + + * Install the modules in /lib/modules/`uname -r`/misc for + compatibility with the modules tools. + -- Mike + + * If the requested connection indications in a bind request + is greater than zero do a listen() if the bind is successful. + We still also do a listen() if the program selects() on + a bound but unconnected stream. This may help some broken + programs. It may also break some broken programs. It's + debatable whether this should now be in or out. + -- Mike + + * The bit vector mapping used for converting vectors of + signal flags had an off by one error. The signal maps + themselves were also one entry short. + -- Mike + + * At some stage I changed the I_SETOWN STREAMS ioctl but + never committed it? + -- Mike + + +Thu May 9 12:51:10 GMT/BST 1996 + + * Change to install in /lib/modules/`uname -r`/misc instead + of /usr/lib/modules for compatibility with the way the + modules tools have gone. + -- Mike + + +Thu Apr 25 12:34:06 GMT/BST 1996 + + * Use the CONIND_number in a T_BIND_REQ to decide whether + or not we should listen() on the socket. + -- Mike + + +Mon Apr 22 15:42:47 GMT/BST 1996 + + * Added a simple loader that will attempt to pass scripts + that start with ":" and things that look like simple text + to /bin/sh. Hopefully this isn't going to conflict with + magic for other needed formats... + -- Mike + + +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. + -- Mike + + * Changed I_NREAD to understand that control messages constitute + queued data. + -- Mike + + +Fri Jan 19 11:57:20 GMT/BST 1996 + + * Make the socket level connect in timod.c happen synchronously + always. Allowing the async possibility is a little harder. + -- Mike + + +Thu Jan 18 16:06:13 GMT/BST 1996 + + * Added (some of) the intial framework for option management. + This is documented by X/Open but many XTI stacks don't + seem to implement it. Certainly the man page for t_optmgmt + in SCO OS5 says it isn't yet implemented. There do seem + to be programs out there that make options requests though. + Unfortunately I don't have one right now so this is currently + disabled and MAY CAUSE KERNEL FAULTS. I don't know... + -- Mike + + +Tue Jan 16 12:35:21 GMT/BST 1996 + + * Added a slight change to mmap.c. The SVR4 headers describe + a slight change in functionality which is specified with + a special flag that is supposedly set by the C library + interface. I haven't actually seen this flag set by the + SVR4 dynamic loader (which is the only mmapper I've seen) + and things seem to work with or without this change. It + may not be necessary at all? + -- Mike + + +Fri Jan 12 14:56:38 GMT/BST 1996 + + * Remove trace flag from context() in the callmaps. SVR4's + /bin/sh seems to use it but doesn't care if it fails. + -- Mike + + * Added the SCO OS5 SI86GETFEATURES request to sysi86(). OS5 + uses this to establish what "features" are available when + a program starts (i.e. in crt*.o). Currently we just return + the same vector as OS5 itself. I haven't found what the + flags mean - but one of them indicates xstat extensions + which I have added to iBCS. + -- Mike + + * Change .comment parsers in binfmt_coff.c and binfmt_elf.c + so we only grab a single page (asking for two contiguous + pages is antisocial) and then roll through the comment + section in stages. + -- Mike + + * Fixes to binfmt_elf.c and binfmt_aout.c so they compile + and load with 1.3 kernels. + -- Mike + + +Tue Jan 9 14:29:49 GMT/BST 1996 + + * Add a kludge to the TLI connect code. For some reason, under + ISC SVR4, telnet seems to gve the port number in network + byte order ok but the X programs give it in host byte order. + One of them is wrong but presumably both work on ISC (I don't + have the hardware to actually install it). We kludge around + it here by checking if we are SVR4, AF_INET, port 6000 (host + order) and, if so, change it to port 6000 (network order). + This will break anything that wants to make an outgoing + call to port 28695. There are probably other things that + expect incorrect port numbers to work but there seems to + be no easy solution here. + -- Mike + + +Fri Jan 5 13:34:43 GMT/BST 1996 + + * First draft of code to handle select/poll on transport end + points correctly. This isn't well tested but should be good + enough to support normal timod usage. + -- Mike + + +Thu Jan 4 13:52:25 GMT/BST 1996 + + * TLI changes to get error returns from connects correctly. + -- Mike + + +Wed Jan 3 17:06:07 GMT/BST 1996 + + * Added a manual page in the Doc directory. This is not + installed by default. + -- Mike + + * Fixed a problem in the .comment parsers in binfmt_elf.c + and binfmt_coff.c where a number of pages was passed to + __get_free_pages() instead of a binary power. This has + been in release versions of binfmt_coff.c for a long + time but exactly one person has reported anything that + might be attributable to it. Strange, since the bug should + have manifested itself as insidious memory leakage and + corruption... + -- Mike + + +Wed Jan 3 12:16:47 GMT/BST 1996 + + * Removed all kernel patches in the Patches directory. None + should be need for kernels 1.3.50 (or earlier?) and onwards. + None should be essential for 1.2.13 - although some capability + is lost notably SCO OpenServer 5 ELF binaries (if the kernel + ELF loader is present) and BSD a.out binaries. + -- Mike + + * Another fix to termio[s] ioctls to get the control character + settings right for SVR4. Previously this was just copied + from the SCO mapping and just never got changed. + -- Mike + + +Thu Dec 14 10:41:36 GMT 1995 + + * Added basic getpmsg/putpmsg support. It doesn't do anything + with bands but we don't have anyway to use them. + -- Mike + + +Tue Dec 12 09:38:01 GMT 1995 + + * First commit of the major TLI rewrite for Eric Sixt. This + should be enough for normal TCP & UDP clients. It may be + sufficient for servers as well but this is untested so far. + The client stuff has been tested with SCO cu, ISC telnet + and custom test code down to the getmsg/putmsg level. A shared + libnsl_s is also included. This has the functions needed for + clients but lacks some needed for servers currently. It has + been tested on a real SCO system. It could be done better + (and should be) but for now we are interested in making existing + programs work rather than handling all the error conditions + by the book. The library uses SVR3 shared library tools and + needs to be built on an SVR3 system (I used SCO). + Included is a rewrite of the /dev/spx kludging (the old didn't + work if TLI was enabled). This now allows connections to other + than /tmp/.X11-unix/X0 (if configured) so you can run multiple + X servers on the VCs and display SCO X programs on all of them. + The major/minor numbers used for the emulation devices have + (necessarily) changed. The top level Makefile will (re)create + them on a "make install" or "make devices". + Oh yeah, I built stubs for other libraries as well (specifically + SCO/SecureWare protlib_s) but don't expect it to have any real + support. If programs _really_ need stuff from there they are + like to have reduced or completely broken functionality on + Linux! + The script I used to generate the skeleton APIs for the + shared libraries is libs/mkltab if anyone feels the urge to + look at other libraries... + -- Mike + + * Removed the old quota compile option. It isn't compatible with + the quota stuff in 1.3.46 and would only cause confusion. This + means you can't use iBCS if you have the old quota patches + in a pre-1.3.46 kernel. Tough :-). + -- Mike + + +Mon Dec 11 15:14:46 GMT 1995 + + * Map I_SETSIG/I_GETSIG to FIOSETOWN/FIOGETOWN and pray... + -- Mike + + * Fixed possible memory leak in COFF & ELF personality recognition + when the offset/size of the .comments section is invalid. This + could leak when the .comments section exists but is zero bytes + long I think. + -- Mike + + +Wed Dec 6 11:31:27 GMT 1995 + + * A stat of a file must give an inode that matches what we get + from a read of the directory since code that figures out cwd + needs the inodes to match. Mind you, if there are several inode + numbers greater than 65534 in the directory we are going to get + some strange paths. I don't know if this is fixable properly at + all? + -- Mike + + * Yes it is. We just mask off the high word to get the short + inode number for the stat structure. + -- Mike + + +Thu Nov 30 16:21:32 GMT 1995 + + * Fix the SVR4 additions to the V7 terminal ioctls. Add handling + of TIOC[GS]ETD. Have TIOCL[GS]ET trivially succeed (I can't + find the documentation for the arguments). + -- Mike + + +Wed Nov 29 12:57:42 GMT 1995 + + * Changed the guesswork svr4_waitsys to implement the correct + waitid syscall. + -- Mike + + * Enable the i486-linuxaout option in x286emul/Makefile by + default. There seem to be significant numbers of people + using ELF compilers now. This may be a mistake... + -- Mike + + * Fixes to sigsuspend and sigpause in signal.c. The previous + invocations of the Linux sigsuspend syscall were wrong and + liable to lead to random freeze ups of programs which used + sigsuspend() or sigpause(). + -- Mike + + +Fri Nov 24 11:03:01 GMT 1995 + + * Interactive SVR4 seems to be overloading the BSD termio + ioctls with its own. + -- Mike + + * The SVR4 procid subcodes don't match the SCO ones. Or, at + least, I seem to remember I got the orignal set from SCO + and UnixWare and Interactive SVR4 are different (but match + each other). + -- Mike + + +Thu Nov 23 17:21:56 GMT 1995 + + * Interactive SVR4's /bin/sh calls access(..., 011) but Linux + returns EINVAL if the access mode has any other bits than + 007 set. So we have to wrap it and mask it :-(. + -- Mike + + +Wed Nov 22 10:11:49 GMT 1995 + + * Change to binfmt_elf.c to set total_vm value introduced in + kernel 1.3.43. + -- Mike + + +Thu Nov 16 15:02:58 GMT 1995 + + * Added support for SCO OpenServer 5 binaries using .comment + section parsing as with COFF. + Built a BSD capable a.out loader as part of iBCS. + The iBCS ELF loader is only used for recognised (using + .comments) binaries if the standard ELF loader is configured + in the kernel iBCS is built against. If the ELF loader is + not configured in the kernel iBCS is built against the iBCS + ELF loader is used for all ELF binaries. This prevents the + iBCS module from becoming un-unloadable on ELF based Linux + systems. + Similarly the iBCS a.out loader tries to avoid dealing + with anything other than BSD binaries for the same reasons. + This requires a kernel 1.3.42 or greater to allow iBCS + to insert its loaders into the list before the standard + kernel ones. Kernels 1.3.39(~) to 1.3.41 have some support + but there are bugs which will likely prevent you running + *anything* as soon as iBCS is loaded. Mea culpa. Tough. + -- Mike + + +Thu Nov 16 11:00:08 GMT 1995 + + * Minor clean up in binfmt_coff.c and fix a minor bug in + parse_comments that caused it to miss checking a string + if there was a zero length string in among. + -- Mike + + +Fri Nov 10 12:22:05 GMT 1995 + + * Changes for latest module bogosities (~1.3.38). We need to + define __NO_VERSION__ to avoid linux/module.h putting + a kernel_version in *every* damn file. + -- Mike + + +Tue Nov 7 10:55:05 GMT 1995 + + * When stealing temp space from the stack we have to actually + move esp down and then restore it as the 1.3.x kernels add + a check to trap out of bounds stack accesses. This is not + tested but I think it only affects the TLI emulation code + which is disabled by default. + -- Mike + + +Mon Oct 9 11:22:29 BST 1995 + + * Use kernel readv/writev if available. + -- Mike + + +Thu Sep 14 12:21:48 BST 1995 + + * Changed references to current->sigaction to allow for the + changes in kernel patch 1.3.26 which allow sharing of signal + state between clone processes. + -- Mike + + +Mon Sep 4 10:04:22 BST 1995 + Originally: Wed Aug 2 09:57:56 GMT 1995 + + * Removed Xenix interrupt bug, created wait() workaround + for INFORMIX-SQL and built the locking() to fcntl() + mapping. + -- Peter + + +Wed Aug 30 09:19:54 BST 1995 + + * Merged kernel patch for binfmt_elf.c from 1.3.21 which sets + EDX to zero on process start up. See the comment in the code + for reasons. + -- Mike + + +Tue Aug 29 08:44:50 BST 1995 + + * Workaround. Local X won't work because a putmsg occurs + after we have already swapped the open descriptor for a + Unix domain socket. We either need to peek at socket + internals or actually implement the messages for passing + file descriptors. This quick fix enables local X connections + if we build without XTI support. + -- Mike + + +Tue Aug 8 11:36:41 BST 1995 + + * Fix streams kludging so local X works again (should do + anyway - it's untested as yet due to hard disk collapse. + Hopefully someone will tell me if it doesn't work.) + -- Mike + + +Mon Jul 31 13:25:58 BST 1995 + + * Changes to allow compilation in the presence of a kernel + built with the quota patches. + -- Dimitrios Mpougoulias + + +Tue Jul 18 09:01:53 BST 1995 + + * Fixed timod getinfo ioctl. This functionality should move + into the message handling as bind has. + -- Mike + + +Mon Jul 17 10:16:43 BST 1995 + + * Added handling of BSD-ish sgtty ioctls. For some reason the + SVR4 network programs such as telnet have been modified to + pushd the ttold STREAMS modules and use sgtty calls instead + of simply using termio[s]. Don't blame me! :-) + -- Mike + + * Restructuring of timod.c complete. Timod ioctls now use + message routines to avoid duplicating code. + -- Mike + + +Wed Jul 12 14:44:30 BST 1995 + + * Made debug output in binfmt_coff.c less verbose. We only + really care about matched comment strings. If we dump them + all here we overrun the kernel message buffer and miss + interesting stuff when the program actually starts running. + -- Mike + + * Changed __get_free_pages in binfmt_coff.c to give the extra + argument required in 1.3 kernels. + -- Mike + + +Tue Jul 4 11:48:27 BST 1995 + + * Restructure timod.c ready to rewrite timod_ioctl to use + putmsg/getmsg rather than reimplementing the same message + protocol again. + -- Mike + + +Mon Jul 3 13:41:49 BST 1995 + + * Initial TLI support for outgoing TCP and UDP. Merged BSD/Wyse + socket ioctl handling with the socksys handler. Fixed (some) + bugs in poll() emulation. Devices in /dev/inet have changed + to support TLI access. See README for details. + -- Mike + + +Tue Jun 27 09:00:02 BST 1995 + + * Don't export symbols from iBCS. I'm not sure when register_symtab + was introduced so we only drop our symbol table in 1.3 + and later. + -- Mike + + * Added missing brackets in binfmt_elf.c as per kernel + patch 1.3.4. + -- Mike + + +Thu Jun 22 13:09:49 BST 1995 + + * Big step forward with TLI. I now seem to understand what is + happening when and have enough to do the initial open and + get info requests. This may one day actually work... + -- Mike + + * Trap EUC ioctls and return EINVAL. We don't do EUC :-). + -- Mike + + * Changes for the 1.3 development kernel. This compiles but is + as yet untested. It still seems ok with 1.2.10. + -- Mike + + +Wed Jun 14 09:15:39 BST 1995 + + * Added Eric's protection mapping fixes to binfmt_elf.c + from 1.2.10. + -- Mike + + +Fri Jun 9 12:31:53 BST 1995 + + * Linux can't stat unmounted filesystems but SCO can (by + specifying the pathname/fd of a block device and the + filesystem type. Linux will just stat the filesystem + that the device node is on (i.e. the root filesystem). + There isn't much we can do about it. I just lie and + claim there is 100MB free of 1GB. I hope this won't + cause too much grief... + -- Mike + + +Thu May 18 12:06:50 BST 1995 + + * When trying to get an IP domain name don't try the utsname + domainname if it is "(none)". If we get that far we have to + give in and return a blank domain name. + -- Mike + + +Wed May 17 10:15:42 BST 1995 + + * Recheck the socket functions when accept returns a new socket. + This is pedantic at this stage since we must have had a + socket initially and the current kernel code isn't likely + to handle removal and reloading of in use modules. iBCS + can handle this happening to it though :-). + -- Mike + + * Fix timod faking to correctly return an error if given an + invalid file descriptor rather than trying to dereference + a null pointer in kernel mode. + -- Mike + + +Tue Apr 25 11:35:43 BST 1995 + + * If nap() is given a zero timeout return immediately rather + than blocking indefinitely. Ensure that SIGALRM is not ignored + during the pause or we never get woken up by the timeout. + -- Mike + + +Mon Apr 24 09:21:30 BST 1995 + + * Various documentation updates from Eric. + -- Mike + + +Fri Apr 21 14:34:25 BST 1995 + + * Fixes to IPC. Now it really *should* work... + -- Mike + + +Thu Apr 13 14:03:45 BST 1995 + + * Tidy up documentation ready for new release. + -- Mike + + +Wed Apr 12 11:07:52 BST 1995 + + * Moved to an ELF development system with a GCC 2.6.4 snapshot. + This pointed out a few signed/unsigned mismatches so I + fixed them. We also have to ensure that x286emul is built + as a QMAGIC a.out because it won't work any other way. It + isn't likely to work any other way unless someone pays for + for it to be done - it isn't what you might call a "sexy" + project... + -- Mike + + +Wed Apr 12 08:53:22 BST 1995 + + * Added the kernel patch to handle statically linked SVR4 ELF + binaries to the Patches directory since it doesn't seem to + have made any of the 1.2.x patches yet. + -- Mike + + +Tue Mar 28 09:55:38 BST 1995 + + * Made the ISC specific stuff optional via CONFIG. + -- Mike + + * 1. INTERACTIVE UNIX signal numbers are different from IBCS2. + I added new signalmaps and exec_domains. + 2. setpgrp does not deattach the controlling terminal. + Try the setpgrp test program included here after the patch + on real SCO or xxxx and Linux/IBCS2. + 3. sigset behavior is incorrect. Test program also included. + Short description: signal handlers registered whith sigset + should run with the signal blocked, and after return + the handler must be restored, so sa_flags = 0 + is the correct setting. + Calling sigset should remove the signal from the + blocked set. + -- Remete Gabor + + +Fri Mar 24 10:20:57 GMT 1995 + + * Set the fragment size to zero for [f]statfs() just to be + pedantic (SCO does this). + -- Mike + + +Tue Mar 21 10:24:14 GMT 1995 + + * Fixes to 286 overlay and x.out loader by Don Camp + . + -- Mike + + * New code for SVR4 {get,set}groups since SVR4 uses longs + for gids whereas Linux uses shorts. + -- Mike + + +Mon Mar 20 17:06:23 GMT 1995 + + * Added code for waitsys(). This is guesswork at this stage + but appears sufficient for ISC 4.0 ksh to do something + reasonable in the simplest case. + -- Mike + + +Tue Mar 14 09:44:13 GMT 1995 + + * Initial implementation of ptrace. This allows programs + (SCO and Wyse V/386 programs) to access a process' + registers but actual tracing semantics will be difficult + to make functional. + -- Mike + + * Alter emulate return to allow return of numbers > 2^^31 + which don't fall in the error code space. + -- Mike + + * Added signal mapping to wait() syscalls. + -- Mike + + * Updated the main README with the vger mailing list details + and a few other tidy ups. + -- Mike + + +Thu Mar 9 10:10:53 GMT 1995 + + * Added a load more system calls to the SVR4 tables (these + match UnixWare at least I think). Some of these may work, + some are just marked to shut up run time warnings. + -- Mike + + * Increased the size of the buffer used for parsing comment + sections in binfmt_coff.c to 8k (from 1k). There are + programs out there that need it. + -- Mike + + +Tue Mar 7 16:12:36 GMT 1995 + + * More XLI/TLI changes - mostly fixes. + -- Mike + + * Added basic handling of the termiox extension used by SVR4 + to give access to hardware flow control. Only RTS & CTS + or nothing is allowed because that's all Linux does. The + same comments as below apply to the status of this. + -- Mike + + * Rework ioctl handling for termios. SCO uses short in a termios + structure, SVR4 uses longs. The bit shuffling used for SVR4 is + the same as for SCO - there are known to be some slight + differences but these are not believed to be critical for + most things. A large amount of guesswork went in to this. + One day I may be able to test it... + -- Mike + + +Mon Mar 6 12:31:05 GMT 1995 + + * Added a -DMODULE to iBCSemul/Makefile to make new style kernel + modules work. + -- Mike + + +Fri Mar 3 15:04:14 GMT 1995 + + * Patches from Eric. (Use Eric's [f]statvfs instead of mine). + -- Mike + + +Thu Mar 2 11:46:03 GMT 1995 + + * Fixed a silly in the handling of SO_IMASOCKET and SO_PROTOTYPE + plus added a check on the given buffer length. + -- Mike + + * Fixed a silly in the sockopt.inc options mapping. + -- Mike + + +Wed Mar 1 14:20:06 GMT 1995 + + * Added SVR4 console keyboard mapping and termcap/terminfo + options to the PROD.Patches directory. + -- Mike + + +Mon Feb 27 13:30:17 GMT 1995 + + * Added simpleminded implementation of [f]statvfs(). + -- Mike + + * [f]statfs() now respects the length argument to allow for + older/smartass code which uses a smaller buffer size. + -- Mike + + +Fri Feb 17 10:33:23 GMT 1995 + + * More tidy up, a little more work on TLI/XTI (still nowhere + near usable), fixed the signal debugging messages so it + makes more sense. + -- Mike + + +Thu Feb 2 12:45:25 GMT 1995 + + * Changed the BSD termio ioctl handler to recognise the fact + that some provide V7 compatibility and may be invoked from + non-BSD binaries - possibly without BSD size encoding. + -- Mike + + * Changes for 1.1.88. More definitions moved around in the + Linux header files :-). + -- Mike + + +Fri Jan 27 10:12:51 GMT 1995 + + * Also mapped new Linux SIGIO to iBCS SIGIO and changed Linux + SIGURG to map to SIGUSR1 as documented in SCO's TCP/IP + programmer's guide. Is SVR4 the same? How badly do we care? + -- Mike + + * Had to add a new personality for Xenix binaries since they + have a different number for SIGPOLL - sigh... + -- Mike + + +Mon Jan 23 15:34:01 GMT 1995 + + * Changes to includes for 1.1.84. + -- Mike + + * Change to binfmt_elf.c from kernel patch 1.1.84. + -- Mike + + +Tue Jan 17 17:10:25 GMT 1995 + + * Added tracing of argument and environment vectors passed + to exec(). + -- Mike + + +Mon Jan 16 11:34:58 GMT 1995 + + * Change socksys.c for 1.1.81. There doesn't seem to be a + convenient define to test but I intended to roll out + most of the "magic" define testing for 1.2 to clean + things up. + -- Mike + + * Ensure the segment registers are correctly set up when we + exec a new program - the LDT we may have been using before + no longer exists. + -- Mike + + +Fri Jan 6 11:32:52 GMT 1995 + + * Fixed a problem where the Xenix 286 emultor wasn't getting + the correct return and error codes from lcall7s. + -- Mike + + * Added support for exec() in the Xenix 286 emulator. + -- Mike + + * Made the spin-before-launch trap in binfmt_xout.c settable + via a trace option, "xout-block". This is used to attach + gdb to a 286 process to debug the emulator. + -- Mike + + * Fixed a problem with binfmt_xout.c setting the wrong intial + brk value for impure segmented binaries. The checks for brk + collisions with mapped space were failing brk changes. Before + the brk checks were introduced I image we simply trashed + text or data... + -- Mike + + +Thu Jan 5 11:21:51 GMT 1995 + + * Added some debug to the STREAMS I_PUSH and I_POP. Also made + them succeed without actually doing anything. We may be able + to work round some instances of STREAMS usage one day... + -- Mike + + +Wed Jan 4 11:17:14 GMT 1995 + + * Change yesterday's mkdir to use getname()/putname() to + fetch the pathname from user space. I hadn't realised + these were already in ksyms.c (although how long have they + been there? This breaks compatibility with older versions + of the kernel I guess). + -- Mike + + * Implement the NIOC ioctls for getting file handles since + Oracle's TCP server seems to be wanting to do this for some + reason (why???). This is a simple implementation that simply + fills in the device number of the filesystem and the inode + number of the file. This seems to agree with what SCO is + doing. I don't know what the "exported" fields are or should be. + -- Mike + + +Tue Jan 3 14:31:13 GMT 1995 + + * POSIX says that a pathname ending with a '/' means the current + directory whereas SYSV drops the trailing slash. This is only + a problem with mkdir() I think. + -- Mike + + +Fri Dec 16 16:25:44 GMT 1994 + + * Added basic support for Wyse V/386 MPX syslocal(). + -- Mike + + +Fri Dec 9 09:14:04 GMT 1994 + + * Changed eaccess() again. We should always set the uid/gid + rather than fsuid/fsgid since the Linux access() call is + getting fsuid/fsgid from the current uid/gid. + -- Mike + + * Don't bother trying to read x.out segments which have no + data in the executable. + -- Mike + + +Thu Dec 8 11:51:06 GMT 1994 + + * Only include if hasn't + defined KERNEL_DS. The header in the linux subdirectory + was obsoleted in 1.1.69. + -- Mike + + +Fri Dec 2 13:50:03 GMT 1994 + + * Force QMAGIC format when building x286emul. + -- Mike + + * Patches for 1.1.69. + -- Mike + + +Thu Dec 1 13:50:37 GMT 1994 + + * Binfmt_xout.c now checks the trace flag to see if debug messages + should be produced. Trace now has an "xout" option. Trace is + now a Linux binary which uses a personality() syscall to enable + emulation so the iBCS trace syscall becomes accessible. + -- Mike + + * Changed binfmt_xout.c to use 0x1020 as the entry point for + the x286emul kludge overlay. This is the expected value + for a QMAGIC binary which is the default with the newest + compiler. Really I think uselib() should return something + useful but I haven't decided what. + -- Mike + + * Made the schedule() trap (so gdb can be attached before the + process starts running) in binfmt_xout.c a CONFIG option + controlled by the XOUT_TRACE setting. + -- Mike + + * Moved the configuration for the optional items out of Makefile + and into CONFIG. + -- Mike + + +Wed Nov 30 17:08:05 GMT 1994 + + * Fixed a nasty bug in binfmt_coff.c where an extra page was + being allocated in the bss causing brk() checks in 1.1.64 + and later to fail _in_certain_circumstances_. + -- Mike + + +Wed Nov 30 13:58:46 GMT 1994 + + * Added support for unpacking ioctls passed via the STREAMS + interface and forwarding them to the file descriptor. With + a slight change to socksys so that devices with minor 2 get + an anonymous dgram socket immediately they are opened this + allows many more network programs to work. Thanks to an old + piece of code from Chip Rosenthal for revealing how it all + worked - it isn't in the documentation :-). + -- Mike + + +Wed Nov 30 11:27:56 GMT 1994 + + * Fixed handling of brk and BSD sbrk so error returns are + handled correctly. + + +Mon Nov 28 10:48:25 GMT 1994 + + * When doing an IPC_STAT on a semaphore force the semaphore + number to be zero as the kernel code erroneously checks + it. + -- Mike + + +Fri Nov 25 14:26:41 GMT 1994 + + * Massive rework of ipc.c. The previous one was buggy as hell. + This one works with all the demo programs from the Wyse V/386 + IPC documentation. Hopefully someone is going to test it with + some *real* applications! + -- Mike + + +Tue Nov 22 09:11:46 GMT 1994 + + * Change the TTYDEVTYPE ioctl to say we on a pseudo terminal + rather than a console. Anything calling this is likely to + want to try fancy stuff like mapping the console memory + and playing with I/O ports if it thinks we are on a console. + -- Mike + + +Tue Nov 22 09:07:04 GMT 1994 + + * Allow direct usage of 57600 and 115200 serial speeds from + the BSD domain with kernels 1.1.65 and later. + The mask-and-merge for iBCS<->Linux termios should be checked + as we tend to try and preserve unmappable bits where there + is no other conflict. In 99% of cases we won't see a problem + though... + -- Mike + + +Mon Nov 21 10:05:19 GMT 1994 + + * Slight change to previous patch. Confusion over which struct + size we should be using for the verify_area plus we need to + do a VERIFY_WRITE as we will rewrite the data before returning. + -- Mike + + * Changes to ipc.c for reading structures from user space. + -- Roberto Bagnara + + +Thu Nov 17 15:24:23 GMT 1994 + + * Some of the unused KD ioctls were removed from Linux 1.1.64 + (or was it 63?). Changed vtkd.c accordingly. + -- Mike + + +Fri Nov 11 14:15:09 GMT 1994 + + * Moved the x286emul overlay to /usr/lib instead of /lib. There + is no real need for this to be on the root filesystem. + -- Mike + + +Mon Nov 7 13:51:55 GMT 1994 + + * Added a version of the BSD exec.c patch for Linux 1.1.62. + -- Mike + + * Extended SCO keyboard mapping for new kbd. + -- Mike + + +Tue Nov 1 10:57:18 GMT 1994 + + * Changed the personality test in the BSD kernel patch. Apparently + FreeBSD uses a machtype of 134 so it's safer to test for Linux + rather than BSD. + -- Mike + + +Fri Oct 28 11:25:43 GMT 1994 + + * General clean up of the configuration options in the Makefile + and elsewhere. It is now possible to choose which loaders are + included and whether or not BSD or Xenix 286 emulation is + required. + -- Mike + + * Added the x286emul overlay library. This is still very alpha + but SCO's /bin/masm seems to do the things expected of it :-). + -- Mike + + +Wed Oct 5 17:00:13 BST 1994 + + * Fleshed out the F_CHSIZE and F_RDCHK fcntls. I still don't + know if these are ever used from the user layer. + -- Mike + + +Tue Oct 4 13:17:32 BST 1994 + + * Fixed the BSD termios mappings. This _looks_ ok from the + point of view of the NetBSD stty. + -- Mike + + +Fri Sep 23 11:08:31 BST 1994 + + * Add SCO ODT version of CorelDraw to COMPAT file. + -- Doug Ledford + + +Thu Sep 22 09:25:04 BST 1994 + + * Added the phone numbers of McGraw Hill's order desk to the + README file. + -- Mike + + * chsize() was causing a segment error. The callmap entry punted + to a Linux system call but the argument count was not negative + resulting in a call to a bad function pointer. + -- Mike + + * Linux doesn't have the l_sysid field in struct flock so we need + to slide the l_pid field down a word after doing a locking + fcntl. + -- Mike + + +Tue Sep 20 10:31:01 BST 1994 + + * Added a simplistic implementation of writev since BSD seems + so keen to use it as much as possible. + -- Mike + + * Fixed the x.out loader (mostly). This requires a minor patch + to the kernel. Expect this to be put in to the kernel itself + sometime after 1.1.51. Segment support is still buggy and + therefore disabled. If programs assume they know what segments + exist it they are broken anyway! + -- Mike + + +Wed Sep 14 11:24:18 BST 1994 + + * Added extra fcntl code 14 (used by SVR4 for GETLCK). + -- Mike + + +Tue Sep 6 10:58:49 BST 1994 + + * Added setting of fsuid/fsgid to the loaders and changed the + eaccess() function in xnx.c to flip fsuid/fsgid rather than + uid/gid. If you were having problems with setuid/setgid iBCS + binaries this is likely to help. + -- Mike + + +Mon Sep 5 15:07:06 BST 1994 + + * Fixed the bad initialisation of howcnv in signal.c. + -- Mike + + +Fri Sep 2 11:01:26 BST 1994 + + * Added a little program to the Tools subdirectory which will + restamp old binaries with the Linux machine type rather than + zero which is used by BSD. Once this is done you can reliably + distinguish between BSD and Linux binaries (the current Linux + linker will set the correct machine type on all new binaries). + -- Mike + + * Updated the BSD patch. + -- Mike + + * Changed binfmt_coff to avoid passing meaningless MAP_DENYWRITE + and MAP_EXECUTABLE flags to mmap when we are not actually + mapping from a file. It would probably never be a problem... + -- Mike + + +Tue Aug 23 17:21:45 BST 1994 + + * Added my device trace stub in case anyone needs to investigate + and emulate some special device. + -- Mike + + +Wed Aug 17 14:06:34 BST 1994 + + * Added an extern definition of the formats list needed by + the 1.0.x hooks. Presumably this went AWOL at some stage? + -- Mike + + +Fri Aug 12 09:52:38 BST 1994 + + * Slight change to the socksys major allocation. Removed + redundant error message. + -- Mike + + +Wed Aug 10 08:57:32 BST 1994 + + * Added the spelling corrections from the 1.1.42 kernel patch. + -- Mike + + +Fri Aug 5 10:05:14 BST 1994 + + * Added Scott Michel's SCO multiscreen patches. + -- Mike + + * More changes to loaders for latest kernel changes. + -- Mike + + +Wed Jul 27 10:59:14 BST 1994 + + * Changes for 1.1.36 vm/mprotect. + -- Mike + + +Tue Jul 26 14:20:27 BST 1994 + + * Tidied up the system call maps a little. ISC is now handled + by the same maps as SCO. + -- Mike + + +Wed Jul 20 12:39:55 BST 1994 + + * Removed the lock.patch. This is in the latest kernels. + -- Mike + + * Changed the socksys/SCO utsname stuff to do the right thing + if we have the hostname set to the fqdn and the domainname + set to the NIS domain. If hostname is not an fqdn we assume + we are using the domainname == IP domain convention. + -- Mike + + +Wed Jun 29 13:34:34 BST 1994 + + * Revised the lock.patch to fix the unlock problem and allow + locks on devices. This should go to Linus (and probably has). + -- Mike + + * Removed the kernel 1.1.20 patch. This isn't needed as of + 1.1.22. + -- Mike + + +Mon Jun 27 09:26:24 BST 1994 + + * Can't use select() for nap() since the Linux select system + call expects to pull its arguments from the user stack. + Rewritten nap() using itimers. + -- Mike + + * More fixes from Eric for 1.0 compatibility. + -- Mike + + +Fri Jun 24 09:37:50 BST 1994 + + * Added a bit about time zones to the HINTS file. + -- Mike + + * First draft of BSD termios mapping. Still buggy. Needs + work to be useful. + -- Mike + + * Fixed BSD getdirentries() to align dirents on long word + boundaries. 'ls' now works and 'tcsh' finds and executes + commands successfully. + -- Mike + + * ibcs_exit should be listed in callmap.inc with arg count 1 + not -1. + -- Mike + +Thu Jun 23 09:48:43 BST 1994 + + * Lots more BSD-ish stuff. Commit now for release since there is + confusion over versions at the moment. + -- Mike + + * List Xess MOTIF spreadsheet in COMPAT file. + -- Michael K.Johnson + + * When slurping in mis-aligned COFF binaries we shouldn't be + aligning the file offset and virtual address to a page + boundary! + -- Mike + + * Merged Eric's latest patches for 1.0 compatibility and Linux + ELF capability. This was done by hand. I think it's perfect... + -- Mike + + +Wed Jun 22 14:28:38 BST 1994 + + * Many sigsuspend entries in the callmap had argumetn counts + of 1 instead of Spl. This caused kernel faults. + -- Mike + + * Implemented the ioctls for the pseudo nfs device which under + SCO is used to get/set the NIS domain. You need to link + /dev/nfsd to /dev/socksys. + -- Mike + + * The socksys getdomainname() was doing the same write null to + kernel space instead of user space as the wysev386 version. + -- Mike + + +Tue Jun 21 08:54:34 BST 1994 + + * Use the map_bitvec() function (added as part of the BSD changes) + in signal.c. Note that there were quite a few mapping bugs in + the old code. I think I got them all but few would have been + triggered by my SCO and Wyse stuff. + -- Mike + + * Snapshot BSD stuff again ready for release. + -- Mike + + * binfmt_coff.c and binfmt_xout.c should be using mmap(NULL,...) + instead of zeromap_page_range as this will create the vm area + descriptor as well as mapping the pages. This is needed for + the verify_area() in 1.1.20 which has tighter checks than + previous versions. + -- Mike + + * Map stack region as a GROWSDOWN vm area in binfmt_elf.c + -- Mike + + +Fri Jun 17 16:42:59 BST 1994 + + * Major and on going work to add BSD support (optional - see the + Makefile). I'm committing this now so I have a current tree + ready for release when Linus goes to 1.1.20. + -- Mike + + * Wyse get{host,domain}name were using direct assignment to add + a trailing null instead of put_fs_byte(). Oops... + -- Mike + + * Changes for execution domain support which will be in the main + kernel as of 1.1.20. This allows easy registration of lcall7 + handlers, binary loaders etc. for different personalities. + -- Mike + + +Fri Jun 10 10:12:55 BST 1994 + + * Added patch file for kernel locking from Niklas Hallqvist + . This (or something very similar) should + end up in the kernel at some stage. + -- Mike + + * Merged Eric's changes for 1.0 compatibilty - or rather didn't. + After playing with diff for quite a while I finally realised + we'd both done exactly the same changes :-). However Eric + has tested them... + -- Mike + + * Added Brandon's iBCS trace binary from Eric's 1.0 compatibility + release. + -- Mike + + +Thu Jun 9 10:22:56 BST 1994 + + * Mapped msgsys to ibcs_msgsys in callmap.inc. It existed, we + just didn't admit it before :-). + -- Mike + + +Tue Jun 7 08:50:34 BST 1994 + + * Sorted out some more ioctl stuff and added a handler for the + STREAMS ioctl set. This is needed for I_NREAD (number of + characters readable). Some SYSV X libraries contain implicit + assumptions that the X connection is via a STREAM and use + I_NREAD in preference to BSD/socket FIONREAD. + -- Mike + + * Oh, Jeez... The changes made for the official kernel patches + completely shafted the 1.0 compatibility. I've remerged the + previous code with the new code - there may still be some + things that need pulling back though. At this point I don't + have a 1.0 kernel tree around to test against. + -- Mike + + * If a COFF program is not correctly aligned disable demand + paging and resort to slurping the whole lot in at start up. + -- Mike + + * Added missing -I../include to the Tools Makefile. + -- Mike + + +Fri Jun 3 11:53:21 BST 1994 + + * Added my virtual system tools. A virtualised SCO 3.2.4 + system is usable for real work for me... + -- Mike + + * Added the synchronous ioctl set. This conflicts with the + SCO 3.2.x (x < 4) ioctl for getting the video map so it should + be dependent on the file descriptor it is applied to but since + we don't currently support either... + -- Mike + + +Thu Jun 2 17:02:26 BST 1994 + + * Added support for FIORDCHK ioctl. SCO says it's there for + "backward compatibility" but the system programs still + seem to use it (notably ksh). + -- Mike + + +Tue May 31 13:39:34 BST 1994 + + * Patches to sysfs.c for 1.0.x compatibility from Tor with + some extra clean up. + -- Mike + + +Fri May 27 09:15:21 BST 1994 + + * Ensure we set up signal() handlers as SA_ONESHOT and sigaction() + handlers as sticky - similar to patch from Remete Gabor. + -- Mike + + * Added the SCO cxenix sigaction extensions. Barely tested... + -- Mike + + * Added the cxenix {get,set}itimer calls discovered on SCO by + Brandon. Currently these are directly mapped to the Linux + syscalls. They are undocumented by SCO (as far as we know) + and untested by us (for now). + -- Mike + + +Thu May 26 11:58:18 BST 1994 + + * Don't include the 0.0.0.0 to localhost address mapping if we + are building for 1.1.15+. This is mapped in the kernel as of + 1.1.6 and since we don't support 1.1 kernels before 15... + -- Mike + + * Type of signal map vectors should be unsigned long not int. + -- Mike + + * Allow tracing to be compiled in to the COFF loader and turned + on and off with the Tools/trace program. + -- Mike + + * Signal maps moved out to maps/signal.inc. The only special + mapping that happens is for ISC which has a problem with + Oracle sending SIGSTOP to its backend when SIGSTOP doesn't + appear to be defined for ISC. We just map SIGSTOP to 0 so + it appears to work but does nothing. + -- Mike + + * Changes for 1.1.15. This will not work with kernels between + 1.1.10 and 1.1.14 inclusive - guaranteed. It should still + work with the 1.0.x series but has not been tested recently. + It probably works against 1.1.0 to 1.1.13 inclusive but that + is purely coincidence - you shouldn't be using old 1.1.x + kernels as it's a development series. + -- Mike + + +Tue May 24 17:27:54 1994 Eric Youngdale (eric@tantalus) + + * binfmt_xout.c: Use linux_binfmt struct, register_binfmt, + unregister_binfmt as in pl14. + + * binfmt_elf.c, binfmt_xout.c: Likewise. + + * signals.c: Make signals[] and lsignals[] global variables. + + * ibcs/include/ibcs.h: Add prototypes for signals[] and lsignals[]. + + +Tue May 24 10:37:01 BST 1994 + + * Added map entries for the ISC personality to all the maps + files. Must be more careful adding personalities. + -- Mike + + * Added Oracle to the COMPAT file. + -- Mike + + * Remember the problem with interrupting an Informix 4GL program + causing it to go psycho because of I/O errors from the tty? + Well, this doesn't happen with the new tty drivers in 1.1.13. + I never found why it happened... + -- Mike + + * Noted that the 1.1.11 kernel patches are still ok with 1.1.13. + -- Mike + + +Mon May 23 08:50:21 BST 1994 + + * Mapped ISC sysconf() to the existing Xenix sysconf(). This + looks right but isn't checked at all. + -- Mike + + * Added ISC TCSETPGRP and TCGETPGRP ioctl traps. + -- Mike + + +Thu May 19 09:26:34 BST 1994 + + * Added a bug hunting section to the README. + -- Mike + + * Always access the socket layer by picking up the file operations + from an open socket descriptor. This removes the need for + kernel socket functions to be global and should be friendlier + towards a loadable socket layer one day. + -- Mike + + +Mon May 16 10:20:38 BST 1994 + + * Always access system calls via the system call table regardless + of whether we are using a loadable module or linking directly + to the kernel. This allows other things to be loadable too. + -- Mike + + +Wed May 11 13:52:12 BST 1994 + + * Added a tip on how to fix X font problems to the HINTS file. + Other "soft" changes welcome. Does anyone read the ChangeLog? + -- Mike + + * Introduced the PROD.Patches directory and put the WP install + fixes in there. Documented in COMPAT and README. + -- Mike + + * Added some hints on incompatible shell behaviour. + -- Mike + + +Mon May 9 11:07:52 BST 1994 + + * Updated the 1.1 patch file for 1.1.11. + -- Mike + + * Additions for Interactive 4.0 + -- Karl Kiniger (ki@kretz.co.at) + + +Fri May 6 12:03:00 BST 1994 + + * Merged old sysfs.c with the new sysfs.c. The code will now + work against any kernel - 1.0, 1.1, 1.1.9, 1.1.10... + -- Mike + + +Thu May 5 10:39:52 BST 1994 + + * Reworked for compatibility with 1.1.10. Kernel patches + are *not* updated yet. We expect the kernel changes to go + in to the official distribution any time now... + -- Mike + + +Tue May 3 12:03:31 BST 1994 + + * Joe/Brad's IPC additions. + + +Fri Apr 29 10:06:10 BST 1994 + + * Updated the README to explain the difference between sysfs.c + and sysfs.c.old + -- Mike + + +Wed Apr 27 11:38:52 BST 1994 + + * Added mapping of chsize() to ftruncate(). Implemented nap() + using select(). + -- Mike + + * Further fix to termios mapping for iexten and tostop. + -- Mike + + * Updated the 1.1.? patch. New ksyms.c with fewer symbols plus + removed all the socket patches. Sockfunc.h is no longer + required. The 1.0 patch isn't updated but the extra cruft + that's in there now shouldn't be any problem. + -- Mike + + +Tue Apr 26 11:49:07 BST 1994 + + * Removed references to linux/sockfunc.h. We seem to have run + out of internal socket functions to put in it finally. + -- Mike + + * Removed use of socki_lookup(). This just wraps some checks + around inode->i_socket. We assume the socket layer is stable + by now... + -- Mike + + * Access [gs]etsockopt via the socketcall interface. + -- Mike + + * If we have to use our own CFLAGS look in the include directory + above in case we have been dropped in to the kernel. + -- Eric + + * Grab socket file operations when we create a socket rather + than linking against them directly. Similar to Eric's + changes but different... + -- Mike + + +Fri Apr 22 11:10:18 BST 1994 + + * The 'x' class of ioctls are back to being termios rather + than termio. The problem was that the field size in iBCS + termios and Linux termios is different. + -- Mike + + * Added iBCS <-> Linux termios mapping. This is untested and + probably imperfect at this stage but nothing crashes with + this code... + -- Mike + + * The iBCS time() syscall doesn't take an argument, the save, + if any, is handled in the interface library. + -- Mike + + * Updated the 1.1 kernel patch to be against 1.1.8. It won't + work with anything less than 1.1.8 but then if you are + playing with 1.1 you should be playing with the latest... + This involves a change in the way sysfs() works. If you + are using 1.0 and have applications that call sysfs() + (practically none do) then you need to build with sysfs.c.old. + -- Mike + + * The Linux kernel 1.1.8 replaces the static file_systems + table with a linked list ready for loadable file systems. + Naturally, I was ready for this... :-( + -- Mike + + +Thu Apr 21 10:34:34 BST 1994 + + * sysfs.c should be including linux/string.h to get the + inline string functions rather than needing library + functions. + -- Mike + + * Added code to map between Linux termio structs and SCO/iBCS + termio structs. There are slight differences. Mapping needs + to be done for termios structs too. Anything that uses termios + at this stage is likely to ge a nasty shock! + -- Mike + + +Tue Apr 19 22:56:55 1994 Eric Youngdale (eric@esp22) + + * ibcs.h: Put declaration of sys_call_table outside of ifdef. + (So can be compiled into kernel instead as a module). + + +Tue Apr 19 10:21:17 BST 1994 + + * It looks as though the 'x' class of ioctls should be termio + ioctls rather than termios. At least this is the case as far + as SCO 3.2.4 stty appears to be concerned. + -- Mike + + * Avoid copying the entire lock structure backwards and forwards + just to increment one field in open.c. There could be a problem + here - SCO has a sysid field *before* the pid field but only + if _XOPEN_SOURCE or _POSIX_SOURCE is defined at compile time. + There appears to be no obvious way to know what is being used??? + -- Mike + + +Mon Apr 18 08:49:37 BST 1994 + + * There appear to odd little niceties involved with SYSV which + depend on system configuration and the way users do things. + Added a HINTS file with known problems/workarounds. + -- Mike + + * Changed some annoying KERN_ERRs to KERN_DEBUGs in signal.c + -- Mike + + * Watch out for (mis)use of INADDR_ANY instead of localhost + (primarily by syslog() code?) and replace it with the + localhost address. We should perhaps do this for sendto() + as well? (Eric spotted this one on CorelDraw but it's a + problem with the standard libsocket.c) + -- Mike + + * Processes should be allowed to reduce their file size + limit but only increase it if they have root privileges. + -- Mike + + * Fixed the bug in [f]statfs where the first two arguments + to memcpt_tofs() were exchanged (spotted by Eric). + -- Mike + + * SCO seems to like utsys (v7_utsname) to return the same + thing for sysname and nodename fields just like the SCO + extended utsname structure has. The SVR4 (abi_utsname) + return is unknown at this time. + -- Mike + + * Removed comments on IPC from README. It *is* fixed? + -- Mike + + * Fix IPC which was broken by syscall changes. Also fix + structure mappings. + -- Joseph L. Portman III + + +Thu Apr 14 11:27:24 BST 1994 + + * At some stage SCO managed to build some of their binaries + with the copyright comment string in quotes so we have a + new recognition string in the COFF loader. (Seen in uname + on a 3.2.2 system). + -- Mike + + * If we have tracing compiled in then only give unsupported + syscall messages if we are tracing the API or the syscall + in question. This allows us to quieten unsupported but + unimportant syscalls. + -- Mike + + * Comment on the IPC limitations in the README file. + -- Mike + + * Added implementation of xnx_pathconf(). Actually it doesn't + look as if we really need it. The Microsoft C compiler seems + to be misusing it anyway and doesn't even care that it gets + an error. + -- Mike + + +Wed Apr 13 09:14:50 BST 1994 + + * Added handling of TIOC[GS]PGRP. + -- Mike + + * Added implementation of xnx_eaccess(). This is currently + simpleminded because Linux access() is. My eaccess() may + even be wrong. + -- Mike + + * When tracing signal delivery we shouldn't be clearing the + signal flag after reporting it or the signal is never actually + delivered. I copied the assembler from the kernel and forgot + to deleted an opcode... + -- Mike + + * Signal 0 should have been identity mapped so kill 0 works. + -- Brandon S. Allbery (kf8nh@kf8nh.ampr.org) (bsa@kf8nh.wariat.org) + +Tue Apr 12 14:30:25 BST 1994 + + * Corrected file size passed to/from setrlimit/getrlimit + -- Graham Adams (gadams@ddrive.demon.co.uk) + + +Tue Apr 12 11:16:45 BST 1994 + + * Added support for an obscure SCO extension that is used + to get SCO's extended utsname information. + -- Mike + + * Changed ipc.c to always go via the ipc syscall rather than + direct to internal functions. This should survive if ipc + isn't in the kernel. It should even do sensible things if + the ipc module is loaded/unloaded on us. + -- Mike + + * Initial changes to access system calls via sys_call_table + -- Mike + + +05 April 1994 + + * Eric's pre-release fixes. + + +Wed Mar 30 22:35:28 1994 Eric Youngdale (eric@esp22) + + * ioctl.c: Change 'F' to 'f' for SVr4 FIONREAD ioctl. + + * Makefile: Add svr4.c. + + * svr4.c: New file (sort of - it got lost in shuffle before). + + * include/ibcs/ibcs.h: Include prototypes for abi_uname. + + * maps/callmap.inc: Insert abi_uname in syscall number 135. + Add sys_rename in slot 134 (emacs v18 requires this). + + +Tue Mar 29 23:32:35 1994 Eric Youngdale (eric@esp22) + + * Makefile: Fix so that we do not need uname. Use symbol from + .config instead. + + * README: Update a bit. + + +28 March 1994 + + * Preparation for release: + Tidy up documentation and create CREDITS file from the old + ToDo list. + -- Mike + + +27 March 1994 + + * Preparation for release: + Move headers into a subdirectory. + Move maps into a subdirectory. + -- Mike + + +25 March 1994 + + * Changed the COFF loader so that if the filesystem doesn't + support mmap we read in the whole lot initially and let + it page to swap if necessary. This is already in the x.out + loader, it should go in the ELF loader too at some point. + -- Mike + + +24 March 1994 + + * Added a loader for x.out i386 small model binaries - i.e 386 + Xenix programs. <=286, non-small model binaries are not + supported and not likely to be in the near future. + -- Mike + + +Wed Mar 23 23:12:54 1994 Eric Youngdale (eric@esp22) + + * Add ioctl for 0x4004667f (FIONREAD) (used by SVr4). + + * map.h (map_segment.map): Make unsigned. + + * hrtsys.c: New file implementing parts of the hrtsys syscall. + + +02 March 1994 + + * Add socket value mappings. This meant a general move round + to tidy things up and group map functions/tables. + There is a new kernel patch in the Patches directory called + net.patch which gives us access to the sock_*sockopts + functions directly. + -- Mike + + +28 February 1994 + + * Implementation of poll(). + -- Eric + + +25 February 1994 + + * Pedantic change to call maps so that IBCS_function contains + a void * instead of a function pointer - we cast it as + necessary later in emulate.c. The warnings were annoying me. + + * Moved struct abi_sigaction from signal.c to abi4.h so it is + available for prototype declarations. Changed prototype for + abi_sigsuspend to correspond to implementation in signal.c. + -- Mike + + * Reversed out Eric's earlier signal patches and added new ones. + -- Mike + + * Updated trace code and trace control program to be useful. + Control of tracing individual functions is still not there + yet - perhaps another day. + Default trace mode is now none (i.e. only functions with + the trace flag set are traced). Use the trace program to + change the trace level. + -- Mike + + * File modes (open/fcntl flags) are different between Linux and + iBCS so we need to map between them. Open also requires this + so fcntl.c is now merged with open.c. Failure to set and reset + non-blocking mode was what was breaking Unipox. + -- Mike + + * Signal handling function changes to map to and from the Linux + signal set and sigaction flags correctly. + -- Eric + + +24 February 1994 + + * Added code to the emulate() function to let us know when we + are about to process a signal on exit from the syscall. + -- Mike + + * Implemented proctl() as a no-op. It's not really relevent + under Linux. + -- Mike + + * Added argument count and type for eaccess() + -- Mike + + * Have emulate.c return -ENOSYS for unimplemented system calls + rather than zero. + -- Mike + + * Added Eric's patches to waitpid. + + * Created the ChangeLog! diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/Error.map linux/Documentation/abi/Error.map --- linux-2.4.3/Documentation/abi/Error.map Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/Error.map Fri Mar 30 16:12:20 2001 @@ -0,0 +1,143 @@ +Mapping of error codes from Linux to various personalities. Codes which Linux +may generate but which can't be mapped directly in a given personality must +be mapped to the nearest equivalent which may invoke the correct behaviour +in the application. This is especially true for things like the ERESTART* +set of error returns! + +NOTES: + +The Xenix set was built with reference to an old SCO Xenix manual rather +than by reference to a real system. It may be incomplete or wrong. If anyone +has access to the Xenix TCP/IP kit we need to add mappings for the TCP/IP +error codes. + +Other personalities may need adding. COFF binaries default + +Linux Name Linux ABI SCO Wyse Xenix 386bsd + +EPERM 1 /* Operation not permitted */ +ENOENT 2 /* No such file or directory */ +ESRCH 3 /* No such process */ +EINTR 4 /* Interrupted system call */ +EIO 5 /* I/O error */ +ENXIO 6 /* No such device or address */ +E2BIG 7 /* Arg list too long */ +ENOEXEC 8 /* Exec format error */ +EBADF 9 /* Bad file number */ +ECHILD 10 /* No child processes */ +EAGAIN 11 35 /* Try again */ +ENOMEM 12 /* Out of memory */ +EACCES 13 /* Permission denied */ +EFAULT 14 /* Bad address */ +ENOTBLK 15 /* Block device required */ +EBUSY 16 /* Device or resource busy */ +EEXIST 17 /* File exists */ +EXDEV 18 /* Cross-device link */ +ENODEV 19 /* No such device */ +ENOTDIR 20 /* Not a directory */ +EISDIR 21 /* Is a directory */ +EINVAL 22 /* Invalid argument */ +ENFILE 23 /* File table overflow */ +EMFILE 24 /* Too many open files */ +ENOTTY 25 /* Not a typewriter */ +ETXTBSY 26 /* Text file busy */ +EFBIG 27 /* File too large */ +ENOSPC 28 /* No space left on device */ +ESPIPE 29 /* Illegal seek */ +EROFS 30 /* Read-only file system */ +EMLINK 31 /* Too many links */ +EPIPE 32 /* Broken pipe */ +EDOM 33 /* Math argument out of domain of func */ +ERANGE 34 /* Math result not representable */ +EDEADLK 35 45 45 45 36 11 /* Resource deadlock would occur */ +ENAMETOOLONG 36 78 78 228 EINVAL 63 /* File name too long */ +ENOLCK 37 46 46 46 45 77 /* No record locks available */ +ENOSYS 38 89 89 EINVAL EINVAL 78 /* Function not implemented */ +ENOTEMPTY 39 93 145 231 EINVAL 66 /* Directory not empty */ +ELOOP 40 90 150 227 EINVAL 62 /* Too many symbolic links encountered */ +EWOULDBLOCK EAGAIN 90 90 200 EINVAL 35 /* Operation would block */ +ENOMSG 42 35 35 35 43 ? /* No message of desired type */ +EIDRM 43 36 36 36 44 ? /* Identifier removed */ +ECHRNG 44 37 37 37 EINVAL ? /* Channel number out of range */ +EL2NSYNC 45 38 38 38 EINVAL ? /* Level 2 not synchronized */ +EL3HLT 46 39 39 39 EINVAL ? /* Level 3 halted */ +EL3RST 47 40 40 40 EINVAL ? /* Level 3 reset */ +ELNRNG 48 41 41 41 EINVAL ? /* Link number out of range */ +EUNATCH 49 42 42 42 EINVAL ? /* Protocol driver not attached */ +ENOCSI 50 43 43 43 EINVAL ? /* No CSI structure available */ +EL2HLT 51 44 44 44 EINVAL ? /* Level 2 halted */ +EBADE 52 ? 50 50 EINVAL ? /* Invalid exchange */ +EBADR 53 ? 51 51 EINVAL ? /* Invalid request descriptor */ +EXFULL 54 ? 52 52 EINVAL ? /* Exchange full */ +ENOANO 55 ? 53 53 EINVAL ? /* No anode */ +EBADRQC 56 ? 54 54 EINVAL ? /* Invalid request code */ +EBADSLT 57 ? 55 55 EINVAL ? /* Invalid slot */ +EDEADLOCK 58 ? 56 56 36 11 /* File locking deadlock error */ +EBFONT 59 ? 57 57 EINVAL ? /* Bad font file format */ +ENOSTR 60 EINVAL ? /* Device not a stream */ +ENODATA 61 EINVAL ? /* No data available */ +ETIME 62 EINVAL ? /* Timer expired */ +ENOSR 63 EINVAL ? /* Out of streams resources */ +ENONET 64 EINVAL ? /* Machine is not on the network */ +ENOPKG 65 EINVAL ? /* Package not installed */ +EREMOTE 66 EINVAL 71 /* Object is remote */ +ENOLINK 67 EINVAL ? /* Link has been severed */ +EADV 68 EINVAL ? /* Advertise error */ +ESRMNT 69 EINVAL ? /* Srmount error */ +ECOMM 70 EINVAL ? /* Communication error on send */ +EPROTO 71 ? ? /* Protocol error */ +EMULTIHOP 72 74 74 74 ? ? /* Multihop attempted */ +EDOTDOT 73 76 76 76 ? ? /* RFS specific error */ +EBADMSG 74 77 77 77 ? ? /* Not a data message */ +EOVERFLOW 75 79 EINVAL EINVAL ? ? /* Value too large for defined data type */ +ENOTUNIQ 76 80 80 80 ? ? /* Name not unique on network */ +EBADFD 77 81 81 81 ? ? /* File descriptor in bad state */ +EREMCHG 78 82 82 82 ? ? /* Remote address changed */ +ELIBACC 79 83 83 83 ? ? /* Can not access a needed shared library */ +ELIBBAD 80 84 84 84 ? ? /* Accessing a corrupted shared library */ +ELIBSCN 81 85 85 85 ? ? /* .lib section in a.out corrupted */ +ELIBMAX 82 86 86 86 ? ? /* Attempting to link in too many shared libraries */ +ELIBEXEC 83 87 87 87 ? ? /* Cannot exec a shared library directly */ +EILSEQ 84 88 EINVAL EINVAL ? ? /* Illegal byte sequence */ +ERESTART 85 91 EINTR EINTR ? ? /* Interrupted system call should be restarted */ +ESTRPIPE 86 92 EINVAL EINVAL ? ? /* Streams pipe error */ +EUSERS 87 94 EINVAL 233 ? 68 /* Too many users */ +ENOTSOCK 88 95 93 203 ? 38 /* Socket operation on non-socket */ +EDESTADDRREQ 89 96 94 204 ? 39 /* Destination address required */ +EMSGSIZE 90 97 95 205 ? 40 /* Message too long */ +EPROTOTYPE 91 98 96 206 ? 41 /* Protocol wrong type for socket */ +ENOPROTOOPT 92 99 EINVAL 207 ? 42 /* Protocol not available */ +EPROTONOSUPPORT 93 120 97 208 ? 43 /* Protocol not supported */ +ESOCKTNOSUPPORT 94 121 98 209 ? 44 /* Socket type not supported */ +EOPNOTSUPP 95 122 99 210 ? 45 /* Operation not supported on transport endpoint */ +EPFNOSUPPORT 96 123 100 211 ? 46 /* Protocol family not supported */ +EAFNOSUPPORT 97 124 101 212 ? 47 /* Address family not supported by protocol */ +EADDRINUSE 98 125 102 213 ? 48 /* Address already in use */ +EADDRNOTAVAIL 99 126 103 214 ? 49 /* Cannot assign requested address */ +ENETDOWN 100 127 104 215 ? 50 /* Network is down */ +ENETUNREACH 101 128 105 216 ? 51 /* Network is unreachable */ +ENETRESET 102 129 106 217 ? 52 /* Network dropped connection because of reset */ +ECONNABORTED 103 130 107 218 ? 53 /* Software caused connection abort */ +ECONNRESET 104 131 108 219 ? 54 /* Connection reset by peer */ +ENOBUFS 105 132 63 220 ? 55 /* No buffer space available */ +EISCONN 106 133 110 221 ? 56 /* Transport endpoint is already connected */ +ENOTCONN 107 134 111 222 ? 57 /* Transport endpoint is not connected */ +ESHUTDOWN 108 143 112 223 ? 58 /* Cannot send after transport endpoint shutdown */ +ETOOMANYREFS 109 144 113 224 ? 59 /* Too many references: cannot splice */ +ETIMEDOUT 110 145 114 225 ? 60 /* Connection timed out */ +ECONNREFUSED 111 146 115 226 ? 61 /* Connection refused */ +EHOSTDOWN 112 147 116 229 ? 64 /* Host is down */ +EHOSTUNREACH 113 148 117 230 ? 65 /* No route to host */ +EALREADY 114 149 92 202 ? 37 /* Operation already in progress */ +EINPROGRESS 115 150 91 201 ? 36 /* Operation now in progress */ +ESTALE 116 EINVAL EINVAL 237 ? 70 /* Stale NFS file handle */ +EUCLEAN 117 ? 135 135 35 ? /* Structure needs cleaning */ +ENOTNAM 118 ? 137 137 37 ? /* Not a XENIX named type file */ +ENAVAIL 119 ? 138 138 38 ? /* No XENIX semaphores available */ +EISNAM 120 ? 139 139 39 ? /* Is a named type file */ +EREMOTEIO 121 ? 140 140 EINVAL ? /* Remote I/O error */ +EDQUOT 122 ? ENOSPC 234 ENOSPC 69 /* Quota exceeded */ + +ERESTARTSYS 512 EINTR EINTR EINTR EINTR EINTR +ERESTARTNOINTR 513 EINTR EINTR EINTR EINTR EINTR +ERESTARTNOHAND 514 EINTR EINTR EINTR EINTR EINTR /* restart if no handler.. */ diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/HINTS linux/Documentation/abi/HINTS --- linux-2.4.3/Documentation/abi/HINTS Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/HINTS Fri Mar 30 16:12:20 2001 @@ -0,0 +1,245 @@ +PROBLEM: + Cannot determine user name by reference to /etc/passwd. Failure + to determine the user name causes some programs (notably programs + built with Informix 4GL) to exit. + +REASON: + The functions that parse /etc/passwd are sensitive under SCO + at least. A corrupt line is taken to be the end of the file + and further entries are ignored. Any line which has a null + home directory counts as a corrupt line for SCO. + +SOLUTION: + Ensure that all lines in /etc/passwd have home directories + specified. Simply edit /etc/passwd with an editor. + + +# ----------------------------------------------------------------------- + +PROBLEM: + Cannot connect to X server using local connection. + +REASON: + Some versions of X libraries seem to require 'localhost' to be + allowed to connect to the X server even if we aren't using a + TCP/IP connection. The X libraries used for VSI*FAX require + this, the X libraries used for WordPerfect don't. + +SOLUTION: + Explicitly allow 'localhost' to connect to the X server using + 'xhost localhost'. + + +# ----------------------------------------------------------------------- + +PROBLEM: + Installation disks claim to be Unix tar format but they appear + to be blank MS-DOS format disks! + +REASON: + Unix provides two floppy devices, the normal floppy devices + that we all know and love (and which are listed as the Xenix + compatible devices in the man page) and a second set which + skips the first track of the disk. For some reason a few vendors + seem to use this second set when preparing distribution disks. + WordPerfect seem to do this. Linux currently only supports + the normal floppy devices. + +SOLUTION: + You have to skip the first track by hand and read each disk + individually. Try 'dd if=/dev/fd0 bs=18k skip=1 | tar xfv -' + for a 3.5" high density disk. Change the 18k to 15k for a + 5.25" high density disk. + +# ----------------------------------------------------------------------- + +PROBLEM: + A script bombs out with an unexpected EOF looking for "'". This + only happens on Linux. + +REASON: + There is a bug in the script which is only a problem on Linux. + Take the following example: + + count=`ls | wc | awk '{ printf "%05d", $1 }` + + Note the missing "'" at the end of the awk statment. The /bin/sh + supplied with SCO will assume (in this case correctly) that the + "'" should have occurred immediately before the closing "`" and + the expression will succeed. The /bin/sh used with Linux (normally + bash) does not make this assumption and gives an error message. + +SOLUTION: + Either fix the script or arrange to have it run by a SYSV shell + rather than bash. + +# ----------------------------------------------------------------------- + +PROBLEM: + Test complains that a numeric argument is required before -eq, -le + etc. + +REASON: + The GNU shellutils test and the test built in to bash which are + the versions of test used under Linux do not accept a null + argument as equivalent to 0 so 'test "" -le 5' will give an error. + Under SCO a null argument is taken as equivalent to 0 so the + statement would be evaluated as 'test 0 -le 5'. + +SOLUTION: + Fix the script to check arguments for validity before using them + or provide a fixed version of test and ensure that it is used in + preference to any shell built in. + +# ----------------------------------------------------------------------- + +PROBLEM: + Some X fonts supplied with packages appear corrupt. + +REASON: + These are probably snf fonts. The XFree86 X server used with + Linux appears to fail to load some snf fonts silently and displays + garbage. Pcf fonts work ok and should be used where possible. + +SOLUTION: + If you only have the snf fonts all you can do is to try asking the + vendor for pcf versions or the bdf definitions. + + If you have the bdf definitions (WordPerfect ship them) then you + can build a pcf set using: + + # for bdffn in *.bdf + > do + > fn=`basename $bdffn .bdf` + > [ -r $fn.snf ] && mv $fn.snf $fn.snf.old + > bdftopcf -o $fn.pcf $bdffn + > done + # mkfontdir . + # xset fp rehash + +# ----------------------------------------------------------------------- + +PROBLEM: + Function keys don't work. + +REASON: + The default sequences for function keys under Linux are "sort of" + VT10x like whereas you have probably told your application that + you are running on an ansi or SCO console. + +SOLUTION: + It is probably best to run as an ansi screen - especially if + colour is used - so use the "loadkeys" program to load the + SCO.map keyboard description from the PROD.Patches directory. + This directory also contains flexible termcap and terminfo + descriptions which will allow you run permanently with a SCO + or SVR4-like console. + +# ----------------------------------------------------------------------- + +PROBLEM: + Line drawing characters come out as weird symbols. + +REASON: + The application believes you are using a console screen with a + PC character set and is using 8-bit codes rather than escape + sequences. Linux defaults to an ISO8859-1 character set though. + +SOLUTION: + Linux can be switched to PC character set mode with the escape + sequence ESC-(-U. Arrange to have this sequence sent either + before the application is started or as part of the initialisation + that the application does. You can restore the ISO character + set afterwards with ESC-(-K. + +# ----------------------------------------------------------------------- + +PROBLEM: + SYSV binaries see the wrong time zone. + +REASON: + SYSV binaries establish the time zone from the TZ environment + variable whereas Linux uses BSD style zoneinfo files generally. + +SOLUTION: + Set the TZ environment variable to reflect your time zone. Note + that the zoneinfo mechanism can also use TZ in preference to + the /usr/lib/zoneinfo/localtime file if you wish. For this to + work you must have /usr/lib/zoneinfo/posixrules linked to one + of the US timezone files. The posixrules file defines how the + zoneinfo functions interpret TZ and this information is only + found in the US data files. See the documentation for the + timezone/zoneinfo package for details. + +# ----------------------------------------------------------------------- + +PROBLEM: + BSD binaries don't see the right time zone. + +REASON: + Although BSD binaries use the same timezone handling method as + Linux they expect the zoneinfo information in different places. + +SOLUTION: + Make the links: + + # ln -s /usr/lib/zoneinfo /etc/localtime + # ln -s /usr/lib/zoneinfo /usr/share/zoneinfo + +# ----------------------------------------------------------------------- + +PROBLEM: + BSD binaries complain that they can't find /etc/termcap. + +REASON: + They may be lying. BSD sometimes uses /usr/share/misc/termcap + or ~/.termcap (if it exists). + +SOLUTION: + Either move termcap to /usr/share/misc and make /etc/termcap + a link to it or make /usr/share/misc/termcap a link to /etc/termcap. + The use of /usr/share/misc/termcap may be useful in a networked + environment. +# ----------------------------------------------------------------------- + +PROBLEM: + SVr4 binaries cannot locate shared libraries, or fail to start. + +REASON: + The shared libraries are not in the correct location, or the dynamic + loader cannot be located by the kernel. + +SOLUTION: + Put all SVr4 shared libraries in the directory /usr/i486-sysv4/lib. + Then create two symbolic links: + + ln -s /usr/i486-sysv4/lib/libc.so.1 /usr/lib/libc.so.1 + ln -s /usr/i486-sysv4/lib/ld.so.1 /usr/lib/ld.so.1 +# ----------------------------------------------------------------------- + +PROBLEM: + SVr4 binaries want to access terminfo instead of termcap + +REASON: + SVr4 traditionally uses something called terminfo instead of + termcap to specify terminal characteristics. + +SOLUTION: + The ncurses distribution (available on many fine ftp sites) + contains a terminfo database. Just install this, and you + should be all set. +# ----------------------------------------------------------------------- + +PROBLEM: + The Informix Dynamic Server installation for SCO says + invalid INFORMIXDIR or insufficient space. + +REASON: + It wants to scan /etc/mnttab to find all possible + filesystems. Since Linux uses /etc/mtab instead the + installation program is under the impression you have + no filesystems and no space(!). + +SOLUTION: + Run the perl script Tools/mkmnttab which will build an + /etc/mnttab from /etc/mtab. diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/Local-X linux/Documentation/abi/Local-X --- linux-2.4.3/Documentation/abi/Local-X Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/Local-X Fri Mar 30 16:12:20 2001 @@ -0,0 +1,22 @@ +** Local X interface + +The local X interface is simplistic. It assumes only one local X server +exists and assumes that the pathname of the Unix domain socket for +local connections is always /tmp/.X11-unix/X0. + + The SCO code opens both /dev/X0R and /dev/spx, writes a single byte +to /dev/X0R, reads a message from /dev/X0R with getmsg then writes this +message to /dev/spx with putmsg and closes /dev/X0R. This establishes +the /dev/spx file descriptor as a connection to the X server listening +on /dev/X0R. + + We ignore all activity on the /dev/X0R device (hence it is a link to +/dev/null), getmsg and putmsg are stubbed so don't do anything and opens +on the /dev/spx simply replace the open inode with a socket connected +to the X server's Unix domain socket. + + At some point in the future we will implement a simple minded /dev/X* +driver that returns some form of id via the getmsg which can then be +passed to /dev/spx with putmsg and which will allow /dev/spx to connect +to the relevant X server. This will only happen if someone actually +*needs* multiple local X servers... diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/Notes.Signal linux/Documentation/abi/Notes.Signal --- linux-2.4.3/Documentation/abi/Notes.Signal Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/Notes.Signal Fri Mar 30 16:12:20 2001 @@ -0,0 +1,42 @@ +Drew, Joe, and Brandon. + +This file contains my code for the signal functions. I realized that the +existing signal functions will not suffice. This module should do the +proper processing for iBCS signals. + +There are patches to the emulate module offered by Drew in his pl14n code +release. The Makefile was changed to include the module. + +In addition, I have include a signal.doc file which contains the text from +my UNIX S5 manual describing the functions used by iBCS. I based the +emulator code on this document. Please look it over and see if I have +messed up. I believe it to be correct. However, it never hurts to have +someone check the work before we can trust it. + +It follows what I believe to be the proper calling sequence for signals. I +sent a message to the IBSC2 group with the text from the McGraw Hill book +concerning signals. If you would like a copy of the message, then let me +know. + +Of couse, this could be totally wrong. That is the whole point about +sending this out to a limited distribution. + +In addition to the processing for the various function requests, you may +have noticed that the signal _numbers_ must be changed between the values +used by iBCS and Linux. + +I have had to modify the emulate.c module to export an additional +procedure (and for emulate.c to use the procedure itself.) In addition, I +change the branch table to re-direct the signal processing to the signal.c +module. + +I hope that this will help the project when it has been proven workable. +Please let me know how this turns out -- one way or the other. + +If it does work, then I'll give the final code to Drew to merge into the +master code. That is unless, Drew, you already have it. :-) + +Thanks much. + +-- +Al Longyear longyear@netcom.com longyear@sii.com diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/Personality linux/Documentation/abi/Personality --- linux-2.4.3/Documentation/abi/Personality Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/Personality Fri Mar 30 16:12:20 2001 @@ -0,0 +1,88 @@ +*** Why are multiple personalities necessary? + +Personalities are used to provide the expected set of syscalls and error +code mapping for non-Linux processes. In theory the set of syscalls and +error codes should be standardised across all SYSV systems. In practice +this is the case for SVR4, however SVR3 is a much older code base and +many vendors have extended it leading to incompatibilities between the +expected interfaces. Personalities allow us to vary the interface presented +on a per-process basis thus allowing Linux to run binaries created for +different vendor's extended SVR3s simultaneously. + + +*** How are personalities implemented? + +The per-process task structure contains a field "personality". This defaults +to 0 for Linux binaries, 1 (SVR4) for ELF binaries and 2 (SVR3) for COFF +binaries. However when the COFF loader is called on to load a new binary +it looks at the first 1k of data in each .comment section and compares +the strings it finds with a built in table. If it finds a match it will +set the personality appropriately. + + When the application makes a system call the iBCS emulation layer uses +the personality code in the per-process task structure to determine which +system call mappings to use to locate the correct function. + + If the function returns an (Linux) error code the iBCS emulation layer +uses the personality code to determine which error code mappings to use +to translate the error code in to a value the application will understand. + + +*** What personalities are implemented? + +Currently the implemented personalities are SVR4, SVR3 (as a direct +subset of SVR4), SCO 3.[24] and Wyse V/386 3.2.1. Of these the Wyse +emulation is the most complete at this time. Rather than using the +more common streams based TCP/IP stack on their SVR3, Wyse used a BSD +implementation with a system call interface. Currently the Wyse emulation +is the only one capable of running non-Linux TCP/IP binaries. + + +*** When do I need to add a personality rather than use the default? + +When your applications start failing for inexplicable reasons! Seriously, +if you have an SVR3 based Unix which does not currently have its own +personality defined then you should check some things very carefully. + + Firstly compare your system's /usr/include/sys/errno.h with the data +in the Error.map file. If the values defined in your errno.h do not +match those in the ABI column then you will need to create a new +personality in order to map error codes to the correct values. + + Next compare your system's /usr/include/sys.s with the data in the +Syscall.map file. If there are system calls in your sys.s that don't +do the same thing as those in the ABI column (other than ones that +simply aren't implemented on your system) then you will need to create +a new personality in order to mapp system calls to the correct functions. + + +*** How do I add a new personality? + +The first step is to find a way for the COFF loader to recognise your +binaries as being different. To do this you need to examine the comments +embedded in a range of binaries, system executables, bought programs of +various ages and locally compiled programs, using "mcs -p" to list the +.comments sections. If you don't have "mcs" use "strings" and look for +version or copyright messages. You are looking for one or more strings +near the top which uniquely identify the system. + + Once you have your identifying strings you must add a value for the +new personality to linux/include/linux/personality.h (just use the +next highest number) and add the strings to the table in the COFF loader +linux/fs/binfmt_coff.c. + + The next step is to modify the error map. Edit the file errmap.inc and +look at the end of the file where there is an array of pointers to error +maps call err_map. There is one entry for each personality. Add a new +entry to the end for your personality. If your personality is compatible +with an exising personality you can simply reuse the same error map (see +the duplicate entries for the SVR4 map which is use for both SVR4 and +SVR3 personalities), otherwise you must figure out how to create a new +error mapping. One day it may be documented here :-). + + Next you must modify the syscall mapping. Edit the file callmap.inc +and look at the end of the file where there is an array containg one +pointer for each personality. Add a new entry to the end. If your syscalls +match one of the existing personalities you may reuse the existing map. +Otherwise you have to build a new one. Again, one day it may be documented +here... diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/README.first linux/Documentation/abi/README.first --- linux-2.4.3/Documentation/abi/README.first Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/README.first Fri Mar 30 16:12:20 2001 @@ -0,0 +1,13 @@ +First notes on Linux-ABI documentation +2001-March-30 +Christoph Hellwig, + + +Please note that most files in this directory are leftovers from iBCS, which is +dead since 1998. Do not expect this files to uptodate or complete. + +I will update the files and add new onces from time to time. + + --hch + +$Id$ diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/Syscall.map linux/Documentation/abi/Syscall.map --- linux-2.4.3/Documentation/abi/Syscall.map Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/Syscall.map Fri Mar 30 16:12:20 2001 @@ -0,0 +1,185 @@ +Call ABI SCO 3.2 SCO 3.4 Wyse V/386 3.2.1 386bsd + + 1 exit + 2 fork + 3 read + 4 write + 5 open + 6 close + 7 wait + 8 creat + 9 link + 10 unlink + 11 exec + 12 chdir + 13 time fchdir + 14 mknod + 15 chmod + 16 chown + 17 brk/break + 18 stat getfsstat + 19 seek/seek + 20 getpid + 21 mount + 22 umount + 23 setuid + 24 getuid + 25 stime geteuid + 26 ptrace + 27 alarm recvmsg + 28 fstat sendmsg + 29 pause recvfrom + 30 utime accept + 31 stty getpeername + 32 gtty getsockname + 33 access + 34 nice chflags + 35 statfs fchflags + 36 sync + 37 kill + 38 fstatfs stat + 39 setpgrp getppid + 40 cxenix lstat + 41 dup + 42 pipe + 43 times getegid + 44 prof + 45 lock/plock ktrace + 46 setgid sigaction + 47 getgid + 48 signal sigprocmask + 49 msgsys getlogin + 50 sysi86/sys3b setlogin + 51 sysacct/acct + 52 shmsys sigpending + 53 semsys sigaltstack + 54 ioctl + 55 uadmin reboot + 56 ??? revoke + 57 utssys symlink + 58 ??? readlink + 59 execv + 60 umask + 61 chroot + 62 fcntl fstat + 63 ulimit getkerninfo + 64 ??? getpagesize + 65 ??? msync + 66 ??? vfork + 67 ??? vread + 68 ??? vwrite + 69 ??? sbrk + 70 advfs sstk + 71 unadvfs mmap + 72 rmount vadvise + 73 rumount munmap + 74 rfstart mprotect + 75 ??? madvise + 76 rdebug vhangup + 77 rfstop vlimit + 78 rfsys mincore + 79 rmdir getgroups + 80 mkdir setgroups + 81 getdents getpgrp + 82 libattach setpgid + 83 libdetach setitimer + 84 sysfs wait + 85 getmsg swapon + 86 putmsg getitimer + 87 poll gethostname + 88 lstat --- --- --- sethostname + 89 symlink --- --- --- getdtablesize + 90 readlink --- symlink --- dup2 + 91 setgroups --- lstat --- --- + 92 getgroups --- readlink --- fcntl + 93 fchmod --- --- --- select + 94 fchown --- --- --- --- + 95 sigprocmask --- --- --- fsync + 96 sigsuspend --- --- --- setpriority + 97 sigaltstack --- --- --- socket + 98 sigaction --- --- --- connect + 99 sigpending --- --- --- accept +100 context --- --- --- getpriority +101 evsys --- --- --- send +102 evtrapret --- --- --- recv +103 statvfs --- --- --- sigreturn +104 fstatvfs --- --- --- bind +105 ??? setsockopt +106 nfssys --- --- --- listen +107 waitsys --- --- --- vtimes +108 sigsendsys --- --- --- sigvec +109 hrtsys --- --- --- sigblock +110 acancel --- --- --- sigsetmask +111 async --- --- --- sigsuspend +112 priocntlsys --- --- --- sigstack +113 pathconf --- --- --- recvmsg +114 mincore --- --- --- sendmsg +115 mmap --- --- --- vtrace +116 mprotect --- --- --- gettimeofday +117 munmap --- --- --- getrusage +118 fpathconf --- --- --- getsockopt +119 vfork --- --- --- resuba +120 fchdir --- --- --- readv +121 readv --- --- --- writev +122 writev --- --- --- settimeofday +123 xstat --- --- --- fchown +124 lxstat --- --- --- fchmod +125 fxstat --- --- --- recvfrom +126 xmknod --- --- --- setreuid +127 clocal setregid +128 setrlimit --- --- lstat rename +129 getrlimit --- --- readlink truncate +130 lchown --- --- symlink ftruncate +131 memcntl --- --- --- flock +132 getpmsg --- --- --- mkfifo +133 putpmsg --- --- gethostname sendto +134 rename --- --- sethostname shutdown +135 uname --- --- getdomainname socketpair +136 setegid --- --- setdomainname mkdir +137 sysconfig --- --- --- rmdir +138 adjtime --- --- setreuid utimes +139 systeminfo --- --- setregid sigreturn +140 ??? adjtime +141 seteuid --- --- --- getpeername +142 --- --- --- --- gethostid +143 --- --- --- --- sethostid +144 --- --- --- --- getrlimit +145 --- --- --- --- setrlimit +146 --- --- --- --- killpg +147 --- --- --- --- setsid +148 --- --- --- --- quotactl +149 --- --- --- --- quota +150 --- --- --- --- getsockname +151 --- --- --- --- +152 --- --- --- --- +153 --- --- --- --- +154 --- --- --- --- +155 --- --- --- --- nfssvc +156 --- --- --- --- getdirentries +157 --- --- --- --- statfs +158 --- --- --- --- fstatfs +159 --- --- --- --- +160 --- --- --- --- async_daemon +161 --- --- --- --- getfh +162 --- --- --- --- getdomainname +163 --- --- --- --- setdomainname +164 --- --- --- --- uname +165 --- --- --- --- sysarch +166 --- --- --- --- +167 --- --- --- --- +168 --- --- --- --- +169 --- --- --- --- semsys +170 --- --- --- --- msgsys +171 --- --- --- --- shmsys +172 --- --- --- --- +173 --- --- --- --- +174 --- --- --- --- +175 --- --- --- --- ntp_gettime +176 --- --- --- --- ntp_adjtime +177 --- --- --- --- vm_allocate +178 --- --- --- --- vm_deallocate +179 --- --- --- --- vm_inherit +180 --- --- --- --- vm_protect +181 --- --- --- --- setgid +182 --- --- --- --- setegid +183 --- --- --- --- seteuid diff -uNr --exclude-from=dontdiff linux-2.4.3/Documentation/abi/TODO.ibcs linux/Documentation/abi/TODO.ibcs --- linux-2.4.3/Documentation/abi/TODO.ibcs Thu Jan 1 01:00:00 1970 +++ linux/Documentation/abi/TODO.ibcs Fri Mar 30 16:12:20 2001 @@ -0,0 +1,61 @@ + + These are leftovers from iBCS, I just removed what is already + done in linux-abi or isn't relevant for us. --hch + + +^Z disconnects but the next read seems to return an error instead +of blocking? (Fixed?) + +SIOGIFFLAGS seems to get passed an empty string as the interface name +(ISC ping). What is supposed to be happening? + +If a timod putmsg fails we should set an error status on the socket and +return it on future calls for strict compatibility. Currently we recover +from things such as protocol errors rather more than we should. + +Getmsg() - when select returns we may not be the first process to wake +up and handle the event. So the recvfrom ought to be non-blocking (not +possible?). If it would block we should go back to the select (unless +the descriptor is in non-blocking mode). (DONE?) + +How should we go about returning TLOOK? Currently we are only working +synchronously so it isn't essential yet. It looks like it's all handled +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. + +getmsg() returns EINTR if a signal interrupts it but the t_*() functions +don't seem to propogate this back to the application. Presumably they +loop round? + +The SCO timod doesn't seem to pay much attention to the TI_* command +in an ioctl but uses the T_* primitive in the message block. i.e. if +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 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 +is supposed to contain the address we connected to and that is only +available from the connection request message. Unless we save it +somewhere or look it up from the socket. Hang on, we have getpeername() +capabilities... + +There are slight semantic differences between O_NDELAY and O_NONBLOCK +which cause different behaviour on SCO at least. For instance O_NDELAY +does cause t_connect to work asynchronously but O_NONBLOCK doesn't. +Under Linux O_NDELAY and O_NONBLOCK are the same. This could cause +problems at some point I guess... + +Under SCO at least poll and select are different. Poll works on things +that select can be used on but select cannot necessarily work on things +that can be polled. Specifically you can poll a transport end point +but not select on it. Badly written programs could block when they +wouldn't normally. diff -uNr --exclude-from=dontdiff linux-2.4.3/Makefile linux/Makefile --- linux-2.4.3/Makefile Fri Mar 30 14:48:20 2001 +++ linux/Makefile Fri Mar 30 17:25:23 2001 @@ -118,10 +118,11 @@ CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o NETWORKS =net/network.o +ABI =abi/abi.o CRYPTO =crypto/crypto.o LIBS =$(TOPDIR)/lib/lib.a -SUBDIRS =kernel drivers mm fs net ipc lib crypto +SUBDIRS =kernel drivers mm fs net ipc lib crypto abi DRIVERS-n := DRIVERS-y := @@ -265,6 +265,7 @@ --start-group \ $(CORE_FILES) \ $(DRIVERS) \ + $(ABI) \ $(NETWORKS) \ $(CRYPTO) \ $(LIBS) \ diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/Config.in linux/abi/Config.in --- linux-2.4.3/abi/Config.in Thu Jan 1 01:00:00 1970 +++ linux/abi/Config.in Fri Mar 30 16:13:20 2001 @@ -0,0 +1,37 @@ + +mainmenu_option next_comment +comment 'Binary emulation of other systems' + +tristate 'Support for binary emulation of other systems' CONFIG_ABI + +# BSD is completly out of date ... +#dep_tristate ' BSD binary emulation support' CONFIG_ABI_BSD $CONFIG_ABI $CONFIG_ABI +dep_tristate ' SVR3/SVR4 (and derivates) binary emulation support' CONFIG_ABI_SVR4 $CONFIG_ABI +if [ "$CONFIG_ABI_SVR4" = "y" -o "$CONFIG_ABI_SVR4" = "m" ]; then + dep_mbool ' Include SCO OpenServer specifics' CONFIG_ABI_IBCS_SCO $CONFIG_ABI_SVR4 + dep_mbool ' Include ISC specifics' CONFIG_ABI_IBCS_ISC $CONFIG_ABI_SVR4 + dep_mbool ' Include Wyse V/386 specifics' CONFIG_ABI_IBCS_WYSE $CONFIG_ABI_SVR4 + dep_mbool ' Include Xenix specifics' CONFIG_ABI_XENIX $CONFIG_ABI_SVR4 + + dep_tristate ' UnixWare 7.x binary emulation support' CONFIG_ABI_UW7 $CONFIG_ABI_SVR4 + dep_tristate ' Solaris 2.x binary emulation support' CONFIG_ABI_SOLARIS $CONFIG_ABI_SVR4 +fi + +comment 'Support for foreign binary formats' +# coff is used by SVR3, x.out by Xenix, both are SVR4-subsets +dep_tristate ' Kernel support for x.out binaries' CONFIG_BINFMT_XOUT $CONFIG_ABI_SVR4 +dep_tristate ' Kernel support for COFF binaries' CONFIG_BINFMT_COFF $CONFIG_ABI_SVR4 + +comment 'Linux-ABI debugging settings' +dep_mbool ' Enable verbose errors' CONFIG_ABI_VERBOSE_ERRORS $CONFIG_ABI + + +if [ "$CONFIG_ABI" != "n" ]; then + define_bool CONFIG_ABI_SPX y + define_bool CONFIG_ABI_XTI y + + define_bool CONFIG_ABI_TLI_OPTMGMT y + define_bool CONFIG_ABI_XTI_OPTMGMT n +fi + +endmenu diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/Makefile linux/abi/Makefile --- linux-2.4.3/abi/Makefile Thu Jan 1 01:00:00 1970 +++ linux/abi/Makefile Tue Mar 13 18:49:41 2001 @@ -0,0 +1,21 @@ +# $Id$ +# +# Makefile for the kernel ABI code +# + +O_TARGET := abi.o + + +res-$(CONFIG_ABI) += common/abi-common.o +res-$(CONFIG_ABI_SVR4) += svr4/abi-svr4.o +res-$(CONFIG_ABI_UW7) += uw7/abi-uw7.o +res-$(CONFIG_ABI_SOLARIS) += solaris/abi-solaris.o + +subdir-$(CONFIG_ABI) += common +subdir-$(CONFIG_ABI_SVR4) += svr4 +subdir-$(CONFIG_ABI_UW7) += uw7 +subdir-$(CONFIG_ABI_SOLARIS) += solaris + +obj-y += $(res-y) + +include $(TOPDIR)/Rules.make diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/common/Makefile linux/abi/common/Makefile --- linux-2.4.3/abi/common/Makefile Thu Jan 1 01:00:00 1970 +++ linux/abi/common/Makefile Mon Mar 12 16:34:48 2001 @@ -0,0 +1,19 @@ +# +# Makefile for the kernel ABI code shared by different emulations +# + +O_TARGET := dummy.o + +list-multi := abi-common.o +abi-common-objs := core.o ioctl.o map.o signal.o socket.o socksys.o stat.o \ + wysev386.o $(ARCH)_dispatch.o $(ARCH)_maps.o + +export-objs := $(abi-common-objs) + +obj-$(CONFIG_ABI) += abi-common.o + + +include $(TOPDIR)/Rules.make + +abi-common.o: $(abi-common-objs) + $(LD) -r -o $@ $(abi-common-objs) diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/common/core.c linux/abi/common/core.c --- linux-2.4.3/abi/common/core.c Thu Jan 1 01:00:00 1970 +++ linux/abi/common/core.c Fri Mar 30 15:23:38 2001 @@ -0,0 +1,618 @@ +/* $Id$ + * core.c - generic emulation syscalls + * + * Copyright (C) 1993 Linus Torvalds + * + * Modified by Eric Youngdale to include all ibcs syscalls. + * Re-written by Drew Sullivan to handle lots more of the syscalls correctly. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +int abi_brk(unsigned long newbrk) +{ + if (!newbrk) + return current->mm->brk; + if (newbrk != current->mm->brk && (unsigned long)SYS(brk)(newbrk) != newbrk) + return -ENOMEM; + return 0; +} + +EXPORT_SYMBOL(abi_brk); + +#ifdef __sparc__ +int abi_fork(struct pt_regs * regs) { + /* No fork yet */ + printk ("ibcs2/sparc: No fork yet\n"); + send_sig(SIGSEGV, current, 1); + return -1; +} + +EXPORT_SYMBOL(abi_fork); + +int abi_wait(struct pt_regs * regs) { + /* No fork yet */ + printk ("ibcs2/sparc: No wait yet\n"); + send_sig(SIGSEGV, current, 1); + return -1; +} + +EXPORT_SYMBOL(abi_wait); + +int abi_exec(struct pt_regs * regs) +{ + + /* No exec yet */ + printk ("ibcs2/sparc: No fork yet\n"); + send_sig(SIGSEGV, current, 1); + return -1; +} + +EXPORT_SYMBOL(abi_exec); + +int abi_pipe(struct pt_regs * regs) +{ + long filedes[2]; + mm_segment_t old_fs = get_fs(); + int rvalue; + + set_fs(get_ds()); + rvalue = SYS(pipe)(&filedes); + set_fs(old_fs); + if (rvalue == 0) { + rvalue = filedes[0]; + regs->u_regs [UREG_I0] = filedes[1]; + } + return rvalue; +} + +EXPORT_SYMBOL(abi_pipe); + +int abi_getpid(struct pt_regs * regs) +{ + return current->pid; +} + +EXPORT_SYMBOL(abi_getpid); + +int abi_getuid(struct pt_regs * regs) +{ + return current->uid; +} + +EXPORT_SYMBOL(abi_getuid); + +int abi_getgid(struct pt_regs * regs) +{ + return current->gid; +} + +EXPORT_SYMBOL(abi_getgid); + +#else /* __sparc__ */ + +int abi_lseek(int fd, unsigned long offset, int whence) +{ + int error; + struct file *file; + struct inode *inode; + + error = SYS(lseek)(fd, offset, whence); + if (error != -ESPIPE || !personality(PER_SCOSVR3)) + return error; + + file = fget(fd); + if (!file) + goto out; + inode = file->f_dentry->d_inode; + if (inode && (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))) + error = 0; + fput(file); +out: + return error; +} + +EXPORT_SYMBOL(abi_lseek); + +int abi_fork(struct pt_regs * regs) +{ + int rvalue; + + regs->eflags &= ~1; /* Clear carry flag */ + rvalue = SYS(fork)(regs->ebx, regs->ecx, 1, + regs->esi, regs->edi, regs->ebp, regs->eax, regs->xds, + regs->xes, regs->orig_eax, + regs->eip, regs->xcs, regs->eflags, regs->esp, regs->xss); + regs->edx = 0; + return rvalue; +} + +EXPORT_SYMBOL(abi_fork); + +int abi_pipe(struct pt_regs * regs) +{ + long filedes[2]; + mm_segment_t old_fs = get_fs(); + int rvalue; + + set_fs(get_ds()); + rvalue = SYS(pipe)(&filedes); + set_fs(old_fs); + if (rvalue == 0) { + rvalue = filedes[0]; + regs->edx = filedes[1]; + } + return rvalue; +} + +EXPORT_SYMBOL(abi_pipe); + +/* note the double value return in eax and edx */ +int abi_getpid(struct pt_regs * regs) +{ + regs->edx = current->p_pptr->pid; + + return current->pid; +} + +EXPORT_SYMBOL(abi_getpid); + +/* note the double value return in eax and edx */ +int abi_getuid(struct pt_regs * regs) +{ + regs->edx = current->euid; + + return current->uid; +} + +EXPORT_SYMBOL(abi_getuid); + +/* note the double value return in eax and edx */ +int abi_getgid(struct pt_regs * regs) +{ + regs->edx = current->egid; + + return current->gid; +} + +EXPORT_SYMBOL(abi_getgid); + +#define FLAG_ZF 0x0040 +#define FLAG_PF 0x0004 +#define FLAG_SF 0x0080 +#define FLAG_OF 0x0800 + +#define MAGIC_WAITPID_FLAG (FLAG_ZF | FLAG_PF | FLAG_SF | FLAG_OF) + +int abi_wait(struct pt_regs * regs) +{ + long result, kopt; + int pid, loc, opt; + mm_segment_t old_fs; + + /* xenix wait() puts status to edx and returns pid */ + if (personality(PER_XENIX)) { + old_fs = get_fs(); + set_fs (get_ds()); + result = SYS(wait4)(-1, &loc, 0, NULL); + set_fs(old_fs); + + regs->edx = loc; + return result; + } + /* if ZF,PF,SF,and OF are set then it is waitpid */ + if ((regs->eflags & MAGIC_WAITPID_FLAG) == MAGIC_WAITPID_FLAG) { + get_user(pid, ((unsigned long *) regs->esp) + 1); + get_user(loc, ((unsigned long *) regs->esp) + 2); + get_user(opt, ((unsigned long *) regs->esp) + 3); + + /* Now translate the options from the SVr4 numbers */ + kopt = 0; + if (opt & 0100) kopt |= WNOHANG; + if (opt & 4) kopt |= WUNTRACED; + + result = SYS(wait4)(pid, loc, kopt, NULL); + } else { + get_user(loc, ((unsigned long *) regs->esp) + 1); + result = SYS(wait4)(-1, loc, WUNTRACED, NULL); + } + if (result >= 0 && loc) { + get_user(regs->edx, (unsigned long *) loc); + if ((regs->edx & 0xff) == 0x7f) { + int sig = (regs->edx >> 8) & 0xff; + if (sig < NSIGNALS) + sig = current->exec_domain->signal_map[sig]; + regs->edx = (regs->edx & (~0xff00)) | (sig << 8); + put_user(regs->edx, (unsigned long *)loc); + } else if (regs->edx && regs->edx == (regs->edx & 0xff)) { + if ((regs->edx & 0x7f) < NSIGNALS) + regs->edx = current->exec_domain->signal_map[regs->edx & 0x7f]; + put_user(regs->edx, (unsigned long *)loc); + } + } + return result; +} + +EXPORT_SYMBOL(abi_wait); + +/* + * abi_exec() executes a new program. + */ +int abi_exec(struct pt_regs *regs) +{ + int error; + char *pgm, **argv, **envp; + char *filename; + + get_user((unsigned long) pgm, ((unsigned long *) regs->esp) + 1); + get_user((unsigned long) argv, ((unsigned long *) regs->esp) + 2); + get_user((unsigned long) envp, ((unsigned long *) regs->esp) + 3); + + if (abi_traced(ABI_TRACE_API)) { + int i; + char **v, *p, *q; + + q = getname(pgm); + if (IS_ERR(q)) { + __abi_trace(" pgm: 0x%lx pointer error %ld\n", + (unsigned long)pgm, PTR_ERR(q)); + } else { + __abi_trace(" pgm: 0x%lx \"%s\"\n", + (unsigned long)pgm, q); + putname(q); + } + + for (i = 0, v = argv; v && i < 20; v++,i++) { + if (get_user(p, v) || !p) + break; + q = getname(p); + if (IS_ERR(q)) { + __abi_trace(" arg: 0x%lx pointer error %ld\n", + (unsigned long)p, PTR_ERR(q)); + } else { + __abi_trace(" arg: 0x%lx \"%s\"\n", + (unsigned long)p, q); + putname(q); + } + } + if (v && p) + __abi_trace(" arg: ...\n"); + + for (i=0,v=envp; v && i < 20; v++,i++) { + if (get_user(p, v) || !p) + break; + q = getname(p); + if (IS_ERR(q)) { + __abi_trace(" env: 0x%lx pointer error %ld\n", + (unsigned long)p, PTR_ERR(q)); + } else { + __abi_trace(" env: 0x%lx \"%s\"\n", + (unsigned long)p, q); + putname(q); + } + } + if (v && p) + __abi_trace(" env: ...\n"); + } + + filename = getname(pgm); + error = PTR_ERR(filename); + if (!IS_ERR(filename)) { + /* if you get an error on this undefined, then remove the */ + /* 'static' declaration in /linux/fs/exec.c */ + error = do_execve(filename, argv, envp, regs); + putname (filename); + } + return error; +} + +EXPORT_SYMBOL(abi_exec); + +int abi_procids(struct pt_regs * regs) +{ + int op, arg_offset; + + get_user(op, ((unsigned long *)regs->esp)+1); + + /* Remap op codes for current personality if necessary. */ + switch (current->personality & PER_MASK) { + case (PER_SVR3 & PER_MASK): + case (PER_SCOSVR3 & PER_MASK): + case (PER_WYSEV386 & PER_MASK): + case (PER_XENIX & PER_MASK): { + if (op < 0 || op > 5) + return -EINVAL; + op = "\000\001\005\003\377\377"[op]; + + /* SCO at least uses an interesting library to + * syscall mapping that leaves an extra return + * address between the op code and the arguments. + */ + arg_offset = 1; + break; + } + + default: + arg_offset = 0; + } + + switch (op) { + case 0: /* getpgrp */ + return current->pgrp; + + case 1: /* setpgrp */ + SYS(setpgid)(0, 0); + current->tty=NULL; + return current->pgrp; + + case 2: { /* getsid */ + unsigned long pid; + get_user(pid, ((unsigned long *)regs->esp) + + 2 + arg_offset); + return SYS(getsid)(pid); + } + + case 3: /* setsid */ + return SYS(setsid)(); + + case 4: { /* getpgid */ + unsigned long pid; + get_user(pid, ((unsigned long *)regs->esp) + + 2 + arg_offset); + return SYS(getpgid)(pid); + } + + case 5: { /* setpgid */ + int pid, pgid; + + get_user(pid, ((unsigned long *)regs->esp) + + 2 + arg_offset); + get_user(pgid, ((unsigned long *)regs->esp) + + 3 + arg_offset); + return SYS(setpgid)(pid, pgid); + } + } + + return -EINVAL; +} +EXPORT_SYMBOL(abi_procids); + +#endif /* __sparc__ */ + +int abi_read(int fd, char *buf, int nbytes) +{ + int error, here, posn, reclen; + struct file *file; + struct dirent *d; + mm_segment_t old_fs; + + error = SYS(read)(fd, buf, nbytes); + if (error != -EISDIR) + return error; + + /* + * Stupid bloody thing is trying to read a directory. Some old + * programs expect this to work. It works on SCO. To emulate it + * we have to map a dirent to a direct. This involves shrinking + * a long inode to a short. Fortunately nothing this archaic is + * likely to care about anything but the filenames of entries + * with non-zero inodes. + */ + + file = fget(fd); + if (!file) + return -EBADF; + + d = (struct dirent *)get_free_page(GFP_KERNEL); + if (!d) { + fput(file); + return -ENOMEM; + } + + error = posn = reclen = 0; + + while (posn + reclen < nbytes) { + /* Save the current position and get another dirent */ + here = file->f_pos; + old_fs = get_fs(); + set_fs (get_ds()); + error = SYS(readdir)(fd, d, 1); + set_fs(old_fs); + if (error <= 0) + break; + + /* If it'll fit in the buffer save it otherwise back up + * so it is read next time around. + * Oh, if we're at the beginning of the buffer there's + * no chance that this entry will ever fit so don't + * copy it and don't back off - we'll just pretend it + * isn't here... + */ + reclen = 16 * ((d->d_reclen + 13) / 14); + if (posn + reclen <= nbytes) { + /* SCO (at least) handles long filenames by breaking + * them up in to 14 character chunks of which all + * but the last have the inode set to 0xffff. + */ + char *p = d->d_name; + + /* Put all but the last chunk. */ + while (d->d_reclen > 14) { + put_user(0xffff, (unsigned short *)(buf+posn)); + posn += 2; + copy_to_user(buf+posn, p, 14); + posn += 14; + p += 14; + d->d_reclen -= 14; + } + /* Put the last chunk. Note the we have to fold a + * long inode number down to a short avoiding + * giving a zero inode number since that indicates + * an unused directory slot. Note also that the + * folding used here must match that used in stat() + * or path finding programs that do read() on + * directories will fail. + */ +#if 0 + /* This appears to match what SCO does for + * reads on a directory with long inodes. + */ + if ((unsigned long)d->d_ino > 0xfffe) + put_user(0xfffe, (unsigned short *)(buf+posn)); + else + put_user((short)d->d_ino, (unsigned short *)(buf+posn)); +#else + /* This attempts to match the way stat and + * getdents fold long inodes to shorts. + */ + if ((unsigned long)d->d_ino & 0xffff) + put_user((unsigned long)d->d_ino & 0xffff, + (unsigned short *)(buf+posn)); + else + put_user(0xfffe, (unsigned short *)(buf+posn)); +#endif + posn += 2; + copy_to_user(buf+posn, p, d->d_reclen); + + /* Ensure that filenames that don't fill the array + * completely are null filled. + */ + for (; d->d_reclen < 14; d->d_reclen++) + put_user('\0', buf+posn+d->d_reclen); + + posn += 14; + } else if (posn) { + SYS(lseek)(fd, here, 0); + } /* else posn == 0 */ + } + + free_page((unsigned long)d); + fput(file); + + /* If we've put something in the buffer return the byte count + * otherwise return the error status. + */ + return (posn ? posn : error); +} + +EXPORT_SYMBOL(abi_read); + +#ifdef __TRACE_SELECT__ +int abi_select(int n, void *rfds, void *wfds, void *efds, struct timeval *t) +{ + struct timeval tv; + int error; + + if (!abi_traced(ABI_TRACE_API) || !t) + goto doit; + + error = get_user(tv.tv_sec, &(t->tv_sec)); + if (!error) + error = get_user(tv.tv_usec, &(t->tv_usec)); + if (error) + return (error); + + __abi_trace("select timeout in %lus, %luus", tv.tv_sec, tv.tv_usec); + +doit: + return SYS(_newselect)(n, rfds, wfds, efds, t); +} +EXPORT_SYMBOL(abi_select); +#endif + + +int +abi_time(void) +{ + return SYS(time)(0); +} + +EXPORT_SYMBOL(abi_time); + + +int abi_mknod(const char *fname, int mode, int dev) +{ + /* Linux doesn't allow us to create a directory with mknod(). */ + if ((mode & 0017000) == 0040000) + return abi_mkdir(fname, mode); + return SYS(mknod)(fname, mode, dev); +} + +EXPORT_SYMBOL(abi_mknod); + +int abi_mkdir(const char *fname, int mode) +{ + int error; + mm_segment_t old_fs; + char *tmp, *p; + + tmp = getname(fname); + if (IS_ERR(tmp)) + return PTR_ERR(tmp); + + /* Drop any trailing slash */ + for (p=tmp; *p; p++); + p--; + if (*p == '/') + *p = '\0'; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(mkdir)(tmp, mode); + set_fs(old_fs); + + putname(tmp); + return error; +} + +EXPORT_SYMBOL(abi_mkdir); + +/* + * Translate the signal number to the corresponding item for Linux. + */ +static inline int abi_mapsig(int sig) +{ + if ((unsigned int) sig >= NSIGNALS) + return -1; + return current->exec_domain->signal_map[sig]; +} + +int abi_kill(int pid, int sig) +{ + int outsig = abi_mapsig(sig & 0xFF); + + abi_trace(ABI_TRACE_SIGNAL, "kill: insig (%d) outsig(%d)", + sig & 0xFF, outsig); + + if (outsig < 0) + return -EINVAL; + return SYS(kill)(pid, outsig); +} + +EXPORT_SYMBOL(abi_kill); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/common/i386_dispatch.c linux/abi/common/i386_dispatch.c --- linux-2.4.3/abi/common/i386_dispatch.c Thu Jan 1 01:00:00 1970 +++ linux/abi/common/i386_dispatch.c Fri Mar 30 15:23:38 2001 @@ -0,0 +1,304 @@ +/* + * arch/i386/abi/dispatch_i386.c + * + * Copyright (C) 1993 Linus Torvalds + * Modified by Eric Youngdale to include all ibcs syscalls. + * Re-written by Drew Sullivan to handle lots more of the syscalls correctly. + * + * Jan 30 1994, Merged Joe Portman's code -- Drew + * Jan 31 1994, Merged Eric Yongdale's code for elf support -- Drew + * + * Feb 4 1994 + * Rebuilt with handling for multiple binary personalities + * -- Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * Feb 14 1994 + * Dual mode. Compiled in if you say yes to the configure iBCS + * question during 'make config'. Loadable module with kernel + * hooks otherwise. + * -- Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * Feb 18 1994 + * Added the /dev/socksys emulator. This allows applications which + * use the socket interface to Lachman streams based TCP/IP to use + * the Linux TCP/IP stack. + * -- Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * $Id$ + * $Source$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +#include "verb_errmap.inc" + +#define last(x) ((sizeof(x)/sizeof(*x))-1) + + +MODULE_AUTHOR("Mike Jagdis "); +MODULE_DESCRIPTION("Support for non-Linux programs"); + + +u_int abi_traceflg = 0xffffffff; + +MODULE_PARM(abi_traceflg, "i"); +MODULE_PARM_DESC(abi_traceflg, "iBCS debug trace"); + + +static void fail(long eax, ABI_func * p); +static void plist(char * name, char * args, int * list); + +ABI_func * abi_current; + +static const char * const sig_names[] = { + "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", + "SIGTRAP", "SIGABRT/SIGIOT","SIGUNUSED", "SIGFPE", + "SIGKILL", "SIGUSR1", "SIGSEGV", "SIGUSR2", + "SIGPIPE", "SIGALRM", "SIGTERM", "SIGSTKFLT", + "SIGCHLD", "SIGCONT", "SIGSTOP", "SIGTSTP", + "SIGTTIN", "SIGTTOU", "SIGIO/SIGPOLL/SIGURG", + "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", + "SIGWINCH", "SIGLOST", "SIGPWR", "SIG 31", + "SIG 32" +}; + + +void +abi_dispatch(struct pt_regs * regs, ABI_func * p, int of) +{ + int i; + int args[8]; + int rvalue; + void *kfunc; + short nargs; + + abi_current = p; + + kfunc = p->kfunc; + nargs = p->nargs; + + /* If the number of arguments is negative this is an unfudged + * system call function and we need to look up the real function + * address in the kernel's sys_call_table. + * Note that we never modify the callmap itself but do the lookup + * for each call. This allows modules that provide syscalls to + * be loaded and unloaded without any messy locking. + */ + if (nargs < 0) { + kfunc = sys_call_table[(int)kfunc]; + + /* Watch for a magic zero. This exists because we + * can't use -0 to represent a system call that + * takes no arguments. + */ + if (nargs == -ZERO) + nargs = 0; + else + nargs = -nargs; + } + + if (nargs <= (short)(sizeof(args)/sizeof(args[0]))) + for(i=0; i < nargs; i++) + get_user(args[i], ((unsigned long *)regs->esp)+(i+of)); + + if (abi_traced(ABI_TRACE_API)) { + if (nargs == Spl) { + for(i = 0; i < (int)strlen(p->args); i++) + get_user(args[i], ((u_long *)regs->esp) + (i + of)); + } + plist(p->name, p->args, args); + } + + rvalue = -ENOSYS; + if (kfunc) { + switch(nargs) { + case Fast: + ((sysfun_p)kfunc)(regs); + if (abi_traced(ABI_TRACE_API|ABI_TRACE_SIGNAL) && + signal_pending(current)) { + u_long signr; + + signr = current->pending.signal.sig[0] & + ~current->blocked.sig[0]; + + __asm__("bsf %1,%0\n\t" + :"=r" (signr) + :"0" (signr)); + + __abi_trace("SIGNAL %lu <%s>\n", + signr + 1, sig_names[signr]); + } + return; + case Spl: + rvalue = ((sysfun_p)kfunc)(regs); + break; + case 0: + rvalue = ((sysfun_p)kfunc)(); + break; + case 1: + rvalue = ((sysfun_p)kfunc)(args[0]); + break; + case 2: + rvalue = ((sysfun_p)kfunc)(args[0], args[1]); + break; + case 3: + rvalue = ((sysfun_p)kfunc)(args[0], args[1], args[2]); + break; + case 4: + rvalue = ((sysfun_p)kfunc)(args[0], args[1], args[2], args[3]); + break; + case 5: + rvalue = ((sysfun_p)kfunc)(args[0], args[1], args[2], + args[3], args[4]); + break; + case 6: + rvalue = ((sysfun_p)kfunc)(args[0], args[1], args[2], + args[3], args[4], args[5]); + break; + case 7: + rvalue = ((sysfun_p)kfunc)(args[0], args[1], args[2], + args[3], args[4], args[5], + args[6]); + break; + default: + fail(regs->eax, p); + } + } else + fail(regs->eax, p); + + if (rvalue >= 0 || rvalue < -ENOIOCTLCMD) { + regs->eflags &= ~1; /* Clear carry flag */ + regs->eax = rvalue; + + abi_trace(ABI_TRACE_API, "%s returns %ld {%ld}\n", + p->name, regs->eax, regs->edx); + } else { + regs->eflags |= 1; /* Set carry flag */ + regs->eax = iABI_errors(-rvalue); + + if (abi_traced(ABI_TRACE_API)) { +#ifdef CONFIG_ABI_VERBOSE_ERRORS + __abi_trace("%s error return linux=%d -> ibcs=%ld <%s>\n", + p->name, rvalue, regs->eax, + -rvalue < (int)(sizeof(errmsg)/sizeof(errmsg[0])) + ? errmsg[-rvalue] + : "unknown"); +#else + __abi_trace("%s error return linux=%d -> ibcs=%ld\n", + p->name, rvalue, regs->eax); +#endif + } + } + + if (abi_traced(ABI_TRACE_API|ABI_TRACE_SIGNAL) && + signal_pending(current)) { + u_long signr; + + signr = current->pending.signal.sig[0] & + ~current->blocked.sig[0]; + + __asm__("bsf %1,%0\n\t" + :"=r" (signr) + :"0" (signr)); + + __abi_trace("SIGNAL %lu <%s>, queued 0x%08lx\n", + signr + 1, sig_names[signr], + current->pending.signal.sig[0]); + } +} +EXPORT_SYMBOL(abi_dispatch); + +int +abi_syscall(struct pt_regs *regs) +{ + get_user(regs->eax, ((unsigned long *) regs->esp) + 1); + + ++regs->esp; + current->exec_domain->handler(-1,regs); + --regs->esp; + + return 0; +} +EXPORT_SYMBOL(abi_syscall); + +/* + * plist is used by the trace code to show the arg list + */ +static void +plist(char * name, char * args, int * list) +{ + int error; + char *tmp, *p, arg_buf[512]; + + arg_buf[0] = '\0'; + p = arg_buf; + while (*args) { + switch(*args++) { + case 'd': + sprintf(p, "%d", *list++); + break; + case 'o': + sprintf(p, "0%o", *list++); + break; + case 'p': + sprintf(p, "0x%p", (void *)(*list++)); + break; + case '?': + case 'x': + sprintf(p, "0x%x", *list++); + break; + case 's': + tmp = getname((char *)(*list++)); + error = PTR_ERR(tmp); + if (!IS_ERR(tmp)) { + /* we are debugging, we don't need to see it all */ + tmp[80] = '\0'; + sprintf(p, "\"%s\"", tmp); + putname(tmp); + } + break; + default: + sprintf(p, "?%c%c?", '%', args[-1]); + break; + } + while (*p) + ++p; + if (*args) { + *p++ = ','; + *p++ = ' '; + *p = '\0'; + } + } + __abi_trace("%s(%s)\n", name, arg_buf); +} + +static void +fail(long eax, ABI_func * p) +{ + if (!abi_traced(ABI_TRACE_API)) + return; + + printk(KERN_ERR "[%s:%d] Unsupported ABI function 0x%lx (%s)\n", + current->comm, current->pid, eax, p->name); +} + +EXPORT_SYMBOL(abi_traceflg); +EXPORT_SYMBOL(abi_current); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/common/i386_maps.c linux/abi/common/i386_maps.c --- linux-2.4.3/abi/common/i386_maps.c Thu Jan 1 01:00:00 1970 +++ linux/abi/common/i386_maps.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#define __NO_VERSION__ + #include + +struct map_segment abi_sockopt_map[] = { + { 0x0001, 0x0001, (char *)SO_DEBUG }, + { 0x0002, 0x0002, (char *)__SO_ACCEPTCON }, + { 0x0004, 0x0004, (char *)SO_REUSEADDR }, + { 0x0008, 0x0008, (char *)SO_KEEPALIVE }, + { 0x0010, 0x0010, (char *)SO_DONTROUTE }, + { 0x0020, 0x0020, (char *)SO_BROADCAST }, + { 0x0040, 0x0040, (char *)SO_USELOOPBACK }, + { 0x0080, 0x0080, (char *)SO_LINGER }, + { 0x0100, 0x0100, (char *)SO_OOBINLINE }, + { 0x0200, 0x0200, (char *)SO_ORDREL }, + { 0x0400, 0x0400, (char *)SO_IMASOCKET }, + { 0x1001, 0x1001, (char *)SO_SNDBUF }, + { 0x1002, 0x1002, (char *)SO_RCVBUF }, + { 0x1003, 0x1003, (char *)SO_SNDLOWAT }, + { 0x1004, 0x1004, (char *)SO_RCVLOWAT }, + { 0x1005, 0x1005, (char *)SO_SNDTIMEO }, + { 0x1006, 0x1006, (char *)SO_RCVTIMEO }, + { 0x1007, 0x1007, (char *)SO_ERROR }, + { 0x1008, 0x1008, (char *)SO_TYPE }, + { 0x1009, 0x1009, (char *)SO_PROTOTYPE }, + { -1 } +}; + + +struct map_segment abi_af_map[] = { + /* The first three entries (AF_UNSPEC, AF_UNIX and AF_INET) + * are identity mapped. All others aren't available under + * Linux, nor are Linux's AF_AX25 and AF_IPX available from + * SCO as far as I know. + */ + { 0, 2, NULL }, + { -1 } +}; + +EXPORT_SYMBOL(abi_af_map); +EXPORT_SYMBOL(abi_sockopt_map); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/common/ioctl.c linux/abi/common/ioctl.c --- linux-2.4.3/abi/common/ioctl.c Thu Jan 1 01:00:00 1970 +++ linux/abi/common/ioctl.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,685 @@ +/* $Id$ + * + * ioctl.c - generic emultions ioctls + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * Written by Drew Sullivan. + * Rewritten by Mike Jagdis. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + + +int abi_ioctl_socksys(int fd, unsigned int func, void *arg); + + +static inline char *fix(int n) +{ + static char char_class[4]; + + char_class[0] = n & 0xFF0000 ? (char)((n >> 16) & 0xFF) : '.'; + char_class[1] = n & 0x00FF00 ? (char)((n >> 8) & 0xFF) : '.'; + char_class[2] = n & 0x0000FF ? (char)((n ) & 0xFF) : '.'; + char_class[3] = 0; + + return char_class; +} + +#define BSD_NCCS 20 +struct bsd_termios { + unsigned long c_iflag; + unsigned long c_oflag; + unsigned long c_cflag; + unsigned long c_lflag; + unsigned char c_cc[BSD_NCCS]; + long c_ispeed; + long c_ospeed; +}; +static unsigned long speed_map[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 +}; + +static unsigned long +bsd_to_linux_speed(unsigned long s) +{ + unsigned int i; + +#ifdef B57600 + if (s == 57600) + return B57600; +#endif +#ifdef B115200 + if (s == 115200) + return B115200; +#endif + + for (i=0; ic_iflag); + t.c_iflag = (t.c_iflag & ~0xc00) + | ((t.c_iflag & 0x400) << 1) + | ((t.c_iflag & 0x800) >> 1); + + get_user(temp, &it->c_oflag); + t.c_oflag = (t.c_oflag & ~0x1805) + | (temp & 9) + | ((temp & 2) << 1) + | ((temp & 4) << 10) + | ((temp & 4) << 9); + + get_user(temp, &it->c_cflag); + t.c_cflag = (t.c_cflag & ~0xfff) + | ((temp & 0xff00) >> 4); + if (t.c_cflag & 0x30000) + t.c_cflag |= 020000000000; + t.c_cflag |= bsd_to_linux_speed(({long s; get_user(s, &it->c_ospeed); s;})) + | (bsd_to_linux_speed(({long s; get_user(s, &it->c_ispeed); s;})) << 16); + + get_user(temp, &it->c_lflag); + t.c_lflag = (t.c_lflag & ~0157663) + | ((temp & 1) << 12) + | ((temp & 0x46) << 3) + | ((temp & 0x420) << 5) + | ((temp & 0x180) >> 7) + | ((temp & 0x400000) >> 14) + | ((temp & 0x2800000) >> 11) + | ((temp & 0x80000000) >> 24); + + copy_from_user(bsd_cc, &it->c_cc, BSD_NCCS); + t.c_cc[VEOF] = bsd_cc[0]; + t.c_cc[VEOL] = bsd_cc[1]; + t.c_cc[VEOL2] = bsd_cc[2]; + t.c_cc[VERASE] = bsd_cc[3]; + t.c_cc[VWERASE] = bsd_cc[4]; + t.c_cc[VKILL] = bsd_cc[5]; + t.c_cc[VREPRINT] = bsd_cc[6]; + t.c_cc[VSWTC] = bsd_cc[7]; + t.c_cc[VINTR] = bsd_cc[8]; + t.c_cc[VQUIT] = bsd_cc[9]; + t.c_cc[VSUSP] = bsd_cc[10]; +/* t.c_cc[VDSUSP] = bsd_cc[11];*/ + t.c_cc[VSTART] = bsd_cc[12]; + t.c_cc[VSTOP] = bsd_cc[13]; + t.c_cc[VLNEXT] = bsd_cc[14]; + t.c_cc[VDISCARD] = bsd_cc[15]; + t.c_cc[VMIN] = bsd_cc[16]; + t.c_cc[VTIME] = bsd_cc[17]; +/* t.c_cc[VSTATUS] = bsd_cc[18];*/ + + set_fs(get_ds()); + error = SYS(ioctl)(fd, op, &t); + set_fs(old_fs); + + return error; +} + + +static int +linux_to_bsd_termios(int fd, int op, struct bsd_termios *it) +{ + struct termios t; + char bsd_cc[BSD_NCCS]; + mm_segment_t old_fs; + int error; + + error = verify_area(VERIFY_WRITE, it, sizeof(struct bsd_termios)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, op, &t); + set_fs(old_fs); + if (error) + return error; + + put_user((t.c_iflag & 0777) + | ((t.c_iflag & 02000) >> 1) + | ((t.c_iflag & 010000) >> 2) + | ((t.c_iflag & 020000) >> 4), + &it->c_iflag); + + put_user((t.c_oflag & 1) + | ((t.c_oflag & 04) >> 1) + | ((t.c_oflag & 014000) == 014000 ? 4 : 0), + &it->c_oflag); + + put_user((t.c_cflag & ~020000007777) + | ((t.c_cflag & 0xff0) << 4) + | ((t.c_cflag & 020000000000) ? 0x30000 : 0), + &it->c_cflag); + + put_user(linux_to_bsd_speed(t.c_cflag & CBAUD), &it->c_ospeed); + if ((t.c_cflag & CIBAUD) != 0) + put_user(linux_to_bsd_speed((t.c_cflag & CIBAUD) >> 16), + &it->c_ispeed); + else + put_user(linux_to_bsd_speed(t.c_cflag & CBAUD), + &it->c_ispeed); + + put_user((t.c_lflag & 07777626010) + | ((t.c_lflag & 03) << 7) + | ((t.c_lflag & 01160) >> 3) + | ((t.c_lflag & 0400) << 14) + | ((t.c_lflag & 02000) >> 4) + | ((t.c_lflag & 04000) >> 11) + | ((t.c_lflag & 010000) << 11) + | ((t.c_lflag & 040000) << 15) + | ((t.c_lflag & 0100000) >> 5), + &it->c_lflag); + + bsd_cc[0] = t.c_cc[VEOF]; + bsd_cc[1] = t.c_cc[VEOL]; + bsd_cc[2] = t.c_cc[VEOL2]; + bsd_cc[3] = t.c_cc[VERASE]; + bsd_cc[4] = t.c_cc[VWERASE]; + bsd_cc[5] = t.c_cc[VKILL]; + bsd_cc[6] = t.c_cc[VREPRINT]; + bsd_cc[7] = t.c_cc[VSWTC]; + bsd_cc[8] = t.c_cc[VINTR]; + bsd_cc[9] = t.c_cc[VQUIT]; + bsd_cc[10] = t.c_cc[VSUSP]; + bsd_cc[11] = t.c_cc[VSUSP]; + bsd_cc[12] = t.c_cc[VSTART]; + bsd_cc[13] = t.c_cc[VSTOP]; + bsd_cc[14] = t.c_cc[VLNEXT]; + bsd_cc[15] = t.c_cc[VDISCARD]; + bsd_cc[16] = t.c_cc[VMIN]; + bsd_cc[17] = t.c_cc[VTIME]; + bsd_cc[18] = 0; /* t.c_cc[VSTATUS]; */ + bsd_cc[19] = 0; + + copy_to_user(&it->c_cc, bsd_cc, BSD_NCCS); + + return error; +} + + + + +struct v7_sgttyb { + unsigned char sg_ispeed; + unsigned char sg_ospeed; + unsigned char sg_erase; + unsigned char sg_kill; + int sg_flags; +}; + +struct v7_tchars { + char t_intrc; + char t_quitc; + char t_startc; + char t_stopc; + char t_eofc; + char t_brkc; +}; + +struct v7_ltchars { + char t_suspc; + char t_dsuspc; + char t_rprntc; + char t_flushc; + char t_werasc; + char t_lnextc; +}; + + +int bsd_ioctl_termios(int fd, unsigned int func, void *arg) +{ + switch (func & 0xff) { + case 0: { /* TIOCGETD */ + unsigned long ldisc; + mm_segment_t old_fs; + int error; + + error = verify_area(VERIFY_WRITE, arg, + sizeof(unsigned short)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TIOCGETD, &ldisc); + set_fs(old_fs); + if (!error) + put_user(ldisc, (unsigned short *)arg); + return error; + } + case 1: { /* TIOCSETD */ + unsigned long ldisc; + mm_segment_t old_fs; + int error; + + error = verify_area(VERIFY_READ, arg, + sizeof(unsigned short)); + if (error) + return error; + + get_user(ldisc, (unsigned short *)arg); + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TIOCSETD, &ldisc); + set_fs(old_fs); + return error; + } + + case 2: { /* TIOCHPCL */ + int error; + mm_segment_t old_fs; + struct termios t; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETS, &t); + set_fs(old_fs); + if (error) + return error; + + if (arg) + t.c_cflag |= HUPCL; + else + t.c_cflag &= ~HUPCL; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCSETS, &t); + set_fs(old_fs); + return error; + } + + case 8: { /* TIOCGETP */ + int error; + mm_segment_t old_fs; + struct termios t; + struct v7_sgttyb sg; + + error = verify_area(VERIFY_WRITE, arg, sizeof(sg)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETS, &t); + set_fs(old_fs); + if (error) + return error; + + sg.sg_ispeed = sg.sg_ospeed = 0; + sg.sg_erase = t.c_cc[VERASE]; + sg.sg_kill = t.c_cc[VKILL]; + sg.sg_flags = + /* Old - became TANDEM instead. + * ((t.c_cflag & HUPCL) >> 10) + * | + */ +/* O_ODDP */ ((t.c_cflag & PARODD) >> 3) +/* O_EVENP */ | ((t.c_cflag & PARENB) >> 1) +/* LITOUT */ | ((t.c_cflag & OPOST) ? 0 : 0x200000) +/* O_CRMOD */ | ((t.c_oflag & ONLCR) << 2) +/* O_NL1|O_VTDELAY */ | (t.c_oflag & (NL1|VTDLY)) +/* O_TBDELAY */ | ((t.c_oflag & TABDLY) ? 02000 : 0) +/* O_CRDELAY */ | ((t.c_oflag & CRDLY) << 3) +/* O_BSDELAY */ | ((t.c_oflag & BSDLY) << 2) +/* O_ECHO|O_LCASE */ | (t.c_lflag & (XCASE|ECHO)) + | ((t.c_lflag & ICANON) +/* O_CBREAK or O_RAW */ ? 0 : ((t.c_lflag & ISIG) ? 0x02 : 0x20)) + /* Incomplete... */ + ; + + copy_to_user(arg, &sg, sizeof(sg)); + return 0; + } + + case 9: /* TIOCSETP */ + case 10: { /* TIOCSETN */ + int error; + mm_segment_t old_fs; + struct termios t; + struct v7_sgttyb sg; + + error = verify_area(VERIFY_READ, arg, sizeof(sg)); + if (error) + return error; + copy_from_user(&sg, arg, sizeof(sg)); + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETS, &t); + set_fs(old_fs); + if (error) + return error; + + t.c_cc[VERASE] = sg.sg_erase; + t.c_cc[VKILL] = sg.sg_kill; + t.c_iflag = ICRNL | IXON; + t.c_oflag = 0; + t.c_lflag = ISIG | ICANON; + if (sg.sg_flags & 0x02) /* O_CBREAK */ + t.c_lflag &= (~ICANON); + if (sg.sg_flags & 0x08) /* O_ECHO */ + t.c_lflag |= ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN; + if (sg.sg_flags & 0x10) /* O_CRMOD */ + t.c_oflag |= OPOST|ONLCR; + if (sg.sg_flags & 0x20) { /* O_RAW */ + t.c_iflag = 0; + t.c_lflag &= ~(ISIG|ICANON); + } + if (sg.sg_flags & 0x200000) /* LITOUT */ + t.c_oflag &= (~OPOST); + if (!(t.c_lflag & ICANON)) { + t.c_cc[VMIN] = 1; + t.c_cc[VTIME] = 0; + } + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCSETS, &t); + set_fs(old_fs); + return error; + } + + case 17: { /* TIOCSETC */ + int error; + mm_segment_t old_fs; + struct termios t; + struct v7_tchars tc; + + error = verify_area(VERIFY_READ, arg, sizeof(tc)); + if (error) + return error; + copy_from_user(&tc, arg, sizeof(tc)); + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETS, &t); + set_fs(old_fs); + if (error) + return error; + + t.c_cc[VINTR] = tc.t_intrc; + t.c_cc[VQUIT] = tc.t_quitc; + t.c_cc[VSTART] = tc.t_startc; + t.c_cc[VSTOP] = tc.t_stopc; + t.c_cc[VEOF] = tc.t_eofc; + t.c_cc[VEOL2] = tc.t_brkc; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCSETS, &t); + set_fs(old_fs); + return error; + } + + case 18: { /* TIOCGETC */ + int error; + mm_segment_t old_fs; + struct termios t; + struct v7_tchars tc; + + error = verify_area(VERIFY_WRITE, arg, sizeof(tc)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETS, &t); + set_fs(old_fs); + if (error) + return error; + + tc.t_intrc = t.c_cc[VINTR]; + tc.t_quitc = t.c_cc[VQUIT]; + tc.t_startc = t.c_cc[VSTART]; + tc.t_stopc = t.c_cc[VSTOP]; + tc.t_eofc = t.c_cc[VEOF]; + tc.t_brkc = t.c_cc[VEOL2]; + + copy_to_user(arg, &tc, sizeof(tc)); + return 0; + } + + case 116: { /* TIOCGLTC */ + int error; + mm_segment_t old_fs; + struct termios t; + struct v7_ltchars tc; + + error = verify_area(VERIFY_WRITE, arg, sizeof(tc)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETS, &t); + set_fs(old_fs); + if (error) + return error; + + tc.t_suspc = t.c_cc[VSUSP]; + tc.t_dsuspc = t.c_cc[VSUSP]; + tc.t_rprntc = t.c_cc[VREPRINT]; + tc.t_flushc = t.c_cc[VEOL2]; + tc.t_werasc = t.c_cc[VWERASE]; + tc.t_lnextc = t.c_cc[VLNEXT]; + + copy_to_user(arg, &tc, sizeof(tc)); + return 0; + } + + case 117: { /* TIOCSLTC */ + int error; + mm_segment_t old_fs; + struct termios t; + struct v7_ltchars tc; + + error = verify_area(VERIFY_READ, arg, sizeof(tc)); + if (error) + return error; + copy_from_user(&tc, arg, sizeof(tc)); + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETS, &t); + set_fs(old_fs); + if (error) + return error; + + t.c_cc[VSUSP] = tc.t_suspc; + t.c_cc[VEOL2] = tc.t_dsuspc; + t.c_cc[VREPRINT] = tc.t_rprntc; + t.c_cc[VEOL2] = tc.t_flushc; + t.c_cc[VWERASE] = tc.t_werasc; + t.c_cc[VLNEXT] = tc.t_lnextc; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCSETS, &t); + set_fs(old_fs); + return error; + } + + case 13: /* TIOEXCL */ + return SYS(ioctl)(fd, TIOCEXCL, arg); + + case 14: /* TIOCNXCL */ + return SYS(ioctl)(fd, TIOCNXCL, arg); + + case 16: /* TIOCFLUSH */ + return SYS(ioctl)(fd, TCFLSH, arg); + + /* ISC (maybe SVR4 in general?) has some extensions over + * the sgtty stuff. So do later BSDs. Needless to say they + * both have different extensions. + */ + case 20: /* TCSETPGRP (TIOC|20) set pgrp of tty */ + return bsd_to_linux_termios(fd, TCSETS, arg); + + case 21: /* TCGETPGRP (TIOC|21) get pgrp of tty */ + return bsd_to_linux_termios(fd, TCSETSW, arg); + + case 19: /* TIOCGETA */ + return linux_to_bsd_termios(fd, TCGETS, arg); + + case 22: /* TIOCSETAF */ + return bsd_to_linux_termios(fd, TCSETSF, arg); + + case 26: /* TIOCGETD */ + return SYS(ioctl)(fd, TIOCGETD, arg); + + case 27: /* TIOCSETD */ + return SYS(ioctl)(fd, TIOCSETD, arg); + + case 97: /* TIOCSCTTY */ + return SYS(ioctl)(fd, TIOCSCTTY, arg); + + case 103: /* TIOCSWINSZ */ + return SYS(ioctl)(fd, TIOCSWINSZ, arg); + + case 104: /* TIOCGWINSZ */ + return SYS(ioctl)(fd, TIOCGWINSZ, arg); + + case 113: /* TIOCNOTTY */ + return SYS(ioctl)(fd, TIOCNOTTY, arg); + + case 118: /* TIOCSPGRP */ + return SYS(ioctl)(fd, TIOCSPGRP, arg); + + case 119: /* TIOCGPGRP */ + return SYS(ioctl)(fd, TIOCGPGRP, arg); + + case 123: /* TIOCSBRK */ + return SYS(ioctl)(fd, TCSBRK, arg); + + case 124: /* TIOCLGET */ + case 125: /* TIOCLSET */ + return 0; + + + case 3: /* TIOCMODG */ + case 4: /* TIOCMODS */ + case 94: /* TIOCDRAIN */ + case 95: /* TIOCSIG */ + case 96: /* TIOCEXT */ + case 98: /* TIOCCONS */ + case 102: /* TIOCUCNTL */ + case 105: /* TIOCREMOTE */ + case 106: /* TIOCMGET */ + case 107: /* TIOCMBIC */ + case 108: /* TIOCMBIS */ + case 109: /* TIOCMSET */ + case 110: /* TIOCSTART */ + case 111: /* TIOCSTOP */ + case 112: /* TIOCPKT */ + case 114: /* TIOCSTI */ + case 115: /* TIOCOUTQ */ + case 120: /* TIOCCDTR */ + case 121: /* TIOCSDTR */ + case 122: /* TIOCCBRK */ + + } + + printk(KERN_ERR "BSD/V7: terminal ioctl 0x%08lx unsupported\n", + (unsigned long)func); + return -EINVAL; +} + + +EXPORT_SYMBOL(bsd_ioctl_termios); + + +int abi_ioctl_console(int fd, unsigned int func, void *arg) { + switch(func) { + case 0x6301: /* CONS_CURRENT: Get display adapter type */ + case 0x6302: /* CONS_GET: Get display mode setting */ + /* Always error so the application never tries + * anything overly fancy on the console. + */ + return -EINVAL; + case 0x4304: /* _TTYDEVTYPE */ + /* If on console then 1, if pseudo tty then 2 */ + return 2; + } + printk(KERN_ERR "iBCS: console ioctl %d unsupported\n", func); + return -EINVAL; +} + +EXPORT_SYMBOL(abi_ioctl_console); + +int abi_ioctl_video(int fd, unsigned int func, void *arg) { + switch(func) { + case 1: /* MAP_CLASS */ + /* Get video memory map & IO privilege */ + /* This doesn't agree with my SCO 3.2.4 ???? */ + case 4: /* C_IOC */ + /* see /etc/conf/pack.d/cn/class.h on any SCO unix box :-) */ + } + printk(KERN_ERR "iBCS: video ioctl %d unsupported\n", func); + return -EINVAL; +} + +EXPORT_SYMBOL(abi_ioctl_video); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/common/map.c linux/abi/common/map.c --- linux-2.4.3/abi/common/map.c Thu Jan 1 01:00:00 1970 +++ linux/abi/common/map.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,100 @@ +/* $Id$ + * + * map.c - generic mapping routines for binary emulation + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +long +map_bitvec(unsigned long vec, long map[]) +{ + unsigned long newvec, m; + int i; + + newvec = 0; + for (m=1,i=1; i<=32; m<<=1,i++) + if ((vec & m) && map[i] != -1) + newvec |= (1 << map[i]); + + return newvec; +} + +EXPORT_SYMBOL(map_bitvec); + +unsigned long +map_sigvec_from_kernel(sigset_t vec, unsigned long map[]) +{ + unsigned long newvec; + int i; + + newvec = 0; + for (i=1; i<=32; i++) { + if (sigismember(&vec, i) && map[i] != -1) + newvec |= (1 << map[i]); + } + return newvec; +} + +EXPORT_SYMBOL(map_sigvec_from_kernel); + +sigset_t +map_sigvec_to_kernel(unsigned long vec, unsigned long map[]) +{ + sigset_t newvec; + unsigned long m; + int i; + + sigemptyset(&newvec); + for (m=1,i=1; i<=32; m<<=1,i++) { + if ((vec & m) && map[i] != -1) + sigaddset(&newvec, map[i]); + } + return newvec; +} + +EXPORT_SYMBOL(map_sigvec_to_kernel); + +int +map_value(struct map_segment *m, int val, int def) { + struct map_segment *seg; + + /* If no mapping exists in this personality just return the + * number we were given. + */ + if (!m) + return val; + + /* Search the map looking for a mapping for the given number. */ + for (seg=m; seg->start != -1; seg++) { + if (seg->start <= val && val <= seg->end) { + /* If the start and end are the same then this + * segment has one entry and the map is the value + * it maps to. Otherwise if we have a vector we + * pick out the relevant value, if we don't have + * a vector we give identity mapping. + */ + if (seg->start == seg->end) + return (int)seg->map; + else + return (seg->map ? seg->map[val-seg->start] : val); + } + } + + /* Number isn't mapped. Returned the requested default. */ + return def; +} + +EXPORT_SYMBOL(map_value); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/common/signal.c linux/abi/common/signal.c --- linux-2.4.3/abi/common/signal.c Thu Jan 1 01:00:00 1970 +++ linux/abi/common/signal.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,573 @@ +/* $Id$ + * + * signal.c - generic signal emulation code + * + * This module does not go through the normal processing routines for + * ibcs. The reason for this is that for most events, the return is a + * procedure address for the previous setting. This procedure address + * may be negative which is not an error. Therefore, the return processing + * for standard functions is skipped by declaring this routine as a "special" + * module for the decoder and dealing with the register settings directly. + * + * Please consider this closely if you plan on changing this mode. + * -- Al Longyear + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#define SIG_HOLD ((__sighandler_t)2) /* hold signal */ + +#include +#include + + +typedef void (*pfn) (void); /* Completion function */ + +/* + * Parameters to the signal functions have a common stack frame. This + * defines the stack frame. + */ + +#define SIGNAL_NUMBER get_syscall_parameter (regs, 0) +#define HIDDEN_PARAM (SIGNAL_NUMBER & ~0xFF) +#define SECOND_PARAM get_syscall_parameter (regs, 1) +#ifdef __sparc__ +#define THIRD_PARAM get_syscall_parameter (regs, 2) +#else /* __sparc__ */ +#define THIRD_PARAM ((unsigned long) regs->edx) +#endif /* __sparc__ */ + +/* Return a mask that includes SIG only. */ +#define __sigmask(sig) (1 << ((sig) - 1)) + + +#define TO_KERNEL(save) \ + save = get_fs (); \ + set_fs (get_ds ()) + +#define FROM_KERNEL(save) \ + set_fs (save) + +#define _S(nr) (1<<((nr)-1)) + +#define _BLOCKABLE (~(_S(IBCS_SIGKILL) | _S(IBCS_SIGSTOP))) + +void +deactivate_signal(struct task_struct *task, int signum) +{ + spin_lock_irq(&task->sigmask_lock); + sigdelset(&task->pending.signal, signum); + spin_unlock_irq(&task->sigmask_lock); +} + + +EXPORT_SYMBOL(deactivate_signal); + +/* + * Translate the signal number to the corresponding item for Linux. + */ +static inline int abi_mapsig(int sig) +{ + if ((unsigned int) sig >= NSIGNALS) + return -1; + return current->exec_domain->signal_map[sig]; +} + + +inline int abi_signo (struct pt_regs *regs, int *sig) +{ + int value = abi_mapsig(SIGNAL_NUMBER & 0xFF); + + if (value == -1) { + set_error (regs, iABI_errors (EINVAL)); + return 0; + } + + *sig = value; + return 1; +} + +EXPORT_SYMBOL(abi_signo); + +/* + * Process the signal() function from iBCS + * + * This version appeared in "Advanced Programming in the Unix Environment" + * by W. Richard Stevens, page 298. + */ + +void abi_sig_handler (struct pt_regs * regs, int sig, + __sighandler_t handler, int oneshot) +{ + struct sigaction act, oact; + int answer; + mm_segment_t old_fs; + + sigemptyset (&act.sa_mask); + act.sa_restorer = NULL; + act.sa_handler = handler; + act.sa_flags = 0; + + if (oneshot) + act.sa_flags = SA_ONESHOT | SA_NOMASK; + else + act.sa_flags = 0; + + TO_KERNEL (old_fs); + answer = SYS(rt_sigaction) (sig, &act, &oact, sizeof(sigset_t)); + FROM_KERNEL (old_fs); + + if (answer < 0) { + set_error (regs, iABI_errors (-answer)); + } else + set_result (regs, (int) oact.sa_handler); +} + +EXPORT_SYMBOL(abi_sig_handler); + +/* + * Process the signal() function from iBCS + */ +int abi_signal (struct pt_regs * regs) +{ + __sighandler_t vec; + int sig; + + if (abi_signo (regs, &sig)) { + vec = (__sighandler_t) SECOND_PARAM; + abi_sig_handler (regs, sig, vec, 1); + } + return 0; +} + +EXPORT_SYMBOL(abi_signal); + +/* + * Process the iBCS sigset function. + * + * This is basically the same as the signal() routine with the exception + * that it will accept a SIG_HOLD parameter. + * + * A SIG_HOLD will defer the processing of the signal until a sigrelse() + * function is called. + */ +int abi_sigset (struct pt_regs * regs) +{ + sigset_t newmask, oldmask; + __sighandler_t vec; + int sig, answer; + mm_segment_t old_fs; + + if (abi_signo (regs, &sig)) { + vec = (__sighandler_t) SECOND_PARAM; + if (vec != SIG_HOLD) { + deactivate_signal(current, sig); + abi_sig_handler (regs, sig, vec, 0); + } else { +/* + * Process the hold function + */ + sigemptyset (&newmask); + sigaddset (&newmask, sig); + + TO_KERNEL (old_fs); + answer = SYS(rt_sigprocmask) (SIG_BLOCK, + &newmask, &oldmask, + sizeof(sigset_t)); + FROM_KERNEL (old_fs); + + if (answer < 0) { + set_error (regs, iABI_errors (-answer)); + } + } + } + return 0; +} + +EXPORT_SYMBOL(abi_sigset); + +/* + * Process the iBCS sighold function. + * + * Suspend the signal from future recognition. + */ +void abi_sighold (struct pt_regs * regs) +{ + sigset_t newmask, oldmask; + int sig, answer; + mm_segment_t old_fs; + + if (!abi_signo (regs, &sig)) + return; + + sigemptyset (&newmask); + sigaddset (&newmask, sig); + + TO_KERNEL (old_fs); + answer = SYS(rt_sigprocmask) (SIG_BLOCK, &newmask, &oldmask, + sizeof(sigset_t)); + FROM_KERNEL (old_fs); + + if (answer < 0) { + set_error (regs, iABI_errors (-answer)); + } +} + +EXPORT_SYMBOL(abi_sighold); + +/* + * Process the iBCS sigrelse. + * + * Re-enable the signal processing from a previously suspended + * signal. This may have been done by calling the sighold() function + * or a longjmp() during the signal processing routine. If you do a + * longjmp() function then it is expected that you will call sigrelse + * before going on with the program. + */ +void abi_sigrelse (struct pt_regs * regs) +{ + sigset_t newmask, oldmask; + int sig, answer; + mm_segment_t old_fs; + + if (!abi_signo (regs, &sig)) + return; + + sigemptyset (&newmask); + sigaddset (&newmask, sig); + + TO_KERNEL (old_fs); + answer = SYS(rt_sigprocmask) (SIG_UNBLOCK, &newmask, &oldmask, + sizeof(sigset_t)); + FROM_KERNEL (old_fs); + + if (answer < 0) { + set_error (regs, iABI_errors (-answer)); + } +} + +EXPORT_SYMBOL(abi_sigrelse); + +/* + * Process the iBCS sigignore + * + * This is basically a signal (...,SIG_IGN) call. + */ + +void abi_sigignore (struct pt_regs * regs) +{ + struct sigaction act, oact; + int sig, answer; + mm_segment_t old_fs; + + if (!abi_signo (regs, &sig)) + return; + + sigemptyset (&act.sa_mask); + + act.sa_restorer = NULL; + act.sa_handler = SIG_IGN; + act.sa_flags = 0; + + TO_KERNEL (old_fs); + answer = SYS(rt_sigaction) (sig, &act, &oact, sizeof(sigset_t)); + FROM_KERNEL (old_fs); + + if (answer < 0) { + set_error (regs, iABI_errors (-answer)); + } +} + +EXPORT_SYMBOL(abi_sigignore); + +/* + * Process the iBCS sigpause + * + * Wait for the signal indicated to arrive before resuming the + * processing. I do not know if the signal is processed first using + * the normal event processing before the return. If someone can + * shed some light on this then please correct this code. I block + * the signal and look for it to show up in the pending list. + */ + +void abi_sigpause (struct pt_regs * regs) +{ + old_sigset_t newset; + int sig, answer; + +#ifdef __sparc__ + printk(KERN_ERR "Sparc/iBCS: sigpause not yet implemented\n"); +#else + if (!abi_signo(regs, &sig)) + return; + + newset = ~0UL; + newset &= (1UL << (sig-1)); + answer = SYS(sigsuspend)(0, current->blocked, + newset, regs->esi, regs->edi, + regs->ebp, regs->eax, + regs->xds, regs->xes, + regs->orig_eax, + regs->eip, regs->xcs, regs->eflags, + regs->esp, regs->xss); + + if (answer < 0) { + set_error(regs, iABI_errors(-answer)); + } +#endif +} + +EXPORT_SYMBOL(abi_sigpause); + +/* + * This is the service routine for the syscall #48 (signal funcs). + * + * Examine the request code and branch on the request to the appropriate + * function. + */ + +int abi_sigfunc (struct pt_regs * regs) +{ + int sig_type = (int) HIDDEN_PARAM; + + abi_trace(ABI_TRACE_SIGNAL|ABI_TRACE_SIGNAL_F, "sig%s(%ld, 0x%08lx, 0x%08lx)", + sig_type == 0 ? "nal" + : (sig_type == 0x100 ? "set" + : (sig_type == 0x200 ? "hold" + : (sig_type == 0x400 ? "relse" + : (sig_type == 0x800 ? "ignore" + : (sig_type == 0x1000 ? "pause" + : "???" ))))), + SIGNAL_NUMBER & 0xff, SECOND_PARAM, THIRD_PARAM); + +#ifdef __sparc__ + set_result (regs, 0); +#else /* __sparc__ */ + regs->eflags &= ~1; + regs->eax = 0; +#endif /* __sparc__ */ + switch (sig_type) { + case 0x0000: + abi_signal (regs); + break; + + case 0x0100: + abi_sigset (regs); + break; + + case 0x0200: + abi_sighold (regs); + break; + + case 0x0400: + abi_sigrelse (regs); + break; + + case 0x0800: + abi_sigignore (regs); + break; + + case 0x1000: + abi_sigpause (regs); + break; + + default: + set_error (regs, EINVAL); + + abi_trace(ABI_TRACE_SIGNAL|ABI_TRACE_SIGNAL_F, + "sigfunc(%x, %ld, %lx, %lx) unsupported", + sig_type, + SIGNAL_NUMBER, SECOND_PARAM, THIRD_PARAM); + + return 0; + } + + abi_trace(ABI_TRACE_SIGNAL|ABI_TRACE_SIGNAL_F, + "returns %ld", get_result (regs)); + return 0; +} + +EXPORT_SYMBOL(abi_sigfunc); + + +/* This function is used to handle the sigaction call from SVr4 binaries. + If anyone else uses this, this function needs to be modified since the + order and size of the ibcs_sigaction structure is different in ibcs + and the SVr4 ABI */ + + +asmlinkage int abi_sigaction(int abi_signum, const struct abi_sigaction * action, + struct abi_sigaction * oldaction) +{ + struct abi_sigaction new_sa, old_sa; + int error, signo; + mm_segment_t old_fs; + struct sigaction nsa, osa; + + signo = abi_mapsig(abi_signum); + if (signo == -1) + return -EINVAL; + + if (oldaction) { + error = verify_area(VERIFY_WRITE, oldaction, + sizeof(struct abi_sigaction)); + if (error) + return error; + } + + if (action) { + error = copy_from_user(&new_sa, action, + sizeof(struct abi_sigaction)); + if (error) + return -EFAULT; + nsa.sa_restorer = NULL; + nsa.sa_handler = new_sa.sa_handler; + nsa.sa_mask = map_sigvec_to_kernel(new_sa.sa_mask, + current->exec_domain->signal_map); + if(new_sa.sa_flags & ABI_SA_ONSTACK) + nsa.sa_flags |= SA_ONSTACK; + if(new_sa.sa_flags & ABI_SA_RESTART) + nsa.sa_flags |= SA_RESTART; + if(new_sa.sa_flags & ABI_SA_NODEFER) + nsa.sa_flags |= SA_NODEFER; + if(new_sa.sa_flags & ABI_SA_RESETHAND) + nsa.sa_flags |= SA_RESETHAND; + if(new_sa.sa_flags & ABI_SA_NOCLDSTOP) + nsa.sa_flags |= SA_NOCLDSTOP; + if(new_sa.sa_flags & ABI_SA_NOCLDWAIT) + nsa.sa_flags |= SA_NOCLDWAIT; + } + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(rt_sigaction)(signo, + action ? &nsa : NULL, + oldaction ? &osa : NULL, + sizeof(sigset_t)); + set_fs(old_fs); + + if (!error && oldaction) { + old_sa.sa_handler = osa.sa_handler; + old_sa.sa_mask = map_sigvec_from_kernel(osa.sa_mask, + current->exec_domain->signal_invmap); + old_sa.sa_flags = 0; + if(osa.sa_flags & SA_ONSTACK) + old_sa.sa_flags |= ABI_SA_ONSTACK; + if(osa.sa_flags & SA_RESTART) + old_sa.sa_flags |= ABI_SA_RESTART; + if(osa.sa_flags & SA_NODEFER) + old_sa.sa_flags |= ABI_SA_NODEFER; + if(osa.sa_flags & SA_RESETHAND) + old_sa.sa_flags |= ABI_SA_RESETHAND; + if(osa.sa_flags & SA_NOCLDSTOP) + old_sa.sa_flags |= ABI_SA_NOCLDSTOP; + if(osa.sa_flags & SA_NOCLDWAIT) + old_sa.sa_flags |= ABI_SA_NOCLDWAIT; + /* This should never fail... */ + copy_to_user(oldaction, &old_sa, sizeof(struct abi_sigaction)); + } + return error; +} + +EXPORT_SYMBOL(abi_sigaction); + + +static short int howcnv[] = {SIG_SETMASK, SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK}; + +asmlinkage int +abi_sigprocmask(int how, unsigned long *abinset, unsigned long *abioset) +{ + sigset_t new_set, *nset, old_set, *oset; + unsigned long new_set_abi, old_set_abi; + mm_segment_t old_fs; + int error; + + nset = oset = NULL; + + if (abinset) { + get_user(new_set_abi, abinset); + new_set = map_sigvec_to_kernel(new_set_abi, + current->exec_domain->signal_map); + nset = &new_set; + } + if (abioset) + oset = &old_set; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(rt_sigprocmask)(howcnv[how], nset, oset, sizeof(sigset_t)); + set_fs(old_fs); + + if (!error && abioset) { + old_set_abi = map_sigvec_from_kernel(old_set, + current->exec_domain->signal_invmap); + put_user(old_set_abi, abioset); + } + + return error; +} + + +EXPORT_SYMBOL(abi_sigprocmask); + +#ifndef __sparc__ +int abi_sigsuspend(struct pt_regs * regs) +{ + unsigned long * set; + unsigned long oldset; + old_sigset_t newset; + int error; + + if (personality(PER_BSD)) { + oldset = get_syscall_parameter (regs, 0); + } else + { + set = (unsigned long *)get_syscall_parameter (regs, 0); + error = get_user(oldset, set); + if (error) + return error; + } + newset = map_bitvec(oldset, + current->exec_domain->signal_map); + + abi_trace(ABI_TRACE_SIGNAL, + "sigsuspend oldset, newset = %lx %lx", oldset, newset); + { +#if 0 + extern do_sigpause(unsigned int, struct pt_regs *); + return do_sigpause(newset, regs); +#endif + } + return SYS(sigsuspend)(0, oldset, + newset, regs->esi, regs->edi, + regs->ebp, regs->eax, + regs->xds, regs->xes, + regs->orig_eax, + regs->eip, regs->xcs, regs->eflags, + regs->esp, regs->xss); +} + +EXPORT_SYMBOL(abi_sigsuspend); +#endif /* __sparc__ */ diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/common/socket.c linux/abi/common/socket.c --- linux-2.4.3/abi/common/socket.c Thu Jan 1 01:00:00 1970 +++ linux/abi/common/socket.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,263 @@ +/* $Id$ + * + * socket.c - generic emulated socket code + * + * Copyright (C) 1994, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +int +abi_do_setsockopt(unsigned long *sp) +{ + int error; + int level, optname; + + error = verify_area(VERIFY_READ, + ((unsigned long *)sp), + 5*sizeof(long)); + if (error) + return error; + + get_user(level, ((unsigned long *)sp)+1); + get_user(optname, ((unsigned long *)sp)+2); + + if (abi_traced(ABI_TRACE_STREAMS|ABI_TRACE_SOCKSYS)) { + u_long optval, optlen; + + get_user(optval, ((u_long *)sp) + 3); + get_user(optlen, ((u_long *)sp) + 4); + __abi_trace("setsockopt level=%d, optname=%d, " + "optval=0x%08lx, optlen=0x%08lx\n", + level, optname, optval, optlen); + } + + switch (level) { + case 0: /* IPPROTO_IP aka SOL_IP */ + /* This is correct for the SCO family. Hopefully + * it is correct for other SYSV... + */ + optname--; + if (optname == 0) + optname = 4; + if (optname > 4) { + optname += 24; + if (optname <= 33) + optname--; + if (optname < 32 || optname > 36) + return -EINVAL; + } + put_user(optname, ((unsigned long *)sp)+2); + break; + + case 0xffff: + put_user(SOL_SOCKET, ((unsigned long *)sp)+1); + optname = map_value(current->exec_domain->sockopt_map, optname, 0); + put_user(optname, ((unsigned long *)sp)+2); + + switch (optname) { + case SO_LINGER: { + unsigned long optlen; + + /* SO_LINGER takes a struct linger + * as the argument but some code + * uses an int and expects to get + * away without an error. Sigh... + */ + get_user(optlen, ((unsigned long *)sp)+4); + if (optlen == sizeof(int)) + return 0; + break; + } + + /* 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_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; + } + + 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 SYS(socketcall)(SYS_SETSOCKOPT, sp); +} + +EXPORT_SYMBOL(abi_do_setsockopt); + +int +abi_do_getsockopt(unsigned long *sp) +{ + int error; + int level, optname; + char *optval; + long *optlen; + + error = verify_area(VERIFY_READ, + ((unsigned long *)sp), + 5*sizeof(long)); + if (error) + return error; + + get_user((unsigned long) level, ((unsigned long *)sp)+1); + get_user((unsigned long) optname, ((unsigned long *)sp)+2); + get_user((unsigned long) optval, ((unsigned long *)sp)+3); + get_user((unsigned long) optlen, ((unsigned long *)sp)+4); + + if (abi_traced(ABI_TRACE_STREAMS|ABI_TRACE_SOCKSYS)) { + long l; + + get_user(l, optlen); + __abi_trace("getsockopt level=%d, optname=%d, optval=0x%08lx, " + "optlen=0x%08lx[%ld]\n", level, optname, + (u_long)optval, (u_long)optlen, l); + } + + switch (level) { + case 0: /* IPPROTO_IP aka SOL_IP */ + /* This is correct for the SCO family. Hopefully + * it is correct for other SYSV... + */ + optname--; + if (optname == 0) + optname = 4; + if (optname > 4) { + optname += 24; + if (optname <= 33) + optname--; + if (optname < 32 || optname > 36) + return -EINVAL; + } + put_user(optname, ((unsigned long *)sp)+2); + break; + + case 0xffff: + put_user(SOL_SOCKET, ((unsigned long *)sp)+1); + optname = map_value(current->exec_domain->sockopt_map, optname, 0); + put_user(optname, ((unsigned long *)sp)+2); + + switch (optname) { + case SO_LINGER: { + long l; + + /* SO_LINGER takes a struct linger + * as the argument but some code + * uses an int and expects to get + * away without an error. Sigh... + */ + get_user(l, optlen); + if (l == sizeof(int)) { + put_user(0, (long *)optval); + return 0; + } + break; + } + + /* 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: { + unsigned long len; + error = get_user(len, optlen); + if (error) + return error; + if (len < sizeof(long)) + return -EINVAL; + + error = verify_area(VERIFY_WRITE, + (char *)optval, + sizeof(long)); + if (!error) { + put_user(0, (long *)optval); + put_user(sizeof(long), + optlen); + } + 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: { + unsigned long len; + error = get_user(len, optlen); + if (error) + return error; + if (len < sizeof(long)) + return -EINVAL; + + error = verify_area(VERIFY_WRITE, + (char *)optval, + sizeof(long)); + if (!error) { + put_user(1, (long *)optval); + put_user(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 SYS(socketcall)(SYS_GETSOCKOPT, sp); +} + +EXPORT_SYMBOL(abi_do_getsockopt); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/common/socksys.c linux/abi/common/socksys.c --- linux-2.4.3/abi/common/socksys.c Thu Jan 1 01:00:00 1970 +++ linux/abi/common/socksys.c Sun Mar 18 18:45:12 2001 @@ -0,0 +1,1106 @@ +/* $Id$ + * socksys.c - svr4 /dev/socksys emulation + * + * Copyright 1994-1996 Mike Jagdis (jaggy@purplet.demon.co.uk) + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#include +#include +#include +#include +#include + + +static int socksys_read(struct file *filep, + char *buf, size_t count, loff_t *offset); +static int socksys_write(struct file *filep, + const char *buf, size_t count, loff_t *offset); +static int socksys_open(struct inode *ino, struct file *filep); +static int socksys_close(struct inode *ino, struct file *filep); +static unsigned int socksys_poll(struct file *filep, struct poll_table_struct *wait); + + +/* + * socksys_fops defines the file operations that can be applied to the + * /dev/socksys device. + */ +static struct file_operations socksys_fops = { + owner: THIS_MODULE, + read: socksys_read, + write: socksys_write, + open: socksys_open, + release: socksys_close, +}; + +/* socksys_socket_fops defines the file operations that can be applied to + * sockets themselves. This gets initialised when the first socket is + * created. + */ +static struct file_operations socksys_socket_fops = { + NULL, +}; + +static int (*sock_close)(struct inode *inode, struct file *file); +static unsigned int (*sock_poll)(struct file *filep, struct poll_table_struct *wait); + + +void +inherit_socksys_funcs(unsigned int fd, int state) +{ +#ifdef CONFIG_ABI_XTI + struct T_private *priv; +#endif + struct inode *ino; + struct file *filep = fget(fd); + if (!filep) + return; + + ino = filep->f_dentry->d_inode; + +#ifdef SO_BSDCOMPAT + /* SYSV sockets are BSD like with respect to ICMP errors + * with UDP rather than RFC conforming. I think. + */ + ino->u.socket_i.sk->bsdism = 1; +#endif + +#ifdef CONFIG_ABI_XTI + priv = (struct T_private *)kmalloc(sizeof(struct T_private), GFP_KERNEL); + if (priv) { + priv->magic = XTI_MAGIC; + priv->state = state; + priv->offset = 0; + priv->pfirst = priv->plast = NULL; + } + filep->private_data = priv; +#endif + + /* If our file operations don't appear to match + * what the socket system is advertising it may + * be because we haven't initialised ours at all + * yet or it may be because the old socket system + * module was unloaded and reloaded. This isn't + * entirely safe because we may still have open + * sockets which *should* use the old routines + * until they close - tough, for now. + */ + if (socksys_socket_fops.read != filep->f_op->read) { + memcpy(&socksys_socket_fops, + filep->f_op, + sizeof(struct file_operations)); + sock_close = socksys_socket_fops.release; + sock_poll = socksys_socket_fops.poll; + socksys_socket_fops.release = socksys_close; + socksys_socket_fops.poll = socksys_poll; + } + filep->f_op = &socksys_socket_fops; +#if 1 + ino->i_mode = 0020000; /* S_IFCHR */ + ino->i_rdev = MKDEV(SOCKSYS_MAJOR, 0); +#endif + fput(filep); + // MOD_INC_USE_COUNT; +} + +EXPORT_SYMBOL(inherit_socksys_funcs); + +static int +spx_connect(unsigned int fd, int spxnum) +{ + int newfd, err, args[3]; + struct sockaddr_un addr = { + AF_UNIX, "/tmp/.X11-unix/X0" + }; + mm_segment_t old_fs = get_fs(); + + abi_trace(ABI_TRACE_SOCKSYS, + "SPX: %u choose service %d", fd, spxnum); + + /* Rather than use an explicit path to the X :0 server + * socket we should use the given number to look up a path + * name to use (we can't rely on servers registering their + * sockets either - for one thing we don't emulate that yet + * and for another thing different OS binaries do things in + * different ways but all must interoperate). + * I suggest putting the mapping in, say, /dev/spx.map/%d + * where each file is a symlink containing the path of the + * socket to use. Then we can just do a readlink() here to + * get the pathname. + * Hey, this is what we do here now! + */ + addr.sun_family = AF_UNIX; + sprintf(addr.sun_path, "/dev/spx.map/%u", spxnum); + set_fs(get_ds()); + err = SYS(readlink)(addr.sun_path, addr.sun_path, + sizeof(addr.sun_path)-1); + set_fs(old_fs); + if (err == -ENOENT) { + + abi_trace(ABI_TRACE_SOCKSYS, + "SPX: %u no symlink \"%s\", try X :0", + fd, addr.sun_path); + strcpy(addr.sun_path, "/tmp/.X11-unix/X0"); + } else { + if (err < 0) + return err; + addr.sun_path[err] = '\0'; + } + + abi_trace(ABI_TRACE_SOCKSYS, "SPX: %u get a Unix domain socket", fd); + + args[0] = AF_UNIX; + args[1] = SOCK_STREAM; + args[2] = 0; + set_fs(get_ds()); + newfd = SYS(socketcall)(SYS_SOCKET, args); + set_fs(old_fs); + if (newfd < 0) + return newfd; + + abi_trace(ABI_TRACE_SOCKSYS, "SPX: %u connect to \"%s\"", + fd, addr.sun_path); + + args[0] = newfd; + args[1] = (int)&addr; + args[2] = sizeof(struct sockaddr_un); + set_fs(get_ds()); + err = SYS(socketcall)(SYS_CONNECT, args); + set_fs(old_fs); + if (err) { + SYS(close)(newfd); + return err; + } + return newfd; +} + + +int +abi_socksys_fd_init(int fd, int rw, const char *buf, int *count) +{ + struct file *filep; + struct inode *ino; + int error, sockfd; + + /* FIXME: we are always holding the filep when we get here + * anyway so we could just use fcheck here... + */ + filep = fget(fd); + if (!filep) + return -EBADF; + ino = filep->f_dentry->d_inode; + + abi_trace(ABI_TRACE_SOCKSYS, "socksys: fd=%d initializing", fd); + + /* Minor = 0 is the socksys device itself. No special handling + * will be needed as it is controlled by the application + * via ioctls. + */ + if (MINOR(ino->i_rdev) == 0) { + fput(filep); + return 0; + } + + /* Minor = 1 is the spx device. This is the client side of a + * streams pipe to the X server. Under SCO and friends + * the library code messes around setting the connection + * up itself. We do it ourselves - this means we don't + * need to worry about the implementation of the server + * side (/dev/X0R - which must exist but can be a link + * to /dev/null) nor do we need to actually implement + * getmsg/putmsg. + */ + if (MINOR(ino->i_rdev) == 1) { + int unit = 1; + + fput(filep); + + /* It seems early spx implementations were just a + * quick hack to get X to work. They only supported + * one destination and connected automatically. + * Later versions take a single byte write, the + * value of the byte telling them which destination + * to connect to. Hence this quick hack to work + * with both. If the first write is a single byte + * it's a connect request otherwise we auto-connect + * to destination 1. + */ + if (rw == 1 && *count == 1) { + error = get_user(unit, buf); + if (error) + return error; + (*count)--; + } + + sockfd = spx_connect(fd, unit); + if (sockfd < 0) + return sockfd; + } + + /* + * Otherwise the high 4 bits specify the address/protocol + * family (AF_INET, AF_UNIX etc.) and the low 4 bits determine + * the protocol (IPPROTO_IP, IPPROTO_UDP, IPPROTO_TCP etc.) + * although not using a one-to-one mapping as the minor number + * is not big enough to hold everything directly. The socket + * type is inferrred from the protocol. + */ + else { /* XTI */ + int args[3]; + mm_segment_t old_fs = get_fs(); + + /* Grab a socket. */ + + abi_trace(ABI_TRACE_SOCKSYS, + "XTI: %d get socket for transport end" + " point (dev = 0x%04x)", + fd, ino->i_rdev); + + switch ((args[0] = ((MINOR(ino->i_rdev) >> 4) & 0x0f))) { + case AF_UNIX: + args[1] = SOCK_STREAM; + args[2] = 0; + break; + + case AF_INET: { + int prot[16] = { + IPPROTO_ICMP, IPPROTO_ICMP, + IPPROTO_IGMP, IPPROTO_IPIP, + IPPROTO_TCP, IPPROTO_EGP, + IPPROTO_PUP, IPPROTO_UDP, + IPPROTO_IDP, IPPROTO_RAW, + }; + int type[16] = { + SOCK_RAW, SOCK_RAW, + SOCK_RAW, SOCK_RAW, + SOCK_STREAM, SOCK_RAW, + SOCK_RAW, SOCK_DGRAM, + SOCK_RAW, SOCK_RAW, + }; + int i = MINOR(ino->i_rdev) & 0x0f; + args[2] = prot[i]; + args[1] = type[i]; + break; + } + + default: + args[1] = SOCK_RAW; + args[2] = 0; + break; + } + fput(filep); + + abi_trace(ABI_TRACE_SOCKSYS, + "XTI: %d socket %d %d %d", + fd, args[0], args[1], args[2]); + + set_fs(get_ds()); + sockfd = SYS(socketcall)(SYS_SOCKET, args); + set_fs(old_fs); + if (sockfd < 0) + return sockfd; + } + + /* Redirect operations on the socket fd via our emulation + * handlers then swap the socket fd and the original fd, + * discarding the original fd. + */ + inherit_socksys_funcs(sockfd, TS_UNBND); + + abi_trace(ABI_TRACE_SOCKSYS, "XTI: %d -> %d", fd, sockfd); + + SYS(dup2)(sockfd, fd); + SYS(close)(sockfd); + return 1; +} +EXPORT_SYMBOL(abi_socksys_fd_init); + + +static int +socksys_read(struct file *filep, char *buf, size_t count, loff_t *offset) +{ + struct inode *ino = filep->f_dentry->d_inode; + + /* FIXME: this condition *must* be true - if we have already + * replaced this with a socket we have changed the file ops + * too surely? + */ + if (ino && !ino->i_sock) { + int fd; + for (fd = 0; fd < current->files->max_fdset; fd++) { + if (fcheck(fd) == filep) { + int error; + error = abi_socksys_fd_init(fd, 0, NULL, NULL); + if (error > 0) { + fput(filep); + filep = fget(fd); + return filep->f_op->read(filep, buf, + count, offset); + } else + return error ? error : -EINVAL; + } + } + } + return -EINVAL; +} + + +static int +socksys_write(struct file *filep, const char *buf, size_t count, loff_t *offset) +{ + struct inode *ino = filep->f_dentry->d_inode; + + /* FIXME: this condition *must* be true - if we have already + * replaced this with a socket we have changed the file ops + * too surely? + */ + if (ino && !ino->i_sock) { + int fd; + for (fd = 0; fd < current->files->max_fdset; fd++) { + if (fcheck(fd) == filep) { + int error; + error = abi_socksys_fd_init(fd, 1, buf, &count); + if (error > 0) { + fput(filep); + filep = fget(fd); + return count + ? filep->f_op->write(filep, buf, + count, offset) + : 0; + } else + return error ? error : -EINVAL; + } + } + } + return -EINVAL; +} + + +int +socksys_syscall(int *sp) +{ + int error, cmd; + + error = get_user(cmd, sp); + if (error) + return error; + sp++; + + if (abi_traced(ABI_TRACE_SOCKSYS)) { + u_long a0, a1, a2, a3, a4, a5; + static const char * const cmd_map[] = { + "", "accept", "bind", "connect", "getpeername", + "getsockname", "getsockopt", "listen", "recv", + "recvfrom", "send", "sendto", "setsockopt", "shutdown", + "socket", "select", "getipdomain", "setipdomain", + "adjtime", "setreuid", "setregid", "gettimeofday", + "settimeofday", "getitimer", "setitimer", + "recvmsg", "sendmsg", "sockpair" + }; + + get_user(a0, sp+0); + get_user(a1, sp+1); + get_user(a2, sp+2); + get_user(a3, sp+3); + get_user(a4, sp+4); + get_user(a5, sp+5); + + __abi_trace("socksys: %s (%d) " + "<0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx>", + (cmd >= 0 && + cmd < sizeof(cmd_map) / sizeof(cmd_map[0])) + ? cmd_map[cmd] : "???", cmd, + a0, a1, a2, a3, a4, a5); + } + + switch (cmd) { + case SSYS_SO_SOCKET: { + /* Get a socket but replace the socket file + * operations with our own so we can do the + * right thing for ioctls. + */ + int fd; + unsigned long x; + + get_user(x, ((unsigned long *)sp)+0); + put_user(map_value(current->exec_domain->af_map, x, 0), + ((unsigned long *)sp)+0); + get_user(x, ((unsigned long *)sp)+1); + put_user(map_value(current->exec_domain->socktype_map, x, 0), + ((unsigned long *)sp)+1); + + if ((fd = SYS(socketcall)(SYS_SOCKET, sp)) < 0) + return fd; + + inherit_socksys_funcs(fd, TS_UNBND); + return fd; + } + + case SSYS_SO_ACCEPT: { + int fd; + + if ((fd = SYS(socketcall)(SYS_ACCEPT, sp)) < 0) + return fd; + + inherit_socksys_funcs(fd, TS_DATA_XFER); + return fd; + } + case SSYS_SO_BIND: + return SYS(socketcall)(SYS_BIND, sp); + case SSYS_SO_CONNECT: + return SYS(socketcall)(SYS_CONNECT, sp); + case SSYS_SO_GETPEERNAME: + return SYS(socketcall)(SYS_GETPEERNAME, sp); + case SSYS_SO_GETSOCKNAME: + return SYS(socketcall)(SYS_GETSOCKNAME, sp); + case SSYS_SO_GETSOCKOPT: + return abi_do_getsockopt((unsigned long *)sp); + case SSYS_SO_LISTEN: + return SYS(socketcall)(SYS_LISTEN, sp); + case SSYS_SO_RECV: { + int err = SYS(socketcall)(SYS_RECV, sp); + if (err == -EAGAIN) err = -EWOULDBLOCK; + return err; + } + case SSYS_SO_RECVFROM: { + int err = SYS(socketcall)(SYS_RECVFROM, sp); + if (err == -EAGAIN) err = -EWOULDBLOCK; + return err; + } + case SSYS_SO_SEND: { + int err = SYS(socketcall)(SYS_SEND, sp); + if (err == -EAGAIN) err = -EWOULDBLOCK; + return err; + } + case SSYS_SO_SENDTO: { + int err = SYS(socketcall)(SYS_SENDTO, sp); + if (err == -EAGAIN) err = -EWOULDBLOCK; + return err; + } + case SSYS_SO_SETSOCKOPT: + return abi_do_setsockopt((unsigned long *)sp); + case SSYS_SO_SHUTDOWN: + return SYS(socketcall)(SYS_SHUTDOWN, sp); + + case SSYS_SO_GETIPDOMAIN: { + int error, len; + char *name, *p; + + error = get_user((unsigned long) name, (char *)(sp+0)); + if (!error) + get_user(len, sp+1); + if (!error) { + down_read(&uts_sem); + error = verify_area(VERIFY_WRITE, name, len); + if (!error) { + --len; + for (p=system_utsname.nodename; *p && *p != '.'; p++); + if (*p == '.') + p++; + else + p = system_utsname.domainname; + if (strcmp(p, "(none)")) + for (;*p && len > 0; p++,len--) { + __put_user(*p, name); + name++; + } + __put_user('\0', name); + } + up_read(&uts_sem); + } + return error; + } + case SSYS_SO_SETIPDOMAIN: { + int error, len, togo; + char *name, *p; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + error = get_user((unsigned long) name, (char *)(sp+0)); + if (!error) + error = get_user(len, sp+1); + if (error) + return error; + + down_write(&uts_sem); + togo = __NEW_UTS_LEN; + for (p=system_utsname.nodename; *p && *p != '.'; p++,togo--); + if (*p == '.') + p++,togo--; + + error = -EINVAL; + if (len <= togo) { + while (len-- > 0) { + get_user(*p, name); + p++; + name++; + } + *p = '\0'; + error = 0; + } + up_write(&uts_sem); + return error; + } + + case SSYS_SO_SETREUID: + case SSYS_SO_SETREGID: { + int error; + uid_t ruid, euid; + + error = get_user(ruid, sp+0); + if (!error) + error = get_user(euid, sp+1); + if (error) + return error; + return (cmd == SSYS_SO_SETREUID) + ? SYS(setreuid)(ruid, euid) + : SYS(setregid)(ruid, euid); + } + + case SSYS_SO_GETTIME: + case SSYS_SO_SETTIME: { + int error; + struct timeval *tv; + struct timezone *tz; + + error = get_user((unsigned long) tv, sp+0); + if (!error) + error = get_user((unsigned long) tz, sp+1); + if (error) + return error; + return (cmd == SSYS_SO_GETTIME) + ? SYS(gettimeofday)(tv, tz) + : SYS(settimeofday)(tv, tz); + } + + case SSYS_SO_GETITIMER: { + int error, which; + struct itimerval *value; + + error = get_user((unsigned long) which, sp+0); + if (!error) + error = get_user((unsigned long) value, sp+1); + if (error) + return error; + return SYS(getitimer)(which, value); + } + case SSYS_SO_SETITIMER: { + int error, which; + struct itimerval *value, *ovalue; + + error = get_user((unsigned long) which, sp+0); + if (!error) + error = get_user((unsigned long) value, sp+1); + if (!error) + error = get_user((unsigned long) ovalue, sp+2); + if (error) + return error; + return SYS(setitimer)(which, value, ovalue); + } + + case SSYS_SO_SELECT: + /* This may be wrong? I don't know how to trigger + * this case. Select seems to go via the Xenix + * select entry point. + */ + return SYS(select)(sp); + + case SSYS_SO_ADJTIME: + return -EINVAL; + + /* These appear in SCO 3.2v5. I assume that the format of + * a msghdr is identical with Linux. I have not checked. + */ + case SSYS_SO_RECVMSG: { + int err = SYS(socketcall)(SYS_RECVMSG, sp); + if (err == -EAGAIN) err = -EWOULDBLOCK; + return err; + } + case SSYS_SO_SENDMSG: { + int err = SYS(socketcall)(SYS_SENDMSG, sp); + if (err == -EAGAIN) err = -EWOULDBLOCK; + return err; + } + + case SSYS_SO_SOCKPAIR: { + /* Get a socketpair but replace the socket file + * operations with our own so we can do the + * right thing for ioctls. + */ + struct file *filep; + struct inode *ino; + int error, args[4], pairin[2], pairout[2]; + mm_segment_t old_fs = get_fs(); + + /* The first two arguments are file descriptors + * of sockets which have already been opened + * and should now be connected back to back. + */ + error = get_user(pairin[0], sp+0); + if (!error) + error = get_user(pairin[1], sp+1); + if (error) + return error; + + filep = fget(pairin[0]); + if (!filep) + return -EBADF; + ino = filep->f_dentry->d_inode; + if (!ino || !ino->i_sock) { + fput(filep); + return -EBADF; + } + + args[0] = AF_UNIX; + args[1] = ino->u.socket_i.type; + args[2] = 0; + args[3] = (int)pairout; + + fput(filep); + + /* FIXME: Do we need to close these here? If we + * fail to connect them should they be open? + */ + SYS(close)(pairin[0]); + SYS(close)(pairin[1]); + + set_fs(get_ds()); + error = SYS(socketcall)(SYS_SOCKETPAIR, args); + set_fs(old_fs); + if (error < 0) + return error; + + if (pairout[0] != pairin[0]) { + SYS(dup2)(pairout[0], pairin[0]); + SYS(close)(pairout[0]); + } + if (pairout[1] != pairin[1]) { + SYS(dup2)(pairout[1], pairin[1]); + SYS(close)(pairout[1]); + } + + inherit_socksys_funcs(pairin[0], TS_DATA_XFER); + inherit_socksys_funcs(pairin[1], TS_DATA_XFER); + return 0; + } + } + + return -EINVAL; +} + + +EXPORT_SYMBOL(socksys_syscall); + +int +abi_ioctl_socksys(int fd, unsigned int cmd, void *arg) +{ + int error; + + switch (cmd) { + /* Strictly the ip domain and nis domain are separate and + * distinct under SCO but Linux only has the one domain. + */ + case NIOCGETDOMNAM: { + struct domnam_args dn; + char *p; + + error = copy_from_user(&dn, (char *)arg, + sizeof(struct domnam_args)); + if (error) + return -EFAULT; + + down_read(&uts_sem); + error = verify_area(VERIFY_WRITE, dn.name, dn.namelen); + if (!error) { + --dn.namelen; + for (p=system_utsname.domainname; *p && dn.namelen > 0; p++,dn.namelen--) { + __put_user(*p, dn.name); + dn.name++; + } + __put_user('\0', dn.name); + } + up_read(&uts_sem); + return error; + } + case NIOCSETDOMNAM: { + struct domnam_args dn; + + error = copy_from_user(&dn, (char *)arg, + sizeof(struct domnam_args)); + if (error) + return -EFAULT; + + return SYS(setdomainname)(dn.name, dn.namelen); + } + + case NIOCLSTAT: { + /* I think this was used before symlinks were added + * to the base SCO OS? + */ + struct lstat_args st; + + error = copy_from_user(&st, (char *)arg, + sizeof(struct lstat_args)); + if (error) + return -EFAULT; + + return abi_lstat(st.fname, st.statb); + } + + case NIOCOLDGETFH: + case NIOCGETFH: { + struct getfh_args gf; + struct nameidata nd; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + error = copy_from_user(&gf, (char *)arg, + sizeof(struct getfh_args)); + if (error) + return -EFAULT; + + /* XXX: is this needed anymore? */ + error = verify_area(VERIFY_WRITE, (char *)gf.fhp, sizeof(fhandle_t)); + if (error) + return error; + + error = user_path_walk(gf.fname, &nd); + if (error) + return error; + + error = do_revalidate(nd.dentry); + if (!error) { + struct inode *ino = nd.dentry->d_inode; + __put_user(ino->i_dev, &gf.fhp->fh.fsid); + __put_user(ino->i_ino, &gf.fhp->fh.fno); + __put_user(0L, &gf.fhp->fh.fgen); + __put_user(ino->i_dev, &gf.fhp->fh.ex_fsid); + __put_user(ino->i_ino, &gf.fhp->fh.ex_fno); + __put_user(0L, &gf.fhp->fh.ex_fgen); + error = 0; + } + path_release(&nd); + return error; + } + + case NIOCNFSD: + case NIOCASYNCD: + case NIOCCLNTHAND: + case NIOCEXPORTFS: + return -EINVAL; + + case SSYS_SIOCSOCKSYS: /* Pseudo socket syscall */ + case SVR4_SIOCSOCKSYS: + return socksys_syscall((int *)arg); + + case SSYS_SIOCSHIWAT: /* set high watermark */ + case SVR4_SIOCSHIWAT: + case SSYS_SIOCSLOWAT: /* set low watermark */ + case SVR4_SIOCSLOWAT: + /* Linux doesn't support them but lie anyway + * or some things take it as fatal (why?) + * FIXME: actually we can do this now... + */ + return 0; + + case SSYS_SIOCGHIWAT: /* get high watermark */ + case SVR4_SIOCGHIWAT: + case SSYS_SIOCGLOWAT: /* get low watermark */ + case SVR4_SIOCGLOWAT: + /* Linux doesn't support them but lie anyway + * or some things take it as fatal (why?) + * FIXME: actually we can do this now... + */ + if ((error = verify_area(VERIFY_WRITE, (char *)arg, + sizeof(unsigned long)))) + return error; + put_user(0, (unsigned long *)arg); + return 0; + + case SSYS_SIOCATMARK: /* at oob mark? */ + case SVR4_SIOCATMARK: + return SYS(ioctl)(fd, SIOCATMARK, arg); + + case SSYS_SIOCSPGRP: /* set process group */ + case SVR4_SIOCSPGRP: + return SYS(ioctl)(fd, SIOCSPGRP, arg); + case SSYS_SIOCGPGRP: /* get process group */ + case SVR4_SIOCGPGRP: + return SYS(ioctl)(fd, SIOCGPGRP, arg); + + case FIONREAD: + case SSYS_FIONREAD: /* BSD compatibilty */ + error = SYS(ioctl)(fd, TIOCINQ, arg); + + if (!error && abi_traced(ABI_TRACE_SOCKSYS)) { + u_long n; + + get_user(n, (u_long *)arg); + __abi_trace("socksys: %d FIONREAD " + "found %lu bytes ready", + fd, n); + } + + return error; + + case SSYS_FIONBIO: /* BSD compatibilty */ + return SYS(ioctl)(fd, FIONBIO, arg); + + case SSYS_FIOASYNC: /* BSD compatibilty */ + return SYS(ioctl)(fd, FIOASYNC, arg); + + case SSYS_SIOCADDRT: /* add route */ + case SVR4_SIOCADDRT: + return SYS(ioctl)(fd, SIOCADDRT, arg); + case SSYS_SIOCDELRT: /* delete route */ + case SVR4_SIOCDELRT: + return SYS(ioctl)(fd, SIOCDELRT, arg); + + case SSYS_SIOCSIFADDR: /* set ifnet address */ + case SVR4_SIOCSIFADDR: + return SYS(ioctl)(fd, SIOCSIFADDR, arg); + case SSYS_SIOCGIFADDR: /* get ifnet address */ + case SVR4_SIOCGIFADDR: + return SYS(ioctl)(fd, SIOCGIFADDR, arg); + + case SSYS_SIOCSIFDSTADDR: /* set p-p address */ + case SVR4_SIOCSIFDSTADDR: + return SYS(ioctl)(fd, SIOCSIFDSTADDR, arg); + case SSYS_SIOCGIFDSTADDR: /* get p-p address */ + case SVR4_SIOCGIFDSTADDR: + return SYS(ioctl)(fd, SIOCGIFDSTADDR, arg); + + case SSYS_SIOCSIFFLAGS: /* set ifnet flags */ + case SVR4_SIOCSIFFLAGS: + return SYS(ioctl)(fd, SIOCSIFFLAGS, arg); + case SSYS_SIOCGIFFLAGS: /* get ifnet flags */ + case SVR4_SIOCGIFFLAGS: +#if 0 + case SVRX_SIOCGIFFLAGS: +#endif + return SYS(ioctl)(fd, SIOCGIFFLAGS, arg); + + case SSYS_SIOCGIFCONF: /* get ifnet list */ + case SVR4_SIOCGIFCONF: +#if 0 + case SVRX_SIOCGIFCONF: +#endif + return SYS(ioctl)(fd, SIOCGIFCONF, arg); + + case SSYS_SIOCGIFBRDADDR: /* get broadcast addr */ + case SVR4_SIOCGIFBRDADDR: + return SYS(ioctl)(fd, SIOCGIFBRDADDR, arg); + case SSYS_SIOCSIFBRDADDR: /* set broadcast addr */ + case SVR4_SIOCSIFBRDADDR: + return SYS(ioctl)(fd, SIOCSIFBRDADDR, arg); + + case SSYS_SIOCGIFNETMASK: /* get net addr mask */ + case SVR4_SIOCGIFNETMASK: + return SYS(ioctl)(fd, SIOCGIFNETMASK, arg); + case SSYS_SIOCSIFNETMASK: /* set net addr mask */ + return SYS(ioctl)(fd, SIOCSIFNETMASK, arg); + + case SSYS_SIOCGIFMETRIC: /* get IF metric */ + case SVR4_SIOCGIFMETRIC: + return SYS(ioctl)(fd, SIOCGIFMETRIC, arg); + case SSYS_SIOCSIFMETRIC: /* set IF metric */ + case SVR4_SIOCSIFMETRIC: + return SYS(ioctl)(fd, SIOCSIFMETRIC, arg); + + case SSYS_SIOCSARP: /* set arp entry */ + case SVR4_SIOCSARP: + return SYS(ioctl)(fd, SIOCSARP, arg); + case SSYS_SIOCGARP: /* get arp entry */ + case SVR4_SIOCGARP: + return SYS(ioctl)(fd, SIOCGARP, arg); + case SSYS_SIOCDARP: /* delete arp entry */ + case SVR4_SIOCDARP: + return SYS(ioctl)(fd, SIOCDARP, arg); + + case SSYS_SIOCGENADDR: /* Get ethernet addr */ + case SVR4_SIOCGENADDR: + return SYS(ioctl)(fd, SIOCGIFHWADDR, arg); + + case SSYS_SIOCSIFMTU: /* get if_mtu */ + case SVR4_SIOCSIFMTU: + return SYS(ioctl)(fd, SIOCSIFMTU, arg); + case SSYS_SIOCGIFMTU: /* set if_mtu */ + case SVR4_SIOCGIFMTU: + return SYS(ioctl)(fd, SIOCGIFMTU, arg); + + case SSYS_SIOCGETNAME: /* getsockname */ + case SVR4_SIOCGETNAME: + case SSYS_SIOCGETPEER: /* getpeername */ + case SVR4_SIOCGETPEER: + { + struct sockaddr uaddr; + int uaddr_len = sizeof(struct sockaddr); + int op, args[3]; + mm_segment_t old_fs; + + if ((error = verify_area(VERIFY_WRITE, (char *)arg, sizeof(struct sockaddr)))) + return error; + if (cmd == SSYS_SIOCGETNAME || cmd == SVR4_SIOCGETNAME) + op = SYS_GETSOCKNAME; + else + op = SYS_GETPEERNAME; + args[0] = fd; + args[1] = (int)&uaddr; + args[2] = (int)&uaddr_len; + old_fs = get_fs(); + set_fs (get_ds()); + error = SYS(socketcall)(op, args); + set_fs(old_fs); + if (error >= 0) + copy_to_user((char *)arg, &uaddr, uaddr_len); + return error; + } + + case SSYS_IF_UNITSEL: /* set unit number */ + case SVR4_IF_UNITSEL: + case SSYS_SIOCXPROTO: /* empty proto table */ + case SVR4_SIOCXPROTO: + + case SSYS_SIOCIFDETACH: /* detach interface */ + case SVR4_SIOCIFDETACH: + case SSYS_SIOCGENPSTATS: /* get ENP stats */ + case SVR4_SIOCGENPSTATS: + + case SSYS_SIOCSIFNAME: /* set interface name */ + case SVR4_SIOCSIFNAME: + case SSYS_SIOCGIFONEP: /* get one-packet params */ + case SSYS_SIOCSIFONEP: /* set one-packet params */ + + case SSYS_SIOCPROTO: /* link proto */ + case SVR4_SIOCPROTO: + case SSYS_SIOCX25XMT: + case SVR4_SIOCX25XMT: + case SSYS_SIOCX25RCV: + case SVR4_SIOCX25RCV: + case SSYS_SIOCX25TBL: + case SVR4_SIOCX25TBL: + + default: + printk(KERN_DEBUG "%d iBCS: socksys: %d: ioctl 0x%x with argument 0x%lx requested\n", + current->pid, fd, + cmd, (unsigned long)arg); + break; + } + + return -EINVAL; +} + +EXPORT_SYMBOL(abi_ioctl_socksys); + + +static int +socksys_open(struct inode *ino, struct file *filep) +{ + abi_trace(ABI_TRACE_SOCKSYS, + "socksys: filep=0x%08lx, inode=0x%08lx opening", + (u_long)filep, (u_long)ino); + return 0; +} + + +static unsigned int +socksys_poll(struct file *filep, struct poll_table_struct *wait) +{ + unsigned int mask = 0; + +#ifdef CONFIG_ABI_XTI + struct inode *ino = filep->f_dentry->d_inode; + + /* If this is a timod transport end point and there + * is a control message queued we have readable data. + */ + if (ino && ino->i_sock && MINOR(ino->i_rdev) != 1 + && Priv(filep) && Priv(filep)->pfirst) + mask = Priv(filep)->pfirst->pri == MSG_HIPRI + ? POLLPRI + : POLLIN; +#endif + + if (sock_poll) + mask |= (*sock_poll)(filep, wait); + return mask; +} + + +static int +socksys_close(struct inode *ino, struct file *filep) +{ + int error; + + /* Not being a socket is not an error - it is probably + * just the pseudo device transport provider. + */ + error = 0; + if (ino && ino->i_sock) { +#ifdef CONFIG_ABI_XTI + if (filep->private_data) { + struct T_primsg *it; + it = ((struct T_private *)filep->private_data)->pfirst; + while (it) { + struct T_primsg *tmp = it; + it = it->next; + kfree(tmp); + } + kfree(filep->private_data); + } +#endif + error = sock_close(ino, filep); + } + + abi_trace(ABI_TRACE_SOCKSYS, "socksys: %lx closed", (u_long)filep); + + return error; +} + +static int __init init_abi(void) +{ + int ret; + + if ((ret = register_chrdev(SOCKSYS_MAJOR, "socksys", &socksys_fops))) + printk(KERN_ERR "abi: unable register socksys char major\n"); + return (ret); +} + +static void __exit cleanup_abi(void) +{ + unregister_chrdev(SOCKSYS_MAJOR, "socksys"); +} + +module_init(init_abi); +module_exit(cleanup_abi); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/common/stat.c linux/abi/common/stat.c --- linux-2.4.3/abi/common/stat.c Thu Jan 1 01:00:00 1970 +++ linux/abi/common/stat.c Sun Mar 18 17:35:53 2001 @@ -0,0 +1,139 @@ +/* $Id$ + * stat.c - iABI stat(2) emulation + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * Hacked by Eric Youngdale for iBCS. + * Added to by Drew Sullivan. + * Heavily rewritten by Christoph Hellwig for Linux 2.4. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +#ifdef __sparc__ +static int cp_abi_stat(struct inode * inode, struct ibcs_stat * statbuf) +{ + struct ibcs_stat tmp; + + memset ((void *) &tmp, 0, sizeof (tmp)); + tmp.st_dev = inode->i_dev; + tmp.st_ino = inode->i_ino; + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlink; + tmp.st_uid = inode->i_uid; + tmp.st_gid = inode->i_gid; + tmp.st_rdev = inode->i_rdev; + tmp.st_size = inode->i_size; + tmp.st_atime.tv_sec = inode->i_atime; + tmp.st_mtime.tv_sec = inode->i_mtime; + tmp.st_ctime.tv_sec = inode->i_ctime; + tmp.st_blksize = inode->i_blksize; + tmp.st_blocks = inode->i_blocks; + return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; +} + +#else /* if not sparc... */ + +/* + * Believe it or not, the original stat structure is compatible with ibcs2. + * The xstat struct used by SVr4 is different than our new struct, but we will + * deal with that later + */ +static int cp_abi_stat(struct inode * inode, struct ibcs_stat * statbuf) +{ + struct ibcs_stat tmp; + + /* Note that we have to fold a long inode number down to a short. + * This must match what happens in coff:ibcs_read() and + * open.c:svr4_getdents() since code that figures out cwd needs + * the inodes to match. Because it must match read() on a + * directory we have to avoid the situation where we end up + * with a zero inode value. A zero inode value in a read() + * on a directory indicates an empty directory slot. + */ + if ((unsigned long)inode->i_ino & 0xffff) + tmp.st_ino = (unsigned long)inode->i_ino & 0xffff; + else + tmp.st_ino = 0xfffe; + + tmp.st_dev = inode->i_dev; + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlink; + tmp.st_uid = inode->i_uid; + tmp.st_gid = inode->i_gid; + tmp.st_rdev = inode->i_rdev; + tmp.st_size = inode->i_size; + tmp.st_atime = inode->i_atime; + tmp.st_mtime = inode->i_mtime; + tmp.st_ctime = inode->i_ctime; + return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; +} +#endif /* not sparc */ + + +int abi_stat(char *filename, struct ibcs_stat *st) +{ + struct nameidata nd; + int error; + + error = user_path_walk(filename, &nd); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_abi_stat(nd.dentry->d_inode, st); + path_release(&nd); + } + return error; +} + +EXPORT_SYMBOL(abi_stat); + + +int abi_lstat(char *filename, struct ibcs_stat *st) +{ + struct nameidata nd; + int error; + + error = user_path_walk_link(filename, &nd); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_abi_stat(nd.dentry->d_inode, st); + path_release(&nd); + } + return error; +} + +EXPORT_SYMBOL(abi_lstat); + + +int abi_fstat(unsigned int fd, struct ibcs_stat *st) +{ + struct file * f; + int err = -EBADF; + + f = fget(fd); + if (f) { + struct dentry * dentry = f->f_dentry; + err = do_revalidate(dentry); + if (!err) + err = cp_abi_stat(dentry->d_inode, st); + fput(f); + } + + return err; +} + +EXPORT_SYMBOL(abi_fstat); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/common/verb_errmap.inc linux/abi/common/verb_errmap.inc --- linux-2.4.3/abi/common/verb_errmap.inc Thu Jan 1 01:00:00 1970 +++ linux/abi/common/verb_errmap.inc Mon Mar 12 16:34:48 2001 @@ -0,0 +1,129 @@ + +#ifdef CONFIG_ABI_VERBOSE_ERRORS +static char *errmsg[] = { + "No error", + "Operation not permitted", + "No such file or directory", + "No such process", + "Interrupted system call", + "I/O error", + "No such device or address", + "Arg list too long", + "Exec format error", + "Bad file number", + "No child processes", + "Try again", + "Out of memory", + "Permission denied", + "Bad address", + "Block device required", + "Device or resource busy", + "File exists", + "Cross-device link", + "No such device", + "Not a directory", + "Is a directory", + "Invalid argument", + "File table overflow", + "Too many open files", + "Not a typewriter", + "Text file busy", + "File too large", + "No space left on device", + "Illegal seek", + "Read-only file system", + "Too many links", + "Broken pipe", + "Math argument out of domain of func", + "Math result not representable", + "Resource deadlock would occur", + "File name too long", + "No record locks available", + "Function not implemented", + "Directory not empty", + "Too many symbolic links encountered", + "", + "No message of desired type", + "Identifier removed", + "Channel number out of range", + "Level 2 not synchronized", + "Level 3 halted", + "Level 3 reset", + "Link number out of range", + "Protocol driver not attached", + "No CSI structure available", + "Level 2 halted", + "Invalid exchange", + "Invalid request descriptor", + "Exchange full", + "No anode", + "Invalid request code", + "Invalid slot", + "File locking deadlock error", + "Bad font file format", + "Device not a stream", + "No data available", + "Timer expired", + "Out of streams resources", + "Machine is not on the network", + "Package not installed", + "Object is remote", + "Link has been severed", + "Advertise error", + "Srmount error", + "Communication error on send", + "Protocol error", + "Multihop attempted", + "RFS specific error", + "Not a data message", + "Value too large for defined data type", + "Name not unique on network", + "File descriptor in bad state", + "Remote address changed", + "Can not access a needed shared library", + "Accessing a corrupted shared library", + ".lib section in a.out corrupted", + "Attempting to link in too many shared libraries", + "Cannot exec a shared library directly", + "Illegal byte sequence", + "Interrupted system call should be restarted", + "Streams pipe error", + "Too many users", + "Socket operation on non-socket", + "Destination address required", + "Message too long", + "Protocol wrong type for socket", + "Protocol not available", + "Protocol not supported", + "Socket type not supported", + "Operation not supported on transport endpoint", + "Protocol family not supported", + "Address family not supported by protocol", + "Address already in use", + "Cannot assign requested address", + "Network is down", + "Network is unreachable", + "Network dropped connection because of reset", + "Software caused connection abort", + "Connection reset by peer", + "No buffer space available", + "Transport endpoint is already connected", + "Transport endpoint is not connected", + "Cannot send after transport endpoint shutdown", + "Too many references: cannot splice", + "Connection timed out", + "Connection refused", + "Host is down", + "No route to host", + "Operation already in progress", + "Operation now in progress", + "Stale NFS file handle", + "Structure needs cleaning", + "Not a XENIX named type file", + "No XENIX semaphores available", + "Is a named type file", + "Remote I/O error", + "Quota exceeded", +}; + +#endif /* CONFIG_ABI_VERBOSE_ERRORS */ diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/common/wysev386.c linux/abi/common/wysev386.c --- linux-2.4.3/abi/common/wysev386.c Thu Jan 1 01:00:00 1970 +++ linux/abi/common/wysev386.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,226 @@ +/* $Id$ + * + * wysev386.c - wyse386 specific syscalls + * + * Copyright 1994, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * XXX: the name of this file is wrong -- ch + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +int abi_gethostname(char *name, int len) +{ + int error; + char *p; + + down_read(&uts_sem); + error = verify_area(VERIFY_WRITE, name, len); + if (!error) { + --len; + for (p = system_utsname.nodename; *p && len; p++,len--) { + __put_user(*p, name); + name++; + } + __put_user('\0', name); + } + up_read(&uts_sem); + + return error; +} + +EXPORT_SYMBOL(abi_gethostname); + +int abi_getdomainname(char *name, int len) +{ + int error; + char *p; + + down_read(&uts_sem); + error = verify_area(VERIFY_WRITE, name, len); + if (!error) { + --len; + for (p = system_utsname.domainname; *p && len; p++,len--) { + __put_user(*p, name); + name++; + } + __put_user('\0', name); + } + up_read(&uts_sem); + + return error; +} + +EXPORT_SYMBOL(abi_getdomainname); + +int abi_wait3(int *loc) +{ + int pid; + + pid = SYS(wait4)(-1, loc, WNOHANG, 0); + + if(loc) { + int res; + __get_user(res, (unsigned long *) loc); + if ((res & 0xff) == 0x7f) { + int sig = (res >> 8) & 0xff; + sig = current->exec_domain->signal_map[sig]; + res = (res & (~0xff00)) | (sig << 8); + put_user(res, (unsigned long *)loc); + } else if (res && res == (res & 0xff)) { + res = current->exec_domain->signal_map[res & 0x7f]; + put_user(res, (unsigned long *)loc); + } + } + + return pid; +} + +EXPORT_SYMBOL(abi_wait3); + + +/* It would probably be better to remove the statics in linux/net/socket.c + * and go direct to the sock_ calls than via the indirection routine. + */ +int abi_socket(struct pt_regs *regs) +{ + unsigned long v; + + get_user(v, ((unsigned long*)regs->esp)+1); + put_user( + map_value(current->exec_domain->af_map, v, 0), + ((unsigned long *)regs->esp)+1); + get_user(v, ((unsigned long*)regs->esp)+2); + put_user( + map_value(current->exec_domain->socktype_map, v, 0), + ((unsigned long *)regs->esp)+2); + + return SYS(socketcall)(SYS_SOCKET, ((unsigned long *)regs->esp) + 1); +} + +EXPORT_SYMBOL(abi_socket); + +int abi_connect(struct pt_regs *regs) +{ + return SYS(socketcall)(SYS_CONNECT, ((unsigned long *)regs->esp) + 1); +} + +EXPORT_SYMBOL(abi_connect); + +int abi_accept(struct pt_regs *regs) +{ + return SYS(socketcall)(SYS_ACCEPT, ((unsigned long *)regs->esp) + 1); +} + +EXPORT_SYMBOL(abi_accept); + +int abi_send(struct pt_regs *regs) +{ + int err = SYS(socketcall)(SYS_SEND, ((unsigned long *)regs->esp) + 1); + if (err == -EAGAIN) + err = -EWOULDBLOCK; + return err; +} + +EXPORT_SYMBOL(abi_send); + +int abi_recv(struct pt_regs *regs) +{ + int err = SYS(socketcall)(SYS_RECV, ((unsigned long *)regs->esp) + 1); + if (err == -EAGAIN) + err = -EWOULDBLOCK; + return err; +} + +EXPORT_SYMBOL(abi_recv); + + +int abi_bind(struct pt_regs *regs) +{ + return SYS(socketcall)(SYS_BIND, ((unsigned long *)regs->esp) + 1); +} + +EXPORT_SYMBOL(abi_bind); + +int abi_setsockopt(struct pt_regs *regs) +{ + return abi_do_setsockopt(((unsigned long *)regs->esp) + 1); +} + +EXPORT_SYMBOL(abi_setsockopt); + +int abi_listen(struct pt_regs *regs) +{ + return SYS(socketcall)(SYS_LISTEN, ((unsigned long *)regs->esp) + 1); +} + +EXPORT_SYMBOL(abi_listen); + +int abi_getsockopt(struct pt_regs *regs) +{ + return abi_do_getsockopt(((unsigned long *)regs->esp) + 1); +} + +EXPORT_SYMBOL(abi_getsockopt); + +int abi_recvfrom(struct pt_regs *regs) +{ + int err = SYS(socketcall)(SYS_RECVFROM, ((unsigned long *)regs->esp) + 1); + if (err == -EAGAIN) + err = -EWOULDBLOCK; + return err; +} + +EXPORT_SYMBOL(abi_recvfrom); + +int abi_sendto(struct pt_regs *regs) +{ + int err = SYS(socketcall)(SYS_SENDTO, ((unsigned long *)regs->esp) + 1); + if (err == -EAGAIN) + err = -EWOULDBLOCK; + return err; +} + +EXPORT_SYMBOL(abi_sendto); + +int abi_shutdown(struct pt_regs *regs) +{ + return SYS(socketcall)(SYS_SHUTDOWN, ((unsigned long *)regs->esp) + 1); +} + +EXPORT_SYMBOL(abi_shutdown); + +int abi_socketpair(struct pt_regs *regs) +{ + return SYS(socketcall)(SYS_SOCKETPAIR, ((unsigned long *)regs->esp) + 1); +} + +EXPORT_SYMBOL(abi_socketpair); + +int abi_getpeername(struct pt_regs *regs) +{ + return SYS(socketcall)(SYS_GETPEERNAME, ((unsigned long *)regs->esp) + 1); +} + +EXPORT_SYMBOL(abi_getpeername); + +int abi_getsockname(struct pt_regs *regs) +{ + return SYS(socketcall)(SYS_GETSOCKNAME, ((unsigned long *)regs->esp) + 1); +} + +EXPORT_SYMBOL(abi_getsockname); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/solaris/Makefile linux/abi/solaris/Makefile --- linux-2.4.3/abi/solaris/Makefile Thu Jan 1 01:00:00 1970 +++ linux/abi/solaris/Makefile Mon Mar 12 16:34:48 2001 @@ -0,0 +1,16 @@ +# +# Makefile for the kernel ABI code for Solaris emulation +# + +O_TARGET := dummy.o + +list-multi := abi-solaris.o +abi-solaris-objs:= do_solaris.o lfs.o solarisx86.o + +obj-$(CONFIG_ABI_SOLARIS) += abi-solaris.o + + +include $(TOPDIR)/Rules.make + +abi-solaris.o: $(abi-solaris-objs) + $(LD) -r -o $@ $(abi-solaris-objs) diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/solaris/do_solaris.c linux/abi/solaris/do_solaris.c --- linux-2.4.3/abi/solaris/do_solaris.c Thu Jan 1 01:00:00 1970 +++ linux/abi/solaris/do_solaris.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,181 @@ +#include +#include +#include + +#include +#include +#include +#include + +EXPORT_NO_SYMBOLS; + +extern ABI_func svr4_generic_funcs[]; + +static ABI_func Solaris_funcs[] = { + { 0, Ukn ITR(1, "vtrace", "") }, /* 142 */ + { 0, Ukn ITR(1, "fork1", "") }, /* 143 */ + { 0, Ukn ITR(1, "sigtimedwait", "") }, /* 144 */ + { 0, Ukn ITR(1, "lwp_info", "") }, /* 145 */ + { 0, Ukn ITR(1, "yield", "") }, /* 146 */ + { 0, Ukn ITR(1, "lwp_sema_wait", "") }, /* 147 */ + { 0, Ukn ITR(1, "lwp_sema_post", "") }, /* 148 */ + { 0, Ukn ITR(1, "lwp_sema_trywait","") }, /* 149 */ + { 0, Ukn ITR(1, "?", "") }, /* 150 */ + { 0, Ukn ITR(1, "?", "") }, /* 151 */ + { 0, Ukn ITR(1, "modctl", "") }, /* 152 */ + { 0, Ukn ITR(1, "fchroot", "") }, /* 153 */ + { 0, Ukn ITR(1, "utimes", "") }, /* 154 */ + { 0, Ukn ITR(1, "vhangup", "") }, /* 155 */ + { SC(gettimeofday), -2 ITR(0, "gettimeofday", "xx") }, /* 156 */ + { SC(getitimer), -2 ITR(0, "getitimer", "dx") }, /* 157 */ + { SC(setitimer), -3 ITR(0, "setitimer", "dxx") }, /* 158 */ + { 0, Ukn ITR(1, "lwp_create", "") }, /* 159 */ + { 0, Ukn ITR(1, "lwp_exit", "") }, /* 160 */ + { 0, Ukn ITR(1, "lwp_suspend", "") }, /* 161 */ + { 0, Ukn ITR(1, "lwp_continue", "") }, /* 162 */ + { 0, Ukn ITR(1, "lwp_kill", "") }, /* 163 */ + { 0, Ukn ITR(1, "lwp_self", "") }, /* 164 */ + { 0, Ukn ITR(1, "lwp_setprivate","") }, /* 165 */ + { 0, Ukn ITR(1, "lwp_getprivate","") }, /* 166 */ + { 0, Ukn ITR(1, "lwp_wait", "") }, /* 167 */ + { 0, Ukn ITR(1, "lwp_mutex_unlock","") }, /* 168 */ + { 0, Ukn ITR(1, "lwp_mutex_lock","") }, /* 169 */ + { 0, Ukn ITR(1, "lwp_cond_wait", "") }, /* 170 */ + { 0, Ukn ITR(1, "lwp_cond_signal","") }, /* 171 */ + { 0, Ukn ITR(1, "lwp_cond_broadcast","") }, /* 172 */ + { SC(pread), -4 ITR(1, "pread", "dpdd") }, /* 173 */ + { SC(pwrite), -4 ITR(1, "pwrite", "dpdd") }, /* 174 */ + { sol_llseek, Spl ITR(1, "llseek", "dxxd") }, /* 175 */ + { 0, Ukn ITR(1, "inst_sync", "") }, /* 176 */ + { 0, Ukn ITR(1, "?", "") }, /* 177 */ + { 0, Ukn ITR(1, "kaio", "") }, /* 178 */ + { 0, Ukn ITR(1, "?", "") }, /* 179 */ + { 0, Ukn ITR(1, "?", "") }, /* 180 */ + { 0, Ukn ITR(1, "?", "") }, /* 181 */ + { 0, Ukn ITR(1, "?", "") }, /* 182 */ + { 0, Ukn ITR(1, "?", "") }, /* 183 */ + { 0, Ukn ITR(1, "tsolsys", "") }, /* 184 */ + { sol_acl, 4 ITR(1, "acl", "sddp") }, /* 185 */ + { 0, Ukn ITR(1, "auditsys", "") }, /* 186 */ + { 0, Ukn ITR(1, "processor_bind","") }, /* 187 */ + { 0, Ukn ITR(1, "processor_info","") }, /* 188 */ + { 0, Ukn ITR(1, "p_online", "") }, /* 189 */ + { 0, Ukn ITR(1, "sigqueue", "") }, /* 190 */ + { 0, Ukn ITR(1, "clock_gettime", "") }, /* 191 */ + { 0, Ukn ITR(1, "clock_settime", "") }, /* 192 */ + { 0, Ukn ITR(1, "clock_getres", "") }, /* 193 */ + { 0, Ukn ITR(1, "timer_create", "") }, /* 194 */ + { 0, Ukn ITR(1, "timer_delete", "") }, /* 195 */ + { 0, Ukn ITR(1, "timer_settime", "") }, /* 196 */ + { 0, Ukn ITR(1, "timer_gettime", "") }, /* 197 */ + { 0, Ukn ITR(1, "timer_getoverrun","") }, /* 198 */ + { SC(nanosleep), -2 ITR(1, "nanosleep", "pp") }, /* 199 */ + { 0, Ukn ITR(1, "modstat", "") }, /* 200 */ + { 0, Ukn ITR(1, "facl", "") }, /* 201 */ + { SC(setreuid), -2 ITR(1, "setreuid", "dd") }, /* 202 */ + { SC(setregid), -2 ITR(1, "setregid", "dd") }, /* 203 */ + { 0, Ukn ITR(1, "install_utrap", "") }, /* 204 */ + { 0, Ukn ITR(1, "signotify", "") }, /* 205 */ + { 0, Ukn ITR(1, "schedctl", "") }, /* 206 */ + { 0, Ukn ITR(1, "pset", "") }, /* 207 */ + { 0, Ukn ITR(1, "?", "") }, /* 208 */ + { 0, Ukn ITR(1, "resolvepath", "") }, /* 209 */ + { 0, Ukn ITR(1, "signotifywait", "") }, /* 210 */ + { 0, Ukn ITR(1, "lwp_sigredirect","") }, /* 211 */ + { 0, Ukn ITR(1, "lwp_alarm", "") }, /* 212 */ + { sol_getdents64, 3 ITR(0, "getdents64", "dxd") }, /* 213 */ + { sol_mmap64, 7 ITR(1, "mmap64", "pxdddxx")}, /*214 */ + { sol_stat64, 2 ITR(0, "stat64", "sp") }, /* 215 */ + { sol_lstat64, 2 ITR(0, "lstat64", "sp") }, /* 216 */ + { sol_fstat64, 2 ITR(0, "fstat64", "dp") }, /* 217 */ + { 0, Ukn ITR(1, "statvfs64", "") }, /* 218 */ + { 0, Ukn ITR(1, "fstatvfs64", "") }, /* 219 */ + { 0, Ukn ITR(1, "setrlimit64", "") }, /* 220 */ + { 0, Ukn ITR(1, "getrlimit64", "") }, /* 221 */ + { 0, Ukn ITR(1, "pread64", "") }, /* 222 */ + { 0, Ukn ITR(1, "pwrite64", "") }, /* 223 */ + { 0, Ukn ITR(1, "creat64", "") }, /* 224 */ + { sol_open64, 3 ITR(0, "open64", "soo") }, /* 225 */ + { 0, Ukn ITR(1, "rpcsys", "") }, /* 226 */ + { 0, Ukn ITR(1, "?", "") }, /* 227 */ + { 0, Ukn ITR(1, "?", "") }, /* 228 */ + { 0, Ukn ITR(1, "?", "") }, /* 229 */ + { abi_socket, Spl ITR(1, "so_socket", "ddd") }, /* 230 */ + { abi_socketpair, Spl ITR(1, "so_socketpair", "dddx") }, /* 231 */ + { abi_bind, Spl ITR(1, "bind", "dxd") }, /* 232 */ + { abi_listen, Spl ITR(1, "listen", "dd") }, /* 233 */ + { abi_accept, Spl ITR(1, "accept", "dxx") }, /* 234 */ + { abi_connect, Spl ITR(1, "connect", "dxd") }, /* 235 */ + { abi_shutdown, Spl ITR(1, "shutdown", "dd") }, /* 236 */ + { abi_recv, Spl ITR(1, "recv", "dxdd") }, /* 237 */ + { abi_recvfrom, Spl ITR(1, "recvfrom", "dxddxd")}, /* 238 */ + { 0, Ukn ITR(1, "recvmsg", "") }, /* 239 */ + { abi_send, Spl ITR(1, "send", "dxdd") }, /* 240 */ + { 0, Ukn ITR(0, "sendmsg", "") }, /* 241 */ + { abi_sendto, Spl ITR(1, "sendto", "dxddxd")}, /* 242 */ + { abi_getpeername, Spl ITR(1, "getpeername", "dxx") }, /* 243 */ + { abi_getsockname, Spl ITR(1, "getsockname", "") }, /* 244 */ + { abi_getsockopt, Spl ITR(1, "getsockopt", "dddxx")}, /* 245 */ + { abi_setsockopt, Spl ITR(1, "setsockopt", "dddxd")}, /* 246 */ + { 0, Ukn ITR(1, "sockconfig", "") }, /* 247 */ + { 0, Ukn ITR(1, "ntp_gettime", "") }, /* 248 */ + { 0, Ukn ITR(0, "ntp_adjtime", "") }, /* 249 */ + { 0, Ukn ITR(1, "?", "") }, /* 250 */ + { 0, Ukn ITR(1, "?", "") }, /* 251 */ + { 0, Ukn ITR(1, "?", "") }, /* 252 */ + { 0, Ukn ITR(1, "?", "") }, /* 253 */ + { 0, Ukn ITR(1, "?", "") }, /* 254 */ + { 0, Ukn ITR(1, "?", "") } /* 255 */ +}; + + + +static void Solaris_lcall7(int segment, struct pt_regs * regs) +{ + int i = regs->eax & 0xff; + ABI_func *p; + + if (i < 142) + p = &svr4_generic_funcs[i]; + else + p = &Solaris_funcs[i - 142]; + + abi_dispatch(regs, p, 1); +} + +extern struct map_segment svr4_err_map[]; +extern struct map_segment svr4_socktype_map[]; +extern struct map_segment abi_sockopt_map[]; +extern struct map_segment abi_af_map[]; + +extern long linux_to_ibcs_signals[]; +extern long ibcs_to_linux_signals[]; + + +struct exec_domain solaris_exec_domain = { + "Solaris/x86", + Solaris_lcall7, + 13 /* PER_SOLARIS */, 13 /* PER_SOLARIS */, + ibcs_to_linux_signals, + linux_to_ibcs_signals, + svr4_err_map, + svr4_socktype_map, + abi_sockopt_map, + abi_af_map, + THIS_MODULE, + NULL +}; + + +static void __exit solaris_cleanup(void) +{ + unregister_exec_domain(&solaris_exec_domain); +} + +static int __init solaris_init(void) +{ + return register_exec_domain(&solaris_exec_domain); +} + +module_init(solaris_init); +module_exit(solaris_cleanup); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/solaris/lfs.c linux/abi/solaris/lfs.c --- linux-2.4.3/abi/solaris/lfs.c Thu Jan 1 01:00:00 1970 +++ linux/abi/solaris/lfs.c Fri Mar 30 16:13:52 2001 @@ -0,0 +1,301 @@ +/* $Id$ + * lfs.c - Solaris Large File Summit support + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern unsigned short fl_ibcs_to_linux[]; +extern unsigned short fl_ibcs_to_linux[]; + + +int +sol_open64(const char *fname, int flag, int mode) +{ + int error, fd, args[3]; + struct file *file; + mm_segment_t old_fs; + char *p; + struct sockaddr_un addr; + + fd = SYS(open)(fname, map_flags(flag, fl_ibcs_to_linux) | O_LARGEFILE, mode); + if (fd < 0) + return fd; + + /* Sometimes a program may open a pathname which it expects + * to be a named pipe (or STREAMS named pipe) when the + * Linux domain equivalent is a Unix domain socket. (e.g. + * UnixWare uses a STREAMS named pipe /dev/X/Nserver.0 for + * X :0 but Linux uses a Unix domain socket /tmp/.X11-unix/X0) + * It isn't enough just to make the symlink because you cannot + * open() a socket and read/write it. If we spot the error we can + * switch to socket(), connect() and things will likely work + * as expected however. + */ + file = fget(fd); + if (!file) + return fd; /* Huh?!? */ + if (!S_ISSOCK(file->f_dentry->d_inode->i_mode)) { + fput(file); + return fd; + } + fput(file); + + SYS(close)(fd); + args[0] = AF_UNIX; + args[1] = SOCK_STREAM; + args[2] = 0; + old_fs = get_fs(); + set_fs(get_ds()); + fd = SYS(socketcall)(SYS_SOCKET, args); + set_fs(old_fs); + if (fd < 0) + return fd; + + p = getname(fname); + if (IS_ERR(p)) { + SYS(close)(fd); + return PTR_ERR(p); + } + if (strlen(p) >= UNIX_PATH_MAX) { + putname(p); + SYS(close)(fd); + return -E2BIG; + } + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, p); + putname(p); + + args[0] = fd; + args[1] = (int)&addr; + args[2] = sizeof(struct sockaddr_un); + set_fs(get_ds()); + error = SYS(socketcall)(SYS_CONNECT, args); + set_fs(old_fs); + if (error) { + SYS(close)(fd); + return error; + } + + return fd; +} + + +static int +cp_sol_stat64(struct inode *inode, struct sol_stat64 * statbuf) +{ + struct sol_stat64 tmp; + + memset(&tmp, 0, sizeof(struct sol_stat64)); + + /* I don't see why this makes sense for solaris --hch */ + if ((unsigned long)inode->i_ino & 0xffff) + tmp.st_ino = (unsigned long)inode->i_ino & 0xffff; + else + tmp.st_ino = 0xfffe; + + tmp.st_dev = inode->i_dev; + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlink; + tmp.st_uid = inode->i_uid; + tmp.st_gid = inode->i_gid; + tmp.st_rdev = inode->i_rdev; + tmp.st_size = inode->i_size; + tmp.st_atime = inode->i_atime; + tmp.st_mtime = inode->i_mtime; + tmp.st_ctime = inode->i_ctime; + + return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; +} + +int +sol_stat64(char *filename, struct sol_stat64 *statbuf) +{ + struct nameidata nd; + int error; + + error = user_path_walk(filename, &nd); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_sol_stat64(nd.dentry->d_inode, statbuf); + path_release(&nd); + } + return error; +} + +int +sol_lstat64(char *filename, struct sol_stat64 *statbuf) +{ + struct nameidata nd; + int error; + + error = user_path_walk_link(filename, &nd); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_sol_stat64(nd.dentry->d_inode, statbuf); + path_release(&nd); + } + return error; +} + +int +sol_fstat64(unsigned int fd, struct sol_stat64 * statbuf) +{ + struct file *fp; + int err = -EBADF; + + fp = fget(fd); + if (fp) { + struct dentry *dentry = fp->f_dentry; + + err = do_revalidate(dentry); + if (!err) + err = cp_sol_stat64(dentry->d_inode, statbuf); + fput(fp); + } + + return err; +} + + + +/* If/when the readdir function is changed to read multiple entries + * at once this should be updated to take advantage of the fact. + * + * N.B. For Linux the reclen in a dirent is the number of characters + * in the filename, for SCO (at least) reclen is the total size of + * the particular dirent rounded up to the next multiple of 4. The SCO + * behaviour is faithfully emulated here. + * + * XXXX + * We don't truncate long filenames at all when copying. If we meet a + * long filename and the buffer supplied by the application simply isn't + * big enough to hold it we'll return without filling the buffer (i.e + * return 0). The application will see this as a (premature) end of + * directory. Is there a work around for this at all??? + */ +int +sol_getdents64(int fd, char *buf, int nbytes) +{ + int error, here, posn, reclen; + struct file *file; + struct dirent *d; + mm_segment_t old_fs; + + error = verify_area(VERIFY_WRITE, buf, nbytes); + if (error) + return error; + + /* Check the file handle here. This is so we can access the current + * position in the file structure safely without a tedious call + * to sys_lseek that does nothing useful. + */ + file = fget(fd); + if (!file) + return -EBADF; + + d = (struct dirent *)__get_free_page(GFP_KERNEL); + if (!d) { + fput(file); + return -ENOMEM; + } + + error = posn = reclen = 0; + while (posn + reclen < nbytes) { + struct sol_dirent64 tmpbuf; + /* Save the current position and get another dirent */ + here = file->f_pos; + old_fs = get_fs(); + set_fs (get_ds()); + error = SYS(readdir)(fd, d, 1); + set_fs(old_fs); + if (error <= 0) + break; + + /* If it'll fit in the buffer save it otherwise back up + * so it is read next time around. + * Oh, if we're at the beginning of the buffer there's + * no chance that this entry will ever fit so don't + * copy it and don't back off - we'll just pretend it + * isn't here... + */ + reclen = (sizeof(long long) + sizeof(long long) + + sizeof(unsigned short) + d->d_reclen + 1 + + 3) & (~3); + if (posn + reclen <= nbytes) { + tmpbuf.d_off = file->f_pos; + tmpbuf.d_ino = d->d_ino; + tmpbuf.d_off = file->f_pos; + tmpbuf.d_reclen = reclen; + copy_to_user(buf+posn, &tmpbuf, + sizeof(struct sol_dirent64) -1); + copy_to_user(buf+posn+sizeof(struct sol_dirent64)-2, + &d->d_name, d->d_reclen+1); + posn += reclen; + } else if (posn) { + SYS(lseek)(fd, here, 0); + } /* else posn == 0 */ + } + + /* Loose the intermediate buffer. */ + free_page((unsigned long)d); + + fput(file); + + /* If we've put something in the buffer return the byte count + * otherwise return the error status. + */ + return ((posn > 0) ? posn : error); +} + + +int +sol_mmap64(u_int addr, u_int len, int prot, int flags, + int fd, u_int off_hi, u_int off) +{ + loff_t off64 = (off | ((loff_t)off_hi << 32)); + u_long pgoff = (off64 >> PAGE_SHIFT); + struct file *file = NULL; + int error; + + if ((off64 + PAGE_ALIGN(len)) < off64) + return -EINVAL; + + if (!(off64 & ~PAGE_MASK)) + return -EINVAL; + + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + if (!(flags & MAP_ANONYMOUS)) { + if (!(file = fget(fd))) + return -EBADF; + } + + if (!(flags & 0x80000000) && addr) + flags |= MAP_FIXED; + else + flags &= 0x7fffffff; + + down_write(¤t->mm->mmap_sem); + error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + up_write(¤t->mm->mmap_sem); + + if (file) + fput(file); + return (error); +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/solaris/solarisx86.c linux/abi/solaris/solarisx86.c --- linux-2.4.3/abi/solaris/solarisx86.c Thu Jan 1 01:00:00 1970 +++ linux/abi/solaris/solarisx86.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int sol_llseek(struct pt_regs * regs) +{ + unsigned int fd; + unsigned long offset_high, offset_low; + unsigned origin; + long long res; + unsigned int rvalue; + mm_segment_t old_fs; + struct inode *inode; + struct file *file; + get_user(fd, ((unsigned int *)regs->esp)+1); + get_user(offset_low, ((unsigned long *)regs->esp)+2); + get_user(offset_high, ((unsigned long *)regs->esp)+3); + get_user(origin, ((unsigned int *)regs->esp)+4); + + old_fs = get_fs(); + set_fs(get_ds()); + rvalue = SYS(_llseek)(fd,offset_high,offset_low,&res,origin); + set_fs(old_fs); + + if ( rvalue < -ENOIOCTLCMD) { + regs->edx = (res >> 32); + rvalue = (res & 0xffffffff); + } + else if (rvalue == -ESPIPE) { + /* Solaris allows you to seek on a pipe */ + file = fget(fd); + if (file) { + inode = file->f_dentry->d_inode; + if (inode && (S_ISCHR(inode->i_mode) + || S_ISBLK(inode->i_mode))) { + rvalue = 0; + regs->edx = 0; + } + fput(file); + } + } + + return rvalue; +} + +int ibcs_memcntl(unsigned addr, unsigned len, int cmd, unsigned arg, + int attr, int mask) +{ + // printk("ibcs_memcntl being ignored\n"); + return 0; +} + +int sol_acl(char *pathp, int cmd, int nentries, void *aclbufp) +{ + switch (cmd) { + case GETACLCNT: + return 0; + + case GETACL: + return -EIO; + + case SETACL: + return -EPERM; + + default: + return -EINVAL; + } +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/Makefile linux/abi/svr4/Makefile --- linux-2.4.3/abi/svr4/Makefile Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/Makefile Mon Mar 12 16:34:48 2001 @@ -0,0 +1,29 @@ +# +# Makefile for the kernel ABI code which is shared by iBCS, Solaris and UW7 +# Loosely speaking, this is the SVR4 code - so that's the name it's got. +# + +O_TARGET := dummy.o + +objs := isc.o isc_funcs.o vtkbd.o xnx.o +export-objs := funcs.o hrtsys.o ioctl.o ipc.o mmap.o open.o poll.o ptrace.o \ + svr4.o sysconf.o sysfs.o sysinfo.o sysi86.o syslocal.o \ + ulimit.o utsname.o stream.o timod.o xnx_funcs.o xstat.o +list-multi := abi-svr4.o +abi-svr4-objs := $(objs) $(export-objs) + +ifeq ($(CONFIG_ABI_IBCS_SCO),y) +abi-svr4-objs += sco_secureware.o +endif +ifeq ($(CONFIG_ABI_IBCS_WYSE),y) +abi-svr4-objs += wyse_nfs.o wyse_tcp.o +endif + + +obj-$(CONFIG_ABI_SVR4) += abi-svr4.o + + +include $(TOPDIR)/Rules.make + +abi-svr4.o: $(abi-svr4-objs) + $(LD) -r -o $@ $(abi-svr4-objs) diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/funcs.c linux/abi/svr4/funcs.c --- linux-2.4.3/abi/svr4/funcs.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/funcs.c Sun Mar 18 17:28:55 2001 @@ -0,0 +1,587 @@ +/* $Id$ + * funcs.c - iBCS syscall dispatch table + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_ABI_IBCS_SCO +MODULE_PARM(sco_serial, "1-10s"); +MODULE_PARM_DESC(sco_serial, "SCO Serial Number"); +#endif + +extern void iBCS_class_XNX(struct pt_regs *regs); +extern void iBCS_class_ISC(struct pt_regs *regs); + +#ifdef CONFIG_ABI_IBCS_WYSE +extern void iBCS_class_WYSETCP(struct pt_regs *regs); +extern void iBCS_class_WYSENFS(struct pt_regs *regs); +#endif + + +static char type_svr4_to_linux_seg1[] = { + SOCK_DGRAM, + SOCK_STREAM, + 0, + SOCK_RAW, + SOCK_RDM, + SOCK_SEQPACKET +}; +struct map_segment svr4_socktype_map[] = { + /* 1 to 6 are remapped as indicated. Nothing else is valid. */ + { 1, 6, type_svr4_to_linux_seg1 }, + { -1 } +}; + +EXPORT_SYMBOL(svr4_socktype_map); + +/* Map Linux RESTART* values (512,513,514) to EINTR */ +static unsigned char LNX_err_table[] = { + EINTR, EINTR, EINTR +}; + + +/* + * Default Linux to iBCS mapping. + * We could remove some of the long identity mapped runs but at the + * expense of extra comparisons for each mapping at run time... + */ +static unsigned char SVR4_err_table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 45, 78, 46, 89, 93, 90, 90, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 50, 51, 52, 53, 54, 55, 56, 57, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 74, 76, 77, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 91, 92, 94, 95, 96, 97, 98, 99,120,121,122, + 123,124,125,126,127,128,129,130,131,132,133,134,143,144,145,146, + 147,148,149,150, 22,135,137,138,139,140, 28 +}; + + +/* SVR4 (aka the full official iBCS) is the base mapping - no exceptions, + * other than the RESTART* values. + */ +struct map_segment svr4_err_map[] = { + { 0, 0+sizeof(SVR4_err_table)-1, SVR4_err_table }, + { 512, 512+sizeof(LNX_err_table)-1, LNX_err_table }, + { -1 } +}; + +EXPORT_SYMBOL(svr4_err_map); + +ABI_func svr4_generic_funcs[] = { + { abi_syscall, Fast ITR(0, "syscall", "") }, /* 0 */ + { SC(exit), -1 ITR(0, "exit", "d") }, /* 1 */ + { abi_fork, Spl ITR(0, "fork", "") }, /* 2 */ + { abi_read, 3 ITR(0, "read", "dpd") }, /* 3 */ + { SC(write), -3 ITR(0, "write", "dpd") }, /* 4 */ + { svr4_open, 3 ITR(0, "open", "soo") }, /* 5 */ + { SC(close), -1 ITR(0, "close", "d") }, /* 6 */ + { abi_wait, Spl ITR(0, "wait", "xxx") }, /* 7 */ + { SC(creat), -2 ITR(0, "creat", "so") }, /* 8 */ + { SC(link), -2 ITR(0, "link", "ss") }, /* 9 */ + { SC(unlink), -1 ITR(0, "unlink", "s") }, /* 10 */ + { abi_exec, Spl ITR(0, "exec", "sxx") }, /* 11 */ + { SC(chdir), -1 ITR(0, "chdir", "s") }, /* 12 */ + { abi_time, 0 ITR(0, "time", "") }, /* 13 */ + { abi_mknod, 3 ITR(0, "mknod", "soo") }, /* 14 */ + { SC(chmod), -2 ITR(0, "chmod", "so") }, /* 15 */ + { SC(chown), -3 ITR(0, "chown", "sdd") }, /* 16 */ + { abi_brk, 1 ITR(0, "brk/break", "x") }, /* 17 */ + { abi_stat, 2 ITR(0, "stat", "sp") }, /* 18 */ + { abi_lseek, 3 ITR(0, "seek/lseek", "ddd") }, /* 19 */ + { abi_getpid, Spl ITR(0, "getpid", "") }, /* 20 */ + { 0, Ukn ITR(1, "mount", "") }, /* 21 */ + { SC(umount), -1 ITR(0, "umount", "s") }, /* 22 */ + { SC(setuid), -1 ITR(0, "setuid", "d") }, /* 23 */ + { abi_getuid, Spl ITR(0, "getuid", "") }, /* 24 */ + { SC(stime), -1 ITR(0, "stime", "d") }, /* 25 */ + { svr4_ptrace, 4 ITR(0, "ptrace", "xdxx") }, /* 26 */ + { SC(alarm), -1 ITR(0, "alarm", "d") }, /* 27 */ + { abi_fstat, 2 ITR(0, "fstat", "dp") }, /* 28 */ + { SC(pause), -ZERO ITR(0, "pause", "") }, /* 29 */ + { SC(utime), -2 ITR(0, "utime", "xx") }, /* 30 */ + { 0, Ukn ITR(0, "stty", "") }, /* 31 */ + { 0, Ukn ITR(1, "gtty", "") }, /* 32 */ + { SC(access), -2 ITR(0, "access", "so") }, /* 33 */ + { SC(nice), -1 ITR(0, "nice", "d") }, /* 34 */ + { svr4_statfs, 4 ITR(0, "statfs", "spdd") }, /* 35 */ + { SC(sync), -ZERO ITR(0, "sync", "") }, /* 36 */ + { abi_kill, 2 ITR(0, "kill", "dd") }, /* 37 */ + { svr4_fstatfs, 4 ITR(0, "fstatfs", "dpdd") }, /* 38 */ + { abi_procids, Spl ITR(0, "ibcs_procids", "d") }, /* 39 */ + { iBCS_class_XNX, Fast ITR(0, "cxenix", "") }, /* 40 */ + { SC(dup), -1 ITR(0, "dup", "d") }, /* 41 */ + { abi_pipe, Spl ITR(0, "pipe", "") }, /* 42 */ + { SC(times), -1 ITR(0, "times", "p") }, /* 43 */ + { SC(profil), -4 ITR(0, "prof", "xxxx")}, /* 44 */ + { 0, Ukn ITR(1, "lock/plock", "") }, /* 45 */ + { SC(setgid), -1 ITR(0, "setgid", "d") }, /* 46 */ + { abi_getgid, Spl ITR(0, "getgid", "") }, /* 47 */ + { abi_sigfunc, Fast ITR(0, "sigfunc", "xxx") }, /* 48 */ + { svr4_msgsys, Spl ITR(0, "msgsys", "dxddd")}, /* 49 */ + { svr4_sysi86, Spl ITR(0, "sysi86/sys3b", "d") }, /* 50 */ + { SC(acct), -1 ITR(0, "acct/sysacct", "x") }, /* 51 */ + { svr4_shmsys, Fast ITR(0, "shmsys", "ddxo")}, /* 52 */ + { svr4_semsys, Spl ITR(0, "semsys", "dddx")}, /* 53 */ + { svr4_ioctl, Spl ITR(0, "ioctl", "dxx") }, /* 54 */ + { 0, 3 ITR(0, "uadmin", "xxx") }, /* 55 */ + { 0, Ukn ITR(1, "?", "") }, /* 56 */ + { v7_utsname, 1 ITR(0, "utsys", "x") }, /* 57 */ + { SC(fsync), -1 ITR(0, "fsync", "d") }, /* 58 */ + { abi_exec, Spl ITR(0, "execv", "spp") }, /* 59 */ + { SC(umask), -1 ITR(0, "umask", "o") }, /* 60 */ + { SC(chroot), -1 ITR(0, "chroot", "s") }, /* 61 */ + { svr4_fcntl, Spl ITR(0, "fcntl", "dxx") }, /* 62 */ + { svr4_ulimit, 2 ITR(0, "ulimit", "xx") }, /* 63 */ + { 0, Ukn ITR(1, "?", "") }, /* 64 */ + { 0, Ukn ITR(1, "?", "") }, /* 65 */ + { 0, Ukn ITR(1, "?", "") }, /* 66 */ + { 0, Ukn ITR(1, "?", "") }, /* 67 */ + { 0, Ukn ITR(1, "?", "") }, /* 68 */ + { 0, Ukn ITR(1, "?", "") }, /* 69 */ + { 0, Ukn ITR(1, "advfs", "") }, /* 70 */ + { 0, Ukn ITR(1, "unadvfs", "") }, /* 71 */ + { 0, Ukn ITR(1, "rmount", "") }, /* 72 */ + { 0, Ukn ITR(1, "rumount", "") }, /* 73 */ + { 0, Ukn ITR(1, "rfstart", "") }, /* 74 */ + { 0, Ukn ITR(1, "?", "") }, /* 75 */ + { 0, Ukn ITR(1, "rdebug", "") }, /* 76 */ + { 0, Ukn ITR(1, "rfstop", "") }, /* 77 */ + { 0, Ukn ITR(1, "rfsys", "") }, /* 78 */ + { SC(rmdir), -1 ITR(0, "rmdir", "s") }, /* 79 */ + { abi_mkdir, 2 ITR(0, "mkdir", "so") }, /* 80 */ + { svr4_getdents, 3 ITR(0, "getdents", "dxd") }, /* 81 */ + { 0, Ukn ITR(1, "libattach", "") }, /* 82 */ + { 0, Ukn ITR(1, "libdetach", "") }, /* 83 */ + { svr4_sysfs, 3 ITR(0, "sysfs", "dxx") }, /* 84 */ + { svr4_getmsg, Spl ITR(0, "getmsg", "dxxx") }, /* 85 */ + { svr4_putmsg, Spl ITR(0, "putmsg", "dxxd") }, /* 86 */ + { svr4_poll, 3 ITR(0, "poll", "xdd") }, /* 87 */ + { abi_lstat, 2 ITR(0, "lstat", "sp") }, /* 88 */ + { SC(symlink), -2 ITR(0, "symlink", "ss") }, /* 89 */ + { SC(readlink), -3 ITR(0, "readlink", "spd") }, /* 90 */ + { 0, Ukn ITR(0, "svr4_setgroups","dp") }, /* 91 */ + { 0, Ukn ITR(0, "svr4_getgroups","dp") }, /* 92 */ + { SC(fchmod), -2 ITR(0, "fchmod", "do") }, /* 93 */ + { SC(fchown), -3 ITR(0, "fchown", "ddd") }, /* 94 */ + { abi_sigprocmask, 3 ITR(0, "sigprocmask", "dxx") }, /* 95 */ + { abi_sigsuspend, Spl ITR(0, "sigsuspend", "x") }, /* 96 */ + { 0, 2 ITR(1, "sigaltstack", "xx") }, /* 97 */ + { abi_sigaction, 3 ITR(0, "sigaction", "dxx") }, /* 98 */ + { svr4_sigpending, 2 ITR(1, "sigpending", "dp") }, /* 99 */ + { svr4_context, Spl ITR(0, "context", "") }, /* 100 */ + { 0, Ukn ITR(1, "evsys", "") }, /* 101 */ + { 0, Ukn ITR(1, "evtrapret", "") }, /* 102 */ + { abi_statvfs, 2 ITR(0, "statvfs", "sp") }, /* 103 */ + { abi_statvfs, 2 ITR(0, "fstatvfs", "dp") }, /* 104 */ + { iBCS_class_ISC, Fast ITR(0, "sysisc", "") }, /* 105 */ + { 0, Ukn ITR(1, "nfssys", "") }, /* 106 */ + { 0, 4 ITR(0, "waitid", "ddxd") }, /* 107 */ + { 0, 3 ITR(1, "sigsendsys", "ddd") }, /* 108 */ + { svr4_hrtsys, Spl ITR(0, "hrtsys", "xxx") }, /* 109 */ + { 0, 3 ITR(1, "acancel", "dxd") }, /* 110 */ + { 0, Ukn ITR(1, "async", "") }, /* 111 */ + { 0, Ukn ITR(1, "priocntlsys", "") }, /* 112 */ + { svr4_pathconf, 2 ITR(1, "pathconf", "sd") }, /* 113 */ + { 0, 3 ITR(1, "mincore", "xdx") }, /* 114 */ + { svr4_mmap, 6 ITR(0, "mmap", "xxxxdx") },/* 115 */ + { SC(mprotect), -3 ITR(0, "mprotect", "xdx") },/* 116 */ + { SC(munmap), -2 ITR(0, "munmap", "xd") },/* 117 */ + { svr4_fpathconf, 2 ITR(1, "fpathconf", "dd") }, /* 118 */ + { abi_fork, Spl ITR(0, "vfork", "") }, /* 119 */ + { SC(fchdir), -1 ITR(0, "fchdir", "d") }, /* 120 */ + { SC(readv), -3 ITR(0, "readv", "dxd") }, /* 121 */ + { SC(writev), -3 ITR(0, "writev", "dxd") }, /* 122 */ + { svr4_xstat, 3 ITR(0, "xstat", "dsx") }, /* 123 */ + { svr4_lxstat, 3 ITR(0, "lxstat", "dsx") }, /* 124 */ + { svr4_fxstat, 3 ITR(0, "fxstat", "ddx") }, /* 125 */ + { svr4_xmknod, 4 ITR(0, "xmknod", "dsox")}, /* 126 */ + { svr4_syslocal, Spl ITR(0, "syslocal", "d") }, /* 127 */ + { svr4_getrlimit, 2 ITR(0, "setrlimit", "dx") }, /* 128 */ + { svr4_setrlimit, 2 ITR(0, "getrlimit", "dx") }, /* 129 */ + { 0, 3 ITR(1, "lchown", "sdd") }, /* 130 */ + { 0, Ukn ITR(1, "memcntl", "") }, /* 131 */ +#ifdef CONFIG_ABI_XTI + { svr4_getpmsg, 5 ITR(0, "getpmsg", "dxxxx")}, /* 132 */ + { svr4_putpmsg, 5 ITR(0, "putpmsg", "dxxdd")}, /* 133 */ +#else + { 0, 5 ITR(0, "getpmsg", "dxxxx")}, /* 132 */ + { 0, 5 ITR(0, "putpmsg", "dxxdd")}, /* 133 */ +#endif + { SC(rename), -2 ITR(0, "rename", "ss") }, /* 134 */ + { abi_utsname, 1 ITR(0, "uname", "x") }, /* 135 */ + { svr4_setegid, 1 ITR(1, "setegid", "d") }, /* 136 */ + { svr4_sysconfig, 1 ITR(0, "sysconfig", "d") }, /* 137 */ + { 0, Ukn ITR(1, "adjtime", "") }, /* 138 */ + { svr4_sysinfo, 3 ITR(0, "systeminfo", "dsd") }, /* 139 */ + { socksys_syscall, 1 ITR(0, "socksys_syscall","x") }, /* 140 */ + { svr4_seteuid, 1 ITR(1, "seteuid", "d") }, /* 141 */ +}; + +EXPORT_SYMBOL(svr4_generic_funcs); + + +static ABI_func iBCS_funcs[] = { + { 0, Ukn ITR(1, "?", "") }, /* 142 */ + { 0, Ukn ITR(1, "?", "") }, /* 143 */ + { 0, 2 ITR(1, "secsys", "dx") }, /* 144 */ + { 0, 4 ITR(1, "filepriv", "sdxd") }, /* 145 */ + { 0, 3 ITR(1, "procpriv", "dxd") }, /* 146 */ + { 0, 3 ITR(1, "devstat", "sdx") }, /* 147 */ + { 0, 5 ITR(1, "aclipc", "ddddx")}, /* 148 */ + { 0, 3 ITR(1, "fdevstat", "ddx") }, /* 149 */ + { 0, 3 ITR(1, "flvlfile", "ddx") }, /* 150 */ + { 0, 3 ITR(1, "lvlfile", "sdx") }, /* 151 */ + { 0, Ukn ITR(1, "?", "") }, /* 152 */ + { 0, 2 ITR(1, "lvlequal", "xx") }, /* 153 */ + { 0, 2 ITR(1, "lvlproc", "dx") }, /* 154 */ + { 0, Ukn ITR(1, "?", "") }, /* 155 */ + { 0, 4 ITR(1, "lvlipc", "dddx") }, /* 156 */ + { 0, 4 ITR(1, "acl", "sddx") }, /* 157 */ + { 0, Ukn ITR(1, "auditevt", "") }, /* 158 */ + { 0, Ukn ITR(1, "auditctl", "") }, /* 159 */ + { 0, Ukn ITR(1, "auditdmp", "") }, /* 160 */ + { 0, Ukn ITR(1, "auditlog", "") }, /* 161 */ + { 0, Ukn ITR(1, "auditbuf", "") }, /* 162 */ + { 0, 2 ITR(1, "lvldom", "xx") }, /* 163 */ + { 0, Ukn ITR(1, "lvlvfs", "") }, /* 164 */ + { 0, 2 ITR(1, "mkmld", "so") }, /* 165 */ + { 0, Ukn ITR(1, "mlddone", "") }, /* 166 */ + { 0, 2 ITR(0, "secadvise", "xx") }, /* 167 */ + { 0, Ukn ITR(1, "online", "") }, /* 168 */ + { SC(setitimer), -3 ITR(0, "setitimer", "dxx") }, /* 169 */ + { SC(getitimer), -2 ITR(0, "getitimer", "dx") }, /* 170 */ + { SC(gettimeofday), -2 ITR(0, "gettimeofday", "xx") }, /* 171 */ + { SC(settimeofday), -2 ITR(0, "settimeofday", "xx") }, /* 172 */ + { 0, Ukn ITR(1, "lwpcreate", "") }, /* 173 */ + { 0, Ukn ITR(1, "lwpexit", "") }, /* 174 */ + { 0, Ukn ITR(1, "lwpwait", "") }, /* 175 */ + { 0, Ukn ITR(1, "lwpself", "") }, /* 176 */ + { 0, Ukn ITR(1, "lwpinfo", "") }, /* 177 */ + { 0, Ukn ITR(1, "lwpprivate", "") }, /* 178 */ + { 0, Ukn ITR(1, "processorbind", "") }, /* 179 */ + { 0, Ukn ITR(1, "processorexbind","") }, /* 180 */ + { 0, Ukn ITR(1, "", "") }, /* 181 */ + { 0, Ukn ITR(1, "sync_mailbox", "") }, /* 182 */ + { 0, Ukn ITR(1, "prepblock", "") }, /* 183 */ + { 0, Ukn ITR(1, "block", "") }, /* 184 */ + { 0, Ukn ITR(1, "rdblock", "") }, /* 185 */ + { 0, Ukn ITR(1, "unblock", "") }, /* 186 */ + { 0, Ukn ITR(1, "cancelblock", "") }, /* 187 */ + { 0, Ukn ITR(1, "?", "") }, /* 188 */ + { 0, Ukn ITR(1, "pread", "") }, /* 189 */ + { 0, Ukn ITR(1, "pwrite", "") }, /* 190 */ + { SC(truncate), -2 ITR(0, "truncate", "sd") }, /* 191 */ + { SC(ftruncate), -2 ITR(0, "ftruncate", "dd") }, /* 192 */ + { 0, Ukn ITR(1, "lwpkill", "") }, /* 193 */ + { 0, Ukn ITR(1, "sigwait", "") }, /* 194 */ + { 0, Ukn ITR(1, "fork1", "") }, /* 195 */ + { 0, Ukn ITR(1, "forkall", "") }, /* 196 */ + { 0, Ukn ITR(1, "modload", "") }, /* 197 */ + { 0, Ukn ITR(1, "moduload", "") }, /* 198 */ + { 0, Ukn ITR(1, "modpath", "") }, /* 199 */ + { 0, Ukn ITR(1, "modstat", "") }, /* 200 */ + { 0, Ukn ITR(1, "modadm", "") }, /* 201 */ + { 0, Ukn ITR(1, "getksym", "") }, /* 202 */ + { 0, Ukn ITR(1, "lwpsuspend", "") }, /* 203 */ + { 0, Ukn ITR(1, "lwpcontinue", "") }, /* 204 */ + { 0, Ukn ITR(1, "?", "") }, /* 205 */ + { 0, Ukn ITR(1, "?", "") }, /* 206 */ + { 0, Ukn ITR(1, "?", "") }, /* 207 */ + { 0, Ukn ITR(1, "?", "") }, + { 0, Ukn ITR(1, "?", "") }, + { 0, Ukn ITR(1, "?", "") }, + { 0, Ukn ITR(1, "?", "") }, + { 0, Ukn ITR(1, "?", "") }, + { 0, Ukn ITR(1, "?", "") }, +#ifdef CONFIG_ABI_IBCS_WYSE + { iBCS_class_WYSETCP,Fast ITR(1, "?", "") }, +#else + { 0, Fast ITR(1, "?", "") }, +#endif + { 0, Ukn ITR(1, "?", "") } +}; + +#ifdef CONFIG_ABI_IBCS_SCO +static ABI_func SCO_funcs[] = { + { 0, Ukn ITR(1, "?", "") }, /* 88 */ + { sw_security, 6 ITR(0, "security", "dxxxxx")},/* 89 */ + { SC(symlink), -2 ITR(0, "symlink", "ss") }, /* 90 */ + { abi_lstat, 2 ITR(0, "lstat", "sp") }, /* 91 */ + { SC(readlink), -3 ITR(0, "readlink", "spd") }, /* 92 */ + { 0, Ukn ITR(1, "?", "") }, /* 93 */ + { 0, Ukn ITR(1, "?", "") }, /* 94 */ + { 0, Ukn ITR(1, "?", "") } /* 95 */ +}; +#endif + +#ifdef CONFIG_ABI_IBCS_WYSE +static ABI_func WYSE_funcs[] = { + { abi_lstat, 2 ITR(0, "lstat", "sp") }, /* 128 */ + { SC(readlink), -3 ITR(0, "readlink", "spd") }, /* 129 */ + { SC(symlink), -2 ITR(0, "symlink", "ss") }, /* 130 */ + { iBCS_class_WYSETCP,Fast ITR(0, "?", "") }, /* 131 */ + { iBCS_class_WYSENFS,Fast ITR(0, "?", "") }, /* 132 */ + { abi_gethostname, 2 ITR(0, "gethostname", "xd") }, /* 133 */ + { SC(sethostname), -2 ITR(0, "sethostname", "sd") }, /* 134 */ + { abi_getdomainname,2 ITR(0, "getdomainname","xd") }, /* 135 */ + { SC(setdomainname), -2 ITR(0, "setdomainname","sd") }, /* 136 */ + { 0, Ukn ITR(1, "?", "") }, /* 137 */ + { SC(setreuid), -2 ITR(0, "setreuid", "dd") }, /* 138 */ + { SC(setregid), -2 ITR(0, "setregid", "dd") }, /* 139 */ + { 0, Ukn ITR(1, "?", "") }, /* 140 */ + { 0, Ukn ITR(1, "?", "") }, /* 141 */ + { 0, Ukn ITR(1, "?", "") }, /* 142 */ + { 0, Ukn ITR(1, "?", "") } /* 143 */ +}; +#endif + +static void +iBCS_lcall7(int segment, struct pt_regs * regs) +{ + int i = regs->eax & 0xff; + ABI_func *p; + + if (segment == 0x27) { + printk(KERN_ERR "solaris binary slipped into svr4 handler, exiting\n"); + return; + } + +#ifdef CONFIG_ABI_IBCS_WYSE + if (i < 0x88 && i > 0x77 && current->personality == PER_WYSEV386) + p = &WYSE_funcs[i - 0x78]; + else +#endif +#ifdef CONFIG_ABI_IBCS_SCO + if (i < 0x60 && i > 0x57 && current->personality == PER_SCOSVR3) + p = &SCO_funcs[i - 0x58]; + else +#endif + if (i < 142) + p = &svr4_generic_funcs[i]; + else + p = &iBCS_funcs[i - 142]; + + abi_dispatch(regs, p, 1); +} + +extern struct map_segment svr4_err_map[]; +extern struct map_segment svr4_socktype_map[]; +extern struct map_segment abi_sockopt_map[]; +extern struct map_segment abi_af_map[]; + + +long linux_to_ibcs_signals[NSIGNALS+1] = { + 0, + IBCS_SIGHUP, IBCS_SIGINT, IBCS_SIGQUIT, IBCS_SIGILL, + IBCS_SIGTRAP, IBCS_SIGABRT, -1, IBCS_SIGFPE, + IBCS_SIGKILL, IBCS_SIGUSR1, IBCS_SIGSEGV, IBCS_SIGUSR2, + IBCS_SIGPIPE, IBCS_SIGALRM, IBCS_SIGTERM, IBCS_SIGSEGV, + IBCS_SIGCHLD, IBCS_SIGCONT, IBCS_SIGSTOP, IBCS_SIGTSTP, + IBCS_SIGTTIN, IBCS_SIGTTOU, IBCS_SIGURG, IBCS_SIGGXCPU, + IBCS_SIGGXFSZ, IBCS_SIGVTALRM, IBCS_SIGPROF, IBCS_SIGWINCH, + IBCS_SIGIO, IBCS_SIGPWR, -1, -1 +}; + +long ibcs_to_linux_signals[NSIGNALS+1] = { + 0, + SIGHUP, SIGINT, SIGQUIT, SIGILL, + SIGTRAP, SIGIOT, SIGUNUSED, SIGFPE, + SIGKILL, SIGUNUSED, SIGSEGV, SIGUNUSED, + SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, + SIGUSR2, SIGCHLD, SIGPWR, SIGWINCH, + SIGURG, SIGPOLL, SIGSTOP, SIGTSTP, + SIGCONT, SIGTTIN, SIGTTOU, SIGVTALRM, + SIGPROF, SIGXCPU, SIGXFSZ, -1 +}; + +EXPORT_SYMBOL(linux_to_ibcs_signals); +EXPORT_SYMBOL(ibcs_to_linux_signals); + +#ifdef CONFIG_ABI_IBCS_SCO +static long linux_to_sco_signals[NSIGNALS+1] = { + 0, + IBCS_SIGHUP, IBCS_SIGINT, IBCS_SIGQUIT, IBCS_SIGILL, + IBCS_SIGTRAP, IBCS_SIGABRT, -1, IBCS_SIGFPE, + IBCS_SIGKILL, IBCS_SIGUSR1, IBCS_SIGSEGV, IBCS_SIGUSR2, + IBCS_SIGPIPE, IBCS_SIGALRM, IBCS_SIGTERM, IBCS_SIGSEGV, + IBCS_SIGCHLD, IBCS_SIGCONT, IBCS_SIGSTOP, IBCS_SIGTSTP, + IBCS_SIGTTIN, IBCS_SIGTTOU, IBCS_SIGUSR1, IBCS_SIGGXCPU, + IBCS_SIGGXFSZ, IBCS_SIGVTALRM, IBCS_SIGPROF, IBCS_SIGWINCH, + IBCS_SIGIO, IBCS_SIGPWR, -1, -1 +}; + +static long sco_to_linux_signals[NSIGNALS+1] = { + 0, + SIGHUP, SIGINT, SIGQUIT, SIGILL, + SIGTRAP, SIGIOT, SIGUNUSED, SIGFPE, + SIGKILL, SIGUNUSED, SIGSEGV, SIGUNUSED, + SIGPIPE, SIGALRM, SIGTERM, SIGURG, + SIGUSR2, SIGCHLD, SIGPWR, SIGWINCH, + SIGUNUSED, SIGPOLL, SIGSTOP, SIGTSTP, + SIGCONT, SIGTTIN, SIGTTOU, SIGVTALRM, + SIGPROF, SIGXCPU, SIGXFSZ, -1 +}; +#endif + +extern long linux_to_ibcs_signals[]; +extern long ibcs_to_linux_signals[]; + + +#ifdef CONFIG_ABI_IBCS_ISC +static long linux_to_isc_signals[NSIGNALS+1] = { + 0, + IBCS_SIGHUP, IBCS_SIGINT, IBCS_SIGQUIT, IBCS_SIGILL, + IBCS_SIGTRAP, IBCS_SIGABRT, -1, IBCS_SIGFPE, + IBCS_SIGKILL, IBCS_SIGUSR1, IBCS_SIGSEGV, IBCS_SIGUSR2, + IBCS_SIGPIPE, IBCS_SIGALRM, IBCS_SIGTERM, IBCS_SIGSEGV, + IBCS_SIGCHLD, ISC_SIGCONT, ISC_SIGSTOP, ISC_SIGTSTP, + IBCS_SIGTTIN, IBCS_SIGTTOU, IBCS_SIGUSR1, IBCS_SIGGXCPU, + IBCS_SIGGXFSZ, IBCS_SIGVTALRM, IBCS_SIGPROF, IBCS_SIGWINCH, + IBCS_SIGIO, IBCS_SIGPWR, -1, -1 +}; + +static long isc_to_linux_signals[NSIGNALS+1] = { + 0, + SIGHUP, SIGINT, SIGQUIT, SIGILL, + SIGTRAP, SIGIOT, SIGUNUSED, SIGFPE, + SIGKILL, SIGUNUSED, SIGSEGV, SIGUNUSED, + SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, + SIGUSR2, SIGCHLD, SIGPWR, SIGWINCH, + -1, SIGPOLL, SIGCONT, SIGSTOP, + SIGTSTP, SIGTTIN, SIGTTOU, SIGVTALRM, + SIGPROF, SIGXCPU, SIGXFSZ, -1 +}; +#endif /* CONFIG_ABI_IBCS_ISC */ + +#ifdef CONFIG_ABI_XENIX +static long linux_to_xnx_signals[NSIGNALS+1] = { + 0, + IBCS_SIGHUP, IBCS_SIGINT, IBCS_SIGQUIT, IBCS_SIGILL, + IBCS_SIGTRAP, IBCS_SIGABRT, -1, IBCS_SIGFPE, + IBCS_SIGKILL, IBCS_SIGUSR1, IBCS_SIGSEGV, IBCS_SIGUSR2, + IBCS_SIGPIPE, IBCS_SIGALRM, IBCS_SIGTERM, IBCS_SIGSEGV, + IBCS_SIGCHLD, IBCS_SIGCONT, IBCS_SIGSTOP, IBCS_SIGTSTP, + IBCS_SIGTTIN, IBCS_SIGTTOU, IBCS_SIGUSR1, IBCS_SIGGXCPU, + IBCS_SIGGXFSZ, IBCS_SIGVTALRM, IBCS_SIGPROF, IBCS_SIGWINCH, + 20 /*XNX_SIGIO*/, IBCS_SIGPWR, -1, -1 +}; + +static long xnx_to_linux_signals[NSIGNALS+1] = { + 0, + SIGHUP, SIGINT, SIGQUIT, SIGILL, + SIGTRAP, SIGIOT, SIGUNUSED, SIGFPE, + SIGKILL, SIGUNUSED, SIGSEGV, SIGUNUSED, + SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, + SIGUSR2, SIGCHLD, SIGPWR, SIGPOLL, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1 +}; +#endif + +struct exec_domain ibcs_exec_domain = { + name: "iBCS2", + handler: iBCS_lcall7, + pers_low: 1 /* PER_SVR4 */, + pers_high: 2 /* PER_SVR3 */, + signal_map: ibcs_to_linux_signals, + signal_invmap: linux_to_ibcs_signals, + err_map: svr4_err_map, + socktype_map: svr4_socktype_map, + sockopt_map: abi_sockopt_map, + af_map: abi_af_map, + module: THIS_MODULE +}; + +#ifdef CONFIG_ABI_IBCS_SCO +struct exec_domain sco_exec_domain = { + name: "OpenServer", + handler: iBCS_lcall7, + pers_low: 3 /* PER_SCOSVR3 */, + pers_high: 3 /* PER_SCOSVR3 */, + signal_map: sco_to_linux_signals, + signal_invmap: linux_to_sco_signals, + err_map: svr4_err_map, + socktype_map: svr4_socktype_map, + sockopt_map: abi_sockopt_map, + af_map: abi_af_map, + module: THIS_MODULE +}; +#endif + +#ifdef CONFIG_ABI_IBCS_XENIX +struct exec_domain xnx_exec_domain = { + name: "Xenix", + handler: iBCS_lcall7, + pers_low: 7 /* PER_XENIX */, + pers_high: 7 /* PER_XENIX */, + signal_map: xnx_to_linux_signals, + signal_invmap: linux_to_xnx_signals, + err_map: svr4_err_map, + socktype_map: svr4_socktype_map, + sockopt_map: abi_sockopt_map, + af_map: abi_af_map, + module: THIS_MODULE +}; +#endif + +#ifdef CONFIG_ABI_IBCS_ISC +struct exec_domain isc_exec_domain = { + name: "ISC", + handler: iBCS_lcall7, + pers_low: 5 /* PER_ISCR4 */, + pers_high: 5 /* PER_ISCR4 */, + signal_map: isc_to_linux_signals, + signal_invmap: linux_to_isc_signals, + err_map: svr4_err_map, + socktype_map: svr4_socktype_map, + sockopt_map: abi_sockopt_map, + af_map: abi_af_map, + module: THIS_MODULE +}; +#endif + + + +static void __exit +ibcs_cleanup(void) +{ +#ifdef CONFIG_ABI_IBCS_ISC + unregister_exec_domain(&isc_exec_domain); +#endif +#ifdef CONFIG_ABI_IBCS_XENIX + unregister_exec_domain(&xnx_exec_domain); +#endif +#ifdef CONFIG_ABI_IBCS_SCO + unregister_exec_domain(&sco_exec_domain); +#endif + unregister_exec_domain(&ibcs_exec_domain); +} + + +static int __init +ibcs_init(void) +{ + register_exec_domain(&ibcs_exec_domain); +#ifdef CONFIG_ABI_IBCS_SCO + register_exec_domain(&sco_exec_domain); +#endif +#ifdef CONFIG_ABI_IBCS_XENIX + register_exec_domain(&xnx_exec_domain); +#endif +#ifdef CONFIG_ABI_IBCS_ISC + register_exec_domain(&isc_exec_domain); +#endif + return 0; +} + +module_init(ibcs_init); +module_exit(ibcs_cleanup); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/hrtsys.c linux/abi/svr4/hrtsys.c --- linux-2.4.3/abi/svr4/hrtsys.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/hrtsys.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,186 @@ +/* $Id$ + * + * This file contins the emulated SVR4 hrtsys interface + * + * Copyright (C) 1994 Eric Youngdale. + * + * The hrtsys interface is used by SVR4, and is effectively a way of doing + * itimer. I do not know why this is used instead of the regular itimer + * stuff, but it appears to be related to bsd programs/functionality. + * + */ + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + + +struct hrt_time_t { + unsigned long secs; + unsigned long sub_sec; /* Less than one second. */ + unsigned long resolution; /* Resolution of timer */ +}; + +struct hrtcmd { + int cmd; + int clk; + struct hrt_time_t interval; + struct hrt_time_t tod; + int flags; + int error; + int reserved[3]; +}; + +static int +ibcs_hrtcntl (struct pt_regs * regs) +{ + unsigned int param[4]; + struct timeval * tv; + int i, error; + + for (i=0; i<4; i++) + param[i] = get_syscall_parameter (regs, 1+i); + + if (param[0] != 1 || param[1] != 1 || param[2] != 0) + return -EINVAL; + + tv = (struct timeval *) param[3]; + + abi_trace(ABI_TRACE_API, "hrtcntl(0x%lx)\n", (u_long)tv); + + error = verify_area(VERIFY_WRITE, (char *) tv,sizeof *tv); + if (error) + return error; + + return SYS(gettimeofday)(tv, NULL); +} + +static int +ibcs_hrtalarm (struct pt_regs * regs) +{ + struct itimerval get_buffer; + struct hrtcmd * hcmd; + int i, error, cmd, retval, which; + mm_segment_t old_fs = get_fs(); + + i = get_syscall_parameter (regs, 2); + if(i != 1) + return -EINVAL; + + hcmd = (struct hrtcmd *) get_syscall_parameter (regs, 1); + + error = verify_area (VERIFY_WRITE, (char *) hcmd,sizeof *hcmd); + if (error) + return error; + + get_user (cmd, ((unsigned long *) hcmd)); + + /* Now figure out which clock we want to fiddle with */ + get_user (which, ((unsigned long *) hcmd)+1); + + abi_trace(ABI_TRACE_API, "%d hrtalarm(0x%lx %d)", + (u_long)cmd, which); + + switch (which) { + case 4: + which = 2; + break; + case 2: + which = 1; + break; + case 1: + which = 0; + break; + default: + return -EINVAL; + }; + + switch (cmd) { + case 0xc: + if(({long r; get_user(r, ((unsigned long *) hcmd)+4); r;}) != 1000000) + return -EINVAL; + copy_from_user(&get_buffer.it_value, ((unsigned long *) hcmd)+2, + sizeof(struct timeval)); + memset(&get_buffer.it_interval, 0, sizeof(struct timeval)); + set_fs(get_ds()); + retval = SYS(setitimer)(which, &get_buffer, NULL); + set_fs(old_fs); + break; + case 0xd: + set_fs(get_ds()); + retval = SYS(getitimer)(which, &get_buffer); + set_fs(old_fs); + + abi_trace(ABI_TRACE_API, "hrtalarm(d %lx) %lx %lx %lx %lx", + (u_long)hcmd, + get_buffer.it_interval.tv_sec, + get_buffer.it_interval.tv_usec, + get_buffer.it_value.tv_sec, + get_buffer.it_value.tv_usec); + + put_user(1000000, &hcmd->interval.resolution); + copy_to_user(((unsigned long *) hcmd)+2, &get_buffer.it_interval, + sizeof(get_buffer)); + retval = 1; + break; + case 0xf: + if(({long r; get_user(r, ((unsigned long *) hcmd)+4); r;}) != 1000000) + return -EINVAL; + if(({long r; get_user(r, ((unsigned long *) hcmd)+7); r;}) != 1000000) + return -EINVAL; + copy_from_user(&get_buffer.it_value, &hcmd->tod, + sizeof(struct timeval)); + copy_from_user(&get_buffer.it_interval, &hcmd->interval, + sizeof(struct timeval)); + set_fs(get_ds()); + retval = SYS(setitimer)(which, &get_buffer, NULL); + set_fs(old_fs); + break; + case 0x10: + memset(&get_buffer, 0, sizeof(get_buffer)); + set_fs(get_ds()); + retval = SYS(setitimer)(which, &get_buffer, NULL); + set_fs(old_fs); + break; + default: + retval = -EINVAL; + }; + + return retval; +} + +int +svr4_hrtsys (struct pt_regs * regs) +{ + int func, retval; + + func = get_syscall_parameter (regs, 0); + + abi_trace(ABI_TRACE_API, "hrtsys(%d)", func); + + switch (func) { + case 0: + retval = ibcs_hrtcntl(regs); + break; + case 1: + retval = ibcs_hrtalarm(regs); + break; + case 2: + case 3: + default: + retval = -EINVAL; + } + + return retval; +} + +EXPORT_SYMBOL(svr4_hrtsys); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/ioctl.c linux/abi/svr4/ioctl.c --- linux-2.4.3/abi/svr4/ioctl.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/ioctl.c Sun Mar 18 11:54:28 2001 @@ -0,0 +1,1212 @@ +/* $Id$ + * + * This file contains a SYSV compatibe ioctl(2) implementation + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * Written by Drew Sullivan. + * Rewritten by Mike Jagdis. + * + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#ifdef CONFIG_ABI_IBCS_SCO +static int sco_ioctl_tape(int fd, unsigned int func, unsigned long arg); +#endif +static int bsd_ioctl_file(int fd, unsigned int func, void *arg); +static int ibcs_ioctl_tape(int fd, unsigned int func, unsigned long arg); +static int ibcs_ioctl_termios(int fd, unsigned int func, void *arg); +static int ibcs_ioctl_termio(int fd, unsigned int func, void *arg); +extern int abi_ioctl_console(int fd, unsigned int func, void *arg); +extern int abi_ioctl_video(int fd, unsigned int func, void *arg); + +/* do_ioctl() is a meta mapper, that is + it looks up the class of the ioctl and then + dispatchs to lower level routines to handle the + mapping of the actual ioctls +*/ + +static int +do_ioctl(struct pt_regs *regs, int fd, unsigned long ioctl_num, void *arg) +{ + unsigned int class = ioctl_num >> 8; + char class_str[4]; + + switch (class) { + case 0: /* SCO ioctls on the pseudo NFS device probably. */ + return abi_ioctl_socksys(fd, ioctl_num, arg); + + case 'A': /* ??? SCO console keyboard stuff? */ + return -EINVAL; + +#ifdef CONFIG_ABI_IBCS_SCO + case 'm': + return sco_ioctl_tape(fd, ioctl_num, (unsigned long)arg); +#endif + case 't': + if (personality(PER_SVR4)) + return ibcs_ioctl_tape(fd, ioctl_num, (unsigned long)arg); + else + return bsd_ioctl_termios(fd, ioctl_num, arg); + + case 'f': + return bsd_ioctl_file(fd, ioctl_num, arg); + + case 'T': /* xenix ioctl compatibility */ + return ibcs_ioctl_termio(fd, ioctl_num & 0xFF, arg); + + case ('i' << 16) | ('X' << 8): /* iBCS2 POSIX */ + case 'x': /* Pre-iBCS2 POSIX */ + return ibcs_ioctl_termios(fd, ioctl_num & 0xFF, arg); + + case 'C': + case 'c': + return abi_ioctl_console(fd, ioctl_num, arg); + + case ('i' << 16) | ('C' << 8): /* iBCS2 POSIX */ + return abi_ioctl_video(fd, ioctl_num & 0xFF, arg); + + /* SCO 3.2.2 uses ('X'<<8)|1 for access to the video map + * and the 'X' set is also used for synchronous comm + * lines (I think?). SVR4 uses it for tty extensions to + * support hardware flow control and external clocks. + */ + case 'X': + if (personality(PER_SVR4) || personality(PER_SOLARIS)) + return svr4_ioctl_termiox(fd, ioctl_num & 0xFF, arg); + return -EINVAL; + + /* These aren't implemented and are never likely to be as they + * are specific to drivers for obscure hardware. (For those + * that don't know they're the JERQ ioctls. Says it all + * really!) + */ + case 'j': + return -EINVAL; + + /* The 'S' set could also be display mode switch + * ioctls in a SCO 3.2.x x<4 environment. It should + * depend on the descriptor they are applied to. + * According to ISC the Xenix STREAMS ioctls had the + * high bit set on the command to differentiate them + * from mode switch ioctls. Yuk, yuk, yuk... + */ + case 'S': + return svr4_ioctl_stream(regs, fd, ioctl_num & 0x7F, arg); + + /* These are STREAMS socket module ioctls. */ + case 'I': +#if defined(CONFIG_ABI_XTI) + return svr4_ioctl_sockmod(fd, ioctl_num & 0xFF, arg); +#else + return -EINVAL; +#endif + + /* These are SCO ioctls - see vtkd.h */ + case 'v': + case 'K': + return ibcs_ioctl_vtkd(fd, ioctl_num, arg); + + /* EUC ioctls. These are something to do with chararcter + * code set conversions in SVR4. If we don't support + * them the correct thing to do is to return EINVAL. + */ + case 'E'|0x80: + return -EINVAL; + + /* SCO channel mapping. I can't find any documentation + * for this. These are the LD?MAP ioctls defined in + * sys/termio.h and sys/emap.h. They are used by mapchan. + */ + case 'D': + return -EINVAL; + } + + /* If we haven't handled it yet it must be a BSD style ioctl + * with a (possible) argument description in the high word of + * the opcode. + */ + switch (class & 0xff) { + /* From SVR4 as specified in sys/iocomm.h */ + case 'f': + return bsd_ioctl_file(fd, ioctl_num, arg); + + /* BSD or V7 terminal ioctls. */ + case 't': + return bsd_ioctl_termios(fd, ioctl_num, arg); + + /* "Traditional" BSD and Wyse V/386 3.2.1A TCP/IP ioctls. */ + case 's': + case 'r': + case 'i': + return abi_ioctl_socksys(fd, ioctl_num, arg); + + /* SVR3 streams based socket TCP/IP ioctls. + * These are handed over to the standard ioctl + * handler since /dev/socksys is an emulated device + * and front ends any sockets created through it. + * Note that 'S' ioctls without the BSDish argument + * type in the high bytes are STREAMS ioctls and 'I' + * ioctls without the BSDish type in the high bytes + * are the STREAMS socket module ioctls. (see above). + */ + case 'S': + case 'R': + case 'I': + return abi_ioctl_socksys(fd, ioctl_num, arg); + } + + /* If nothing has handled it yet someone may have to do some + * more work... + */ + class_str[0] = class & 0xFF0000 ? (char)((class >> 16) & 0xFF) : '.'; + class_str[1] = class & 0x00FF00 ? (char)((class >> 8) & 0xFF) : '.'; + class_str[2] = class & 0x0000FF ? (char)((class ) & 0xFF) : '.'; + class_str[3] = 0; + + printk(KERN_ERR "iBCS: ioctl(%d, %lx[%s], 0x%lx) unsupported\n", + fd, ioctl_num, class_str, (unsigned long)arg); + + return -EINVAL; +} + + +/* Some of these are used by SVR3/4 too... */ +static int bsd_ioctl_file(int fd, unsigned int func, void *arg) +{ + switch (func) { + case BSD__IOV('f', 1): case BSD__IO('f', 1): /* FIOCLEX */ + FD_SET(fd, current->files->close_on_exec); + return 0; + + case BSD__IOV('f', 2): case BSD__IO('f', 2): /* FIONCLEX */ + FD_CLR(fd, current->files->close_on_exec); + return 0; + + case BSD__IOV('f', 3): case BSD__IO('f', 3): { /* FIORDCHK */ + int error, nbytes; + mm_segment_t old_fs; + + old_fs = get_fs(); + set_fs (get_ds()); + error = SYS(ioctl)(fd, FIONREAD, &nbytes); + set_fs(old_fs); + + return (error <= 0 ? error : nbytes); + } + + case BSD__IOW('f', 123, int): /* FGETOWN */ + return SYS(ioctl)(fd, FIOGETOWN, arg); + + case BSD__IOW('f', 124, int): /* FSETOWN */ + return SYS(ioctl)(fd, FIOSETOWN, arg); + + case BSD__IOW('f', 125, int): /* FIOASYNC */ + return SYS(ioctl)(fd, FIOASYNC, arg); + + case BSD__IOW('f', 126, int): /* FIONBIO */ + return SYS(ioctl)(fd, FIONBIO, arg); + + case BSD__IOR('f', 127, int): /* FIONREAD */ + return SYS(ioctl)(fd, FIONREAD, arg); + } + + printk(KERN_ERR "iBCS: file ioctl 0x%08lx unsupported\n", + (unsigned long)func); + return -EINVAL; +} + +static int svr_to_linux_termio(int fd, int op, struct svr_termio *it) +{ + struct termio t; + mm_segment_t old_fs; + char eof; + unsigned short lflag; + int error; + + error = verify_area(VERIFY_READ, it, sizeof(struct svr_termio)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETA, &t); + set_fs(old_fs); + if (error) + return error; + + /* Save things we may need later. */ + eof = t.c_cc[4]; + lflag = t.c_lflag; + + /* Copy the entire structure then fix up as necessary. */ + copy_from_user(&t, it, sizeof(struct svr_termio)); + + /* If ICANON isn't set then we've been given VMIN in place + * of VEOF. + */ + if (!(t.c_lflag & 0000002)) { + t.c_cc[6] = t.c_cc[4]; + t.c_cc[4] = eof; + } + + if (t.c_cflag & 0100000) /* CRTSFL - SCO only? */ + t.c_cflag |= CRTSCTS; + t.c_cflag &= ~0170000; /* LOBLK|CTSFLOW|RTSFLOW|CRTSFL */ + + set_fs(get_ds()); + error = SYS(ioctl)(fd, op, &t); + set_fs(old_fs); + + return error; +} + +static int linux_to_svr_termio(int fd, struct svr_termio *it) +{ + struct termio t; + mm_segment_t old_fs; + int error; + + error = verify_area(VERIFY_WRITE, it, sizeof(struct svr_termio)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETA, &t); + set_fs(old_fs); + if (error) + return error; + + /* If ICANON isn't set then we substitute VEOF with VMIN. */ + if (!(t.c_lflag & 0000002)) { + t.c_cc[4] = t.c_cc[6]; + } + + /* Copy to the user supplied structure. */ + copy_to_user(it, &t, sizeof(struct svr_termio)); + + return error; +} + + +#ifdef CONFIG_ABI_IBCS_SCO +#define SCO_NCCS (SVR_NCC+5) +struct sco_termios { + unsigned short c_iflag; + unsigned short c_oflag; + unsigned short c_cflag; + unsigned short c_lflag; + char c_line; + unsigned char c_cc[SCO_NCCS]; + char c_ispeed; + char c_ospeed; +}; +static int sco_to_linux_termios(int fd, int op, struct sco_termios *it) +{ + struct termios t; + mm_segment_t old_fs; + unsigned short lflag, r; + char sco_cc[SCO_NCCS]; + int error; + + error = verify_area(VERIFY_READ, it, sizeof(struct sco_termios)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETS, &t); + set_fs(old_fs); + if (error) + return error; + + __get_user(t.c_iflag, &it->c_iflag); + t.c_iflag &= ~0100000; /* DOSMODE */ + + __get_user(t.c_oflag, &it->c_oflag); + + __get_user(t.c_cflag, &it->c_cflag); + if (t.c_cflag & 0100000) /* CRTSFL - SCO only? */ + t.c_cflag |= CRTSCTS; + t.c_cflag &= ~0170000; /* LOBLK|CTSFLOW|RTSFLOW|CRTSFL */ + + lflag = t.c_lflag; + t.c_lflag &= ~0100777; + __get_user(r, &it->c_lflag); + t.c_lflag |= r; + if ((t.c_lflag & 0100000)) + SYS(ioctl)(fd, TIOCEXCL, 0); + else + SYS(ioctl)(fd, TIOCNXCL, 0); + t.c_lflag &= ~0100000; + t.c_lflag |= (t.c_lflag & 0000400) << 7; /* Move IEXTEN */ + t.c_lflag &= ~0000400; + t.c_lflag |= (t.c_lflag & 0001000) >> 1; /* Move TOSTOP */ + t.c_lflag &= ~0001000; + t.c_lflag |= (lflag & 0001000); /* Restore ECHOCTL */ + + __get_user(t.c_line, &it->c_line); /* XXX Map this? */ + + copy_from_user(sco_cc, &it->c_cc, SCO_NCCS); + t.c_cc[0] = sco_cc[0]; + t.c_cc[1] = sco_cc[1]; + t.c_cc[2] = sco_cc[2]; + t.c_cc[3] = sco_cc[3]; + t.c_cc[7] = sco_cc[7]; + t.c_cc[8] = sco_cc[11]; + t.c_cc[9] = sco_cc[12]; + t.c_cc[10] = sco_cc[10]; + t.c_cc[16] = sco_cc[6]; + if (t.c_lflag & ICANON) { + t.c_cc[4] = sco_cc[4]; + t.c_cc[11] = sco_cc[5]; + } else { + t.c_cc[4] = sco_cc[8]; + t.c_cc[5] = sco_cc[5]; + t.c_cc[6] = sco_cc[4]; + t.c_cc[11] = sco_cc[9]; + } + + set_fs(get_ds()); + error = SYS(ioctl)(fd, op, &t); + set_fs(old_fs); + + return error; +} + +static int linux_to_sco_termios(int fd, int op, struct sco_termios *it) +{ + struct termios t; + char sco_cc[SCO_NCCS]; + mm_segment_t old_fs; + int error; + + error = verify_area(VERIFY_WRITE, it, sizeof(struct sco_termios)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, op, &t); + set_fs(old_fs); + if (error) + return error; + + put_user(t.c_iflag & 0017777, &it->c_iflag); + + put_user(t.c_oflag & 0177777, &it->c_oflag); + + if (t.c_cflag & CRTSCTS) + t.c_cflag |= 0100000; /* CRTSFL - SCO only? */ + put_user(t.c_cflag & 0177777, &it->c_cflag); + + t.c_lflag &= ~0001000; + t.c_lflag |= (t.c_lflag & 0000400) << 1; + t.c_lflag &= ~0000400; + t.c_lflag |= (t.c_lflag & 0100000) >> 7; + t.c_lflag &= ~0100000; + put_user(t.c_lflag & 0001777, &it->c_lflag); + + put_user(t.c_line, &it->c_line); /* XXX Map this? */ + + sco_cc[0] = t.c_cc[0]; + sco_cc[1] = t.c_cc[1]; + sco_cc[2] = t.c_cc[2]; + sco_cc[3] = t.c_cc[3]; + sco_cc[6] = t.c_cc[16]; + sco_cc[7] = t.c_cc[7]; + sco_cc[8] = t.c_cc[4]; + sco_cc[9] = t.c_cc[11]; + sco_cc[10] = t.c_cc[10]; + sco_cc[11] = t.c_cc[8]; + sco_cc[12] = t.c_cc[9]; + if (t.c_lflag & ICANON) { + sco_cc[4] = t.c_cc[4]; + sco_cc[5] = t.c_cc[11]; + } else { + sco_cc[4] = t.c_cc[6]; + sco_cc[5] = t.c_cc[5]; + } + + copy_to_user(&it->c_cc, sco_cc, SCO_NCCS); + + return error; +} +#endif /* CONFIG_ABI_IBCS_SCO */ + + +/* XXX This is just copied from SCO above. There are minor differences + * but not in any of the critical flags and non of them overlap - I think. + */ + +static int svr4_to_linux_termios(int fd, int op, struct svr4_termios *it) +{ + struct termios t; + mm_segment_t old_fs; + unsigned short lflag, r; + char svr4_cc[SVR4_NCCS]; + int error; + + error = verify_area(VERIFY_READ, it, sizeof(struct svr4_termios)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETS, &t); + set_fs(old_fs); + if (error) + return error; + + __get_user(t.c_iflag, &it->c_iflag); + t.c_iflag &= ~0100000; /* DOSMODE */ + + __get_user(t.c_oflag, &it->c_oflag); + + __get_user(t.c_cflag, &it->c_cflag); + if (t.c_cflag & 0100000) /* CRTSFL - SCO only? */ + t.c_cflag |= CRTSCTS; + t.c_cflag &= ~0170000; /* LOBLK|CTSFLOW|RTSFLOW|CRTSFL */ + + lflag = t.c_lflag; + t.c_lflag &= ~0100777; + __get_user(r, &it->c_lflag); + t.c_lflag |= r; + if ((t.c_lflag & 0100000)) + SYS(ioctl)(fd, TIOCEXCL, 0); + else + SYS(ioctl)(fd, TIOCNXCL, 0); + t.c_lflag &= ~0100000; + t.c_lflag |= (t.c_lflag & 0000400) << 7; /* Move IEXTEN */ + t.c_lflag &= ~0000400; + t.c_lflag |= (t.c_lflag & 0001000) >> 1; /* Move TOSTOP */ + t.c_lflag &= ~0001000; + t.c_lflag |= (lflag & 0001000); /* Restore ECHOCTL */ + + copy_from_user(svr4_cc, &it->c_cc, SVR4_NCCS); + t.c_cc[0] = svr4_cc[0]; + t.c_cc[1] = svr4_cc[1]; + t.c_cc[2] = svr4_cc[2]; + t.c_cc[3] = svr4_cc[3]; + t.c_cc[7] = svr4_cc[7]; + t.c_cc[8] = svr4_cc[8]; + t.c_cc[9] = svr4_cc[9]; + t.c_cc[10] = svr4_cc[10]; + t.c_cc[12] = svr4_cc[12]; + t.c_cc[13] = svr4_cc[13]; + t.c_cc[14] = svr4_cc[14]; + t.c_cc[15] = svr4_cc[15]; + t.c_cc[16] = svr4_cc[16]; + if (t.c_lflag & ICANON) { + t.c_cc[4] = svr4_cc[4]; + t.c_cc[11] = svr4_cc[5]; + } else { + t.c_cc[5] = svr4_cc[5]; + t.c_cc[6] = svr4_cc[4]; + t.c_cc[11] = svr4_cc[6]; + } + + set_fs(get_ds()); + error = SYS(ioctl)(fd, op, &t); + set_fs(old_fs); + + return error; +} + +static int linux_to_svr4_termios(int fd, int op, struct svr4_termios *it) +{ + struct termios t; + char svr4_cc[SVR4_NCCS]; + mm_segment_t old_fs; + int error; + + error = verify_area(VERIFY_WRITE, it, sizeof(struct svr4_termios)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, op, &t); + set_fs(old_fs); + if (error) + return error; + + put_user(t.c_iflag & 0017777, &it->c_iflag); + + put_user(t.c_oflag & 0177777, &it->c_oflag); + + if (t.c_cflag & CRTSCTS) + t.c_cflag |= 0100000; /* CRTSFL - SCO only? */ + put_user(t.c_cflag & 0177777, &it->c_cflag); + + t.c_lflag &= ~0001000; + t.c_lflag |= (t.c_lflag & 0000400) << 1; + t.c_lflag &= ~0000400; + t.c_lflag |= (t.c_lflag & 0100000) >> 7; + t.c_lflag &= ~0100000; + put_user(t.c_lflag & 0001777, &it->c_lflag); + + svr4_cc[0] = t.c_cc[0]; + svr4_cc[1] = t.c_cc[1]; + svr4_cc[2] = t.c_cc[2]; + svr4_cc[3] = t.c_cc[3]; + svr4_cc[6] = t.c_cc[16]; + svr4_cc[7] = t.c_cc[7]; + svr4_cc[8] = t.c_cc[8]; + svr4_cc[9] = t.c_cc[9]; + svr4_cc[10] = t.c_cc[10]; + svr4_cc[11] = t.c_cc[10]; + svr4_cc[12] = t.c_cc[12]; + svr4_cc[13] = t.c_cc[13]; + svr4_cc[14] = t.c_cc[14]; + svr4_cc[15] = t.c_cc[15]; + if (t.c_lflag & ICANON) { + svr4_cc[4] = t.c_cc[4]; + svr4_cc[5] = t.c_cc[11]; + } else { + svr4_cc[4] = t.c_cc[6]; + svr4_cc[5] = t.c_cc[5]; + } + + copy_to_user(&it->c_cc, svr4_cc, SVR4_NCCS); + + return error; +} + + +static int ibcs_ioctl_termios(int fd, unsigned int func, void *arg) +{ +#ifdef CONFIG_ABI_IBCS_SCO + switch(func) { + case 1: /* XCGETA */ + return linux_to_sco_termios(fd, TCGETS, arg); + case 2: /* XCSETA */ + return sco_to_linux_termios(fd, TCSETS, arg); + case 3: /* XCSETAW */ + return sco_to_linux_termios(fd, TCSETSW, arg); + case 4: /* XCSETAF */ + return sco_to_linux_termios(fd, TCSETSF, arg); + } +#endif + printk(KERN_ERR "iBCS: SCO termios ioctl %d unsupported\n", func); + return -EINVAL; +} + +static int ibcs_ioctl_termio(int fd, unsigned int func, void *arg) +{ + switch(func) { + case 1: /* TCGETA (TIOC|1) */ + return linux_to_svr_termio(fd, arg); + + case 2: /* TCSETA (TIOC|2) */ + return svr_to_linux_termio(fd, TCSETA, arg); + case 3: /* TCSETAW (TIOC|3) */ + return svr_to_linux_termio(fd, TCSETAW, arg); + case 4: /* TCSETAF (TIOC|4) */ + return svr_to_linux_termio(fd, TCSETAF, arg); + + case 5: /* TCSBRK (TIOC|5) */ + return SYS(ioctl)(fd, TCSBRK, arg); + case 6: /* TCXONC (TIOC|6) */ + return SYS(ioctl)(fd, TCXONC, arg); + case 7: /* TCFLSH (TIOC|7) */ + return SYS(ioctl)(fd, TCFLSH, arg); + + /* This group appear in SVR4 but not SVR3 (SCO). */ + case 8: /* TIOCKBON */ + case 9: /* TIOCKBOF */ + case 10: /* KBENABLED */ + return -EINVAL; + + /* This set is used by SVR4 for termios ioctls. */ + case 13: /* TCGETS */ + return linux_to_svr4_termios(fd, TCGETS, arg); + case 14: /* TCSETS */ + return svr4_to_linux_termios(fd, TCSETS, arg); + case 15: /* TCSETSW */ + return svr4_to_linux_termios(fd, TCSETSW, arg); + case 16: /* TCSETSF */ + return svr4_to_linux_termios(fd, TCSETSF, arg); + + /* These two are specific to ISC. */ + case 20: /* TCSETPGRP (TIOC|20) set pgrp of tty */ + return SYS(ioctl)(fd, TIOCSPGRP, arg); + case 21: /* TCGETPGRP (TIOC|21) get pgrp of tty */ + return SYS(ioctl)(fd, TIOCGPGRP, arg); + + case 34: /* TCGETSC (TIOC|34) ioctl for scancodes */ + return 0x04; /* Translates scancode to ascii */ + case 35: /* TCSETSC (TIOC|35) ioctl for scancodes */ + return 0; + + case 103: /* TIOCSWINSZ (TIOC|103) */ + return SYS(ioctl)(fd, TIOCSWINSZ, arg); + case 104: /* TIOCGWINSZ (TIOC|104) */ + return SYS(ioctl)(fd, TIOCGWINSZ, arg); + + case 118: /* TIOCSPGRP (TIOC|118) set pgrp of tty */ + return SYS(ioctl)(fd, TIOCSPGRP, arg); + case 119: /* TIOCGPGRP (TIOC|119) get pgrp of tty */ + return SYS(ioctl)(fd, TIOCGPGRP, arg); + + case 32: /* TCDSET (TIOC|32) */ + case 33: /* RTS_TOG (TIOC|33) 386 - "RTS" toggle define 8A1 protocol */ + + case 120: /* TIOSETSAK (TIOC|120) set SAK sequence for tty */ + case 121: /* TIOGETSAK (TIOC|121) get SAK sequence for tty */ + printk(KERN_ERR "iBCS: termio ioctl %d unimplemented\n", + func); + return -EINVAL; + } + printk(KERN_ERR "iBCS: termio ioctl %d unsupported\n", func); + return -EINVAL; +} + +struct termiox { + unsigned short x_hflag; + unsigned short x_cflag; + unsigned short x_rflag[5]; + unsigned short x_sflag; +}; + +#define RTSXOFF 0x0001 +#define CTSXON 0x0002 + +int svr4_ioctl_termiox(int fd, unsigned int func, void *arg) +{ + struct termios t; + struct termiox tx; + mm_segment_t old_fs; + int error; + + if (func < 1 || func > 4) + return -EINVAL; + + error = verify_area(func == 1 ? VERIFY_WRITE : VERIFY_READ, + arg, sizeof(struct termiox)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETS, &t); + set_fs(old_fs); + if (error) + return error; + + if (func == 1) { /* TCGETX */ + memset(&tx, '\0', sizeof(struct termiox)); + if (t.c_cflag & CRTSCTS) + tx.x_hflag = RTSXOFF|CTSXON; + copy_to_user(arg, &tx, sizeof(struct termiox)); + return 0; + } + + copy_from_user(&tx, arg, sizeof(struct termiox)); + 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) + return -EINVAL; + + if (tx.x_hflag) + t.c_cflag |= CRTSCTS; + else + t.c_cflag &= (~CRTSCTS); + + old_fs = get_fs(); + set_fs(get_ds()); + switch (func) { + case 2: /* TCSETX */ + error = SYS(ioctl)(fd, TCSETS, &t); + break; + case 3: /* TCSETXW */ + error = SYS(ioctl)(fd, TCSETSW, &t); + break; + case 4: /* TCSETXF */ + error = SYS(ioctl)(fd, TCSETSF, &t); + break; + } + set_fs(old_fs); + return error; +} +EXPORT_SYMBOL(svr4_ioctl_termiox); + + +int svr4_ioctl_stream(struct pt_regs *regs, int fd, unsigned int func, void *arg) +{ + struct file *filep; + struct inode *ino; + int error; + + filep = fget(fd); + if (!filep) + return -EBADF; + ino = filep->f_dentry->d_inode; + + if (ino && !ino->i_sock + && MAJOR(ino->i_rdev) == SOCKSYS_MAJOR) { + error = abi_socksys_fd_init(fd, 0, NULL, NULL); + if (error < 0) + return error; + fput(filep); + filep = fget(fd); + if (!filep) + return -EBADF; + ino = filep->f_dentry->d_inode; + } + + switch (func) { + case 001: /* I_NREAD */ + error = verify_area(VERIFY_WRITE, + arg, sizeof(unsigned long)); + if (error) { + fput(filep); + return error; + } +#ifdef CONFIG_ABI_XTI + if (ino->i_sock && MAJOR(ino->i_rdev) == SOCKSYS_MAJOR) + timod_update_socket(fd, filep, regs); + + if (ino->i_sock + && Priv(filep) && Priv(filep)->pfirst) { + put_user(Priv(filep)->pfirst->length, + (unsigned long *)arg); + fput(filep); + return 1; /* at least 1... (FIXME) */ + } +#endif + fput(filep); + error = SYS(ioctl)(fd, TIOCINQ, arg); + if (error == -EINVAL) + return 0; + if (error) + return error; + __get_user(error, (unsigned long *)arg); + return (error == 0 ? 0 : 1); + + case 017: { /* I_PEEK */ +#ifdef CONFIG_ABI_XTI + struct strpeek buf; + + error = verify_area(VERIFY_WRITE, + arg, sizeof(struct strpeek)); + if (error) { + fput(filep); + return error; + } + copy_from_user(&buf, arg, sizeof(buf)); + + if (ino->i_sock && MAJOR(ino->i_rdev) == SOCKSYS_MAJOR) + timod_update_socket(fd, filep, regs); + + if (ino->i_sock + && Priv(filep) && Priv(filep)->pfirst + && (!buf.flags || buf.flags == Priv(filep)->pfirst->pri)) { + int l = buf.ctl.maxlen <= Priv(filep)->pfirst->length + ? buf.ctl.maxlen + : Priv(filep)->pfirst->length; + error = verify_area(VERIFY_WRITE, + buf.ctl.buf, l); + if (error) { + fput(filep); + return error; + } + copy_to_user(buf.ctl.buf, + ((char *)&Priv(filep)->pfirst->type) + + Priv(filep)->offset, l); + put_user(l, &((struct strpeek *)arg)->ctl.len); + if (buf.dat.maxlen >= 0) + put_user(0, &((struct strpeek *)arg)->dat.len); + put_user(Priv(filep)->pfirst->pri, + &((struct strpeek *)arg)->flags); + fput(filep); + return 1; + } + /* FIXME: I think we should also be able to peek + * at data as well? + */ +#endif + fput(filep); + return 0; /* Nothing to peek at. */ + } + } + + fput(filep); + + switch (func) { + case 010: { /* I_STR */ + /* Unpack the ioctl data and forward as a normal + * ioctl. Timeouts are not handled (yet?). + */ + struct strioctl { + int cmd, timeout, len; + char *data; + } it; + + error = verify_area(VERIFY_READ, + arg, sizeof(struct strioctl)); + if (error) + return error; + copy_from_user(&it, arg, sizeof(struct strioctl)); + + abi_trace(ABI_TRACE_STREAMS, + "STREAMS I_STR ioctl(%d, 0x%08lx, 0x%08lx)", + fd, (u_long)it.cmd, (u_long)it.data); + + switch (it.cmd >> 8) { + case 'T':/* timod */ +#ifdef CONFIG_ABI_XTI + return timod_ioctl(regs, + fd, it.cmd & 0xff, + it.data, it.len, + &((struct strioctl *)arg)->len); +#else + return -EINVAL; +#endif + default: + return do_ioctl(regs, fd, it.cmd, it.data); + } + } + + case 002: { /* I_PUSH */ + char *tmp; + + /* Get the name anyway to validate it. */ + tmp = getname(arg); + if (IS_ERR(tmp)) + return PTR_ERR(tmp); + + abi_trace(ABI_TRACE_STREAMS, + "%d STREAMS I_PUSH %s", fd, tmp); + + putname(tmp); + return 0; + } + + case 003: /* I_POP */ + abi_trace(ABI_TRACE_STREAMS, "%d STREAMS I_POP", fd); + return 0; + + case 005: /* I_FLUSH */ + return 0; + + case 013: { /* I_FIND */ + char *tmp; + + /* Get the name anyway to validate it. */ + tmp = getname(arg); + if (IS_ERR(tmp)) + return PTR_ERR(tmp); + + abi_trace(ABI_TRACE_STREAMS, + "%d STREAMS I_FIND %s", fd, tmp); +#ifdef CONFIG_ABI_XTI + if (!strcmp(tmp, "timod")) { + putname(tmp); + return 1; + } +#endif + putname(tmp); + return 0; + } + + /* FIXME: These are bogus. */ + case 011: /* I_SETSIG */ + return SYS(ioctl)(fd, FIOSETOWN, current->pid); + case 012: /* I_GETSIG */ + return SYS(ioctl)(fd, FIOGETOWN, arg); + + case 020: /* I_FDINSERT */ +#ifdef CONFIG_ABI_XTI + return stream_fdinsert(regs, fd, + (struct strfdinsert *)arg); +#else + return -EINVAL; +#endif + + case 004: /* I_LOOK */ + case 006: /* I_SRDOPT */ + case 007: /* I_GRDOPT */ + case 014: /* I_LINK */ + case 015: /* I_UNLINK */ + case 021: /* I_SENDFD */ + case 022: /* I_RECVFD */ + case 023: /* I_SWROPT */ + case 040: /* I_SETCLTIME */ + return 0; /* Lie... */ + case 042: /* I_CANPUT */ + /* Arg is the priority band in question. We only + * support one priority band so arg must be 0. + * If the band is writable we should return 1, if + * the band is flow controlled we should return 0. + */ + if (arg) + return -EINVAL; + + /* FIXME: How can we test if a write would block? */ + return 1; + + case 024: /* I_GWROPT */ + case 025: /* I_LIST */ + case 026: /* I_PLINK */ + case 027: /* I_PUNLINK */ + case 030: /* I_SETEV */ + case 031: /* I_GETEV */ + case 032: /* I_STREV */ + case 033: /* I_UNSTREV */ + case 034: /* I_FLUSHBAND */ + case 035: /* I_CKBAND */ + case 036: /* I_GETBAND */ + case 037: /* I_ATMARK */ + case 041: /* I_GETCLTIME */ + /* Unsupported - drop out. */ + } + printk(KERN_ERR "iBCS: STREAMS ioctl 0%o unsupported\n", func); + return -EINVAL; +} + +EXPORT_SYMBOL(svr4_ioctl_stream); + + +#ifdef CONFIG_ABI_IBCS_SCO +static int sco_ioctl_tape(int fd, unsigned int func, unsigned long arg) +{ + mm_segment_t old_fs; + int error; + struct mtop mtop; + + mtop.mt_count = 1; + + switch (func & 0xff) { + case 1: /* MT_RESET */ + mtop.mt_op = MTRESET; + break; + + case 2: /* MT_RETEN */ + mtop.mt_op = MTRETEN; + break; + + case 3: /* MT_REWIND */ + mtop.mt_op = MTREW; + break; + + case 4: /* MT_ERASE */ + case 23: /* HP_ERASE */ + mtop.mt_op = MTERASE; + break; + + case 6: /* MT_RFM */ + mtop.mt_op = MTFSF; + break; + + case 7: /* MT_WFM */ + mtop.mt_op = MTWEOF; + break; + + case 8: /* MT_LOAD */ + mtop.mt_op = MTLOAD; + break; + + case 9: /* MT_UNLOAD */ + mtop.mt_op = MTOFFL; + break; + + case 19: /* MT_RSM */ + mtop.mt_op = MTFSS; + break; + + case 20: /* MT_WSM */ + mtop.mt_op = MTWSM; + break; + + case 21: /* MT_EOD */ + mtop.mt_op = MTEOM; + break; + + case 24: /* MT_SETBLK */ + mtop.mt_op = MTSETBLK; + mtop.mt_count = arg; + break; + + case 25: /* MT_LOCK */ + mtop.mt_op = MTLOCK; + break; + + case 26: /* MT_UNLOCK */ + mtop.mt_op = MTUNLOCK; + break; + + +#if 0 +/* The following function codes are just copied from the SCO + include file. +*/ + case 0: /* MT_STATUS */ + case 5: /* MT_AMOUNT */ + case 10: /* MT_DSTATUS */ + case 11: /* MT_FORMAT */ + case 12: /* MT_GETHDR */ + case 13: /* MT_PUTHDR */ + case 14: /* MT_GETNEWBB */ + case 15: /* MT_PUTNEWBB */ + case 16: /* MT_GETVTBL */ + case 17: /* MT_PUTVTBL */ + case 18: /* MT_SERVO */ + case 22: /* MT_FORMPART */ + case 38: /* MT_SETANSI */ + case 64: /* MT_REPORT */ +#endif + default: + printk (KERN_ERR "iBCS: SCO tape ioctl func=%d arg=%x unsupported\n", + func & 0xff, (int) arg); + return -EINVAL; + } + + old_fs = get_fs (); + set_fs (get_ds ()); + error = SYS (ioctl) (fd, MTIOCTOP, &mtop); + set_fs (old_fs); + return error; +} +#endif + +static int ibcs_ioctl_tape(int fd, unsigned int func, unsigned long arg) +{ + mm_segment_t old_fs; + int error; + struct mtop mtop; + + mtop.mt_count = 1; + + switch (func & 0xff) { + case 1: /* MT_RETEN */ + mtop.mt_op = MTRETEN; + break; + + case 2: /* MT_REWIND */ + mtop.mt_op = MTREW; + break; + + case 3: /* MT_ERASE */ + mtop.mt_op = MTERASE; + break; + + case 4: /* MT_WFM */ + mtop.mt_op = MTWEOF; + break; + + case 5: /* MT_RESET */ + mtop.mt_op = MTRESET; + break; + + case 7: /* T_SFF */ + mtop.mt_op = MTFSF; + break; + + case 8: /* T_SBF */ + mtop.mt_op = MTBSF; + break; + + case 9: /* T_LOAD */ + mtop.mt_op = MTLOAD; + break; + + case 10: /* MT_UNLOAD */ + mtop.mt_op = MTOFFL; + break; + + case 15: /* T_WRBLKLEN */ + mtop.mt_op = MTLOCK; + mtop.mt_count = arg; + break; + + case 16: /* T_PREVMV */ + mtop.mt_op = MTLOCK; + break; + + case 17: /* T_ALLOMV */ + mtop.mt_op = MTUNLOCK; + break; + + case 20: /* T_EOD */ + mtop.mt_count = arg; + mtop.mt_op = MTEOM; + break; + + case 21: /* T_SSFB */ + mtop.mt_count = arg; + mtop.mt_op = MTBSFM; + break; + + case 22: /* T_SSFF */ + mtop.mt_count = arg; + mtop.mt_op = MTFSFM; + break; + + case 24: /* T_STD */ + mtop.mt_count = arg; + mtop.mt_op = MTSETDENSITY; + break; + +#if 0 + case 6: /* T_STATUS */ + case 14: /* T_RDBLKLEN */ + case 18: /* T_SBB */ + case 19: /* T_SFB */ + case 23: /* T_STS */ +#endif + default: + printk (KERN_ERR "iBCS: SYSV tape ioctl func=%d arg=%x unsupported\n", + func & 0xff, (int) arg); + return -EINVAL; + } + + old_fs = get_fs (); + set_fs (get_ds ()); + error = SYS (ioctl) (fd, MTIOCTOP, &mtop); + set_fs (old_fs); + return error; +} + + +int svr4_ioctl(struct pt_regs * regs) +{ + int fd; + unsigned int ioctl_num; + void *arg; + + fd = (int)get_syscall_parameter (regs, 0); + ioctl_num = (unsigned int)get_syscall_parameter (regs, 1); + arg = (void *)get_syscall_parameter (regs, 2); + return do_ioctl(regs, fd, ioctl_num, arg); +} + +EXPORT_SYMBOL(svr4_ioctl); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/ipc.c linux/abi/svr4/ipc.c --- linux-2.4.3/abi/svr4/ipc.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/ipc.c Fri Mar 30 15:23:46 2001 @@ -0,0 +1,942 @@ +/* $Id$ + * + * Thiss file contains the emulated SYSV IPC impementation + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * Massive work over with a fine tooth comb, lots of rewriting. There + * were a *lot* of bugs in this - mismatched structs that weren't + * mapped, wrong pointers etc. I've tested this version with the + * demo programs from the Wyse V/386 IPC documentation which exercise + * all the functions. I don't have any major IPC using applications + * to test it with - as far as I know... + * + * Original copyright etc. follows: + * + * Copyright (C) 1993,1994 Joe Portman (baron@hebron.connected.com) + * First stab at ibcs shm, sem and msg handlers + * + * NOTE: + * Please contact the author above before blindly making changes + * to this file. You will break things. + * + * 04-15-1994 JLP III + * Still no msgsys, but IPC_STAT now works for shm calls + * Corrected argument order for sys_ipc calls, to accomodate Mike's + * changes, so that we can just call sys_ipc instead of the internal + * sys_* calls for ipc functions. + * Cleaned up translation of perm structures + * tstshm for Oracle now works. + * + * 04-23-1994 JLP III + * Added in msgsys calls, Tested and working + * Added translation for IPC_SET portions of all xxxctl functions. + * Added SHM_LOCK and SHM_UNLOCK to shmsys + * + * 04-28-1994 JLP III + * Special thanks to Brad Pepers for adding in the GETALL and SETALL + * case of semaphores. (pepersb@cuug.ab.ca) + * + */ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +struct ibcs_ipc_perm { + unsigned short uid; /* owner's user id */ + unsigned short gid; /* owner's group id */ + unsigned short cuid; /* creator's user id */ + unsigned short cgid; /* creator's group id */ + unsigned short mode; /* access modes */ + unsigned short seq; /* slot usage sequence number */ + long key; /* key */ +}; + +struct ibcs_ipc_perm_l { + unsigned long uid; /* owner's user id */ + unsigned long gid; /* owner's group id */ + unsigned long cuid; /* creator's user id */ + unsigned long cgid; /* creator's group id */ + unsigned long mode; /* access modes */ + unsigned long seq; /* slot usage sequence number */ + long key; /* key */ + void *ipc_secp; /* security structure pointer */ + long pad[3]; /* reserved */ +}; + +struct ibcs_semid_ds { + struct ibcs_ipc_perm sem_perm; + struct sem *sem_base; + unsigned short sem_nsems; + char __pad[2]; + unsigned long sem_otime; + unsigned long sem_ctime; +}; + +struct ibcs_semid_ds_l { + struct ibcs_ipc_perm_l sem_perm; + struct sem *sem_base; + unsigned short sem_nsems; + char __pad[2]; + unsigned long sem_otime; + unsigned long sem_pad1; + unsigned long sem_ctime; + unsigned long sem_pad2; + unsigned long sem_pad3[4]; +}; + +struct ibcs_shmid_ds { + struct ibcs_ipc_perm shm_perm; /* operation permission struct */ + int shm_segsz; /* size of segment in bytes */ + struct region *__pad1; /* ptr to region structure */ + char __pad2[4]; /* for swap compatibility */ + ushort shm_lpid; /* pid of last shmop */ + ushort shm_cpid; /* pid of creator */ + unsigned short shm_nattch; /* used only for shminfo */ + unsigned short __pad3; + time_t shm_atime; /* last shmat time */ + time_t shm_dtime; /* last shmdt time */ + time_t shm_ctime; /* last change time */ +}; + +struct ibcs_shmid_ds_l { + struct ibcs_ipc_perm_l shm_perm;/* operation permission struct */ + int shm_segsz; /* size of segment in bytes */ + struct region *__pad1; /* ptr to region structure */ + unsigned short shm_lckcnt; /* number of times it is being locked */ + char __pad2[2]; /* for swap compatibility */ + unsigned long shm_lpid; /* pid of last shmop */ + unsigned long shm_cpid; /* pid of creator */ + unsigned long shm_nattch; /* used only for shminfo */ + unsigned long shm_cnattch; + unsigned long shm_atime; /* last shmat time */ + unsigned long shm_pad1; + unsigned long shm_dtime; /* last shmdt time */ + unsigned long shm_pad2; + unsigned long shm_ctime; /* last change time */ + unsigned long shm_pad3; + unsigned long shm_pad4[4]; +}; + +struct ibcs_msqid_ds { + struct ibcs_ipc_perm msg_perm; + struct msg *msg_first; + struct msg *msg_last; + ushort msg_cbytes; + ushort msg_qnum; + ushort msg_qbytes; + ushort msg_lspid; + ushort msg_lrpid; + time_t msg_stime; + time_t msg_rtime; + time_t msg_ctime; +}; + +struct ibcs_msqid_ds_l { + struct ibcs_ipc_perm_l msg_perm; + struct msg *msg_first; + struct msg *msg_last; + unsigned long msg_cbytes; + unsigned long msg_qnum; + unsigned long msg_qbytes; + unsigned long msg_lspid; + unsigned long msg_lrpid; + unsigned long msg_stime; + unsigned long msg_pad1; + unsigned long msg_rtime; + unsigned long msg_pad2; + unsigned long msg_ctime; + unsigned long msg_pad3; + unsigned long msg_pad4[4]; +}; + + +static inline void ip_to_lp(struct ibcs_ipc_perm *ip, struct ipc_perm *lp) +{ + lp->uid = ip->uid; + lp->gid = ip->gid; + lp->cuid = ip->cuid; + lp->cgid = ip->cgid; + lp->mode = ip->mode; + lp->seq = ip->seq; + lp->key = ip->key; +} + +static inline void lp_to_ip(struct ipc_perm *lp, struct ibcs_ipc_perm *ip) +{ + ip->uid = lp->uid; + ip->gid = lp->gid; + ip->cuid = lp->cuid; + ip->cgid = lp->cgid; + ip->mode = lp->mode; + ip->seq = lp->seq; + ip->key = lp->key; +} + +static inline void ip_to_lp_l(struct ibcs_ipc_perm_l *ip, struct ipc_perm *lp) +{ + lp->uid = ip->uid; + lp->gid = ip->gid; + lp->cuid = ip->cuid; + lp->cgid = ip->cgid; + lp->mode = ip->mode; + lp->seq = ip->seq; + lp->key = ip->key; +} + +static inline void lp_to_ip_l(struct ipc_perm *lp, struct ibcs_ipc_perm_l *ip) +{ + ip->uid = lp->uid; + ip->gid = lp->gid; + ip->cuid = lp->cuid; + ip->cgid = lp->cgid; + ip->mode = lp->mode; + ip->seq = lp->seq; + ip->key = lp->key; +} + + +#define U_SEMCTL (0) +#define U_SEMGET (1) +#define U_SEMOP (2) +#define U_SHMLOCK (3) +#define U_SHMUNLOCK (4) + +#define U_IPC_RMID 0 +#define U_IPC_SET 1 +#define U_IPC_STAT 2 +#define U_GETNCNT 3 +#define U_GETPID 4 +#define U_GETVAL 5 +#define U_GETALL 6 +#define U_GETZCNT 7 +#define U_SETVAL 8 +#define U_SETALL 9 +#define U_IPC_RMID_L 10 +#define U_IPC_SET_L 11 +#define U_IPC_STAT_L 12 + +static inline int ibcs_sem_trans(int arg) +{ + switch (arg) { + case U_IPC_RMID: return IPC_RMID; + case U_IPC_SET: return IPC_SET; + case U_IPC_STAT: return IPC_STAT; + case U_GETNCNT: return GETNCNT; + case U_GETPID: return GETPID; + case U_GETVAL: return GETVAL; + case U_GETALL: return GETALL; + case U_GETZCNT: return GETZCNT; + case U_SETVAL: return SETVAL; + case U_SETALL: return SETALL; + case U_IPC_RMID_L: return IPC_RMID; + case U_IPC_SET_L: return U_IPC_SET_L; + case U_IPC_STAT_L: return U_IPC_STAT_L; + } + return -1; +} + +static void isem_to_lsem(struct ibcs_semid_ds *is, struct semid_ds *ls) +{ + ip_to_lp(&is->sem_perm, &ls->sem_perm); + ls->sem_base = is->sem_base; + ls->sem_nsems = is->sem_nsems; + ls->sem_otime = is->sem_otime; + ls->sem_ctime = is->sem_ctime; +} + +static void lsem_to_isem(struct semid_ds *ls, struct ibcs_semid_ds *is) +{ + lp_to_ip(&ls->sem_perm, &is->sem_perm); + is->sem_base = ls->sem_base; + is->sem_nsems = ls->sem_nsems; + is->sem_otime = ls->sem_otime; + is->sem_ctime = ls->sem_ctime; +} + +static void isem_to_lsem_l(struct ibcs_semid_ds_l *is, struct semid_ds *ls) +{ + ip_to_lp_l(&is->sem_perm, &ls->sem_perm); + ls->sem_base = is->sem_base; + ls->sem_nsems = is->sem_nsems; + ls->sem_otime = is->sem_otime; + ls->sem_ctime = is->sem_ctime; +} + +static void lsem_to_isem_l(struct semid_ds *ls, struct ibcs_semid_ds_l *is) +{ + memset(is, 0, sizeof(*is)); + lp_to_ip_l(&ls->sem_perm, &is->sem_perm); + is->sem_base = ls->sem_base; + is->sem_nsems = ls->sem_nsems; + is->sem_otime = ls->sem_otime; + is->sem_ctime = ls->sem_ctime; +} + +int svr4_semsys(struct pt_regs *regs) +{ + int command = get_syscall_parameter (regs, 0); + int arg1, arg2, arg3; + union semun *arg4; + struct semid_ds ls; + union semun lsemun; + mm_segment_t old_fs; + int retval; + + arg1 = get_syscall_parameter (regs, 1); + arg2 = get_syscall_parameter (regs, 2); + arg3 = get_syscall_parameter (regs, 3); + switch (command) { + case U_SEMCTL: + /* XXX - The value for arg4 depends on how union + * passing is implement on this architecture and + * compiler. The following is *only* known to be + * right for Intel (the default else case). + */ +#ifdef __sparc__ + arg4 = (union semun *)get_syscall_parameter (regs, 4); +#else + arg4 = (union semun *)(((unsigned long *) regs->esp) + (5)); +#endif + + abi_trace(ABI_TRACE_API, "semctl: args: %d %d %d %lx", + arg1, arg2, arg3, (u_long)arg4); + + switch (arg3) { + case U_IPC_SET: { + struct ibcs_semid_ds is, *is_p; + + retval = get_user(is_p, (struct ibcs_semid_ds **)&arg4->buf); + if (!retval) + retval = verify_area(VERIFY_WRITE, is_p, sizeof(is)); + if (retval) + return retval; + + copy_from_user(&is, (char *)is_p, sizeof(is)); + isem_to_lsem(&is, &ls); + + lsemun.buf = &ls; + old_fs = get_fs(); + set_fs (get_ds()); + retval = SYS (ipc) (SEMCTL, arg1, arg2, IPC_SET, &lsemun); + set_fs(old_fs); + + lsem_to_isem(&ls, &is); + copy_to_user((char *)is_p, &is, sizeof(is)); + return retval; + } + + case U_IPC_SET_L: { + struct ibcs_semid_ds_l is, *is_p; + + retval = get_user(is_p, (struct ibcs_semid_ds_l **)&arg4->buf); + if (!retval) + retval = verify_area(VERIFY_WRITE, is_p, sizeof(is)); + if (retval) + return retval; + + copy_from_user(&is, (char *)is_p, sizeof(is)); + isem_to_lsem_l(&is, &ls); + + lsemun.buf = &ls; + old_fs = get_fs(); + set_fs (get_ds()); + retval = SYS (ipc) (SEMCTL, arg1, arg2, IPC_SET, &lsemun); + set_fs(old_fs); + + lsem_to_isem_l(&ls, &is); + copy_to_user((char *)is_p, &is, sizeof(is)); + return retval; + } + + case U_IPC_RMID: + case U_IPC_RMID_L: + case U_SETVAL: + case U_GETVAL: + case U_GETPID: + case U_GETNCNT: + case U_GETZCNT: { + int cmd = ibcs_sem_trans(arg3); + return SYS (ipc) (SEMCTL, arg1, arg2, cmd, arg4); + } + + case U_SETALL: + case U_GETALL: { + int cmd = ibcs_sem_trans(arg3); + return SYS (ipc) (SEMCTL, arg1, 0, cmd, arg4); + } + + case U_IPC_STAT: { + struct ibcs_semid_ds is, *is_p; + + retval = get_user(is_p, (struct ibcs_semid_ds **)&arg4->buf); + if (!retval) + retval = verify_area(VERIFY_WRITE, (char *)is_p, sizeof(is)); + if (retval) + return retval; + + lsemun.buf = &ls; + old_fs = get_fs(); + set_fs(get_ds()); + retval = SYS (ipc) (SEMCTL, arg1, 0, IPC_STAT, &lsemun); + set_fs(old_fs); + if (retval < 0) + return retval; + + lsem_to_isem(&ls, &is); + copy_to_user((char *)is_p, &is, sizeof(is)); + return retval; + } + + case U_IPC_STAT_L: { + struct ibcs_semid_ds_l is, *is_p; + + retval = get_user(is_p, (struct ibcs_semid_ds_l **)&arg4->buf); + if (!retval) + retval = verify_area(VERIFY_WRITE, (char *)is_p, sizeof(is)); + if (retval) + return retval; + + lsemun.buf = &ls; + old_fs = get_fs(); + set_fs(get_ds()); + retval = SYS (ipc) (SEMCTL, arg1, 0, IPC_STAT, &lsemun); + set_fs(old_fs); + if (retval < 0) + return retval; + + lsem_to_isem_l(&ls, &is); + copy_to_user((char *)is_p, &is, sizeof(is)); + return retval; + } + + default: + printk(KERN_ERR "%d ibcs_semctl: unsupported command %d\n", + current->pid, arg3); + return -EINVAL; + } + + case U_SEMGET: + abi_trace(ABI_TRACE_API, "semget: args: %d %d %o", + arg1, arg2, arg3); + return SYS(ipc)(SEMGET, arg1, arg2, arg3, 0); + + case U_SEMOP: + if (abi_traced(ABI_TRACE_API)) { + struct sembuf * tp = (struct sembuf *) arg2; + struct sembuf tmp; + int x; + + __abi_trace("semop: args: %d 0x%08lx %d", + arg1, (u_long)arg2, arg3); + + for (x = 0; x < arg3; x++) { + copy_from_user (&tmp, tp, sizeof(tmp)); + __abi_trace("semop args: %d %d 0%o", + tmp.sem_num, + tmp.sem_op, + tmp.sem_flg); + tp++; + } + } + return SYS(ipc)(SEMOP, arg1, arg3, 0, (struct sembuf *)arg2); + } + return -EINVAL; +} + +EXPORT_SYMBOL(svr4_semsys); + + +#define U_SHMAT (0) +#define U_SHMCTL (1) +#define U_SHMDT (2) +#define U_SHMGET (3) + +static void +ishm_to_lshm(struct ibcs_shmid_ds *is, struct shmid_ds *ls) +{ + ip_to_lp(&is->shm_perm, &ls->shm_perm); + ls->shm_segsz = is->shm_segsz; + ls->shm_lpid = is->shm_lpid; + ls->shm_cpid = is->shm_cpid; + ls->shm_nattch = is->shm_nattch; + ls->shm_atime = is->shm_atime; + ls->shm_dtime = is->shm_dtime; + ls->shm_ctime = is->shm_ctime; +} + +static void +lshm_to_ishm(struct shmid_ds *ls, struct ibcs_shmid_ds *is) +{ + lp_to_ip(&ls->shm_perm, &is->shm_perm); + is->shm_segsz = ls->shm_segsz; + is->shm_lpid = ls->shm_lpid; + is->shm_cpid = ls->shm_cpid; + is->shm_nattch = ls->shm_nattch; + is->shm_atime = ls->shm_atime; + is->shm_dtime = ls->shm_dtime; + is->shm_ctime = ls->shm_ctime; +} + +static void +ishm_to_lshm_l(struct ibcs_shmid_ds_l *is, struct shmid_ds *ls) +{ + ip_to_lp_l(&is->shm_perm, &ls->shm_perm); + ls->shm_segsz = is->shm_segsz; + ls->shm_lpid = is->shm_lpid; + ls->shm_cpid = is->shm_cpid; + ls->shm_nattch = is->shm_nattch; + ls->shm_atime = is->shm_atime; + ls->shm_dtime = is->shm_dtime; + ls->shm_ctime = is->shm_ctime; +} + +static void lshm_to_ishm_l(struct shmid_ds * ls, struct ibcs_shmid_ds_l * is) +{ + memset(is, 0, sizeof(*is)); + lp_to_ip_l(&ls->shm_perm, &is->shm_perm); + is->shm_segsz = ls->shm_segsz; + is->shm_lpid = ls->shm_lpid; + is->shm_cpid = ls->shm_cpid; + is->shm_nattch = ls->shm_nattch; + is->shm_atime = ls->shm_atime; + is->shm_dtime = ls->shm_dtime; + is->shm_ctime = ls->shm_ctime; +} + + +int svr4_shmsys(struct pt_regs * regs) +{ + int command = get_syscall_parameter (regs, 0); + int arg1, arg2, arg3; + mm_segment_t old_fs; + long retval = 0; + char *addr = 0; + + arg1 = arg2 = arg3 = 0; + switch (command) { + case U_SHMAT: + case U_SHMCTL: + case U_SHMGET: + arg1 = get_syscall_parameter (regs, 1); + arg2 = get_syscall_parameter (regs, 2); + arg3 = get_syscall_parameter (regs, 3); + break; + case U_SHMDT: + addr = (char *) get_syscall_parameter (regs, 1); + break; + default: + printk(KERN_ERR "%d iBCS: bad SHM command %d\n", + current->pid, command); + retval = -EINVAL; + goto test_exit; + } + + switch (command) { + case U_SHMAT: { +#ifdef IPCCALL + unsigned long raddr; +#endif + abi_trace(ABI_TRACE_API, "shmat: args: %d %x %o", + arg1, arg2, arg3); + /* + * raddr = 0 tells sys_shmat to limit to 2G + * and we are IBCS, no raddr value to return + */ +#ifdef IPCCALL + old_fs = get_fs(); + set_fs(get_ds()); + retval = SYS (ipc) (IPCCALL(1,SHMAT), arg1, arg3, &raddr, (char *) arg2); + set_fs(old_fs); + if (retval >= 0) + retval = raddr; +#else + retval = SYS (ipc) (SHMAT, arg1, arg3, 0, (char *) arg2); +#endif + + abi_trace(ABI_TRACE_API, "shmat: return val is %lx", retval); + goto test_exit; + } + + case U_SHMGET: + abi_trace(ABI_TRACE_API, "shmget: args: %d %x %o", + arg1, arg2, arg3); + + retval = SYS(ipc)(SHMGET, arg1, arg2, arg3, 0); + goto test_exit; + + case U_SHMDT: + abi_trace(ABI_TRACE_API, "shmdt: arg: %lx", + (u_long)addr); + retval = SYS(ipc)(SHMDT, 0, 0, 0, addr); + goto test_exit; + + case U_SHMCTL: + abi_trace(ABI_TRACE_API, "shmctl: args: %d %x %o %d %x", + arg1, arg2, arg3, arg3, arg3); + switch (arg2) { + case U_SHMLOCK: + retval = SYS (ipc) (SHMCTL, arg1, SHM_LOCK, 0, arg3); + goto test_exit; + + case U_SHMUNLOCK: + retval = SYS (ipc) (SHMCTL, arg1, SHM_UNLOCK, 0, arg3); + goto test_exit; + + case U_IPC_SET: { + struct ibcs_shmid_ds is; + struct shmid_ds ls; + + retval = verify_area(VERIFY_WRITE, (char *)arg3, sizeof(is)); + if (retval) + goto test_exit; + + copy_from_user(&is, (char *)arg3, sizeof(is)); + ishm_to_lshm(&is, &ls); + + old_fs = get_fs(); + set_fs (get_ds()); + retval = SYS (ipc) (SHMCTL, arg1, IPC_SET, 0, &ls); + set_fs(old_fs); + if (retval < 0) + goto test_exit; + + lshm_to_ishm(&ls, &is); + copy_to_user((char *)arg3, &is, sizeof(is)); + goto test_exit; + } + + case U_IPC_SET_L: { + struct ibcs_shmid_ds_l is; + struct shmid_ds ls; + + retval = verify_area(VERIFY_WRITE, (char *)arg3, sizeof(is)); + if (retval) + goto test_exit; + + copy_from_user(&is, (char *)arg3, sizeof(is)); + ishm_to_lshm_l(&is, &ls); + + old_fs = get_fs(); + set_fs (get_ds()); + retval = SYS (ipc) (SHMCTL, arg1, IPC_SET, 0, &ls); + set_fs(old_fs); + if (retval < 0) + goto test_exit; + + lshm_to_ishm_l(&ls, &is); + copy_to_user((char *)arg3, &is, sizeof(is)); + goto test_exit; + } + + case U_IPC_RMID: + case U_IPC_RMID_L: + retval = SYS (ipc) (SHMCTL, arg1, IPC_RMID, arg3); + goto test_exit; + + case U_IPC_STAT: { + struct ibcs_shmid_ds is; + struct shmid_ds ls; + + old_fs = get_fs(); + set_fs (get_ds()); + retval = SYS (ipc) (SHMCTL, arg1, IPC_STAT, 0, &ls); + set_fs(old_fs); + if (retval < 0) + goto test_exit; + + lshm_to_ishm(&ls, &is); + retval = copy_to_user((char *)arg3, &is, sizeof(is)) ? -EFAULT : 0; + goto test_exit; + } + + case U_IPC_STAT_L: { + struct ibcs_shmid_ds_l is; + struct shmid_ds ls; + + old_fs = get_fs(); + set_fs (get_ds()); + retval = SYS (ipc) (SHMCTL, arg1, IPC_STAT, 0, &ls); + set_fs(old_fs); + if (retval < 0) + goto test_exit; + + lshm_to_ishm_l(&ls, &is); + retval = copy_to_user((char *)arg3, &is, sizeof(is)) ? -EFAULT : 0; + goto test_exit; + } + + default: + printk(KERN_ERR "%d iBCS: ibcs_shmctl: unsupported command %d\n", + current->pid, arg2); + } + retval = -EINVAL; + goto test_exit; + + default: + __abi_trace("shmsys: command: %x", command); + retval = -EINVAL; + goto test_exit; + } + +test_exit:; + if ((retval < 0) && (retval > -255)) { + set_error (regs, iABI_errors (-retval)); + abi_trace(ABI_TRACE_API, "Error %ld", get_result (regs)); + } else { + clear_error (regs); + set_result (regs, retval); + } + + return 0; +} + +EXPORT_SYMBOL(svr4_shmsys); + + +#define U_MSGGET (0) +#define U_MSGCTL (1) +#define U_MSGRCV (2) +#define U_MSGSND (3) + +static void imsq_to_lmsq(struct ibcs_msqid_ds * im, struct msqid_ds * lm) +{ + ip_to_lp(&im->msg_perm, &lm->msg_perm); + lm->msg_first = im->msg_first; + lm->msg_last = im->msg_last; + lm->msg_cbytes = im->msg_cbytes; + lm->msg_qnum = im->msg_qnum; + lm->msg_qbytes = im->msg_qbytes; + lm->msg_lspid = im->msg_lspid; + lm->msg_lrpid = im->msg_lrpid; + lm->msg_stime = im->msg_stime; + lm->msg_rtime = im->msg_rtime; + lm->msg_ctime = im->msg_ctime; +} + +static void +lmsq_to_imsq(struct msqid_ds *lm, struct ibcs_msqid_ds *im) +{ + lp_to_ip(&lm->msg_perm, &im->msg_perm); + im->msg_first = lm->msg_first; + im->msg_last = lm->msg_last; + im->msg_cbytes = lm->msg_cbytes; + im->msg_qnum = lm->msg_qnum; + im->msg_qbytes = lm->msg_qbytes; + im->msg_lspid = lm->msg_lspid; + im->msg_lrpid = lm->msg_lrpid; + im->msg_stime = lm->msg_stime; + im->msg_rtime = lm->msg_rtime; + im->msg_ctime = lm->msg_ctime; +} + +static void +imsq_to_lmsq_l(struct ibcs_msqid_ds_l *im, struct msqid_ds *lm) +{ + ip_to_lp_l(&im->msg_perm, &lm->msg_perm); + lm->msg_first = im->msg_first; + lm->msg_last = im->msg_last; + lm->msg_cbytes = im->msg_cbytes; + lm->msg_qnum = im->msg_qnum; + lm->msg_qbytes = im->msg_qbytes; + lm->msg_lspid = im->msg_lspid; + lm->msg_lrpid = im->msg_lrpid; + lm->msg_stime = im->msg_stime; + lm->msg_rtime = im->msg_rtime; + lm->msg_ctime = im->msg_ctime; +} + +static void lmsq_to_imsq_l(struct msqid_ds * lm, struct ibcs_msqid_ds_l * im) +{ + memset(im, 0, sizeof(*im)); + lp_to_ip_l(&lm->msg_perm, &im->msg_perm); + im->msg_first = lm->msg_first; + im->msg_last = lm->msg_last; + im->msg_cbytes = lm->msg_cbytes; + im->msg_qnum = lm->msg_qnum; + im->msg_qbytes = lm->msg_qbytes; + im->msg_lspid = lm->msg_lspid; + im->msg_lrpid = lm->msg_lrpid; + im->msg_stime = lm->msg_stime; + im->msg_rtime = lm->msg_rtime; + im->msg_ctime = lm->msg_ctime; +} + +int svr4_msgsys(struct pt_regs * regs) +{ + int command = get_syscall_parameter (regs, 0); + int arg1, arg2, arg4, arg5; + mm_segment_t old_fs; + char *arg3; + int retval; + + arg1 = get_syscall_parameter (regs, 1); + arg2 = get_syscall_parameter (regs, 2); + arg3 = (char *) get_syscall_parameter (regs, 3); + + switch (command) { + /* hard one first */ + case U_MSGCTL: + switch (arg2) { + case U_IPC_SET: { + struct ibcs_msqid_ds im; + struct msqid_ds lm; + + retval = verify_area(VERIFY_WRITE, arg3, sizeof(im)); + if (retval) + return retval; + + copy_from_user(&im, (char *) arg3, sizeof(im)); + imsq_to_lmsq(&im, &lm); + + old_fs = get_fs(); + set_fs (get_ds()); + retval = SYS (ipc) (MSGCTL, arg1, IPC_SET, 0, &lm); + set_fs (old_fs); + + lmsq_to_imsq(&lm, &im); + copy_to_user((char *)arg3, &im, sizeof(im)); + return retval; + } + + case U_IPC_SET_L: { + struct ibcs_msqid_ds_l im; + struct msqid_ds lm; + + retval = verify_area(VERIFY_WRITE, arg3, sizeof(im)); + if (retval) + return retval; + + copy_from_user(&im, (char *) arg3, sizeof(im)); + imsq_to_lmsq_l(&im, &lm); + + old_fs = get_fs(); + set_fs (get_ds()); + retval = SYS (ipc) (MSGCTL, arg1, IPC_SET, 0, &lm); + set_fs (old_fs); + + lmsq_to_imsq_l(&lm, &im); + copy_to_user((char *)arg3, &im, sizeof(im)); + return retval; + } + + case U_IPC_RMID: + case U_IPC_RMID_L: + return SYS (ipc) (MSGCTL, arg1, IPC_RMID, 0, arg3); + + case U_IPC_STAT: { + struct ibcs_msqid_ds im; + struct msqid_ds lm; + + retval = verify_area(VERIFY_WRITE, arg3, sizeof(im)); + if (retval) + return retval; + + old_fs = get_fs(); + set_fs (get_ds()); + retval = SYS (ipc) (MSGCTL, arg1, IPC_STAT, 0, &lm); + set_fs (old_fs); + + if (retval < 0) + return retval; + + lmsq_to_imsq(&lm, &im); + copy_to_user((char *)arg3, &im, sizeof(im)); + return retval; + } + + case U_IPC_STAT_L: { + struct ibcs_msqid_ds_l im; + struct msqid_ds lm; + + retval = verify_area(VERIFY_WRITE, arg3, sizeof(im)); + if (retval) + return retval; + + old_fs = get_fs(); + set_fs (get_ds()); + retval = SYS (ipc) (MSGCTL, arg1, IPC_STAT, 0, &lm); + set_fs (old_fs); + + if (retval < 0) + return retval; + + lmsq_to_imsq_l(&lm, &im); + copy_to_user((char *)arg3, &im, sizeof(im)); + return retval; + } + + default: + printk(KERN_ERR "%d ibcs_msgctl: unsupported command %d\n", + current->pid, arg2); + } + + case U_MSGGET: + return SYS (ipc) (MSGGET, arg1, arg2, 0, 0); + + case U_MSGSND: + arg4 = get_syscall_parameter (regs, 4); + retval = SYS (ipc) (MSGSND, arg1, arg3, arg4, (char *) arg2); + return ((retval > 0) ? 0 : retval); + + case U_MSGRCV: { +#ifdef IPCCALL + arg4 = get_syscall_parameter (regs, 4); + arg5 = get_syscall_parameter (regs, 5); + return SYS(ipc)(IPCCALL(1,MSGRCV), arg1, arg3, arg5, arg2, arg4); +#else +#ifdef __sparc__ + printk(KERN_ERR + "%d Sparc/IBCS: Kludgy U_MSGRCV not implemented\n", + current->pid); + return -EINVAL; +#else /* __sparc__ */ + struct ipc_kludge *scratch; + long old_esp = regs->esp; + + scratch = (struct ipc_kludge *)((regs->esp-1024-sizeof(struct ipc_kludge)) & 0xfffffffc); + regs->esp = (long)scratch; + get_user(arg4, ((unsigned long *) regs->esp) + 5); + get_user(arg5, ((unsigned long *) regs->esp) + 6); + put_user((long)arg2, &scratch->msgp); + put_user((long)arg4, &scratch->msgtyp); + retval = SYS (ipc) (MSGRCV, arg1, arg3, arg5, scratch); + regs->esp = old_esp; + return retval; +#endif /* sparc */ +#endif /* IPCCALL */ + } + + default: + printk(KERN_ERR "%d ibcs_msgctl: unsupported command %d\n", + current->pid, command); + } + return -EINVAL; +} + +EXPORT_SYMBOL(svr4_msgsys); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/isc.c linux/abi/svr4/isc.c --- linux-2.4.3/abi/svr4/isc.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/isc.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,29 @@ +/* $Id$ + * + * This file contains code to enable ISC 4.0 executables (posix setostype) + * + * Copyright (C) 1994 Karl Kiniger (ki@kretz.co.at) + * + * Some changes also done to callmap.inc: readlink, symlink, lstat + * entry point numbers are differing from SYSVr4 + * + */ + +#include +#include + +#include +#include +#include + +#include +#include + + +int +isc_setostype(int arg1) +{ + abi_trace(ABI_TRACE_API, + "sysisc: ISC_SETOSTYPE 0x%x", arg1); + return 0; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/isc_funcs.c linux/abi/svr4/isc_funcs.c --- linux-2.4.3/abi/svr4/isc_funcs.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/isc_funcs.c Fri Mar 30 15:23:46 2001 @@ -0,0 +1,57 @@ +/* $Id$ + * + * The isc syscall dispatcher + * + */ + +#include + +#include + +#include + +#include +#include + +#define SC(name) (void *)__NR_##name + +#define ITR(trace, name, args) ,trace,name,args + +static ABI_func ISC_funcs[] = { + { 0, Ukn ITR(1, "isc_sysisc0", "") }, /* 00 */ + { isc_setostype, 1 ITR(0, "isc_setostype", "d") }, /* 01 */ + { SC(rename), -2 ITR(0, "isc_rename", "ss") }, /* 02 */ + { abi_sigaction, 3 ITR(0, "isc_sigaction", "dxx") }, /* 03 */ + { abi_sigprocmask, 3 ITR(0, "isc_sicprocmask","dxx") }, /* 04 */ + { 0, 1 ITR(0, "isc_sigpending","x") }, /* 05 */ + { SC(getgroups), -2 ITR(0, "isc_getgroups", "dp") }, /* 06 */ + { SC(setgroups), -2 ITR(0, "isc_setgroups", "dp") }, /* 07 */ + { 0, Ukn ITR(1, "pathconf", "") }, /* 08 */ + { 0, Ukn ITR(1, "fpathconf", "") }, /* 09 */ + { ibcs_sysconf, 1 ITR(0, "sysconf", "d") }, /* 10 */ + { SC(waitpid), -3 ITR(0, "isc_waitpid", "dxx") }, /* 11 */ + { SC(setsid), -ZERO ITR(0, "isc_setsid", "") }, /* 12 */ + { SC(setpgid), -2 ITR(0, "isc_setpgid", "dd") }, /* 13 */ + { 0, Ukn ITR(1, "isc_adduser", "") }, /* 14 */ + { 0, Ukn ITR(1, "isc_setuser", "") }, /* 15 */ + { 0, Ukn ITR(1, "isc_sysisc16", "") }, /* 16 */ + { abi_sigsuspend, Spl ITR(0, "isc_sigsuspend","x") }, /* 17 */ + { SC(symlink), -2 ITR(0, "isc_symlink", "ss") }, /* 18 */ + { SC(readlink), -3 ITR(0, "isc_readlink", "spd") }, /* 19 */ + { 0, Ukn ITR(1, "isc_getmajor", "") } /* 20 */ +}; + + +void iBCS_class_ISC(struct pt_regs *regs) { + int i; + + get_user(i, ((unsigned long *)regs->esp)+1); + if (i > 20) { + regs->eax = iABI_errors(-EINVAL); + regs->eflags |= 1; + return; + } + + abi_dispatch(regs, &ISC_funcs[i], 2); + return; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/mmap.c linux/abi/svr4/mmap.c --- linux-2.4.3/abi/svr4/mmap.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/mmap.c Fri Mar 30 16:14:03 2001 @@ -0,0 +1,47 @@ +/* $Id$ + * mmap.c - svr4 mmap(2) emulation + * + * Copyright (c) 1994 Eric Youngdale + * Copyright (c) 2001 Christoph Hellwig + */ + +#include +#include +#include +#include +#include +#include + +int +svr4_mmap(u_int addr, u_int len, int prot, int flags, int fd, u_int off) +{ + struct file * fp = NULL; + int error = -EBADF; + + if (!(flags & MAP_ANONYMOUS)) { + fp = fget(fd); + if (!fp) + goto out; + } + + if (personality(PER_SVR4) && !(flags & 0x80000000) && addr) { + u_long ret; + + down_write(¤t->mm->mmap_sem); + ret = do_mmap(fp, addr, len, prot, flags | MAP_FIXED, off); + up_write(¤t->mm->mmap_sem); + error = (ret == addr ? 0 : (int)ret); + goto put; + } + + down_write(¤t->mm->mmap_sem); + error = do_mmap(fp, addr, len, prot, flags & 0x7fffffff, off); + up_write(¤t->mm->mmap_sem); + +put: + if (fp) + fput(fp); +out: + return (error); +} +EXPORT_SYMBOL(svr4_mmap); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/open.c linux/abi/svr4/open.c --- linux-2.4.3/abi/svr4/open.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/open.c Sun Mar 18 11:54:28 2001 @@ -0,0 +1,475 @@ +/* $Id$ + * open.c - svr4 open(2), statfs(2), fcntl(2) and getdents(2) emulation + * + * Copyright (c) 1993 Joe Portman (baron@hebron.connected.com) + * Copyright (c) 1993, 1994 Drew Sullivan (re-worked for iBCS2) + * Copyright (c) 2000 Christoph Hellwig (rewrote lookup-related code) + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#include +#include +#include + +#include + + +/* ISC (at least) assumes O_CREAT if O_TRUNC is given. This is emulated + * here but is it correct for iBCS in general? Do we care? + */ +unsigned short fl_ibcs_to_linux[] = { + 0x0001, 0x0002, 0x0800, 0x0400, 0x1000, 0x0000, 0x0000, 0x0800, + 0x0040, 0x0240, 0x0080, 0x0100, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +EXPORT_SYMBOL(fl_ibcs_to_linux); + +unsigned short fl_linux_to_ibcs[] = { + 0x0001, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0400, + 0x0800, 0x0200, 0x0008, 0x0004, 0x0010, 0x0000, 0x0000, 0x0000 +}; + +static int +copy_statfs(struct ibcs_statfs *buf, struct statfs *st) +{ + struct ibcs_statfs ibcsstat; + + ibcsstat.f_type = st->f_type; + ibcsstat.f_bsize = st->f_bsize; + ibcsstat.f_frsize = 0; + ibcsstat.f_blocks = st->f_blocks; + ibcsstat.f_bfree = st->f_bfree; + ibcsstat.f_files = st->f_files; + ibcsstat.f_ffree = st->f_ffree; + memset(ibcsstat.f_fname, 0, sizeof(ibcsstat.f_fname)); + memset(ibcsstat.f_fpack, 0, sizeof(ibcsstat.f_fpack)); + + /* Finally, copy it to the user's buffer */ + return copy_to_user(buf, &ibcsstat, sizeof(struct ibcs_statfs)); +} + +int svr4_statfs(const char * path, struct ibcs_statfs * buf, int len, int fstype) +{ + struct ibcs_statfs ibcsstat; + + if (len > (int)sizeof(struct ibcs_statfs)) + return -EINVAL; + + if (!fstype) { + struct nameidata nd; + int error; + + error = user_path_walk(path, &nd); + if (!error) { + struct statfs tmp; + error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); + if (!error && copy_statfs(buf, &tmp)) + error = -EFAULT; + path_release(&nd); + } + + return error; + } + + /* + * Linux can't stat unmounted filesystems so we + * simply lie and claim 500MB of 8GB is free. Sorry. + */ + ibcsstat.f_bsize = 1024; + ibcsstat.f_frsize = 0; + ibcsstat.f_blocks = 8 * 1024 * 1024; /* 8GB */ + ibcsstat.f_bfree = 500 * 1024; /* 100MB */ + ibcsstat.f_files = 60000; + ibcsstat.f_ffree = 50000; + memset(ibcsstat.f_fname, 0, sizeof(ibcsstat.f_fname)); + memset(ibcsstat.f_fpack, 0, sizeof(ibcsstat.f_fpack)); + + /* Finally, copy it to the user's buffer */ + return copy_to_user(buf, &ibcsstat, len) ? -EFAULT : 0; +} + +EXPORT_SYMBOL(svr4_statfs); + +int svr4_fstatfs(unsigned int fd, struct ibcs_statfs * buf, int len, int fstype) +{ + struct ibcs_statfs ibcsstat; + + if (len > (int)sizeof(struct ibcs_statfs)) + return -EINVAL; + + if (!fstype) { + struct file * file; + struct statfs tmp; + int error; + + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); + if (!error && copy_statfs(buf, &tmp)) + error = -EFAULT; + fput(file); + +out: + return error; + } + + /* + * Linux can't stat unmounted filesystems so we + * simply lie and claim 500MB of 8GB is free. Sorry. + */ + ibcsstat.f_bsize = 1024; + ibcsstat.f_frsize = 0; + ibcsstat.f_blocks = 8 * 1024 * 1024; /* 8GB */ + ibcsstat.f_bfree = 500 * 1024; /* 100MB */ + ibcsstat.f_files = 60000; + ibcsstat.f_ffree = 50000; + memset(ibcsstat.f_fname, 0, sizeof(ibcsstat.f_fname)); + memset(ibcsstat.f_fpack, 0, sizeof(ibcsstat.f_fpack)); + + /* Finally, copy it to the user's buffer */ + return copy_to_user(buf, &ibcsstat, len) ? -EFAULT : 0; +} + +EXPORT_SYMBOL(svr4_fstatfs); + + +int svr4_open(const char *fname, int flag, int mode) +{ +#ifdef __sparc__ + return SYS(open)(fname, map_flags(flag, fl_ibcs_to_linux), mode); +#else + int error, fd, args[3]; + struct file *file; + mm_segment_t old_fs; + char *p; + struct sockaddr_un addr; + + fd = SYS(open)(fname, map_flags(flag, fl_ibcs_to_linux), mode); + if (fd < 0) + return fd; + + /* Sometimes a program may open a pathname which it expects + * to be a named pipe (or STREAMS named pipe) when the + * Linux domain equivalent is a Unix domain socket. (e.g. + * UnixWare uses a STREAMS named pipe /dev/X/Nserver.0 for + * X :0 but Linux uses a Unix domain socket /tmp/.X11-unix/X0) + * It isn't enough just to make the symlink because you cannot + * open() a socket and read/write it. If we spot the error we can + * switch to socket(), connect() and things will likely work + * as expected however. + */ + file = fget(fd); + if (!file) + return fd; /* Huh?!? */ + if (!S_ISSOCK(file->f_dentry->d_inode->i_mode)) { + fput(file); + return fd; + } + fput(file); + + SYS(close)(fd); + args[0] = AF_UNIX; + args[1] = SOCK_STREAM; + args[2] = 0; + old_fs = get_fs(); + set_fs(get_ds()); + fd = SYS(socketcall)(SYS_SOCKET, args); + set_fs(old_fs); + if (fd < 0) + return fd; + + p = getname(fname); + if (IS_ERR(p)) { + SYS(close)(fd); + return PTR_ERR(p); + } + if (strlen(p) >= UNIX_PATH_MAX) { + putname(p); + SYS(close)(fd); + return -E2BIG; + } + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, p); + putname(p); + + args[0] = fd; + args[1] = (int)&addr; + args[2] = sizeof(struct sockaddr_un); + set_fs(get_ds()); + error = SYS(socketcall)(SYS_CONNECT, args); + set_fs(old_fs); + if (error) { + SYS(close)(fd); + return error; + } + + return fd; +#endif +} + +EXPORT_SYMBOL(svr4_open); + + +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1)) + +struct svr4_getdents_callback { + struct dirent * current_dir; + struct dirent * previous; + int count; + int error; +}; + +static int svr4_filldir(void * __buf, const char * name, int namlen, off_t offset, + ino_t ino, unsigned int d_type) +{ + struct dirent * dirent; + struct svr4_getdents_callback * buf = (struct svr4_getdents_callback *) __buf; + int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); + + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; + + dirent = buf->previous; + if (dirent) + put_user(offset, &dirent->d_off); + dirent = buf->current_dir; + buf->previous = dirent; + + if (current->personality & SHORT_INODE) { + /* read() on a directory only handles + * short inodes but cannot use 0 as that + * indicates an empty directory slot. + * Therefore stat() must also fold + * inode numbers avoiding 0. Which in + * turn means that getdents() must fold + * inodes avoiding 0 - if the program + * was built in a short inode environment. + * If we have short inodes in the dirent + * we also have a two byte pad so we + * can let the high word fall in the pad. + * This makes it a little more robust if + * we guessed the inode size wrong. + */ + if (!((unsigned long)dirent->d_ino & 0xffff)) + dirent->d_ino = 0xfffffffe; + } + + put_user(ino, &dirent->d_ino); + put_user(reclen, &dirent->d_reclen); + copy_to_user(dirent->d_name, name, namlen); + put_user(0, dirent->d_name + namlen); + ((char *) dirent) += reclen; + buf->current_dir = dirent; + buf->count -= reclen; + return 0; +} + + + +int svr4_getdents(int fd, char *dirent, int count) +{ + struct file * file; + struct dirent * lastdirent; + struct svr4_getdents_callback buf; + int error; + + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + + buf.current_dir = (struct dirent *) dirent; + buf.previous = NULL; + buf.count = count; + buf.error = 0; + error = vfs_readdir(file, svr4_filldir, &buf); + if (error < 0) + goto out_putf; + error = buf.error; + lastdirent = buf.previous; + if (lastdirent) { + put_user(file->f_pos, &lastdirent->d_off); + error = count - buf.count; + } + +out_putf: + fput(file); + +out: + return error; +} + +EXPORT_SYMBOL(svr4_getdents); + +struct ibcs_flock { + short l_type; /* numbers don't match */ + short l_whence; + off_t l_start; + off_t l_len; /* 0 means to end of file */ + short l_sysid; + short l_pid; +}; + + +int svr4_fcntl(struct pt_regs *regs) +{ + int arg1, arg2, arg3; + int error, retval; + +#ifndef __sparc__ + error = verify_area(VERIFY_READ, + ((unsigned long *)regs->esp)+1, + 3*sizeof(long)); + if (error) + return error; +#endif /* __sparc__ */ + arg1 = get_syscall_parameter (regs, 0); + arg2 = get_syscall_parameter (regs, 1); + arg3 = get_syscall_parameter (regs, 2); + + switch (arg2) { + /* These match the Linux commands. */ + case 0: /* F_DUPFD */ + case 1: /* F_GETFD */ + case 2: /* F_SETFD */ + return SYS(fcntl)(arg1, arg2, arg3); + + /* The iBCS flags don't match Linux flags. */ + case 3: /* F_GETFL */ + return map_flags(SYS(fcntl)(arg1, arg2, arg3), + fl_linux_to_ibcs); + case 4: /* F_SETFL */ + arg3 = map_flags(arg3, fl_ibcs_to_linux); + return SYS(fcntl)(arg1, arg2, arg3); + + /* The lock stucture is different. */ + case 14: /* F_GETLK SVR4 */ + arg2 = 5; + /* fall through */ + case 5: /* F_GETLK */ + case 6: /* F_SETLK */ + case 7: /* F_SETLKW */ + { + struct ibcs_flock fl; + struct flock l_fl; + mm_segment_t old_fs; + + error = verify_area(VERIFY_WRITE, (void *)arg3, + sizeof(fl)); + if (error) + return error; + error = copy_from_user(&fl, (void *)arg3, sizeof(fl)); + if (error) + return -EFAULT; + + l_fl.l_type = fl.l_type - 1; + l_fl.l_whence = fl.l_whence; + l_fl.l_start = fl.l_start; + l_fl.l_len = fl.l_len; + l_fl.l_pid = fl.l_pid; + + abi_trace(ABI_TRACE_API, + "lock l_type: %d l_whence: %d " + "l_start: %lu l_len: %lu " + "l_sysid: %d l_pid: %d\n", + fl.l_type, fl.l_whence, + fl.l_start, fl.l_len, + fl.l_sysid, fl.l_pid); + + old_fs = get_fs(); + set_fs(get_ds()); + retval = SYS(fcntl)(arg1, arg2, &l_fl); + set_fs(old_fs); + + if (!retval) { + fl.l_type = l_fl.l_type + 1; + fl.l_whence = l_fl.l_whence; + fl.l_start = l_fl.l_start; + fl.l_len = l_fl.l_len; + fl.l_sysid = 0; + fl.l_pid = l_fl.l_pid; + /* This should not fail... */ + copy_to_user((void *)arg3, &fl, sizeof(fl)); + } + + return retval; + } + + case 10: /* F_ALLOCSP */ + /* Extend allocation for specified portion of file. */ + case 11: /* F_FREESP */ + /* Free a portion of a file. */ + return 0; + + /* These are intended to support the Xenix chsize() and + * rdchk() system calls. I don't know if these may be + * generated by applications or not. + */ + case 0x6000: /* F_CHSIZE */ + return SYS(ftruncate)(arg1, arg3); +#ifndef __sparc__ + case 0x6001: /* F_RDCHK */ + return xnx_rdchk(arg1); +#endif /* __sparc__ */ + +#ifdef CONFIG_ABI_IBCS_SCO + /* This could be SCO's get highest fd open if the fd we + * are called on is -1 otherwise it could be F_CHKFL. + */ + case 8: /* F_GETHFDO */ + if (arg1 == -1) + return find_first_zero_bit(current->files->open_fds, + current->files->max_fdset); + /* else fall through to fail */ +#else + /* The following are defined but reserved and unknown. */ + case 8: /* F_CHKFL */ +#endif + + /* These are made from the Xenix locking() system call. + * According to available documentation these would + * never be generated by an application - only by the + * kernel Xenix support. + */ + case 0x6300: /* F_LK_UNLCK */ + case 0x7200: /* F_LK_LOCK */ + case 0x6200: /* F_LK_NBLCK */ + case 0x7100: /* F_LK_RLCK */ + case 0x6100: /* F_LK_NBRLCK */ + + default: + abi_trace(ABI_TRACE_API, + "unsupported fcntl 0x%lx, arg 0x%lx", + (u_long)arg2, (u_long)arg3); + + return -EINVAL; + break; + } +} +EXPORT_SYMBOL(svr4_fcntl); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/poll.c linux/abi/svr4/poll.c --- linux-2.4.3/abi/svr4/poll.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/poll.c Sun Mar 18 11:54:28 2001 @@ -0,0 +1,99 @@ +/* $Id$ + * + * This file contains the procedures for the handling of poll. + * + * Copyright (C) 1994 Eric Youngdale + * + * Created for Linux based loosely upon linux select code, which + * in turn is loosely based upon Mathius Lattner's minix + * patches by Peter MacDonald. Heavily edited by Linus. + * + * Poll is used by SVr4 instead of select, and it has considerably + * more functionality. Parts of it are related to STREAMS, and since + * we do not have streams, we fake it. In fact, select() still exists + * under SVr4, but libc turns it into a poll() call instead. + * + * (note: poll is now native to Linux... -- hch) + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +/* FIXME: This is just copied from linux/fs/select.c simply so we can + * add the XTI message check - and even then only if XTI is enabled + * in the module. We could probably do better. But see the following + * comment which notes the possibility of needing to do some flag + * mapping in the event vectors one day... + */ + +/* FIXME: Some of the event flags may need mapping. This list does + * not agree with the list Linux is using. The important ones do, but... + */ +#define POLLIN 1 +#define POLLPRI 2 +#define POLLOUT 4 +#define POLLERR 8 +#define POLLHUP 16 +#define POLLNVAL 32 +#define POLLRDNORM 64 +#define POLLWRNORM POLLOUT +#define POLLRDBAND 128 +#define POLLWRBAND 256 + +#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM) + + +/* + * FIXME: just have the callmap go direct to Linux poll()? + */ +int +svr4_poll(struct poll * ufds, size_t nfds, int timeout) +{ + int error; + + if (abi_traced(ABI_TRACE_API)) { + int i; + + for (i = 0; i < nfds; i++) { + __abi_trace(" %3d 0x%04x 0x%04x", + ufds[i].fd, ufds[i].events, + ufds[i].revents); + } + } + + error = SYS(poll)(ufds, nfds, timeout); + + if (abi_traced(ABI_TRACE_API)) { + int i; + + for (i = 0; i < nfds; i++) { + __abi_trace(" %3d 0x%04x 0x%04x", + ufds[i].fd, ufds[i].events, + ufds[i].revents); + } + } + + return error; +} + +EXPORT_SYMBOL(svr4_poll); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/ptrace.c linux/abi/svr4/ptrace.c --- linux-2.4.3/abi/svr4/ptrace.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/ptrace.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,145 @@ +/* $Id$ + * + * sysv ptrace(2) emulation + * + * Copyright (C) 1995 Mike Jagdis + * + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + + +#define NREGS 19 + +#define U(X) ((unsigned long)&((struct user *)0)->X) + +#ifdef CONFIG_ABI_IBCS_SCO +static unsigned long sco_to_linux_reg[NREGS] = { + U(regs.gs), U(regs.fs), U(regs.es), U(regs.ds), + U(regs.edi), U(regs.esi), + U(regs.ebp), + U(regs.esp /* ESP */), + U(regs.ebx), U(regs.edx), U(regs.ecx), U(regs.eax), + U(signal /* Trap */), + U(reserved /* ERR */), + U(regs.eip), U(regs.cs), U(regs.eflags), + U(regs.esp), U(regs.ss) +}; +#endif + +#ifdef CONFIG_ABI_IBCS_WYSE +static unsigned long wysev386_to_linux_reg[NREGS] = { + U(regs.es), U(regs.ds), U(regs.edi), U(regs.esi), + U(regs.ebp), U(regs.esp), + U(regs.ebx), U(regs.edx), U(regs.ecx), U(regs.eax), + U(signal /* Trap */), + U(reserved /* ERR */), + U(regs.eip), U(regs.cs), + U(regs.eflags), + U(regs.esp /* UESP */), + U(regs.ss), + U(regs.fs), U(regs.gs) +}; +#endif + + +unsigned long *reg_map[] = { + NULL, + NULL, /* SVR4 */ + NULL, /* SVR3 is a subset of SVR4 */ +#ifdef CONFIG_ABI_IBCS_SCO + sco_to_linux_reg, /* SCO SVR3 */ +#else + NULL, +#endif +#ifdef CONFIG_ABI_IBCS_WYSE + wysev386_to_linux_reg, /* Wyse V/386 */ +#else + NULL, +#endif + NULL, /* ISC R4 */ + NULL, /* BSD */ + NULL /* Xenix */ +}; + + +int svr4_ptrace(int req, int pid, unsigned long addr, unsigned long data) +{ +#if !defined(CONFIG_ABI_IBCS_SCO) && !defined(CONFIG_ABI_IBCS_WYSE) + return -EIO; +#else + unsigned long res; + + /* Slight variations between iBCS and Linux codes. */ + if (req == PTRACE_ATTACH) + req = 10; + else if (req == PTRACE_DETACH) + req = 11; + + /* Remap access to the registers. */ + if (req == 3 || req == 6) { + if (addr == 0x1200 /* get offset of u_ar0 (SCO) */ + || addr == 0x1292) { /* get offset of u_ar0 (Wyse V/386) */ + return 0x4000; + } + + if ((addr & 0xff00) == 0x4000) { /* Registers */ + addr = (addr & 0xff) >> 2; + if (addr > NREGS + || (int)(addr = reg_map[current->personality & PER_MASK][addr]) == -1) + return -EIO; + } + } + + if (req == 7 && data > 0) { + if (data > NSIGNALS) + return -EIO; + data = current->exec_domain->signal_map[data]; + } + + if (req == 1 || req == 2 || req == 3) { + mm_segment_t old_fs; + int error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ptrace)(req, pid, addr, &res); + set_fs(old_fs); + if (error) + return error; + } + + if ((abi_traced(ABI_TRACE_API)) && (req == 3 || req == 6)) { + static const char * const regnam[] = { + "EBX", "ECX", "EDX", "ESI", "EDI", "EBP", "EAX", + "DS", "ES", "FS", "GS", "ORIG_EAX", "EIP", "CS", + "EFL", "UESP", "SS" + }; + __abi_trace("%ld [%s] = 0x%08lx\n", + addr>>2, + (addr>>2) < sizeof(regnam)/sizeof(regnam[0]) + ? regnam[addr>>2] : "???", + req == 3 ? res : data); + } + + if (req == 1 || req == 2 || req == 3) + return res; + + return SYS(ptrace)(req, pid, addr, data); +#endif /* !defined(CONFIG_ABI_IBCS_SCO) && !defined(CONFIG_ABI_IBCS_WYSE) */ +} + +EXPORT_SYMBOL(svr4_ptrace); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/sco_secureware.c linux/abi/svr4/sco_secureware.c --- linux-2.4.3/abi/svr4/sco_secureware.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/sco_secureware.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,52 @@ +/* $Id$ + * + * sco_secureware.c - secureware syscall emulation + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * + * SecureWare, Inc. provided the C2 security subsystem used on SCO Unix. + * This is not that package. This does not even attempt to emulate + * that package. This emulates just enough of the "obvious" bits to + * allow some programs to get a bit further. It is not useful to + * try to implement C2 security in an emulator. Nor is it particularly + * useful to run SCO's secure admin programs on Linux anyway... + */ + +#include +#include +#include + +#include +#include + + +int +sw_security(int cmd, void *p1, void *p2, void *p3, void *p4, void *p5) +{ + switch (cmd) { + case 1: /* getluid */ + /* We want the login user id. We don't have it + * specifically so we'll just use the real uid + * instead - it should be good enough. + */ + return current->uid; + + case 2: /* setluid */ + /* Strictly we should only be able to call setluid() + * once but we can't enforce that. We have the choice + * between having it always succeed or always fail. + * Since setluid() should only ever be invoked by + * things like login processes we always fail it. + */ + return -EPERM; + + case 0: + case 3: + case 4: + default: + printk(KERN_ERR "iBCS: unsupported security call cmd=%d\n", + cmd); + return -EINVAL; + } +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/stream.c linux/abi/svr4/stream.c --- linux-2.4.3/abi/svr4/stream.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/stream.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,132 @@ +/* $Id$ + * stream.c - SVR4 streams handling + * + * Copyright 1994,1995 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +int svr4_getmsg(struct pt_regs *regs) +{ + int fd; + struct file *filep; + struct inode *ino; + int error; + + fd = (int)get_syscall_parameter (regs, 0); + filep = fget(fd); + if (!filep) + return -EBADF; + + error = -EBADF; + ino = filep->f_dentry->d_inode; + if (ino->i_sock) { +#if defined(CONFIG_ABI_XTI) || defined(CONFIG_ABI_SPX) + error = timod_getmsg(fd, ino, 0, regs); +#else + error = 0; +#endif /* CONFIG_ABI_XTI */ + } + fput(filep); + return error; +} + +EXPORT_SYMBOL(svr4_getmsg); + + +int svr4_putmsg(struct pt_regs *regs) +{ + int fd; + struct file *filep; + struct inode *ino; + int error; + + fd = (int)get_syscall_parameter (regs, 0); + filep = fget(fd); + if (!filep) + return -EBADF; + + error = -EBADF; + ino = filep->f_dentry->d_inode; + if (ino->i_sock + || (MAJOR(ino->i_rdev) == 30 && MINOR(ino->i_rdev) == 1)) { +#if defined(CONFIG_ABI_XTI) || defined(CONFIG_ABI_SPX) + error = timod_putmsg(fd, ino, 0, regs); +#else + error = 0; +#endif + } + fput(filep); + return error; +} + +EXPORT_SYMBOL(svr4_putmsg); + +#ifdef CONFIG_ABI_XTI +int svr4_getpmsg(struct pt_regs *regs) +{ + int fd; + struct file *filep; + struct inode *ino; + int error; + + fd = (int)get_syscall_parameter (regs, 0); + + filep = fget(fd); + if (!filep) + return -EBADF; + + error = -EBADF; + ino = filep->f_dentry->d_inode; + if (ino->i_sock) + error = timod_getmsg(fd, ino, 1, regs); + fput(filep); + return error; +} + +EXPORT_SYMBOL(svr4_getpmsg); + +int svr4_putpmsg(struct pt_regs *regs) +{ + int fd; + struct file *filep; + struct inode *ino; + int error; + + fd = (int)get_syscall_parameter (regs, 0); + + filep = fget(fd); + if (!filep) + return -EBADF; + + error = -EBADF; + ino = filep->f_dentry->d_inode; + if (ino->i_sock + || (MAJOR(ino->i_rdev) == 30 && MINOR(ino->i_rdev) == 1)) + error = timod_putmsg(fd, ino, 1, regs); + fput(filep); + return error; +} + +EXPORT_SYMBOL(svr4_putpmsg); + +#endif /* CONFIG_ABI_XTI */ diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/svr4.c linux/abi/svr4/svr4.c --- linux-2.4.3/abi/svr4/svr4.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/svr4.c Sun Mar 18 11:54:28 2001 @@ -0,0 +1,346 @@ +/* $Id$ + * + * This file contains the emulation of some simple sysv syscalls + * + * Copyright (C) 1995 Mike Jagdis + * + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * Interactive SVR4's /bin/sh calls access(... 011) but Linux returns + * EINVAL if the access mode has any other bits than 007 set. + */ + +int +svr4_access(char *path, int mode) +{ + return SYS(access)(path, mode & 007); +} + + +int +svr4_getgroups(int n, unsigned long *buf) +{ + int i; + + if (n) { + i = verify_area(VERIFY_WRITE, buf, sizeof(unsigned long) * n); + if (i) + return i; + } + for (i = 0; i < current->ngroups && i < n; i++) { + put_user(current->groups[i], buf); + buf++; + } + return(i); +} + + +int +svr4_setgroups(int n, unsigned long *buf) +{ + int i; + + if (!capable(CAP_SETGID)) + return -EPERM; + if (n > NGROUPS) + return -EINVAL; + /* FIXME: Yuk! What if we hit a bad address? */ + for (i = 0; i < n; i++, buf++) { + get_user(current->groups[i], buf); + } + current->ngroups = n; + return 0; +} + + +int +svr4_waitid(int idtype, int id, struct svr4_siginfo *infop, int options) +{ + long result, kopt; + mm_segment_t old_fs; + int pid, status; + + switch (idtype) { + case 0: /* P_PID */ + pid = id; + break; + + case 1: /* P_PGID */ + pid = -id; + break; + + case 7: /* P_ALL */ + pid = -1; + break; + + default: + return -EINVAL; + } + + if (infop) { + result = verify_area(VERIFY_WRITE, infop, + sizeof(struct svr4_siginfo)); + if (result) + return result; + } + + kopt = 0; + if (options & 0100) kopt |= WNOHANG; + if (options & 4) kopt |= WUNTRACED; + + old_fs = get_fs(); + set_fs(get_ds()); + result = SYS(wait4)(pid, &status, kopt, NULL); + set_fs(old_fs); + if (result < 0) + return result; + + if (infop) { + unsigned long op, st; + + put_user(current->exec_domain->signal_map[SIGCHLD], + &infop->si_signo); + put_user(result, + &infop->_data._proc._pid); + + if ((status & 0xff) == 0) { + /* Normal exit. */ + op = SVR4_CLD_EXITED; + st = status >> 8; + } else if ((status & 0xff) == 0x7f) { + /* Stopped. */ + st = (status & 0xff00) >> 8; + op = (st == SIGSTOP || st == SIGTSTP) + ? SVR4_CLD_STOPPED + : SVR4_CLD_CONTINUED; + st = current->exec_domain->signal_invmap[st]; + } else { + st = (status & 0xff00) >> 8; + op = (status & 0200) + ? SVR4_CLD_DUMPED + : SVR4_CLD_KILLED; + st = current->exec_domain->signal_invmap[st]; + } + put_user(op, &infop->si_code); + put_user(st, &infop->_data._proc._pdata._cld._status); + } + return 0; +} + +EXPORT_SYMBOL(svr4_waitid); + +int +svr4_seteuid(int uid) +{ + return SYS(setreuid)(-1, uid); +} + +int +svr4_setegid(int gid) +{ + return SYS(setregid)(-1, gid); +} + +int +svr4_pathconf(char *path, int name) +{ + switch (name) { + case _PC_LINK_MAX: + /* Although Linux headers define values on a per + * filesystem basis there is no way to access + * these without hard coding fs information here + * so for now we use a bogus value. + */ + return LINK_MAX; + + case _PC_MAX_CANON: + return MAX_CANON; + + case _PC_MAX_INPUT: + return MAX_INPUT; + + case _PC_PATH_MAX: + return PATH_MAX; + + case _PC_PIPE_BUF: + return PIPE_BUF; + + case _PC_CHOWN_RESTRICTED: + /* We should really think about this and tell + * the truth. + */ + return 0; + + case _PC_NO_TRUNC: + /* Not sure... It could be fs dependent? */ + return 1; + + case _PC_VDISABLE: + return 1; + + case _PC_NAME_MAX: { + struct statfs buf; + char *p; + int error; + mm_segment_t old_fs; + + p = getname(path); + error = PTR_ERR(p); + if (!IS_ERR(p)) { + old_fs = get_fs(); + set_fs (get_ds()); + error = SYS(statfs)(p, &buf); + set_fs(old_fs); + putname(p); + if (!error) + return buf.f_namelen; + } + return error; + } + } + + return -EINVAL; +} + +EXPORT_SYMBOL(svr4_pathconf); + +int +svr4_fpathconf(int fildes, int name) +{ + switch (name) { + case _PC_LINK_MAX: + /* Although Linux headers define values on a per + * filesystem basis there is no way to access + * these without hard coding fs information here + * so for now we use a bogus value. + */ + return LINK_MAX; + + case _PC_MAX_CANON: + return MAX_CANON; + + case _PC_MAX_INPUT: + return MAX_INPUT; + + case _PC_PATH_MAX: + return PATH_MAX; + + case _PC_PIPE_BUF: + return PIPE_BUF; + + case _PC_CHOWN_RESTRICTED: + /* We should really think about this and tell + * the truth. + */ + return 0; + + case _PC_NO_TRUNC: + /* Not sure... It could be fs dependent? */ + return 1; + + case _PC_VDISABLE: + return 1; + + case _PC_NAME_MAX: { + struct statfs buf; + int error; + mm_segment_t old_fs; + + old_fs = get_fs(); + set_fs (get_ds()); + error = SYS(statfs)(fildes, &buf); + set_fs(old_fs); + if (!error) + return buf.f_namelen; + return error; + } + } + + return -EINVAL; +} + +EXPORT_SYMBOL(svr4_fpathconf); + +int +svr4_sigpending(int which_routine, svr4_sigset_t *set) +{ + /* Solaris multiplexes on this one */ + /* Which routine has the actual routine that should be called */ + + switch (which_routine){ + case 1: /* sigpending */ + printk ("iBCS/Intel: sigpending not implemented\n"); + return -EINVAL; + + case 2: /* sigfillset */ + set->setbits [0] = ~0; + set->setbits [1] = 0; + set->setbits [2] = 0; + set->setbits [3] = 0; + return 0; + } + return -EINVAL; +} + +EXPORT_SYMBOL(svr4_sigpending); + +static int +svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs) +{ + printk (KERN_DEBUG "Getting context\n"); + return 0; +} + +static int +svr4_getcontext(svr4_ucontext_t *c, struct pt_regs *regs) +{ + printk (KERN_DEBUG "Setting context\n"); + return 0; +} + +int +svr4_context(struct pt_regs *regs) +{ + int context_fn = get_syscall_parameter (regs, 0); + struct svr4_ucontext_t *uc = (void *) get_syscall_parameter (regs, 1); + + switch (context_fn){ + case 0: /* getcontext */ + return svr4_getcontext (uc, regs); + + case 1: /* setcontext */ + return svr4_setcontext (uc, regs); + } + return -EINVAL; +} + +EXPORT_SYMBOL(svr4_context); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/sysconf.c linux/abi/svr4/sysconf.c --- linux-2.4.3/abi/svr4/sysconf.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/sysconf.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,178 @@ +/* $Id$ + * sysconf.c - sysv sysconf(2) and sysconfig(2) emulation + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +/* The sysconf() call is supposed to give applications access to various + * kernel parameters. According to SCO's man page this a POSIX mandated + * function. Perhaps it should be moved across as a native Linux call? + * + * N.B. SCO only has sysconf in the Xenix group. Therefore this is based + * on the Xenix spec. Is SVR4 the same? Wyse Unix V.3.2.1A doesn't have + * sysconf documented at all. + * + * N.B. 0-7 are required (by who?). Other values may be defined for + * various systems but there appears no guarantee that they match across + * platforms. Thus, unless we can identify what system the executable + * was compiled for, we probably prefer to have extensions fail. Hell, + * nothing important is going to use this obscure stuff anyway... + */ +#define _SC_ARG_MAX 0 +#define _SC_CHILD_MAX 1 +#define _SC_CLK_TCK 2 +#define _SC_NGROUPS_MAX 3 +#define _SC_OPEN_MAX 4 +#define _SC_JOB_CONTROL 5 +#define _SC_SAVED_IDS 6 +#define _SC_VERSION 7 + +#define _SC_PAGESIZE 11 +#define _SCO_SC_PAGESIZE 34 + +extern int max_threads; + + +/* This is an SVR4 system call that is undocumented except for some + * hints in a header file. It appears to be a forerunner to the + * POSIX sysconf() call. + */ +int svr4_sysconfig(int name) +{ + switch (name) { + case _CONFIG_NGROUPS: + /* From limits.h */ + return (NGROUPS_MAX); + + case _CONFIG_CHILD_MAX: + /* From limits.h */ + return (CHILD_MAX); + + case _CONFIG_OPEN_FILES: + /* From limits.h */ + return (OPEN_MAX); + + case _CONFIG_POSIX_VER: + /* The version of the POSIX standard we conform + * to. SCO defines _POSIX_VERSION as 198808L + * sys/unistd.h. What are we? We are 199009L. + */ + return (199009L); + + case _CONFIG_PAGESIZE: + return (PAGE_SIZE); + + case _CONFIG_CLK_TCK: + return (HZ); + + case _CONFIG_XOPEN_VER: + return 4; + + case _CONFIG_NACLS_MAX: + return 0; + + case _CONFIG_NPROC: + return max_threads; + + case _CONFIG_NENGINE: + case _CONFIG_NENGINE_ONLN: + return (smp_num_cpus); + + case _CONFIG_TOTAL_MEMORY: + return (max_mapnr << (PAGE_SHIFT-10)); + + case _CONFIG_USEABLE_MEMORY: + case _CONFIG_GENERAL_MEMORY: + return ((unsigned long) (nr_free_pages()) << (PAGE_SHIFT-10)); + + case _CONFIG_DEDICATED_MEMORY: + return 0; + + case _CONFIG_NCGS_CONF: + case _CONFIG_NCGS_ONLN: + case _CONFIG_MAX_ENG_PER_CG: + return 1; /* no NUMA-Q support on Linux yet */ + + case _CONFIG_CACHE_LINE: + return 32; /* XXX is there a more accurate way? */ + + case _CONFIG_KERNEL_VM: + return -EINVAL; + + case _CONFIG_ARG_MAX: + /* From limits.h */ + return (ARG_MAX); + } + + abi_trace(ABI_TRACE_API, "unsupported sysconfig call %d", name); + return -EINVAL; +} + + +int ibcs_sysconf(int name) +{ + switch (name) { + case _SC_ARG_MAX: + /* From limits.h */ + return (ARG_MAX); + + case _SC_CHILD_MAX: + /* From limits.h */ + return (CHILD_MAX); + + case _SC_CLK_TCK: + return (HZ); + + case _SC_NGROUPS_MAX: + /* From limits.h */ + return (NGROUPS_MAX); + + case _SC_OPEN_MAX: + /* From limits.h */ + return (OPEN_MAX); + + case _SC_JOB_CONTROL: + return (1); + + case _SC_SAVED_IDS: + return (1); + + case _SC_PAGESIZE: + case _SCO_SC_PAGESIZE: + return PAGE_SIZE; + + case _SC_VERSION: + /* The version of the POSIX standard we conform + * to. SCO defines _POSIX_VERSION as 198808L + * sys/unistd.h. What are we? + */ + return (198808L); + } + + abi_trace(ABI_TRACE_API, "unsupported sysconf call %d", name); + return -EINVAL; +} + +EXPORT_SYMBOL(svr4_sysconfig); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/sysfs.c linux/abi/svr4/sysfs.c --- linux-2.4.3/abi/svr4/sysfs.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/sysfs.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,119 @@ +/* $Id$ + * sysfs.c - sysfs(2) emulation + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + */ + +#include +#include +#include +#include + +/* + * The kernel sysfs() code is almost all we need but, apparently, + * the SCO (at least) sysfs() will also accept a "magic number" + * as an index argument and will return the name of the relevant + * file system. Since Linux doesn't have any concept of fs magic + * numbers outside the file system code themselves there is no + * clean way to do it in the kernel. There isn't a clean way to + * to it here either but it needs to be done somehow :-(. + */ + +#define GETFSIND 1 +#define GETFSTYP 2 +#define GETNFSTYP 3 + + +int +svr4_sysfs(int cmd, int arg1, int arg2) +{ + if (cmd == GETFSIND) + return SYS(sysfs)(cmd, (char *)arg1); + + if (cmd == GETNFSTYP) + return SYS(sysfs)(cmd); + + if (cmd == GETFSTYP) { + char *buf = (char *)arg2; + int error; + + if (arg1 & 0x80000000) + arg1 &= 0x0000ffff; + if (arg1 >= 0 && arg1 < SYS(sysfs)(GETNFSTYP)) + return SYS(sysfs)(cmd, arg1-1, arg2); + + /* + * Kludge alert! Hardcoded known magic numbers! + */ + switch (arg1) { + case 0xef53: case 0xffffef53: + case 0xef51: case 0xffffef51: + /* + * Some SCO programs (i.e. Informix Dynamic + * Server are using this to detect "real" + * filesystems by checking type names :-(. + * So we lie :-). + */ + if (personality(PER_SCOSVR3)) + error = copy_to_user(buf, "HTFS", 5); + else + error = copy_to_user(buf, "ext2", 5); + break; + case 0x137d: + error = copy_to_user(buf, "ext", 4); + break; + case 0x9660: case 0xffff9660: + error = copy_to_user(buf, "iso9660", 8); + break; + case 0x4d44: + error = copy_to_user(buf, "msdos", 6); + break; + case 0x6969: + error = copy_to_user(buf, "nfs", 4); + break; + case 0x9fa0: case 0xffff9fa0: + error = copy_to_user(buf, "proc", 5); + break; + case 0xf995e849: + case 0xe849: case 0xffffe849: + error = copy_to_user(buf, "hpfs", 5); + break; + case 0x137f: /* original */ + case 0x138f: /* original + 30 char names */ + case 0x2468: /* V2 */ + case 0x2478: /* V2 + 30 char names */ + error = copy_to_user(buf, "minix", 6); + break; + case 0x564c: + error = copy_to_user(buf, "ncpfs", 6); + break; + case 0x517b: + error = copy_to_user(buf, "smbfs", 6); + break; + case 0x00011954: + error = copy_to_user(buf, "ufs", 4); + break; + case 0x012fd16d: case 0xffffd16d: + error = copy_to_user(buf, "xiafs", 6); + break; + case 0x012ff7b3+1: case 0xfffff7b3+1: + error = copy_to_user(buf, "xenix", 6); + break; + case 0x012ff7b3+2: case 0xfffff7b3+2: + case 0x012ff7b3+3: case 0xfffff7b3+3: + error = copy_to_user(buf, "sysv", 5); + break; + case 0x012ff7b3+4: case 0xfffff7b3+4: + error = copy_to_user(buf, "coherent", 9); + break; + default: + error = copy_to_user(buf, "", 1); + break; + } + return error; + } + + abi_trace(ABI_TRACE_API, "unsupported sysfs call %d", cmd); + return -EINVAL; +} +EXPORT_SYMBOL(svr4_sysfs); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/sysi86.c linux/abi/svr4/sysi86.c --- linux-2.4.3/abi/svr4/sysi86.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/sysi86.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,235 @@ +/* $Id$ + * sysi86.c - ix86 spcific sysv syscalls + * + * Copyright 1994,1995 Mike Jagdis + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +/* The sysi86() call is used for machine specific functions. Only the + * most basic are implemented here. + */ +#define SI86SWPI 1 /* General swap functions. */ +#define SI86SYM 2 /* Get symbol table */ +#define SI86CONF 4 /* Get configuration table */ +#define SI86BOOT 5 /* Get timestamp and name of program + * booted. + */ +#define SI86DMM 7 /* Double-map data segment for + * read/write/execute support + */ +#define SI86AUTO 9 /* Was an auto-config boot done? */ +#define SI86EDT 10 /* Copy contents of EDT to user */ +#define SI86SWAP 12 /* Declare swap space */ +#define SI86FPHW 40 /* what (if any?) floating-point hardware */ +# define FP_NO 0 /* No fp at all */ +# define FP_SW 1 /* using emulator */ +# define FP_HW 2 /* using hardware */ +# define FP_287 2 /* using a 287 */ +# define FP_387 3 /* using a 387 */ +#define GRNON 52 /* set green light to solid on state */ +#define GRNFLASH 53 /* start green light flashing */ +#define STIME 54 /* set internal time */ +#define SETNAME 56 /* rename the system */ +#define RNVR 58 /* read NVRAM */ +#define WNVR 59 /* write NVRAM */ +#define RTODC 60 /* read time of day clock */ +#define CHKSER 61 /* check soft serial number */ +#define SI86NVPRT 62 /* print an xtra_nvr structure */ +#define SANUPD 63 /* sanity update of kernel buffers */ +#define SI86KSTR 64 /* make a copy of a kernel string */ +#define SI86MEM 65 /* return the memory size of system */ +#define SI86TODEMON 66 /* Transfer control to firmware. */ +#define SI86CCDEMON 67 /* Control character access to demon. */ +#define SI86CACHE 68 /* Turn cache on and off. */ +#define SI86DELMEM 69 /* Delete available memory for testing. */ +#define SI86ADDMEM 70 /* Add back deleted memory. */ +/* 71 through 74 reserved for VPIX */ +#define SI86V86 71 /* V86 system calls (see v86.h) */ +#define SI86SLTIME 72 /* Set local time correction */ +#define SI86DSCR 75 /* Set a segment or gate descriptor */ +#define RDUBLK 76 /* Read U Block */ +/* #ifdef MERGE386 */ +/* NFA entry point */ +#define SI86NFA 77 /* make nfa_sys system call */ +#define SI86VM86 81 +#define SI86VMENABLE 82 +/* #endif MERGE386 */ +#define SI86VM86 81 +#define SI86VMENABLE 82 +#define SI86LIMUSER 91 /* liscense interface */ +#define SI86RDID 92 /* ROM BIOS Machid ID */ +#define SI86RDBOOT 93 /* Bootable Non-SCSI Hard Disk */ +/* Merged Product defines */ +#define SI86SHFIL 100 /* map a file into addr space of a proc */ +#define SI86PCHRGN 101 /* make globally visible change to a region */ +#define SI86BADVISE 102 /* badvise subcommand - see below for */ + /* badvise subfunction definitions */ +#define SI86SHRGN 103 /* enable/disable XENIX small model shared */ + /* data context switching */ +#define SI86CHIDT 104 /* set user level int 0xf0, ... 0xff handlers */ +#define SI86EMULRDA 105 /* remove special emulator read access */ +#define SI86GETPIPE 106 /* return the pipe filesystem */ +#define SI86SETPIPE 107 /* set the pipe filesystem */ +#define SI86SETPIPE_NM 108 /* set the pipe filesystem -non mountable */ +#define SI86GETNPIPE 109 /* get # of pipe filesystems */ +#define SI86GETPIPE_ALL 110 /* get data on all of pipe filesystems */ +#define SI86POPPIPE 111 /* pop pipe file system off stack */ +#define SI86APM 112 /* get APM information passed by boot(HW) */ +#define SI86TIMECHG 113 /* get time before/after last timechange */ +#define SI86GETFEATURES 114 /* get os features vector */ + +/* The SI86BADVISE command is used to set Xenix behaviour. */ +#define SI86B_SET 0x0100 /* Set badvise bits */ +#define SI86B_GET 0x0200 /* Get badvise bits */ +#define SI86B_LOCK 0x0001 /* XENIX advisory locking bit */ +#define SI86B_PRE_SV 0x0008 /* follow pre-System V x.out behavior */ +#define SI86B_XOUT 0x0010 /* follow XENIX x.out behavior */ +#define SI86B_XSDSWTCH 0x0080 /* XENIX small model shared data */ + /* context switching enabled */ + + +/* + * The SI86DSCR subcommand of the sysi86() system call + * sets a segment or gate descriptor in the kernel. + * The following descriptor types are accepted: + * - executable and data segments in the LDT at DPL 3 + * - a call gate in the GDT at DPL 3 that points to a segment in the LDT + * The request structure declared below is used to pass the values + * to be placed in the descriptor. A pointer to the structure is + * passed as the second argument of the system call. + * If acc1 is zero, the descriptor is cleared. + */ + +/* request structure passed by user */ +struct ssd { + unsigned int sel; /* descriptor selector */ + unsigned int bo; /* segment base or gate offset */ + unsigned int ls; /* segment limit or gate selector */ + unsigned int acc1; /* access byte 5 */ + unsigned int acc2; /* access bits in byte 6 or gate count */ +}; + + + +int svr4_sysi86(struct pt_regs * regs) +{ + int error, cmd; + + error = get_user(cmd, ((unsigned long *) regs->esp) + 1); + if (error) + return error; + + switch (cmd) { + case SI86FPHW: { + unsigned long *np; + + /* If we remove the 'static' from the definition + * of fpu_error in linux/init/main.c we can tell + * whether we are using hardware or software at + * least. For now let's lie... (actually SCO + * Unix 3.4 gives me -1...) + */ + get_user((unsigned long) np, ((unsigned long *) regs->esp) + 2); + error = verify_area(VERIFY_WRITE, np, sizeof(int)); + if (error) + return error; + put_user(FP_387, np); + return 0; + } + + case STIME: { + /* Set the system time. The argument is a long, + * sys_stime() expects a pointer to a long... + */ + return SYS(stime)(((unsigned long *) regs->esp) + 2); + } + + case SETNAME: { + /* The name is required to be string of no more + * than 7 characters. We don't get passed the + * length so we are depending upon the current + * implementation of sys_sethostname() here. + */ + char *cp; + + error = get_user((unsigned long) cp, ((unsigned long *) regs->esp) + 2); + if (error) + return error; + return SYS(sethostname)(cp, 7); + } + + case SI86MEM: { + /* Returns the size of physical memory. + */ + struct sysinfo i; + + si_meminfo(&i); + return i.totalram; + } + +#if defined(CONFIG_ABI_IBCS_SCO) + case SI86GETFEATURES: { + char *vec; + int len, used; + + if (!personality(PER_SCOSVR3)) { + current->personality &= ~PER_MASK; + current->personality |= PER_SCOSVR3; + } + +#if 1 + error = get_user((unsigned long) vec, ((unsigned long *) regs->esp) + 2); + if (!error) + error = get_user(len, ((unsigned long *) regs->esp) + 3); + if (error) + return (error); + /* No, I don't know what these feature flags actually + * _mean_. This vector just matches SCO OS 5.0.0. + */ + used = len > 12 ? 12 : len; + return copy_to_user(vec, "\001\001\001\001\001\001\001\001\002\001\001\001", used) ? -EFAULT : used; +#else + return 0; +#endif + } +#endif + + case SI86DSCR: { + struct ssd buf; + unsigned long ssdptr; + + error = get_user(ssdptr, ((unsigned long *)regs->esp) + 2); + if (error) + return (error); + error = copy_from_user(&buf, (void *)ssdptr, sizeof(struct ssd)); + if (error) + return (error); + + printk("SI86DSCR(%x,%x,%x,%x,%x)\n",buf.sel,buf.bo,buf.ls,buf.acc1,buf.acc2); + return -EINVAL; + } + } + + abi_trace(ABI_TRACE_API, "unsupported sysi86 call %d", cmd); + return -EINVAL; +} + +EXPORT_SYMBOL(svr4_sysi86); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/sysinfo.c linux/abi/svr4/sysinfo.c --- linux-2.4.3/abi/svr4/sysinfo.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/sysinfo.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,129 @@ +/* $Id$ + * + * sysv sysinfo(2) syscall + * + * Copyright (C) 1995 Eric Youngdale + * + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + + +#define __O_SI_SYSNAME 1 /* return name of operating system */ +#define __O_SI_HOSTNAME 2 /* return name of node */ +#define SI_RELEASE 3 /* return release of operating system */ +#define SI_VERSION 4 /* return version field of utsname */ +#define __O_SI_MACHINE 5 /* return kind of machine */ +#define __O_SI_ARCHITECTURE 6 /* return instruction set arch */ +#define SI_HW_SERIAL 7 /* return hardware serial number */ +#define __O_SI_HW_PROVIDER 8 /* return hardware manufacturer */ +#define SI_SRPC_DOMAIN 9 /* return secure RPC domain */ +#define SI_INITTAB_NAME 10 /* return name of inittab file used */ +#define SI_ARCHITECTURE 100 /* return instruction set arch */ +#define SI_BUSTYPES 101 /* return list of bus types */ +#define SI_HOSTNAME 102 /* return fully-qualified node name */ +#define SI_HW_PROVIDER 103 /* return hardware manufacturer */ +#define SI_KERNEL_STAMP 104 /* return kernel generation timestamp */ +#define SI_MACHINE 105 /* return kind of machine */ +#define SI_OS_BASE 106 /* return base operating system */ +#define SI_OS_PROVIDER 107 /* return operating system provider */ +#define SI_SYSNAME 108 /* return name of operating system */ +#define SI_USER_LIMIT 109 /* return maximum number of users */ + + + +int svr4_sysinfo(int cmd, char * buf, long count) +{ + char * return_string; + static unsigned int serial_number = 0; + char buffer[16]; + int error; + int slen; + + return_string = NULL; + + switch(cmd) { + case __O_SI_SYSNAME: + case SI_SYSNAME: + return_string = system_utsname.sysname; + break; + case __O_SI_HOSTNAME: + case SI_HOSTNAME: + return_string = system_utsname.nodename; + break; + case SI_VERSION: + return_string = "2"; + break; + case SI_RELEASE: + return_string = system_utsname.release; + break; + case SI_MACHINE: + case __O_SI_MACHINE: + return_string = system_utsname.machine; + break; + case __O_SI_ARCHITECTURE: + case SI_ARCHITECTURE: + return_string = "IA32"; /* XXX: this seems wrong, the name ia32 is very new ... -- ch */ + break; + case SI_BUSTYPES: + return_string = "PCI ISA"; + break; + case __O_SI_HW_PROVIDER: + case SI_HW_PROVIDER: + return_string = "Generic AT"; + break; + case SI_KERNEL_STAMP: + return_string = UTS_VERSION; + break; + case SI_INITTAB_NAME: + return_string = "/etc/inittab"; + break; + case SI_HW_SERIAL: + if(serial_number == 0) + serial_number = 0xdeadbeef; + sprintf(buffer,"%8.8x", serial_number); + return_string = buffer; + break; + case SI_OS_BASE: + return_string = "Linux"; + break; + case SI_OS_PROVIDER: + return_string = "LBT"; /* someone's initials ? */ + break; + case SI_SRPC_DOMAIN: + return_string = system_utsname.domainname; + break; + case SI_USER_LIMIT: + /* have you seen a Linux box with more than 500000 users? */ + return_string = "500000"; + break; + default: + abi_trace(ABI_TRACE_API, + "unsupported sysinfo call %d", cmd); + return -EINVAL; + } + + if (!return_string) + return 0; + + down_read(&uts_sem); + slen = (count < strlen(return_string) + 1 ? count : strlen(return_string) + 1); + error = copy_to_user(buf, return_string, slen); + up_read(&uts_sem); + + return error ? -EFAULT : slen; +} + +EXPORT_SYMBOL(svr4_sysinfo); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/syslocal.c linux/abi/svr4/syslocal.c --- linux-2.4.3/abi/svr4/syslocal.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/syslocal.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,63 @@ +/* $Id$ + * syslocal.c - wyse syslocal(2) emulation + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + */ + +#include +#include +#include + +#include +#include + + +/* + * The syslocal() call is used for machine specific functions. For + * instance on a Wyse 9000 it give information and control of the + * available processors. + */ +#ifdef CONFIG_ABI_IBCS_WYSE +# define SL_ONLINE 0 /* Turn processor online */ +# define SL_OFFLINE 1 /* Turn processor offline */ +# define SL_QUERY 2 /* Query processor status */ +# define SL_NENG 3 /* Return No. of processors configured */ +# define SL_AFFINITY 4 /* processor binding */ +# define SL_CMC_STAT 7 /* gather CMC performance counters info */ +# define SL_KACC 8 /* make kernel data readable by user */ +# define SL_MACHTYPE 9 /* return machine type (MP/AT) */ +# define SL_BOOTNAME 10 /* return name of booted kernel */ +# define SL_BOOTDEV 11 /* return type of booted device */ +# define SL_UQUERY 12 /* query user status */ + +# define SL_MACH_MP 0 +# define SL_MACH_AT 1 +# define SL_MACH_EISA 2 +# define SL_MACH_EMP 3 +#endif + + +int +svr4_syslocal(struct pt_regs * regs) +{ + int cmd; + + cmd = get_syscall_parameter (regs, 0); + +#ifdef CONFIG_ABI_IBCS_WYSE + switch (cmd) { + case SL_QUERY: + return 0; + + case SL_NENG: + return 1; + + case SL_MACHTYPE: + return (EISA_bus ? SL_MACH_EISA : SL_MACH_AT); + } +#endif + + abi_trace(ABI_TRACE_API, "unsupported syslocal call %d", cmd); + return -EINVAL; +} +EXPORT_SYMBOL(svr4_syslocal); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/timod.c linux/abi/svr4/timod.c --- linux-2.4.3/abi/svr4/timod.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/timod.c Fri Mar 30 15:23:46 2001 @@ -0,0 +1,1723 @@ +/* $Id$ + * + * Copyright 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + */ + +#include + +#ifdef CONFIG_ABI_XTI +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + + +static __inline__ struct socket * +socki_lookup(struct inode * inode) +{ + return &(inode->u.socket_i); +} + + +/* + * 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. + */ +#if defined(CONFIG_ABI_XTI_OPTMGMT) && defined(CONFIG_ABI_TLI_OPTMGMT) +# error "unable to support _both_ TLI and XTI option management" +#endif + + +static char * +xti_prim(int n) +{ + char *tab[] = { + "T_CONN_REQ", "T_CONN_RES", "T_DISCON_REQ", "T_DATA_REQ", + "T_EXDATA_REQ", "T_INFO_REQ", "T_BIND_REQ", "T_UNBIND_REQ", + "T_UNITDATA_REQ", "T_OPTMGMT_REQ", "T_ORDREL_REQ", + "T_CONN_IND", "T_CONN_CON", "T_DISCON_IND", "T_DATA_IND", + "T_EXDATA_IND", "T_INFO_ACK", "T_BIND_ACK", "T_ERROR_ACK", + "T_OK_ACK", "T_UNITDATA_IND", "T_UDERROR_IND", + "T_OPTMGMT_ACK", "T_ORDREL_IND" + }; + + if (n < 0 || n >= sizeof(tab)/sizeof(tab[0])) + return ""; + return tab[n]; +} + + +#define timod_mkctl(len) kmalloc(sizeof(struct T_primsg)-sizeof(long)+len, \ + GFP_KERNEL) + + +static void +timod_socket_wakeup(struct file * fp) +{ + struct socket * sock; + + sock = socki_lookup(fp->f_dentry->d_inode); + wake_up_interruptible(&sock->wait); + + read_lock(&sock->sk->callback_lock); + if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) + __kill_fasync(sock->fasync_list, SIGIO, POLL_IN); + read_unlock(&sock->sk->callback_lock); +} + + +static void +timod_ok(int fd, int prim) +{ + struct file * fp = fcheck(fd); + struct T_primsg * it; + struct T_ok_ack * ok; + + abi_trace(ABI_TRACE_STREAMS, "%u ok ack prim=%d", fd, prim); + + if (!(it = timod_mkctl(sizeof(struct T_ok_ack)))) + return; + + ok = (struct T_ok_ack *)&it->type; + ok->PRIM_type = T_OK_ACK; + ok->CORRECT_prim = prim; + + it->pri = MSG_HIPRI; + it->length = sizeof(struct T_ok_ack); + it->next = Priv(fp)->pfirst; + + Priv(fp)->pfirst = it; + if (!Priv(fp)->plast) + Priv(fp)->plast = it; + timod_socket_wakeup(fp); +} + +static void +timod_error(int fd, int prim, int terr, int uerr) +{ + struct file * fp = fcheck(fd); + struct T_primsg * it; + struct T_error_ack * err; + + abi_trace(ABI_TRACE_STREAMS, "%u error prim=%d, TLI=%d, UNIX=%d", + fd, prim, terr, uerr); + + if (!(it = timod_mkctl(sizeof(struct T_error_ack)))) + return; + + err = (struct T_error_ack *)&it->type; + err->PRIM_type = T_ERROR_ACK; + err->ERROR_prim = prim; + err->TLI_error = terr; + err->UNIX_error = iABI_errors(uerr); + + it->pri = MSG_HIPRI; + it->length = sizeof(struct T_error_ack); + it->next = Priv(fp)->pfirst; + + Priv(fp)->pfirst = it; + if (!Priv(fp)->plast) + Priv(fp)->plast = it; + timod_socket_wakeup(fp); +} + + +#if defined(CONFIG_ABI_XTI_OPTMGMT) || defined(CONFIG_ABI_TLI_OPTMGMT) +/* + * XXX: this function is a _horrible_ mess. + */ +static int +timod_optmgmt(int fd, struct pt_regs * regs, int flag, + char * opt_buf, int opt_len, int do_ret) +{ + struct file * fp = fcheck(fd); + char *ret_buf, *ret_base; + u_long old_esp, *tsp; + int is_tli, error, failed; + int ret_len, ret_space; + + if (opt_buf && opt_len > 0) { + error = verify_area(VERIFY_READ, opt_buf, opt_len); + if (error) + return error; + } + + /* + * FIXME: + * We should be able to detect the difference between + * TLI and XTI requests at run time? + */ + is_tli = CONFIG_ABI_TLI_OPTMGMT; + + 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 two + * longs 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 = 1024 + opt_len + + 2*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 CONFIG_ABI_TLI_OPTMGMT + if (is_tli) { + printk(KERN_WARNING + "%d iBCS: TLI optmgmt requested but not supported\n", + current->pid); + } +#else + if (is_tli) + while (opt_len >= sizeof(struct opthdr)) { + struct opthdr opt; + + abi_trace(ABI_TRACE_STREAMS, "TLI optmgmt opt_len=%d, " + "ret_buf=0x%08lx, ret_len=%d, ret_space=%d", + opt_len, (unsigned long)ret_buf, + ret_len, ret_space); + + copy_from_user(&opt, opt_buf, sizeof(struct opthdr)); + + /* Idiot check... */ + if (opt.len > opt_len) { + failed = TBADOPT; + break; + } + + if (abi_traced(ABI_TRACE_STREAMS)) { + unsigned long v; + get_user(v, (unsigned long *)(opt_buf+sizeof(struct opthdr))); + __abi_trace("TLI optmgmt fd=%d, level=%ld, " + "name=%ld, value=%ld", + fd, opt.level, opt.name, v); + } + + /* 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_user(fd, tsp); + put_user(opt.level, tsp+1); + put_user(opt.name, tsp+2); + put_user((int)(opt_buf+sizeof(struct opthdr)), tsp+3); + put_user(opt.len, tsp+4); + error = abi_do_setsockopt(tsp); + + if (error) { + abi_trace(ABI_TRACE_STREAMS, + "setsockopt failed: %d", error); + failed = TBADOPT; + break; + } + } + if (!error) { + int len; + + put_user(fd, tsp); + put_user(opt.level, tsp+1); + put_user(opt.name, tsp+2); + put_user((int)(ret_buf+sizeof(struct opthdr)), tsp+3); + put_user((int)(tsp+5), tsp+4); + put_user(ret_space, tsp+5); + error = abi_do_getsockopt(tsp); + + if (error) { + abi_trace(ABI_TRACE_STREAMS, + "getsockopt failed: %d", error); + failed = TBADOPT; + break; + } + + get_user(len, tsp+5); + copy_to_user(ret_buf, &opt, sizeof(opt)); + put_user(len, + &((struct opthdr *)opt_buf)->len); + ret_space -= sizeof(struct opthdr) + len; + ret_len += sizeof(struct opthdr) + len; + ret_buf += sizeof(struct opthdr) + len; + } + + opt_len -= sizeof(struct opthdr) + opt.len; + opt_buf += sizeof(struct opthdr) + opt.len; + } +#endif /* CONFIG_ABI_TLI_OPTMGMT */ +#ifndef CONFIG_ABI_XTI_OPTMGMT + else { + printk(KERN_WARNING + "%d iBCS: XTI optmgmt requested but not supported\n", + current->pid); + } +#else + else while (opt_len >= sizeof(struct t_opthdr)) { + struct t_opthdr opt; + + copy_from_user(&opt, opt_buf, sizeof(struct t_opthdr)); + if (opt.len > opt_len) { + failed = 1; + break; + } + + if (abi_traced(ABI_TRACE_STREAMS)) { + unsigned long v; + get_user(v, (unsigned long *)(opt_buf+sizeof(struct t_opthdr))); + __abi_trace("XTI optmgmt fd=%d, level=%ld, " + "name=%ld, value=%ld", + fd, opt.level, opt.name, v); + } + + /* 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. + * (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_user(fd, tsp); + put_user(opt.level, tsp+1); + put_user(opt.name, tsp+2); + put_user((int)(opt_buf+sizeof(struct t_opthdr)), tsp+3); + put_user(opt.len-sizeof(struct t_opthdr), tsp+4); + error = abi_do_setsockopt(tsp); + } + if (!error) { + put_user(fd, tsp); + put_user(opt.level, tsp+1); + put_user(opt.name, tsp+2); + put_user((int)(ret_buf+sizeof(struct t_opthdr)), tsp+3); + put_user((int)(tsp+5), tsp+4); + put_user(ret_space, tsp+5); + error = abi_do_getsockopt(tsp); + if (!error) { + int len; + get_user(len, tsp+5); + /* FIXME: opt.status should be set... */ + copy_to_user(ret_buf, &opt, sizeof(opt)); + put_user(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 /* CONFIG_ABI_XTI_OPTMGMT */ + +#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; + } + + abi_trace(ABI_TRACE_STREAMS, + "optmgmt returns %d bytes, failed=%d", + ret_len, failed); + + /* 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); + copy_from_user(((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(fp)->pfirst; + Priv(fp)->pfirst = it; + if (!Priv(fp)->plast) + Priv(fp)->plast = it; + timod_socket_wakeup(fp); + } + } + + regs->esp = old_esp; + return 0; +} + +#else /* no CONFIG_ABI_XTI_OPTMGMT or CONFIG_ABI_TLI_OPTMGMT */ + +static int +timod_optmgmt(int fd, struct pt_regs * regs, int flag, + char * opt_buf, int opt_len, int do_ret) +{ + return -EINVAL; +} + +#endif /* CONFIG_ABI_XTI_OPTMGMT or CONFIG_ABI_TLI_OPTMGMT */ + +#define T_PRIV(fp) Priv(fp) + +int +timod_update_socket(int fd, struct file * fp, struct pt_regs * regs) +{ + struct socket * sock; + struct T_private * priv; + struct T_primsg * it; + struct T_conn_ind * ind; + u_long old_esp, * tsp, alen; + u_short oldflags; + int error = 0; + + sock = socki_lookup(fp->f_dentry->d_inode); + priv = T_PRIV(fp); + + /* + * If this a SOCK_STREAM and is in the TS_WRES_CIND state + * we are supposed to be looking for an incoming connection. + */ + if (sock->type != SOCK_STREAM || priv->state != TS_WRES_CIND) + goto out; + + old_esp = regs->esp; + regs->esp -= 1024; + tsp = (unsigned long *)regs->esp; + error = verify_area(VERIFY_WRITE, tsp, + 3*sizeof(long)+sizeof(struct sockaddr)); + if (error) { + regs->esp = old_esp; + goto out; + } + + put_user(fd, tsp); + put_user((unsigned long)(tsp+4), tsp+1); + put_user((unsigned long)(tsp+3), tsp+2); + put_user(sizeof(struct sockaddr), tsp+3); + + /* + * We don't want to block in the accept(). Any + * blocking necessary must be handled earlier. + */ + oldflags = fp->f_flags; + fp->f_flags |= O_NONBLOCK; + error = SYS(socketcall)(SYS_ACCEPT, tsp); + fp->f_flags = oldflags; + + if (error < 0) + goto out_set; + + /* The new fd needs to be fixed up + * with the iBCS file functions and a + * timod state block. + */ + inherit_socksys_funcs(error, TS_DATA_XFER); + + /* Generate a T_CONN_IND and queue it. */ + get_user(alen, tsp+3); + it = timod_mkctl(sizeof(struct T_conn_ind) + alen); + if (!it) { + /* Oops, just drop the connection I guess. */ + SYS(close)(error); + goto out_set; + } + + ind = (struct T_conn_ind *)&it->type; + ind->PRIM_type = T_CONN_IND; + ind->SRC_length = alen; + ind->SRC_offset = sizeof(struct T_conn_ind); + ind->OPT_length = ind->OPT_offset = 0; + ind->SEQ_number = error; + + copy_from_user(((char *)ind)+sizeof(struct T_conn_ind), tsp+4, alen); +#if 0 + it->pri = MSG_HIPRI; +#endif + it->length = sizeof(struct T_conn_ind) + alen; + it->next = Priv(fp)->pfirst; + Priv(fp)->pfirst = it; + if (!Priv(fp)->plast) + Priv(fp)->plast = it; + timod_socket_wakeup(fp); + +out_set: + regs->esp = old_esp; +out: + return (error); +} + + +static int +do_getmsg(int fd, struct pt_regs *regs, + char *ctl_buf, int ctl_maxlen, int *ctl_len, + char *dat_buf, int dat_maxlen, int *dat_len, + int *flags_p) +{ + int error; + long old_esp; + unsigned long *tsp; + unsigned short oldflags; + struct T_unitdata_ind udi; + struct file *filep; + + /* + * It may not be obvious but we are always holding an fget(fd) + * at this point so we can use fcheck(fd) rather than fget...fput. + */ + filep = fcheck(fd); + + if (!Priv(filep) && Priv(filep)->magic != XTI_MAGIC) { + printk("putmsg on non-STREAMS fd %d by %s\n",fd, current->comm); + return -EINVAL; + } + + abi_trace(ABI_TRACE_STREAMS, + "getmsg %d, 0x%lx[%d], 0x%lx[%d], %x", + fd, (u_long)ctl_buf, ctl_maxlen, + (u_long)dat_buf, dat_maxlen, *flags_p); + + /* + * We need some user space to build syscall argument vectors + * later. Set it up now and page it in if necessary. This will + * avoid (most?) potential blocking after the select(). + */ + old_esp = regs->esp; + regs->esp -= 1024; + tsp = (unsigned long *)regs->esp; + error = verify_area(VERIFY_WRITE, tsp, 6*sizeof(long)); + regs->esp = old_esp; + if (error) + return error; + + /* + * If the TEP is not non-blocking we must test for + * something to do. We don't necessarily know what order + * events will be happening on the socket so we have to + * watch for evrything at once. + * N.B. If we weren't asked for data we should only be looking + * for connection requests. There are socket type issues to + * consider here. + */ + if (!(filep->f_flags & O_NONBLOCK)) { + poll_table wait_table, *wait; + unsigned long mask = (POLLIN | POLLRDNORM | POLLHUP | POLLERR); + + if (*flags_p == MSG_HIPRI) + mask |= POLLPRI; + + poll_initwait(&wait_table); + wait = &wait_table; + + /* + * N.B. We need to be sure to recheck after a schedule() + * so that when we proceed it is because there is + * something to do and nothing else can get there + * before us. + */ + while (!(filep->f_op->poll(filep, wait) & mask) + && !signal_pending(current)) { + current->state = TASK_INTERRUPTIBLE; + wait = NULL; + schedule(); + } + + current->state = TASK_RUNNING; + poll_freewait(&wait_table); + + if (signal_pending(current)) + return -EINTR; + } + + if (ctl_maxlen >= 0 && !Priv(filep)->pfirst) + timod_update_socket(fd, filep, regs); + + /* + * If we were asked for a control part and there is an outstanding + * message queued as a result of some other operation we'll + * return that. + */ + if (ctl_maxlen >= 0 && Priv(filep)->pfirst) { + int l = ctl_maxlen <= Priv(filep)->pfirst->length + ? ctl_maxlen : Priv(filep)->pfirst->length; + error = verify_area(VERIFY_WRITE, ctl_buf, l); + if (error) + return error; + + abi_trace(ABI_TRACE_STREAMS, + "priority message %ld %s", + Priv(filep)->pfirst->type, + xti_prim(Priv(filep)->pfirst->type)); + + copy_to_user(ctl_buf, ((char *)&Priv(filep)->pfirst->type) + + Priv(filep)->offset, l); + put_user(l, ctl_len); + if (dat_maxlen >= 0) + put_user(0, dat_len); + *flags_p = Priv(filep)->pfirst->pri; + Priv(filep)->pfirst->length -= l; + + if (abi_traced(ABI_TRACE_STREAMS) && ctl_buf && l > 0) { + int i = -1; + + for (i = 0; i < l && i < 64; i += 4) { + u_long v; + + get_user(v, (u_long *)(ctl_buf + i)); + __abi_trace("ctl: 0x%08lx", v); + } + if (i != l) + __abi_trace("ctl: ..."); + } + + if (Priv(filep)->pfirst->length) { + Priv(filep)->offset += l; + + abi_trace(ABI_TRACE_STREAMS, + "MORECTL %d bytes", + Priv(filep)->pfirst->length); + return MORECTL; + } else { + struct T_primsg *it = Priv(filep)->pfirst; + Priv(filep)->pfirst = it->next; + if (!Priv(filep)->pfirst) + Priv(filep)->plast = NULL; + kfree(it); + Priv(filep)->offset = 0; + return 0; + } + } + + *flags_p = 0; + + /* If we weren't asked for data there is nothing more to do. */ + if (dat_maxlen <= 0) { + if (dat_maxlen == 0) + put_user(0, dat_len); + if (ctl_maxlen >= 0) + put_user(0, ctl_len); + return -EAGAIN; + } + + /* If the select() slept we may have had our temp space paged + * out. The re-verify_area is only really needed for pre-486 + * chips which don't handle write faults from kernel mode. + */ + regs->esp = (unsigned long)tsp; + error = verify_area(VERIFY_WRITE, tsp, 6*sizeof(long)); + if (error) { + regs->esp = old_esp; + return error; + } + put_user(fd, tsp); + put_user((unsigned long)dat_buf, tsp+1); + put_user((dat_maxlen < 0 ? 0 : dat_maxlen), tsp+2); + put_user(0, tsp+3); + if (ctl_maxlen > (int)sizeof(udi) && Priv(filep)->state == TS_IDLE) { + put_user((unsigned long)ctl_buf+sizeof(udi), tsp+4); + put_user(ctl_maxlen-sizeof(udi), ctl_len); + put_user((int)ctl_len, tsp+5); + } else { + put_user(0, tsp+4); + put_user(0, ctl_len); + put_user((int)ctl_len, tsp+5); + } + + /* We don't want to block in the recvfrom(). Any blocking is + * handled by the select stuff above. + */ + oldflags = filep->f_flags; + filep->f_flags |= O_NONBLOCK; + error = SYS(socketcall)(SYS_RECVFROM, tsp); + filep->f_flags = oldflags; + + regs->esp = old_esp; + if (error < 0) + return error; + if (error + && ctl_maxlen > (int)sizeof(udi) + && Priv(filep)->state == TS_IDLE) { + udi.PRIM_type = T_UNITDATA_IND; + get_user(udi.SRC_length, ctl_len); + udi.SRC_offset = sizeof(udi); + udi.OPT_length = udi.OPT_offset = 0; + copy_to_user(ctl_buf, &udi, (int)sizeof(udi)); + put_user(sizeof(udi)+udi.SRC_length, ctl_len); +#if 0 + if (abi_traced(ABI_TRACE_STREAMS) && + ctl_buf && udi.SRC_length > 0) { + char * buf = ctl_buf + sizeof(udi); + int i = -1; + + for (i = 0; i < udi.SRC_length && + i < 64; i += 4) { + u_long v; + + get_user(v, (u_long *)(buf+i)); + __abi_trace("dat: 0x%08lx", v); + } + if (i != udi.SRC_length) + __abi_trace("dat: ..."); + } +#endif + } else { + put_user(0, ctl_len); + } + put_user(error, dat_len); + + return 0; +} + + +static int +do_putmsg(int fd, struct pt_regs *regs, char *ctl_buf, int ctl_len, + char *dat_buf, int dat_len, int flags) +{ + struct file *filep; + int error, terror; + unsigned long cmd; + + /* It may not be obvious but we are always holding an fget(fd) + * at this point so we can use fcheck(fd) rather than fget...fput. + */ + filep = fcheck(fd); + + if (!Priv(filep) && Priv(filep)->magic != XTI_MAGIC) { + printk("putmsg on non-STREAMS fd %d by %s\n",fd, current->comm); + return -EINVAL; + } + + if (abi_traced(ABI_TRACE_STREAMS)) { + u_long v; + __abi_trace("putmsg %d, 0x%lx[%d], 0x%lx[%d], %x", + fd, (u_long)ctl_buf, ctl_len, + (u_long)dat_buf, dat_len, flags); + + get_user(v, ctl_buf); + __abi_trace("putmsg prim: %ld %s", v, xti_prim(v)); + + if (ctl_buf && ctl_len > 0) { + int i = -1; + + for (i = 0; i < ctl_len && i < 64; i += 4) { + u_long v; + + get_user(v, (u_long *)(ctl_buf + i)); + __abi_trace("ctl: 0x%08lx", v); + } + if (i != ctl_len) + __abi_trace("ctl: ..."); + } + + if (dat_buf && dat_len > 0) { + int i = -1; + + for (i = 0; i < dat_len && i < 64; i += 4) { + u_long v; + + get_user(v, (u_long *)(dat_buf + i)); + __abi_trace("dat: 0x%08lx", v); + } + if (i != dat_len) + __abi_trace("dat: ..."); + } + } + + error = get_user(cmd, (unsigned long *)ctl_buf); + if (error) + return error; + + switch (cmd) { + case T_BIND_REQ: { + struct T_bind_req req; + long old_esp; + unsigned long *tsp; + + abi_trace(ABI_TRACE_STREAMS, "%u bind req", fd); + + error = verify_area(VERIFY_READ, ctl_buf, sizeof(req)); + if (error) + return error; + + if (Priv(filep)->state != TS_UNBND) { + timod_error(fd, T_BIND_REQ, TOUTSTATE, 0); + return 0; + } + + old_esp = regs->esp; + regs->esp -= 1024; + tsp = (unsigned long *)(regs->esp); + error = verify_area(VERIFY_WRITE, tsp, 3*sizeof(long)); + if (error) { + timod_error(fd, T_BIND_REQ, TSYSERR, -error); + regs->esp = old_esp; + return 0; + } + + copy_from_user(&req, ctl_buf, sizeof(req)); + if (req.ADDR_offset && req.ADDR_length) { + struct sockaddr_in *sin; + unsigned short family; + +#if 1 /* Wheee... Kludge time... */ + sin = (struct sockaddr_in *)(ctl_buf + + req.ADDR_offset); + get_user(family, &sin->sin_family); + + /* Sybase seems to have set up the address + * struct with sa->sa_family = htons(AF_?) + * which is bollocks. I have no idea why it + * apparently works on SCO?!? + */ + if (family && !(family & 0x00ff)) + put_user(ntohs(family), &sin->sin_family); +#endif + + put_user(fd, tsp); + put_user((unsigned long)ctl_buf + + req.ADDR_offset, tsp+1); + /* For TLI/XTI the length may be the 8 *used* + * bytes, for (IP?) sockets it must be the 16 + * *total* bytes in a sockaddr_in. + */ + put_user(req.ADDR_length == 8 + ? 16 : req.ADDR_length, + tsp+2); + error = SYS(socketcall)(SYS_BIND, tsp); + + if (!error) { + if (req.CONIND_number) { + + abi_trace(ABI_TRACE_STREAMS, + "%u listen backlog=%lu", + fd, req.CONIND_number); + + put_user(fd, tsp); + put_user(req.CONIND_number, tsp+1); + SYS(socketcall)(SYS_LISTEN, tsp); + Priv(filep)->state = TS_WRES_CIND; + } else { + Priv(filep)->state = TS_IDLE; + } + } + } else { + error = 0; + } + + regs->esp = old_esp; + + if (!error) { + struct T_primsg *it; + it = timod_mkctl(ctl_len); + if (it) { + struct T_bind_ack *ack = (struct T_bind_ack *)&it->type; + copy_from_user(ack, ctl_buf, ctl_len); + ack->PRIM_type = T_BIND_ACK; + it->pri = MSG_HIPRI; + it->length = ctl_len; + it->next = NULL; + timod_ok(fd, T_BIND_REQ); + Priv(filep)->plast->next = it; + Priv(filep)->plast = it; + return 0; + } + } + switch (error) { + case -EINVAL: + terror = TOUTSTATE; + error = 0; + break; + case -EACCES: + terror = TACCES; + error = 0; + break; + case -EADDRNOTAVAIL: + case -EADDRINUSE: + terror = TNOADDR; + error = 0; + break; + default: + terror = TSYSERR; + break; + } + timod_error(fd, T_BIND_REQ, terror, -error); + return 0; + } + case T_CONN_RES: { + struct T_conn_res *res = (struct T_conn_res *)ctl_buf; + unsigned int conn_fd; + + error = get_user(conn_fd, &res->SEQ_number); + if (error) + return error; + + abi_trace(ABI_TRACE_STREAMS, + "%u accept: conn fd=%u, use fd=%u\n", + fd, conn_fd, flags); + + if (conn_fd != flags) { + error = SYS(dup2)(conn_fd, flags); + SYS(close)(conn_fd); + if (error < 0) + return error; + } + timod_ok(fd, T_CONN_RES); + return 0; + } + case T_CONN_REQ: { + struct T_conn_req req; + long old_esp; + unsigned short oldflags; + unsigned long *tsp; + struct T_primsg *it; + struct sockaddr_in *sin; + unsigned short family; + + abi_trace(ABI_TRACE_STREAMS, "%u connect req", fd); + + error = verify_area(VERIFY_READ, ctl_buf, sizeof(req)); + if (error) + return error; + + if (Priv(filep)->state != TS_UNBND + && Priv(filep)->state != TS_IDLE) { + timod_error(fd, T_CONN_REQ, TOUTSTATE, 0); + return 0; + } + + old_esp = regs->esp; + regs->esp -= 1024; + tsp = (unsigned long *)(regs->esp); + error = verify_area(VERIFY_WRITE, tsp, 3*sizeof(long)); + if (error) { + timod_error(fd, T_CONN_REQ, TSYSERR, -error); + regs->esp = old_esp; + return 0; + } + copy_from_user(&req, ctl_buf, sizeof(req)); + put_user(fd, tsp); + put_user((unsigned long)ctl_buf + req.DEST_offset, tsp+1); + /* For TLI/XTI the length may be the 8 *used* + * bytes, for (IP?) sockets it must be the 16 + * *total* bytes in a sockaddr_in. + */ + put_user(req.DEST_length == 8 + ? 16 : req.DEST_length, + tsp+2); + +#if 1 /* Wheee... Kludge time... */ + sin = (struct sockaddr_in *)(ctl_buf + + req.DEST_offset); + get_user(family, &sin->sin_family); + + /* Sybase seems to have set up the address + * struct with sa->sa_family = htons(AF_?) + * which is bollocks. I have no idea why it + * apparently works on SCO?!? + */ + if (family && !(family & 0x00ff)) { + family = ntohs(family); + put_user(family, &sin->sin_family); + } + + /* Sheesh... ISC telnet seems to give the port + * number low byte first as I expected but the + * X programs seem to be giving high byte first. + * One is broken of course but clearly both + * should work. No, I don't understand this + * either but I can at least try... + * A better solution would be for you to change + * the definition of xserver0 in ISC's /etc/services + * but then it wouldn't work out of the box... + */ + if (personality(PER_SVR4) && family == AF_INET) { + get_user(family, &sin->sin_port); + if (family == 0x1770) + put_user(htons(family), + &sin->sin_port); + } +#endif + /* FIXME: We should honour non-blocking mode + * here but that means that the select probe + * needs to know that if select returns ok and + * we are in T_OUTCON we have a connection + * completion. This isn't so bad but the real + * problem is that the connection acknowledgement + * is supposed to contain the destination + * address. + */ + oldflags = filep->f_flags; + filep->f_flags &= ~O_NONBLOCK; + error = SYS(socketcall)(SYS_CONNECT, tsp); + filep->f_flags = oldflags; + regs->esp = old_esp; + + if (!error) { + struct T_conn_con *con; + + it = timod_mkctl(ctl_len); + if (!it) + return -ENOMEM; + it->length = ctl_len; + con = (struct T_conn_con *)&it->type; + copy_from_user(con, ctl_buf, ctl_len); + con->PRIM_type = T_CONN_CON; + Priv(filep)->state = TS_DATA_XFER; + } else { + struct T_discon_ind *dis; + + abi_trace(ABI_TRACE_STREAMS, + "%u connect failed (errno=%d)", + fd, error); + + it = timod_mkctl(sizeof(struct T_discon_ind)); + if (!it) + return -ENOMEM; + it->length = sizeof(struct T_discon_ind); + dis = (struct T_discon_ind *)&it->type; + dis->PRIM_type = T_DISCON_IND; + dis->DISCON_reason = iABI_errors(-error); + dis->SEQ_number = 0; + } + timod_ok(fd, T_CONN_REQ); + it->pri = 0; + it->next = NULL; + Priv(filep)->plast->next = it; + Priv(filep)->plast = it; + return 0; + } + + case T_DISCON_REQ: { + struct T_discon_req *req; + + req = (struct T_discon_req *)ctl_buf; + error = get_user(fd, &req->SEQ_number); + if (error) + return error; + + abi_trace(ABI_TRACE_STREAMS, "disconnect %u", fd); + /* Fall through... */ + } + case T_ORDREL_REQ: { + SYS(close)(fd); + return 0; + } + + case T_DATA_REQ: { + long old_esp; + unsigned long *tsp; + + abi_trace(ABI_TRACE_STREAMS, "%u data req", fd); + + if (Priv(filep)->state != TS_DATA_XFER) { + return 0; + } + + old_esp = regs->esp; + regs->esp -= 1024; + tsp = (unsigned long *)(regs->esp); + error = verify_area(VERIFY_WRITE, tsp, 6*sizeof(long)); + if (error) { + regs->esp = old_esp; + return 0; + } + put_user(fd, tsp); + put_user((unsigned long)dat_buf, tsp+1); + put_user(dat_len, tsp+2); + put_user(0, tsp+3); + error = SYS(socketcall)(SYS_SEND, tsp); + regs->esp = old_esp; + return error; + } + + case T_UNITDATA_REQ: { + struct T_unitdata_req req; + long old_esp; + unsigned long *tsp; + + + abi_trace(ABI_TRACE_STREAMS, "%u unitdata req", fd); + + error = verify_area(VERIFY_READ, ctl_buf, sizeof(req)); + if (error) + return error; + + if (Priv(filep)->state != TS_IDLE + && Priv(filep)->state != TS_DATA_XFER) { + timod_error(fd, T_UNITDATA_REQ, TOUTSTATE, 0); + return 0; + } + + old_esp = regs->esp; + regs->esp -= 1024; + tsp = (unsigned long *)(regs->esp); + error = verify_area(VERIFY_WRITE, tsp, 6*sizeof(long)); + if (error) { + timod_error(fd, T_UNITDATA_REQ, TSYSERR, -error); + regs->esp = old_esp; + return 0; + } + put_user(fd, tsp); + put_user((unsigned long)dat_buf, tsp+1); + put_user(dat_len, tsp+2); + put_user(0, tsp+3); + copy_from_user(&req, ctl_buf, sizeof(req)); + if (req.DEST_length > 0) { + put_user((unsigned long)(ctl_buf+req.DEST_offset), tsp+4); + put_user(req.DEST_length, tsp+5); + error = SYS(socketcall)(SYS_SENDTO, tsp); + regs->esp = old_esp; + return error; + } + error = SYS(socketcall)(SYS_SEND, tsp); + regs->esp = old_esp; + return error; + } + + case T_UNBIND_REQ: + Priv(filep)->state = TS_UNBND; + timod_ok(fd, T_UNBIND_REQ); + return 0; + + case T_OPTMGMT_REQ: { + struct T_optmgmt_req req; + + abi_trace(ABI_TRACE_STREAMS, "%u optmgmt req", fd); + + error = verify_area(VERIFY_READ, ctl_buf, sizeof(req)); + if (error) + return error; + copy_from_user(&req, ctl_buf, sizeof(req)); + + return timod_optmgmt(fd, regs, req.MGMT_flags, + req.OPT_offset > 0 + ? ctl_buf+req.OPT_offset + : NULL, + req.OPT_length, + 1); + } + } + if (!abi_traced(ABI_TRACE_STREAMS)) + goto err; + + if (ctl_buf && ctl_len > 0) { + int i; + + for (i = 0; i < ctl_len && i < 32; i += 4) { + u_long v; + + get_user(v, (u_long *)(ctl_buf + i)); + __abi_trace("ctl: 0x%08lx\n", v); + } + if (i != ctl_len) + __abi_trace("ctl: ...\n"); + } + if (dat_buf && dat_len > 0) { + int i; + for (i = 0; i < dat_len && i < 32; i += 4) { + u_long v; + + get_user(v, (u_long *)(dat_buf + i)); + __abi_trace("dat: 0x%08lx\n", v); + } + if (i != dat_len) + __abi_trace("dat: ...\n"); + } +err: + return -EINVAL; +} + + +int +timod_ioctl(struct pt_regs *regs, + int fd, unsigned int func, void *arg, int len, int *len_p) +{ + struct file *filep; + struct inode *ino; + int error; + + filep = fget(fd); + if (!filep) + return TBADF; + + error = verify_area(VERIFY_WRITE, len_p, sizeof(int)); + if (error) { + fput(filep); + return (-error << 8) | TSYSERR; + } + + ino = filep->f_dentry->d_inode; + + /* SCO/SVR3 starts at 100, ISC/SVR4 starts at 140. */ + switch (func >= 140 ? func-140 : func-100) { + case 0: /* TI_GETINFO */ + { + struct T_info_ack it; + unsigned long v; + + abi_trace(ABI_TRACE_STREAMS, "%u getinfo", fd); + + /* The pre-SVR4 T_info_ack structure didn't have + * the PROVIDER_flag on the end. + */ + error = verify_area(VERIFY_WRITE, arg, + func == 140 + ? sizeof(struct T_info_ack) + : sizeof(struct T_info_ack)-sizeof(long)); + if (error) { + fput(filep); + return (-error << 8) | TSYSERR; + } + + __get_user(v, &((struct T_info_req *)arg)->PRIM_type); + if (v != T_INFO_REQ) { + fput(filep); + return (EINVAL << 8) | TSYSERR; + } + + it.PRIM_type = T_INFO_ACK; + it.CURRENT_state = Priv(filep)->state; + it.CDATA_size = -2; + it.DDATA_size = -2; + it.OPT_size = -1; + it.TIDU_size = 16384; + switch ((MINOR(ino->i_rdev)>>4) & 0x0f) { + case AF_UNIX: + it.ADDR_size = sizeof(struct sockaddr_un); + break; + case AF_INET: + it.ADDR_size = sizeof(struct sockaddr_in); + break; + default: + /* Uh... dunno... play safe(?) */ + it.ADDR_size = 1024; + break; + } + switch (ino->u.socket_i.type) { + case SOCK_STREAM: + it.ETSDU_size = 1; + it.TSDU_size = 0; + it.SERV_type = 2; + break; + default: + it.ETSDU_size = -2; + it.TSDU_size = 16384; + it.SERV_type = 3; + break; + } + + fput(filep); + + /* The pre-SVR4 T_info_ack structure didn't have + * the PROVIDER_flag on the end. + */ + if (func == 140) { + it.PROVIDER_flag = 0; + copy_to_user(arg, &it, sizeof(it)); + put_user(sizeof(it), len_p); + return 0; + } + copy_to_user(arg, &it, sizeof(it)-sizeof(long)); + put_user(sizeof(it)-sizeof(long), len_p); + return 0; + } + + case 2: /* TI_BIND */ + { + int i; + long prim; + + abi_trace(ABI_TRACE_STREAMS, "%u bind", fd); + + error = do_putmsg(fd, regs, arg, len, + NULL, -1, 0); + if (error) { + fput(filep); + return (-error << 8) | TSYSERR; + } + + /* Get the response. This should be either + * T_OK_ACK or T_ERROR_ACK. + */ + i = MSG_HIPRI; + error = do_getmsg(fd, regs, + arg, len, len_p, + NULL, -1, NULL, + &i); + if (error) { + fput(filep); + return (-error << 8) | TSYSERR; + } + + get_user(prim, (unsigned long *)arg); + if (prim == T_ERROR_ACK) { + unsigned long a, b; + fput(filep); + get_user(a, ((unsigned long *)arg)+3); + get_user(b, ((unsigned long *)arg)+2); + return (a << 8) | b; + } + if (prim != T_OK_ACK) { + fput(filep); + return TBADSEQ; + } + + /* Get the response to the bind request. */ + i = MSG_HIPRI; + error = do_getmsg(fd, regs, + arg, len, len_p, + NULL, -1, NULL, + &i); + fput(filep); + if (error) + return (-error << 8) | TSYSERR; + + return 0; + } + + case 3: /* TI_UNBIND */ + if (Priv(filep)->state != TS_IDLE) { + fput(filep); + return TOUTSTATE; + } + Priv(filep)->state = TS_UNBND; + fput(filep); + return 0; + + case 1: { /* TI_OPTMGMT */ +#if defined(CONFIG_ABI_XTI_OPTMGMT) || defined(CONFIG_ABI_TLI_OPTMGMT) + int i; + long prim; + + abi_trace(ABI_TRACE_STREAMS, "%u optmgmt", fd); + + error = do_putmsg(fd, regs, arg, len, + NULL, -1, 0); + if (error) { + fput(filep); + return (-error << 8) | TSYSERR; + } + + /* 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 > 0) { + /* If there is excess data in the response + * our buffer is too small which implies + * the application is broken. SO_LINGER + * is a common fault. Because it works + * on other systems we attempt to recover + * by discarding the excess. + */ + struct T_primsg *it = Priv(filep)->pfirst; + Priv(filep)->pfirst = it->next; + if (!Priv(filep)->pfirst) + Priv(filep)->plast = NULL; + kfree(it); + Priv(filep)->offset = 0; + + abi_trace(ABI_TRACE_STREAMS, + "excess discarded"); + } + + fput(filep); + + if (error < 0) + return (-error << 8) | TSYSERR; + + __get_user(prim, (unsigned long *)arg); + if (prim == T_ERROR_ACK) { + unsigned long a, b; + __get_user(a, ((unsigned long *)arg)+3); + __get_user(b, ((unsigned long *)arg)+2); + return (a << 8) | b; + } + + return 0; +#else /* no CONFIG_ABI_XTI_OPTMGMT or CONFIG_ABI_TLI_OPTMGMT */ + fput(filep); + return TNOTSUPPORT; +#endif /* CONFIG_ABI_XTI_OPTMGMT or CONFIG_ABI_TLI_OPTMGMT */ + } + + case 4: /* TI_GETMYNAME */ + case 5: /* TI_SETPEERNAME */ + case 6: /* TI_GETMYNAME */ + case 7: /* TI_SETPEERNAME */ + } + + abi_trace(ABI_TRACE_STREAMS, + "STREAMS timod op %d not supported", func); + + fput(filep); + return TNOTSUPPORT; +} + + +int svr4_ioctl_sockmod(int fd, unsigned int func, void *arg) +{ + struct file *filep; + struct inode *ino; + int error; + + filep = fget(fd); + if (!filep) + return TBADF; + ino = filep->f_dentry->d_inode; + + if (MAJOR(ino->i_rdev) == SOCKSYS_MAJOR) { + error = abi_socksys_fd_init(fd, 0, NULL, NULL); + if (error < 0) + return error; + fput(filep); + filep = fget(fd); + if (!filep) + return TBADF; + ino = filep->f_dentry->d_inode; + } + + switch (func) { +#ifdef __sparc__ + case 110: { /* SI_GETUDATA -- Solaris */ + struct { + int tidusize, addrsize, optsize, etsdusize; + int servtype, so_state, so_options; + int tsdusize; + + /* Socket parameters */ + int family, type, protocol; + } *it = arg; + + abi_trace(ABI_TRACE_STREAMS, "%u new_getudata", fd); + + error = verify_area(VERIFY_WRITE, it, sizeof(*it)); + if (error) { + fput(filep); + return (-error << 8) | TSYSERR; + } + + __put_user(16384, &it->tidusize); + __put_user(sizeof(struct sockaddr), &it->addrsize); + __put_user(-1, &it->optsize); + __put_user(0, &it->so_state); + __put_user(0, &it->so_options); + __put_user(16384, &it->tsdusize); + + switch (ino->u.socket_i.type) { + case SOCK_STREAM: + __put_user(1, &it->etsdusize); + __put_user(2, &it->servtype); + break; + default: + __put_user(-2, &it->etsdusize); + __put_user(3, &it->servtype); + break; + } + __put_user (ino->u.socket_i.ops->family, &it->family); + __put_user (ino->u.socket_i.type, &it->type); + __put_user (ino->u.socket_i.ops->family, &it->protocol); + fput(filep); + return 0; + } + +#endif + case 101: { /* SI_GETUDATA */ + struct { + int tidusize, addrsize, optsize, etsdusize; + int servtype, so_state, so_options; +#ifdef __sparc__ + int tsdusize; +#endif + } *it = arg; + + abi_trace(ABI_TRACE_STREAMS, "%u getudata", fd); + + error = verify_area(VERIFY_WRITE, it, sizeof(*it)); + if (error) { + fput(filep); + return (-error << 8) | TSYSERR; + } + + __put_user(16384, &it->tidusize); + __put_user(sizeof(struct sockaddr), &it->addrsize); + __put_user(-1, &it->optsize); + __put_user(0, &it->so_state); + __put_user(0, &it->so_options); + +#ifdef __sparc__ + __put_user(16384, &it->tsdusize); +#endif + switch (ino->u.socket_i.type) { + case SOCK_STREAM: + __put_user(1, &it->etsdusize); + __put_user(2, &it->servtype); + break; + default: + __put_user(-2, &it->etsdusize); + __put_user(3, &it->servtype); + break; + } + fput(filep); + return 0; + } + + case 102: /* SI_SHUTDOWN */ + case 103: /* SI_LISTEN */ + case 104: /* SI_SETMYNAME */ + case 105: /* SI_SETPEERNAME */ + case 106: /* SI_GETINTRANSIT */ + case 107: /* SI_TCL_LINK */ + case 108: /* SI_TCL_UNLINK */ + } + + abi_trace(ABI_TRACE_STREAMS, + "STREAMS sockmod op %d not supported", func); + + fput(filep); + return TNOTSUPPORT; +} +EXPORT_SYMBOL(svr4_ioctl_sockmod); +#endif /* CONFIG_ABI_XTI */ + + +#if defined(CONFIG_ABI_XTI) || defined(CONFIG_ABI_IBCS_SPX) + +int timod_getmsg(int fd, struct inode *ino, int is_pmsg, struct pt_regs *regs) +{ + struct strbuf *ctlptr, *datptr; + int *flags_p, flags, *band_p; + int error; + struct strbuf ctl, dat; + struct file *filep; + + ctlptr = (struct strbuf *) get_syscall_parameter (regs, 1); + datptr = (struct strbuf *) get_syscall_parameter (regs, 2); + if (!is_pmsg) { + flags_p = (int *) get_syscall_parameter (regs, 3); + } else { + band_p = (int *) get_syscall_parameter (regs, 3); + flags_p = (int *) get_syscall_parameter (regs, 4); + error = verify_area(VERIFY_WRITE, band_p, sizeof(int)); + if (error) + return error; + } + + error = verify_area(VERIFY_WRITE, flags_p, sizeof(int)); + if (error) + return error; + + if (ctlptr) { + error = verify_area(VERIFY_WRITE, ctlptr, sizeof(ctl)); + if (error) + return error; + __copy_from_user(&ctl, ctlptr, sizeof(ctl)); + __put_user(-1, &ctlptr->len); + } else { + ctl.maxlen = -1; + } + + if (datptr) { + error = verify_area(VERIFY_WRITE, datptr, sizeof(dat)); + if (error) + return error; + __copy_from_user(&dat, datptr, sizeof(dat)); + __put_user(-1, &datptr->len); + } else { + dat.maxlen = -1; + } + + error = verify_area(VERIFY_WRITE, flags_p, sizeof(int)); + if (error) + return error; + __get_user(flags, flags_p); + +#ifdef CONFIG_ABI_IBCS_SPX + if (MAJOR(ino->i_rdev) == SOCKSYS_MAJOR && MINOR(ino->i_rdev) == 1) { + abi_trace(ABI_TRACE_STREAMS, + "%d getmsg offers descriptor %d", fd, fd); + __put_user((u_long)fd, (u_long *)ctl.buf); + __put_user(4, &ctlptr->len); + return 0; + } +#endif /* CONFIG_ABI_IBCS_SPX */ + +#ifdef CONFIG_ABI_XTI + if (flags != 0 && flags != MSG_HIPRI && flags != MSG_ANY + && flags != MSG_BAND) { + abi_trace(ABI_TRACE_STREAMS, + "%d getmsg flags value bad (%d)", fd, flags); + return -EINVAL; + } + + filep = fget(fd); + error = do_getmsg(fd, regs, + ctl.buf, ctl.maxlen, &ctlptr->len, + dat.buf, dat.maxlen, &datptr->len, + &flags); + fput(filep); + if (error >= 0) + put_user(flags, flags_p); + return error; +#else /* CONFIG_ABI_XTI */ + return -EINVAL; +#endif /* CONFIG_ABI_XTI */ +} + + +int timod_putmsg(int fd, struct inode *ino, int is_pmsg, struct pt_regs *regs) +{ + struct strbuf *ctlptr, *datptr; + int flags, error, band; + struct strbuf ctl, dat; + + ctlptr = (struct strbuf *)get_syscall_parameter (regs, 1); + datptr = (struct strbuf *)get_syscall_parameter (regs, 2); + if (!is_pmsg) { + flags = (int)get_syscall_parameter (regs, 3); + } else { + band = (int)get_syscall_parameter (regs, 3); + flags = (int)get_syscall_parameter (regs, 4); + } + + if (ctlptr) { + error = copy_from_user(&ctl, ctlptr, sizeof(ctl)); + if (error) + return -EFAULT; + if (ctl.len < 0 && flags) + return -EINVAL; + } else { + ctl.len = 0; + ctl.buf = NULL; + } + + if (datptr) { + error = copy_from_user(&dat, datptr, sizeof(dat)); + if (error) + return -EFAULT; + } else { + dat.len = 0; + dat.buf = NULL; + } + +#ifdef CONFIG_ABI_IBCS_SPX + if (MAJOR(ino->i_rdev) == SOCKSYS_MAJOR && MINOR(ino->i_rdev) == 1) { + unsigned int newfd; + + if (ctl.len != 4) + return -EIO; + + get_user(newfd, (unsigned int *)ctl.buf); + abi_trace(ABI_TRACE_STREAMS, + "%d putmsg dups descriptor %d", fd, newfd); + error = SYS(dup2)(newfd, fd); + if (error < 0) + return error; + + return 0; + } +#endif /* CONFIG_ABI_IBCS_SPX */ + +#ifdef CONFIG_ABI_XTI + return do_putmsg(fd, regs, ctl.buf, ctl.len, + dat.buf, dat.len, flags); +#else /* CONFIG_ABI_XTI */ + return -EINVAL; +#endif /* CONFIG_ABI_XTI */ +} + +int stream_fdinsert(struct pt_regs *regs, int fd, struct strfdinsert *arg) +{ + struct strfdinsert sfd; + int error; + + error = copy_from_user(&sfd, arg, sizeof(sfd)); + if (error) + return -EFAULT; + + abi_trace(ABI_TRACE_STREAMS, + "%u fdinsert: flags=%ld, fildes=%u, offset=%d", + fd, sfd.flags, sfd.fildes, sfd.offset); + + return do_putmsg(fd, regs, sfd.ctlbuf.buf, sfd.ctlbuf.len, + sfd.datbuf.buf, sfd.datbuf.len, sfd.fildes); +} + +#endif /* defined(CONFIG_ABI_XTI) || defined(CONFIG_ABI_IBCS_SPX) */ diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/ulimit.c linux/abi/svr4/ulimit.c --- linux-2.4.3/abi/svr4/ulimit.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/ulimit.c Sun Mar 18 11:54:28 2001 @@ -0,0 +1,148 @@ +/* $Id$ + * + * Copyright (C) 1993 Joe Portman (baron@hebron.connected.com) + * First stab at ulimit + * + * April 9 1994, corrected file size passed to/from setrlimit/getrlimit + * -- Graham Adams (gadams@ddrive.demon.co.uk) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * Arguments to ulimit - it's one of the stupid multipled calls... + */ +#define U_GETFSIZE (1) /* get max file size in blocks */ +#define U_SETFSIZE (2) /* set max file size in blocks */ +#define U_GETMEMLIM (3) /* get process size limit */ +#define U_GETMAXOPEN (4) /* get max open files for this process */ +#define U_GTXTOFF (64) /* get text offset */ + +/* + * Define nominal block size parameters. + */ +#define ULIM_BLOCKSIZE_BITS 9 /* block size = 512 */ +#define ULIM_MAX_BLOCKSIZE (INT_MAX >> ULIM_BLOCKSIZE_BITS) + + +int +svr4_ulimit (int cmd, int val) +{ + switch (cmd) { + case U_GETFSIZE: + return (current->rlim[RLIMIT_FSIZE].rlim_cur) >> ULIM_BLOCKSIZE_BITS; + + case U_SETFSIZE: + if ((val > ULIM_MAX_BLOCKSIZE) || (val < 0)) + return -ERANGE; + val <<= ULIM_BLOCKSIZE_BITS; + if (val > current->rlim[RLIMIT_FSIZE].rlim_max) { + if (!capable(CAP_SYS_RESOURCE)) + return -EPERM; + current->rlim[RLIMIT_FSIZE].rlim_max = val; + } + current->rlim[RLIMIT_FSIZE].rlim_cur = val; + return 0; + + case U_GETMEMLIM: + return current->rlim[RLIMIT_DATA].rlim_cur; + + case U_GETMAXOPEN: + return current->rlim[RLIMIT_NOFILE].rlim_cur; + + default: + abi_trace(ABI_TRACE_API, "unsupported ulimit call %d", cmd); + return -EINVAL; + } +} +EXPORT_SYMBOL(svr4_ulimit); + + +/* + * getrlimit/setrlimit args. + */ +#define U_RLIMIT_CPU 0 +#define U_RLIMIT_FSIZE 1 +#define U_RLIMIT_DATA 2 +#define U_RLIMIT_STACK 3 +#define U_RLIMIT_CORE 4 +#define U_RLIMIT_NOFILE 5 +#define U_RLIMIT_AS 6 + + +int +svr4_getrlimit(int cmd, void *val) +{ + switch (cmd) { + case U_RLIMIT_CPU: + cmd = RLIMIT_CPU; + break; + case U_RLIMIT_FSIZE: + cmd = RLIMIT_FSIZE; + break; + case U_RLIMIT_DATA: + cmd = RLIMIT_DATA; + break; + case U_RLIMIT_STACK: + cmd = RLIMIT_STACK; + break; + case U_RLIMIT_CORE: + cmd = RLIMIT_CORE; + break; + case U_RLIMIT_NOFILE: + cmd = RLIMIT_NOFILE; + break; + case U_RLIMIT_AS: + cmd = RLIMIT_AS; + break; + default: + return -EINVAL; + } + + return SYS(getrlimit)(cmd, val); +} +EXPORT_SYMBOL(svr4_getrlimit); + +int +svr4_setrlimit(int cmd, void *val) +{ + switch (cmd) { + case U_RLIMIT_CPU: + cmd = RLIMIT_CPU; + break; + case U_RLIMIT_FSIZE: + cmd = RLIMIT_FSIZE; + break; + case U_RLIMIT_DATA: + cmd = RLIMIT_DATA; + break; + case U_RLIMIT_STACK: + cmd = RLIMIT_STACK; + break; + case U_RLIMIT_CORE: + cmd = RLIMIT_CORE; + break; + case U_RLIMIT_NOFILE: + cmd = RLIMIT_NOFILE; + break; + case U_RLIMIT_AS: + cmd = RLIMIT_AS; + break; + default: + return -EINVAL; + } + + return SYS(getrlimit)(cmd, val); +} +EXPORT_SYMBOL(svr4_setrlimit); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/utsname.c linux/abi/svr4/utsname.c --- linux-2.4.3/abi/svr4/utsname.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/utsname.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,159 @@ +/* $Id$ + * + * svr4 utsname emuation + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * The SVR4 utsname support is based on the code originally in svr4.c + * which was: + * + * Copyright (C) 1994 Eric Youngdale. + */ + +#include +#include + +#include + +#include +#include +#include +#include + +#include + +char sco_serial[10] = "public"; + +struct sco_utsname { + char sysname[9]; + char nodename[9]; + char release[16]; + char kernelid[20]; + char machine[9]; + char bustype[9]; + char sysserial[10]; + unsigned short sysorigin; + unsigned short sysoem; + char numusers[9]; + unsigned short numcpu; +}; + +struct v7_utsname { + char sysname[9]; + char nodename[9]; + char release[9]; + char version[9]; + char machine[9]; +}; + +#define SVR4_NMLN 257 +struct svr4_utsname { + char sysname[SVR4_NMLN]; + char nodename[SVR4_NMLN]; + char release[SVR4_NMLN]; + char version[SVR4_NMLN]; + char machine[SVR4_NMLN]; +}; + + +#define set_utsfield(to, from, dotchop) \ + { \ + char *p; \ + int i, len = (sizeof(to) > sizeof(from) ? sizeof(from) : sizeof(to)); \ + __copy_to_user(to, from, len); \ + if (dotchop) \ + for (p=from,i=0; *p && *p != '.' && --len; p++,i++); \ + else \ + i = len - 1; \ + __put_user('\0', to+i); \ + } + + +int +sco_utsname(unsigned long addr) +{ + int error; + struct sco_utsname *it = (struct sco_utsname *)addr; + + /* This shouldn't be invoked by anything that isn't running + * in the SCO personality. I can envisage a program that uses + * this to test if it is running on SCO or not. It probably + * won't happen but let's make sure it doesn't anyway... + */ + if (!personality(PER_SCOSVR3)) + return -ENOSYS; + + down_read(&uts_sem); + error = verify_area(VERIFY_WRITE, it, sizeof (struct sco_utsname)); + if (!error) { +#if 0 + set_utsfield(it->sysname, system_utsname.nodename, 1); +#else + set_utsfield(it->sysname, "SCO_SV", 0); +#endif + set_utsfield(it->nodename, system_utsname.nodename, 1); +#if 0 + set_utsfield(it->release, system_utsname.release, 0); +#else + set_utsfield(it->release, "3.2v5.0.0\0", 0); +#endif + set_utsfield(it->kernelid, system_utsname.version, 0); + set_utsfield(it->machine, system_utsname.machine, 0); + if (EISA_bus) { + set_utsfield(it->bustype, "EISA", 0); + } else { + set_utsfield(it->bustype, "ISA", 0); + } + set_utsfield(it->sysserial, sco_serial, 0); + __put_user(0xffff, &it->sysorigin); + __put_user(0xffff, &it->sysoem); + set_utsfield(it->numusers, "unlim", 0); + __put_user(1, &it->numcpu); + } + up_read(&uts_sem); + + return error; +} + + +int v7_utsname(unsigned long addr) +{ + int error; + struct v7_utsname *it = (struct v7_utsname *)addr; + + down_read(&uts_sem); + error = verify_area(VERIFY_WRITE, it, sizeof (struct v7_utsname)); + if (!error) { + set_utsfield(it->sysname, system_utsname.nodename, 1); + set_utsfield(it->nodename, system_utsname.nodename, 1); + set_utsfield(it->release, system_utsname.release, 0); + set_utsfield(it->version, system_utsname.version, 0); + set_utsfield(it->machine, system_utsname.machine, 0); + } + up_read(&uts_sem); + + return error; +} + +EXPORT_SYMBOL(v7_utsname); + +int abi_utsname(unsigned long addr) +{ + int error; + struct svr4_utsname *it = (struct svr4_utsname *)addr; + + down_read(&uts_sem); + error = verify_area(VERIFY_WRITE, it, sizeof (struct svr4_utsname)); + if (!error) { + set_utsfield(it->sysname, system_utsname.sysname, 0); + set_utsfield(it->nodename, system_utsname.nodename, 0); + set_utsfield(it->release, system_utsname.release, 0); + set_utsfield(it->version, system_utsname.version, 0); + set_utsfield(it->machine, system_utsname.machine, 0); + } + up_read(&uts_sem); + + return error; +} + +EXPORT_SYMBOL(abi_utsname); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/vtkbd.c linux/abi/svr4/vtkbd.c --- linux-2.4.3/abi/svr4/vtkbd.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/vtkbd.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,94 @@ +/* $Id$ + * + * This provides internal emulation support for the SCO on + * the multiscreen console. More or less, this involves translating the + * input ioctl()'s into a similar Linux ioctl()'s. + * + * Not emulated SCO multiscreen functions: + * None. + * + * Not emulated SCO keyboard functions: + * KIOCDOSMODE set DOSMODE + * KIOCNONDOSMODE unset DOSMODE + * KDDISPINFO get display start and size + * KDGKBSTATE get state of keyboard shift keys + * + * Written by Scott Michel, scottm@intime.com + * (c) 1994 Scott Michel as part of the Linux iBCS-2 emulator project. + * + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +static struct { + int in_ioctl; /* only lower 8 bits */ + int out_ioctl; /* Linux version */ +} trantab[] = { +#ifdef KDDISPTYPE + { 1, KDDISPTYPE }, +#endif + { 2, KDMAPDISP }, + { 3, KDUNMAPDISP }, + { 6, KDGKBMODE }, + { 7, KDSKBMODE }, + { 8, KDMKTONE }, + { 9, KDGETMODE }, + { 10, KDSETMODE }, + { 11, KDADDIO }, + { 12, KDDELIO }, + { 60, KDENABIO }, + { 61, KDDISABIO }, +#ifdef KIOCINFO + { 62, KIOCINFO }, +#endif + { 63, KIOCSOUND }, + { 64, KDGKBTYPE }, + { 65, KDGETLED }, + { 66, KDSETLED }, +}; + +/*-------------------------------------------------------------------------- + * ibcs_ioctl_vtkd() + *------------------------------------------------------------------------*/ + +int +ibcs_ioctl_vtkd(int fd, int todo, void *arg) +{ + int gen = (todo >> 8) & 0xff, spec = todo & 0xff; + int newf; + + if (gen == 'v') { + /* Could make this translation process table based, but, why + waste the valuable kernel space? */ + + newf = (spec == 1 ? VT_OPENQRY : + (spec == 2 ? VT_SETMODE : + (spec == 3 ? VT_GETMODE : + (spec == 4 ? VT_RELDISP : + (spec == 5 ? VT_ACTIVATE : -1))))); + if (newf != -1) + return SYS(ioctl)(fd, newf, arg); + } else if (gen == 'K') { + register unsigned int i; + + for (i = 0; i < sizeof(trantab) / sizeof(trantab[0]); ++i) { + if (spec == trantab[i].in_ioctl) + return SYS(ioctl)(fd, trantab[i].out_ioctl, arg); + } + } + + printk(KERN_ERR "iBCS: vtkd ioctl 0x%02x unsupported\n", todo); + return -EINVAL; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/wyse_nfs.c linux/abi/svr4/wyse_nfs.c --- linux-2.4.3/abi/svr4/wyse_nfs.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/wyse_nfs.c Fri Mar 30 15:23:46 2001 @@ -0,0 +1,30 @@ +/* $Id$ */ + +#include +#include +#include + +#define SC(name) (void *)__NR_##name +#define ITR(trace, name, args) ,trace,name,args + +static ABI_func WYSENFS_funcs[] = { + { 0, Ukn ITR(1, "nfs_svc", "") }, /* 0 */ + { 0, Ukn ITR(1, "async_daemon", "") }, /* 1 */ + { 0, Ukn ITR(1, "nfs_getfh", "") }, /* 2 */ + { 0, Ukn ITR(1, "nfsmount", "") } /* 3 */ +}; + + +void iBCS_class_WYSENFS(struct pt_regs *regs) { + int i; + + i = regs->eax >> 8; + if (i > 3) { + regs->eax = iABI_errors(-EINVAL); + regs->eflags |= 1; + return; + } + + abi_dispatch(regs, &WYSENFS_funcs[i],1); + return; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/wyse_tcp.c linux/abi/svr4/wyse_tcp.c --- linux-2.4.3/abi/svr4/wyse_tcp.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/wyse_tcp.c Fri Mar 30 15:23:46 2001 @@ -0,0 +1,51 @@ +/* $Id$ */ + +#include +#include +#include + +#define SC(name) (void *)__NR_##name + +#define ITR(trace, name, args) ,trace,name,args + +static ABI_func WYSETCP_funcs[] = { +#ifdef __TRACE_SELECT__ + { abi_select, 5 ITR(0, "select", "dxxxx")},/* 0 */ +#else + { SC(_newselect), -5 ITR(0, "select", "dxxxx")},/* 0 */ +#endif + { abi_socket, Spl ITR(0, "socket", "ddd") }, /* 1 */ + { abi_connect, Spl ITR(0, "connect", "dxd") }, /* 2 */ + { abi_accept, Spl ITR(0, "accept", "dxx") }, /* 3 */ + { abi_send, Spl ITR(0, "send", "dxdd")}, /* 4 */ + { abi_recv, Spl ITR(0, "recv", "dxdd")}, /* 5 */ + { abi_bind, Spl ITR(0, "bind", "dxd") }, /* 6 */ + { abi_setsockopt, Spl ITR(0, "setsockopt", "") }, /* 7 */ + { abi_listen, Spl ITR(0, "listen", "dd") }, /* 8 */ + { 0, 3 ITR(1, "recvmsg", "dxd") }, /* 9 */ + { 0, 3 ITR(1, "sendmsg", "dxd") }, /* 10 */ + { abi_getsockopt, Spl ITR(0, "getsockopt", "dddxx")}, /* 11 */ + { abi_recvfrom, Spl ITR(0, "recvfrom", "dxddxd")},/* 12 */ + { abi_sendto, Spl ITR(0, "sendto", "dxddxd")},/* 13 */ + { abi_shutdown, Spl ITR(0, "shutdown", "dd") }, /* 14 */ + { abi_socketpair, Spl ITR(0, "socketpair", "dddx")}, /* 15 */ + { 0, Ukn ITR(1, "trace", "") }, /* 16 */ + { abi_getpeername, Spl ITR(0, "getpeername", "dxx") }, /* 17 */ + { abi_getsockname, Spl ITR(0, "getsockname", "") }, /* 18 */ + { abi_wait3, 1 ITR(0, "wait3", "x") }, /* 19 */ +}; + + +void iBCS_class_WYSETCP(struct pt_regs *regs) { + int i; + + i = regs->eax >> 8; + if (i > 19) { + regs->eax = iABI_errors(-EINVAL); + regs->eflags |= 1; + return; + } + + abi_dispatch(regs, &WYSETCP_funcs[i], 1); + return; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/xnx.c linux/abi/svr4/xnx.c --- linux-2.4.3/abi/svr4/xnx.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/xnx.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,428 @@ +/* $Id$ + * + * This file contains an emulation of Xenix syscalls that are used by SCO binaries + * + * Copyright (C) 1993,1994 Drew Sullivan + * Copyright (C) 1994,1995-1996 Mike Jagdis + * + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#define XF_UNLCK 0 +#define XF_WRLCK 1 +#define XF_RDLCK 3 + + +struct ibcs_flock { + short l_type; + short l_whence; + off_t l_start; + off_t l_len; + short l_sysid; + short l_pid; +}; + + +/* locking() requires mandatory locking. Processes that attempt to + * read or write a region locked with locking() are required to block. + * You need to build a kernel with mandatory locking support and set + * the permissions on the required file to setgid, no group execute. + */ +int xnx_locking(int fd, int mode, unsigned long size) +{ + struct flock fl; + mm_segment_t old_fs; + int error; + + if ((mode < 0 || mode > 7) && mode != 20) { + abi_trace(ABI_TRACE_API, + "unsupported locking() mode=0x%x", mode); + return -EINVAL; + } + + /* Modes 5, 6 & 7 are very like the fcntl mechanism but + * we can't just punt to that because the type values are + * different. + */ + if (mode > 4 && mode < 8) { + struct ibcs_flock *ifl = (struct ibcs_flock *)size; + short t; + + error = verify_area(VERIFY_READ, ifl, sizeof(*ifl)); + if (error) + return error; + + get_user(t, &ifl->l_type); + switch (t) { + case XF_UNLCK: t = F_UNLCK; break; + case XF_WRLCK: t = F_WRLCK; break; + case XF_RDLCK: t = F_RDLCK; break; + default: return -EINVAL; + } + put_user(t, &ifl->l_type); + + error = SYS(fcntl)(fd, mode, ifl); + + get_user(t, &ifl->l_type); + switch (t) { + case F_UNLCK: t = XF_UNLCK; break; + case F_WRLCK: t = XF_WRLCK; break; + case F_RDLCK: t = XF_RDLCK; break; + } + put_user(t, &ifl->l_type); + + get_user(t, &ifl->l_sysid); + put_user(t, &ifl->l_pid); + put_user(0, &ifl->l_sysid); + return error; + } + + fl.l_type = (mode == 0 ? F_UNLCK + : ((mode <= 2 || mode == 20) ? F_WRLCK + : F_RDLCK)); + fl.l_whence = 1; + fl.l_start = 0; + fl.l_len = size; + + old_fs = get_fs(); + set_fs (get_ds()); + error = SYS(fcntl)(fd, + mode == 5 ? F_GETLK + : (!(mode % 2) ? F_SETLK : F_SETLKW), + &fl); + set_fs(old_fs); + return error; +} + + +int xnx_creatsem(char *sem_name, int mode) { + return -EPERM; +} + +int xnx_opensem(char *sem_name) { + return -EPERM; +} + +int xnx_sigsem(int sem_num) { + return -EPERM; +} + +int xnx_waitsem(int sem_num) { + return -EPERM; +} + +int xnx_nbwaitsem(int sem_num) { + return -EPERM; +} + +/* Check if input is available */ +int xnx_rdchk(int fd) { + int error, nbytes; + mm_segment_t old_fs; + + old_fs = get_fs(); + set_fs (get_ds()); + error = SYS(ioctl)(fd, FIONREAD, &nbytes); + set_fs(old_fs); + + if (error < 0) return error; + return nbytes ? 1 : 0; +} + +/* Linux has a stub sys_ftime. Perhaps this should be there? On the other + * hand it's an old call that probably shouldn't be used by most modern + * applications so perhaps it's better here where it needn't bloat the + * base kernel. + */ +int xnx_ftime(struct timeb * tp) { + struct timeval tv; + struct timezone tz; + int error; + mm_segment_t old_fs; + + error = verify_area(VERIFY_WRITE, tp, sizeof(struct timeb)); + if (error) + return error; + + old_fs = get_fs(); + set_fs (get_ds()); + error = SYS(gettimeofday)(&tv, &tz); + set_fs(old_fs); + if (error) + return error; + + put_user(tv.tv_sec, &tp->time); + put_user((unsigned short)(tv.tv_usec/1000), &tp->millitm); + put_user((short)tz.tz_minuteswest, &tp->timezone); + put_user((short)tz.tz_dsttime, &tp->dstflag); + + return 0; +} + +/* go to sleep for period milliseconds */ +int xnx_nap(long period) +{ + __sighandler_t old_handler; + struct itimerval it; + struct timeval tv1, tv2; + struct timezone tz; + mm_segment_t old_fs; + + if (!period) + return 0; + + it.it_interval.tv_sec = 0; + it.it_interval.tv_usec = 0; + it.it_value.tv_sec = 0; + it.it_value.tv_usec = period * 1000; + old_fs = get_fs(); + set_fs (get_ds()); + SYS(gettimeofday)(&tv1, &tz); + spin_lock_irq(¤t->sig[SIGALRM-1].siglock); + old_handler = current->sig->action[SIGALRM-1].sa.sa_handler; + current->sig->action[SIGALRM-1].sa.sa_handler = SIG_DFL; + spin_unlock_irq(¤t->sig[SIGALRM-1].siglock); + SYS(setitimer)(ITIMER_REAL, &it, NULL); + SYS(pause)(); + spin_lock_irq(¤t->sig[SIGALRM-1].siglock); + current->sig->action[SIGALRM-1].sa.sa_handler = old_handler; + spin_unlock_irq(¤t->sig[SIGALRM-1].siglock); + SYS(gettimeofday)(&tv2, &tz); + set_fs(old_fs); + + deactivate_signal(current, SIGALRM); + + return (signal_pending(current) + ? -EINTR + : ((tv2.tv_sec - tv1.tv_sec) * 1000000 + + (tv2.tv_usec - tv1.tv_usec)) / 1000); +} + +int xnx_sdget(char *path, int flags, long size, int mode) { + return -EPERM; +} + +int xnx_sdfree(char* addr) { + return -EPERM; +} + +int xnx_sdenter(char *addr, int flags) { + return -EPERM; +} + +int xnx_sdleave(char *addr) { + return -EPERM; +} + +int xnx_sdgetv(char *addr) { + return -EPERM; +} + +int xnx_sdwaitv(char *addr, int vnum) { + return -EPERM; +} + +/* This allows processes to be allowed to exceed available swap. The man + * page isn't too clear - it seems to suggest Xenix supports physical + * memory > swap but this doesn't make sense to me? It almost certainly + * isn't useful for Linux to actually do anything with this - just lie. + */ +int xnx_proctl(int pid, int command, char *arg) { +#define PRHUGEX 1 +#define PRNORMEX 2 + return 0; +} + +int xnx_execseg(excode_t oldaddr, unsigned size) { + return -EPERM; +} + + +int xnx_unexecseg(excode_t addr) { + return -EPERM; +} + +/* eaccess() checks access to the given path using the effective + * uid/gid rather than the real uid/gid. + */ +int xnx_eaccess(char *path, int mode) { + unsigned short ouid, ogid; + int err; + + ouid = current->uid; + ogid = current->gid; + current->uid = current->euid; + current->gid = current->egid; + + err = SYS(access)(path, mode); + + current->uid = ouid; + current->gid = ogid; + + return err; +} + +/* This allows running adb without executing any programs, but disassembly + * will work fine with that lie. + */ +int xnx_paccess(int pid, int cmd, int offset, int count, char *ptr) { + return 0; +} + +int xnx_sigpending(unsigned long *set) { + return -EPERM; +} + + +#define _PC_LINK_MAX 0 +#define _PC_MAX_CANON 1 +#define _PC_MAX_INPUT 2 +#define _PC_NAME_MAX 3 +#define _PC_PATH_MAX 4 +#define _PC_PIPE_BUF 5 +#define _PC_CHOWN_RESTRICTED 6 +#define _PC_NO_TRUNC 7 +#define _PC_VDISABLE 8 + +int +xnx_pathconf(char *path, int name) +{ + switch (name) { + case _PC_LINK_MAX: + /* Although Linux headers define values on a per + * filesystem basis there is no way to access + * these without hard coding fs information here + * so for now we use a bogus value. + */ + return LINK_MAX; + + case _PC_MAX_CANON: + return MAX_CANON; + + case _PC_MAX_INPUT: + return MAX_INPUT; + + case _PC_PATH_MAX: + return PATH_MAX; + + case _PC_PIPE_BUF: + return PIPE_BUF; + + case _PC_CHOWN_RESTRICTED: + /* We should really think about this and tell + * the truth. + */ + return 0; + + case _PC_NO_TRUNC: + /* Not sure... It could be fs dependent? */ + return 1; + + case _PC_VDISABLE: + return 1; + + case _PC_NAME_MAX: { + struct statfs buf; + char *p; + int error; + mm_segment_t old_fs; + + p = getname(path); + error = PTR_ERR(p); + if (!IS_ERR(p)) { + old_fs = get_fs(); + set_fs (get_ds()); + error = SYS(statfs)(p, &buf); + set_fs(old_fs); + putname(p); + if (!error) + return buf.f_namelen; + } + return error; + } + } + + return -EINVAL; +} + +int +xnx_fpathconf(int fildes, int name) +{ + switch (name) { + case _PC_LINK_MAX: + /* Although Linux headers define values on a per + * filesystem basis there is no way to access + * these without hard coding fs information here + * so for now we use a bogus value. + */ + return LINK_MAX; + + case _PC_MAX_CANON: + return MAX_CANON; + + case _PC_MAX_INPUT: + return MAX_INPUT; + + case _PC_PATH_MAX: + return PATH_MAX; + + case _PC_PIPE_BUF: + return PIPE_BUF; + + case _PC_CHOWN_RESTRICTED: + /* We should really think about this and tell + * the truth. + */ + return 0; + + case _PC_NO_TRUNC: + /* Not sure... It could be fs dependent? */ + return 1; + + case _PC_VDISABLE: + return 1; + + case _PC_NAME_MAX: { + struct statfs buf; + int error; + mm_segment_t old_fs; + + old_fs = get_fs(); + set_fs (get_ds()); + error = SYS(statfs)(fildes, &buf); + set_fs(old_fs); + if (!error) + return buf.f_namelen; + return error; + } + } + + return -EINVAL; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/xnx_funcs.c linux/abi/svr4/xnx_funcs.c --- linux-2.4.3/abi/svr4/xnx_funcs.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/xnx_funcs.c Fri Mar 30 15:23:46 2001 @@ -0,0 +1,163 @@ +/* $Id$ */ + +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#define SC(name) (void *)__NR_##name +#define ITR(trace, name, args) ,trace,name,args + +/* + * Translate the signal number to the corresponding item for Linux. + */ +static inline int abi_mapsig(int sig) +{ + if ((unsigned int) sig >= NSIGNALS) + return -1; + return current->exec_domain->signal_map[sig]; +} + + +asmlinkage int sco_sigaction(int sco_signum, const struct sco_sigaction * action, + struct sco_sigaction * oldaction) +{ + struct sco_sigaction new_sa, old_sa; + int error, signo; + mm_segment_t old_fs; + struct sigaction nsa, osa; + + signo = abi_mapsig(sco_signum); + if (signo == -1) + return -EINVAL; + + if (oldaction) { + error = verify_area(VERIFY_WRITE, oldaction, + sizeof(struct sco_sigaction)); + if (error) + return error; + } + + if (action) { + error = copy_from_user(&new_sa, action, + sizeof(struct sco_sigaction)); + if (error) + return -EFAULT; + nsa.sa_restorer = NULL; + nsa.sa_handler = new_sa.sa_handler; + nsa.sa_mask = map_sigvec_to_kernel(new_sa.sa_mask, + current->exec_domain->signal_map); + nsa.sa_flags = SA_NOMASK; + if (new_sa.sa_flags & SCO_SA_NOCLDSTOP) + nsa.sa_flags |= SA_NOCLDSTOP; + } + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(rt_sigaction)(signo, + action ? &nsa : NULL, + oldaction ? &osa : NULL, + sizeof(sigset_t)); + set_fs(old_fs); + + if (!error && oldaction) { + old_sa.sa_handler = osa.sa_handler; + old_sa.sa_mask = map_sigvec_from_kernel(osa.sa_mask, + current->exec_domain->signal_invmap); + old_sa.sa_flags = 0; + if(osa.sa_flags & SA_NOCLDSTOP) + old_sa.sa_flags |= SCO_SA_NOCLDSTOP; + /* This should never fail... */ + copy_to_user(oldaction, &old_sa, sizeof(struct sco_sigaction)); + } + return error; +} + +static ABI_func XNX_funcs[] = { + { 0, Ukn ITR(1, "syscall", "") }, /* 0 */ + { xnx_locking, 3 ITR(0, "locking", "ddd") }, /* 1 */ + { xnx_creatsem, 2 ITR(1, "creatsem", "sd") }, /* 2 */ + { xnx_opensem, 1 ITR(1, "opensem", "s") }, /* 3 */ + { xnx_sigsem, 1 ITR(1, "sigsem", "d") }, /* 4 */ + { xnx_waitsem, 1 ITR(1, "waitsem", "d") }, /* 5 */ + { xnx_nbwaitsem, 1 ITR(1, "nbwaitsem", "d") }, /* 6 */ + { xnx_rdchk, 1 ITR(0, "rdchk", "d") }, /* 7 */ + { 0, Ukn ITR(1, "stkgro", "") }, /* 8 */ + { 0, Ukn ITR(1, "?", "") }, /* 9 */ + { SC(ftruncate), -2 ITR(0, "chsize", "dd") }, /* 10 */ + { xnx_ftime, 1 ITR(0, "ftime", "x") }, /* 11 */ + { xnx_nap, 1 ITR(0, "nap", "d") }, /* 12 */ + { xnx_sdget, 4 ITR(1, "sdget", "sddd") }, /* 13 */ + { xnx_sdfree, 1 ITR(1, "sdfree", "x") }, /* 14 */ + { xnx_sdenter, 2 ITR(1, "sdenter", "xd") }, /* 15 */ + { xnx_sdleave, 1 ITR(1, "sdleave", "x") }, /* 16 */ + { xnx_sdgetv, 1 ITR(1, "sdgetv", "x") }, /* 17 */ + { xnx_sdwaitv, 2 ITR(1, "sdwaitv", "xd") }, /* 18 */ + { 0, Ukn ITR(1, "brkctl", "") }, /* 19 */ + { 0, Ukn ITR(1, "?", "") }, /* 20 */ + { 0, 2 ITR(0, "sco-getcwd?", "dx") }, /* 21 */ + { 0, Ukn ITR(1, "?", "") }, /* 22 */ + { 0, Ukn ITR(1, "?", "") }, /* 23 */ + { 0, Ukn ITR(1, "?", "") }, /* 24 */ + { 0, Ukn ITR(1, "?", "") }, /* 25 */ + { 0, Ukn ITR(1, "?", "") }, /* 26 */ + { 0, Ukn ITR(1, "?", "") }, /* 27 */ + { 0, Ukn ITR(1, "?", "") }, /* 28 */ + { 0, Ukn ITR(1, "?", "") }, /* 29 */ + { 0, Ukn ITR(1, "?", "") }, /* 30 */ + { 0, Ukn ITR(1, "?", "") }, /* 31 */ + { xnx_proctl, 3 ITR(0, "proctl", "ddx") }, /* 32 */ + { xnx_execseg, 2 ITR(1, "execseg", "xd") }, /* 33 */ + { xnx_unexecseg, 1 ITR(1, "unexecseg", "x") }, /* 34 */ + { 0, Ukn ITR(1, "?", "") }, /* 35 */ +#ifdef __TRACE_SELECT__ + { abi_select, 5 ITR(0, "select", "dxxxx")}, /* 36 */ +#else + { SC(_newselect), -5 ITR(0, "select", "dxxxx")}, /* 36 */ +#endif + { xnx_eaccess, 2 ITR(0, "eaccess", "so") }, /* 37 */ + { xnx_paccess, 5 ITR(1, "paccess", "dddds")},/* 38 */ + { sco_sigaction, 3 ITR(0, "sigaction", "dxx") }, /* 39 */ + { abi_sigprocmask, 3 ITR(0, "sigprocmask", "dxx") }, /* 40 */ + { xnx_sigpending, 1 ITR(1, "sigpending", "x") }, /* 41 */ + { abi_sigsuspend, Spl ITR(0, "sigsuspend", "x") }, /* 42 */ + { SC(getgroups), -2 ITR(0, "getgroups", "dx") }, /* 43 */ + { SC(setgroups), -2 ITR(0, "setgroups", "dx") }, /* 44 */ + { ibcs_sysconf, 1 ITR(0, "sysconf", "d") }, /* 45 */ + { xnx_pathconf, 2 ITR(0, "pathconf", "sd") }, /* 46 */ + { xnx_fpathconf, 2 ITR(0, "fpathconf", "dd") }, /* 47 */ + { SC(rename), -2 ITR(0, "rename", "ss") }, /* 48 */ + { 0, Ukn ITR(1, "?", "") }, /* 49 */ + { sco_utsname, 1 ITR(0, "sco_utsname", "x") }, /* 50 */ + { 0, Ukn ITR(1, "?", "") }, /* 51 */ + { 0, Ukn ITR(1, "?", "") }, /* 52 */ + { 0, Ukn ITR(1, "?", "") }, /* 53 */ + { 0, Ukn ITR(1, "?", "") }, /* 54 */ + { SC(getitimer), -2 ITR(0, "getitimer", "dx") }, /* 55 */ + { SC(setitimer), -3 ITR(0, "setitimer", "dxx") } /* 56 */ +}; + + +void iBCS_class_XNX(struct pt_regs *regs) +{ + int i; + + i = regs->eax >> 8; + if (i > 56) { + regs->eax = iABI_errors(-EINVAL); + regs->eflags |= 1; + return; + } + + abi_dispatch(regs, &XNX_funcs[i], 1); + return; +} + +EXPORT_SYMBOL(iBCS_class_XNX); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/svr4/xstat.c linux/abi/svr4/xstat.c --- linux-2.4.3/abi/svr4/xstat.c Thu Jan 1 01:00:00 1970 +++ linux/abi/svr4/xstat.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,470 @@ +/* $Id$ + * xstat.c - xstat(2) related code for sysv emulation + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * Hacked by Eric Youngdale for iBCS (1993, 1994). + * Added to by Drew Sullivan, modified by EY for xstat (used by SVr4). + * Modified by Christoph Hellwig for Kernel 2.4 + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * The xstat interface is used by SVr4, and is effectively an extension + * to stat. The general idea is that stat has some limitations (chiefly + * 16 bit inode numbers), and the solution in SVr4 was to add an entirely + * new syscall. The /usr/include/sys/stat.h header file defines stat as xstat + * so that the new interface is used. The one advantage of xstat is that + * we pass a version number so that it is possible to tell exactly what + * the application is expecting, and it is easy to do the right thing. + * There is usually an inline wrapper function in /usr/include/sys/stat.h + * to perform this conversion. + */ + +#define R3_MKNOD_VERSION 1 /* SVr3 */ +#define R4_MKNOD_VERSION 2 /* SVr4 */ +#define R3_STAT_VERSION 1 /* SVr3 */ +#define R4_STAT_VERSION 2 /* SVr4 */ +#define UW7_XSTAT64_VERSION 4 /* UW7 xstat64 */ +#define SCO_STAT_VERSION 51 /* SCO OS5 */ + +/* Various functions to provide compatibility between the linux + syscalls and the ABI ABI compliant calls */ + +/* Convert a linux dev number into the SVr4 equivalent. */ +#define R4_DEV(DEV) ((DEV & 0xff) | ((DEV & 0xff00) << 10)) + + +struct sco_xstat { + short st_dev; + long __pad1[3]; + unsigned long st_ino; + unsigned short st_mode; + short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + short st_rdev; + long __pad2[2]; + long st_size; + long __pad3; + long st_atime; + long st_mtime; + long st_ctime; + long st_blksize; + long st_blocks; + char st_fstype[16]; + long __pad4[7]; + long st_sco_flags; +}; + + + +/* + * st_blocks and st_blksize are approximated with a simple algorithm if + * they aren't supported directly by the filesystem. The minix and msdos + * filesystems don't keep track of blocks, so they would either have to + * be counted explicitly (by delving into the file itself), or by using + * this simple algorithm to get a reasonable (although not 100% accurate) + * value. + * + * Use minix fs values for the number of direct and indirect blocks. The + * count is now exact for the minix fs except that it counts zero blocks. + * Everything is in BLOCK_SIZE'd units until the assignment to + * tmp.st_blksize. + */ +static void +set_blocks(struct inode *inode, long *st_blksize, long *st_blocks) +{ + long blocks, indirect; + +#define D_B 7 +#define I_B (BLOCK_SIZE / sizeof(unsigned short)) + + if (!inode->i_blksize) { + blocks = (inode->i_size + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (blocks > D_B) { + indirect = (blocks - D_B + I_B - 1) / I_B; + blocks += indirect; + if (indirect > 1) { + indirect = (indirect - 1 + I_B - 1) / I_B; + blocks += indirect; + if (indirect > 1) + blocks++; + } + } + *st_blocks = (BLOCK_SIZE / 512) * blocks; + *st_blksize = BLOCK_SIZE; + } else { + *st_blocks = inode->i_blocks; + *st_blksize = inode->i_blksize; + } +} + + +static int +cp_sco_xstat(struct inode * inode, struct sco_xstat * statbuf) +{ + struct sco_xstat tmp = {0, }; + + /* + * If we thought we were in a short inode environment we are + * probably already too late - getdents() will have likely + * already assumed short inodes and "fixed" anything with + * a zero low word (because it must match stat() which must + * match read() on a directory). We will just have to go + * along with it. + */ + if ((current->personality & SHORT_INODE) + && !((unsigned long)tmp.st_ino & 0xffff)) + tmp.st_ino = 0xfffffffe; + else + tmp.st_ino = inode->i_ino; + tmp.st_dev = inode->i_dev; + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlink; + tmp.st_uid = inode->i_uid; + tmp.st_gid = inode->i_gid; + tmp.st_rdev = inode->i_rdev; + tmp.st_size = inode->i_size; + tmp.st_atime = inode->i_atime; + tmp.st_mtime = inode->i_mtime; + tmp.st_ctime = inode->i_ctime; + set_blocks(inode, &tmp.st_blksize, &tmp.st_blocks); + strcpy(tmp.st_fstype, "ext2"); + tmp.st_sco_flags = 0; /* 1 if remote */ + return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; +} + + +static int +cp_svr4_xstat(struct inode * inode, struct svr4_xstat * statbuf) +{ + struct svr4_xstat tmp = {0, }; + + tmp.st_dev = R4_DEV(inode->i_dev); + tmp.st_ino = inode->i_ino; + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlink; + tmp.st_uid = inode->i_uid; + tmp.st_gid = inode->i_gid; + tmp.st_rdev = R4_DEV(inode->i_rdev); + tmp.st_size = inode->i_size; + tmp.st_atim.tv_sec = inode->i_atime; + tmp.st_mtim.tv_sec = inode->i_mtime; + tmp.st_ctim.tv_sec = inode->i_ctime; + set_blocks(inode, &tmp.st_blksize, &tmp.st_blocks); + strcpy(tmp.st_fstype, "ext2"); + return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; +} + +static int +cp_uw7_stat64(struct inode * inode, struct uw7_stat64 * statbuf) +{ + struct uw7_stat64 tmp = {0, }; + + tmp.st_dev = inode->i_dev; + tmp.st_ino = (unsigned long long)inode->i_ino; + tmp.st_mode = (unsigned long)inode->i_mode; + tmp.st_nlink = inode->i_nlink; + tmp.st_uid = inode->i_uid; + tmp.st_gid = inode->i_gid; + tmp.st_rdev = inode->i_rdev; /* XXX check this! */ + tmp.st_size = (long long)inode->i_size; + tmp.st_atime.tv_sec = inode->i_atime; + tmp.st_atime.tv_usec = 0L; + tmp.st_mtime.tv_sec = inode->i_mtime; + tmp.st_mtime.tv_usec = 0L; + tmp.st_ctime.tv_sec = inode->i_ctime; + tmp.st_ctime.tv_usec = 0L; + set_blocks(inode, &tmp.st_blksize, (long *)&tmp.st_blocks); + strcpy(tmp.st_fstype, "ext2"); + tmp.st_aclcnt = 0; + tmp.st_level = 0; + tmp.st_flags = 0; + tmp.st_cmwlevel = 0; + + return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; +} + +int svr4_xstat(int vers, char * filename, void * buf) +{ + struct nameidata nd; + int error; + + if (vers == R3_STAT_VERSION) + return abi_stat(filename, (struct ibcs_stat *)buf); + + error = user_path_walk(filename, &nd); + if (error) + return error; + + error = do_revalidate(nd.dentry); + if (!error) + switch (vers) { + case R4_STAT_VERSION: + error = cp_svr4_xstat(nd.dentry->d_inode, buf); + break; + + case SCO_STAT_VERSION: + error = cp_sco_xstat(nd.dentry->d_inode, buf); + break; + + case UW7_XSTAT64_VERSION: + error = cp_uw7_stat64(nd.dentry->d_inode, buf); + break; + + default: + error = -EINVAL; + abi_trace(ABI_TRACE_API, + "xstat version %d not supported", + vers); + break; + } + + path_release(&nd); + return error; +} + +EXPORT_SYMBOL(svr4_xstat); + +int svr4_lxstat(int vers, char * filename, void * buf) +{ + struct nameidata nd; + int error; + + if (vers == R3_STAT_VERSION) + return abi_lstat(filename, (struct ibcs_stat *)buf); + + error = user_path_walk_link(filename, &nd); + if (error) + return error; + + error = do_revalidate(nd.dentry); + if (!error) + switch (vers) { + case R4_STAT_VERSION: + error = cp_svr4_xstat(nd.dentry->d_inode, buf); + break; + + case SCO_STAT_VERSION: + error = cp_sco_xstat(nd.dentry->d_inode, buf); + break; + + case UW7_XSTAT64_VERSION: + error = cp_uw7_stat64(nd.dentry->d_inode, buf); + break; + + default: + error = -EINVAL; + abi_trace(ABI_TRACE_API, + "xstat version %d not supported", + vers); + break; + } + + path_release(&nd); + return error; +} + +EXPORT_SYMBOL(svr4_lxstat); + +int svr4_fxstat(int vers, int fd, void *buf) +{ + struct file * f; + int error = -EBADF; + + if (vers == R3_STAT_VERSION) + return abi_fstat(fd, (struct ibcs_stat *)buf); + + f = fget(fd); + if (f) { + struct dentry * dentry = f->f_dentry; + + error = do_revalidate(dentry); + if (!error) + switch(vers) { + case R4_STAT_VERSION: + error = cp_svr4_xstat(dentry->d_inode, buf); + break; + + case SCO_STAT_VERSION: + error = cp_sco_xstat(dentry->d_inode, buf); + break; + + case UW7_XSTAT64_VERSION: + error = cp_uw7_stat64(dentry->d_inode, buf); + break; + + default: + abi_trace(ABI_TRACE_API, + "fxstat version %d not supported", vers); + error = -EINVAL; + } + + fput(f); + } + return error; +} + +EXPORT_SYMBOL(svr4_fxstat); + +int svr4_xmknod(int vers, const char * path, mode_t mode, dev_t dev) +{ + unsigned int major, minor; + + switch(vers) { + case R3_MKNOD_VERSION: + return abi_mknod(path, mode, dev); + + case R4_MKNOD_VERSION: + minor = dev & 0x3ffff; + major = dev >> 18; + if (minor > 0xff || major > 0xff) + return -EINVAL; + return abi_mknod(path, mode, ((major << 8) | minor)); + } + + abi_trace(ABI_TRACE_API, + "xmknod version %d not supported", vers); + return -EINVAL; +} + +EXPORT_SYMBOL(svr4_xmknod); + +/* + * The following code implements the statvfs function used by SVr4. + */ + +static int +cp_abi_statvfs(struct dentry *dentry, + struct statfs *src, struct abi_statvfs *statbuf) +{ + struct inode *inode = dentry->d_inode; + struct abi_statvfs tmp = {0, }; + + tmp.f_blocks = src->f_blocks; + + tmp.f_bsize = src->f_bsize; + tmp.f_frsize = 0; + tmp.f_blocks = src->f_blocks;; + tmp.f_bfree = src->f_bfree; + tmp.f_bavail = src->f_bavail; + tmp.f_files = src->f_files; + tmp.f_free = src->f_ffree; + tmp.f_sid = inode->i_sb->s_dev; + + /* Get the name of the filesystem */ + strcpy(tmp.f_basetype, inode->i_sb->s_type->name); + + tmp.f_flag = 0; + if (IS_RDONLY(inode)) tmp.f_flag |= 1; + if (IS_NOSUID(inode)) tmp.f_flag |= 2; + + tmp.f_namemax = src->f_namelen; + + return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; +} + + +static int +cp_sco_statvfs(struct dentry *dentry, + struct statfs *src, struct sco_statvfs *statbuf) +{ + struct inode *inode = dentry->d_inode; + struct sco_statvfs tmp = {0, }; + + tmp.f_blocks = src->f_blocks; + + tmp.f_bsize = src->f_bsize; + tmp.f_frsize = src->f_bsize; + tmp.f_blocks = src->f_blocks;; + tmp.f_bfree = src->f_bfree; + tmp.f_bavail = src->f_bavail; + tmp.f_files = src->f_files; + tmp.f_free = src->f_ffree; + tmp.f_favail = src->f_ffree; /* SCO addition in the middle! */ + tmp.f_sid = inode->i_sb->s_dev; + + /* Get the name of the filesystem. Sadly, some code + * "in the wild" actually checks the name against a + * hard coded list to see if it is a "real" fs or not. + * I believe Informix Dynamic Server for SCO is one such. + * More lies... + */ + if (personality(PER_SCOSVR3) + && !strncmp(inode->i_sb->s_type->name, "ext2", 4)) { + strcpy(tmp.f_basetype, "HTFS"); + } else { + strcpy(tmp.f_basetype, inode->i_sb->s_type->name); + } + + tmp.f_flag = 0; + if (IS_RDONLY(inode)) tmp.f_flag |= 1; + if (IS_NOSUID(inode)) tmp.f_flag |= 2; + + tmp.f_namemax = src->f_namelen; + + return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; +} + +int abi_statvfs(char * filename, void * stat) +{ + struct nameidata nd; + int error; + + error = user_path_walk(filename, &nd); + if (!error) { + struct statfs tmp; + error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); + if (!error) { + if (personality(PER_SCOSVR3)) + error = cp_sco_statvfs(nd.dentry, &tmp, stat); + else + error = cp_abi_statvfs(nd.dentry, &tmp, stat); + } + path_release(&nd); + } + return error; +} + +EXPORT_SYMBOL(abi_statvfs); + + +int abi_fstatvfs(int fd, void *stat) +{ + struct file * file; + struct statfs tmp; + int error; + + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); + if (!error) { + if (personality(PER_SCOSVR3)) + error = cp_sco_statvfs(file->f_dentry, &tmp, stat); + else + error = cp_abi_statvfs(file->f_dentry, &tmp, stat); + } + fput(file); +out: + return error; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/uw7/Makefile linux/abi/uw7/Makefile --- linux-2.4.3/abi/uw7/Makefile Thu Jan 1 01:00:00 1970 +++ linux/abi/uw7/Makefile Fri Mar 30 18:25:34 2001 @@ -0,0 +1,17 @@ +# +# Makefile for the kernel ABI code for UnixWare 7.x emulation +# + +O_TARGET := dummy.o + +list-multi := abi-uw7.o +abi-uw7-objs := funcs.o kernel.o ioctl.o context.o mac.o access.o \ + statvfs.o mmap.o + +obj-$(CONFIG_ABI_UW7) += abi-uw7.o + + +include $(TOPDIR)/Rules.make + +abi-uw7.o: $(abi-uw7-objs) + $(LD) -r -o $@ $(abi-uw7-objs) diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/uw7/access.c linux/abi/uw7/access.c --- linux-2.4.3/abi/uw7/access.c Thu Jan 1 01:00:00 1970 +++ linux/abi/uw7/access.c Sun Mar 18 17:35:58 2001 @@ -0,0 +1,72 @@ +/* + * abi/uw7/access.c - support for UnixWare access(2) system call. + * + * We handle the non-POSIX EFF_ONLY_OK/EX_OK flags. + * This software is under GPL. + */ + +#include +#include +#include + +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#define UW7_R_OK 004 +#define UW7_W_OK 002 +#define UW7_X_OK 001 +#define UW7_F_OK 000 +#define UW7_EFF_ONLY_OK 010 +#define UW7_EX_OK 020 + +#define UW7_MODE_MSK (UW7_R_OK|UW7_W_OK|UW7_X_OK|UW7_F_OK|UW7_EFF_ONLY_OK|UW7_EX_OK) + +int uw7_access(char * filename, int mode) +{ + struct nameidata nd; + int error; + + DBG(KERN_ERR "UW7[%d]: access(%p,%o)\n", current->pid, filename, mode); + + if (mode & ~UW7_MODE_MSK) + return -EINVAL; + + if (mode & UW7_EX_OK) { + error = user_path_walk(filename, &nd); + if (!error) { + error = do_revalidate(nd.dentry); + if (error) { + path_release(&nd); + return -EIO; + } + if (!S_ISREG(nd.dentry->d_inode->i_mode)) { + path_release(&nd); + return -EACCES; + } + path_release(&nd); + } + mode &= ~UW7_EX_OK; + mode |= UW7_X_OK; + } + if (mode & UW7_EFF_ONLY_OK) { + uid_t old_uid = current->uid, old_gid = current->gid; + + current->uid = current->euid; + current->gid = current->egid; + mode &= ~UW7_EFF_ONLY_OK; + error = SYS(access)(filename, mode); + current->uid = old_uid; + current->gid = old_gid; + } else + error = SYS(access)(filename, mode); + + return error; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/uw7/context.c linux/abi/uw7/context.c --- linux-2.4.3/abi/uw7/context.c Thu Jan 1 01:00:00 1970 +++ linux/abi/uw7/context.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,96 @@ +/* + * abi/uw7/context.c + * + * This software is under GPL + */ + + +#include +#include + +#include + +#include +#include +#include + +int +uw7_sigaltstack(const uw7_stack_t *uw7_ss, uw7_stack_t *uw7_oss) +{ + stack_t ss, oss, *ssp = NULL, *ossp = NULL; + int error; + mm_segment_t old_fs; + + if (uw7_ss) { + error = verify_area(VERIFY_READ, uw7_ss, sizeof(uw7_stack_t)); + if (error) + return error; + __get_user(ss.ss_sp, &uw7_ss->ss_sp); + __get_user(ss.ss_size, &uw7_ss->ss_size); + __get_user(ss.ss_flags, &uw7_ss->ss_flags); + ssp = &ss; + } + + if (uw7_oss) { + error = verify_area(VERIFY_WRITE, uw7_oss, sizeof(uw7_stack_t)); + if (error) + return error; + __get_user(oss.ss_sp, &uw7_oss->ss_sp); + __get_user(oss.ss_size, &uw7_oss->ss_size); + __get_user(oss.ss_flags, &uw7_oss->ss_flags); + ossp = &oss; + } + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(sigaltstack)(ssp, ossp); + set_fs(old_fs); + + if (ossp) { + __put_user(ossp->ss_sp, &uw7_oss->ss_sp); + __put_user(ossp->ss_size, &uw7_oss->ss_size); + __put_user(ossp->ss_flags, &uw7_oss->ss_flags); + } + return error; +} + +static int +getcontext(uw7_context_t * uc, struct pt_regs * regs) +{ + uw7_context_t tmp = { 0 }; + + return copy_to_user(uc, &tmp, sizeof(uw7_context_t)) ? -EFAULT : 0; +} + +static int +getxcontext(uw7_context_t * uc, struct pt_regs * regs) +{ + return 0; +} + +static int +setcontext(uw7_context_t * uc, struct pt_regs * regs) +{ + if (!uc) /* SVR4 says setcontext(NULL) => exit(0) */ + SYS(exit)(0); + return 0; +} + +int +uw7_context(struct pt_regs * regs) +{ + int fcn = get_syscall_parameter(regs, 0); + uw7_context_t * uc = (uw7_context_t *) get_syscall_parameter(regs, 1); + + switch (fcn) { + case UW7_GETCONTEXT: + return getcontext(uc, regs); + + case UW7_GETXCONTEXT: + return getxcontext(uc, regs); + + case UW7_SETCONTEXT: + return setcontext(uc, regs); + } + return -EINVAL; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/uw7/funcs.c linux/abi/uw7/funcs.c --- linux-2.4.3/abi/uw7/funcs.c Thu Jan 1 01:00:00 1970 +++ linux/abi/uw7/funcs.c Fri Mar 30 18:28:41 2001 @@ -0,0 +1,315 @@ +/* + * abi/uw7/funcs.c - UnixWare 7.x system call dispatch table. + * + * This software is under GPL + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + + +MODULE_DESCRIPTION("SCO UnixWare 7.x emulator"); + + +extern void iBCS_class_XNX(struct pt_regs *regs); + +ABI_func uw7_funcs[] = { + { abi_syscall, Fast ITR(0, "syscall", "") }, /* 0 */ + { SC(exit), -1 ITR(0, "exit", "d") }, /* 1 */ + { abi_fork, Spl ITR(0, "fork", "") }, /* 2 */ + { abi_read, 3 ITR(0, "read", "dpd") }, /* 3 */ + { SC(write), -3 ITR(0, "write", "dpd") }, /* 4 */ + { svr4_open, 3 ITR(0, "open", "soo") }, /* 5 */ + { SC(close), -1 ITR(0, "close", "d") }, /* 6 */ + { abi_wait, Spl ITR(0, "wait", "xxx") }, /* 7 */ + { SC(creat), -2 ITR(0, "creat", "so") }, /* 8 */ + { SC(link), -2 ITR(0, "link", "ss") }, /* 9 */ + { SC(unlink), -1 ITR(0, "unlink", "s") }, /* 10 */ + { abi_exec, Spl ITR(0, "exec", "sxx") }, /* 11 */ + { SC(chdir), -1 ITR(0, "chdir", "s") }, /* 12 */ + { abi_time, 0 ITR(0, "time", "") }, /* 13 */ + { abi_mknod, 3 ITR(0, "mknod", "soo") }, /* 14 */ + { SC(chmod), -2 ITR(0, "chmod", "so") }, /* 15 */ + { SC(chown), -3 ITR(0, "chown", "sdd") }, /* 16 */ + { abi_brk, 1 ITR(0, "brk/break", "x") }, /* 17 */ + { abi_stat, 2 ITR(0, "stat", "sp") }, /* 18 */ + { abi_lseek, 3 ITR(0, "seek/lseek", "ddd") }, /* 19 */ + { abi_getpid, Spl ITR(0, "getpid", "") }, /* 20 */ + { 0, Ukn ITR(1, "mount", "") }, /* 21 */ + { SC(umount), -1 ITR(0, "umount", "s") }, /* 22 */ + { SC(setuid), -1 ITR(0, "setuid", "d") }, /* 23 */ + { abi_getuid, Spl ITR(0, "getuid", "") }, /* 24 */ + { SC(stime), -1 ITR(0, "stime", "d") }, /* 25 */ + { svr4_ptrace, 4 ITR(0, "ptrace", "xdxx") }, /* 26 */ + { SC(alarm), -1 ITR(0, "alarm", "d") }, /* 27 */ + { abi_fstat, 2 ITR(0, "fstat", "dp") }, /* 28 */ + { SC(pause), -ZERO ITR(0, "pause", "") }, /* 29 */ + { SC(utime), -2 ITR(0, "utime", "xx") }, /* 30 */ + { uw7_stty, 2 ITR(0, "stty", "dd") }, /* 31 */ + { uw7_gtty, 2 ITR(1, "gtty", "dd") }, /* 32 */ + { uw7_access, 2 ITR(0, "access", "so") }, /* 33 */ + { SC(nice), -1 ITR(0, "nice", "d") }, /* 34 */ + { svr4_statfs, 4 ITR(0, "statfs", "spdd") }, /* 35 */ + { SC(sync), -ZERO ITR(0, "sync", "") }, /* 36 */ + { abi_kill, 2 ITR(0, "kill", "dd") }, /* 37 */ + { svr4_fstatfs, 4 ITR(0, "fstatfs", "dpdd") }, /* 38 */ + { abi_procids, Spl ITR(0, "ibcs_procids", "d") }, /* 39 */ + { iBCS_class_XNX, Fast ITR(0, "sysext", "") }, /* 40 */ + { SC(dup), -1 ITR(0, "dup", "d") }, /* 41 */ + { abi_pipe, Spl ITR(0, "pipe", "") }, /* 42 */ + { SC(times), -1 ITR(0, "times", "p") }, /* 43 */ + { SC(profil), -4 ITR(0, "prof", "xxxx")}, /* 44 */ + { 0, Ukn ITR(1, "lock/plock", "") }, /* 45 */ + { SC(setgid), -1 ITR(0, "setgid", "d") }, /* 46 */ + { abi_getgid, Spl ITR(0, "getgid", "") }, /* 47 */ + { abi_sigfunc, Fast ITR(0, "sigfunc", "xxx") }, /* 48 */ + { svr4_msgsys, Spl ITR(0, "msgsys", "dxddd")}, /* 49 */ + { svr4_sysi86, Spl ITR(0, "sysi86/sys3b", "d") }, /* 50 */ + { SC(acct), -1 ITR(0, "acct/sysacct", "x") }, /* 51 */ + { svr4_shmsys, Fast ITR(0, "shmsys", "ddxo")}, /* 52 */ + { svr4_semsys, Spl ITR(0, "semsys", "dddx")}, /* 53 */ + { uw7_ioctl, Spl ITR(0, "ioctl", "dxx") }, /* 54 */ + { 0, 3 ITR(0, "uadmin", "xxx") }, /* 55 */ + { 0, Ukn ITR(1, "exch", "") }, /* 56 */ + { v7_utsname, 1 ITR(0, "utsys", "x") }, /* 57 */ + { SC(fsync), -1 ITR(0, "fsync", "d") }, /* 58 */ + { abi_exec, Spl ITR(0, "execv", "spp") }, /* 59 */ + { SC(umask), -1 ITR(0, "umask", "o") }, /* 60 */ + { SC(chroot), -1 ITR(0, "chroot", "s") }, /* 61 */ + { svr4_fcntl, Spl ITR(0, "fcntl", "dxx") }, /* 62 */ + { svr4_ulimit, 2 ITR(0, "ulimit", "xx") }, /* 63 */ + { 0, Ukn ITR(1, "cg_ids", "") }, /* 64 */ + { 0, Ukn ITR(1, "cg_processors", "") }, /* 65 */ + { 0, Ukn ITR(1, "cg_info", "") }, /* 66 */ + { 0, Ukn ITR(1, "cg_bind", "") }, /* 67 */ + { 0, Ukn ITR(1, "cg_current", "") }, /* 68 */ + { 0, Ukn ITR(1, "cg_memloc", "") }, /* 69 */ + { 0, Ukn ITR(1, "advfs", "") }, /* 70 */ + { 0, Ukn ITR(1, "unadvfs", "") }, /* 71 */ + { 0, Ukn ITR(1, "rmount", "") }, /* 72 */ + { 0, Ukn ITR(1, "rumount", "") }, /* 73 */ + { 0, Ukn ITR(1, "rfstart", "") }, /* 74 */ + { 0, Ukn ITR(1, "unused 75", "") }, /* 75 */ + { 0, Ukn ITR(1, "rdebug", "") }, /* 76 */ + { 0, Ukn ITR(1, "rfstop", "") }, /* 77 */ + { 0, Ukn ITR(1, "rfsys", "") }, /* 78 */ + { SC(rmdir), -1 ITR(0, "rmdir", "s") }, /* 79 */ + { SC(mkdir), 2 ITR(0, "mkdir", "so") }, /* 80 */ + { svr4_getdents, 3 ITR(0, "getdents", "dxd") }, /* 81 */ + { 0, Ukn ITR(1, "libattach", "") }, /* 82 */ + { 0, Ukn ITR(1, "libdetach", "") }, /* 83 */ + { svr4_sysfs, 3 ITR(0, "sysfs", "dxx") }, /* 84 */ + { svr4_getmsg, Spl ITR(0, "getmsg", "dxxx") }, /* 85 */ + { svr4_putmsg, Spl ITR(0, "putmsg", "dxxd") }, /* 86 */ + { svr4_poll, 3 ITR(0, "poll", "xdd") }, /* 87 */ + { abi_lstat, 2 ITR(0, "lstat", "sp") }, /* 88 */ + { SC(symlink), -2 ITR(0, "symlink", "ss") }, /* 89 */ + { SC(readlink), -3 ITR(0, "readlink", "spd") }, /* 90 */ + { 0, Ukn ITR(0, "svr4_setgroups","dp") }, /* 91 */ + { 0, Ukn ITR(0, "svr4_getgroups","dp") }, /* 92 */ + { SC(fchmod), -2 ITR(0, "fchmod", "do") }, /* 93 */ + { SC(fchown), -3 ITR(0, "fchown", "ddd") }, /* 94 */ + { abi_sigprocmask, 3 ITR(0, "sigprocmask", "dxx") }, /* 95 */ + { abi_sigsuspend, Spl ITR(0, "sigsuspend", "x") }, /* 96 */ + { uw7_sigaltstack, 2 ITR(1, "sigaltstack", "xx") }, /* 97 */ + { abi_sigaction, 3 ITR(0, "sigaction", "dxx") }, /* 98 */ + { svr4_sigpending, 2 ITR(1, "sigpending", "dp") }, /* 99 */ + { uw7_context, Spl ITR(0, "ucontext", "") }, /* 100 */ + { 0, Ukn ITR(1, "evsys", "") }, /* 101 */ + { 0, Ukn ITR(1, "evtrapret", "") }, /* 102 */ + { abi_statvfs, 2 ITR(0, "statvfs", "sp") }, /* 103 */ + { abi_statvfs, 2 ITR(0, "fstatvfs", "dp") }, /* 104 */ + { 0, Ukn ITR(1, "reserved 105", "") }, /* 105 */ + { 0, Ukn ITR(1, "nfssys", "") }, /* 106 */ + { svr4_waitid, 4 ITR(0, "waitid", "ddxd") }, /* 107 */ + { 0, 3 ITR(1, "sigsendsys", "ddd") }, /* 108 */ + { svr4_hrtsys, Spl ITR(0, "hrtsys", "xxx") }, /* 109 */ + { 0, 3 ITR(1, "acancel", "dxd") }, /* 110 */ + { 0, Ukn ITR(1, "async", "") }, /* 111 */ + { 0, Ukn ITR(1, "priocntlsys", "") }, /* 112 */ + { svr4_pathconf, 2 ITR(1, "pathconf", "sd") }, /* 113 */ + { 0, 3 ITR(1, "mincore", "xdx") }, /* 114 */ + { uw7_mmap, 6 ITR(0, "mmap", "xxxxdx") },/* 115 */ + { SC(mprotect), -3 ITR(0, "mprotect", "xdx") },/* 116 */ + { SC(munmap), -2 ITR(0, "munmap", "xd") },/* 117 */ + { svr4_fpathconf, 2 ITR(1, "fpathconf", "dd") }, /* 118 */ + { abi_fork, Spl ITR(0, "vfork", "") }, /* 119 */ + { SC(fchdir), -1 ITR(0, "fchdir", "d") }, /* 120 */ + { SC(readv), -3 ITR(0, "readv", "dxd") }, /* 121 */ + { SC(writev), -3 ITR(0, "writev", "dxd") }, /* 122 */ + { svr4_xstat, 3 ITR(0, "xstat", "dsx") }, /* 123 */ + { svr4_lxstat, 3 ITR(0, "lxstat", "dsx") }, /* 124 */ + { svr4_fxstat, 3 ITR(0, "fxstat", "ddx") }, /* 125 */ + { svr4_xmknod, 4 ITR(0, "xmknod", "dsox")}, /* 126 */ + { svr4_syslocal, Spl ITR(0, "syslocal", "d") }, /* 127 */ + { svr4_getrlimit, 2 ITR(0, "setrlimit", "dx") }, /* 128 */ + { svr4_setrlimit, 2 ITR(0, "getrlimit", "dx") }, /* 129 */ + { SC(lchown), 3 ITR(1, "lchown","sdd") }, /* 130 */ + { 0, Ukn ITR(1, "memcntl", "") }, /* 131 */ +#ifdef CONFIG_ABI_XTI + { svr4_getpmsg, 5 ITR(0, "getpmsg", "dxxxx")}, /* 132 */ + { svr4_putpmsg, 5 ITR(0, "putpmsg", "dxxdd")}, /* 133 */ +#else + { 0, 5 ITR(0, "getpmsg", "dxxxx")}, /* 132 */ + { 0, 5 ITR(0, "putpmsg", "dxxdd")}, /* 133 */ +#endif + { SC(rename), -2 ITR(0, "rename", "ss") }, /* 134 */ + { abi_utsname, 1 ITR(0, "uname", "x") }, /* 135 */ + { uw7_setegid, 1 ITR(1, "setegid", "d") }, /* 136 */ + { svr4_sysconfig, 1 ITR(0, "sysconfig", "d") }, /* 137 */ + { 0, Ukn ITR(1, "adjtime", "") }, /* 138 */ + { svr4_sysinfo, 3 ITR(0, "systeminfo", "dsd") }, /* 139 */ + { socksys_syscall, 1 ITR(0, "socksys_syscall","x") }, /* 140 */ + { uw7_seteuid, 1 ITR(1, "seteuid", "d") }, /* 141 */ + { 0, Ukn ITR(1, "?", "") }, /* 142 */ + { 0, Ukn ITR(1, "keyctl", "") }, /* 143 */ + { 0, 2 ITR(1, "secsys", "dx") }, /* 144 */ + { 0, 4 ITR(1, "filepriv", "sdxd") }, /* 145 */ + { 0, 3 ITR(1, "procpriv", "dxd") }, /* 146 */ + { 0, 3 ITR(1, "devstat", "sdx") }, /* 147 */ + { 0, 5 ITR(1, "aclipc", "ddddx")}, /* 148 */ + { 0, 3 ITR(1, "fdevstat", "ddx") }, /* 149 */ + { 0, 3 ITR(1, "flvlfile", "ddx") }, /* 150 */ + { 0, 3 ITR(1, "lvlfile", "sdx") }, /* 151 */ + { 0, Ukn ITR(1, "sendv", "") }, /* 152 */ + { 0, 2 ITR(1, "lvlequal", "xx") }, /* 153 */ + { 0, 2 ITR(1, "lvlproc", "dx") }, /* 154 */ + { 0, Ukn ITR(1, "?", "") }, /* 155 */ + { 0, 4 ITR(1, "lvlipc", "dddx") }, /* 156 */ + { 0, 4 ITR(1, "acl", "sddx") }, /* 157 */ + { 0, Ukn ITR(1, "auditevt", "") }, /* 158 */ + { 0, Ukn ITR(1, "auditctl", "") }, /* 159 */ + { 0, Ukn ITR(1, "auditdmp", "") }, /* 160 */ + { 0, Ukn ITR(1, "auditlog", "") }, /* 161 */ + { 0, Ukn ITR(1, "auditbuf", "") }, /* 162 */ + { 0, 2 ITR(1, "lvldom", "xx") }, /* 163 */ + { 0, Ukn ITR(1, "lvlvfs", "") }, /* 164 */ + { 0, 2 ITR(1, "mkmld", "so") }, /* 165 */ + { uw7_mldmode, 1 ITR(1, "mldmode", "d") }, /* 166 */ + { 0, 2 ITR(0, "secadvise", "xx") }, /* 167 */ + { 0, Ukn ITR(1, "online", "") }, /* 168 */ + { SC(setitimer), -3 ITR(0, "setitimer", "dxx") }, /* 169 */ + { SC(getitimer), -2 ITR(0, "getitimer", "dx") }, /* 170 */ + { SC(gettimeofday), -2 ITR(0, "gettimeofday", "xx") }, /* 171 */ + { SC(settimeofday), -2 ITR(0, "settimeofday", "xx") }, /* 172 */ + { 0, Ukn ITR(1, "lwpcreate", "") }, /* 173 */ + { 0, Ukn ITR(1, "lwpexit", "") }, /* 174 */ + { 0, Ukn ITR(1, "lwpwait", "") }, /* 175 */ + { 0, Ukn ITR(1, "lwpself", "") }, /* 176 */ + { 0, Ukn ITR(1, "lwpinfo", "") }, /* 177 */ + { 0, Ukn ITR(1, "lwpprivate", "") }, /* 178 */ + { 0, Ukn ITR(1, "processorbind", "") }, /* 179 */ + { 0, Ukn ITR(1, "processorexbind","") }, /* 180 */ + { 0, Ukn ITR(1, "", "") }, /* 181 */ + { 0, Ukn ITR(1, "sync_mailbox", "") }, /* 182 */ + { 0, Ukn ITR(1, "prepblock", "") }, /* 183 */ + { 0, Ukn ITR(1, "block", "") }, /* 184 */ + { 0, Ukn ITR(1, "rdblock", "") }, /* 185 */ + { 0, Ukn ITR(1, "unblock", "") }, /* 186 */ + { 0, Ukn ITR(1, "cancelblock", "") }, /* 187 */ + { 0, Ukn ITR(1, "187", "") }, /* 188 */ + { uw7_pread, 4 ITR(1, "pread", "dsdd") }, /* 189 */ + { uw7_pwrite, 4 ITR(1, "pwrite", "dsdd") }, /* 190 */ + { SC(truncate), -2 ITR(0, "truncate", "sd") }, /* 191 */ + { SC(ftruncate), -2 ITR(0, "ftruncate", "dd") }, /* 192 */ + { 0, Ukn ITR(1, "lwpkill", "") }, /* 193 */ + { 0, Ukn ITR(1, "sigwait", "") }, /* 194 */ + { abi_fork, Spl ITR(1, "fork1", "") }, /* 195 */ + { abi_fork, Spl ITR(1, "forkall", "") }, /* 196 */ + { 0, Ukn ITR(1, "modload", "") }, /* 197 */ + { 0, Ukn ITR(1, "moduload", "") }, /* 198 */ + { 0, Ukn ITR(1, "modpath", "") }, /* 199 */ + { 0, Ukn ITR(1, "modstat", "") }, /* 200 */ + { 0, Ukn ITR(1, "modadm", "") }, /* 201 */ + { 0, Ukn ITR(1, "getksym", "") }, /* 202 */ + { 0, Ukn ITR(1, "lwpsuspend", "") }, /* 203 */ + { 0, Ukn ITR(1, "lwpcontinue", "") }, /* 204 */ + { 0, Ukn ITR(1, "priocntllst", "") }, /* 205 */ + { uw7_sleep, 1 ITR(1, "sleep", "d") }, /* 206 */ + { 0, Ukn ITR(1, "lwp_sema_wait", "") }, /* 207 */ + { 0, Ukn ITR(1, "lwp_sema_post", "") }, /* 208 */ + { 0, Ukn ITR(1, "lwp_sema_trywait","") }, /* 209 */ + { 0, Ukn ITR(1, "reserved 210","") }, /* 210 */ + { 0, Ukn ITR(1, "unused 211","") }, /* 211 */ + { 0, Ukn ITR(1, "unused 212","") }, /* 212 */ + { 0, Ukn ITR(1, "unused 213","") }, /* 213 */ + { 0, Ukn ITR(1, "unused 214","") }, /* 214 */ + { 0, Ukn ITR(1, "unused 215","") }, /* 215 */ + { uw7_fstatvfs64, 2 ITR(1, "fstatvfs64", "dp") }, /* 216 */ + { uw7_statvfs64, 2 ITR(1, "statvfs64", "sp") }, /* 217 */ + { 0, Ukn ITR(1, "ftruncate64","") }, /* 218 */ + { 0, Ukn ITR(1, "truncate64","") }, /* 219 */ + { 0, Ukn ITR(1, "getrlimit64","") }, /* 220 */ + { 0, Ukn ITR(1, "setrlimit64","") }, /* 221 */ + { uw7_lseek64, 4 ITR(1, "lseek64", "dddd") }, /* 222 */ + { 0, Ukn ITR(1, "mmap64","") }, /* 223 */ + { uw7_pread64, 5 ITR(1, "pread64", "dsddd")}, /* 224 */ + { uw7_pwrite64, 5 ITR(1, "pwrite64", "dsddd")}, /* 225 */ + { 0, Ukn ITR(1, "creat64","") }, /* 226 */ + { 0, Ukn ITR(1, "dshmsys","") }, /* 227 */ + { 0, Ukn ITR(1, "invlpg","") }, /* 228 */ + { 0, Ukn ITR(1, "rfork1","") }, /* 229 */ + { 0, Ukn ITR(1, "rforkall","") }, /* 230 */ + { 0, Ukn ITR(1, "rexecve","") }, /* 231 */ + { 0, Ukn ITR(1, "migrate","") }, /* 232 */ + { 0, Ukn ITR(1, "kill3","") }, /* 233 */ + { 0, Ukn ITR(1, "ssisys","") }, /* 234 */ + { 0, Ukn ITR(1, "xaccept","") }, /* 235 */ + { 0, Ukn ITR(1, "xbind","") }, /* 236 */ + { 0, Ukn ITR(1, "xbindresvport","") }, /* 237 */ + { 0, Ukn ITR(1, "xconnect","") }, /* 238 */ + { 0, Ukn ITR(1, "xgetsockaddr","") }, /* 239 */ + { 0, Ukn ITR(1, "xgetsockopt","") }, /* 240 */ + { 0, Ukn ITR(1, "xlisten","") }, /* 241 */ + { 0, Ukn ITR(1, "xrecvmsg","") }, /* 242 */ + { 0, Ukn ITR(1, "xsendmsg","") }, /* 243 */ + { 0, Ukn ITR(1, "xsetsockaddr","") }, /* 244 */ + { 0, Ukn ITR(1, "xsetsockopt","") }, /* 245 */ + { 0, Ukn ITR(1, "xshutdown","") }, /* 246 */ + { 0, Ukn ITR(1, "xsocket","") }, /* 247 */ + { 0, Ukn ITR(1, "xsocketpair","") }, /* 248 */ + { 0, Ukn ITR(1, "unused 249","") }, /* 249 */ + { 0, Ukn ITR(1, "unused 250","") }, /* 250 */ +}; + +static void +UW7_lcall7(int segment, struct pt_regs * regs) +{ + abi_dispatch(regs, &uw7_funcs[regs->eax & 0xff], 1); +} + +static struct exec_domain uw7_exec_domain = { + name: "UnixWare 7", + handler: UW7_lcall7, + pers_low: 14 /* PER_UW7 */, + pers_high: 14 /* PER_UW7 */, + signal_map: ibcs_to_linux_signals, + signal_invmap: linux_to_ibcs_signals, + err_map: svr4_err_map, + socktype_map: svr4_socktype_map, + sockopt_map: abi_sockopt_map, + af_map: abi_af_map, + module: THIS_MODULE +}; + +static int __init +init_uw7(void) +{ + return (register_exec_domain(&uw7_exec_domain)); +} + +static void __exit +cleanup_uw7(void) +{ + unregister_exec_domain(&uw7_exec_domain); +} + +module_init(init_uw7); +module_exit(cleanup_uw7); diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/uw7/ioctl.c linux/abi/uw7/ioctl.c --- linux-2.4.3/abi/uw7/ioctl.c Thu Jan 1 01:00:00 1970 +++ linux/abi/uw7/ioctl.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,224 @@ +/* + * abi/uw7/ioctl.c - Support for UnixWare 7.x ioctl(2) system call. + * + * This module provides a function uw7_ioctl() which is called indirectly + * via uw7_funcs[] array, see abi/uw7/funcs.c. + * This software is under GPL + */ + +#include +#include + +#include + +#include +#include +#include + + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + + +static int tioc_tcgets(int fd, struct uw7_termios * tios); +static int tioc_tcsets(int fd, int lnx_cmd, struct uw7_termios * tios); +static int ioctl_T(int fd, unsigned int cmd, void * arg); + +int uw7_ioctl(struct pt_regs * regs) +{ + int fd; + unsigned int cmd, class; + void * arg; + char class_str[4]; + + fd = (int)get_syscall_parameter(regs, 0); + cmd = (unsigned int)get_syscall_parameter(regs, 1); + arg = (void *)get_syscall_parameter(regs, 2); + class = cmd >> 8; + switch (class) { + case 'T': + return ioctl_T(fd, cmd, arg); + } + + class_str[0] = class & 0xFF0000 ? (char)((class >> 16) & 0xFF) : '.'; + class_str[1] = class & 0x00FF00 ? (char)((class >> 8) & 0xFF) : '.'; + class_str[2] = class & 0x0000FF ? (char)((class ) & 0xFF) : '.'; + class_str[3] = 0; + + DBG(KERN_ERR "UW7: ioctl(%d, %x[%s], 0x%lx) unsupported\n", + fd, cmd, class_str, (unsigned long)arg); + + return -EINVAL; +} + +static int tioc_tcsets(int fd, int lnx_cmd, struct uw7_termios * tios) +{ + struct termios t; + struct uw7_termios tmp = {0, }; + mm_segment_t old_fs; + int error; + + DBG(KERN_ERR "UW7[%d]: tioc_tcsets(%d,%x,%p)\n", + current->pid, fd, lnx_cmd, tios); + + error = verify_area(VERIFY_READ, tios, sizeof(struct uw7_termios)); + if (error) + return error; + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETS, &t); + set_fs(old_fs); + if (error) + return error; + + if (copy_from_user(&tmp, tios, sizeof(struct uw7_termios))) + return -EFAULT; + t.c_iflag = tmp.c_iflag & ~UW7_DOSMODE; + t.c_oflag = tmp.c_oflag; + t.c_cflag = tmp.c_cflag; + t.c_lflag = tmp.c_lflag & ~UW7_DEFECHO; + if (tmp.c_lflag & UW7_FLUSHO) + t.c_lflag |= FLUSHO; + else + t.c_lflag &= ~FLUSHO; + + DBG(KERN_ERR + "UW7[%d]: iflag: %lx->%lx, oflag: %lx->%lx, cflag: %lx->%lx, lflag: %lx->%lx\n", + current->pid, tmp.c_iflag, t.c_iflag, tmp.c_oflag, t.c_oflag, + tmp.c_cflag, t.c_cflag, tmp.c_lflag, t.c_lflag); + + t.c_cc[VINTR] = tmp.c_cc[UW7_VINTR]; + t.c_cc[VQUIT] = tmp.c_cc[UW7_VQUIT]; + t.c_cc[VERASE] = tmp.c_cc[UW7_VERASE]; + t.c_cc[VKILL] = tmp.c_cc[UW7_VKILL]; + t.c_cc[VEOL2] = tmp.c_cc[UW7_VEOL2]; + t.c_cc[VSWTC] = tmp.c_cc[UW7_VSWTCH]; + t.c_cc[VSTART] = tmp.c_cc[UW7_VSTART]; + t.c_cc[VSTOP] = tmp.c_cc[UW7_VSTOP]; + t.c_cc[VSUSP] = tmp.c_cc[UW7_VSUSP]; + t.c_cc[VREPRINT] = tmp.c_cc[UW7_VREPRINT]; + t.c_cc[VDISCARD] = tmp.c_cc[UW7_VDISCARD]; + t.c_cc[VWERASE] = tmp.c_cc[UW7_VWERASE]; + t.c_cc[VLNEXT] = tmp.c_cc[UW7_VLNEXT]; + if (t.c_lflag & ICANON) { + t.c_cc[VEOF] = tmp.c_cc[UW7_VEOF]; + t.c_cc[VEOL] = tmp.c_cc[UW7_VEOL]; + } else { + t.c_cc[VMIN] = tmp.c_cc[UW7_VMIN]; + t.c_cc[VTIME] = tmp.c_cc[UW7_VTIME]; + t.c_cc[VEOL] = tmp.c_cc[UW7_VEOL2]; + } + + + DBG(KERN_ERR + "UW7[%d]: " + "VINTR: %x->%x, VQUIT: %x->%x, VERASE: %x->%x, VKILL: %x->%x\n" + "VEOL2: %x->%x\n", + current->pid, tmp.c_cc[UW7_VINTR], t.c_cc[VINTR], + tmp.c_cc[UW7_VQUIT], t.c_cc[VQUIT], + tmp.c_cc[UW7_VERASE], t.c_cc[VERASE], + tmp.c_cc[UW7_VKILL], t.c_cc[VKILL], + tmp.c_cc[UW7_VEOL2], t.c_cc[VEOL2]); + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, lnx_cmd, &t); + set_fs(old_fs); + return error; +} + +static int tioc_tcgets(int fd, struct uw7_termios * tios) +{ + struct termios t; + struct uw7_termios tmp = { 0 }; + mm_segment_t old_fs; + int error; + + DBG(KERN_ERR "UW7[%d]: tioc_tcgets(%d,%p)\n", current->pid, fd, tios); + + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(ioctl)(fd, TCGETS, &t); + set_fs(old_fs); + if (error) + return error; + + tmp.c_iflag = UW7_IFLAG_MSK & (t.c_iflag & ~UW7_DOSMODE); + tmp.c_oflag = UW7_OFLAG_MSK & t.c_oflag; + tmp.c_cflag = UW7_CFLAG_MSK & t.c_cflag; + tmp.c_lflag = UW7_LFLAG_MSK & (t.c_lflag & ~UW7_DEFECHO); + if (t.c_lflag & FLUSHO) + tmp.c_lflag |= UW7_FLUSHO; + else + tmp.c_lflag &= ~UW7_FLUSHO; + + DBG(KERN_ERR + "UW7[%d]: iflag: %lx->%lx, oflag: %lx->%lx, cflag: %lx->%lx, lflag: %lx->%lx\n", + current->pid, tmp.c_iflag, t.c_iflag, tmp.c_oflag, t.c_oflag, + tmp.c_cflag, t.c_cflag, tmp.c_lflag, t.c_lflag); + + if (t.c_lflag & ICANON) { + tmp.c_cc[UW7_VEOF] = t.c_cc[VEOF]; + tmp.c_cc[UW7_VEOL] = t.c_cc[VEOL]; + } else { + tmp.c_cc[UW7_VMIN] = t.c_cc[VMIN]; + tmp.c_cc[UW7_VTIME] = t.c_cc[VTIME]; + } + + tmp.c_cc[UW7_VINTR] = t.c_cc[VINTR]; + tmp.c_cc[UW7_VQUIT] = t.c_cc[VQUIT]; + tmp.c_cc[UW7_VERASE] = t.c_cc[VERASE]; + tmp.c_cc[UW7_VKILL] = t.c_cc[VKILL]; + tmp.c_cc[UW7_VEOL2] = t.c_cc[VEOL2]; + tmp.c_cc[UW7_VSWTCH] = t.c_cc[VSWTC]; + tmp.c_cc[UW7_VSTART] = t.c_cc[VSTART]; + tmp.c_cc[UW7_VSTOP] = t.c_cc[VSTOP]; + tmp.c_cc[UW7_VSUSP] = tmp.c_cc[UW7_VDSUSP] = t.c_cc[VSUSP]; + tmp.c_cc[UW7_VREPRINT] = t.c_cc[VREPRINT]; + tmp.c_cc[UW7_VDISCARD] = t.c_cc[VDISCARD]; + tmp.c_cc[UW7_VWERASE] = t.c_cc[VWERASE]; + tmp.c_cc[UW7_VLNEXT] = t.c_cc[VLNEXT]; + + return copy_to_user(tios, &tmp, sizeof(struct uw7_termios)) ? -EFAULT : 0; +} + +static int ioctl_T(int fd, unsigned int cmd, void * arg) +{ + DBG(KERN_ERR "ioctl_T(%d,%x,%p)\n", fd, cmd, arg); + + switch (cmd) { + case UW7_TCSBRK: + return SYS(ioctl)(fd, TCSBRK, arg); + + case UW7_TCXONC: + return SYS(ioctl)(fd, TCXONC, arg); + + case UW7_TCFLSH: + return SYS(ioctl)(fd, TCFLSH, arg); + + case UW7_TIOCSWINSZ: + return SYS(ioctl)(fd, TIOCSWINSZ, arg); + + case UW7_TIOCGWINSZ: + return SYS(ioctl)(fd, TIOCGWINSZ, arg); + + case UW7_TCGETS: + return tioc_tcgets(fd, arg); + + case UW7_TCSETS: + return tioc_tcsets(fd, TCSETS, arg); + + case UW7_TCSETSW: + return tioc_tcsets(fd, TCSETSW, arg); + + case UW7_TCSETSF: + return tioc_tcsets(fd, TCSETSF, arg); + } + return -EINVAL; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/uw7/kernel.c linux/abi/uw7/kernel.c --- linux-2.4.3/abi/uw7/kernel.c Thu Jan 1 01:00:00 1970 +++ linux/abi/uw7/kernel.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,97 @@ +/* + * abi/uw7/kernel.c - various UW7 system calls. + * + * This software is under GPL + */ + +#include + +#include +#include +#include + + +#include +#include + + +int uw7_sleep(int seconds) +{ + struct timespec t; + mm_segment_t old_fs; + int error; + + t.tv_sec = seconds; + t.tv_nsec = 0; + old_fs = get_fs(); + set_fs(get_ds()); + error = SYS(nanosleep)(&t, NULL); + set_fs(old_fs); + return error; +} + +#define UW7_MAXUID 60002 + +int uw7_seteuid(int uid) +{ + if (uid < 0 || uid > UW7_MAXUID) + return -EINVAL; + return SYS(setreuid)(-1, uid); +} + +int uw7_setegid(int gid) +{ + if (gid < 0 || gid > UW7_MAXUID) + return -EINVAL; + return SYS(setreuid)(-1, gid); +} + +int uw7_lseek64(unsigned int fd, unsigned int off, unsigned int off_hi, unsigned int orig) +{ + loff_t result; /* XXX: how does uw7 return the result? -- ch */ + int retval; + + /* if (off_hi != 0) (commented because some buggy progs set off_hi = -1) + return -EINVAL; */ + retval = SYS(_llseek)(fd, (off_t) off_hi, off, &result, orig); + + return retval ? retval : (int) result; +} + +/* can't call sys_pread() directly because off is 32bit on UW7 */ +int uw7_pread(unsigned int fd, char * buf, int count, long off) +{ + return SYS(pread)(fd, buf, count, (loff_t)off); +} + +int uw7_pread64(unsigned int fd, char * buf, int count, unsigned int off, unsigned int off_hi) +{ + if (off_hi != 0) + return -EINVAL; + + return SYS(pread)(fd, buf, count, ((loff_t) off_hi << 32) | off); +} + +int uw7_pwrite64(unsigned int fd, char * buf, int count, unsigned int off, unsigned int off_hi) +{ + if (off_hi != 0) + return -EINVAL; + + return SYS(pread)(fd, buf, count, ((loff_t) off_hi << 32) | off); +} + +/* can't call sys_pwrite() directly because off is 32bit on UW7 */ +int uw7_pwrite(unsigned int fd, char * buf, int count, long off) +{ + return SYS(pwrite)(fd, buf, count, (loff_t)off); +} + +int uw7_stty(int fd, int cmd) +{ + return -EIO; +} + +int uw7_gtty(int fd, int cmd) +{ + return -EIO; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/uw7/mac.c linux/abi/uw7/mac.c --- linux-2.4.3/abi/uw7/mac.c Thu Jan 1 01:00:00 1970 +++ linux/abi/uw7/mac.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,41 @@ +/* + * abi/uw7/mac.c - mldmode(2) and friends. + * + * This software is under GPL + */ + +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#define UW7_MLD_REAL 1 +#define UW7_MLD_VIRT 0 +#define UW7_MLD_QUERY 2 + +int uw7_mldmode(int mldmode) +{ + switch (mldmode) { + case UW7_MLD_REAL: + DBG(KERN_ERR "UW7[%d]: mldmode(MLD_REAL)\n", current->pid); + break; + + case UW7_MLD_VIRT: + DBG(KERN_ERR "UW7[%d]: mldmode(MLD_VIRT)\n", current->pid); + break; + + case UW7_MLD_QUERY: + DBG(KERN_ERR "UW7[%d]: mldmode(MLD_QUERY)\n", current->pid); + return UW7_MLD_REAL; + + default: + return -EINVAL; + } + return 0; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/uw7/mmap.c linux/abi/uw7/mmap.c --- linux-2.4.3/abi/uw7/mmap.c Thu Jan 1 01:00:00 1970 +++ linux/abi/uw7/mmap.c Fri Mar 30 16:14:07 2001 @@ -0,0 +1,43 @@ +/* + * abi/uw7/mmap.c - mmap(2) system call. + * + * This software is under GPL + */ + +#include +#include +#include +#include +#include + +#include +#include + +/* same as arch/i386/kernel/sys_i386.c:sys_mmap2 (besides the UW_* handling) -- ch */ +int uw7_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long offset) +{ + int error = -EBADF; + struct file * file = NULL; + + if (flags & UW7_MAP_ANONYMOUS) { + flags |= MAP_ANONYMOUS; + flags &= ~UW7_MAP_ANONYMOUS; + } + + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + if (!(flags & MAP_ANONYMOUS)) { + file = fget(fd); + if (!file) + goto out; + } + + down_write(¤t->mm->mmap_sem); + error = do_mmap(file, addr, len, prot, flags, offset); + up_write(¤t->mm->mmap_sem); + + if (file) + fput(file); +out: + return error; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/abi/uw7/statvfs.c linux/abi/uw7/statvfs.c --- linux-2.4.3/abi/uw7/statvfs.c Thu Jan 1 01:00:00 1970 +++ linux/abi/uw7/statvfs.c Mon Mar 12 16:34:48 2001 @@ -0,0 +1,76 @@ +/* + * abi/uw7/statvfs.c - statvfs64() and friends for UW7 + * + * This software is under GPL + */ + +#include +#include + +#include + +#include + +static int +cp_uw7_statvfs64(struct super_block * sb, struct statfs * src, + struct uw7_statvfs64 * dst) +{ + struct uw7_statvfs64 tmp = {0, }; + + tmp.f_bsize = src->f_bsize; + tmp.f_frsize = src->f_bsize; + tmp.f_blocks = src->f_blocks;; + tmp.f_bfree = src->f_bfree; + tmp.f_bavail = src->f_bavail; + tmp.f_files = src->f_files; + tmp.f_ffree = src->f_ffree; + tmp.f_favail = src->f_ffree; + tmp.f_fsid = sb->s_dev; + + strcpy(tmp.f_basetype, sb->s_type->name); + + tmp.f_flag = 0; + tmp.f_namemax = src->f_namelen; + + return copy_to_user(dst, &tmp, sizeof(tmp)) ? -EFAULT : 0; +} + +int +uw7_statvfs64(char * filename, struct uw7_statvfs64 * buf) +{ + + struct nameidata nd; + int error; + + error = user_path_walk(filename, &nd); + if (!error) { + struct statfs tmp; + error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); + if (!error && cp_uw7_statvfs64(nd.dentry->d_inode->i_sb, &tmp, buf)) + error = -EFAULT; + path_release(&nd); + } + + return error; +} + + +int +uw7_fstatvfs64(int fd, struct uw7_statvfs64 * buf) +{ + struct file * file; + struct statfs tmp; + int error; + + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); + if (!error && cp_uw7_statvfs64(file->f_dentry->d_inode->i_sb, &tmp, buf)) + error = -EFAULT; + fput(file); + +out: + return error; +} diff -uNr --exclude-from=dontdiff linux-2.4.3/arch/i386/config.in linux/arch/i386/config.in --- linux-2.4.3/arch/i386/config.in Fri Mar 30 14:45:00 2001 +++ linux/arch/i386/config.in Fri Mar 30 17:25:23 2001 @@ -246,6 +246,8 @@ endmenu +source abi/Config.in + source drivers/mtd/Config.in source drivers/parport/Config.in diff -uNr --exclude-from=dontdiff linux-2.4.3/fs/Makefile linux/fs/Makefile --- linux-2.4.3/fs/Makefile Fri Mar 30 14:48:44 2001 +++ linux/fs/Makefile Fri Mar 30 17:25:23 2001 @@ -64,6 +64,8 @@ obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o +obj-$(CONFIG_BINFMT_XOUT) += binfmt_xout.o +obj-$(CONFIG_BINFMT_COFF) += binfmt_coff.o obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o obj-$(CONFIG_BINFMT_MISC) += binfmt_misc.o diff -uNr --exclude-from=dontdiff linux-2.4.3/fs/binfmt_coff.c linux/fs/binfmt_coff.c --- linux-2.4.3/fs/binfmt_coff.c Thu Jan 1 01:00:00 1970 +++ linux/fs/binfmt_coff.c Fri Mar 30 16:32:53 2001 @@ -0,0 +1,950 @@ +/* $Id$ */ +/* + * These are the functions used to load COFF IBCS style executables. + * Information on COFF format may be obtained in either the Intel Binary + * Compatibility Specification 2 or O'Rilley's book on COFF. The shared + * libraries are defined only the in the Intel book. + * + * This file is based upon code written by Eric Youngdale for the ELF object + * file format. + * + * Author: Al Longyear (longyear@sii.com) + * + * Latest Revision: + * 3 February 1994 + * Al Longyear (longyear@sii.com) + * Cleared first page of bss section using put_fs_byte. + * + * 4 February 1994 + * Mike Jagdis (jaggy@purplet.demon.co.uk) + * Added scanning of .comment sections for clues as to the + * "personality" of the executable. This is then used to emulate + * the right set of non-standard syscall extensions and bugs. :-) + * + * 18 February 1994 + * Mike Jagdis (jaggy@purplet.demon.co.uk) + * If compile the module version of iBCS rather than the in-kernel + * version we must take care to signal when module code is in use + * or it may be freed from under us - Bad News :-). + */ + + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +static unsigned long * create_coff_tables(char *p, + struct linux_binprm *bprm, int ibcs); + +static int load_coff_binary(struct linux_binprm *bprm, struct pt_regs *regs); +static int load_coff_library(struct file * file); +static int preload_library(struct linux_binprm *exe_bprm, + COFF_SCNHDR * sect, struct file *fp); +static int load_object(struct linux_binprm *bprm, struct pt_regs *regs, + int lib_ok); +static int parse_comments(struct linux_binprm *exe_bprm, COFF_SCNHDR * sect, + long *personality); + +/* + * The following table gives clues to the "personality" of the executable + * which we hope to find in the .comment sections of the binary. + * The set here may not be comprehensive even for those systems listed. + * Use 'mcs -p' to list the .comments sections of a binary to see what + * clues might be there. Or use 'strings' if you don't have mcs. + */ +struct coff_clue { + short terminal; /* non-zero to stop parsing with this entry */ + short len; /* negative number uses strstr for lookup */ + char *text; + unsigned long mask_and, mask_or; +}; + +static struct coff_clue coff_clues[] = { + /* Wyse Unix V/386 3.2.1[A]. */ + {1, 36, "@(#) UNIX System V/386 Release 3.2.1", + 0, PER_WYSEV386}, + + /* SCO Unix V 3.2, 3.2.2, 3.2.4, 3.2.4.2 etc. */ + {1, 23, "@(#) crt1.s 1.8 89/05/30", + 0, PER_SCOSVR3}, + {1, 16, "@(#)SCO UNIX 3.2", + 0, PER_SCOSVR3}, + {1, 18, "\"@(#) SCO UNIX 3.2", + 0, PER_SCOSVR3}, + {1, 17, "@(#) SCO UNIX 3.2", + 0, PER_SCOSVR3}, + {1, 11, "@(#)SCO 3.2", + 0, PER_SCOSVR3}, + + /* + * SCO Unix 3.2.4.2 OpenServer 5 gives 32 bit inodes except + * programs compiled with ods30 compatibilty. In fact OS5 + * always gives 32 bits but the library drops the top 16 in + * odt30 mode. We know what should happen and do it however. + */ + {0, 32, "@(#) crt1.s.source 20.1 94/12/04", + 0, PER_SCOSVR3}, + {1, 13, "ods_30_compat", + ~0, SHORT_INODE}, + + /* Interactive (ISC) 4.0 */ + {1, -1, "INTERACTIVE", + 0, PER_ISCR4}, + + /* End of table */ + {0, 0, 0, 0, 0} +}; + + +static struct linux_binfmt coff_format = { + NULL, THIS_MODULE, load_coff_binary, load_coff_library, NULL, PAGE_SIZE +}; + + +/* + * Small procedure to test for the proper file alignment. + */ + +static inline int is_properly_aligned(COFF_SCNHDR * sect) +{ + long scnptr = COFF_LONG(sect->s_scnptr); + long vaddr = COFF_LONG(sect->s_vaddr); + + +/* + * Return the error code if the section is not properly aligned. + */ + + return ((((vaddr - scnptr) & ~PAGE_MASK) != 0) ? -ENOEXEC : 0); +} + +/* + * Clear the bytes in the last page of data. + */ + +static +int clear_memory(unsigned long addr, unsigned long size) +{ + int status; + + size = (PAGE_SIZE - (addr & ~PAGE_MASK)) & ~PAGE_MASK; + if (size == 0) + status = 0; + else { + + status = verify_area(VERIFY_WRITE, (void *) addr, size); + if (status >= 0) + while (size-- != 0) { + __put_user(0, (char *) addr); + addr++; + } + } + return status; +} + +struct coff_section { + long scnptr; + long size; + long vaddr; +}; + +static inline unsigned long +map_coff(struct file *file, struct coff_section * sect, unsigned long prot, + unsigned long flag, unsigned long offset) +{ + unsigned long map_addr; + + down(¤t->mm->mmap_sem); + map_addr = do_mmap(file, + sect->vaddr & PAGE_MASK, + sect->size + (sect->vaddr & ~PAGE_MASK), + prot, flag, offset); + up(¤t->mm->mmap_sem); + + return (map_addr); +} + + +/* + * Helper function to process the load operation. + */ + +static int +load_object(struct linux_binprm * bprm, struct pt_regs * regs, int lib_ok) +{ + COFF_FILHDR * coff_hdr = NULL; + COFF_SCNHDR * sect_bufr = NULL; /* Pointer to section table */ + COFF_SCNHDR * sect_ptr = NULL; + + COFF_SCNHDR * text_sect, * data_sect, * bss_sect; + + struct coff_section text, data, bss; + mm_segment_t old_fs; + + int text_count, data_count, bss_count, lib_count; + + unsigned int start_addr = 0; /* Starting location for program */ + short int sections = 0; /* Number of sections in the file */ + short int aout_size = 0; /* Size of the a.out header area */ + short int flags; /* Flag bits from the COFF header */ + int not_pageable = 0; /* Can we demand page the executable? */ + unsigned long p = bprm->p; + unsigned long personality; + int coff_exec_fileno; + + int status = 0; /* Result status register */ + int nIndex; + + text_sect = data_sect = bss_sect = NULL; + + coff_hdr = (COFF_FILHDR *) bprm->buf; /* COFF Header */ + + /* + * Validate the magic value for the object file. + */ + + if (COFF_I386BADMAG(*coff_hdr)) + return -ENOEXEC; + + flags = COFF_SHORT(coff_hdr->f_flags); + + /* + * The object file should have 32 BIT little endian format. Do not allow + * it to have the 16 bit object file flag set as Linux is not able to run + * on the 80286/80186/8086. + */ + if ((flags & (COFF_F_AR32WR | COFF_F_AR16WR)) != COFF_F_AR32WR) + return -ENOEXEC; + + /* + * If the file is not executable then reject the execution. This means + * that there must not be external references. + */ + if ((flags & COFF_F_EXEC) == 0) + return -ENOEXEC; + + /* + * Extract the header information which we need. + */ + sections = COFF_SHORT(coff_hdr->f_nscns); /* Number of sections */ + aout_size = COFF_SHORT(coff_hdr->f_opthdr); /* Size of opt. headr */ + + /* + * There must be atleast one section. + */ + if (!sections) + return -ENOEXEC; + + if (!bprm->file->f_op->mmap) + not_pageable = 1; + + if (!(sect_bufr = kmalloc(sections * COFF_SCNHSZ, GFP_KERNEL))) { + printk(KERN_WARNING "coff: kmalloc failed\n"); + return -ENOMEM; + } + + status = kernel_read(bprm->file, aout_size + COFF_FILHSZ, + (char *)sect_bufr, sections * COFF_SCNHSZ); + if (status < 0) + goto out_free_buf; + + status = get_unused_fd(); + if (status < 0) + goto out_free_buf; + + get_file(bprm->file); + fd_install(coff_exec_fileno = status, bprm->file); + + text_count = 0; + data_count = 0; + bss_count = 0; + lib_count = 0; + + /* + * Loop through the sections and find the various types + */ + sect_ptr = sect_bufr; + + for (nIndex = 0; nIndex < sections; ++nIndex) { + long int sect_flags = COFF_LONG(sect_ptr->s_flags); + + switch (sect_flags) { + case COFF_STYP_TEXT: + status = is_properly_aligned(sect_ptr); + text_sect = sect_ptr; + text_count++; + break; + + case COFF_STYP_DATA: + status = is_properly_aligned(sect_ptr); + data_sect = sect_ptr; + data_count++; + break; + + case COFF_STYP_BSS: + bss_sect = sect_ptr; + bss_count++; + break; + + case COFF_STYP_LIB: + lib_count++; + break; + + default: + break; + } + + sect_ptr = (COFF_SCNHDR *) & ((char *) sect_ptr)[COFF_SCNHSZ]; + } + + /* + * If any of the sections weren't properly aligned we aren't going to + * be able to demand page this executable. Note that at this stage the + * *only* excuse for having status <= 0 is if the alignment test failed. + */ + + if (status < 0) { + not_pageable = 1; + status = 0; + } + + /* + * Ensure that there are the required sections. There must be one text + * sections and one each of the data and bss sections for an executable. + * A library may or may not have a data / bss section. + */ + + if (text_count != 1) + status = -ENOEXEC; + + if (lib_ok) + if (data_count != 1 || bss_count != 1) + status = -ENOEXEC; + + /* + * If there is no additional header then assume the file starts at + * the first byte of the text section. This may not be the proper place, + * so the best solution is to include the optional header. A shared library + * __MUST__ have an optional header to indicate that it is a shared library. + */ + + if (status < 0) + goto out_free_file; + + if (aout_size == 0) { + if (!lib_ok) + status = -ENOEXEC; + start_addr = COFF_LONG(text_sect->s_vaddr); + + /* + * There is some header. Ensure that it is sufficient. + */ + + } else { + if (aout_size < (short) COFF_AOUTSZ) + status = -ENOEXEC; + else { + /* Pointer to a.out header */ + COFF_AOUTHDR *aout_hdr = + (COFF_AOUTHDR *) & ((char *) coff_hdr)[COFF_FILHSZ]; + short int aout_magic = COFF_SHORT(aout_hdr->magic); /* id */ + + /* + * Validate the magic number in the a.out header. If it is valid then + * update the starting symbol location. Do not accept these file formats + * when loading a shared library. + */ + + switch (aout_magic) { + case COFF_OMAGIC: + case COFF_ZMAGIC: + case COFF_STMAGIC: + if (!lib_ok) + status = -ENOEXEC; + start_addr = + (unsigned int) COFF_LONG(aout_hdr->entry); + break; + + /* + * Magic value for a shared library. This is valid only when loading a + * shared library. (There is no need for a start_addr. It won't be used.) + */ + + case COFF_SHMAGIC: + if (lib_ok) + status = -ENOEXEC; + break; + + default: + status = -ENOEXEC; + break; + } + } + } + + if (status < 0) + goto out_free_file; + + /* + * Generate the proper values for the text fields + * + * THIS IS THE POINT OF NO RETURN. THE NEW PROCESS WILL TRAP OUT SHOULD + * SOMETHING FAIL IN THE LOAD SEQUENCE FROM THIS POINT ONWARD. + */ + + text.scnptr = COFF_LONG(text_sect->s_scnptr); + text.size = COFF_LONG(text_sect->s_size); + text.vaddr = COFF_LONG(text_sect->s_vaddr); + + /* + * Generate the proper values for the data fields + */ + + if (data_sect != NULL) { + data.scnptr = COFF_LONG(data_sect->s_scnptr); + data.size = COFF_LONG(data_sect->s_size); + data.vaddr = COFF_LONG(data_sect->s_vaddr); + } else { + data.scnptr = 0; + data.size = 0; + data.vaddr = 0; + } + + /* + * Generate the proper values for the bss fields + */ + + if (bss_sect != NULL) { + bss.size = COFF_LONG(bss_sect->s_size); + bss.vaddr = COFF_LONG(bss_sect->s_vaddr); + } else { + bss.size = 0; + bss.vaddr = 0; + } + + /* + * Flush the executable from memory. At this point the executable is + * committed to being defined or a segmentation violation will occur. + */ + + if (lib_ok) { + status = flush_old_exec(bprm); /* SIGSEGV */ + if (status != 0) + goto out_free_file; + + /* + * Look for clues as to the system this binary was compiled on in the + * comments section(s). Only look at the main binary, not the shared + * libraries (or would it be better to prefer shared libraries over + * binaries? Or could they be different???) + */ + + personality = PER_SVR3; + + if (lib_ok) { + COFF_SCNHDR *sect_ptr2 = sect_bufr; + int i; + + for (i = 0; i < sections; i++) { + long sect_flags = COFF_LONG(sect_ptr2->s_flags); + + if (sect_flags == COFF_STYP_INFO && + (status = parse_comments(bprm, sect_ptr2, &personality)) > 0) + goto found; + + sect_ptr2 = (COFF_SCNHDR *) & ((char *) sect_ptr2) [COFF_SCNHSZ]; + } + + /* + * If no .comments section was found there is no way to + * figure out the personality. Odds on it is SCO though... + */ + personality = PER_SCOSVR3; + } + +found: + set_personality(personality); + + current->mm->start_data = 0; + current->mm->end_data = 0; + current->mm->end_code = 0; + current->mm->mmap = NULL; + current->flags &= ~PF_FORKNOEXEC; + + /* + * Construct the parameter and environment string table entries. + */ + + current->mm->rss = 0; + status = setup_arg_pages(bprm); + if (status < 0) { + send_sig(SIGSEGV, current, 1); + return status; + } + p = (unsigned long) create_coff_tables((char *) + bprm->p, bprm, 1); + + /* + * Do the end processing once the stack has been constructed + */ + + current->mm->end_code = text.size + + (current->mm->start_code = text.vaddr); + current->mm->end_data = data.size + + (current->mm->start_data = data.vaddr); + current->mm->brk = bss.size + + (current->mm->start_brk = bss.vaddr); + + current->mm->start_stack = p; + compute_creds(bprm); + start_thread(regs, start_addr, p); + } + + old_fs = get_fs(); + set_fs(get_ds()); + + if (not_pageable) { + /* + * Read the file from disk... + * + * XXX: untested. + */ + loff_t pos = data.scnptr; + status = do_brk(text.vaddr, text.size); + bprm->file->f_op->read(bprm->file, + (char *)data.vaddr, data.scnptr, &pos); + status = do_brk(data.vaddr, data.size); + bprm->file->f_op->read(bprm->file, + (char *)text.vaddr, text.scnptr, &pos); + status = 0; + } else { + /* + * Map the text pages + */ + + status = map_coff(bprm->file, &text, PROT_READ | PROT_EXEC, + MAP_FIXED | MAP_SHARED | MAP_DENYWRITE | MAP_EXECUTABLE, + text.scnptr & PAGE_MASK); + + if (status != (text.vaddr & PAGE_MASK)) { + status = -ENOEXEC; + goto out_free_file; + } + + /* + * Map the data pages + */ + + if (data.size != 0) { + status = map_coff(bprm->file, &data, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, + data.scnptr & PAGE_MASK); + + if (status != (data.vaddr & PAGE_MASK)) { + status = -ENOEXEC; + goto out_free_file; + } + } + } + + /* + * Construct the bss data for the process. The bss ranges from the + * end of the data (which may not be on a page boundary) to the end + * of the bss section. Allocate any necessary pages for the data. + */ + + if (bss.size != 0) { + down(¤t->mm->mmap_sem); + do_mmap(NULL, PAGE_ALIGN(bss.vaddr), + bss.size + bss.vaddr - + PAGE_ALIGN(bss.vaddr), + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, 0); + up(¤t->mm->mmap_sem); + status = clear_memory(bss.vaddr, bss.size); + + if (status < 0) + goto out_free_file; + } + + set_fs(old_fs); + + /* + * Load any shared library for the executable. + */ + + if (lib_ok && lib_count != 0) { + int nIndex; + COFF_SCNHDR *sect_ptr = sect_bufr; + + /* + * Find the library sections. (There should be at least one. It was counted + * earlier.) This will eventually recurse to our code and load the shared + * library with our own procedures. + */ + + for (nIndex = 0; nIndex < sections; ++nIndex) { + long int sect_flags = + COFF_LONG(sect_ptr->s_flags); + if (sect_flags == COFF_STYP_LIB) { + status = preload_library(bprm, + sect_ptr, bprm->file); + + if (status != 0) + break; + } + sect_ptr = + (COFF_SCNHDR *) & ((char *) sect_ptr) [COFF_SCNHSZ]; + } + } + + if (lib_ok) { + set_binfmt(&coff_format); + + /* + * Generate any needed trap for this process. If an error occured then + * generate a segmentation violation. If the process is being debugged + * then generate the load trap. (Note: If this is a library load then + * do not generate the trap here. Pass the error to the caller who + * will do it for the process in the outer lay of this procedure call.) + */ + + if (status < 0) + send_sig(SIGSEGV, current, 0); /* Generate the error trap */ + else { + if (current->ptrace & PT_PTRACED) + send_sig(SIGTRAP, current, 0); + } + status = 0; /* We are committed. It can't fail */ + } + + +out_free_file: + sys_close(coff_exec_fileno); + +out_free_buf: + kfree(sect_bufr); + return (status); +} + +/* + * This procedure will load the library listed in the file name given + * as the parameter. The result will be non-zero should something fail + * to load. + */ + +static int +preload_this_library(struct linux_binprm *exe_bprm, char *lib_name) +{ + int status; + mm_segment_t old_fs = get_fs(); +/* + * Change the FS register to the proper kernel address space and attempt + * to load the library. The library name is allocated from the kernel + * pool. + */ + set_fs(get_ds()); + status = SYS(uselib) (lib_name); + set_fs(old_fs); +/* + * Return the success/failure to the caller. + */ + return (status); +} + +/* + * This procedure is called to load a library section. The various + * libraries are loaded from the list given in the section data. + */ + +static int +preload_library(struct linux_binprm *exe_bprm, + COFF_SCNHDR * sect, struct file *fp) +{ + int status = 0; /* Completion status */ + long nbytes; /* Count of bytes in the header area */ +/* + * Fetch the size of the section. There must be enough room for at least + * one entry. + */ + nbytes = (long) COFF_LONG(sect->s_size); + if (nbytes < (long) COFF_SLIBSZ) { + status = -ENOEXEC; + } +/* + * Allocate a buffer to hold the section data + */ + else { + COFF_SLIBHD *phdr; + char *buffer = (char *) kmalloc(nbytes, GFP_KERNEL); + + if (0 == buffer) { + status = -ENOEXEC; + printk(KERN_WARNING "COFF: kmalloc failed\n"); + } else { + status = kernel_read(exe_bprm->file, + COFF_LONG(sect->s_scnptr), buffer, nbytes); + + if (status >= 0 && status != nbytes) + status = -ENOEXEC; + } +/* + * At this point, go through the list of libraries in the data area. + */ + phdr = (COFF_SLIBHD *) buffer; + while (status >= 0 && nbytes > (long) COFF_SLIBSZ) { + int entry_size = + COFF_LONG(phdr->sl_entsz) * sizeof(long); + int header_size = + COFF_LONG(phdr->sl_pathndx) * sizeof(long); +/* + * Validate the sizes of the various items. I don't trust the linker!! + */ + if ((unsigned) header_size >= (unsigned) nbytes || + entry_size <= 0 || + (unsigned) entry_size <= + (unsigned) header_size) { + status = -ENOEXEC; + } +/* + * Load the library. Stop the load process on the first error. + */ + else { + status = preload_this_library(exe_bprm, + &((char *) + phdr) + [header_size]); + } +/* + * Point to the next library in the section data. + */ + nbytes -= entry_size; + phdr = + (COFF_SLIBHD *) & ((char *) phdr)[entry_size]; + } +/* + * Release the space for the library list. + */ + if (buffer != NULL) + kfree(buffer); + } +/* + * Return the resulting status to the caller. + */ + return (status); +} + +/* + * Parse a comments section looking for clues as to the system this + * was compiled on so we can get the system call interface right. + */ + +static int +parse_comments(struct linux_binprm *exe_bprm, COFF_SCNHDR * sect, long *personality) +{ + unsigned long offset, nbytes; + char *buffer; + int status, hits; + +/* + * Fetch the size of the section. There must be something in there or the + * section wouldn't exist at all. We only bother with the first 8192 + * characters though. There isn't any point getting too carried away! + */ + if ((nbytes = COFF_LONG(sect->s_size)) > 8192) + nbytes = 8192; + + if (!(buffer = (char *) __get_free_page(GFP_KERNEL))) + return 0; + + hits = 0; + offset = COFF_LONG(sect->s_scnptr); + while (nbytes > 0) { + char *p; + unsigned long count, str_start; + + status = kernel_read(exe_bprm->file, offset, buffer, + nbytes > PAGE_SIZE ? PAGE_SIZE : nbytes); + + if (status <= 0) { + free_page((unsigned long) buffer); + return 0; + } + + p = buffer; + str_start = 0; + for (count = 0; count < status; count++) { + struct coff_clue *clue; + char c = *(buffer + PAGE_SIZE - 1); + *(buffer + PAGE_SIZE - 1) = '\0'; + for (clue = coff_clues; clue->len; clue++) { + if ((clue->len < 0 && strstr(p, clue->text)) + || (clue->len > 0 + && !strncmp(p, clue->text, clue->len))) { + *personality &= clue->mask_and; + *personality |= clue->mask_or; + if (clue->terminal) { + free_page((unsigned long) + buffer); + return (1); + } + hits++; + } + } + *(buffer + PAGE_SIZE - 1) = c; + + while (*p && count < status) + p++, count++; + if (count < status) { + p++; + count++; + str_start = count; + } + } + + /* If we didn't find an end ofstring at all this page + * probably isn't useful string data. + */ + if (str_start == 0) + str_start = status; + + nbytes -= str_start; + offset += str_start; + } + + free_page((unsigned long) buffer); + return hits; +} + + +/* + * Load the image for an (coff) binary. + * + * => this procedure is called by the main load sequence, + * it will load the executable and prepare it for execution + */ +static int +load_coff_binary(struct linux_binprm *bprm, struct pt_regs *regs) +{ + return load_object(bprm, regs, 1); +} + +/* + * Load the image for an (coff) shared library. + * + * => this is called when we need to load a library based upon a file name. + * => also called through preload_this_library + */ +static int +load_coff_library(struct file *fp) +{ + struct linux_binprm *bpp; + struct pt_regs regs; + int err = -ENOMEM; + + if (!(bpp = kmalloc(sizeof(struct linux_binprm), GFP_KERNEL))) { + printk(KERN_WARNING "coff: kmalloc failed\n"); + goto out; + } + + memset(bpp, 0, sizeof(struct linux_binprm)); + bpp->file = fp; + + if ((err = kernel_read(fp, 0L, bpp->buf, sizeof(bpp->buf))) < 0) + printk(KERN_WARNING "coff: unable to read library header\n"); + else + err = load_object(bpp, ®s, 0); + + kfree(bpp); +out: + return (err); +} + +static unsigned long * +create_coff_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++); + p += strlen_user(p); + } + + __put_user(NULL, argv); + current->mm->arg_end = current->mm->env_start = (unsigned long) p; + + while (envc-- > 0) { + __put_user(p, envp++); + p += strlen_user(p); + } + + __put_user(NULL, envp); + current->mm->env_end = (unsigned long) p; + + return sp; +} + + + + +static void __exit +cleanup_binfmt_coff(void) +{ + unregister_binfmt(&coff_format); +} + + + +static int __init +init_binfmt_coff(void) +{ + register_binfmt(&coff_format); + return 0; +} + +module_init(init_binfmt_coff); +module_exit(cleanup_binfmt_coff); + diff -uNr --exclude-from=dontdiff linux-2.4.3/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- linux-2.4.3/fs/binfmt_elf.c Fri Mar 30 14:48:44 2001 +++ linux/fs/binfmt_elf.c Fri Mar 30 17:25:23 2001 @@ -397,7 +397,6 @@ int load_addr_set = 0; char * elf_interpreter = NULL; unsigned int interpreter_type = INTERPRETER_NONE; - unsigned char ibcs2_interpreter = 0; mm_segment_t old_fs; unsigned long error; struct elf_phdr * elf_ppnt, *elf_phdata; @@ -477,40 +476,18 @@ elf_ppnt->p_filesz); if (retval < 0) goto out_free_interp; - /* If the program interpreter is one of these two, - * then assume an iBCS2 image. Otherwise assume - * a native linux image. + + /* + * Change our personality, if needed. */ - if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || - strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) - ibcs2_interpreter = 1; + SET_ELF_PERSONALITY(elf_ex, elf_interpreter); + #if 0 printk("Using ELF interpreter %s\n", elf_interpreter); #endif -#ifdef __sparc__ - if (ibcs2_interpreter) { - unsigned long old_pers = current->personality; - struct exec_domain *old_domain = current->exec_domain; - struct exec_domain *new_domain; - struct fs_struct *old_fs = current->fs, *new_fs; - get_exec_domain(old_domain); - atomic_inc(&old_fs->count); - - set_personality(PER_SVR4); - interpreter = open_exec(elf_interpreter); - - new_domain = current->exec_domain; - new_fs = current->fs; - current->personality = old_pers; - current->exec_domain = old_domain; - current->fs = old_fs; - put_exec_domain(new_domain); - put_fs_struct(new_fs); - } else -#endif - { - interpreter = open_exec(elf_interpreter); - } + + interpreter = open_exec(elf_interpreter); + retval = PTR_ERR(interpreter); if (IS_ERR(interpreter)) goto out_free_interp; @@ -582,10 +559,6 @@ current->flags &= ~PF_FORKNOEXEC; elf_entry = (unsigned long) elf_ex.e_entry; - /* Do this immediately, since STACK_TOP as used in setup_arg_pages - may depend on the personality. */ - SET_PERSONALITY(elf_ex, ibcs2_interpreter); - /* Do this so that we can load the interpreter, if need be. We will change some of these later */ current->mm->rss = 0; @@ -725,8 +698,7 @@ printk("(brk) %lx\n" , (long) current->mm->brk); #endif - if ( current->personality == PER_SVR4 ) - { + if (current->personality & MMAP_PAGE_ZERO) { /* Why this, you ask??? Well SVr4 maps page 0 as read-only, and some applications "depend" upon this behavior. Since we do not have the power to recompile these, we diff -uNr --exclude-from=dontdiff linux-2.4.3/fs/binfmt_xout.c linux/fs/binfmt_xout.c --- linux-2.4.3/fs/binfmt_xout.c Thu Jan 1 01:00:00 1970 +++ linux/fs/binfmt_xout.c Sun Mar 18 18:41:16 2001 @@ -0,0 +1,804 @@ +/* $Id$ + * binfmt_xout.c - support for the Microsoft Xenix x.out binary format + * + * Copyright (c) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + * Copyright (c) 2001 Christoph Hellwig (chhellwig@gmx.net) + * + * This file is based upon code written by Al Longyear for the COFF file + * format which is in turn based upon code written by Eric Youngdale for + * the ELF object file format. Any errors are most likely my own however. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +/* + * If you compile with dprintk defined to printk you will get + * lots of debugging messages from the x.out module. + */ +#define dprintk + +/* + * If you compile with XOUT_FORCE_PAGE defined (the default) + * then if all segments are aligned on 1k bounaries within the + * file and 4k boundaries within the address space we assume + * that no overlaps occur within the same VM page and the + * executable can thus be mmapped if the filesystem allows it. + * I believe this is the case for all 386 small model binaries, + * 286 binaries can't be demand paged. + */ +#define XOUT_FORCE_PAGE + +/* + * If you compile with XOUT_SEGMENTS defined the loader will take care + * to set up the LDT as would "real" Xenix. This shouldn't be necessary + * for most programs but it is just possible that something out there + * makes assumptions about its environment and uses segment overrides. + * + * The default is not to bother setting up the LDT unless we need support + * for Xenix 286 binaries. + */ +#undef XOUT_SEGMENTS + +/* + * Xenix 286 requires segment handling. + */ +#if defined(CONFIG_ABI_IBCS_X286) || defined(CONFIG_ABI_IBCS_X286) +#define XOUT_SEGMENTS +#endif + + +static int xout_load_binary(struct linux_binprm *, struct pt_regs *); +static int xout_load_library(struct file *); + +static struct linux_binfmt xout_format = { + NULL, THIS_MODULE, xout_load_binary, xout_load_library, NULL, PAGE_SIZE +}; + + +#if defined(XOUT_DEBUG) && defined(XOUT_SEGMENTS) +/* + * This is borrowed (with minor variations since we are in kernel mode) + * from the DPMI code for DOSEMU. I don't claim to understand LDTs :-). + */ +void +print_desc(int which) +{ + u_long base_addr, limit; + u_long *lp; + int count, type, dpl, i; + + if (which) { + lp = (u_long *)((struct desc_struct*)(current->mm->segments)); + count = LDT_ENTRIES; + printk(KERN_DEBUG "xout: LDT\n"); + } else { + lp = (u_long *)0x10c860; /* gdt; DANGER! MAGIC! */ + count = 8; + printk(KERN_DEBUG "xout: GDT\n"); + } + + if (!lp) + return; + + printk(KERN_DEBUG "XOUT: SLOT BASE/SEL LIM/OFF TYPE DPL ACCESSBITS\n"); + for (i=0; i < count; i++, lp++) { + /* First 32 bits of descriptor */ + base_addr = (*lp >> 16) & 0x0000FFFF; + limit = *lp & 0x0000FFFF; + lp++; + + /* First 32 bits of descriptor */ + base_addr |= (*lp & 0xFF000000) | ((*lp << 16) & 0x00FF0000); + limit |= (*lp & 0x000F0000); + type = (*lp >> 10) & 7; + dpl = (*lp >> 13) & 3; + if ((base_addr > 0) || (limit > 0 )) { + printk(KERN_DEBUG "XOUT: %03d 0x%08lx 0x%08lx 0x%02x %03d %s%s%s%s%s%s%s\n", + i, + base_addr, limit, type, dpl, + (*lp & 0x100) ? " ACCS'D" : "", + (*lp & 0x200) ? " R&W" : " R&X", + (*lp & 0x8000) ? " PRESENT" : "", + (*lp & 0x100000) ? " USER" : "", + (*lp & 0x200000) ? " X" : "", + (*lp & 0x400000) ? " 32" : "", + (*lp & 0x800000) ? " PAGES" : ""); + } + } +} +#endif + + +static u_long * +xout_create_tables(char *p, struct linux_binprm *bprm, int ibcs) +{ + int argc = bprm->argc, envc = bprm->envc; + u_long *argv,*envp; + u_long *sp; + + sp = (u_long *) ((-(u_long)sizeof(char *)) & (u_long) p); + sp -= envc+1; + envp = sp; + sp -= argc+1; + argv = sp; + if (!ibcs) { + sp--; + put_user(envp, sp); + sp--; + put_user(argv, sp); + } + sp--; + put_user(argc, sp); + current->mm->arg_start = (u_long) p; + while (argc-->0) { + put_user(p, argv); argv++; + p += strlen_user(p); + } + put_user(NULL,argv); + current->mm->arg_end = current->mm->env_start = (u_long) p; + while (envc-->0) { + put_user(p, envp); envp++; + p += strlen_user(p); + } + put_user(NULL,envp); + current->mm->env_end = (u_long) p; + return (sp); +} + + + + +/* + * If you compile with XOUT_FORCE_PAGE defined (the default) + * then if all segments are aligned on 1k bounaries within the + * file and 4k boundaries within the address space we assume + * that no overlaps occur within the same VM page and the + * executable can thus be mmapped if the filesystem allows it. + * I believe this is the case for all 386 small model binaries + * - which is all we support anyway. + */ +static __inline__ int +isaligned(struct xseg *seg) +{ + dprintk(KERN_DEBUG + "xout: %04x %04x %04x %02x %08lx %08lx %08lx %08lx\n", + seg->xs_type, seg->xs_attr, seg->xs_seg, + seg->xs_align, seg->xs_filpos, seg->xs_psize, + seg->xs_vsize, seg->xs_rbase); + +#ifdef XOUT_FORCE_PAGE + /* + * XXXX The file alignment should be dependent on the block size + * of the filesystem shouldn't it? + */ + if ((seg->xs_filpos & 0x3ff) | (seg->xs_rbase & ~PAGE_MASK)) + printk(KERN_DEBUG "xout: bad alignment - demand paging disabled\n"); + return ((seg->xs_filpos & 0x3ff) | (seg->xs_rbase & ~PAGE_MASK)); +#else + if ((seg->xs_filpos - seg->xs_rbase) & ~PAGE_MASK) + printk(KERN_DEBUG "xout: bad alignment - demand paging disabled\n"); + return ((seg->xs_filpos - seg->xs_rbase) & ~PAGE_MASK); +#endif +} + + +static __inline__ void +clear_memory(u_long addr, u_long size) +{ + while (size-- != 0) + put_user(0, (char *)addr++); +} + +static int +xout_amen(struct file *fp, struct xseg *sp, int pageable) +{ +#ifdef XOUT_SEGMENTS + struct desc_struct def_ldt; + modify_ldt_t ldt_info; + mm_segment_t old_fs; + int l; +#endif + u_long bss_size, bss_base; + int err = 0; + +#ifdef XOUT_SEGMENTS + old_fs = get_fs(); + +seg_again: + l = 0; + + /* + * Xenix 386 segments simply map the whole address + * space either read-exec only or read-write. + */ + ldt_info.entry_number = sp->xs_seg >> 3; + ldt_info.read_exec_only = 0 /* ((s->xs_attr & XS_APURE) ? 1 : 0) */; + ldt_info.contents = ((sp->xs_type == XS_TTEXT) ? 2 : 0); + ldt_info.seg_not_present = 0; + ldt_info.seg_32bit = ((sp->xs_attr & XS_A32BIT) ? 1 : 0); + if (!ldt_info.seg_32bit) { + ldt_info.base_addr = *addrp; + *addrp = PAGE_ALIGN(*addrp + sp->xs_vsize); + sp->xs_rbase = ldt_info.base_addr; + } else + ldt_info.base_addr = 0; +#endif + + bss_size = sp->xs_vsize - sp->xs_psize; + bss_base = sp->xs_rbase + sp->xs_psize; + + /* + * If it is a text segment update the code boundary + * markers. If it is a data segment update the data + * boundary markers. + */ + if (sp->xs_type == XS_TTEXT) { + if ((sp->xs_rbase + sp->xs_psize) > current->mm->end_code) + current->mm->end_code = (sp->xs_rbase + sp->xs_psize); + } else if (sp->xs_type == XS_TDATA) { +#ifdef XOUT_SEGMENTS + /* + * If it is the first data segment note that + * this is the segment we start in. If this + * isn't a 386 binary add the stack to the + * top of this segment. + */ + if ((xexec->x_cpu & XC_CPU) != XC_386) { + if (regs->ebx == regs->ecx) { + regs->ecx = s->xs_seg; + regs->edx = s->xs_vsize; + sp->xs_vsize = 0x10000; + *addrp = PAGE_ALIGN(ldt_info.base_addr + s->xs_vsize); + } + } else { + if (regs->xds == regs->xcs) + regs->xds = regs->xes = regs->xss = s->xs_seg; + } +#endif + if ((sp->xs_rbase + sp->xs_psize) > current->mm->end_data) + current->mm->end_data = (sp->xs_rbase + sp->xs_psize); + } + + if ((sp->xs_rbase + sp->xs_vsize) > current->mm->brk) + current->mm->start_brk = + current->mm->brk = PAGE_ALIGN(sp->xs_rbase + sp->xs_vsize); +#ifdef XOUT_SEGMENTS + if (ldt_info.seg_32bit) { + ldt_info.limit = (TASK_SIZE-1) >> 12; + ldt_info.limit_in_pages = 1; + } else { + ldt_info.limit = s->xs_vsize-1; + ldt_info.limit_in_pages = 0; + } + + dprintk(KERN_DEBUG "xout: ldt %02x, type=%d, base=0x%08lx, " + "limit=0x%08x, pages=%d, 32bit=%d\n", + ldt_info.entry_number, ldt_info.contents, + ldt_info.base_addr, ldt_info.limit, + ldt_info.limit_in_pages, ldt_info.seg_32bit); + + /* + * Use the modify_ldt syscall since this allocates + * the initial space for the LDT table, tweaks the + * GDT etc. We need to read the current LDT first + * since we need to copy the lcall7 call gate. + */ + set_fs(get_ds()); + if (!current->mm->segments) { + SYS(modify_ldt)(0, &def_ldt, sizeof(def_ldt)); + l = 1; + } + + status = SYS(modify_ldt)(1, &ldt_info, sizeof(ldt_info)); +#if 0 + if (status >= 0 && !ntext && s->xs_seg == 0x47) { + /* Uh oh, impure binary... */ + ldt_info.entry_number = 0x3f >> 3; +#if 0 + ldt_info.read_exec_only = 1; +#else + ldt_info.read_exec_only = 0; +#endif + ldt_info.contents = 2; + status = SYS(modify_ldt)(1, &ldt_info, sizeof(ldt_info)); + } +#endif + set_fs(old_fs); + if (l == 1) { + l = 0; + ((struct desc_struct *)(current->mm->segments))[0].a = def_ldt.a; + ((struct desc_struct *)(current->mm->segments))[0].b = def_ldt.b; + } + if (status < 0) + printk(KERN_INFO "xout: modify_ldt returned %d\n", status); +#endif + + if (err < 0) + goto out; + + if (!pageable) { + dprintk(KERN_DEBUG "xout: Null map 0x%08lx, length 0x%08lx\n", + sp->xs_rbase, sp->xs_vsize); + err = do_mmap(NULL, sp->xs_rbase, sp->xs_vsize, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + goto out; + } + + dprintk(KERN_DEBUG "xout: mmap to 0x%08lx from 0x%08lx, length 0x%08lx\n", + sp->xs_rbase, sp->xs_filpos, sp->xs_psize); + if (sp->xs_attr & XS_APURE) { + err = do_mmap(fp, sp->xs_rbase, sp->xs_psize, + PROT_READ|PROT_EXEC, MAP_FIXED|MAP_SHARED, + sp->xs_filpos); + } else { + err = do_mmap(fp, sp->xs_rbase, sp->xs_psize, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, + sp->xs_filpos); + } + + if (err < 0) + goto out; + + /* + * Map uninitialised data. + */ + if (bss_size) { + if (bss_base & PAGE_MASK) { + clear_memory(bss_base, PAGE_ALIGN(bss_base)-bss_base); + bss_size -= (PAGE_ALIGN(bss_base) - bss_base); + bss_base = PAGE_ALIGN(bss_base); + } + + dprintk(KERN_DEBUG "xout: Null map 0x%08lx, length 0x%08lx\n", + bss_base, bss_size); + + err = do_mmap(NULL, bss_base, bss_size, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, 0); + } + +out: +#ifdef XOUT_SEGMENTS + if (err >= 0 && !ntext && ndata == 1 && sp->xs_seg >= 0x47) { + /* + * Uh oh, impure binary. + * Mirror this data segment to the text segment + */ + addrp = mirror_addr = sp->xs_rbase; + sp->xs_seg = xext->xe_eseg; + sp->xs_type = XS_TTEXT; + goto seg_again; + } +#endif + return (err); +} + +/* + * Helper function to process the load operation. + */ +static int +xout_load_object(struct linux_binprm * bpp, struct pt_regs *rp, int executable) +{ + struct xexec *xexec = (struct xexec *)bpp->buf; + struct xext *xext = (struct xext *)(xexec + 1); + struct xseg *seglist; + struct file *fp = NULL; + u_long addr, mirror_addr; + int nsegs, ntext, ndata; + int pageable = 1, err = 0; + int i; + + dprintk(KERN_DEBUG "xout: binfmt_xout entry: %s\n", + bpp->file->f_dentry->d_name.name); + + if (xexec->x_magic != X_MAGIC) { + dprintk(KERN_DEBUG "xout: bad magic %04x\n", xexec->x_magic); + return -ENOEXEC; + } + + switch (xexec->x_cpu & XC_CPU) { + case XC_386: + break; +#ifdef EMU_X286 + case XC_8086: + case XC_286: + case XC_286V: + case XC_186: + break; +#endif + default: + dprintk(KERN_DEBUG "xout: unsupported CPU type (%02x)\n", + xexec->x_cpu); + return -ENOEXEC; + } + + /* + * We can't handle byte or word swapped headers. Well, we + * *could* but they should never happen surely? + */ + if ((xexec->x_cpu & (XC_BSWAP | XC_WSWAP)) != XC_WSWAP) { + dprintk(KERN_DEBUG "xout: wrong byte or word sex (%02x)\n", + xexec->x_cpu); + return -ENOEXEC; + } + + /* Check it's an executable. */ + if (!(xexec->x_renv & XE_EXEC)) { + dprintk(KERN_DEBUG "xout: not executable\n"); + return -ENOEXEC; + } + + /* + * There should be an extended header and there should be + * some segments. At this stage we don't handle non-segmented + * binaries. I'm not sure you can get them under Xenix anyway. + */ + if (xexec->x_ext != sizeof(struct xext)) { + dprintk(KERN_DEBUG "xout: bad extended header\n"); + return -ENOEXEC; + } + + if (!(xexec->x_renv & XE_SEG) || !xext->xe_segsize) { + dprintk(KERN_DEBUG "xout: not segmented\n"); + return -ENOEXEC; + } + + if (!(seglist = kmalloc(xext->xe_segsize, GFP_KERNEL))) { + printk(KERN_WARNING "xout: allocating segment list failed\n"); + return -ENOMEM; + } + + err = kernel_read(bpp->file, xext->xe_segpos, + (char *)seglist, xext->xe_segsize); + if (err < 0) { + dprintk(KERN_DEBUG "xout: problem reading segment table\n"); + goto out; + } + + if (!bpp->file->f_op->mmap) + pageable = 0; + + nsegs = xext->xe_segsize / sizeof(struct xseg); + + ntext = ndata = 0; + for (i=0; imm->mmap = NULL; + current->mm->rss = 0; + + if ((err = setup_arg_pages(bpp)) < 0) { + send_sig(SIGSEGV, current, 1); + return (err); + } + +#ifdef EMU_X286 + bpp->p = (u_long)xout_create_tables((char *)bpp->p, bpp, + (xexec->x_cpu & XC_CPU) == XC_386 ? 1 : 0); +#else + bpp->p = (u_long)xout_create_tables((char *)bpp->p, bpp, 1); +#endif + + /* + * Do the end processing once the stack has been constructed + */ +#ifdef XOUT_SEGMENTS + /* + * These will be set up later once we've seen the + * segments that make the program up. + */ + current->mm->start_code = + current->mm->end_code = + current->mm->end_data = + current->mm->start_brk = + current->mm->brk = 0; +#else + current->mm->start_code = 0; + current->mm->end_code = xexec->x_text; + current->mm->end_data = xexec->x_text + xexec->x_data; + current->mm->start_brk = + current->mm->brk = xexec->x_text + xexec->x_data + xexec->x_bss; +#endif + compute_creds(bpp); + current->flags &= ~PF_FORKNOEXEC; + +#ifdef XOUT_SEGMENTS + /* + * The code selector is advertised in the header. + */ + if ((xexec->x_cpu & XC_CPU) != XC_386) { + regs->ebx = regs->ecx = xext->xe_eseg; + regs->eax = xexec->x_entry; + } else { + regs->xcs = regs->xds = regs->xes = regs->xss = xext->xe_eseg; + regs->eip = xexec->x_entry; + } +#else + rp->xcs = __USER_CS; + rp->xds = rp->xes = rp->xss = __USER_DS; + rp->eip = xexec->x_entry; +#endif + + dprintk(KERN_DEBUG "xout: entry point = 0x%x:0x%08lx\n", + xext->xe_eseg, xexec->x_entry); + + rp->esp = current->mm->start_stack = bpp->p; + + set_personality(PER_XENIX); + } + + /* Base address for mapping 16bit segments. This should lie above + * the emulator overlay. + */ + addr = X286_MAP_ADDR; + +#ifdef EMU_X286 + /* If this isn't a 386 executable we need to load the overlay + * library to emulate a [2]86 environment and save the binary + * headers for later reference by the emulator. + */ + if ((xexec->x_cpu & XC_CPU) != XC_386) { + mm_segment_t old_fs = get_fs(); + + set_fs (get_ds ()); + status = SYS(uselib)("/usr/lib/x286emul"); + set_fs (old_fs); + + status = do_mmap(NULL, + addr, sizeof(struct xexec)+sizeof(struct xext), + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, + 0); + if (status >= 0) { + copy_to_user((char *)addr, xexec, sizeof(struct xexec)); + copy_to_user((char *)addr+sizeof(struct xexec), xext, sizeof(struct xext)); + addr = PAGE_ALIGN(addr+sizeof(struct xexec)+sizeof(struct xext)); + } + } +#endif + + /* + * Scan the segments and map them into the process space. If this + * executable is pageable (unlikely since Xenix aligns to 1k + * boundaries and we want it aligned to 4k boundaries) this is + * all we need to do. If it isn't pageable we go round again + * afterwards and load the data. We have to do this in two steps + * because if segments overlap within a 4K page we'll lose the + * first instance when we remap the page. Hope that's clear... + * + * N.B. If you compile with XOUT_FORCE_PAGE defined (the default) + * then if all segments are aligned on 1k bounaries within the + * file and 4k boundaries within the address space we assume + * that no overlaps occur within the same VM page and the + * executable can thus be mmapped if the filesystem allows it. + * I believe this is the case for all 386 small model binaries + * - which is all we support anyway. + */ + mirror_addr = 0; + + for (i = 0; err >= 0 && i < nsegs; i++) { + struct xseg *sp = seglist+i; + + if (sp->xs_attr & XS_AMEM) + err = xout_amen(fp, sp, pageable); + + } + +#if 0 + if (addr > current->mm->brk) + current->mm->start_brk = current->mm->brk = addr; +#endif + + dprintk(KERN_DEBUG "xout: start code 0x%08lx, end code 0x%08lx," + " end data 0x%08lx, brk 0x%08lx\n", + current->mm->start_code, current->mm->end_code, + current->mm->end_data, current->mm->brk); +#ifdef XOUT_SEGMENTS + print_desc(1); + print_desc(0); +#endif + + if (pageable) + goto trap; + if (err < 0) + goto trap; + + for (i = 0; (err >= 0) && (i < nsegs); i++) { + struct xseg *sp = seglist + i; + u_long psize; + + if (sp->xs_type == XS_TTEXT || sp->xs_type == XS_TDATA) { + dprintk(KERN_DEBUG "xout: read to 0x%08lx from 0x%08lx," + " length 0x%08lx\n", sp->xs_rbase, + sp->xs_filpos, sp->xs_psize); + + if (sp->xs_psize < 0) + continue; + + psize = kernel_read(bpp->file, sp->xs_filpos, + (char *)sp->xs_rbase, sp->xs_psize); + + if (psize != sp->xs_psize) { + dprintk(KERN_DEBUG "xout: short read\n"); + err = -1; + break; + } + } + } + + /* + * Generate any needed trap for this process. If an error occured then + * generate a segmentation violation. If the process is being debugged + * then generate the load trap. (Note: If this is a library load then + * do not generate the trap here. Pass the error to the caller who + * will do it for the process in the outer lay of this procedure call.) + */ +trap: + if (executable) { + if (err < 0) { + dprintk(KERN_DEBUG "xout: loader forces seg fault " + "(err = %d)\n", err); + send_sig(SIGSEGV, current, 0); + } else if (current->ptrace & PT_PTRACED) + send_sig(SIGTRAP, current, 0); + err = 0; + } + +out: + kfree(seglist); + + dprintk(KERN_DEBUG "xout: binfmt_xout: result = %d\n", err); + + /* + * If we are using the [2]86 emulation overlay we enter this + * rather than the real program and give it the information + * it needs to start the ball rolling. + */ + if ((xexec->x_cpu & XC_CPU) != XC_386) { +#if 0 + regs->eax = regs->eip; + regs->ebx = regs->xcs; + regs->ecx = regs->xds; + regs->xcs = __USER_CS; + regs->xds = regs->xes = regs->xss = __USER_DS; +#endif + rp->eip = 0x1020; + dprintk(KERN_DEBUG "xout: x286emul 0x%02lx:0x%04lx," + " ds=0x%02lx, stack 0x%02lx:0x%04lx\n", + rp->ebx, rp->eax, rp->ecx, rp->ecx, + rp->edx); +#ifdef notdef + while (!signal_pending(current)) + schedule(); +#endif + return (err < 0 ? err : rp->eax); + } + +#ifdef notdef + while (!signal_pending(current)) + schedule(); +#endif + /* + * Xenix 386 programs expect the initial brk value to be in eax + * on start up. Hence if we succeeded we need to pass back + * the brk value rather than the status. Ultimately the + * ret_from_sys_call assembly will place this in eax before + * resuming (starting) the process. + */ + return (err < 0 ? err : current->mm->brk); +} + + +/* + * This procedure is called by the main load sequence. It will load + * the executable and prepare it for execution. It provides the additional + * parameters used by the recursive xout loader and tells the loader that + * this is the main executable. How simple it is . . . . + */ +static int +xout_load_binary(struct linux_binprm *bpp, struct pt_regs *rp) +{ + return (xout_load_object(bpp, rp, 1)); +} + +/* + * Load the image for any shared library. This is called when + * we need to load a library based upon a file name. + * + * XXX: I have never seen a Xenix shared library... --hch + */ +static int +xout_load_library(struct file *fp) +{ + struct linux_binprm *bpp; + struct pt_regs regs; + int err = -ENOMEM; + + if (!(bpp = kmalloc(sizeof(struct linux_binprm), GFP_KERNEL))) { + printk(KERN_WARNING "xout: kmalloc failed\n"); + goto out; + } + + memset(bpp, 0, sizeof(struct linux_binprm)); + bpp->file = fp; + + if ((err = kernel_read(fp, 0L, bpp->buf, sizeof(bpp->buf))) < 0) + printk(KERN_WARNING "xout: unable to read library header\n"); + else + err = xout_load_object(bpp, ®s, 0); + + kfree(bpp); +out: + return (err); +} + +static int __init +binfmt_xout_init(void) +{ + return register_binfmt(&xout_format); +} + +static void __exit +binfmt_xout_exit(void) +{ + unregister_binfmt(&xout_format); +} + +module_init(binfmt_xout_init); +module_exit(binfmt_xout_exit); diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/abi.h linux/include/abi/abi.h --- linux-2.4.3/include/abi/abi.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/abi.h Fri Mar 30 15:23:49 2001 @@ -0,0 +1,295 @@ + /* + * Function prototypes used by the iBCS2 emulator + * + * $Id$ + * $Source$ + */ + +#ifndef __IBCS_IBCS_H__ +#define __IBCS_IBCS_H__ +#include /* for pt_regs */ +#include +#include +#include +#include + +#include +#include +#include + +/* This is straight from linux/fs/stat.c. It is required for + * proper NFS attribute caching (so it says there). Maybe the + * kernel should export it - but it is basically simple... + */ +static __inline__ int +do_revalidate(struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + if (inode->i_op && inode->i_op->revalidate) + return inode->i_op->revalidate(dentry); + return 0; +} + + +static inline unsigned short map_flags(unsigned short f, unsigned short map[]) +{ + int i; + unsigned short m, r; + + r = 0; + for (i=0,m=1; i < 16; i++,m<<=1) + if (f & m) + r |= map[i]; + + return r; +} + + +/* XXX anyone has an idea how to make gcc shut up about this? */ +typedef int (*sysfun_p)(); + +extern sysfun_p sys_call_table[]; + +#define SYS(name) (sys_call_table[__NR_##name]) + + +/* + * the function prefix sys_... are used by linux in native mode. + * abi_, svr4_, sol_, uw7_ and ibcs_... are emulation interfaces for routines that + * differ from iBCS2 and linux. The xnx_... are xenix routines. + */ +typedef struct abi_function { + void * kfunc; /* function to call (sys_..., ibcs_... or xnx_...) + * or pointer to a sub class. + */ + short nargs; /* number of args to kfunc or Ukn, Spl or Fast */ + short trace; /* trace function we can turn tracing on or off */ + char * name; /* name of function (for tracing) */ + char * args; /* how to print the arg list (see plist) */ +} ABI_func; + +struct ibcs_statfs { + short f_type; + long f_bsize; + long f_frsize; + long f_blocks; + long f_bfree; + long f_files; + long f_ffree; + char f_fname[6]; + char f_fpack[6]; +}; + + +#ifdef __sparc__ + +typedef struct { + long tv_sec; + long tv_nsec; +} timestruct_t; + +struct ibcs_stat { + unsigned long st_dev; + long st_pad1[3]; /* network id */ + unsigned long st_ino; + unsigned long st_mode; + unsigned long st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned long st_rdev; + long st_pad2[2]; + long st_size; + long st_pad3; /* st_size, off_t expansion */ + timestruct_t st_atime; + timestruct_t st_mtime; + timestruct_t st_ctime; + long st_blksize; + long st_blocks; + char st_fstype[16]; + long st_pad4[8]; /* expansion area */ +}; +#else +struct ibcs_stat { + unsigned short st_dev; + unsigned short st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned long st_size; + unsigned long st_atime; + unsigned long st_mtime; + unsigned long st_ctime; +}; +#endif + + +struct ibcs_iovec { + unsigned long addr; + int len; +}; + +/* coff.c */ +extern int abi_brk(unsigned long newbrk); +extern int abi_lseek(int fd, unsigned long offset, int whence); +extern int abi_fork(struct pt_regs * regs); +extern int abi_pipe(struct pt_regs * regs); +extern int abi_getpid(struct pt_regs * regs); +extern int abi_getuid(struct pt_regs * regs); +extern int abi_getgid(struct pt_regs * regs); +extern int abi_wait(struct pt_regs * regs); +extern int ibcs_execv(struct pt_regs * regs); +extern int abi_exec(struct pt_regs * regs); +extern int abi_read(int fd, char *buf, int nbytes); +extern int abi_procids(struct pt_regs * regs); +extern int abi_select(int n, void *rfds, void *wfds, void *efds, + struct timeval *t); +extern int abi_time(void); +extern int ibcs_writev(int fd, struct ibcs_iovec *it, int n); + +extern int abi_syscall(struct pt_regs *regs); + +/* open.c */ +extern int abi_mkdir(const char *fname, int mode); +extern int abi_mknod(const char *fname, int mode, int dev); + +/* secureware.c */ +extern int sw_security(int cmd, void *p1, void *p2, void *p3, void *p4, void *p5); + +/* signal.c */ +/* For mapping signal numbers */ +void deactivate_signal(struct task_struct *task, int signum); +extern int abi_sigfunc(struct pt_regs * regs); +extern int abi_kill(int pid, int sig); + +/* stat.c */ +extern int abi_stat(char * filename, struct ibcs_stat * statbuf); +extern int abi_lstat(char * filename, struct ibcs_stat * statbuf); +extern int abi_fstat(unsigned int fd, struct ibcs_stat * statbuf); + +/* svr4.c */ +struct svr4_siginfo { + int si_signo; + int si_code; + int si_errno; + union { + struct { /* kill(), SIGCLD */ + long _pid; + union { + struct { + long _uid; + } _kill; + struct { + long _utime; + int _status; + long _stime; + } _cld; + } _pdata; + } _proc; + struct { /* SIGSEGV, SIGBUS, SIGILL, SIGFPE */ + char *_addr; + } _fault; + struct { /* SIGPOLL, SIGXFSZ */ + int _fd; + long _band; + } _file; + } _data; +}; +#define SVR4_CLD_EXITED 1 +#define SVR4_CLD_KILLED 2 +#define SVR4_CLD_DUMPED 3 +#define SVR4_CLD_TRAPPED 4 +#define SVR4_CLD_STOPPED 5 +#define SVR4_CLD_CONTINUED 6 +extern int svr4_getgroups(int n, unsigned long *buf); +extern int svr4_setgroups(int n, unsigned long *buf); +extern int svr4_waitid(int idtype, int id, struct svr4_siginfo *infop, int options); +extern int svr4_access(char *path, int mode); + +/* sysconf.c */ +extern int ibcs_sysconf(int name); + +/* utsname.c */ +extern int abi_utsname(unsigned long addr); +extern int sco_utsname(unsigned long addr); +extern int v7_utsname(unsigned long addr); + +/* socket.c */ +extern int abi_do_setsockopt(unsigned long *sp); +extern int abi_do_getsockopt(unsigned long *sp); + +/* wysev386.c */ +extern int abi_gethostname(char *name, int len); +extern int abi_getdomainname(char *name, int len); +extern int abi_wait3(int *loc); +extern int abi_socket(struct pt_regs *regs); +extern int abi_connect(struct pt_regs *regs); +extern int abi_accept(struct pt_regs *regs); +extern int abi_send(struct pt_regs *regs); +extern int abi_recv(struct pt_regs *regs); +extern int abi_bind(struct pt_regs *regs); +extern int abi_setsockopt(struct pt_regs *regs); +extern int abi_listen(struct pt_regs *regs); +extern int abi_getsockopt(struct pt_regs *regs); +extern int abi_recvfrom(struct pt_regs *regs); +extern int abi_sendto(struct pt_regs *regs); +extern int abi_shutdown(struct pt_regs *regs); +extern int abi_socketpair(struct pt_regs *regs); +extern int abi_getpeername(struct pt_regs *regs); +extern int abi_getsockname(struct pt_regs *regs); + +/* ioctl.c */ +extern int bsd_ioctl_termios(int fd, unsigned int func, void *arg); + +/* signal.c */ +extern int abi_sigsuspend(struct pt_regs *regs); + +/* From wysev386i.c */ +extern int wv386_ioctl(int fd, unsigned int ioctl_num, void *arg); + +/* From socksys.c */ +extern int socksys_major; +extern void inherit_socksys_funcs(unsigned int fd, int state); +extern int abi_socksys_fd_init(int fd, int rw, const char *buf, int *count); +extern int socksys_syscall(int *sp); +extern int abi_ioctl_socksys(int fd, unsigned int cmd, void *arg); + + +/* From sysisc.c */ +extern int isc_setostype(int); + +/* From vtkd.c */ +extern int ibcs_ioctl_vtkd(int, int, void *); + + + +#define SC(name) (void *)__NR_##name +#define ITR(trace, name, args) ,trace,name,args + + +/* This table contains the appropriate kernel routines that can be run + * to perform the syscalls in question. If an entry is 'Ukn' we don't + * know how to handle it yet. (We also set trace on by default for these) + * Spl means that we need to do special processing for this syscall + * (see ibcs_wait or ibcs_getpid) + * Fast means that even the error return handling is done by the function call. + */ +#define ZERO 0x64 /* Um, magic zero for callmap. Don't ask :-). */ +#define Spl 0x65 /* pass the regs structure down */ +#define Ukn 0x66 /* no code to handle this case yet */ +#define Fast 0x67 /* magic on return, return regs structure already set up */ + +void abi_dispatch(struct pt_regs *regs, ABI_func *p, int offset); + + +/* Translate the errno numbers from linux to current personality. + * This should be removed and all other sources changed to call the + * map function above directly. + */ +static inline int iABI_errors(int lnx_errno) +{ + return map_value(current->exec_domain->err_map, lnx_errno, 1); +} + +#endif /* __IBCS_IBCS_H__ */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/abi4.h linux/include/abi/abi4.h --- linux-2.4.3/include/abi/abi4.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/abi4.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,147 @@ +/* + * These are defined to enable their inclsion in the branch table + * defined below. + * + * Hacked by Eric Youngdale for iBCS (1993, 1994). + * + * $Id$ + * $Source$ + */ + +#ifndef __ABI_ABI_H__ +#define __ABI_ABI_H__ +#include + +typedef unsigned long ABI_dev_t; +typedef unsigned long ABI_ino_t; +typedef unsigned long ABI_mode_t; +typedef unsigned long ABI_nlink_t; +typedef long ABI_uid_t; +typedef long ABI_off_t; +typedef struct timeval ABI_timestruc_t; + + +struct abi_sigaction { + int sa_flags; + __sighandler_t sa_handler; + unsigned long sa_mask; + int sa_resv[2]; /* Reserved for something or another */ +}; +#define ABI_SA_ONSTACK 1 +#define ABI_SA_RESETHAND 2 +#define ABI_SA_RESTART 4 +#define ABI_SA_SIGINFO 8 +#define ABI_SA_NODEFER 16 +#define ABI_SA_NOCLDWAIT 0x10000 +#define ABI_SA_NOCLDSTOP 0x20000 + + +struct sco_sigaction { + void (*sa_handler)(int); + unsigned long sa_mask; + int sa_flags; +}; +#define SCO_SA_NOCLDSTOP 0x001 +#define SCO_SA_COMPAT 0x080 /* 3.2.2 compatibilty. Like SA_SIGNAL? */ +#define SCO_SA_SIGNAL 0x100 + + +extern int abi_sigaction(int abi_signum, const struct abi_sigaction * action, + struct abi_sigaction * oldaction); +extern int sco_sigaction(int sco_signum, const struct sco_sigaction * action, + struct sco_sigaction * oldaction); +extern int abi_sigprocmask(int how, unsigned long *set, unsigned long *oset); +extern int abi_sigsuspend(struct pt_regs * regs); + + +/* + * This is the general form of the stat structure in an ABI compliant system. + */ + +struct svr4_xstat { + ABI_dev_t st_dev; + long st_pad1[3]; + ABI_ino_t st_ino; + ABI_mode_t st_mode; + ABI_nlink_t st_nlink; + ABI_uid_t st_uid; + ABI_uid_t st_gid; + ABI_dev_t st_rdev; + long st_pad2[2]; + ABI_off_t st_size; + long st_pad3; + ABI_timestruc_t st_atim; + ABI_timestruc_t st_mtim; + ABI_timestruc_t st_ctim; + long st_blksize; + long st_blocks; + char st_fstype[ 16 ] ; + long st_pad4[8]; +}; + +/* + * Structure used by statvfs syscall. + */ +struct abi_statvfs { + unsigned long f_bsize; /* blocksize */ + unsigned long f_frsize; /* fragment size. */ + unsigned long f_blocks; + unsigned long f_bfree; + unsigned long f_bavail; + unsigned long f_files; + unsigned long f_free; + unsigned long f_sid; + char f_basetype[16]; + unsigned long f_flag; + unsigned long f_namemax; + char f_fstr[32]; + unsigned long f_filler[16]; +}; + +struct sco_statvfs { + unsigned long f_bsize; /* blocksize */ + unsigned long f_frsize; /* fragment size. */ + unsigned long f_blocks; + unsigned long f_bfree; + unsigned long f_bavail; + unsigned long f_files; + unsigned long f_free; + unsigned long f_favail; + unsigned long f_sid; + char f_basetype[16]; + unsigned long f_flag; + unsigned long f_namemax; + char f_fstr[32]; + unsigned long f_filler[16]; +}; + +extern int svr4_xstat(int vers, char * path, void * buf); +extern int svr4_lxstat(int vers, char * path, void * buf); +extern int svr4_xmknod(int vers, const char * path, mode_t mode, dev_t dev); + +extern int abi_statvfs(char * path, void * buf); +extern int abi_fstatvfs(int fd, void * buf); + + + +int svr4_fpathconf(int fd, int name); +int svr4_pathconf(char *path, int name); +int svr4_sigpending (int which_routine, svr4_sigset_t *set); +int svr4_context (struct pt_regs *regs); +int svr4_ioctl(struct pt_regs *regs); + +/* POSIX.1 names */ +#define _PC_LINK_MAX 1 +#define _PC_MAX_CANON 2 +#define _PC_MAX_INPUT 3 +#define _PC_NAME_MAX 4 +#define _PC_PATH_MAX 5 +#define _PC_PIPE_BUF 6 +#define _PC_NO_TRUNC 7 +#define _PC_VDISABLE 8 +#define _PC_CHOWN_RESTRICTED 9 +/* POSIX.4 names */ +#define _PC_ASYNC_IO 10 +#define _PC_PRIO_IO 11 +#define _PC_SYNC_IO 12 +#endif diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/bsd.h linux/include/abi/bsd.h --- linux-2.4.3/include/abi/bsd.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/bsd.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,128 @@ +/* + * Function prototypes used by the BSD emulator + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * $Id$ + * $Source$ + */ + +/* Ioctl's have the command encoded in the lower word, and the size of + * any in or out parameters in the upper word. The high 3 bits of the + * upper word are used to encode the in/out status of the parameter. + * Note that Linux does the same but has the IOC_IN and IOC_OUT values + * round the other way and uses 0 for IOC_VOID. + */ +#define BSD_IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */ +#define BSD_IOC_VOID 0x20000000 /* no parameters */ +#define BSD_IOC_OUT 0x40000000 /* copy out parameters */ +#define BSD_IOC_IN 0x80000000 /* copy in parameters */ +#define BSD_IOC_INOUT (BSD_IOC_IN|BSD_IOC_OUT) + +#define BSD__IOC(inout,group,num,len) \ + (inout | ((len & BSD_IOCPARM_MASK) << 16) | ((group) << 8) | (num)) +#define BSD__IO(g,n) BSD__IOC(BSD_IOC_VOID, (g), (n), 0) +#define BSD__IOR(g,n,t) BSD__IOC(BSD_IOC_OUT, (g), (n), sizeof(t)) +#define BSD__IOW(g,n,t) BSD__IOC(BSD_IOC_IN, (g), (n), sizeof(t)) +#define BSD__IOWR(g,n,t) BSD__IOC(BSD_IOC_INOUT, (g), (n), sizeof(t)) + +/* Some SYSV systems exhibit "compatible" BSD ioctls without the bumf. */ +#define BSD__IOV(c,d) (((c) << 8) | (d)) + + + +#include + + +/* Some BSD values have been extended to 64 bit types... */ +typedef long long quad; + +/* From bsd.c */ +extern int bsd_getpagesize(void); +extern int bsd_geteuid(void); +extern int bsd_getegid(void); +extern int bsd_sbrk(unsigned long n); +extern int bsd_getdtablesize(void); +extern int bsd_killpg(int pgrp, int sig); +extern int bsd_setegid(int egid); +extern int bsd_seteuid(int euid); +extern int bsd_open(const char * fname, int flag, int mode); +extern int bsd_fcntl(struct pt_regs *regs); +extern int bsd_ioctl(struct pt_regs *regs); + +/* From bsdioctl.c */ +extern int bsd_ioctl_termios(int fd, unsigned int func, void *arg); + +/* From bsdsignal.c */ +#define BSD_SA_ONSTACK 0x0001 +#define BSD_SA_RESTART 0x0002 +#define BSD_SA_NOCLDSTOP 0x0004 +struct bsd_sigaction { + void (*sa_handler)(int); + unsigned int sa_mask; + int sa_flags; +}; +extern int bsd_sigaction(int bsd_signum, const struct bsd_sigaction *action, + struct bsd_sigaction *oldaction); +extern int bsd_sigprocmask(int how, unsigned long bsdnset, unsigned long *bsdoset); +extern int bsd_sigpending(unsigned long *set); + +/* From bsdsocket.c */ +extern int bsd_connect(struct pt_regs *regs); + +/* From bsdstat.c */ +struct bsd_stat { + unsigned short st_dev; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned long st_size; + unsigned long st_atime; + unsigned long st_spare1; + unsigned long st_mtime; + unsigned long st_spare2; + unsigned long st_ctime; + unsigned long st_spare3; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_flags; + unsigned long st_gen; +}; +extern int bsd_stat(char *filename, struct bsd_stat *st); +extern int bsd_lstat(char *filename, struct bsd_stat *st); +extern int bsd_fstat(unsigned int fd, struct bsd_stat *st); + + +#define MNAMELEN 90 /* length of buffer for returned name */ + +struct bsd_statfs { + short f_type; /* type */ + short f_flags; /* copy of mount flags */ + long f_fsize; /* fundamental file system block size */ + long f_bsize; /* optimal transfer block size */ + long f_blocks; /* total data blocks in file system */ + long f_bfree; /* free blocks in fs */ + long f_bavail; /* free blocks avail to non-superuser */ + long f_files; /* total file nodes in file system */ + long f_ffree; /* free file nodes in fs */ + quad f_fsid; /* file system id */ + long f_spare[9]; /* spare for later */ + char f_mntonname[MNAMELEN]; /* directory on which mounted */ + char f_mntfromname[MNAMELEN];/* mounted filesystem */ +}; +extern int bsd_statfs(const char *path, struct bsd_statfs *buf); +extern int bsd_fstatfs(unsigned int fd, struct bsd_statfs *buf); + + +#define MAXNAMELEN NAME_MAX + +struct bsd_dirent { + unsigned long d_fileno; + unsigned short d_reclen; + unsigned short d_namlen; + char d_name[MAXNAMELEN+1]; +}; +extern int bsd_getdirentries(int fd, char *buf, int nbytes, char *end_posn); diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/lfs.h linux/include/abi/lfs.h --- linux-2.4.3/include/abi/lfs.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/lfs.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,69 @@ +/* Large File Summit support functions */ + +#ifndef __IBCS_LFS_H__ + +#include +#include + +struct sol_stat64 { + unsigned long st_dev; + long st_pad1[3]; /* reserve for dev expansion */ + /* sysid definition */ + unsigned long long st_ino; + unsigned long st_mode; + unsigned long st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned long st_rdev; + long st_pad2[2]; + unsigned long long st_size; /* large file support */ + unsigned long st_atime; + unsigned long st_mtime; + unsigned long st_ctime; + long st_blksize; + long long st_blocks; /* large file support */ + char st_fstype[16]; + long st_pad4[8]; /* expansion area */ +}; + +struct sol_dirent64 { + unsigned long long d_ino; + unsigned long long d_off; + unsigned short d_reclen; + char d_name[1]; +}; + +int sol_stat64(char * filename, struct sol_stat64 * statbuf); +int sol_lstat64(char * filename, struct sol_stat64 * statbuf); +int sol_fstat64(unsigned int fd, struct sol_stat64 * statbuf); +int sol_open64(const char *fname, int flag, int mode); +int sol_getdents64(int fd, char *buf, int nbytes); +int sol_mmap64(unsigned vaddr, unsigned vsize, int prot, int flags, + int fd, unsigned int off_hi, unsigned file_offset); + +/* version 4 (UW7_STAT64_VERSION) stat structure */ +struct uw7_stat64 { + unsigned long st_dev; + long st_pad1[3]; + unsigned long long st_ino; + unsigned long st_mode; + unsigned long st_nlink; + long st_uid; + long st_gid; + unsigned long st_rdev; + long st_pad2[2]; + long long st_size; + struct timeval st_atime; + struct timeval st_mtime; + struct timeval st_ctime; + long st_blksize; + long long st_blocks; + char st_fstype[16]; + int st_aclcnt; + unsigned long st_level; + unsigned long st_flags; /* may contain MLD flag */ + unsigned long st_cmwlevel; + long st_pad4[4]; +}; + +#endif /* __IBCS_LFS_H__ */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/map.h linux/include/abi/map.h --- linux-2.4.3/include/abi/map.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/map.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,24 @@ +/* + * include/abi/map.h + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * $Id$ + * $Source$ + */ + +#ifndef __ABI_MAP_H__ +#define __ABI_MAP_H__ + +struct map_segment { + int start, end; + unsigned char *map; +}; + + +extern long map_bitvec(unsigned long vec, long map[]); +extern unsigned long map_sigvec_from_kernel(sigset_t vec, unsigned long map[]); +extern sigset_t map_sigvec_to_kernel(unsigned long vec, unsigned long map[]); +extern int map_value(struct map_segment *m, int val, int def); + +#endif diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/signal.h linux/include/abi/signal.h --- linux-2.4.3/include/abi/signal.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/signal.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,75 @@ +#define NSIGNALS 32 + + +/* These are the signal numbers for the SVr4 signal handling */ +#define IBCS_SIGHUP 1 +#define IBCS_SIGINT 2 +#define IBCS_SIGQUIT 3 +#define IBCS_SIGILL 4 +#define IBCS_SIGTRAP 5 +#define IBCS_SIGIOT 6 +#define IBCS_SIGABRT 6 +#define IBCS_SIGEMT 7 +#define IBCS_SIGFPE 8 +#define IBCS_SIGKILL 9 +#define IBCS_SIGBUS 10 +#define IBCS_SIGSEGV 11 +#define IBCS_SIGSYS 12 +#define IBCS_SIGPIPE 13 +#define IBCS_SIGALRM 14 +#define IBCS_SIGTERM 15 +#define IBCS_SIGUSR1 16 +#define IBCS_SIGUSR2 17 +#define IBCS_SIGCLD 18 +#define IBCS_SIGCHLD 18 +#define IBCS_SIGPWR 19 +#define IBCS_SIGWINCH 20 +#define IBCS_SIGURG 21 /* not SCO, SCO uses SIGUSR2 for SIGURG */ +#define IBCS_SIGPOLL 22 +#define IBCS_SIGIO 22 +#define IBCS_SIGSTOP 23 +#define IBCS_SIGTSTP 24 +#define IBCS_SIGCONT 25 +#define IBCS_SIGTTIN 26 +#define IBCS_SIGTTOU 27 +#define IBCS_SIGVTALRM 28 +#define IBCS_SIGPROF 29 +#define IBCS_SIGGXCPU 30 +#define IBCS_SIGGXFSZ 31 + +#define ISC_SIGSTOP 24 +#define ISC_SIGTSTP 25 +#define ISC_SIGCONT 23 + +/* These are the signal numbers used by BSD. */ +#define BSD_SIGHUP 1 +#define BSD_SIGINT 2 +#define BSD_SIGQUIT 3 +#define BSD_SIGILL 4 +#define BSD_SIGTRAP 5 +#define BSD_SIGABRT 6 +#define BSD_SIGEMT 7 +#define BSD_SIGFPE 8 +#define BSD_SIGKILL 9 +#define BSD_SIGBUS 10 +#define BSD_SIGSEGV 11 +#define BSD_SIGSYS 12 +#define BSD_SIGPIPE 13 +#define BSD_SIGALRM 14 +#define BSD_SIGTERM 15 +#define BSD_SIGURG 16 +#define BSD_SIGSTOP 17 +#define BSD_SIGTSTP 18 +#define BSD_SIGCONT 19 +#define BSD_SIGCHLD 20 +#define BSD_SIGTTIN 21 +#define BSD_SIGTTOU 22 +#define BSD_SIGIO 23 +#define BSD_SIGXCPU 24 +#define BSD_SIGXFSZ 25 +#define BSD_SIGVTALRM 26 +#define BSD_SIGPROF 27 +#define BSD_SIGWINCH 28 +#define BSD_SIGINFO 29 +#define BSD_SIGUSR1 30 +#define BSD_SIGUSR2 31 diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/socket.h linux/include/abi/socket.h --- linux-2.4.3/include/abi/socket.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/socket.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,19 @@ +/* + * include/abi/socket.h + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * $Id$ + * $Source$ + */ + +/* Linux spells this differently. */ +#define SO_ACCEPTCONN SO_ACCEPTCON + +/* These aren't (currently) defined by Linux. Watch out for warnings + * about redefinitions... + */ +#define SO_USELOOPBACK 0xff02 +#define SO_ORDREL 0xff03 +#define SO_IMASOCKET 0xff04 +#define SO_PROTOTYPE 0xff09 diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/socksys.h linux/include/abi/socksys.h --- linux-2.4.3/include/abi/socksys.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/socksys.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,277 @@ +/* + * include/abi/socksys.h + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * $Id$ + * $Source$ + */ + +/* Interface to /dev/socksys as used for streams based TCP/IP in SYSV */ + +/* Get struct rtentry from linux/route.h - this should be compatible. */ +#include + +/* Get struct arpreq from linux/if_arp.h - this should be compatible. */ +#include +#include + +/* Get struct ifreq and struct ifconf from linux/if.h - these should + * be compatible. + */ +#include + + +struct socksysreq { + int args[7]; +}; + + +struct socknewproto { + int family; /* address family (AF_INET, etc.) */ + int type; /* protocol type (SOCK_STREAM, etc.) */ + int proto; /* per family proto number */ + dev_t dev; /* major/minor to use (must be a clone) */ + int flags; /* protosw flags */ +}; + + +/* These are nothing to do with what we know as SO_*. I think they + * are the command requests which appear in socksysreq structures? + */ +#define SSYS_SO_ACCEPT 1 +#define SSYS_SO_BIND 2 +#define SSYS_SO_CONNECT 3 +#define SSYS_SO_GETPEERNAME 4 +#define SSYS_SO_GETSOCKNAME 5 +#define SSYS_SO_GETSOCKOPT 6 +#define SSYS_SO_LISTEN 7 +#define SSYS_SO_RECV 8 +#define SSYS_SO_RECVFROM 9 +#define SSYS_SO_SEND 10 +#define SSYS_SO_SENDTO 11 +#define SSYS_SO_SETSOCKOPT 12 +#define SSYS_SO_SHUTDOWN 13 +#define SSYS_SO_SOCKET 14 +#define SSYS_SO_SELECT 15 +#define SSYS_SO_GETIPDOMAIN 16 +#define SSYS_SO_SETIPDOMAIN 17 +#define SSYS_SO_ADJTIME 18 +#define SSYS_SO_SETREUID 19 +#define SSYS_SO_SETREGID 20 +#define SSYS_SO_GETTIME 21 +#define SSYS_SO_SETTIME 22 +#define SSYS_SO_GETITIMER 23 +#define SSYS_SO_SETITIMER 24 +#define SSYS_SO_RECVMSG 25 /* Here down is SCO 3.2v5 and up */ +#define SSYS_SO_SENDMSG 26 +#define SSYS_SO_SOCKPAIR 27 + + +/* We encode the ioctl numbers using the argument size as part of + * the number. This will warn us if we haven't got compatible + * structures :-). + * Naturally the SVR3/Lachman ioctl numbers are different from the + * BSD/SVR4-XTI ioctl numbers. What more would you expect? + */ + +#define SSYS_IOCPARM_MASK 0xff /* parameters must be < 256 bytes */ +#define SSYS_IOC_VOID 0x20000000 /* no parameters */ +#define SSYS_IOC_OUT 0x40000000 /* copy out parameters */ +#define SSYS_IOC_IN 0x80000000 /* copy in parameters */ +#define SSYS_IOC_INOUT (SSYS_IOC_IN|SSYS_IOC_OUT) + +#define SSYS_IOS(x,y) (SSYS_IOC_VOID|(x<<8)|y) +#define SSYS_IOSR(x,y,t) (SSYS_IOC_OUT|((sizeof(t)&SSYS_IOCPARM_MASK)<<16)|(x<<8)|y) +#define SSYS_IOSW(x,y,t) (SSYS_IOC_IN|((sizeof(t)&SSYS_IOCPARM_MASK)<<16)|(x<<8)|y) +#define SSYS_IOSWR(x,y,t) (SSYS_IOC_INOUT|((sizeof(t)&SSYS_IOCPARM_MASK)<<16)|(x<<8)|y) + +#define SSYS_SIOCSHIWAT SSYS_IOSW('S', 1, int) /* set high watermark */ +#define SSYS_SIOCGHIWAT SSYS_IOSR('S', 2, int) /* get high watermark */ +#define SSYS_SIOCSLOWAT SSYS_IOSW('S', 3, int) /* set low watermark */ +#define SSYS_SIOCGLOWAT SSYS_IOSR('S', 4, int) /* get low watermark */ +#define SSYS_SIOCATMARK SSYS_IOSR('S', 5, int) /* at oob mark? */ +#define SSYS_SIOCSPGRP SSYS_IOSW('S', 6, int) /* set process group */ +#define SSYS_SIOCGPGRP SSYS_IOSR('S', 7, int) /* get process group */ + + +#define SSYS_FIONREAD SSYS_IOSR('S', 8, int) /* BSD compatibilty */ +#define SSYS_FIONBIO SSYS_IOSW('S', 9, int) /* BSD compatibilty */ +#define SSYS_FIOASYNC SSYS_IOSW('S', 10, int) /* BSD compatibilty */ +#define SSYS_SIOCPROTO SSYS_IOSW('S', 11, struct socknewproto) /* link proto */ +#define SSYS_SIOCGETNAME SSYS_IOSR('S', 12, struct sockaddr) /* getsockname */ +#define SSYS_SIOCGETPEER SSYS_IOSR('S', 13, struct sockaddr) /* getpeername */ +#define SSYS_IF_UNITSEL SSYS_IOSW('S', 14, int) /* set unit number */ +#define SSYS_SIOCXPROTO SSYS_IOS('S', 15) /* empty proto table */ + +#define SSYS_SIOCADDRT SSYS_IOSW('R', 9, struct rtentry) /* add route */ +#define SSYS_SIOCDELRT SSYS_IOSW('R', 10, struct rtentry) /* delete route */ + +#define SSYS_SIOCSIFADDR SSYS_IOSW('I', 11, struct ifreq) /* set ifnet address */ +#define SSYS_SIOCGIFADDR SSYS_IOSWR('I', 12, struct ifreq) /* get ifnet address */ +#define SSYS_SIOCSIFDSTADDR SSYS_IOSW('I', 13, struct ifreq) /* set p-p address */ +#define SSYS_SIOCGIFDSTADDR SSYS_IOSWR('I', 14, struct ifreq) /* get p-p address */ +#define SSYS_SIOCSIFFLAGS SSYS_IOSW('I', 15, struct ifreq) /* set ifnet flags */ +#define SSYS_SIOCGIFFLAGS SSYS_IOSWR('I', 16, struct ifreq) /* get ifnet flags */ +#define SSYS_SIOCGIFCONF SSYS_IOSWR('I', 17, struct ifconf) /* get ifnet list */ + +#define SSYS_SIOCSIFMTU SSYS_IOSW('I', 21, struct ifreq) /* get if_mtu */ +#define SSYS_SIOCGIFMTU SSYS_IOSWR('I', 22, struct ifreq) /* set if_mtu */ + +#define SSYS_SIOCIFDETACH SSYS_IOSW('I', 26, struct ifreq) /* detach interface */ +#define SSYS_SIOCGENPSTATS SSYS_IOSWR('I', 27, struct ifreq) /* get ENP stats */ + +#define SSYS_SIOCX25XMT SSYS_IOSWR('I', 29, struct ifreq) /* start a slp proc in + * x25if */ +#define SSYS_SIOCX25RCV SSYS_IOSWR('I', 30, struct ifreq) /* start a slp proc in + * x25if */ +#define SSYS_SIOCX25TBL SSYS_IOSWR('I', 31, struct ifreq) /* xfer lun table to + * kernel */ + +#define SSYS_SIOCGIFBRDADDR SSYS_IOSWR('I', 32, struct ifreq) /* get broadcast addr */ +#define SSYS_SIOCSIFBRDADDR SSYS_IOSW('I', 33, struct ifreq) /* set broadcast addr */ +#define SSYS_SIOCGIFNETMASK SSYS_IOSWR('I', 34, struct ifreq) /* get net addr mask */ +#define SSYS_SIOCSIFNETMASK SSYS_IOSW('I', 35, struct ifreq) /* set net addr mask */ +#define SSYS_SIOCGIFMETRIC SSYS_IOSWR('I', 36, struct ifreq) /* get IF metric */ +#define SSYS_SIOCSIFMETRIC SSYS_IOSW('I', 37, struct ifreq) /* set IF metric */ + +#define SSYS_SIOCSARP SSYS_IOSW('I', 38, struct arpreq) /* set arp entry */ +#define SSYS_SIOCGARP SSYS_IOSWR('I', 39, struct arpreq) /* get arp entry */ +#define SSYS_SIOCDARP SSYS_IOSW('I', 40, struct arpreq) /* delete arp entry */ + +#define SSYS_SIOCSIFNAME SSYS_IOSW('I', 41, struct ifreq) /* set interface name */ +#define SSYS_SIOCGIFONEP SSYS_IOSWR('I', 42, struct ifreq) /* get one-packet params */ +#define SSYS_SIOCSIFONEP SSYS_IOSW('I', 43, struct ifreq) /* set one-packet params */ + +#define SSYS_SIOCGENADDR SSYS_IOSWR('I', 65, struct ifreq) /* Get ethernet addr */ + +#define SSYS_SIOCSOCKSYS SSYS_IOSW('I', 66, struct socksysreq) /* Pseudo socket syscall */ + + +#define SVR4_SIOCSHIWAT SSYS_IOSW('s', 0, int) /* set high watermark */ +#define SVR4_SIOCGHIWAT SSYS_IOSR('s', 1, int) /* get high watermark */ +#define SVR4_SIOCSLOWAT SSYS_IOSW('s', 2, int) /* set low watermark */ +#define SVR4_SIOCGLOWAT SSYS_IOSR('s', 3, int) /* get low watermark */ +#define SVR4_SIOCATMARK SSYS_IOSR('s', 7, int) /* at oob mark? */ +#define SVR4_SIOCSPGRP SSYS_IOSW('s', 8, int) /* set process group */ +#define SVR4_SIOCGPGRP SSYS_IOSR('s', 9, int) /* get process group */ + +#define SVR4_SIOCADDRT SSYS_IOSW('r', 10, struct rtentry) /* add route */ +#define SVR4_SIOCDELRT SSYS_IOSW('r', 11, struct rtentry) /* delete route */ + +#define SVR4_SIOCSIFADDR SSYS_IOSW('i', 12, struct ifreq) /* set ifnet address */ +#define SVR4_SIOCGIFADDR SSYS_IOSWR('i',13, struct ifreq) /* get ifnet address */ +#define SVR4_SIOCSIFDSTADDR SSYS_IOSW('i', 14, struct ifreq) /* set p-p address */ +#define SVR4_SIOCGIFDSTADDR SSYS_IOSWR('i',15, struct ifreq) /* get p-p address */ +#define SVR4_SIOCSIFFLAGS SSYS_IOSW('i', 16, struct ifreq) /* set ifnet flags */ +#define SVR4_SIOCGIFFLAGS SSYS_IOSWR('i',17, struct ifreq) /* get ifnet flags */ +#define SVR4_SIOCSIFMEM SSYS_IOSW('i', 18, struct ifreq) /* set interface mem */ +#define SVR4_SIOCGIFMEM SSYS_IOSWR('i',19, struct ifreq) /* get interface mem */ +#define SVR4_SIOCGIFCONF SSYS_IOSWR('i',20, struct ifconf) /* get ifnet list */ +#define SVR4_SIOCSIFMTU SSYS_IOSW('i', 21, struct ifreq) /* set if_mtu */ +#define SVR4_SIOCGIFMTU SSYS_IOSWR('i',22, struct ifreq) /* get if_mtu */ + + /* from 4.3BSD */ +#define SVR4_SIOCGIFBRDADDR SSYS_IOSWR('i',23, struct ifreq) /* get broadcast addr */ +#define SVR4_SIOCSIFBRDADDR SSYS_IOSW('i',24, struct ifreq) /* set broadcast addr */ +#define SVR4_SIOCGIFNETMASK SSYS_IOSWR('i',25, struct ifreq) /* get net addr mask */ +#define SVR4_SIOCSIFNETMASK SSYS_IOSW('i',26, struct ifreq) /* set net addr mask */ +#define SVR4_SIOCGIFMETRIC SSYS_IOSWR('i',27, struct ifreq) /* get IF metric */ +#define SVR4_SIOCSIFMETRIC SSYS_IOSW('i',28, struct ifreq) /* set IF metric */ + +#define SVR4_SIOCSARP SSYS_IOSW('i', 30, struct arpreq) /* set arp entry */ +#define SVR4_SIOCGARP SSYS_IOSWR('i',31, struct arpreq) /* get arp entry */ +#define SVR4_SIOCDARP SSYS_IOSW('i', 32, struct arpreq) /* delete arp entry */ +#define SVR4_SIOCUPPER SSYS_IOSW('i', 40, struct ifreq) /* attach upper layer */ +#define SVR4_SIOCLOWER SSYS_IOSW('i', 41, struct ifreq) /* attach lower layer */ +#define SVR4_SIOCSETSYNC SSYS_IOSW('i', 44, struct ifreq) /* set syncmode */ +#define SVR4_SIOCGETSYNC SSYS_IOSWR('i', 45, struct ifreq) /* get syncmode */ +#define SVR4_SIOCSSDSTATS SSYS_IOSWR('i', 46, struct ifreq) /* sync data stats */ +#define SVR4_SIOCSSESTATS SSYS_IOSWR('i', 47, struct ifreq) /* sync error stats */ + +#define SVR4_SIOCSPROMISC SSYS_IOSW('i', 48, int) /* request promisc mode + on/off */ +#define SVR4_SIOCADDMULTI SSYS_IOSW('i', 49, struct ifreq) /* set m/c address */ +#define SVR4_SIOCDELMULTI SSYS_IOSW('i', 50, struct ifreq) /* clr m/c address */ + +/* protocol i/o controls */ +#define SVR4_SIOCSNIT SSYS_IOSW('p', 0, struct nit_ioc) /* set nit modes */ +#define SVR4_SIOCGNIT SSYS_IOSWR('p', 1, struct nit_ioc) /* get nit modes */ + +/* STREAMS based socket emulation */ + +#define SVR4_SIOCPROTO SSYS_IOSW('s', 51, struct socknewproto) /* link proto */ +#define SVR4_SIOCGETNAME SSYS_IOSR('s', 52, struct sockaddr) /* getsockname */ +#define SVR4_SIOCGETPEER SSYS_IOSR('s', 53, struct sockaddr) /* getpeername */ +#define SVR4_IF_UNITSEL SSYS_IOSW('s', 54, int) /* set unit number */ +#define SVR4_SIOCXPROTO SSYS_IOS('s', 55) /* empty proto table */ + +#define SVR4_SIOCIFDETACH SSYS_IOSW('i', 56, struct ifreq) /* detach interface */ +#define SVR4_SIOCGENPSTATS SSYS_IOSWR('i', 57, struct ifreq) /* get ENP stats */ +#define SVR4_SIOCX25XMT SSYS_IOSWR('i', 59, struct ifreq) /* start a slp proc in + * x25if */ +#define SVR4_SIOCX25RCV SSYS_IOSWR('i', 60, struct ifreq) /* start a slp proc in + * x25if */ +#define SVR4_SIOCX25TBL SSYS_IOSWR('i', 61, struct ifreq) /* xfer lun table to + * kernel */ +#define SVR4_SIOCSLGETREQ SSYS_IOSWR('i', 71, struct ifreq) /* wait for switched + * SLIP request */ +#define SVR4_SIOCSLSTAT SSYS_IOSW('i', 72, struct ifreq) /* pass SLIP info to + * kernel */ +#define SVR4_SIOCSIFNAME SSYS_IOSW('i', 73, struct ifreq) /* set interface name */ +#define SVR4_SIOCGENADDR SSYS_IOSWR('i', 85, struct ifreq) /* Get ethernet addr */ +#define SVR4_SIOCSOCKSYS SSYS_IOSW('i', 86, struct socksysreq) /* Pseudo socket syscall */ + + +#if 0 +/* Strange, there also seem to be two byte SVR4 ioctls used which are + * not simply the BSD style ioctl with the high word masked out. i.e the + * class character doesn't match what I expect. + */ +#define SVRX_SIOCGIFCONF 0x8912 +#define SVRX_SIOCGIFFLAGS 0x8913 +#endif + + +/* With NFS/NIS there is also a pseudo device /dev/nfsd which understands + * some ioctls. Since these don't conflict with the socksys ioctls we + * just link nfsd to socksys and let socksys handle both sets. + */ +#define NIOCNFSD 1 +#define NIOCOLDGETFH 2 +#define NIOCASYNCD 3 +#define NIOCSETDOMNAM 4 +#define NIOCGETDOMNAM 5 +#define NIOCCLNTHAND 6 +#define NIOCEXPORTFS 7 +#define NIOCGETFH 8 +#define NIOCLSTAT 9 + +/* These ioctls take argument structures... */ +struct domnam_args { + char *name; + int namelen; +}; + +struct lstat_args { + char *fname; + void *statb; +}; + +#define NFS_FHSIZE 32 +typedef union { + struct { + unsigned short fsid; /* filesystem id (device) */ + unsigned long fno; /* file number (inode) */ + unsigned long fgen; /* file generation */ + unsigned short ex_fsid; /* exported fs id (device) */ + unsigned long ex_fno; /* exported file no (inode) */ + unsigned long ex_fgen; /* exported file gen */ + } fh; + char pad[NFS_FHSIZE]; +} fhandle_t; + +struct getfh_args { + char *fname; + fhandle_t *fhp; +}; diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/solaris.h linux/include/abi/solaris.h --- linux-2.4.3/include/abi/solaris.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/solaris.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,21 @@ +#ifndef __IBCS_SOLX86_H__ +#define __IBCS_SOLX86_H__ + +#include + +typedef void svr4_ucontext_t; + +int sol_llseek(struct pt_regs * regs); +int ibcs_memcntl(unsigned addr, unsigned len, int cmd, unsigned arg, + int attr, int mask); + + + + +#define GETACL 1 +#define SETACL 2 +#define GETACLCNT 3 + +int sol_acl(char *pathp, int cmd, int nentries, void *aclbufp); + +#endif /* __ IBCS_SOLX86_H__ */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/stream.h linux/include/abi/stream.h --- linux-2.4.3/include/abi/stream.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/stream.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,46 @@ +/* + * include/abi/stream.h + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * $Id$ + * $Source$ + */ + +#ifndef _IBCS_STREAM_H_ +#define _IBCS_STREAM_H_ + +#define MSG_HIPRI 1 +#define RS_HIPRI MSG_HIPRI +#define MSG_ANY 2 +#define MSG_BAND 4 + +#define MORECTL 1 +#define MOREDATA 2 + +struct strbuf { + int maxlen; /* size of buffer */ + int len; /* number of bytes in buffer */ + char *buf; /* pointer to buffer */ +}; + +/* Used for the I_PEEK STREAMS ioctl. */ +struct strpeek { + struct strbuf ctl; + struct strbuf dat; + long flags; +}; + +/* Used for the I_FDINSERT STREAMS ioctl. */ +struct strfdinsert { + struct strbuf ctlbuf; + struct strbuf datbuf; + long flags; + unsigned int fildes; + int offset; +}; + +extern int stream_fdinsert(struct pt_regs *regs, int fd, + struct strfdinsert *arg); + +#endif diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/svr4.h linux/include/abi/svr4.h --- linux-2.4.3/include/abi/svr4.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/svr4.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,134 @@ +/* + * Function prototypes used for SVR4 emulation. + * + * $Id$ + * $Source$ + */ +#include /* for pt_regs */ +#include +#include +#include + +#define SVR_NCC 8 +struct svr_termio { + unsigned short c_iflag; + unsigned short c_oflag; + unsigned short c_cflag; + unsigned short c_lflag; + char c_line; + unsigned char c_cc[SVR_NCC]; +}; + +#define SVR4_NCCS (19) +struct svr4_termios { + unsigned long c_iflag; + unsigned long c_oflag; + unsigned long c_cflag; + unsigned long c_lflag; + unsigned char c_cc[SVR4_NCCS]; +}; + +/* timod.c */ +extern int svr4_ioctl_sockmod(int fd, unsigned int func, void *arg); + +/* svr4.c */ +extern int svr4_getgroups(int n, unsigned long * buf); +extern int svr4_setgroups(int n, unsigned long * buf); +extern int svr4_waitsys(struct pt_regs * regs); +extern int svr4_seteuid(int uid); +extern int svr4_setegid(int gid); + +/* open.c */ +extern int svr4_open(const char * fname, int flag, int mode); +extern int svr4_statfs(const char * path, struct ibcs_statfs * buf, int len, int fstype); +extern int svr4_fstatfs(unsigned int fd, struct ibcs_statfs * buf, int len, int fstype); +extern int svr4_getdents(int fd, char * buf, int nybtes); + +/* ipc.c */ +extern int svr4_semsys(struct pt_regs * regs); +extern int svr4_shmsys(struct pt_regs * regs); +extern int svr4_msgsys(struct pt_regs * regs); + +/* stream.c */ +extern int svr4_getmsg(struct pt_regs *regs); +extern int svr4_putmsg(struct pt_regs *regs); +extern int svr4_getpmsg(struct pt_regs *regs); +extern int svr4_putpmsg(struct pt_regs *regs); + +/* ioctl.c */ +extern int svr4_ioctl_stream(struct pt_regs *regs, int fd, unsigned int func, void *arg); +extern int svr4_ioctl_termiox(int fd, unsigned int func, void *arg); + +/* sysfs.c */ +extern int svr4_sysfs(int cmd, int arg1, int arg2); + +/* sysinfo.c */ +extern int svr4_sysinfo(int, char *, long); + +/* xstat.c */ +extern int svr4_fxstat(int vers, int fd, void * buf); + +/* ulimit.c */ +extern int svr4_ulimit(int cmd, int val); +extern int svr4_getrlimit(int cmd, void *val); +extern int svr4_setrlimit(int cmd, void *val); + +/* poll.c */ +struct poll{ + int fd; + short events; + short revents; +}; +extern int svr4_poll(struct poll * ufds, size_t nfds, int timeout); + +/* hrtsys.c */ +extern int svr4_hrtsys(struct pt_regs * regs); + +/* syslocal.c */ +extern int svr4_syslocal(struct pt_regs * regs); + +/* ptrace.c */ +extern int svr4_ptrace(int req, int pid, unsigned long addr, unsigned long data); + +/* fcntl.c */ +extern int svr4_fcntl(struct pt_regs *regs); + +/* mmap.c */ +extern int svr4_mmap(unsigned int vaddr, unsigned int vsize, int prot, + int flags, int fd, unsigned int file_offset); + +/* sysconf.c */ +#define _CONFIG_NGROUPS 2 /* # configured supplemental groups */ +#define _CONFIG_CHILD_MAX 3 /* max # of processes per uid session */ +#define _CONFIG_OPEN_FILES 4 /* max # of open files per process */ +#define _CONFIG_POSIX_VER 5 /* POSIX version */ +#define _CONFIG_PAGESIZE 6 /* system page size */ +#define _CONFIG_CLK_TCK 7 /* ticks per second */ +#define _CONFIG_XOPEN_VER 8 /* XOPEN version */ +#define _CONFIG_NACLS_MAX 9 /* for Enhanced Security */ +#define _CONFIG_ARG_MAX 10 /* max length of exec args */ +#define _CONFIG_NPROC 11 /* # processes system is config for */ +#define _CONFIG_NENGINE 12 /* # configured processors (CPUs) */ +#define _CONFIG_NENGINE_ONLN 13 /* # online processors (CPUs) */ +#define _CONFIG_TOTAL_MEMORY 14 /* total memory */ +#define _CONFIG_USEABLE_MEMORY 15 /* user + system memory */ +#define _CONFIG_GENERAL_MEMORY 16 /* user only memory */ +#define _CONFIG_DEDICATED_MEMORY 17 /* dedicated memory */ +#define _CONFIG_NCGS_CONF 18 /* # CGs in system */ +#define _CONFIG_NCGS_ONLN 19 /* # CGs online now */ +#define _CONFIG_MAX_ENG_PER_CG 20 /* max engines per CG */ +#define _CONFIG_CACHE_LINE 21 /* memory cache line size */ +#define _CONFIG_SYSTEM_ID 22 /* system id assigned at ISL */ +#define _CONFIG_KERNEL_VM 23 /* size of kernel virtual memory */ +extern int svr4_sysconfig(int name); + +/* sysi86.c */ +extern int svr4_sysi86(struct pt_regs * regs); + +/* svr4_funcs.c */ +extern struct map_segment svr4_err_map[]; +extern struct map_segment svr4_socktype_map[]; +extern struct map_segment abi_sockopt_map[]; +extern struct map_segment abi_af_map[]; +extern long linux_to_ibcs_signals[]; +extern long ibcs_to_linux_signals[]; diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/svr4sig.h linux/include/abi/svr4sig.h --- linux-2.4.3/include/abi/svr4sig.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/svr4sig.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,10 @@ +#ifndef __ABI_SVR4SIG_H__ +#define __ABI_SVR4SIG_H__ +typedef void (*svr4_sig_t)(int, void *, void *); + +typedef struct { + u32 setbits [4]; +} svr4_sigset_t; + + +#endif diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/tli.h linux/include/abi/tli.h --- linux-2.4.3/include/abi/tli.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/tli.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,351 @@ +#ifndef __TLI_H +#define __TLI_H + + +struct t_info { + long addr; + long options; + long tsdu; + long etsdu; + long connect; + long discon; + long servtype; +}; + + +/* Error codes used by TLI transport providers. */ +#define TBADADDR 1 +#define TBADOPT 2 +#define TACCES 3 +#define TBADF 4 +#define TNOADDR 5 +#define TOUTSTATE 6 +#define TBADSEQ 7 +#define TSYSERR 8 +#define TLOOK 9 +#define TBADDATA 10 +#define TBUFOVFLW 11 +#define TFLOW 12 +#define TNODATA 13 +#define TNODIS 14 +#define TNOUDERR 15 +#define TBADFLAG 16 +#define TNOREL 17 +#define TNOTSUPPORT 18 +#define TSTATECHNG 19 + + +/* User level states (maintained internally by libnsl_s). */ +#define T_UNINIT 0 +#define T_UNBND 1 +#define T_IDLE 2 +#define T_OUTCON 3 +#define T_INCON 4 +#define T_DATAXFER 5 +#define T_OUTREL 6 +#define T_INREL 7 +#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 +#define T_CONN_RES 1 +#define T_DISCON_REQ 2 +#define T_DATA_REQ 3 +#define T_EXDATA_REQ 4 +#define T_INFO_REQ 5 +#define T_BIND_REQ 6 +#define T_UNBIND_REQ 7 +#define T_UNITDATA_REQ 8 +#define T_OPTMGMT_REQ 9 +#define T_ORDREL_REQ 10 + +#define T_CONN_IND 11 +#define T_CONN_CON 12 +#define T_DISCON_IND 13 +#define T_DATA_IND 14 +#define T_EXDATA_IND 15 +#define T_INFO_ACK 16 +#define T_BIND_ACK 17 +#define T_ERROR_ACK 18 +#define T_OK_ACK 19 +#define T_UNITDATA_IND 20 +#define T_UDERROR_IND 21 +#define T_OPTMGMT_ACK 22 +#define T_ORDREL_IND 23 + +/* Flags used from user level library routines. */ +#define T_MORE 0x0001 +#define T_EXPEDITED 0x0002 +#define T_NEGOTIATE 0x0004 +#define T_CHECK 0x0008 +#define T_DEFAULT 0x0010 +#define T_SUCCESS 0x0020 +#define T_FAILURE 0x0040 +#define T_CURRENT 0x0080 +#define T_PARTSUCCESS 0x0100 +#define T_READONLY 0x0200 +#define T_NOTSUPPORT 0x0400 + + +struct T_conn_req { + long PRIM_type; /* T_CONN_REQ */ + long DEST_length; + long DEST_offset; + long OPT_length; + long OPT_offset; +}; + +struct T_conn_res { + long PRIM_type; /* T_CONN_RES */ + void *QUEUE_ptr; + long OPT_length; + long OPT_offset; + long SEQ_number; +}; + +struct T_discon_req { + long PRIM_type; /* T_DISCON_REQ */ + long SEQ_number; +}; + +struct T_data_req { + long PRIM_type; /* T_DATA_REQ */ + long MORE_flag; +}; + +struct T_exdata_req { + long PRIM_type; /* T_EXDATA_REQ */ + long MORE_flag; +}; + +struct T_info_req { + long PRIM_type; /* T_INFO_REQ */ +}; + +struct T_bind_req { + long PRIM_type; /* T_BIND_REQ */ + long ADDR_length; + long ADDR_offset; + unsigned long CONIND_number; +}; + +struct T_unbind_req { + long PRIM_type; /* T_UNBIND_REQ */ +}; + +struct T_unitdata_req { + long PRIM_type; /* T_UNITDATA_REQ */ + long DEST_length; + long DEST_offset; + long OPT_length; + long OPT_offset; +}; + +struct T_optmgmt_req { + long PRIM_type; /* T_OPTMGMT_REQ */ + long OPT_length; + long OPT_offset; + long MGMT_flags; +}; + +struct T_ordrel_req { + long PRIM_type; /* T_ORDREL_REQ */ +}; + + +struct T_conn_ind { + long PRIM_type; /* T_CONN_IND */ + long SRC_length; + long SRC_offset; + long OPT_length; + long OPT_offset; + long SEQ_number; +}; + +struct T_conn_con { + long PRIM_type; /* T_CONN_CON */ + long RES_length; + long RES_offset; + long OPT_length; + long OPT_offset; +}; + +struct T_discon_ind { + long PRIM_type; /* T_DISCON_IND */ + long DISCON_reason; + long SEQ_number; +}; + +struct T_data_ind { + long PRIM_type; /* T_DATA_IND */ + long MORE_flag; +}; + +struct T_exdata_ind { + long PRIM_type; /* T_EXDATA_IND */ + long MORE_flag; +}; + +/* information acknowledgment */ + +struct T_info_ack { + long PRIM_type; /* T_INFO_ACK */ + long TSDU_size; + long ETSDU_size; + long CDATA_size; + long DDATA_size; + long ADDR_size; + long OPT_size; + long TIDU_size; + long SERV_type; + long CURRENT_state; + long PROVIDER_flag; +}; + +struct T_bind_ack { + long PRIM_type; /* T_BIND_ACK */ + long ADDR_length; + long ADDR_offset; + unsigned long CONIND_number; +}; + +struct T_error_ack { + long PRIM_type; /* T_ERROR_ACK */ + long ERROR_prim; + long TLI_error; + long UNIX_error; +}; + +struct T_ok_ack { + long PRIM_type; /* T_OK_ACK */ + long CORRECT_prim; +}; + +struct T_unitdata_ind { + long PRIM_type; /* T_UNITDATA_IND */ + long SRC_length; + long SRC_offset; + long OPT_length; + long OPT_offset; +}; + +struct T_uderror_ind { + long PRIM_type; /* T_UDERROR_IND */ + long DEST_length; + long DEST_offset; + long OPT_length; + long OPT_offset; + long ERROR_type; +}; + +struct T_optmgmt_ack { + long PRIM_type; /* T_OPTMGMT_ACK */ + long OPT_length; + long OPT_offset; + long MGMT_flags; +}; + +struct T_ordrel_ind { + long PRIM_type; /* T_ORDREL_IND */ +}; + + +union T_primitives { + long type; + struct T_conn_req conn_req; + struct T_conn_res conn_res; + struct T_discon_req discon_req; + struct T_data_req data_req; + struct T_exdata_req exdata_req; + struct T_info_req info_req; + struct T_bind_req bind_req; + struct T_unbind_req unbind_req; + struct T_unitdata_req unitdata_req; + struct T_optmgmt_req optmgmt_req; + struct T_ordrel_req ordrel_req; + struct T_conn_ind conn_ind; + struct T_conn_con conn_con; + struct T_discon_ind discon_ind; + struct T_data_ind data_ind; + struct T_exdata_ind exdata_ind; + struct T_info_ack info_ack; + struct T_bind_ack bind_ack; + struct T_error_ack error_ack; + struct T_ok_ack ok_ack; + struct T_unitdata_ind unitdata_ind; + struct T_uderror_ind uderror_ind; + struct T_optmgmt_ack optmgmt_ack; + struct T_ordrel_ind ordrel_ind; +}; + + +/* The t_opthdr structure defines the layout of options in a T_OPTMGMT_* + * 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 */ + unsigned long level; + unsigned long name; + unsigned long status; + 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; + unsigned char pri; + unsigned char band; + int length; + long type; +}; + +#define XTI_MAGIC 638654838 + +struct T_private { + int magic; + long state; + int offset; + struct T_primsg *pfirst, *plast; +}; + +#define Priv(file) ((struct T_private *)(file->private_data)) + +extern int timod_ioctl(struct pt_regs *, int, unsigned int, void *, int, int *); +extern int timod_putmsg(int, struct inode *, int, struct pt_regs *); +extern int timod_getmsg(int, struct inode *, int, struct pt_regs *); +extern int timod_update_socket(int, struct file *, struct pt_regs *); + +#endif /* __TLI_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/trace.h linux/include/abi/trace.h --- linux-2.4.3/include/abi/trace.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/trace.h Fri Mar 30 15:23:49 2001 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001 Christoph Hellwig. + * All rights resered. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#ifndef _ABI_TRACE_H_ +#define _ABI_TRACE_H_ + +/* + * Linux-ABI tracing helpers. + */ +#include +#include + + +/* + * The currently executed syscall. + */ +extern ABI_func * abi_current; + +/* + * Check if a syscall needs tracing. + */ +#define abi_traced(res) ((abi_traceflg & (res)) || (abi_current->trace)) + +/* + * Possible flags for abi_traceflg. + */ +#define ABI_TRACE_API 0x00000001 /* all call/return values */ +#define ABI_TRACE_IOCTL 0x00000002 /* all ioctl calls */ +#define ABI_TRACE_IOCTL_F 0x00000004 /* ioctl calls that fail */ +#define ABI_TRACE_SIGNAL 0x00000008 /* all signal calls */ +#define ABI_TRACE_SIGNAL_F 0x00000010 /* signal calls that fail */ +#define ABI_TRACE_SOCKSYS 0x00000020 /* socksys and spx devices */ +#define ABI_TRACE_COFF_LD 0x00000040 /* COFF loader */ +#define ABI_TRACE_ELF_LD 0x00000080 /* ELF loader */ +#define ABI_TRACE_XOUT_LD 0x00000100 /* XOUT loader */ +#define ABI_TRACE_XOUT_DB 0x00000200 /* XOUT loader before launch */ +#define ABI_TRACE_STREAMS 0x00000400 /* STREAMS faking */ +#define ABI_TRACE_FUNC 0x10000000 /* trace this function */ + +extern u_int abi_traceflg; + +#define __abi_trace(fmt...) \ + printk(KERN_DEBUG "[%s:%d]: ", current->comm, current->pid); \ + printk(fmt); + +#define abi_trace(reason, fmt...) \ + { if (abi_traced(reason)) __abi_trace(fmt); } + +#endif /* _ABI_TRACE_H_ */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/unused-termios.h linux/include/abi/unused-termios.h --- linux-2.4.3/include/abi/unused-termios.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/unused-termios.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,200 @@ +/* + * This file was entered from the book + * Intel386 Family Binary Compatability Specification 2 + * McGraw-Hill Book company + * ISBN 0-07-031219-2 + * + * $Id$ + * $Source$ + */ + +#define NCC 8 +#define NCCS 13 + +typedef unsigned short tcflag_t; +typesef unsigned char cc_t; +typedef unsigned long speed_t; + +struct termio { + unsigned short c_iflag; + unsigned short c_oflag; + unsigned short c_cflag; + unsigned short c_lflag; + char c_line; + unsigned char c_cc[NC]; +}; + +struct termios { + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + char c_line; + cc_t c_cc[NCCS]; + char c_ispeed; + char c_ospeed; +}; + +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VEOL 5 +#define VEOL2 6 +#define VMIN 4 +#define VTIME 5 +#define VSWTCH 7 +#define VSUSP 10 +#define VSTART 11 +#define VSTOP 12 + +#define CNUL 0 +#define CDEL 0377 +#define CESC '\\' +#define CINTR 0177 +#define CQUIT 034 +#define CERASE '#' +#define CKILL '@' +#define CSTART 021 +#define CSTOP 023 +#define CSWTCH 032 +#define CNSWTCH 0 +#define CSUSP 032 + +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 /* RESERVED */ +#define DOSMODE 0100000 + +#define OPOST 00000001 +#define OLCUC 00000002 +#define ONLCR 00000004 +#define OCRNL 00000010 +#define ONOCR 00000020 +#define ONLRET 00000040 +#define OFILL 00000100 +#define OFDEL 00000200 +#define NLDLY 00000400 +#define NL0 0 +#define NL1 00000400 +#define CRDLY 00003000 +#define CR0 0 +#define CR1 00001000 +#define CR2 00002000 +#define CR3 00003000 +#define TABDLY 00014000 +#define TAB0 0 +#define TAB1 00004000 +#define TAB2 00010000 +#define TAB3 00014000 +#define BSDLY 00200000 +#define BS0 0 +#define BS1 00200000 +#define VTDLY 00400000 +#define VT0 0 +#define VT1 00400000 +#define FFDLY 01000000 +#define FF0 0 +#define FF1 01000000 + +#define CBAUD 0000017 +#define CSIZE 0000060 +#define CS5 0 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#define RCV1EN 0010000 +#define XMT1EN 0020000 +#define LOBLK 0040000 +#define XCLUDE 0100000 + +#define ISIG 0000001 +#define ICANON 0000002 +#define XCASE 0000004 +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define IEXTEN 0000400 +#defien TOSTOP 0001000 + +/* Bits 10-15 (0176000) in the c_lflag field are RESERVED */ + +/* +#define XIOC ('x'<<8) Level 2 +*/ +#define XIOC (('i'<<8)|('X'<<16)) +#define XCGETA (XIOC|1) +#define XCSETA (XIOC|2) +#define XCSETAW (XIOC|3) +#define XCSETAF (XIOC|4) + +#define TIOC ('T'<<8) + +#define TCGETA (TIOC|1) +#define TCSETA (TIOC|2) +#define TCSETAW (TIOC|3) +#define TCSETAF (TIOC|4) +#define TCSBRK (TIOC|5) +#define TCXONC (TIOC|6) +#define TCFLSH (TIOC|7) + +#define TIOCGWINSZ (TIOC|104) +#define TIOCSWINSZ (TIOC|103) + +#define TCSANOW XCSETA +#define TCSADRAIN XCSETAW +#define TCSAFLUSH XCSETAF +#define TCSADFLUSH XCSETAF + +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +#define B0 0 +#define B50 1 +#define B75 2 +#define B110 3 +#define B134 4 +#define B150 5 +#define B200 6 +#define B300 7 +#define B600 8 +#define B1200 9 +#define B1800 10 +#define B2400 11 +#define B4800 12 +#define B9600 13 +#define B19200 14 +#define B38400 15 + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/uw7.h linux/include/abi/uw7.h --- linux-2.4.3/include/abi/uw7.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/uw7.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,82 @@ +#ifndef __ABI_UW7_H__ +#define __ABI_UW7_H__ + +#ifdef __KERNEL__ + +#define GETACL 1 +#define SETACL 2 +#define GETACLCNT 3 + +struct acl { + int a_type; + uid_t a_id; + ushort a_perm; +}; + +#define UW7_NCCS (19) +struct uw7_termios { + unsigned long c_iflag; + unsigned long c_oflag; + unsigned long c_cflag; + unsigned long c_lflag; + unsigned char c_cc[UW7_NCCS]; +}; + +extern int uw7_acl(char * path, int cmd, int nentries, struct acl * aclp); + +/* access.c */ +extern int uw7_access(char * path, int mode); + +/* kernel.c */ +extern int uw7_sleep(int seconds); +extern int uw7_seteuid(int uid); +extern int uw7_setegid(int gid); +extern int uw7_pread(unsigned int fd, char * buf, int count, long off); +extern int uw7_pwrite(unsigned int fd, char * buf, int count, long off); +extern int uw7_lseek64(unsigned int fd, unsigned int off, + unsigned int off_hi, unsigned int orig); +extern int uw7_pread64(unsigned int fd, char * buf, int count, + unsigned int off_hi, unsigned int off); +extern int uw7_pwrite64(unsigned int fd, char * buf, int count, + unsigned int off_hi, unsigned int off); +extern int uw7_stty(int fd, int cmd); +extern int uw7_gtty(int fd, int cmd); + +/* proc.c */ +extern int uw7_proc_init(void); +extern void uw7_proc_cleanup(void); + +/* ioctl.c */ +extern int uw7_ioctl(struct pt_regs * regs); + +/* mac.c */ +extern int uw7_mldmode(int mldmode); + +struct uw7_statvfs64 { + unsigned long f_bsize; + unsigned long f_frsize; + unsigned long long f_blocks; + unsigned long long f_bfree; + unsigned long long f_bavail; + unsigned long long f_files; + unsigned long long f_ffree; + unsigned long long f_favail; + unsigned long f_fsid; + char f_basetype[16]; + unsigned long f_flag; + unsigned long f_namemax; + char f_fstr[32]; + unsigned long f_filler[16]; +}; + +extern int uw7_statvfs64(char * filename, struct uw7_statvfs64 * buf); +extern int uw7_fstatvfs64(int fd, struct uw7_statvfs64 * buf); + +/* the other MAP_XXX values are the same as on Linux/i386 */ +#define UW7_MAP_ANONYMOUS 0x100 + +extern int uw7_mmap(unsigned long, unsigned long, unsigned long, unsigned long, + unsigned long, unsigned long); + +#endif /* __KERNEL__ */ +#endif /* __ABI_UW7_H__ */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/uw7_context.h linux/include/abi/uw7_context.h --- linux-2.4.3/include/abi/uw7_context.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/uw7_context.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,45 @@ +#ifndef __ABI_UW7_CONTEXT_H__ +#define __ABI_UW7_CONTEXT_H__ + +#ifdef __KERNEL__ + +/* ss_size <-> ss_flags which is why we can't use native Linux stack_t :( */ +typedef struct uw7_stack { + void *ss_sp; + int ss_size; + int ss_flags; +} uw7_stack_t; + +/* XXX more registers, please */ +typedef struct uw7_mcontext { + unsigned short gs, __gsh; + unsigned short fs, __fsh; + unsigned short es, __esh; + unsigned short ds, __dsh; +} uw7_mcontext_t; + +typedef struct uw7_sigset { + unsigned int sigbits[4]; +} uw7_sigset_t; + +typedef struct uw7_context { + unsigned long uc_flags; + struct uw7_context *uc_link; + uw7_sigset_t uc_sigmask; + uw7_stack_t uc_stack; + uw7_mcontext_t uc_mcontext; + void *uc_pdata; + char uc_unused[16]; +} uw7_context_t; + +#define UW7_GETCONTEXT 0 +#define UW7_SETCONTEXT 1 +#define UW7_GETXCONTEXT 2 + + +/* context.c */ +extern int uw7_context(struct pt_regs * regs); +extern int uw7_sigaltstack(const uw7_stack_t *ss, uw7_stack_t *oss); + +#endif /* __KERNEL__ */ +#endif /* __ABI_UW7_CONTEXT_H__ */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/uw7_termbits.h linux/include/abi/uw7_termbits.h --- linux-2.4.3/include/abi/uw7_termbits.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/uw7_termbits.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,150 @@ +#ifndef __ABI_UW7_TERMBITS_H__ +#define __ABI_UW7_TERMBITS_H__ + +#ifdef __KERNEL__ + +#define UW7_TIOC ('T'<<8) +#define UW7_TCGETA (UW7_TIOC|1) +#define UW7_TCSETA (UW7_TIOC|2) +#define UW7_TCSETAW (UW7_TIOC|3) +#define UW7_TCSETAF (UW7_TIOC|4) +#define UW7_TCSBRK (UW7_TIOC|5) +#define UW7_TCXONC (UW7_TIOC|6) +#define UW7_TCFLSH (UW7_TIOC|7) +#define UW7_TCDSET (UW7_TIOC|32) +#define UW7_RTS_TOG (UW7_TIOC|33) +#define UW7_TIOCGWINSZ (UW7_TIOC|104) +#define UW7_TIOCSWINSZ (UW7_TIOC|103) +#define UW7_TCGETS (UW7_TIOC|13) +#define UW7_TCSETS (UW7_TIOC|14) +#define UW7_TCSANOW UW7_TCSETS +#define UW7_TCSETSW (UW7_TIOC|15) +#define UW7_TCSADRAIN UW7_TCSETSW +#define UW7_TCSETSF (UW7_TIOC|16) +#define UW7_TCSAFLUSH UW7_TCSETSF + +/* + * VEOF/VEOL and VMIN/VTIME are overloaded. + * VEOF/VEOL are used in canonical mode (ICANON), + * otherwise VMIN/VTIME are used. + */ +#define UW7_VINTR 0 +#define UW7_VQUIT 1 +#define UW7_VERASE 2 +#define UW7_VKILL 3 +#define UW7_VEOF 4 +#define UW7_VEOL 5 +#define UW7_VEOL2 6 +#define UW7_VMIN 4 +#define UW7_VTIME 5 +#define UW7_VSWTCH 7 +#define UW7_VSTART 8 +#define UW7_VSTOP 9 +#define UW7_VSUSP 10 +#define UW7_VDSUSP 11 +#define UW7_VREPRINT 12 +#define UW7_VDISCARD 13 +#define UW7_VWERASE 14 +#define UW7_VLNEXT 15 + +/* + * Input modes (c_iflag), same as Linux bits, except DOSMODE (obsolete). + */ +#define UW7_IFLAG_MSK 0017777 +#define UW7_IGNBRK 0000001 +#define UW7_BRKINT 0000002 +#define UW7_IGNPAR 0000004 +#define UW7_PARMRK 0000010 +#define UW7_INPCK 0000020 +#define UW7_ISTRIP 0000040 +#define UW7_INLCR 0000100 +#define UW7_IGNCR 0000200 +#define UW7_ICRNL 0000400 +#define UW7_IUCLC 0001000 +#define UW7_IXON 0002000 +#define UW7_IXANY 0004000 +#define UW7_IXOFF 0010000 +#define UW7_IMAXBEL 0020000 +#define UW7_DOSMODE 0100000 + +/* + * Output modes (c_oflag), exactly the same as Linux bits. + */ +#define UW7_OFLAG_MSK 0177777 +#define UW7_OPOST 0000001 +#define UW7_OLCUC 0000002 +#define UW7_ONLCR 0000004 +#define UW7_OCRNL 0000010 +#define UW7_ONOCR 0000020 +#define UW7_ONLRET 0000040 +#define UW7_OFILL 0000100 +#define UW7_OFDEL 0000200 +#define UW7_NLDLY 0000400 +#define UW7_NL0 0000000 +#define UW7_NL1 0000400 +#define UW7_CRDLY 0003000 +#define UW7_CR0 0000000 +#define UW7_CR1 0001000 +#define UW7_CR2 0002000 +#define UW7_CR3 0003000 +#define UW7_TABDLY 0014000 +#define UW7_TAB0 0000000 +#define UW7_TAB1 0004000 +#define UW7_TAB2 0010000 +#define UW7_TAB3 0014000 +#define UW7_XTABS UW7_TAB3 +#define UW7_BSDLY 0020000 +#define UW7_BS0 0000000 +#define UW7_BS1 0020000 +#define UW7_VTDLY 0040000 +#define UW7_VT0 0000000 +#define UW7_VT1 0040000 +#define UW7_FFDLY 0100000 +#define UW7_FF0 0000000 +#define UW7_FF1 0100000 + +/* + * Control modes (c_cflag). + */ +#define UW7_CFLAG_MSK 0177777 +#define UW7_CBAUD 0000017 +#define UW7_CSIZE 0000060 +#define UW7_CS5 0000000 +#define UW7_CS6 0000020 +#define UW7_CS7 0000040 +#define UW7_CS8 0000060 +#define UW7_CSTOPB 0000100 +#define UW7_CREAD 0000200 +#define UW7_PARENB 0000400 +#define UW7_PARODD 0001000 +#define UW7_HUPCL 0002000 +#define UW7_CLOCAL 0004000 +#define UW7_XCLUDE 0100000 +#define UW7_CIBAUD 000003600000 +#define UW7_IBSHIFT 16 +#define UW7_PAREXT 000004000000 + +/* + * Local modes (c_lflag), same as Linux except + * UW7_FLUSHO is different and UW7_DEFECHO is obsolete (set to 0). + */ +#define UW7_LFLAG_MSK 0001777 +#define UW7_ISIG 0000001 +#define UW7_ICANON 0000002 +#define UW7_XCASE 0000004 +#define UW7_ECHO 0000010 +#define UW7_ECHOE 0000020 +#define UW7_ECHOK 0000040 +#define UW7_ECHONL 0000100 +#define UW7_NOFLSH 0000200 +#define UW7_TOSTOP 0000400 +#define UW7_ECHOCTL 0001000 +#define UW7_ECHOPRT 0002000 +#define UW7_ECHOKE 0004000 +#define UW7_DEFECHO 0010000 +#define UW7_FLUSHO 0020000 +#define UW7_PENDIN 0040000 +#define UW7_IEXTEN 0100000 + +#endif /* __KERNEL__ */ +#endif /* __ABI_UW7_TERMBITS_H__ */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/wysev386i.h linux/include/abi/wysev386i.h --- linux-2.4.3/include/abi/wysev386i.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/wysev386i.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,65 @@ +/* + * include/abi/wysev386i.h + * + * Copyright (C) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + * + * $Id$ + * $Source$ + */ + +/* Wyse extensions for 4.3 BSD TCP/IP in V/386 3.2.1A */ + +#include + + +/* Get struct rtentry from linux/route.h - this should be compatible. */ +#include + +/* Get struct arpreq from linux/if_arp.h - this should be compatible. */ +#include + +/* Get struct ifreq and struct ifconf from linux/if.h - these should + * be compatible. + */ +#include + + +/* Wyse use BSD style ioctls. This will warn us if we haven't got compatible + * structures :-). + */ + +/* socket i/o controls */ +#define WVR3_SIOCSHIWAT BSD__IOW('s', 0, int) /* set high watermark */ +#define WVR3_SIOCGHIWAT BSD__IOR('s', 1, int) /* get high watermark */ +#define WVR3_SIOCSLOWAT BSD__IOW('s', 2, int) /* set low watermark */ +#define WVR3_SIOCGLOWAT BSD__IOR('s', 3, int) /* get low watermark */ +#define WVR3_SIOCATMARK BSD__IOR('s', 7, int) /* at oob mark? */ +#define WVR3_SIOCSPGRP BSD__IOW('s', 8, int) /* set process group */ +#define WVR3_SIOCGPGRP BSD__IOR('s', 9, int) /* get process group */ + +#define WVR3_SIOCADDRT BSD__IOW('r', 10, struct rtentry) /* add route */ +#define WVR3_SIOCDELRT BSD__IOW('r', 11, struct rtentry) /* delete route */ + +#define WVR3_SIOCSIFADDR BSD__IOW('i', 12, struct ifreq) /* set ifnet address */ +#define WVR3_SIOCGIFADDR BSD__IOWR('i',13, struct ifreq) /* get ifnet address */ +#define WVR3_SIOCSIFDSTADDR BSD__IOW('i', 14, struct ifreq) /* set p-p address */ +#define WVR3_SIOCGIFDSTADDR BSD__IOWR('i',15, struct ifreq) /* get p-p address */ +#define WVR3_SIOCSIFFLAGS BSD__IOW('i', 16, struct ifreq) /* set ifnet flags */ +#define WVR3_SIOCGIFFLAGS BSD__IOWR('i',17, struct ifreq) /* get ifnet flags */ +#define WVR3_SIOCGIFBRDADDR BSD__IOWR('i',18, struct ifreq) /* get broadcast addr */ +#define WVR3_SIOCSIFBRDADDR BSD__IOW('i',19, struct ifreq) /* set broadcast addr */ +#define WVR3_SIOCGIFCONF BSD__IOWR('i',20, struct ifconf) /* get ifnet list */ +#define WVR3_SIOCGIFNETMASK BSD__IOWR('i',21, struct ifreq) /* get net addr mask */ +#define WVR3_SIOCSIFNETMASK BSD__IOW('i',22, struct ifreq) /* set net addr mask */ +#define WVR3_SIOCGIFMETRIC BSD__IOWR('i',23, struct ifreq) /* get IF metric */ +#define WVR3_SIOCSIFMETRIC BSD__IOW('i',24, struct ifreq) /* set IF metric */ +#define WVR3_SIOCSIFHADDR BSD__IOW('i', 25, struct ifreq) /* set hardware addr */ +#define WVR3_SIOCGIFHADDR BSD__IOWR('i',26, struct ifreq) /* get hardware addr */ +#define WVR3_SIOCRIFHADDR BSD__IOW('i', 27, struct ifreq) /* reset hardware addr */ + +#define WVR3_SIOCSARP BSD__IOW('i', 30, struct arpreq) /* set arp entry */ +#define WVR3_SIOCGARP BSD__IOWR('i',31, struct arpreq) /* get arp entry */ +#define WVR3_SIOCDARP BSD__IOW('i', 32, struct arpreq) /* delete arp entry */ + +#define WVR3_SIOCADDMULTI BSD__IOW('i', 33, struct ifreq) /* set multicast addr */ +#define WVR3_SIOCDELMULTI BSD__IOW('i', 34, struct ifreq) /* set multicast addr */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/xnx.h linux/include/abi/xnx.h --- linux-2.4.3/include/abi/xnx.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/xnx.h Mon Mar 12 16:35:05 2001 @@ -0,0 +1,41 @@ +/* + * include/abi/xnx.h -- xenix ibcs interface + * + * Copyright (C) 1993 Drew Sullivan + * Released for general use as long as this copyright remains. + * + * $Id$ + * $Source$ + */ +typedef unsigned short excode_t; + +struct timeb { + time_t time; + unsigned short millitm; + short timezone; + short dstflag; +}; + +extern int xnx_locking(int fd, int mode, unsigned long size); +extern int xnx_creatsem(char *sem_name, int mode); +extern int xnx_opensem(char *sem_name); +extern int xnx_sigsem(int sem_num); +extern int xnx_waitsem(int sem_num); +extern int xnx_nbwaitsem(int sem_num); +extern int xnx_rdchk(int fd); +extern int xnx_ftime(struct timeb * tp); +extern int xnx_nap(long period); +extern int xnx_sdget(char *path, int flags, long size, int mode); +extern int xnx_sdfree(char* addr); +extern int xnx_sdenter(char *addr, int flags); +extern int xnx_sdleave(char *addr); +extern int xnx_sdgetv(char *addr); +extern int xnx_sdwaitv(char *addr, int vnum); +extern int xnx_proctl(int pid, int command, char *arg); +extern int xnx_execseg(excode_t oldaddr, unsigned size); +extern int xnx_unexecseg(excode_t addr); +extern int xnx_eaccess(char *path, int mode); +extern int xnx_paccess(int pid, int cmd, int offset, int count, char *ptr); +extern int xnx_sigpending(unsigned long *set); +extern int xnx_pathconf(char *path, int name); +extern int xnx_fpathconf(int fildes, int name); diff -uNr --exclude-from=dontdiff linux-2.4.3/include/abi/xout.h linux/include/abi/xout.h --- linux-2.4.3/include/abi/xout.h Thu Jan 1 01:00:00 1970 +++ linux/include/abi/xout.h Sun Mar 18 17:28:03 2001 @@ -0,0 +1,192 @@ +/* $Id$ + * xout.h - Microsoft Xenix x.out binary format data structures + * + * Copyright (c) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) + */ +#ifndef _ABI_XOUT_H_ +#define _ABI_XOUT_H_ + +/* + * This file is based on available documentation for the Xenix x.out + * format. Much is missing here. There is just enough to allow us to + * support 386 small model and not a lot more. + */ + +/* + * X.out header + */ +struct xexec { + u_short x_magic; /* magic number */ + u_short x_ext; /* size of header extension */ + + /* + * For segmented binaries the following sizes are the sums + * of the segment sizes. + */ + long x_text; /* size of text segments */ + long x_data; /* size of initialized data */ + long x_bss; /* size of uninitialized data */ + long x_syms; /* size of symbol table */ + long x_reloc; /* relocation table length */ + + long x_entry; /* entry point */ + char x_cpu; /* cpu type and byte/word order */ + char x_relsym; /* undefined */ + u_short x_renv; /* run-time environment */ +}; + +/* + * X.out header extension + */ +struct xext { + /* + * These are unused. + * */ + long xe_trsize; /* ??? */ + long xe_drsize; /* ??? */ + long xe_tbase; /* ??? */ + long xe_dbase; /* ??? */ + + long xe_stksize; /* stack size (if XE_FS set) */ + + /* + * The following are present if XE_SEG is set. + */ + long xe_segpos; /* offset to segment table */ + long xe_segsize; /* segment table size */ + long xe_mdtpos; /* offset to machdep table */ + long xe_mdtsize; /* machine dependent table size */ + char xe_mdttype; /* machine dependent table type */ + char xe_pagesize; /* file pagesize, in 512 units */ + char xe_ostype; /* operating system type */ + char xe_osvers; /* operating system version */ + u_short xe_eseg; /* entry segment, machdep */ + u_short xe_sres; /* reserved */ +}; + +/* + * X.out segment description. + */ +struct xseg { + u_short xs_type; /* segment type */ + u_short xs_attr; /* segment attributes */ + u_short xs_seg; /* segment number */ + char xs_align; /* log base 2 of alignment */ + char xs_cres; /* unused */ + u_long xs_filpos; /* file position */ + u_long xs_psize; /* physical size (in file) */ + u_long xs_vsize; /* virtual size (in core) */ + u_long xs_rbase; /* relocation base addr/offset */ + u_short xs_noff; /* segment name table offset */ + u_short xs_sres; /* unused */ + long xs_lres; /* unused */ +}; + + +/* + * Magic number for an x.out header. + */ +#define X_MAGIC 0x0206 /* indicates x.out header */ + +/* + * Codes for x_cpu. + */ +#define XC_BSWAP 0x80 /* bytes swapped */ +#define XC_WSWAP 0x40 /* words swapped */ +#define XC_8086 0x04 /* I8086 */ +#define XC_286 0x09 /* iAPX 80286 */ +#define XC_286V 0x29 /* iAPX 80286, use xe_osver for version */ +#define XC_386 0x0a /* iAPX 80386 */ +#define XC_186 0x0b /* iAPX 80186 */ +#define XC_CPU 0x3f /* cpu mask */ + +/* + * Flags for the run-time environment. + */ +#define XE_V2 0x4000 /* version 2.x */ +#define XE_V3 0x8000 /* version 3.x */ +#define XE_OSV 0xc000 /* if XE_SEG use xe_osvers ... */ +#define XE_V5 XE_OSV /* else assume v5.x */ +#define XE_VERS 0xc000 /* version mask */ + +#define XE_5_3 0x2000 /* binary needs 5.3 functionality */ +#define XE_LOCK 0x1000 /* Use Advisory locking */ +#define XE_SEG 0x0800 /* segment table present */ +#define XE_ABS 0x0400 /* absolute memory image (standalone) */ +#define XE_ITER 0x0200 /* iterated text/data present */ +#define XE_HDATA 0x0100 /* huge model data (never used) */ +#define XE_VMOD XE_HDATA /* virtual module */ +#define XE_FPH 0x0080 /* floating point hardware required */ +#define XE_LTEXT 0x0040 /* large model text */ +#define XE_LDATA 0x0020 /* large model data */ +#define XE_OVER 0x0010 /* text overlay */ +#define XE_FS 0x0008 /* fixed stack */ +#define XE_PURE 0x0004 /* pure text */ +#define XE_SEP 0x0002 /* separate I & D */ +#define XE_EXEC 0x0001 /* executable */ + + +/* + * Segment types. + */ +#define XS_TNULL 0 /* unused segment */ +#define XS_TTEXT 1 /* text segment */ +#define XS_TDATA 2 /* data segment */ +#define XS_TSYMS 3 /* symbol table segment */ +#define XS_TREL 4 /* relocation segment */ +#define XS_TSESTR 5 /* segment table's string table segment */ +#define XS_TGRPS 6 /* group definitions segment */ + +#define XS_TIDATA 64 /* iterated data */ +#define XS_TTSS 65 /* tss */ +#define XS_TLFIX 66 /* lodfix */ +#define XS_TDNAME 67 /* descriptor names */ +#define XS_TDTEXT 68 /* debug text segment */ +#define XS_TIDBG XS_TDTEXT +#define XS_TDFIX 69 /* debug relocation */ +#define XS_TOVTAB 70 /* overlay table */ +#define XS_T71 71 +#define XS_TSYSTR 72 /* symbol string table */ + +/* + * Segment attributes. + */ +#define XS_AMEM 0x8000 /* is a memory image */ + +/* + * For text and data segment types + */ +#define XS_AITER 0x0001 /* contains iteration records */ +#define XS_AHUGE 0x0002 /* contains huge element */ +#define XS_ABSS 0x0004 /* contains implicit BSS */ +#define XS_APURE 0x0008 /* read only, shareable */ +#define XS_AEDOWN 0x0010 /* expands downward (stack) */ +#define XS_APRIV 0x0020 /* may not be combined */ +#define XS_A32BIT 0x0040 /* is 32 bit */ + +/* + * File position macros, valid only if !XE_SEG. + */ +#define XEXTPOS(xp) ((long) sizeof(struct xexec)) +#define XTEXTPOS(xp) (XEXTPOS(xp) + (long) (xp)->x_ext) +#define XDATAPOS(xp) (XTEXTPOS(xp) + (xp)->x_text) +#define XBSSPOS(xp) (XDATAPOS(xp) + (xp)->x_data) +#define XSYMPOS(xp) (XDATAPOS(xp) + (xp)->x_data) +#define XRELPOS(xp) (XSYMPOS(xp) + (xp)->x_syms) +#define XENDPOS(xp) (XRELPOS(xp) + (xp)->x_reloc) + +#define XRTEXTPOS(xp, ep) (XRELPOS(xp)) +#define XRDATAPOS(xp, ep) (XRELPOS(xp) + (ep)->xe_trsize) + + +/* + * Specials for the Linux Xenix 286 emulator. + * + * The base address that 286 segments are loaded above. This should be + * above memory used by the emulator overlay. Actual segment data + * starts slightly higher than this since we map the xexec and xext + * structures of the executable to this address. + */ +#define X286_MAP_ADDR 0x4000000 + +#endif /* _ABI_XOUT_H_ */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-alpha/elf.h linux/include/asm-alpha/elf.h --- linux-2.4.3/include/asm-alpha/elf.h Fri Sep 22 23:07:43 2000 +++ linux/include/asm-alpha/elf.h Fri Mar 30 17:25:23 2001 @@ -126,9 +126,22 @@ }) #ifdef __KERNEL__ -#define SET_PERSONALITY(EX, IBCS2) \ - set_personality(((EX).e_flags & EF_ALPHA_32BIT) \ - ? PER_LINUX_32BIT : (IBCS2) ? PER_SVR4 : PER_LINUX) -#endif -#endif +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + unsigned long personality = PER_LINUX; \ + \ + /* If the header identifies the binary, use that information */ \ + if ((ex).e_flags & EF_ALPHA_32BIT) \ + personality = PER_LINUX_32BIT; \ + \ + /* Else check the interpreter for SVR4isms */ \ + else if (strcmp((interp), "/usr/lib/libc.so.1") == 0 || \ + strcmp((interp), "/usr/lib/ld.so.1") == 0) \ + personality = PER_SVR4; \ + \ + set_personality(personality); \ +} while (0) + +#endif /* __KERNEL__ */ +#endif /* __ASM_ALPHA_ELF_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-cris/elf.h linux/include/asm-cris/elf.h --- linux-2.4.3/include/asm-cris/elf.h Fri Feb 23 20:12:50 2001 +++ linux/include/asm-cris/elf.h Fri Mar 30 17:25:23 2001 @@ -62,7 +62,17 @@ #define ELF_PLATFORM (NULL) #ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) -#endif +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + unsigned long personality = PER_LINUX; \ + \ + /* Check the interpreter for SVR4isms */ \ + else if (strcmp((interp), "/usr/lib/libc.so.1") == 0 || \ + strcmp((interp), "/usr/lib/ld.so.1") == 0) \ + personality = PER_SVR4; \ + \ + set_personality(personality); \ +} while (0) -#endif +#endif /* __KERNEL__ */ +#endif /* __ASMCRIS_ELF_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-i386/abi.h linux/include/asm-i386/abi.h --- linux-2.4.3/include/asm-i386/abi.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-i386/abi.h Fri Mar 30 17:25:23 2001 @@ -0,0 +1,7 @@ +#define get_syscall_parameter(regs,n) ({ unsigned long r; \ + get_user(r, ((unsigned long *)regs->esp)+((n)+1)); \ + r; }) +#define set_error(regs,e) { regs->eax = (e); regs->eflags |= 1; } +#define clear_error(regs) { regs->eflags &= ~1; } +#define set_result(regs,r) regs->eax = r +#define get_result(regs) regs->eax diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-i386/elf.h linux/include/asm-i386/elf.h --- linux-2.4.3/include/asm-i386/elf.h Thu Jan 4 23:51:47 2001 +++ linux/include/asm-i386/elf.h Fri Mar 30 17:31:36 2001 @@ -97,8 +97,26 @@ #define ELF_PLATFORM (system_utsname.machine) +/* EF_386_UW7 is needed by elfmark(1) so it's outside __KERNEL__ */ +#define EF_386_UW7 0x314B4455 + #ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) -#endif -#endif +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + unsigned long personality = PER_LINUX; \ + \ + /* If the header identifies the binary, use that information */ \ + if ((ex).e_flags == EF_386_UW7) \ + personality = PER_UW7; \ + \ + /* Else check the interpreter for SVR4isms */ \ + else if (strcmp((interp), "/usr/lib/libc.so.1") == 0 || \ + strcmp((interp), "/usr/lib/ld.so.1") == 0) \ + personality = PER_SVR4; \ + \ + set_personality(personality); \ +} while (0) + +#endif /* __KERNEL__ */ +#endif /* __ASMi386_ELF_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-i386/ldt.h linux/include/asm-i386/ldt.h --- linux-2.4.3/include/asm-i386/ldt.h Sun Jul 11 18:11:46 1999 +++ linux/include/asm-i386/ldt.h Fri Mar 30 17:25:23 2001 @@ -12,7 +12,7 @@ #define LDT_ENTRY_SIZE 8 #ifndef __ASSEMBLY__ -struct modify_ldt_ldt_s { +typedef struct modify_ldt_ldt_s { unsigned int entry_number; unsigned long base_addr; unsigned int limit; @@ -22,7 +22,7 @@ unsigned int limit_in_pages:1; unsigned int seg_not_present:1; unsigned int useable:1; -}; +} modify_ldt_t; #define MODIFY_LDT_CONTENTS_DATA 0 #define MODIFY_LDT_CONTENTS_STACK 1 diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-i386/namei.h linux/include/asm-i386/namei.h --- linux-2.4.3/include/asm-i386/namei.h Mon Apr 3 00:49:07 2000 +++ linux/include/asm-i386/namei.h Fri Mar 30 17:25:23 2001 @@ -1,4 +1,4 @@ -/* $Id$ +/* $Id$ * linux/include/asm-i386/namei.h * * Included from linux/fs/namei.c @@ -7,11 +7,59 @@ #ifndef __I386_NAMEI_H #define __I386_NAMEI_H -/* This dummy routine maybe changed to something useful - * for /usr/gnemul/ emulation stuff. - * Look at asm-sparc/namei.h for details. +//#if defined(CONFIG_ABI) || defined (CONFIG_ABI_MODULE) +#if 1 + +/* + * The base directory for our emulations. + * - sparc uses usr/gmemul here. + */ +#define I386_EMUL_BASE "emul/" + +/* + * We emulate quite a lot operting systems... */ +#define I386_SVR4_EMUL I386_EMUL_BASE "/svr4/" +#define I386_SVR3_EMUL I386_EMUL_BASE "/svr3/" +#define I386_SCOSVR3_EMUL I386_EMUL_BASE "/sco/" +#define I386_WYSEV386_EMUL I386_EMUL_BASE "/wyse/" +#define I386_ISCR4_EMUL I386_EMUL_BASE "/isc/" +#define I386_BSD_EMUL I386_EMUL_BASE "/bsd/" +#define I386_XENIX_EMUL I386_EMUL_BASE "/xenix/" +#define I386_SOLARIS_EMUL I386_EMUL_BASE "/solaris/" +#define I386_UW7_EMUL I386_EMUL_BASE "/uw7/" -#define __emul_prefix() NULL +static inline char *__emul_prefix(void) +{ + switch (current->personality) { + case PER_SVR4: + return I386_SVR4_EMUL; + case PER_SVR3: + return I386_SVR3_EMUL; + case PER_SCOSVR3: + return I386_SCOSVR3_EMUL; + case PER_WYSEV386: + return I386_WYSEV386_EMUL; + case PER_ISCR4: + return I386_ISCR4_EMUL; + case PER_BSD: + return I386_BSD_EMUL; + case PER_XENIX: + return I386_XENIX_EMUL; + case PER_SOLARIS: + return I386_SOLARIS_EMUL; + case PER_UW7: + return I386_UW7_EMUL; + default: + return NULL; + } +} +#else + +/* + * No emulation, no fun :) + */ +#define __emul_prefix() NULL +#endif /* CONFIG_ABI || CONFIG_ABI_MODULE */ #endif /* __I386_NAMEI_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-ia64/elf.h linux/include/asm-ia64/elf.h --- linux-2.4.3/include/asm-ia64/elf.h Wed Jul 12 00:43:45 2000 +++ linux/include/asm-ia64/elf.h Fri Mar 30 17:25:23 2001 @@ -82,7 +82,18 @@ #define ELF_PLATFORM 0 #ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) -#endif +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + unsigned long personality = PER_LINUX; \ + \ + /* Check the interpreter for SVR4isms */ \ + else if (strcmp((interp), "/usr/lib/libc.so.1") == 0 || \ + strcmp((interp), "/usr/lib/ld.so.1") == 0) \ + personality = PER_SVR4; \ + \ + set_personality(personality); \ +} while (0) + +#endif /* __KERNEL__ */ #endif /* _ASM_IA64_ELF_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-m68k/elf.h linux/include/asm-m68k/elf.h --- linux-2.4.3/include/asm-m68k/elf.h Wed Jul 12 00:43:45 2000 +++ linux/include/asm-m68k/elf.h Fri Mar 30 17:25:23 2001 @@ -89,7 +89,17 @@ #define ELF_PLATFORM (NULL) #ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) -#endif +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + unsigned long personality = PER_LINUX; \ + \ + /* Check the interpreter for SVR4isms */ \ + else if (strcmp((interp), "/usr/lib/libc.so.1") == 0 || \ + strcmp((interp), "/usr/lib/ld.so.1") == 0) \ + personality = PER_SVR4; \ + \ + set_personality(personality); \ +} while (0) -#endif +#endif /* __KERNEL__ */ +#endif /* __ASMm68k_ELF_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-mips/elf.h linux/include/asm-mips/elf.h --- linux-2.4.3/include/asm-mips/elf.h Fri Jul 28 03:36:54 2000 +++ linux/include/asm-mips/elf.h Fri Mar 30 17:25:23 2001 @@ -103,7 +103,17 @@ #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) #ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) -#endif +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + unsigned long personality = PER_LINUX; \ + \ + /* Check the interpreter for SVR4isms */ \ + else if (strcmp((interp), "/usr/lib/libc.so.1") == 0 || \ + strcmp((interp), "/usr/lib/ld.so.1") == 0) \ + personality = PER_SVR4; \ + \ + set_personality(personality); \ +} while (0) +#endif /* __KERNEL__ */ #endif /* __ASM_ELF_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-mips64/elf.h linux/include/asm-mips64/elf.h --- linux-2.4.3/include/asm-mips64/elf.h Fri Jul 28 03:36:54 2000 +++ linux/include/asm-mips64/elf.h Fri Mar 30 17:25:23 2001 @@ -97,17 +97,21 @@ #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) #endif -#ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) \ -do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ - current->thread.mflags |= MF_32BIT; \ - else \ - current->thread.mflags &= ~MF_32BIT; \ - if (ibcs2) \ - set_personality(PER_SVR4); \ - else if (current->personality != PER_LINUX32) \ - set_personality(PER_LINUX); \ +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + /* First do some adjustments for 32bit binary compatiblity */ \ + if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ + current->thread.mflags |= MF_32BIT; \ + else \ + current->thread.mflags &= ~MF_32BIT; \ + \ + /* Check the interpreter for SVR4isms */ \ + if (strcmp((interp), "/usr/lib/libc.so.1") == 0 || \ + strcmp((interp), "/usr/lib/ld.so.1") == 0) \ + set_personality(PER_SVR4); \ + else if (current->personality != PER_LINUX32) \ + set_personality(PER_LINUX); \ } while (0) -#endif +#endif /* __KERNEL__ */ #endif /* _ASM_ELF_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-parisc/elf.h linux/include/asm-parisc/elf.h --- linux-2.4.3/include/asm-parisc/elf.h Fri Mar 30 14:45:52 2001 +++ linux/include/asm-parisc/elf.h Fri Mar 30 17:25:23 2001 @@ -90,8 +90,11 @@ #define ELF_PLATFORM ("PARISC\0" /*+((boot_cpu_data.x86-3)*5) */) #ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) \ - current->personality = PER_LINUX -#endif -#endif +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + __set_personality(PER_LINUX); \ +} while (0) + +#endif /* __KERNEL__ */ +#endif /* __ASMPARISC_ELF_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-ppc/elf.h linux/include/asm-ppc/elf.h --- linux-2.4.3/include/asm-ppc/elf.h Sat Feb 3 14:51:14 2001 +++ linux/include/asm-ppc/elf.h Fri Mar 30 17:25:23 2001 @@ -68,8 +68,6 @@ #define ELF_PLATFORM (NULL) -#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) - /* * We need to put in some extra aux table entries to tell glibc what * the cache block size is, so it can use the dcbz instruction safely. @@ -89,5 +87,17 @@ NEW_AUX_ENT(2, AT_UCACHEBSIZE, ucache_bsize); \ } while (0) +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + unsigned long personality = PER_LINUX; \ + \ + /* Check the interpreter for SVR4isms */ \ + else if (strcmp((interp), "/usr/lib/libc.so.1") == 0 || \ + strcmp((interp), "/usr/lib/ld.so.1") == 0) \ + personality = PER_SVR4; \ + \ + set_personality(personality); \ +} while (0) + #endif /* __KERNEL__ */ -#endif +#endif /* __PPC_ELF_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-s390/elf.h linux/include/asm-s390/elf.h --- linux-2.4.3/include/asm-s390/elf.h Fri Feb 23 20:12:50 2001 +++ linux/include/asm-s390/elf.h Fri Mar 30 17:25:23 2001 @@ -75,7 +75,18 @@ #define ELF_PLATFORM (NULL) #ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) -#endif -#endif +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + unsigned long personality = PER_LINUX; \ + \ + /* Check the interpreter for SVR4isms */ \ + else if (strcmp((interp), "/usr/lib/libc.so.1") == 0 || \ + strcmp((interp), "/usr/lib/ld.so.1") == 0) \ + personality = PER_SVR4; \ + \ + set_personality(personality); \ +} while (0) + +#endif /* __KERNEL__ */ +#endif /* __ASMS390_ELF_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-s390x/elf.h linux/include/asm-s390x/elf.h --- linux-2.4.3/include/asm-s390x/elf.h Fri Feb 23 20:12:51 2001 +++ linux/include/asm-s390x/elf.h Fri Mar 30 17:25:23 2001 @@ -76,7 +76,18 @@ #define ELF_PLATFORM (NULL) #ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) -#endif -#endif +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + unsigned long personality = PER_LINUX; \ + \ + /* Check the interpreter for SVR4isms */ \ + else if (strcmp((interp), "/usr/lib/libc.so.1") == 0 || \ + strcmp((interp), "/usr/lib/ld.so.1") == 0) \ + personality = PER_SVR4; \ + \ + set_personality(personality); \ +} while (0) + +#endif /* __KERNEL__ */ +#endif /* __ASMS390_ELF_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-sh/elf.h linux/include/asm-sh/elf.h --- linux-2.4.3/include/asm-sh/elf.h Wed Jul 12 00:43:45 2000 +++ linux/include/asm-sh/elf.h Fri Mar 30 17:25:23 2001 @@ -70,7 +70,11 @@ _r->sr = SR_FD; } while (0) #ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT) -#endif +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + __set_personality(PER_LINUX_32BIT); \ +} while (0) + +#endif /* __KERNEL__ */ #endif /* __ASM_SH_ELF_H */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-sparc/abi.h linux/include/asm-sparc/abi.h --- linux-2.4.3/include/asm-sparc/abi.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-sparc/abi.h Fri Mar 30 17:25:23 2001 @@ -0,0 +1,5 @@ +#define get_syscall_parameter(regs,n) (regs)->u_regs [(n)+8] +#define set_error(regs,e) (regs)->u_regs [8] = -(e) +#define set_result(regs,r) regs->u_regs [8] = r +#define clear_error(regs) +#define get_result(regs) regs->u_regs [8] diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-sparc/elf.h linux/include/asm-sparc/elf.h --- linux-2.4.3/include/asm-sparc/elf.h Wed Jul 12 04:02:37 2000 +++ linux/include/asm-sparc/elf.h Fri Mar 30 17:25:23 2001 @@ -105,7 +105,18 @@ #define ELF_PLATFORM (NULL) #ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) -#endif +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + unsigned long personality = PER_LINUX; \ + \ + /* Check the interpreter for SVR4isms */ \ + else if (strcmp((interp), "/usr/lib/libc.so.1") == 0 || \ + strcmp((interp), "/usr/lib/ld.so.1") == 0) \ + personality = PER_SVR4; \ + \ + set_personality(personality); \ +} while (0) + +#endif /* __KERNEL__ */ #endif /* !(__ASMSPARC_ELF_H) */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/asm-sparc64/elf.h linux/include/asm-sparc64/elf.h --- linux-2.4.3/include/asm-sparc64/elf.h Fri Mar 30 14:48:47 2001 +++ linux/include/asm-sparc64/elf.h Fri Mar 30 17:25:23 2001 @@ -56,10 +56,10 @@ instruction set this cpu supports. */ /* On Ultra, we support all of the v8 capabilities. */ -#define ELF_HWCAP ((HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \ - HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV | \ - HWCAP_SPARC_V9) | \ - ((tlb_type == cheetah) ? HWCAP_SPARC_ULTRA3 : 0)) +#define ELF_HWCAP ((HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \ + HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV | \ + HWCAP_SPARC_V9) | \ + ((tlb_type == cheetah) ? HWCAP_SPARC_ULTRA3 : 0)) /* This yields a string that ld.so will use to load implementation specific libraries for optimization. This is more specific in @@ -68,39 +68,51 @@ #define ELF_PLATFORM (NULL) #ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) \ -do { unsigned char flags = current->thread.flags; \ - if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ - flags |= SPARC_FLAG_32BIT; \ - else \ - flags &= ~SPARC_FLAG_32BIT; \ - if (flags != current->thread.flags) { \ - unsigned long pgd_cache = 0UL; \ - if (flags & SPARC_FLAG_32BIT) { \ - pgd_t *pgd0 = ¤t->mm->pgd[0]; \ - if (pgd_none (*pgd0)) { \ - pmd_t *page = pmd_alloc_one_fast(NULL, 0); \ - if (!page) \ - page = pmd_alloc_one(NULL, 0); \ - pgd_set(pgd0, page); \ - } \ - pgd_cache = pgd_val(*pgd0) << 11UL; \ - } \ - __asm__ __volatile__( \ - "stxa\t%0, [%1] %2\n\t" \ - "membar #Sync" \ - : /* no outputs */ \ - : "r" (pgd_cache), \ - "r" (TSB_REG), \ - "i" (ASI_DMMU)); \ - current->thread.flags = flags; \ - } \ - \ - if (ibcs2) \ - set_personality(PER_SVR4); \ - else if (current->personality != PER_LINUX32) \ - set_personality(PER_LINUX); \ + +#define SET_ELF_PERSONALITY(ex, interp) \ +do { \ + unsigned long personality = PER_LINUX; \ + unsigned char flags = current->thread.flags; \ + \ + if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ + flags |= SPARC_FLAG_32BIT; \ + else \ + flags &= ~SPARC_FLAG_32BIT; \ + \ + if (flags != current->thread.flags) { \ + unsigned long pgd_cache = 0UL; \ + \ + if (flags & SPARC_FLAG_32BIT) { \ + pgd_t *pgd0 = ¤t->mm->pgd[0]; \ + \ + if (pgd_none (*pgd0)) { \ + pmd_t *page = pmd_alloc_one_fast(NULL, 0); \ + \ + if (!page) \ + page = pmd_alloc_one(NULL, 0); \ + pgd_set(pgd0, page); \ + } \ + \ + pgd_cache = pgd_val(*pgd0) << 11UL; \ + } \ + __asm__ __volatile__( \ + "stxa\t%0, [%1] %2\n\t" \ + "membar #Sync" \ + : /* no outputs */ \ + : "r" (pgd_cache), \ + "r" (TSB_REG), \ + "i" (ASI_DMMU)); \ + \ + current->thread.flags = flags; \ + } \ + \ + /* Check the interpreter for SVR4isms */ \ + if (strcmp((interp), "/usr/lib/libc.so.1") == 0 || \ + strcmp((interp), "/usr/lib/ld.so.1") == 0) \ + set_personality(PER_SVR4); \ + else if (current->personality != PER_LINUX32) \ + set_personality(PER_LINUX); \ } while (0) -#endif +#endif /* __KERNEL__ */ #endif /* !(__ASM_SPARC64_ELF_H) */ diff -uNr --exclude-from=dontdiff linux-2.4.3/include/linux/major.h linux/include/linux/major.h --- linux-2.4.3/include/linux/major.h Fri Mar 30 14:45:55 2001 +++ linux/include/linux/major.h Fri Mar 30 17:25:23 2001 @@ -63,6 +63,7 @@ #define ACSI_MAJOR 28 #define AZTECH_CDROM_MAJOR 29 #define GRAPHDEV_MAJOR 29 /* SparcLinux & Linux/68k /dev/fb */ +#define SOCKSYS_MAJOR 30 /* iBCS needs this for STREAMS-based TCP/IP */ #define SHMIQ_MAJOR 85 /* Linux/mips, SGI /dev/shmiq */ #define CM206_CDROM_MAJOR 32 #define IDE2_MAJOR 33 diff -uNr --exclude-from=dontdiff linux-2.4.3/include/linux/personality.h linux/include/linux/personality.h --- linux-2.4.3/include/linux/personality.h Mon Dec 11 21:49:54 2000 +++ linux/include/linux/personality.h Fri Mar 30 17:27:44 2001 @@ -6,9 +6,11 @@ #include /* Flags for bug emulation. These occupy the top three bytes. */ -#define STICKY_TIMEOUTS 0x4000000 -#define WHOLE_SECONDS 0x2000000 +#define MMAP_PAGE_ZERO 0x0100000 #define ADDR_LIMIT_32BIT 0x0800000 +#define SHORT_INODE 0x1000000 +#define WHOLE_SECONDS 0x2000000 +#define STICKY_TIMEOUTS 0x4000000 /* Personality types. These go in the low byte. Avoid using the top bit, * it will conflict with error returns. @@ -16,20 +18,28 @@ #define PER_MASK (0x00ff) #define PER_LINUX (0x0000) #define PER_LINUX_32BIT (0x0000 | ADDR_LIMIT_32BIT) -#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS) -#define PER_SVR3 (0x0002 | STICKY_TIMEOUTS) -#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS) -#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS) +#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO) +#define PER_SVR3 (0x0002 | STICKY_TIMEOUTS | SHORT_INODE) +#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE) +#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS | SHORT_INODE) #define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS) #define PER_BSD (0x0006) #define PER_SUNOS (PER_BSD | STICKY_TIMEOUTS) -#define PER_XENIX (0x0007 | STICKY_TIMEOUTS) +#define PER_XENIX (0x0007 | STICKY_TIMEOUTS | SHORT_INODE) #define PER_LINUX32 (0x0008) #define PER_IRIX32 (0x0009 | STICKY_TIMEOUTS) /* IRIX5 32-bit */ #define PER_IRIXN32 (0x000a | STICKY_TIMEOUTS) /* IRIX6 new 32-bit */ #define PER_IRIX64 (0x000b | STICKY_TIMEOUTS) /* IRIX6 64-bit */ #define PER_RISCOS (0x000c) #define PER_SOLARIS (0x000d | STICKY_TIMEOUTS) +#define PER_UW7 (0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO) + +static __inline__ int +personality(int pers) +{ + return (pers & PER_MASK); +} + /* Prototype for an lcall7 syscall handler. */ typedef void (*lcall7_func)(int, struct pt_regs *); @@ -46,6 +56,10 @@ unsigned char pers_low, pers_high; unsigned long * signal_map; unsigned long * signal_invmap; + struct map_segment * err_map; + struct map_segment * socktype_map; + struct map_segment * sockopt_map; + struct map_segment * af_map; struct module * module; struct exec_domain *next; }; @@ -59,9 +73,12 @@ #define get_exec_domain(it) \ if (it && it->module) __MOD_INC_USE_COUNT(it->module); extern void __set_personality(unsigned long personality); -#define set_personality(pers) do { \ - if (current->personality != pers) \ - __set_personality(pers); \ +#define set_personality(pers) do { \ + if (current->personality != pers) { \ + __set_personality(pers); \ + printk(KERN_DEBUG "[%s:%d]: set personality to %lx\n", \ + current->comm, current->pid, pers); \ + } \ } while (0) asmlinkage long sys_personality(unsigned long personality); diff -uNr --exclude-from=dontdiff linux-2.4.3/kernel/ksyms.c linux/kernel/ksyms.c --- linux-2.4.3/kernel/ksyms.c Fri Mar 30 14:48:47 2001 +++ linux/kernel/ksyms.c Fri Mar 30 17:25:23 2001 @@ -58,6 +58,7 @@ extern void *sys_call_table; +extern int max_threads; extern int sys_tz; extern int request_dma(unsigned int dmanr, char * deviceID); extern void free_dma(unsigned int dmanr); @@ -576,3 +576,6 @@ EXPORT_SYMBOL(tasklist_lock); EXPORT_SYMBOL(pidhash); + +EXPORT_SYMBOL(max_threads); +